Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
DylanLukes opened this issue Jun 4, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@DylanLukes
Copy link

DylanLukes commented Jun 4, 2024

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.

@DylanLukes
Copy link
Author

Currently I bypass this by simply using typing.cast to cast Traversable into Path. This is a bit brittle as there's no guarantee pydantic_settings won't eventually start using something Traversable doesn't support, but at least today it does indeed work.

@hramezani
Copy link
Member

Thanks @DylanLukes for bringing this up.

Would you be interested in working on fixing and creating a PR?

@hramezani hramezani added the enhancement New feature or request label Jun 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants