Skip to content

Make inject markers for Annotations public #269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions injector/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,15 @@ def wrapper(*args: Any, **kwargs: Any) -> Any:
lock = threading.RLock()


_inject_marker = object()
_noinject_marker = object()
inject_marker = object()
noinject_marker = object()

InjectT = TypeVar('InjectT')
Inject = Annotated[InjectT, _inject_marker]
Inject = Annotated[InjectT, inject_marker]
"""An experimental way to declare injectable dependencies utilizing a `PEP 593`_ implementation
in Python 3.9 and backported to Python 3.7+ in `typing_extensions`.

Those two declarations are equivalent::
These three declarations are equivalent::

@inject
def fun(t: SomeType) -> None:
Expand All @@ -115,8 +115,11 @@ def fun(t: SomeType) -> None:
def fun(t: Inject[SomeType]) -> None:
pass

def fun(t: Annotated[SomeType, inject_marker]) -> None:
pass

The advantage over using :func:`inject` is that if you have some noninjectable parameters
it may be easier to spot what are they. Those two are equivalent::
it may be easier to spot what are they. These two are equivalent::

@inject
@noninjectable('s')
Expand All @@ -142,7 +145,7 @@ def fun(t: Inject[SomeType], s: SomeOtherType) -> None:
.. _typing_extensions: https://pypi.org/project/typing-extensions/
"""

NoInject = Annotated[InjectT, _noinject_marker]
NoInject = Annotated[InjectT, noinject_marker]
"""An experimental way to declare noninjectable dependencies utilizing a `PEP 593`_ implementation
in Python 3.9 and backported to Python 3.7+ in `typing_extensions`.

Expand All @@ -154,7 +157,7 @@ def fun(t: Inject[SomeType], s: SomeOtherType) -> None:
* The declaration may be relatively distance in space from the actual parameter declaration, thus
hindering readability

`NoInject` solves both of those concerns, for example (those two declarations are equivalent)::
`NoInject` solves both of those concerns, for example (these three declarations are equivalent)::

@inject
@noninjectable('b')
Expand All @@ -165,6 +168,10 @@ def fun(a: TypeA, b: TypeB) -> None:
def fun(a: TypeA, b: NoInject[TypeB]) -> None:
pass

@inject
def fun(a: TypeA, b: Annotated[TypeB, noinject_marker]) -> None:
pass

.. seealso::

Function :func:`get_bindings`
Expand Down Expand Up @@ -1166,7 +1173,7 @@ def get_bindings(callable: Callable) -> Dict[str, type]:
if not hasattr(callable, '__bindings__'):
type_hints = get_type_hints(callable, include_extras=True)
has_injectable_parameters = any(
_is_specialization(v, Annotated) and _inject_marker in v.__metadata__ for v in type_hints.values()
_is_specialization(v, Annotated) and inject_marker in v.__metadata__ for v in type_hints.values()
)

if not has_injectable_parameters:
Expand Down Expand Up @@ -1244,7 +1251,7 @@ def _is_new_union_type(instance: Any) -> bool:
else:
metadata = tuple()

if only_explicit_bindings and _inject_marker not in metadata or _noinject_marker in metadata:
if only_explicit_bindings and inject_marker not in metadata or noinject_marker in metadata:
del bindings[k]
elif _is_specialization(v, Union) or _is_new_union_type(v):
# We don't treat Optional parameters in any special way at the moment.
Expand All @@ -1264,8 +1271,8 @@ def _is_new_union_type(instance: Any) -> bool:
}
if (
only_explicit_bindings
and _inject_marker not in union_metadata
or _noinject_marker in union_metadata
and inject_marker not in union_metadata
or noinject_marker in union_metadata
):
del bindings[k]
else:
Expand Down