.. _decorate: decorate ********************* ``decorate`` is used to modify or wrap an object which is already configured in another ``Provider``. Provider object has also a ``.decorate`` method with the same logic. If you want to apply decorator pattern and do not want to alter existing provide method, then it is a place for ``decorate``. It will construct object using earlier defined provider and then pass it to your decorator before returning from the container. .. code-block:: python from dishka import decorate, Provider, provide, Scope class UserDAO(Protocol): ... class UserDAOImpl(UserDAO): ... class UserDAOWithMetrics(UserDAO): def __init__(self, dao: UserDAO) -> None: self.dao = dao self.prometheus = Prometheus() def get_by_id(self, uid: UserID) -> User: self.prometheus.get_by_id_metric.inc() return self.dao.get_by_id(uid) class MyProvider(Provider): user_dao = provide( UserDAOImpl, scope=Scope.REQUEST, provides=UserDAO ) @decorate def decorate_user_dao(self, dao: UserDAO) -> UserDAO: return UserDAOWithMetrics(dao) Such decorator function can also have **additional parameters**. .. code-block:: python from dishka import decorate, Provider, provide, Scope class UserDAO(Protocol): ... class UserDAOImpl(UserDAO): ... class UserDAOWithMetrics(UserDAO): def __init__(self, dao: UserDAO, prom: Prometheus) -> None: self.dao = dao self.prometheus = prom def get_by_id(self, uid: UserID) -> User: self.prometheus.get_by_id_metric.inc() return self.dao.get_by_id(uid) class MyProvider(Provider): user_dao = provide( UserDAOImpl, scope=Scope.REQUEST, provides=UserDAO ) prometheus = provide(Prometheus) @decorate def decorate_user_dao( self, dao: UserDAO, prom: Prometheus ) -> UserDAO: return UserDAOWithMetrics(dao, prom) Decorator can change the **Scope** of an object to more narrow one, just pass ``scope=`` argument. The limitation is that you cannot use ``decorate`` in the same provider as you declare factory or alias for dependency. But you won't need it because you can update the factory code. The idea of ``decorate`` is to postprocess dependencies provided by some external source, when you combine multiple ``Provider`` objects into one container. If a sync non-generator decorator is used by an activator dependency, you can opt in to static evaluation with ``allow_static_evaluation=True``: .. code-block:: python from dishka import Marker, Provider, Scope, activate, decorate, provide class MyProvider(Provider): @provide(scope=Scope.APP) def base_cache(self) -> Cache: return InMemoryCache() @decorate(scope=Scope.APP, allow_static_evaluation=True) def tagged_cache(self, cache: Cache) -> Cache: cache.name = "tagged" return cache @activate(Marker("tagged")) def use_tagged(self, cache: Cache) -> bool: return cache.name == "tagged" When the decorator is cached through the decorated dependency, the value created during static evaluation is reused by the runtime container.