Skip to content

Typing for multiple PathTypes (and support Traversable) for SettingsConfigDict json_file, toml_file, yaml_file, etc #299

Open
@DylanLukes

Description

@DylanLukes

There are issues with the typing for the file options for SettingsConfigDict:

  1. They are typed as PathType | None despite documentation indicating they accept lists (which indeed they do).

json_file: PathType | None
json_file_encoding: str | None
yaml_file: PathType | None
yaml_file_encoding: str | None

The documentation indicates this at: https://docs.pydantic.dev/latest/concepts/pydantic_settings/#other-settings-source

  1. PathType could, but does not not include importlib.resources.abc.Traversable:

PathType = Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]

I should note that if one provides a Traversable, it does currently work, indicating the subset of Path functionality used by pydantic-settings is within the Traversable subset of Path.

In the example below, I pass a Traversable, and I have verified in a test that it does indeed load the packaged resource file just fine.


Motivation

A somewhat useful pattern is to package a default configuration file inside a Python package. For example:

class FoobarSettings(BaseSettings):
    data_dir: Path

    model_config = SettingsConfigDict(
        env_prefix="foobar_",
        toml_file=[
            resources.files("foobar").joinpath("foobar.defaults.toml"),
            "foobar.toml"
        ],
    )
    
    @classmethod
    def settings_customise_sources(
            cls,
            settings_cls: type[BaseSettings],
            init_settings: PydanticBaseSettingsSource,
            env_settings: PydanticBaseSettingsSource,
            dotenv_settings: PydanticBaseSettingsSource,
            file_secret_settings: PydanticBaseSettingsSource,
    ) -> tuple[PydanticBaseSettingsSource, ...]:
        default_sources = super().settings_customise_sources(
            settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings
        )
        return *default_sources, TomlConfigSettingsSource(settings_cls)

And then have in src/foobar/foobar.defaults.toml:

data_dir = ".foobar/data"

This currently works. However, it will not type-check.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions