Skip to content

Commit

Permalink
Merge pull request #205 from reagento/fix/decorate_hints
Browse files Browse the repository at this point in the history
replace newtype with temporary object for decorators
  • Loading branch information
Tishka17 committed Aug 10, 2024
2 parents 3c5b459 + 5d5ced1 commit 2a4d6fa
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
18 changes: 14 additions & 4 deletions src/dishka/registry.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from collections import defaultdict
from collections.abc import Callable, Sequence
from typing import Any, NewType, TypeVar, cast, get_args, get_origin
from typing import Any, TypeVar, cast, get_args, get_origin

from ._adaptix.type_tools.basic_utils import is_generic
from ._adaptix.type_tools.fundamentals import get_type_vars
Expand All @@ -26,6 +26,16 @@
from .provider import BaseProvider


class UndecoratedType:
"""Container for a type which is decorated in other place."""
def __init__(self, original: type[Any], depth: int) -> None:
self.original = original
self.level = depth

def __repr__(self) -> str:
return f"UndecoratedType({self.original}, depth={self.level})"


class Registry:
__slots__ = ("scope", "factories", "compiled", "compiled_async")

Expand Down Expand Up @@ -320,9 +330,9 @@ def _process_decorator(
)
scope = self.dependency_scopes[provides]
registry = self.registries[scope]
undecorated_type = NewType( # type: ignore[misc]
f"{provides.type_hint.__name__}@{self.decorator_depth[provides]}",
decorator.provides.type_hint, # type: ignore[name-defined]
undecorated_type = UndecoratedType(
decorator.provides.type_hint,
self.decorator_depth[provides],
)
self.decorator_depth[provides] += 1
old_factory = registry.get_factory(provides)
Expand Down
17 changes: 17 additions & 0 deletions tests/unit/container/test_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ class DProvider(Provider):
assert isinstance(a.a, A)


def test_with_hint():
class MyProvider(Provider):
a = provide(A, scope=Scope.APP, provides=A|None)

class DProvider(Provider):
@decorate
def a(self, a: A|None) -> A|None:
if a is None:
return None
return ADecorator(a)

container = make_container(MyProvider(), DProvider())
a = container.get(A|None)
assert isinstance(a, ADecorator)
assert isinstance(a.a, A)


def test_decorator():
class MyProvider(Provider):
a = provide(A, scope=Scope.APP)
Expand Down

0 comments on commit 2a4d6fa

Please sign in to comment.