Description
<a href="https://explosion.ai"><img src="https://explosion.ai/assets/img/logo.svg" width="125" height="125" align="right" /></a> # Confection: The sweetest config system for Python `confection` :candy: is a lightweight library that offers a **configuration system** letting you conveniently describe arbitrary trees of objects. Configuration is a huge challenge for machine-learning code because you may want to expose almost any detail of any function as a hyperparameter. The setting you want to expose might be arbitrarily far down in your call stack, so it might need to pass all the way through the CLI or REST API, through any number of intermediate functions, affecting the interface of everything along the way. And then once those settings are added, they become hard to remove later. Default values also become hard to change without breaking backwards compatibility. To solve this problem, `confection` offers a config system that lets you easily describe arbitrary trees of objects. The objects can be created via function calls you register using a simple decorator syntax. You can even version the functions you create, allowing you to make improvements without breaking backwards compatibility. The most similar config system we’re aware of is [Gin](https://github.com/google/gin-config), which uses a similar syntax, and also allows you to link the configuration system to functions in your code using a decorator. `confection`'s config system is simpler and emphasizes a different workflow via a subset of Gin’s functionality. [](https://github.com/explosion/confection/actions/workflows/tests.yml) [](https://github.com/explosion/confection/releases) [](https://pypi.org/project/confection/) [](https://anaconda.org/conda-forge/confection) [](https://github.com/ambv/black) ## ⏳ Installation ```bash pip install confection ``` ```bash conda install -c conda-forge confection ``` ## 👩💻 Usage The configuration system parses a `.cfg` file like ```ini [training] patience = 10 dropout = 0.2 use_vectors = false [training.logging] level = "INFO" [nlp] # This uses the value of training.use_vectors use_vectors = ${training.use_vectors} lang = "en" ``` and resolves it to a `Dict`: ```json { "training": { "patience": 10, "dropout": 0.2, "use_vectors": false, "logging": { "level": "INFO" } }, "nlp": { "use_vectors": false, "lang": "en" } } ``` The config is divided into sections, with the section name in square brackets – for example, `[training]`. Within the sections, config values can be assigned to keys using `=`. Values can also be referenced from other sections using the dot notation and placeholders indicated by the dollar sign and curly braces. For example, `${training.use_vectors}` will receive the value of use_vectors in the training block. This is useful for settings that are shared across components. The config format has three main differences from Python’s built-in `configparser`: 1. JSON-formatted values. `confection` passes all values through `json.loads` to interpret them. You can use atomic values like strings, floats, integers or booleans, or you can use complex objects such as lists or maps. 2. Structured sections. `confection` uses a dot notation to build nested sections. If you have a section named `[section.subsection]`, `confection` will parse that into a nested structure, placing subsection within section. 3. References to registry functions. If a key starts with `@`, `confection` will interpret its value as the name of a function registry, load the function registered for that name and pass in the rest of the block as arguments. If type hints are available on the function, the argument values (and return value of the function) will be validated against them. This lets you express complex configurations, like a training pipeline where `batch_size` is populated by a function that yields floats. There’s no pre-defined scheme you have to follow; how you set up the top-level sections is up to you. At the end of it, you’ll receive a dictionary with the values that you can use in your script – whether it’s complete initialized functions, or just basic settings. For instance, let’s say you want to define a new optimizer. You'd define its arguments in `config.cfg` like so: ```ini [optimizer] @optimizers = "my_cool_optimizer.v1" learn_rate = 0.001 gamma = 1e-8 ``` To load and
Release History
| Version | Changes | Urgency | Date |
|---|---|---|---|
| 1.3.3 | Imported from PyPI (1.3.3) | Low | 4/21/2026 |
| release-v1.3.3 | Config values True, False, and None (Python-style capitalised literals) were silently kept as strings rather than being converted to their Python types. This went unnoticed in older releases because pydantic v1's parse_obj coerced the strings during validation. With the new built-in type checker (which correctly requires actual bools), configs using the capitalised forms broke. Handle True/False/None in try_load_json as aliases for the JSON-style true/false/null | Medium | 3/24/2026 |
| release-v1.3.2 | Avoid triggering warning. | Medium | 3/24/2026 |
| release-v1.3.1 | Release release-v1.3.1 | Medium | 3/23/2026 |
| release-v1.3.0 | * Refactor library to properly separate config parsing, overrides, default filling, validation and promise resolution * Rewrite type-checking code to be more reliable | Medium | 3/22/2026 |
| release-v1.2.2 | Fix pydantic v2 compat: check model_fields/model_config before __fields__/__config__, respect Strict metadata in Annotated types | Low | 3/21/2026 |
| release-v1.2.1 | * Use TypeVar self-type pattern (_ConfigSelf, _CVESelf) so Config and ConfigValidationError methods return the correct type for subclasses * Use type(self)() instead of Config() in interpolate/copy/merge so subclass instances are preserved at runtime * Widen input parameters from Dict to Mapping and List to Sequence where the parameter is read-only (overrides, updates, config params, section_order) * Widen ConfigValidationError.config param to accept any Mapping * | Low | 3/21/2026 |
| release-v1.2.0 | - Fix `Config.to_str()` crash on `*` positional arg sections ([#52](https://github.com/explosion/confection/issues/52)). - Fix `_update_from_parsed` crash when a pydantic validator coerces a string to a dict ([#54](https://github.com/explosion/confection/issues/54)). - Coerce dict arguments to BaseModel instances for registered functions ([#58](https://github.com/explosion/confection/issues/58), [#59](https://github.com/explosion/confection/issues/59)). - Support top-level section refe | Low | 3/20/2026 |
| release-v1.1.0 | Pydantic v2 is stricter than v1 and I've been unable to replicate the behaviours we had in the config. I had also attempted to refactor the library to make it easier to port, but this seems to have also introduced regressions. To finally resolve this I'm dropping support for Pydantic in favour of a relatively small amount of custom validation logic. This should finally unblock spaCy and Thinc. | Low | 3/20/2026 |
| release-v1.0.0 | Properly support Pydantic v2 | Low | 3/20/2026 |
| release-v1.0.0a2 | Fix support for Pydantic v2, and greatly extend tests | Low | 2/9/2026 |
| release-v1.0.0.dev0 | Previously confection did three tree operations simultaneously (in the registry._fill method): * Build a version of the config with defaults in-place * Build a modified version suitable for validation * Build an output version with promises resolved The fact that all three were being built at once made the code quite hard to update for Pydantic 2, and just difficult to work with in general. I've therefore refactored the code so that these are separate processes that apply to the whole tr | Low | 4/10/2025 |
| v0.1.5 | ## ✨ Fixes and features * Fixes #47: Ensure config with `*` can be filled (#53) * Allow `typing-extensions<5.0.0` for Python < 3.8 (#63) * Update CI (#64) ## 👥 Contributors @adrianeboyd, @honnibal, @ines, @KennethEnevoldsen, @MartinBernstorff, @svlandeg | Low | 5/31/2024 |
| v0.1.4 | * Support use of `$$` to escape a literal `$` character in config strings (#49). | Low | 11/23/2023 |
| v0.1.3 | * Add frozen structures to `__init__.__all__` to ensure they can be imported easily from `confection` (#43). | Low | 9/11/2023 |
| v0.1.2 | - Implement `deepcopy()` for `FrozenDict` and `FrozenList` to allow setting values in function headers (#41) | Low | 9/6/2023 |
| v0.1.1 | - Make `catalogue` a dev-only requirement (#35). - Allow Pydantic v2 using transitional v1 support (#38). - Format and lint with black/flake8/isort (#39). | Low | 8/4/2023 |
| v0.1.0 | * Add checks with warnings for single-quoted values (#22). * Add `util.SimpleFrozenDict` and `util.SimpleFrozenList` from spaCy (#28). * Remove recursive JSON parsing of list values to preserve string values such as `["003"]` rather than parsing them as integers (#33). | Low | 6/29/2023 |
| v0.0.4 | * Extend support for `typing_extensions` to v4.4.x for Python 3.6 and 3.7. * Add `pyproject.toml` to source package. | Low | 1/10/2023 |
| v0.0.3 | * Extend support to pydantic v1.10.x. | Low | 10/7/2022 |
| v0.0.2 | * Add `py.typed` to package. * Switch to mypy 0.981 for fixes related to Python 3.10.7 and NumPy. * Update README. | Low | 9/28/2022 |
| v0.0.1 | This is the initial release of `confection`, a lightweight library that offers a configuration system letting you conveniently describe arbitrary trees of objects. If you are a user of spaCy or Thinc, you may be familiar with this configuration system already - now you can use it independently. | Low | 8/24/2022 |
