Repository navigation
Support Traversable for json/toml/yaml config file sources (#299) - #902
Conversation
Add typing and runtime support for passing a `Traversable` (e.g. `importlib.resources.files(...).joinpath(...)`) as `json_file`, `toml_file`, or `yaml_file`, so packaged configuration resources no longer need a `cast` to `Path`. - Introduce a dedicated `ConfigFileSourceType` alias (`Path | str | Traversable | Sequence[...]`) and apply it to the config-file fields of `SettingsConfigDict` and the `*ConfigSettingsSource` constructors. `PathType` (used by `secrets_dir`) is left unchanged. - Fix `TomlConfigSettingsSource._any_file_exists`, which coerced every path via `Path(path)` and raised `TypeError` for a non-`Path` `Traversable` such as a resource inside a zip/wheel. It now queries such objects directly via `is_file()`, and also correctly handles a single `str` path. - Guard the `Traversable` import by version (`importlib.resources.abc` on 3.11+, `importlib.abc` on 3.10). - Add zip-packaged (genuine non-`Path`) Traversable regression tests for the toml and yaml sources, and a docs note. Co-Authored-By: Claude Opus 4.8 <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR extends pydantic-settings’ config-file sources (JSON/TOML/YAML) to accept importlib.resources Traversable objects (including non-filesystem resources like files inside a zip/wheel), aligning both typing and runtime behavior and adding regression coverage for TOML/YAML.
Changes:
- Introduces
ConfigFileSourceType(includesTraversable) and applies it toSettingsConfigDictand the JSON/TOML/YAML config sources. - Updates shared config-file reading logic to operate on
Path | Traversableand fixes TOML existence checks for non-PathTraversable. - Adds docs note and new regression tests for zip-packaged
TraversableTOML/YAML loading.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_source_yaml.py | Adds regression test for loading YAML from a zip-packaged non-Path Traversable. |
| tests/test_source_toml.py | Adds Traversable fixture + TOML regression tests; note: new skip conditions need adjustment. |
| tests/test_source_json.py | Updates comment to reflect Traversable is now in the annotation. |
| pydantic_settings/sources/types.py | Adds ConfigFileSourceType and version-guarded Traversable import; exports the alias. |
| pydantic_settings/sources/providers/yaml.py | Switches yaml_file typing to ConfigFileSourceType and supports Traversable in _read_file. |
| pydantic_settings/sources/providers/toml.py | Switches toml_file typing and fixes _any_file_exists for Traversable and single-string inputs. |
| pydantic_settings/sources/providers/json.py | Switches json_file typing and supports Traversable in _read_file. |
| pydantic_settings/sources/base.py | Updates ConfigFileSourceMixin to read `Path |
| pydantic_settings/sources/init.py | Re-exports ConfigFileSourceType from pydantic_settings.sources. |
| pydantic_settings/main.py | Updates SettingsConfigDict field types for json/toml/yaml to ConfigFileSourceType. |
| docs/index.md | Documents Traversable support for json_file/toml_file/yaml_file. |
Comments suppressed due to low confidence (1)
pydantic_settings/sources/init.py:46
ConfigFileSourceTypeis exported frompydantic_settings.sources, but it’s not currently re-exported from the top-levelpydantic_settingspackage. If the intent is “export from the package” (as stated in the PR description), add it topydantic_settings/__init__.py(import +__all__) sofrom pydantic_settings import ConfigFileSourceTypeworks.
from .types import (
DEFAULT_PATH,
ENV_FILE_SENTINEL,
ConfigFileSourceType,
DotenvFiltering,
DotenvType,
EnvPrefixTarget,
ForceDecode,
NoDecode,
PathType,
PydanticModel,
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Use `sys.version_info < (3, 11)` (matching `import_toml`, where `tomli` is only needed below 3.11) instead of `<= (3, 11)` for the new Traversable test skip conditions, addressing PR review feedback. Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
Thanks for the review! Addressed in 450bf45:
|
|
@copilot resolve the merge conflicts in this pull request |
…onfig-files # Conflicts: # pydantic_settings/sources/providers/json.py # pydantic_settings/sources/providers/toml.py # pydantic_settings/sources/providers/yaml.py
Resolved in 74f8bfa. The only conflicts were in the import sections of |
Summary
Closes #299.
Adds typing and runtime support for passing a
Traversable(e.g.importlib.resources.files(...).joinpath(...)) asjson_file,toml_file, oryaml_file. This enables loading a configuration file that is packaged inside a distribution — including resources that don't live on the filesystem, such as a file inside a zip/wheel — without acasttoPath.Background
Issue #299 raised two points:
PathTypeincludesSequence[...].PathTypeshould includeTraversable— still a real typing gap. The issue also noted that aTraversable"currently works" at runtime. That is now only partially true: a genuine non-PathTraversable(a zip/wheel-packaged resource) still works for JSON/YAML, but regressed for TOML —TomlConfigSettingsSource._any_file_existswraps every path inPath(path), which raisesTypeErrorfor an object that isn'tos.PathLike.Changes
ConfigFileSourceTypealias (Path | str | Traversable | Sequence[Path | str | Traversable]) and apply it to the config-file fields ofSettingsConfigDictand to theJson/Toml/Yaml*ConfigSettingsSourceconstructors (and the shared_read_files/_read_file).PathType— used bysecrets_dir— is intentionally left unchanged so directory handling keeps itsPath-only semantics.TomlConfigSettingsSource._any_file_existsto query a non-PathTraversabledirectly viais_file()instead of coercing throughPath(...). This also fixes a latent bug where a singlestrpath was iterated character-by-character.Traversableimport (importlib.resources.abcon 3.11+,importlib.abcon 3.10), sinceimportlib.abc.Traversablewas removed in 3.12+.ConfigFileSourceTypefrom the package.Tests
Path)Traversableregression tests for the TOML source (plain load andtoml_table_header) and the YAML source.TestTraversableSupport; updated its now-stale "not added in annotation" comment.Verified locally:
mypyclean (no new errors over baseline),ruffclean, full test suite green (excluding pre-existing Windows-only symlink test failures unrelated to this change).🤖 Generated with Claude Code