-
-
Notifications
You must be signed in to change notification settings - Fork 64
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
Regression in customizing sources in pydantic V2 #250
Comments
The problem with It was possible to set a private attribute on the If nothing else, documentation is clearly outdated. Also, I was quite surprised by the fact that if you provide multiple config files, it reads them all and merges the result (instead of just using the first one found). This should also be pointed out in the docs. |
You can implement your custom
if you mean
|
Yes, but I need to instantiate this custom subclass of Again, in V1, I could use a
I'm not talking about dotenv files. I'm refering to https://docs.pydantic.dev/latest/concepts/pydantic_settings/#customise-settings-sources
And also https://docs.pydantic.dev/latest/concepts/pydantic_settings/#other-settings-source
This doesn't mention anything about the way multiple files are handled. |
Yeah, you don't have access to the settings model instance in source classes and We can't change it in Regarding multiple files for |
+1 On this issue. Being able to parameterize the file source for yaml/toml/etc configurations feels like it should be a basic feature of these settings, and it's frustrating to have to work around it. |
One possible workaround is to use a closure. It's not particularly pretty, but it will work. import argparse
import sys
from typing import Type, Tuple
from argparse import ArgumentParser
from pathlib import Path
from pydantic_settings import (
BaseSettings,
SettingsConfigDict,
PydanticBaseSettingsSource,
YamlConfigSettingsSource,
)
def to_settings(yaml_file: Path):
class Settings(BaseSettings):
model_config = SettingsConfigDict(yaml_file=yaml_file)
alpha: int
beta: int
@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, ...]:
return (YamlConfigSettingsSource(settings_cls),)
return Settings
def validate_path(sx: str) -> Path:
px = Path(sx)
if px.exists():
return px
raise argparse.ArgumentError(None, message=f"{sx} not a valid file path.")
def to_parser() -> ArgumentParser:
p = ArgumentParser()
p.add_argument(
"-f", "--yaml-file", required=True, type=validate_path, help="Path to YAML file"
)
return p
def main(ax: list[str]) -> int:
p = to_parser()
pargs = p.parse_args(ax)
klass = to_settings(pargs.yaml_file)
settings = klass()
print(settings)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:])) In this example, I'm also validating at the argparse level to better communicate errors. Without this, the errors will be a generic Pydantic error (e.g., python example.py -f test.yml
alpha=1 beta=4 And on errors: python example.py -f junkx.yml
usage: example.py [-h] -f YAML_FILE
example.py: error: junkx.yml not a valid file path. |
I used a
customise_sources
in pydantic V1 to pass a custom config file and recently discovered that this no longer works under pydantic V2.MWE pydantic V1
In pydantic V1 following script works just fine:
MWE pydantic V2
When upgraded to pydantic V2 the script doesn't work (and I don't see a way how to fix it)
Analysis
I traced the changes back to #15 where settings sources have been remade, but
settings
instance was dropped from the callable. Yet the documentation about the return type ofsettings_customise_sources
explicitely states:See https://docs.pydantic.dev/latest/concepts/pydantic_settings/#customise-settings-sources
It seems to me that some use cases were omitted in the sources refactoring and there is no reasonably simple way to restore the behavior under pydantic V2 API. I wouldn't mind to provide a PR, but currently I can't even tell how to handle the differences between V1 and V2.
The text was updated successfully, but these errors were encountered: