Skip to content

Can my custom PydanticBaseSettingsSource get values already retrieved from other PydanticBaseSettingsSources? #290

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

Closed
red8888 opened this issue May 16, 2024 · 2 comments
Assignees

Comments

@red8888
Copy link

red8888 commented May 16, 2024

I also opened an SO post FYI: https://stackoverflow.com/questions/78486685/is-it-possible-for-a-custom-pydanticbasesettingssource-to-retrieve-computed-valu

I know the way it generally works is you use the field_name to locate the value, but I want to have a field that is a model with additional data that my custom PydanticBaseSettingsSource will use to retrieve the actual value and I don't think json_schema_extra would work here because I want to use the actual field value that will be retrieved from the dotenv source.

For example:

config = MyApp(
    # I want my custom source to read the input assigned test01 and return the secret value
    test01 = ExternalSecret(
	id="sdfsdfds", account="sdfsdfsd")
    )

And then in settings_customise_sources

    @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 (
            init_settings,
            env_settings,
            dotenv_settings,
            file_secret_settings,
            MyCustomSource(settings_cls),
        )

I have MyCustomSource run after all the other sources here. Is there a way to, from inside a PydanticBaseSettingsSource, get the currently computed values of a field? Where is that info stored?

I'm assuming that you continuously clobbler/re-write a fields value for each source, but maybe it doesn't work that way? What I'm trying to do I guess might be impossible if you process all sources and then set the value a single time instead of continuously re-assigning it.

What would also work for me would be a post-processor method that just runs at the end of all sources that could loop over all the fields, get their values, and reassign some of the fields values. Is there such a method?

I just found out about pydantic_init_subclass, but I don't know how to get the field values inside of it. This just gives me the field names:

    @classmethod
    def __pydantic_init_subclass__(cls):
        for field_name, field in cls.model_fields.items():

Edit

So just found out about this method, is this the best way to implement what I want? Not using a custom source at all and just looping over all the fields like this?

    def model_post_init(self, __context) -> None:
        for field_name, field_value in self:
            print(field_name)
            print(field_value)
@hramezani
Copy link
Member

Thanks @red8888 for reporting this issue.
I think this could be a duplicate of #223.
Right now the source classes don't have access to other sources' data.

What would also work for me would be a post-processor method that just runs at the end of all sources that could loop over all the fields, get their values, and reassign some of the fields values. Is there such a method?

We don't have such a method in pydantic-settings. but probably pydantic model_validators can help you.

@hramezani
Copy link
Member

Closing this because of duplication

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants