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

Usage recommandation to add checks on provided value

Open gael-ft opened this issue 8 months ago • 3 comments
trafficstars

I am trying to implement a behavior that is really close to ThreadLocalSingleton scopes.

I have a container that is created when app starts. It holds data about the current customer. So when the app starts, the value is None. But at runtime, I want to forbid any injection if the current value is None.

Of course, I would like to keep this DI logic near containers. (No if not context: ... in MyService below)

I am currently able to do this kind of tricks by having 2 providers like below. my_context will be overrode within each requests. _safe_my_context will validate it before being injected in other components.

I'm not 100% comfortable with this. I am feeling like there's room for a DelegatedThreadLocalSingleton that could accept MyContext | None but would provide only a MyContext. Just didn't find examples of Delegate... of how to implement it properly.

Thanks for the lib!

# app/my_context.py

@dataclass
class MyContext:
    customer_id: str

# app/my_service.py

class MyService:
    def __init__(self, context: MyContext):
        ...

# app/containers.py

def _default_context() -> MyContext | None:
    return None

def _ensure_context(context: MyContext | None) -> MyContext:
    if context is None:
        msg = "Context not set"
        raise ValueError(msg)
    return context

class MyContainer(containers.DeclarativeContainer):
    my_context = providers.ThreadLocalSingleton(_default_context)
    _safe_my_context = providers.Callable(_ensure_context, context=my_context)

    some_service = providers.Factory(MyService, _safe_my_context)

gael-ft avatar Mar 10 '25 17:03 gael-ft