config
Version: 7.2.5
wexample-config lets Python developers declare typed configuration schemas as trees of named option classes, then feed raw dicts into them for parsing and validation. Each option enforces a specific type — string, list, dict, union, or a custom ConfigValue subclass — and raises on a mismatch or an unexpected key; nested options recurse the same validation down the tree. One or more AbstractOptionsProvider classes can be registered on a single AbstractConfigManager, so different parts of a codebase can contribute their own option sets without coupling to each other.
Table of Contents
- Installation
- Quickstart
- Tests
- Architecture
- Integration in the Suite
- Dependencies
- Versioning & Compatibility Policy
- License
- About us
- Known Limitations & Roadmap
- Status & Compatibility
- Useful Links
- Migration Notes
Installation
pip install wexample-config
Requires Python >=3.10.
Quickstart
Install the package:
pip install wexample-config
Three classes are enough to parse and validate a real config dict.
1. Declare an option. Subclass AbstractConfigOption and return the expected Python type from get_raw_value_allowed_type. The option key is derived from the class name automatically — VersionConfigOption becomes "version".
2. Register it in a provider. Subclass AbstractOptionsProvider and list the option classes in get_options.
3. Wire the provider into a manager. Subclass AbstractConfigManager and return the provider from get_options_providers.
from typing import Any
from wexample_config.classes.abstract_config_manager import AbstractConfigManager
from wexample_config.config_option.abstract_config_option import AbstractConfigOption
from wexample_config.options_provider.abstract_options_provider import AbstractOptionsProvider
class VersionConfigOption(AbstractConfigOption):
@staticmethod
def get_raw_value_allowed_type() -> Any:
return str
class AppOptionsProvider(AbstractOptionsProvider):
@classmethod
def get_options(cls) -> list[type[AbstractConfigOption]]:
return [VersionConfigOption]
class AppConfigManager(AbstractConfigManager):
def get_options_providers(self) -> list[type[AbstractOptionsProvider]]:
return [AppOptionsProvider]
manager = AppConfigManager()
manager.set_value({"version": "1.0.0"})
print(manager.get_option_value(VersionConfigOption).get_str())
# 1.0.0
set_value raises InvalidOptionException for any key not declared by a provider, and NotAllowedVariableTypeException when the value's type does not match get_raw_value_allowed_type. Both checks happen at parse time, not at read time.
get_option_value returns a ConfigValue wrapper. Call .get_str(), .get_int(), .get_list(), .is_str(), etc. to read the underlying value with or without a type assertion. You can also reach the option object directly via get_option(VersionConfigOption) and call .get_value() on it.
Tests
This project uses pytest for testing and pytest-cov for code coverage analysis.
Installation
First, install the required testing dependencies:
.venv/bin/python -m pip install pytest pytest-cov
Basic Usage
Run all tests with coverage:
.venv/bin/python -m pytest --cov --cov-report=html
Common Commands
# Run tests with coverage for a specific module
.venv/bin/python -m pytest --cov=your_module
# Show which lines are not covered
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing
# Generate an HTML coverage report
.venv/bin/python -m pytest --cov=your_module --cov-report=html
# Combine terminal and HTML reports
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html
# Run specific test file with coverage
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
Viewing HTML Reports
After generating an HTML report, open htmlcov/index.html in your browser to view detailed line-by-line coverage information.
Coverage Threshold
To enforce a minimum coverage percentage:
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
This will cause the test suite to fail if coverage drops below 80%.
Architecture
wexample-config turns raw dicts into validated, typed option trees. The library has four conceptual layers: the manager (entry point), option providers (schema registries), config options (tree nodes), and config values (value wrappers).
Manager
src/wexample_config/classes/abstract_config_manager.py is the public entry point. It extends AbstractNestedConfigOption and is decorated with @base_class (attrs-backed). Consuming code subclasses it and overrides get_options_providers to declare which providers are active:
class AppConfigManager(AbstractConfigManager):
def get_options_providers(self) -> list[type[AbstractOptionsProvider]]:
return [AppOptionsProvider]
Calling manager.set_value({"key": value}) triggers the full parse-and-validate cycle described below.
Option providers
src/wexample_config/options_provider/abstract_options_provider.py is a class-level registry. A subclass implements get_options and returns a list of option classes. get_options_registry caches the name → class mapping on the provider class itself, so the dict is built once and reused.
Multiple providers can be active simultaneously on one manager. AbstractNestedConfigOption.get_options_providers walks up the parent chain to the root before consulting self.options_providers, so providers declared at the manager level apply to the whole tree.
Config options
src/wexample_config/config_option/abstract_config_option.py is the base for every schema node. It holds:
key— derived automatically from the class name (VersionConfigOption→"version") viaHasSnakeShortClassNameClassMixin.value/config_value— the raw input and itsConfigValuewrapper.parent— set at construction time;get_root()memoises the traversal to the root option.
set_value validates the raw input against get_raw_value_allowed_type() before wrapping it in the appropriate ConfigValue subclass. prepare_value runs before wrapping to let subclasses normalise the raw value.
src/wexample_config/config_option/abstract_nested_config_option.py extends the base to own child options. Its set_value calls _create_options, which:
- Builds the allowed-option registry from all active providers (cached by
(type(self), providers)tuple). - Runs
option_class.resolve_config(config)for every option class that overrides the base no-op — this lets an option inject extra keys into the raw dict before children are created. - Rejects any unknown key that is not in the registry (raises
InvalidOptionException) unlessallow_undefined_keys=True, in which case unknown keys are wrapped in a plainConfigOption. - Instantiates each option class with the corresponding raw value, attaching
parent=self.
src/wexample_config/config_option/abstract_list_config_option.py handles options whose raw value is list[dict]. Instead of creating a single nested option, it iterates over the list and appends one child instance per item to self.children.
src/wexample_config/config_option/config_option.py is the concrete fallback used by _create_options when allow_undefined_keys=True and a key has no declared class.
Config values
src/wexample_config/config_value/config_value.py wraps any Python value and provides a uniform API:
- Type checks:
is_str(),is_int(),is_dict(),is_list(),is_callable(), … - Typed getters:
get_str(),get_int(), … — raiseTypeErroron mismatch. - Safe getters:
get_str_or_none(),get_int_or_default(n), … - Typed setters:
set_str(v),set_int(v), … — validate before assigning. - Conversions:
to_str(),to_int(), … — call the built-in constructor.
get_allowed_types (default Any) restricts which Python types the value may carry at construction time; validate_value_type enforces this via wexample_helpers.
src/wexample_config/config_value/nested_config_value.py is used for dict, list, and tuple values. On init it recursively wraps every nested container in another NestedConfigValue and every scalar in a plain ConfigValue. This enables search("a.b.0.c") (dot-separated path traversal) and set_by_path / update_nested for mutation.
src/wexample_config/config_value/callback_render_config_value.py holds a Callable. _create_options calls render(option) on it to resolve the callable to a concrete value before the child option is instantiated. NameConfigOption.resolve_config uses this to accept name: lambda opt: ... in raw configs.
src/wexample_config/config_value/custom_type_config_value.py shows the extension point: overriding get_allowed_types to return a concrete type (here str) restricts what raw values the wrapper may hold.
src/wexample_config/config_value/config_value_collection.py is a typed container over a list of ConfigValue objects. It adds bulk accessors (get_str_collection(), to_int_collection(), etc.) and map(fn).
Types and exceptions
src/wexample_config/const/types.py aliases DictConfig = StringKeysDict (from wexample_helpers). This type is used throughout the library for raw input dicts.
src/wexample_config/exception/invalid_option_exception.py is raised by _create_options when a raw key has no matching option class. It extends UndefinedException from wexample_helpers.
A call through the stack
manager.set_value({"name": "app", "version": "1.0"}) takes this path:
AbstractConfigOption.set_valuevalidatesdictagainstget_raw_value_allowed_type(Union[dict, set[...]]), then wraps the dict in aConfigValue.AbstractNestedConfigOption.set_valuecalls_create_optionswith the same dict._create_optionsresolves the provider list → builds the allowed-option registry → runs anyresolve_confighooks → checks for unknown keys → instantiatesNameConfigOption(parent=manager, value="app")andVersionConfigOption(parent=manager, value="1.0").- Each option's
__attrs_post_init__callsset_valueon its own raw value, running type validation and wrapping in the option'sConfigValuesubclass. - The finished options sit in
manager.options, keyed by name.manager.get_option("name").get_value().get_str()returns"app".
Demo layer
src/wexample_config/demo/ contains a self-contained example: DemoConfigManager, DemoOptionsProvider, and a set of demo option classes covering the standard patterns (scalar, union, list, nested, extensible, custom value type). The test suite in tests/test_config_manager.py exercises all of them and is the fastest way to see each pattern in context.
Integration in the Suite
This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.
Related Packages
The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.
Visit the Wexample Suite documentation for the complete package ecosystem.
Dependencies
- attrs: >=23.1.0
- cattrs: >=23.1.0
- pydantic: <3,>=2
- wexample-helpers: >=20.2.0
Versioning & Compatibility Policy
Wexample packages follow Semantic Versioning (SemVer):
- MAJOR: Breaking changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatible
We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Free to use in both personal and commercial projects.
About us
Wexample stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.
This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.
Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.
Known Limitations & Roadmap
Current limitations and planned features are tracked in the GitHub issues.
See the project roadmap for upcoming features and improvements.
Status & Compatibility
Maturity: Production-ready
Python Support: >=3.10
OS Support: Linux, macOS, Windows
Status: Actively maintained
Useful Links
- Homepage: https://github.com/wexample/python-config
- Documentation: docs.wexample.com
- Issue Tracker: https://github.com/wexample/python-config/issues
- Discussions: https://github.com/wexample/python-config/discussions
- PyPI: pypi.org/project/wexample-config
Migration Notes
When upgrading between major versions, refer to the migration guides in the documentation.
Breaking changes are clearly documented with upgrade paths and examples.
Metadata
Release files for wexample-config 7.2.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wexample_config-7.2.5.tar.gz | 25.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wexample_config-7.2.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 56.1 kB
Release files / wexample_config-7.2.5.tar.gz
| Download URL | wexample_config-7.2.5.tar.gz |
|---|---|
| Size | 25.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4a95363c62e11105149716a30da9852449dcd850eccbc98b4c86787bf7802b61
|
|
BLAKE2b-256 checksum How to use checksums |
bbfd3073c07661f7d4ea1b259195b2b4266c113c5b482e8992440a0d2c5e5cb2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-139-generic
|
Release files / wexample_config-7.2.5-py3-none-any.whl
| Download URL | wexample_config-7.2.5-py3-none-any.whl |
|---|---|
| Size | 30.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
34b6d292b233829e41ec501b4c50dc20eeaaa142c646618811c5ae96615c6f46
|
|
BLAKE2b-256 checksum How to use checksums |
167a94a1eec90c44f2cfa91bff5d9e9124c8ac73d9a599189beed68c04e418e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
pdm/2.25.9 CPython/3.12.3 Linux/6.8.0-139-generic
|