python-dependency-injector
python-dependency-injector copied to clipboard
Conf as pydantic
Hi,
I just wonder if there any possible transform configuration as pydantic.BaseSettings type?
There are some frameworks are dependency on pydantic settings.
This is weird to import pydantic to DI's config then to provide it as pydantic again
Or can I use like
from dependency_injector import containers
from pydantic import BaseSettings
class Settings(BaseSettings):
...
class Contrainer(containers.DeclarativeContainer):
settings = providers.Singleton(Settings)
Hi @jneo8 , check this: https://python-dependency-injector.ets-labs.org/providers/configuration.html#loading-from-a-pydantic-settings
@rmk135 Yes, The doc say we can load pydantic as config, then inject config to another provider. This is how we load config right now.
pydantic -> config
But if I need to inject pydantic's BaseSettings to another provider. So now my workaround is
pydantic -> config -> resource-provider-which-return-pydantic -> another provider
Configuration provider doesn't keep a reference to a provided pydantic object. Only data is stored. You probably could do like you mentioned if you need to inject pydantic object providers.Singleton(Settings)
.
It would be helpful if you could provide a sample code for demonstrating a problem.
I'm trying to use fastapi-jwt-auth
On their basic example, User have to write func to provide config like:
# callback to get your configuration
@AuthJWT.load_config
def get_config():
return Settings()
And this func need BaseSettings object to work.
So here is my workaround right now:
from dependency_injector import containers, providers
from fastapi_jwt_auth import AuthJWT
from pydantic import BaseSettings
class Container(containers.DeclarativeContainer):
"""Dependency injector container."""
def _get_jwt_settings(authjwt_secret_key: str):
"""Workaround to call AuthJWT.load_config without decorator.
For more details please see how fastapi_jwt_auth implement load_config
with classmethod.
"""
class JWTSettings(BaseSettings):
authjwt_secret_key: str
def get_settings():
return JWTSettings(authjwt_secret_key=authjwt_secret_key)
return get_settings
config = providers.Configuration()
jwt_settings = providers.Resource(
_get_jwt_settings,
authjwt_secret_key=config.AUTHJWT_SECRET_KEY,
)
jwt_config = providers.Resource(
AuthJWT.load_config,
settings=jwt_settings,
)
It work but I just consider is there any more clean way to make it work.
I'd like to second this concern- my current use case would benefit from a passed pydantic object rather than the dict:
from dependency_injector import containers, providers
from dependency_injector.wiring import Provide, inject
from pydantic import BaseSettings
import yaml
from slac_services.modeling import ModelDBConfig, ModelDB, ModelingService, RemoteModelingService, LocalModelingService
class Settings(BaseSettings):
model_db: ModelDBConfig
class ServiceContainer(containers.DeclarativeContainer):
config = providers.Configuration()
model_db = providers.Singleton(
ModelDB,
config.model_db # would like to pass as Pydantic settings
)
remote_modeling_service = providers.Singleton(
RemoteModelingService,
model_db=model_db,
)
local_modeling_service = providers.Singleton(
LocalModelingService
)
I have the same issue but managed to work around it by
class Application(containers.DeclarativeContainer):
settings = providers.ThreadSafeSingleton(Settings)
This works, although I would prefer to get the pydantic object from the start when using the pydantic_settings
option 😅