python-dependency-injector icon indicating copy to clipboard operation
python-dependency-injector copied to clipboard

Lazy-load pydantic settings in configuration

Open nicocrm opened this issue 2 years ago • 0 comments

Hi,

Thank you for this package!

I am using a container that loads configuration from a Pydantic setting:

config = providers.Configuration(pydantic_settings=[Settings()])

The problem I am running into is that the Settings are instantiated at import time, rather than at the time the container is created. This is an issue especially in unit tests, because the unit tests will set up some environment variables prior to instantiating the services. If the Settings class declares a mandatory setting, and it is not available until the unit test runs and injects it into the environment, the code crashes at import time. Likewise if the test, or the application code, overrides an environment variable with a custom value, it is not taken into account since the Pydantic settings have already been read.

I could work around it by removing the pydantic_settings parameter and calling container.config.from_pydantic, but that means the application code needs to have a reference to Settings, and it is also complicated by the fact that there are nested containers so I would need to pass the correct Settings to each nested container. I thought too of making the setting non-mandatory in the Pydantic declaration and then overriding the container configuration from the tests, but it would be ideal to keep the settings declaration as expressive as possible, including whether a setting is required or not.

Is it possible to defer the initialization for the container? The closest I found was using a Resource on the container, and it seems to work fine, but it adds a bit of boilerplate code:

class MyContainer(DeclarativeContainer):
    __self__ = providers.Self()
    config = providers.Configuration()
    _load_config = providers.Resource(lambda c: c.config.from_pydantic(Settings()), c=__self__)

nicocrm avatar Aug 17 '22 06:08 nicocrm