0.20.0#
Features#
- Add cross-source references:
${@tag.key}syntax in source init-fields. Sources are loaded in topological order resolved from their inter-dependencies. Cycles and tag collisions on referenced tags raiseDatureConfigErrorwith a descriptive message.$$escapes a literal$.
Cross-ref interpolation is now applied lazily inside the loading pipeline: each source's load_raw() is called exactly once, with ${@...} fields resolved immediately before that single call. _validate() also runs after interpolation, so credential sources like VaultSource see real values in their URL/token fields instead of literal ${@...} strings.
CliSource cross-refs now use the same dot-notation as all other sources (${@cli.db.host}) instead of the flat separator notation (${@cli.db__host}).
When a dependency source is skipped (skip_if_broken=True and the source fails to load), its tag contributes an empty dict to the cross-ref context so that ${@tag.key:-default} fallback expressions on downstream sources still resolve cleanly.
Exception hierarchy: introduced DatureErrorGroup as a base ExceptionGroup without dataclass_name; CrossRefExpandError inherits from it directly. DatureConfigError and all its subclasses drop __new__ overrides — construction uses __init__ only. (#cross_source_refs) - Add when= to Source: a declarative condition that enables a source only when all key→value pairs match after template expansion. Keys support env-var substitution (${VAR}, ${VAR:-default}) and cross-source references (${@tag.key}). Disabled sources contribute no data to the merge and do not participate in the cross-ref dependency graph — enabling the prod/dev token pattern without if/else around load(). (#source_when)
Bugfixes#
- Unhandled exceptions out of
dature.load()no longer print a Python traceback header. Non-dature exceptions raised inside dature (FileNotFoundError, parser errors, user__post_init__failures) are now wrapped at theLoader.load()boundary intoDatureConfigError, so a singlesys.excepthook(installed on import) renders them viatraceback.print_exception(..., tb=None). The same exception classes raised entirely from user code outside dature are unaffected and still print with the normal traceback. (#clean_stderr_excepthook) - Fix field_mapping aliases not matching in sources that normalize key case (EnvSource, EnvFileSource, DockerSecretsSource, IniSource). Aliases such as "DB_PASSWORD" now correctly map to the dataclass field regardless of whether the source lowercases its keys. (#field_mapping_uppercase)
FieldRefis now typed asAnyinstead of a fixed union of primitive types. Fields in user dataclasses can be of any type (including custom classes), so the previous union was incomplete and caused false mypy errors when usingF[DataClass].fieldas afield_mappingkey. (#field_ref_any)- Fix three related
Loaderbugs: decorator footgun (env vars read at import/construction time causedDatureErrorbefore firstload()), validation_loader built from init-time last source instead of runtime last source (wrong retort used when lazywhen=disables the init-chosen source), andall sources filtered out by when=raising a bareDatureErrorinstead of aDatureConfigErrorgroup like all other load errors. (#loader_defer_env)
Refactoring#
- Minor architectural cleanup:
Loader.load()now re-evaluateswhen=conditions on every call and auto-clears the cache when the enabled-source set changes;DatureConfigError.__init__acceptsBaseExceptionitems to avoid silent type-ignore;Loader._debugrenamed to publicLoader.debug;should_skip_brokendocuments thatwhen=Falsetakes priority overskip_if_broken;conditional_sources.mdgains a section onwhen=/skip_if_brokenprecedence. (#arch_cleanup) - Unify the single-source and multi-source loading paths through a single
MergeConfig(removesprepare_single_source); split_do_load_multiinto_run_merge+_validate_mergedfor readability; move all env-dependent setup out ofLoader.__init__into_prepare_for_loadcalled on each.load(); extract_make_retort_keyhelper and replace_get_validation_loader(id-based memoization) with a straightforward_build_validation_loader. (#loader_unify_single_multi)
0.19.1#
Bugfixes#
- Fix field_mapping aliases not matching in sources that normalize key case (EnvSource, EnvFileSource, DockerSecretsSource, IniSource). Aliases such as "DB_PASSWORD" now correctly map to the dataclass field regardless of whether the source lowercases its keys. (#field_mapping_uppercase)
FieldRefis now typed asAnyinstead of a fixed union of primitive types. Fields in user dataclasses can be of any type (including custom classes), so the previous union was incomplete and caused false mypy errors when usingF[DataClass].fieldas afield_mappingkey. (#field_ref_any)
0.19.0#
Features#
- Add
encodingfield toFileSource(andEnvFileSource) and a matchingloading.encodingglobal default. Default isNone(Python'sopen()default — platform locale encoding), so existing behavior is unchanged. Setencoding="utf-8"on a source or viaconfigure(loading={"encoding": "utf-8"})for explicit control. - Re-export
Providerandloaderfromdature.loadersso custom sources no longer needfrom adaptix import .... cacheparameter ondature.load()now acceptsdatetime.timedeltafor TTL-based invalidation (in addition tobool); TTL is bucket-aligned so every class loaded inside the same window invalidates at the exact same instant. Introduced publicdature.Loaderclass as the explicit carrier of load-time state — including cache.dature.load(*sources, schema=Cls, ...)is now a thin shortcut forLoader(*sources, schema=Cls, ...).load()and does not retain cache across calls (throwaway loader). To make caching useful in function mode, construct aLoaderexplicitly and reuse the instance. Decorator-mode caching (@dature.load(...)) is unchanged.LoadingConfig.cacheaccepts the same union type, andDATURE_LOADING__CACHEcan be set to atimedeltastring (e.g.0:00:30) for the same effect.
Bugfixes#
- Fix
read_file_contentin the error formatter to use the source'sencodingsetting. Previously, error location display forFileSource/EnvFileSourcewith a non-default encoding (e.g.cp1251) would silently fall back to the platform encoding, causingUnicodeDecodeErrorthat suppressed line-content from error messages.
Refactoring#
- Internal: comprehensive restructuring of the loading subsystem and import graph. No public API change for end users.
Module layout changes:
loading/single.pyremoved; per-source report factory moved toload_report.py, logger toloader.py.loading/multi.pyrenamed toloading/merge.py(stripped to merge mechanics only).loading/merge_config.pydeleted.- New
loading/merge_runtime.pyhouses the mutual-annotation triangle (MergeConfig↔SourceMergeStrategy↔LoadCtx) together with per-source helpers (apply_source_init_params,apply_source_config_defaults,resolve_type_loaders,should_skip_broken,resolve_skip_invalid,apply_merge_skip_invalid). loading/source_loading.pyreduced toenrich_skipped_errors.SourceEntry/FieldOriginextracted toreport_types.py;LoadReportextracted toload_report.py— breaks thereport_types ↔ merge_runtimecycle.SkippedFieldSource/SourceContextmoved toerrors/location.py(next toErrorContext).CaretSpan/LineRange/SourceLocationextracted toerrors/loc_types.py, breaking theerrors.message → errors.exceptionsdependency.FieldValidatorsalias extracted to newvalidators/types.py;types.pyno longer imports fromvalidators.string_value_loadersmoved fromsources/retort.pytosources/base.py.strategies/source.pyno longer re-exportsLoadCtx/SourceMergeStrategy.
Import hygiene:
typing.TYPE_CHECKINGis now banned project-wide (enforced by ruffflake8-tidy-imports); all imports are at module level.- All function-scope
# noqa: PLC0415imports removed; remaining circular import cycles broken structurally by the module layout changes above.
Potentially breaking for subclasses (private API): _BaseYamlSource._yaml_version() now returns tuple[int, int] instead of ruamel.yaml.docinfo.Version; _BaseTomlSource._toml_version() annotation changed to Literal["1.0.0", "1.1.0"]. - Internal: merged path_finders/ module into the corresponding sources/ files. No public API change.
What changed:
src/dature/path_finders/removed entirely (was internal, never exported).src/dature/_descriptors.py(classproperty) removed — no longer needed.Source.path_finder_classclass variable removed.- New
Source._build_line_index(content: str) -> dict[tuple[str, ...], LineRange] | Nonemethod added. Default returnsNone(no diagnostics). Format sources override it to return a line map. - Line-lookup logic for yaml, toml, json, json5, ini now lives in the same file as the corresponding
Sourceclass (e.g.sources/yaml_.pycontains_build_yaml_line_mapand_walk_yaml_mapping). _find_parent_line_rangeinSourceupdated to accept a dict instead of aPathFinderinstance.- Tests from
tests/path_finders/moved totests/sources/test_<fmt>_line_index.py.
For custom Source subclasses (private API): if you previously set path_finder_class on a custom source, override _build_line_index instead. Return a dict[tuple[str, ...], LineRange] mapping dotted key paths to line ranges, or None to disable diagnostics.
0.18.0#
Features#
- Add
datureCLI withinspect(prints the load report) andvalidate(exits 0 on success, 1 on validation failure) subcommands. Sources are passed as--source type=dature.JsonSource,file=config.json(Docker-style key=value,\,and\=escape separators in values), and the schema as--schema myapp.config:Settings. Global flags mirrorload()and are generated from its signature.
Add ArgparseSource and the abstract CliSource base — a Source for loading command-line arguments into a dataclass. ArgparseSource takes a user-built argparse.ArgumentParser (the parser reads sys.argv itself; supports any depth of subparsers, mapped to nested fields). Bool flags always feed into the result; non-bool args only when explicitly passed, so CLI safely composes with file/env sources via load(). CliSource is the extension point for click/typer/custom parsers — implement _parse_argv() and you're done. (#84) - Add RemoteSource (abstract base for Sources that fetch from remote services) and the first concrete remote: VaultSource for HashiCorp Vault. Supports KV v1 and KV v2, token and AppRole authentication, optional Vault Enterprise namespace. Connection settings (url, credentials, mount_point, kv_version) can be set per-instance, via dature.configure(vault={...}), or via DATURE_VAULT__* env vars; instance-level fields take precedence. Install via pip install dature[vault]. Integration tests requiring a running Vault container are gated behind the integration pytest marker (excluded from the default pytest run; run via pytest -m integration with testcontainers[vault] installed).
Bugfixes#
- Fix
LoadReport.sources[*].file_pathandLoadReport.field_origins[*].source_fileto contain a path string rather than therepr()of apathlib.Path(e.g."PosixPath('...')").
Fix dature ... --secret-field-names X crashing with TypeError: unhashable type: 'list'. The CLI schema declares secret_field_names as list[str] (argparse action="append" produces a list), but load() expects tuple[str, ...] and uses it as part of a dict cache key. build_load_kwargs_from_dataclass now coerces the list back to a tuple at the load() boundary for any param whose load() annotation is tuple-shaped.
Fix CliSource error messages displaying flag names in upper case (e.g. --DB--HOST). The base FlatKeySource uppercases via _build_var_name because that matches env-var convention (APP_DB_HOST); CliSource now overrides _build_var_name to preserve case, so both NestedConflict.used_var (built during nested-conflict detection) and the flag name rendered in error messages remain in their original case (--db--host).
CliSource (and therefore ArgparseSource) now defaults expand_env_vars to "disabled". The shell has already expanded $VAR before values reach Python; re-expanding silently turned quoted literals like --password '$ecret' into empty strings. Users who want CLI values re-expanded can opt in by passing expand_env_vars="default" (or "empty" / "strict") explicitly.
Fix mixed path separators on Windows when a Path is passed to a file-based Source and contains an $ENV_VAR whose value uses /. Toml11Source(file=Path("$DATURE_DIR") / "config.toml") with DATURE_DIR=/etc/app previously produced /etc/app\config.toml; expand_file_path now re-normalizes through pathlib.Path when the input was a Path, yielding \etc\app\config.toml on Windows and /etc/app/config.toml on POSIX. str inputs are still returned verbatim so user-chosen separators are preserved. (#84) - Fix RemoteSource.resolve_location ignoring the source's prefix: error messages for prefixed sources (e.g. VaultSource(prefix="app", ...)) used to show only the field key without the rendered value, because _lookup_loaded was called with the schema-side field_path directly while _loaded_cache holds the raw pre-prefix data. - Fix single-source dature.load(source, schema=...) (and the @load(source) decorator) ignoring dature.configure(...) and DATURE_* env defaults — only the multi-source path was running apply_source_config_defaults. Notably affects VaultSource users who relied on global vault configuration with a single source.
Docs#
- Add documentation for
RemoteSourceand the contract for plugging in custom remote sources, withVaultSourceas a worked example. Examples are runnable end-to-end against a live Vault container in the integration suite.
Refactoring#
datureCLI now parses its own arguments throughArgparseSource: the schema it loads into is built at runtime from the signature ofload()viadataclasses.make_dataclass, so CLI flags stay in sync with the public API automatically.main()no longer accepts anargvparameter — likeArgparseSourceitself, it readssys.argvdirectly. Bool actions registered withdefault=Noneare now suppressed fromArgparseSourceoutput (treated as "unset", same as non-bool flags), so absence on the CLI falls back to the schema/dataclass default rather than emitting a literalNone. (#84)
Misc#
- Move
types-hvacout of the runtimevaultextra into a newtype-stubsextra so production installs ofdature[vault]no longer pull typing stubs. mypy/pyright users opt in withpip install dature[vault,type-stubs].
0.17.1#
Bugfixes#
import datureno longer pulls in the optionaljson5package. Previously,dature.loaders.json5_importedjson5.JsonIdentifierat module load time, so any project that depended on dature without the[json5]extra crashed withModuleNotFoundError: No module named 'json5'on the very firstfrom dature import .... The annotation is now resolved lazily underTYPE_CHECKING.
0.17.0#
Features#
- Set default
fileparameter to".env"in :class:.EnvFileSource. The class can now be instantiated without arguments:EnvFileSource()loads from.envin the current working directory. (#envfile-default-dotenv) - Added automatic config file search in standard system locations.
All FileSource subclasses (YamlSource, JsonSource, TomlSource, IniSource, EnvFileSource) now search for config files in: - ~/.config/ (Linux/macOS) - /etc/ (Linux) - /etc/xdg/ (Linux) - %APPDATA%/ (Windows)
Search is enabled by default. Can be configured globally via dature.configure(loading={...}) or per-source via search_system_paths and system_config_dirs parameters. - Added the V DSL for validation predicates: Annotated[int, (V >= 1) & (V <= 65535)], Annotated[str, V.len() >= 3], Annotated[list[str], V.unique_items() & V.each(V.len() >= 3)]. Predicates compose via &, |, and ~. V.each(...) validates each element and reports the failing index in the field path (tags.2). V.check(func, error_message=...) is the escape hatch for arbitrary user predicates. V.root(func, error_message=...) replaces RootValidator for cross-field checks. Applying a predicate to an incompatible type (e.g. V.len() on int) now raises ValidatorTypeError eagerly, before any configuration data is read. - All concrete source classes (EnvSource, JsonSource, Yaml11Source, Yaml12Source, Toml10Source, Toml11Source, IniSource, Json5Source, EnvFileSource, DockerSecretsSource, FileSource) are now exported from dature directly. - Environment variables in Source(file=...) are now expanded automatically in strict mode. Both directory paths ($CONFIG_DIR/config.toml) and file names (config.$APP_ENV.toml) are supported. - Error messages for EnvSource and DockerSecretsSource now include the actual field value. EnvSource shows ENV 'VAR_NAME' = 'value'; DockerSecretsSource shows the file content before the secret file path. Secret fields are not affected — their values remain hidden. The caret in error messages now points to the specific field's value within a JSON object, rather than the last occurrence of the same string. - Error messages now render a caret (^) under every visible line of a multi-line value, not just single-line values — so the whole offending block is underlined at a glance. Introduces a new CaretSpan(start, end) type in dature.errors and replaces SourceLocation.caret: tuple[int, int] | None with SourceLocation.line_carets: list[CaretSpan] | None (parallel to line_content). Per-line caret computation moves from the message renderer into Source.resolve_location via new classmethods _compute_line_carets, _caret_for_key_line, _nonwhitespace_span — subclasses can override for format-specific pointing.
As a consequence, EnvSource and DockerSecretsSource error output format changes to match the rest of the sources (content line with ├── + caret line + └── location line):
EnvSource:└── ENV 'APP_PORT' = '0'→├── APP_PORT=0/│ ^/└── ENV 'APP_PORT'. Multi-line env values are split across separate content lines, each with its own caret.DockerSecretsSource:├── 0→├── port = 0(content now showssecret_name = valueinstead of just the raw value).- Made merge strategies pluggable via a
Protocol-based class API.
Built-in source-level strategies (SourceLastWins, SourceFirstWins, SourceFirstFound, SourceRaiseOnConflict) and field-level strategies (FieldLastWins, FieldFirstWins, FieldAppend, FieldAppendUnique, FieldPrepend, FieldPrependUnique) are now classes implementing public Protocols — SourceMergeStrategy and FieldMergeStrategy respectively. They live under the new dature.strategies package and can be imported as building blocks for custom strategies.
Source-level strategies receive list[Source] plus a LoadCtx helper, so they can iterate sources themselves, dispatch on source type (e.g. isinstance(src, EnvSource)), and decide when to load each one (FIRST_FOUND short-circuit is preserved). Custom strategies compose built-ins — e.g. SourceLastWins()(files, ctx) inside an EnvOverrides strategy that lays env data strictly on top of files.
The public string API stays: load(strategy="last_wins", field_merges={F.x: "append"}) continues to work exactly as before. Unknown strategy names now raise DatureConfigError("invalid merge strategy: '...'. Available: ...") with the list of valid names.
Internal MergeStrategyEnum/FieldMergeStrategyEnum enums and the load_sources/LoadedSources helpers are removed; their logic moved into LoadCtx.load(). Callers that imported dature.merging.strategy directly need to switch to dature.strategies.
Per-step debug logging (Merge step N, State after step N) and LoadReport.field_origins are now driven by a single primary entry point LoadCtx.merge(source=..., base=..., op=...). Built-in strategies and custom strategies use the same call — origins are computed from per-step deltas, so any custom merge logic (including middle-pick / EnvOverrides-style with priorities) gets correct field_origins for free, without isinstance heuristics on the strategy class. - LoadingConfig.system_config_dirs now holds the full platform-search policy directly: a Mapping[str, Iterable[Path | str]] keyed by sys.platform with XDG-compliant defaults. String entries expand $VAR/${VAR}/${VAR:-default} and ~; each entry is split by os.pathsep after expansion, so $XDG_CONFIG_DIRS=/a:/b yields two directories. Undefined environment variables without a fallback are skipped and a warning is logged. New public type alias dature.types.SystemConfigDirsArg.
Bugfixes#
- Fixed
apply_source_init_paramsleaking a staleFileFieldMixin._resolved_file_pathcache: priming the cache (e.g. viarepr(source)) beforeload(...)no longer preventssearch_system_paths/system_config_dirsoverrides from taking effect. - Fixed attribute name typo (
filecontent→file_content) inraise_on_conflictmerge strategy that causedAttributeErrorwhen conflicting fields were detected. EnvFileSourcenow honorssearch_system_pathsandsystem_config_dirs(previously the system-path search was bypassed for.envfiles).load()no longer emits the "Merge-related parameters have no effect with a single source" warning whenstrategyis left at its default. Detection is now decoupled from the specific default strategy value — the warning fires when the user explicitly passesstrategy, regardless of which strategy was passed (the previous string-equality check incorrectly treated class-form defaults likeSourceLastWins()as non-default).strategy="first_found"now correctly limitsfield_merges,field_groups, and the merged source's type loaders / error context to the single source it selected. Previously, combiningfirst_foundwithfield_groupstriggered an internal pre-load that broke the strategy's documented short-circuit and silent-skip semantics — broken sources could surface errors instead of being skipped, validation errors could be attributed to the wrong file, andfield_mergescould aggregate over sources the strategy never picked.
Docs#
- Added a new "Loading" page to the Getting Started section that walks through common load-time errors (missing file, malformed source, type mismatch, missing required field, multiple errors) with their actual stderr output, plus a
skip_if_brokenrecovery example. - Improved documentation for Caching, Merge Rules, Configure, Custom Types, and Field Groups sections.
- Updated documentation to reflect the renaming of
split_symbolstonested_sepparameter across all affected pages. - Validation docs now use real runnable examples for every source format in the Error Format section (YAML, JSON, JSON5, TOML, INI, ENV, ENV file, Docker Secrets), plus new examples for multi-line and dataclass-typed values. Removed duplicated "Error Messages" section from the Introduction page.
Refactoring#
- Built-in validators (
Ge,Le,Gt,Lt,MinLength,MaxLength,RegexPattern,MinItems,MaxItems,UniqueItems) now acceptvalueas a positional argument:Ge(1)instead ofGe(value=1).RootValidatornow acceptsfuncas a positional argument:RootValidator(check)instead ofRootValidator(func=check).error_messageremains keyword-only in all validators. - Deduplicated
_find_nested_dataclassesinto sharedtype_utils.find_nested_dataclasses. - Error message formatting helpers extracted from
dature.errors.exceptionsinto a newdature.errors.messagemodule. Exception classes now contain only data and delegate rendering toformat_location/format_path. - Examples for docs in
examples/dir now hasline-length = 80 - Extracted retort factory methods from
Sourceinto free functions insources/retort.py.transform_to_dataclassis now a free function. - Extracted shared
resolve_mask_secretslogic fromsingle.pyandmulti.pyintoloading/common.py. - Internal type hints now use
MergeStrategyEnum/FieldMergeStrategyEnuminstead ofMergeStrategyName/FieldMergeStrategyNameLiteral aliases. Public API type hints remain unchanged. - Moved
_string_value_loadersand adaptix runtime imports out ofdature.sources.baseintodature.sources.retort.string_value_loadersis now importable fromdature.sources.retort. Public API is unchanged. - Recommended import style changed from
from dature import load, Sourcetoimport daturewith access viadature.load(),dature.Source(). - Renamed
_MergeConfigtoMergeConfig. - Renamed
display_nametoformat_nameanddisplay_labeltolocation_labelacross all source classes and error types. - Renamed
metadata/source_metaparameters tosourcethroughout the loading module. - Renamed internal package
sources_loadertosources(source classes) andloaders(type conversion). All public imports fromdatureare unchanged. - Simplified
config_paths:get_system_config_dirsis now a generator yielding directories in priority order, private platform helpers inlined, internaliter_config_pathsremoved.find_configis the sole search primitive;sources.baseuses it via a cached_resolved_file_pathproperty (no more repeated filesystem probes on a single source).FileSource._loadhandles streams explicitly. - Source user-facing attributes are no longer mutated during
load(). Load-level params are injected into source fields via_apply_source_init_params()before loading.MergeConfigis split into merge-specific settings and aSourceParamsdataclass holding per-source defaults.load_raw()reads directly fromselfwithout parameters. Theretortscache is still populated lazily during loading. Mergeclass has been removed. Useload()with multipleSourcearguments instead.Source(file_=...)has been renamed toSource(file=...).SourceRaiseOnConflictnow performs its conflict-detection pass internally instead of relying onmulti.py. The generic loader is fully strategy-agnostic; custom strategies can replicate the same behaviour viaraise_on_conflict(ctx.loaded_raw_dicts(), ctx.loaded_source_ctxs(), ctx.dataclass_name, field_merge_paths=ctx.field_merge_paths).LoadCtxnow exposesdataclass_nameandfield_merge_pathsas public attributes for this purpose. As a side effect, whenraise_on_conflictis combined withfield_groupsand both validations would fail,MergeConflictErrornow surfaces beforeFieldGroupError(previously the order was reversed); both errors require user action either way.apply_source_init_paramsis now invoked exactly once per source — insideMergeConfig.__post_init__— instead of being re-applied at each downstream call site (retort warmup, validating retort,LoadCtx.load). The function moved toloading/merge_config.py;MergeConfig.sourcesnow stores prepared sources after construction.configure()now accepts dicts instead of dataclass instances:masking={"mask": "***"},error_display={"max_visible_lines": 5},loading={"debug": True},type_loaders={MyType: my_loader}.
Removals#
- Removed
FieldGroupdataclass from public API. Passfield_groupsastuple[tuple[F[Config].field, ...], ...]instead. - Removed
MergeRuledataclass from public API. Passfield_mergesasdictmappingF[Config].fieldto a strategy string or callable instead. - Removed
MergeStrategyandFieldMergeStrategyenums from public API. Use string literals instead:"last_wins","first_wins","first_found","raise_on_conflict"for merge strategies;"first_wins","last_wins","append","append_unique","prepend","prepend_unique"for field merge strategies. - Removed
TypeLoaderdataclass from public API. Passtype_loadersasdict[type, Callable]instead. - Removed
LoaderProtocolfromdature.protocols. Source classes now handle loading internally. - Removed
dature.config_paths.get_system_config_dirs. System search directories are now fully defined inLoadingConfig.system_config_dirs(accessible asdature.config.loading.system_config_dirsat runtime). - Removed
secret_field_namesandmask_secretsfrom theSourcedataclass. Pass them todature.load()instead — passing them to aSourceconstructor now raisesTypeError. - Removed the per-class validator API (
Ge,Gt,Lt,Le,MinLength,MaxLength,RegexPattern,MinItems,MaxItems,UniqueItems,RootValidator) andValidatorProtocol. All validation must now go throughV— see the+v-dsl.featurefragment. Default error messages for length-based predicates changed from"Value must have at least N characters"/"Value must have at least N items"to the unified"Value length must be greater than or equal to N"(override via.with_error_message(...)if needed). - Renamed
split_symbolsparameter tonested_sepin :class:.FlatKeySourceand all subclasses (EnvSource,EnvFileSource,DockerSecretsSource). The old parameter name is no longer supported.
Misc#
- Added unit tests for
loading/context,loading/source_loading,masking/detection,validators/base,loaders/common,loaders/base.
0.16.0#
Features#
- Reworked masking configuration: replaced
mask_char,min_visible_chars,min_length_for_partial_mask, andfixed_mask_lengthwithmask,visible_prefix, andvisible_suffix. Default masking now fully redacts values as<REDACTED>instead of showing partial content.
Docs#
- Extracted all inline Python code blocks from docs into executable example files with assertions. Affected pages:
masking.md,why-not-pydantic-settings.md,why-not-dynaconf.md,why-not-hydra.md.
Misc#
- Added coverage for test coverage tracking in CI.
0.15.3#
Features#
Mergenow acceptssourcesas a positional argument:Merge(Source(...), Source(...)). (#merge-positional-sources)
0.15.2#
Bugfixes#
- Fixed placeholder values in
ByteSizeandPaymentCardNumberexamples that prevented them from running.
Docs#
- Fixed incorrect code examples in comparison docs (
Mergekeyword args,MergeStrategyenum values, validator import paths). Replaceddocs/changelog.mdwith a symlink to rootCHANGELOG.md.
0.15.1#
Features#
- Switched to hatch-vcs for dynamic versioning from git tags and towncrier for changelog management. Removed PAT token dependency from all CI workflows.
Changelog#
Unreleased#
0.15.0#
Improvements#
- Refactored and renamed the
load_metadatafunction for better clarity and consistency.
Docs#
- Updated documentation across multiple files to reflect changes related to the
load_metadatafunction.
0.14.4#
Docs#
- Improved documentation for the "Why not Pydantic Settings" section.
- Updated the configuration of the documentation site.
0.14.3#
Docs#
- Fixed issues in the documentation for improved clarity and accuracy.
- Updated the configuration for Read the Docs integration in the documentation.
- Updated the JavaScript configuration for Read the Docs.
0.14.2#
Fixes#
- Corrected issues in the documentation related to JavaScript integration.
0.14.1#
Docs#
- Updated documentation for clarity and consistency.
- Improved the CI workflow for better integration with documentation generation.
- Enhanced stylesheets for improved readability in documentation.
- Refactored documentation generation scripts for better maintainability.
- Resolved various issues in the documentation.
0.14.0#
Improvements#
- Refactored error handling in the exceptions module to provide clearer messages.
- Enhanced the sources loader to improve performance and reliability.
- Updated validation examples to demonstrate new features and best practices.
- Improved error handling in the loading module to prevent crashes on invalid inputs.
Fixes#
- Resolved issues with error reporting in the validation module.
- Fixed bugs in the masking examples to ensure accurate functionality.
- Corrected various test cases to improve coverage and reliability.
- Addressed errors in the source loading process to enhance stability.
- Fixed errors related to loading configurations from different sources.
0.13.0#
Features#
- Introduced a new strategy for configuration loading.
Improvements#
- Enhanced the
int_from_stringfunction to correctly cast boolean values to integers. - Improved documentation for advanced configuration options.
Fixes#
- Updated the README to reflect recent changes and improvements.
- Addressed comments from Devin regarding code clarity and documentation.
0.12.4#
Fixes#
- Ensured JSON5 support is now correctly required in the configuration loader.
- Resolved issues related to loading configurations from JSON5 files.
0.12.3#
Improvements#
- Refactored the strict retort functionality for enhanced performance.
- Added a fallback mechanism for Read the Docs (RTD) to improve documentation accessibility.
Fixes#
- Resolved issues in various source loader files to ensure better compatibility and functionality.
0.12.2#
Improvements#
- Removed duplicate error messages for better clarity.
- Eliminated unnecessary traceback information to streamline error reporting.
Fixes#
- Fixed the Read the Docs configuration in the CI workflow to ensure proper documentation generation.
0.12.1#
Improvements#
- Enhanced the changelog generation process to ensure accurate updates.
- Updated documentation to include support for
timedeltaas a valid type. - Resolved security issues to improve overall safety.
Docs#
- Corrected documentation tags for clarity and consistency.
Features#
- Added logging functionality to
dature. - Added Docker Secrets loader.
- Added
SecretStr,PaymentCardNumber, andByteSizespecial field types. - Added secret masking in error messages (by field name and heuristic detection).
- Added ENV variable expansion in config values.
- Added field alias provider for flexible field name mapping.
- Added
configure()for global masking, error display, and loading settings. - Added
Ffield path objects with field mapping support. - Added field group support for merge rules.
- Added custom merge functions and merge strategies (
append,prepend,first_wins, etc.). - Added
skip_invalidandskip_brokenmerge options (global and per-source). - Added mypy plugin.
Improvements#
- Restructured source code into subpackages:
errors/,expansion/,fields/,loading/,masking/,merging/. - Restructured tests to mirror
src/layout. - Improved path finders for YAML, TOML, JSON, JSON5, and INI formats.
- Improved error formatting with source location context.
- Improved source loader base with better type safety.
- Improved ENV loader with strip and type handling.
- Skipped lint/test jobs on tag push in CI (already verified on main push).
- Improved CI configurations for better stability and reliability.
Fixes#
- Fixed various issues in the CI configuration.
- Resolved multiple bugs affecting functionality and stability.
Docs#
- Added documentation site (MkDocs + Material) with full coverage: getting started, features, advanced topics, API reference.
- Added
CHANGELOG.mdwith AI-generated entries on PR creation. - Added social cards, minify, 8-bit themed headings, and custom color scheme to docs.
- Added changelog workflow: AI generates changelog entries per PR, release job extracts them for GitHub Releases.
- Added CI support for tag push:
pypi-publish,github-release, andtrigger-rtdnow run on tag events. - Added
trigger-rtdjob supporting bothlatest(main) andstable(tag) RTD builds. - Added version-bump, dependency-review, scorecard, and docs CI workflows.
- Added dependabot configuration.
- Added CODEOWNERS and SECURITY.md.
- Added comprehensive examples for all features.
- Slimmed down
README.mdin favor of documentation site.