@@ -98,15 +98,15 @@ def wrapper(*args: Any, **kwargs: Any) -> Any:
98
98
lock = threading .RLock ()
99
99
100
100
101
- _inject_marker = object ()
102
- _noinject_marker = object ()
101
+ inject_marker = object ()
102
+ noinject_marker = object ()
103
103
104
104
InjectT = TypeVar ('InjectT' )
105
- Inject = Annotated [InjectT , _inject_marker ]
105
+ Inject = Annotated [InjectT , inject_marker ]
106
106
"""An experimental way to declare injectable dependencies utilizing a `PEP 593`_ implementation
107
107
in Python 3.9 and backported to Python 3.7+ in `typing_extensions`.
108
108
109
- Those two declarations are equivalent::
109
+ These three declarations are equivalent::
110
110
111
111
@inject
112
112
def fun(t: SomeType) -> None:
@@ -115,8 +115,11 @@ def fun(t: SomeType) -> None:
115
115
def fun(t: Inject[SomeType]) -> None:
116
116
pass
117
117
118
+ def fun(t: Annotated[SomeType, inject_marker]) -> None:
119
+ pass
120
+
118
121
The advantage over using :func:`inject` is that if you have some noninjectable parameters
119
- it may be easier to spot what are they. Those two are equivalent::
122
+ it may be easier to spot what are they. These two are equivalent::
120
123
121
124
@inject
122
125
@noninjectable('s')
@@ -142,7 +145,7 @@ def fun(t: Inject[SomeType], s: SomeOtherType) -> None:
142
145
.. _typing_extensions: https://pypi.org/project/typing-extensions/
143
146
"""
144
147
145
- NoInject = Annotated [InjectT , _noinject_marker ]
148
+ NoInject = Annotated [InjectT , noinject_marker ]
146
149
"""An experimental way to declare noninjectable dependencies utilizing a `PEP 593`_ implementation
147
150
in Python 3.9 and backported to Python 3.7+ in `typing_extensions`.
148
151
@@ -154,7 +157,7 @@ def fun(t: Inject[SomeType], s: SomeOtherType) -> None:
154
157
* The declaration may be relatively distance in space from the actual parameter declaration, thus
155
158
hindering readability
156
159
157
- `NoInject` solves both of those concerns, for example (those two declarations are equivalent)::
160
+ `NoInject` solves both of those concerns, for example (these three declarations are equivalent)::
158
161
159
162
@inject
160
163
@noninjectable('b')
@@ -165,6 +168,10 @@ def fun(a: TypeA, b: TypeB) -> None:
165
168
def fun(a: TypeA, b: NoInject[TypeB]) -> None:
166
169
pass
167
170
171
+ @inject
172
+ def fun(a: TypeA, b: Annotated[TypeB, noinject_marker]) -> None:
173
+ pass
174
+
168
175
.. seealso::
169
176
170
177
Function :func:`get_bindings`
@@ -1166,7 +1173,7 @@ def get_bindings(callable: Callable) -> Dict[str, type]:
1166
1173
if not hasattr (callable , '__bindings__' ):
1167
1174
type_hints = get_type_hints (callable , include_extras = True )
1168
1175
has_injectable_parameters = any (
1169
- _is_specialization (v , Annotated ) and _inject_marker in v .__metadata__ for v in type_hints .values ()
1176
+ _is_specialization (v , Annotated ) and inject_marker in v .__metadata__ for v in type_hints .values ()
1170
1177
)
1171
1178
1172
1179
if not has_injectable_parameters :
@@ -1244,7 +1251,7 @@ def _is_new_union_type(instance: Any) -> bool:
1244
1251
else :
1245
1252
metadata = tuple ()
1246
1253
1247
- if only_explicit_bindings and _inject_marker not in metadata or _noinject_marker in metadata :
1254
+ if only_explicit_bindings and inject_marker not in metadata or noinject_marker in metadata :
1248
1255
del bindings [k ]
1249
1256
elif _is_specialization (v , Union ) or _is_new_union_type (v ):
1250
1257
# We don't treat Optional parameters in any special way at the moment.
@@ -1264,8 +1271,8 @@ def _is_new_union_type(instance: Any) -> bool:
1264
1271
}
1265
1272
if (
1266
1273
only_explicit_bindings
1267
- and _inject_marker not in union_metadata
1268
- or _noinject_marker in union_metadata
1274
+ and inject_marker not in union_metadata
1275
+ or noinject_marker in union_metadata
1269
1276
):
1270
1277
del bindings [k ]
1271
1278
else :
0 commit comments