Skip to content

Commit 78bb621

Browse files
authored
Add support for Annotated types (#219)
This is a relatively simple and straightforward implementation with minimal changes and seems to work fine. Resolves #217
1 parent 44ac4e0 commit 78bb621

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

injector/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,8 @@ def _punch_through_alias(type_: Any) -> type:
705705
and type(type_).__name__ == 'NewType'
706706
):
707707
return type_.__supertype__
708+
elif isinstance(type_, _AnnotatedAlias) and getattr(type_, '__metadata__', None) is not None:
709+
return type_.__origin__
708710
else:
709711
return type_
710712

injector_test.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
import traceback
1919
import warnings
2020

21+
if sys.version_info >= (3, 9):
22+
from typing import Annotated
23+
else:
24+
from typing_extensions import Annotated
25+
2126
from typing import Dict, List, NewType
2227

2328
import pytest
@@ -1682,3 +1687,70 @@ def function1(a: int | str) -> None:
16821687
pass
16831688

16841689
assert get_bindings(function1) == {'a': Union[int, str]}
1690+
1691+
1692+
# test for https://github.com/python-injector/injector/issues/217
1693+
def test_annotated_instance_integration_works():
1694+
UserID = Annotated[int, "user_id"]
1695+
1696+
def configure(binder):
1697+
binder.bind(UserID, to=123)
1698+
1699+
injector = Injector([configure])
1700+
assert injector.get(UserID) == 123
1701+
1702+
1703+
def test_annotated_class_integration_works():
1704+
class Shape(abc.ABC):
1705+
pass
1706+
1707+
class Circle(Shape):
1708+
pass
1709+
1710+
first = Annotated[Shape, "first"]
1711+
1712+
def configure(binder):
1713+
binder.bind(first, to=Circle)
1714+
1715+
injector = Injector([configure])
1716+
assert isinstance(injector.get(first), Circle)
1717+
1718+
1719+
def test_annotated_meta_separate_bindings():
1720+
first = Annotated[int, "first"]
1721+
second = Annotated[int, "second"]
1722+
1723+
def configure(binder):
1724+
binder.bind(first, to=123)
1725+
binder.bind(second, to=456)
1726+
1727+
injector = Injector([configure])
1728+
assert injector.get(first) == 123
1729+
assert injector.get(second) == 456
1730+
assert injector.get(first) != injector.get(second)
1731+
1732+
1733+
def test_annotated_origin_separate_bindings():
1734+
UserID = Annotated[int, "user_id"]
1735+
1736+
def configure(binder):
1737+
binder.bind(UserID, to=123)
1738+
binder.bind(int, to=456)
1739+
1740+
injector = Injector([configure])
1741+
assert injector.get(UserID) == 123
1742+
assert injector.get(int) == 456
1743+
assert injector.get(UserID) != injector.get(int)
1744+
1745+
1746+
def test_annotated_non_comparable_types():
1747+
foo = Annotated[int, float("nan")]
1748+
bar = Annotated[int, object()]
1749+
1750+
def configure(binder):
1751+
binder.bind(foo, to=123)
1752+
binder.bind(bar, to=456)
1753+
1754+
injector = Injector([configure])
1755+
assert injector.get(foo) == 123
1756+
assert injector.get(bar) == 456

0 commit comments

Comments
 (0)