4242_R_co = TypeVar ("_R_co" , covariant = True )
4343
4444
45- def _isinstance (obj : Any , tp : Any ) -> bool :
45+ def _isinstance (obj : Any , tp : Any , fn : Any ) -> bool :
4646 # Handle Any type - matches everything
4747 if tp is Any :
4848 return True
@@ -52,7 +52,7 @@ def _isinstance(obj: Any, tp: Any) -> bool:
5252 return isinstance (obj , tp )
5353
5454 elif _typing_inspect .is_union_type (tp ):
55- return any (_isinstance (obj , el ) for el in typing .get_args (tp ))
55+ return any (_isinstance (obj , el , fn ) for el in typing .get_args (tp ))
5656
5757 elif _typing_inspect .is_literal (tp ):
5858 # For Literal types, check if obj is one of the literal values
@@ -62,11 +62,17 @@ def _isinstance(obj: Any, tp: Any) -> bool:
6262 origin = typing .get_origin (tp )
6363 args = typing .get_args (tp )
6464 if origin is type :
65+ atype = args [0 ]
66+ if isinstance (atype , TypeVar ):
67+ atype = atype .__bound__
68+ ns = _namespace .module_ns_of (fn )
69+ atype = _typing_eval .resolve_type (atype , globals = ns )
70+
6571 if isinstance (obj , type ):
66- return issubclass (obj , args [ 0 ] )
72+ return issubclass (obj , atype )
6773 elif (mroent := getattr (obj , "__mro_entries__" , None )) is not None :
6874 genalias_mro = mroent ((obj ,))
69- return any (issubclass (c , args [ 0 ] ) for c in genalias_mro )
75+ return any (issubclass (c , atype ) for c in genalias_mro )
7076 else :
7177 return False
7278
@@ -93,7 +99,7 @@ def _isinstance(obj: Any, tp: Any) -> bool:
9399
94100 # For Mapping[K, V], check first key and first value
95101 k , v = next (iter (obj .items ()))
96- return _isinstance (k , args [0 ]) and _isinstance (v , args [1 ])
102+ return _isinstance (k , args [0 ], fn ) and _isinstance (v , args [1 ], fn )
97103
98104 elif issubclass (origin , tuple ):
99105 # Check the container type first
@@ -111,13 +117,13 @@ def _isinstance(obj: Any, tp: Any) -> bool:
111117 # heterogeneous tuple[*T]
112118 if num_args == 2 and args [1 ] is ...:
113119 # Homogeneous tuple like tuple[int, ...]
114- return _isinstance (next (iter (obj )), args [0 ])
120+ return _isinstance (next (iter (obj )), args [0 ], fn )
115121 elif num_args != num_elems :
116122 # Shape of tuple value does not match type definition
117123 return False
118124 else :
119125 for el_type , el_val in zip (args , obj , strict = True ):
120- if not _isinstance (el_val , el_type ):
126+ if not _isinstance (el_val , el_type , fn ):
121127 return False
122128 return True
123129
@@ -130,7 +136,7 @@ def _isinstance(obj: Any, tp: Any) -> bool:
130136 if not args or len (obj ) == 0 :
131137 return True
132138
133- return _isinstance (next (iter (obj )), args [0 ])
139+ return _isinstance (next (iter (obj )), args [0 ], fn )
134140
135141 else :
136142 # For other generic types, fall back to checking the origin
@@ -270,7 +276,7 @@ def _call(
270276 f"cannot dispatch to { self ._qname } : an overload "
271277 f"is missing a type annotation on the { pn } parameter"
272278 )
273- if not _isinstance (arg , pt ):
279+ if not _isinstance (arg , pt , fn ):
274280 break
275281 else :
276282 if bound_to is not None :
0 commit comments