@@ -547,9 +547,11 @@ def matches_type(
547
547
return False
548
548
return True
549
549
550
- @staticmethod
550
+ @classmethod
551
551
def is_instance (
552
- obj : object , candidates : ty .Union [ty .Type [ty .Any ], ty .Iterable [ty .Type [ty .Any ]]]
552
+ cls ,
553
+ obj : object ,
554
+ candidates : ty .Union [ty .Type [ty .Any ], ty .Iterable [ty .Type [ty .Any ]]],
553
555
) -> bool :
554
556
"""Checks whether the object is an instance of cls or that cls is typing.Any,
555
557
extending the built-in isinstance to check nested type args
@@ -566,9 +568,14 @@ def is_instance(
566
568
for candidate in candidates :
567
569
if candidate is ty .Any :
568
570
return True
571
+ # Handle ty.Type[*] candidates
572
+ if ty .get_origin (candidate ) is type :
573
+ return inspect .isclass (obj ) and cls .is_subclass (
574
+ obj , ty .get_args (candidate )[0 ]
575
+ )
569
576
if NO_GENERIC_ISSUBCLASS :
570
- if candidate is type and inspect .isclass (obj ):
571
- return True
577
+ if inspect .isclass (obj ):
578
+ return candidate is type
572
579
if issubtype (type (obj ), candidate ) or (
573
580
type (obj ) is dict and candidate is ty .Mapping
574
581
):
@@ -597,10 +604,19 @@ def is_subclass(
597
604
any_ok : bool
598
605
whether klass=typing.Any should return True or False
599
606
"""
600
- if not isinstance (candidates , ty .Iterable ):
607
+ if not isinstance (candidates , ty .Sequence ):
601
608
candidates = [candidates ]
602
609
603
610
for candidate in candidates :
611
+ # Handle ty.Type[*] types in klass and candidates
612
+ if ty .get_origin (klass ) is type and (
613
+ candidate is type or ty .get_origin (candidate ) is type
614
+ ):
615
+ if candidate is type :
616
+ return True
617
+ return cls .is_subclass (ty .get_args (klass )[0 ], ty .get_args (candidate )[0 ])
618
+ elif ty .get_origin (klass ) is type or ty .get_origin (candidate ) is type :
619
+ return False
604
620
if NO_GENERIC_ISSUBCLASS :
605
621
if klass is type and candidate is not type :
606
622
return False
0 commit comments