mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-12-14 13:44:03 +03:00
Allow annotated marker to be anywhere in the annotation list (#939)
This commit is contained in:
parent
244deee75f
commit
51f8187202
|
|
@ -682,23 +682,18 @@ def _unpatch_attribute(patched: PatchedAttribute) -> None:
|
|||
|
||||
def _extract_marker(parameter: inspect.Parameter) -> Optional["_Marker"]:
|
||||
if get_origin(parameter.annotation) is Annotated:
|
||||
args = get_args(parameter.annotation)
|
||||
if len(args) > 1:
|
||||
marker = args[1]
|
||||
else:
|
||||
marker = None
|
||||
candidates = get_args(parameter.annotation)[1:]
|
||||
else:
|
||||
marker = parameter.default
|
||||
candidates = (parameter.default,)
|
||||
|
||||
for marker_extractor in MARKER_EXTRACTORS:
|
||||
if _marker := marker_extractor(marker):
|
||||
marker = _marker
|
||||
break
|
||||
|
||||
if not isinstance(marker, _Marker):
|
||||
return None
|
||||
|
||||
return marker
|
||||
for marker in candidates:
|
||||
for marker_extractor in MARKER_EXTRACTORS:
|
||||
if _marker := marker_extractor(marker):
|
||||
marker = _marker
|
||||
break
|
||||
if _is_marker(marker):
|
||||
return marker
|
||||
return None
|
||||
|
||||
|
||||
@cache
|
||||
|
|
@ -1223,9 +1218,11 @@ def _get_members_and_annotated(obj: Any) -> Iterable[Tuple[str, Any]]:
|
|||
for annotation_name, annotation in annotations.items():
|
||||
if get_origin(annotation) is Annotated:
|
||||
args = get_args(annotation)
|
||||
if len(args) > 1:
|
||||
member = args[1]
|
||||
members.append((annotation_name, member))
|
||||
# Search through all metadata items (args[1:]) for a DI marker
|
||||
for arg in args[1:]:
|
||||
if _is_marker(arg):
|
||||
members.append((annotation_name, arg))
|
||||
break
|
||||
return members
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -124,3 +124,10 @@ def test_class_decorator(service: Annotated[Service, Provide[Container.service]]
|
|||
|
||||
def test_container(container: Annotated[Container, Provide[Container]]):
|
||||
return container.service()
|
||||
|
||||
|
||||
@inject
|
||||
def test_annotated_with_non_di_metadata_first(
|
||||
service: Annotated[Service, "some other annotated value", Provide[Container.service]],
|
||||
):
|
||||
return service
|
||||
|
|
|
|||
|
|
@ -174,3 +174,14 @@ def test_class_decorator():
|
|||
def test_container():
|
||||
service = module.test_container()
|
||||
assert isinstance(service, Service)
|
||||
|
||||
|
||||
def test_annotated_with_non_di_metadata_first():
|
||||
"""Test that Annotated works when DI marker is not the first metadata item.
|
||||
|
||||
This tests the case where Annotated has other metadata (like docstrings or
|
||||
other annotations) before the Provide marker, e.g.:
|
||||
Annotated[Service, "some doc", Provide[Container.service]]
|
||||
"""
|
||||
service = module.test_annotated_with_non_di_metadata_first()
|
||||
assert isinstance(service, Service)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user