5555 AnyValue ,
5656 CallableValue ,
5757 CanAssignContext ,
58+ ClassKey ,
59+ ClassOwner ,
5860 ClassSymbol ,
5961 CustomCheckExtension ,
6062 GenericBases ,
@@ -153,11 +155,11 @@ def get_can_assign_context(self) -> CanAssignContext:
153155 raise NotImplementedError
154156
155157 def get_generic_bases (
156- self , typ : type | str , generic_args : Sequence [Value ]
158+ self , typ : ClassKey , generic_args : Sequence [Value ]
157159 ) -> GenericBases :
158160 raise NotImplementedError
159161
160- def get_synthetic_class (self , typ : type | str ) -> SyntheticClassObjectValue | None :
162+ def get_synthetic_class (self , typ : ClassKey ) -> SyntheticClassObjectValue | None :
161163 raise NotImplementedError
162164
163165 def clone_for_attribute_lookup (
@@ -278,14 +280,14 @@ def get_attribute(ctx: AttrContext) -> Value:
278280 args = root_value .args
279281 else :
280282 args = ()
281- if isinstance (root_value .typ , str ):
283+ if isinstance (root_value .typ , ClassOwner ):
282284 attribute_value = _get_attribute_from_synthetic_typed_value (root_value , ctx )
283285 else :
284286 attribute_value = _get_attribute_from_typed (root_value .typ , args , ctx )
285287 elif isinstance (root_value , SubclassValue ):
286- synthetic_name : str | None = None
288+ synthetic_name : ClassKey | None = None
287289 if isinstance (root_value .typ , TypedValue ):
288- if isinstance (root_value .typ .typ , str ):
290+ if isinstance (root_value .typ .typ , ClassOwner ):
289291 synthetic_name = root_value .typ .typ
290292 else :
291293 attribute_value = _get_attribute_from_subclass (
@@ -294,7 +296,7 @@ def get_attribute(ctx: AttrContext) -> Value:
294296 elif isinstance (root_value .typ , TypeVarValue ):
295297 if root_value .typ .typevar_param .bound is not None :
296298 bound = replace_fallback (root_value .typ .typevar_param .bound )
297- if isinstance (bound , TypedValue ) and isinstance (bound .typ , str ):
299+ if isinstance (bound , TypedValue ) and isinstance (bound .typ , ClassOwner ):
298300 synthetic_name = bound .typ
299301 else :
300302 assert_never (root_value .typ )
@@ -358,7 +360,7 @@ def _maybe_specialize_class_partial_root(root_value: Value, ctx: AttrContext) ->
358360 return root_value
359361 root = replace_fallback (root_value .root )
360362 can_assign_ctx = ctx .get_can_assign_context ()
361- class_key : type | str | None = None
363+ class_key : ClassKey | None = None
362364 if isinstance (root , SyntheticClassObjectValue ) and isinstance (
363365 root .class_type , TypedValue
364366 ):
@@ -405,7 +407,7 @@ def _specialized_class_partial_member_to_type(
405407def _get_namedtuple_member_from_sequence_value (
406408 root_value : SequenceValue , ctx : AttrContext
407409) -> Value | None :
408- if not isinstance (root_value .typ , str ):
410+ if not isinstance (root_value .typ , ClassOwner ):
409411 return None
410412 type_object = ctx .get_can_assign_context ().make_type_object (root_value .typ )
411413 if not type_object .is_direct_namedtuple ():
@@ -444,7 +446,7 @@ def _super_receiver_type_value(value: Value) -> tuple[TypedValue | None, bool]:
444446 return None , False
445447
446448
447- def _super_thisclass_key (value : Value ) -> type | str | None :
449+ def _super_thisclass_key (value : Value ) -> ClassKey | None :
448450 value = replace_fallback (value )
449451 if isinstance (value , KnownValue ) and isinstance (value .val , type ):
450452 return value .val
@@ -651,7 +653,7 @@ def _get_attribute_from_synthetic_typed_value(
651653
652654
653655def _get_attribute_from_synthetic_class (
654- class_key : type | str , self_value : Value , ctx : AttrContext
656+ class_key : ClassKey , self_value : Value , ctx : AttrContext
655657) -> Value :
656658 assert isinstance (self_value , SyntheticClassObjectValue )
657659 can_assign_ctx = ctx .get_can_assign_context ()
@@ -914,22 +916,21 @@ def _get_runtime_class_attribute_from_synthetic_class(
914916
915917
916918def _substitute_typevars (
917- typ : type | str ,
919+ typ : ClassKey ,
918920 generic_args : Sequence [Value ],
919921 result : Value ,
920922 provider : object ,
921923 ctx : AttrContext ,
922924) -> Value :
923925 generic_bases = ctx .get_generic_bases (typ , generic_args )
924- provider_key : type | str | None
925- if isinstance (provider , (type , str )) and provider in generic_bases :
926- provider_key = provider
927- else :
926+ provider_key : ClassKey | None = _normalize_class_key (provider )
927+ if provider_key not in generic_bases :
928928 provider_key = None
929- if provider_key is None and not isinstance (provider , str ):
929+ if provider_key is None and not isinstance (provider , ClassOwner ):
930930 origin = get_origin (provider )
931- if isinstance (origin , (type , str )) and origin in generic_bases :
932- provider_key = origin
931+ provider_key = _normalize_class_key (origin )
932+ if provider_key not in generic_bases :
933+ provider_key = None
933934 if provider_key is not None :
934935 provider_typevars = generic_bases [provider_key ]
935936 substituted_typevars = _typevar_map_from_varlike_pairs (
@@ -954,6 +955,12 @@ def _substitute_typevars(
954955 return result
955956
956957
958+ def _normalize_class_key (value : object ) -> ClassKey | None :
959+ if isinstance (value , (type , ClassOwner )):
960+ return value
961+ return None
962+
963+
957964def _unwrap_value_from_typed (result : Value , typ : type , ctx : AttrContext ) -> Value :
958965 if not isinstance (result , KnownValue ):
959966 return result
0 commit comments