2525 Type ,
2626 TypeVar ,
2727 Union ,
28- assert_never ,
2928 cast ,
3029)
3130from warnings import warn
3231
3332try :
34- from typing import Self
33+ from typing import Self , assert_never
3534except ImportError :
36- from typing_extensions import Self
35+ from typing_extensions import Self , assert_never
3736
3837try :
3938 from functools import cache
@@ -140,6 +139,10 @@ class DIWiringWarning(RuntimeWarning):
140139 """Base class for all warnings raised by the wiring module."""
141140
142141
142+ class UnresolvedMarkerWarning (DIWiringWarning ):
143+ """Warning raised when a marker with string identifier cannot be resolved against container."""
144+
145+
143146class PatchedRegistry :
144147
145148 def __init__ (self ) -> None :
@@ -434,6 +437,7 @@ def wire( # noqa: C901
434437 modules : Optional [Iterable [ModuleType ]] = None ,
435438 packages : Optional [Iterable [ModuleType ]] = None ,
436439 keep_cache : bool = False ,
440+ warn_unresolved : bool = False ,
437441) -> None :
438442 """Wire container providers with provided packages and modules."""
439443 modules = [* modules ] if modules else []
@@ -450,9 +454,23 @@ def wire( # noqa: C901
450454 continue
451455
452456 if _is_marker (member ):
453- _patch_attribute (module , member_name , member , providers_map )
457+ _patch_attribute (
458+ module ,
459+ member_name ,
460+ member ,
461+ providers_map ,
462+ warn_unresolved = warn_unresolved ,
463+ warn_unresolved_stacklevel = 1 ,
464+ )
454465 elif inspect .isfunction (member ):
455- _patch_fn (module , member_name , member , providers_map )
466+ _patch_fn (
467+ module ,
468+ member_name ,
469+ member ,
470+ providers_map ,
471+ warn_unresolved = warn_unresolved ,
472+ warn_unresolved_stacklevel = 1 ,
473+ )
456474 elif inspect .isclass (member ):
457475 cls = member
458476 try :
@@ -464,15 +482,30 @@ def wire( # noqa: C901
464482 for cls_member_name , cls_member in cls_members :
465483 if _is_marker (cls_member ):
466484 _patch_attribute (
467- cls , cls_member_name , cls_member , providers_map
485+ cls ,
486+ cls_member_name ,
487+ cls_member ,
488+ providers_map ,
489+ warn_unresolved = warn_unresolved ,
490+ warn_unresolved_stacklevel = 1 ,
468491 )
469492 elif _is_method (cls_member ):
470493 _patch_method (
471- cls , cls_member_name , cls_member , providers_map
494+ cls ,
495+ cls_member_name ,
496+ cls_member ,
497+ providers_map ,
498+ warn_unresolved = warn_unresolved ,
499+ warn_unresolved_stacklevel = 1 ,
472500 )
473501
474502 for patched in _patched_registry .get_callables_from_module (module ):
475- _bind_injections (patched , providers_map )
503+ _bind_injections (
504+ patched ,
505+ providers_map ,
506+ warn_unresolved = warn_unresolved ,
507+ warn_unresolved_stacklevel = 1 ,
508+ )
476509
477510 if not keep_cache :
478511 clear_cache ()
@@ -525,14 +558,21 @@ def _patch_fn(
525558 name : str ,
526559 fn : Callable [..., Any ],
527560 providers_map : ProvidersMap ,
561+ warn_unresolved : bool = False ,
562+ warn_unresolved_stacklevel : int = 0 ,
528563) -> None :
529564 if not _is_patched (fn ):
530565 reference_injections , reference_closing = _fetch_reference_injections (fn )
531566 if not reference_injections :
532567 return
533568 fn = _get_patched (fn , reference_injections , reference_closing )
534569
535- _bind_injections (fn , providers_map )
570+ _bind_injections (
571+ fn ,
572+ providers_map ,
573+ warn_unresolved = warn_unresolved ,
574+ warn_unresolved_stacklevel = warn_unresolved_stacklevel + 1 ,
575+ )
536576
537577 setattr (module , name , fn )
538578
@@ -542,6 +582,8 @@ def _patch_method(
542582 name : str ,
543583 method : Callable [..., Any ],
544584 providers_map : ProvidersMap ,
585+ warn_unresolved : bool = False ,
586+ warn_unresolved_stacklevel : int = 0 ,
545587) -> None :
546588 if (
547589 hasattr (cls , "__dict__" )
@@ -559,7 +601,12 @@ def _patch_method(
559601 return
560602 fn = _get_patched (fn , reference_injections , reference_closing )
561603
562- _bind_injections (fn , providers_map )
604+ _bind_injections (
605+ fn ,
606+ providers_map ,
607+ warn_unresolved = warn_unresolved ,
608+ warn_unresolved_stacklevel = warn_unresolved_stacklevel + 1 ,
609+ )
563610
564611 if fn is method :
565612 # Hotfix, see: https://github.com/ets-labs/python-dependency-injector/issues/884
@@ -595,9 +642,17 @@ def _patch_attribute(
595642 name : str ,
596643 marker : "_Marker" ,
597644 providers_map : ProvidersMap ,
645+ warn_unresolved : bool = False ,
646+ warn_unresolved_stacklevel : int = 0 ,
598647) -> None :
599648 provider = providers_map .resolve_provider (marker .provider , marker .modifier )
600649 if provider is None :
650+ if warn_unresolved :
651+ warn (
652+ f"Unresolved marker { name } in { member !r} " ,
653+ UnresolvedMarkerWarning ,
654+ stacklevel = warn_unresolved_stacklevel + 2 ,
655+ )
601656 return
602657
603658 _patched_registry .register_attribute (PatchedAttribute (member , name , marker ))
@@ -674,7 +729,12 @@ def _fetch_reference_injections( # noqa: C901
674729 return injections , closing
675730
676731
677- def _bind_injections (fn : Callable [..., Any ], providers_map : ProvidersMap ) -> None :
732+ def _bind_injections (
733+ fn : Callable [..., Any ],
734+ providers_map : ProvidersMap ,
735+ warn_unresolved : bool = False ,
736+ warn_unresolved_stacklevel : int = 0 ,
737+ ) -> None :
678738 patched_callable = _patched_registry .get_callable (fn )
679739 if patched_callable is None :
680740 return
@@ -683,6 +743,12 @@ def _bind_injections(fn: Callable[..., Any], providers_map: ProvidersMap) -> Non
683743 provider = providers_map .resolve_provider (marker .provider , marker .modifier )
684744
685745 if provider is None :
746+ if warn_unresolved :
747+ warn (
748+ f"Unresolved marker { injection } in { fn .__qualname__ } " ,
749+ UnresolvedMarkerWarning ,
750+ stacklevel = warn_unresolved_stacklevel + 2 ,
751+ )
686752 continue
687753
688754 if isinstance (marker , Provide ):
0 commit comments