pydantic / pydantic-settings

Settings management using pydantic
https://docs.pydantic.dev/latest/usage/pydantic_settings/
MIT License
591 stars 61 forks source link

Feature request: add a reload method to re-parse env variables #315

Closed nrolin closed 3 months ago

nrolin commented 3 months ago

In the case of tests, we might want to change the config of an existing object in place by supplying it different env variables. We can already do it, but it would be more reassuring if there is a dedicated method.

example:

from pydantic import Field
from pydantic_settings import BaseSettings
import os

class Config(BaseSettings):
    test: bool = Field(default=True)
> my_test = Config()
> print(my_test.test)
True
> os.environ["test"] = "False"
> print(my_test.test)
True
> my_test.__init__()   # <- it would be better to have a reload method that is guaranteed to have the correct semantics
> print(my_test.test)
False
hramezani commented 3 months ago

@nrolin I think you can initialize the settings model again my_test = Config() instead of my_test.__init__().

I think adding a method only for testing purposes is not a good idea.

nrolin commented 3 months ago

@nrolin I think you can initialize the settings model again my_test = Config() instead of my_test.__init__().

Sorry my example wasn't clear enough

in my_file.py

from pydantic import Field
from pydantic_settings import BaseSettings
import os

class Config(BaseSettings):
    test: bool = Field(default=True)

my_test = Config()

def get_my_test():
    return my_test.test

in an ipython :

> from my_file import my_test, os, get_my_test
> get_my_test()
True
> os.environ["test"] = "False"
> get_my_test()
True
> my_test.__init__()   # <- it would be better to have a reload method that is guaranteed to have the correct semantics
> get_my_test()
False

I can't do my_test = Config() because it wouldn't change the result of get_my_test()

I think adding a method only for testing purposes is not a good idea.

Some people are doing really convoluted things to achieve this (e.g : https://rednafi.com/python/patch_pydantic_settings_in_pytest/ ), so it would be nice to have an official guideline on how to solve this issue.

hramezani commented 3 months ago

‌ Some people are doing really convoluted things to achieve this (e.g : https://rednafi.com/python/patch_pydantic_settings_in_pytest/ ), so it would be nice to have an official guideline on how to solve this issue.

I haven't read this carefully but adding some pytest fixture seems good. BTW, I don't see any problem with using my_test.__init__(). So, having another reload method that does the same thing or calls __init__ is extra IMO.

nrolin commented 3 months ago

BTW, I don't see any problem with using my_test.init(). So, having another reload method that does the same thing or calls init is extra IMO.

The problem is that as an user I suppose that __init__ does reload as if I was creating the object, but it kinda a gamble and nothing guarantees that the developer will not silently change the semantics without warning in a future version (which is 100% fair for a dunder method).

Adding it in the doc or a proper method gives a bit more security on this side.

hramezani commented 3 months ago

Ok, would you like to open a PR for this?

nrolin commented 3 months ago

Ok I will try

hramezani commented 3 months ago

Doc added in https://github.com/pydantic/pydantic-settings/commit/c2d44a7723a00f75ba6790cc654aaa507a7ab123