25
25
Type ,
26
26
TypeVar ,
27
27
Union ,
28
- assert_never ,
29
28
cast ,
30
29
)
31
30
from warnings import warn
32
31
33
32
try :
34
- from typing import Self
33
+ from typing import Self , assert_never
35
34
except ImportError :
36
- from typing_extensions import Self
35
+ from typing_extensions import Self , assert_never
37
36
38
37
try :
39
38
from functools import cache
@@ -140,6 +139,10 @@ class DIWiringWarning(RuntimeWarning):
140
139
"""Base class for all warnings raised by the wiring module."""
141
140
142
141
142
+ class UnresolvedMarkerWarning (DIWiringWarning ):
143
+ """Warning raised when a marker with string identifier cannot be resolved against container."""
144
+
145
+
143
146
class PatchedRegistry :
144
147
145
148
def __init__ (self ) -> None :
@@ -434,6 +437,7 @@ def wire( # noqa: C901
434
437
modules : Optional [Iterable [ModuleType ]] = None ,
435
438
packages : Optional [Iterable [ModuleType ]] = None ,
436
439
keep_cache : bool = False ,
440
+ warn_unresolved : bool = False ,
437
441
) -> None :
438
442
"""Wire container providers with provided packages and modules."""
439
443
modules = [* modules ] if modules else []
@@ -450,9 +454,23 @@ def wire( # noqa: C901
450
454
continue
451
455
452
456
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
+ )
454
465
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
+ )
456
474
elif inspect .isclass (member ):
457
475
cls = member
458
476
try :
@@ -464,15 +482,30 @@ def wire( # noqa: C901
464
482
for cls_member_name , cls_member in cls_members :
465
483
if _is_marker (cls_member ):
466
484
_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 ,
468
491
)
469
492
elif _is_method (cls_member ):
470
493
_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 ,
472
500
)
473
501
474
502
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
+ )
476
509
477
510
if not keep_cache :
478
511
clear_cache ()
@@ -525,14 +558,21 @@ def _patch_fn(
525
558
name : str ,
526
559
fn : Callable [..., Any ],
527
560
providers_map : ProvidersMap ,
561
+ warn_unresolved : bool = False ,
562
+ warn_unresolved_stacklevel : int = 0 ,
528
563
) -> None :
529
564
if not _is_patched (fn ):
530
565
reference_injections , reference_closing = _fetch_reference_injections (fn )
531
566
if not reference_injections :
532
567
return
533
568
fn = _get_patched (fn , reference_injections , reference_closing )
534
569
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
+ )
536
576
537
577
setattr (module , name , fn )
538
578
@@ -542,6 +582,8 @@ def _patch_method(
542
582
name : str ,
543
583
method : Callable [..., Any ],
544
584
providers_map : ProvidersMap ,
585
+ warn_unresolved : bool = False ,
586
+ warn_unresolved_stacklevel : int = 0 ,
545
587
) -> None :
546
588
if (
547
589
hasattr (cls , "__dict__" )
@@ -559,7 +601,12 @@ def _patch_method(
559
601
return
560
602
fn = _get_patched (fn , reference_injections , reference_closing )
561
603
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
+ )
563
610
564
611
if fn is method :
565
612
# Hotfix, see: https://github.com/ets-labs/python-dependency-injector/issues/884
@@ -595,9 +642,17 @@ def _patch_attribute(
595
642
name : str ,
596
643
marker : "_Marker" ,
597
644
providers_map : ProvidersMap ,
645
+ warn_unresolved : bool = False ,
646
+ warn_unresolved_stacklevel : int = 0 ,
598
647
) -> None :
599
648
provider = providers_map .resolve_provider (marker .provider , marker .modifier )
600
649
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
+ )
601
656
return
602
657
603
658
_patched_registry .register_attribute (PatchedAttribute (member , name , marker ))
@@ -674,7 +729,12 @@ def _fetch_reference_injections( # noqa: C901
674
729
return injections , closing
675
730
676
731
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 :
678
738
patched_callable = _patched_registry .get_callable (fn )
679
739
if patched_callable is None :
680
740
return
@@ -683,6 +743,12 @@ def _bind_injections(fn: Callable[..., Any], providers_map: ProvidersMap) -> Non
683
743
provider = providers_map .resolve_provider (marker .provider , marker .modifier )
684
744
685
745
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
+ )
686
752
continue
687
753
688
754
if isinstance (marker , Provide ):
0 commit comments