103103 replace_fallback ,
104104 set_self ,
105105 shield_nested_self_typevars ,
106- stringify_object ,
107106 unite_values ,
108107)
109108
@@ -162,11 +161,6 @@ def resolve_name_from_typeshed(self, module: str, name: str) -> Value:
162161 def get_attribute_from_typeshed (self , typ : type , * , on_class : bool ) -> Value :
163162 raise NotImplementedError
164163
165- def get_attribute_from_typeshed_recursively (
166- self , fq_name : str , * , on_class : bool
167- ) -> tuple [Value , type | str ]:
168- raise NotImplementedError
169-
170164 def should_ignore_none_attributes (self ) -> bool :
171165 raise NotImplementedError
172166
@@ -320,7 +314,7 @@ def get_attribute(ctx: AttrContext) -> Value:
320314 synthetic_name = root_value .typ .typ
321315 else :
322316 attribute_value = _get_attribute_from_subclass (
323- root_value .typ .typ , root_value . typ , ctx
317+ root_value .typ .typ , root_value , ctx
324318 )
325319 elif isinstance (root_value .typ , TypeVarValue ):
326320 if root_value .typ .typevar_param .bound is not None :
@@ -362,16 +356,9 @@ def get_attribute(ctx: AttrContext) -> Value:
362356 elif isinstance (root_value , SyntheticClassObjectValue ):
363357 if isinstance (root_value .class_type , TypedDictValue ):
364358 attribute_value = _get_attribute_from_subclass (dict , root_value , ctx )
365- elif isinstance (root_value .class_type .typ , str ):
366- attribute_value = _get_attribute_from_synthetic_class (
367- root_value .class_type .typ , root_value , ctx
368- )
369359 else :
370360 attribute_value = _get_attribute_from_synthetic_class (
371- stringify_object (root_value .class_type .typ ),
372- root_value ,
373- ctx ,
374- runtime_type = root_value .class_type .typ ,
361+ root_value .class_type .typ , root_value , ctx
375362 )
376363 else :
377364 assert_never (root_value )
@@ -596,29 +583,8 @@ def _get_attribute_from_subclass(
596583) -> Value :
597584 ctx .record_attr_read (typ )
598585
599- if isinstance (self_value , SubclassValue ) and isinstance (
600- self_value .typ , TypeVarValue
601- ):
602- can_assign_ctx = ctx .get_can_assign_context ()
603- type_object = can_assign_ctx .make_type_object (typ )
604- symbol = type_object .get_declared_symbol_from_mro (ctx .attr , can_assign_ctx )
605- if symbol is not None :
606- uses_self = (
607- symbol .annotation is not None
608- and _contains_self_typevar (symbol .annotation )
609- ) or (
610- symbol .initializer is not None
611- and _contains_self_typevar (symbol .initializer )
612- )
613- if uses_self or symbol .is_classmethod :
614- attribute = _get_type_object_attribute (
615- type_object , ctx .attr , ctx , on_class = True , receiver_value = self_value
616- )
617- if attribute is not None :
618- ctx .record_usage (typ , attribute .value )
619- return attribute .value
620-
621586 # First check values that are special in Python
587+ # TODO: remove these eventually, they should be handled by TypeObject.get_attribute
622588 if ctx .attr == "__class__" :
623589 return KnownValue (type (typ ))
624590 elif ctx .attr == "__dict__" :
@@ -641,23 +607,8 @@ def _get_attribute_from_subclass(
641607 )
642608 if attribute is None :
643609 return UNINITIALIZED_VALUE
644- # TODO: If we unconditionally use attribute.value here, some tests fail:
645- # pycroscope/test_name_check_visitor.py::TestImportFailureHandlingCodeSamples
646- # pycroscope/test_operations.py::TestBinOps::test_enum_flag_binop
647- if _should_use_resolved_class_attribute (attribute ):
648- ctx .record_usage (typ , attribute .value )
649- return attribute .value
650- result , provider , should_unwrap = _get_attribute_from_mro (typ , ctx , on_class = True )
651- if result is UNINITIALIZED_VALUE :
652- return result
653- if should_unwrap :
654- result = _unwrap_value_from_subclass (result , ctx )
655- if isinstance (self_value , GenericValue ):
656- result = _substitute_typevars (typ , self_value .args , result , provider , ctx )
657- assert safe_isinstance (provider , type )
658- result = set_self (result , self_value , provider )
659- ctx .record_usage (typ , result )
660- return result
610+ ctx .record_usage (typ , attribute .value )
611+ return attribute .value
661612
662613
663614_TCAA = Callable [[object ], bool ]
@@ -763,8 +714,6 @@ def _get_attribute_from_synthetic_typed_value(
763714 root_value : TypedValue , ctx : AttrContext
764715) -> Value :
765716 """Resolve a synthetic instance attribute via ``TypeObject.get_attribute()``."""
766- if not isinstance (root_value .typ , str ):
767- return UNINITIALIZED_VALUE
768717 can_assign_ctx = ctx .get_can_assign_context ()
769718 type_object = can_assign_ctx .make_type_object (root_value .typ )
770719 attribute = _get_type_object_attribute (
@@ -795,8 +744,9 @@ def _get_instance_lookup_receiver(ctx: AttrContext) -> Value | None:
795744
796745
797746def _get_attribute_from_synthetic_class (
798- fq_name : str , self_value : Value , ctx : AttrContext , runtime_type : type | None = None
747+ class_key : type | str , self_value : Value , ctx : AttrContext
799748) -> Value :
749+ # TODO: shouldn't be needed, should be handled by TypeObject.get_attribute
800750 # First check values that are special in Python.
801751 if ctx .attr == "__class__" :
802752 return KnownValue (type )
@@ -805,63 +755,15 @@ def _get_attribute_from_synthetic_class(
805755 assert isinstance (self_value , SyntheticClassObjectValue )
806756 can_assign_ctx = ctx .get_can_assign_context ()
807757 attribute = _get_type_object_attribute (
808- can_assign_ctx .make_type_object (fq_name ),
758+ can_assign_ctx .make_type_object (class_key ),
809759 ctx .attr ,
810760 ctx ,
811761 on_class = True ,
812762 receiver_value = self_value ,
813763 )
814764 if attribute is None :
815765 return UNINITIALIZED_VALUE
816- # If we always use attribute.value these tests fail:
817- # pycroscope/test_enum.py::TestEnum::test_enum_value_literals_on_class_and_instance
818- # pycroscope/test_typeshed.py::TestConstructors::test_init_new
819- # TODO: figure it out
820- if _should_use_resolved_class_attribute (attribute ):
821- return attribute .value
822- result = _get_attribute_from_synthetic_class_inner (
823- fq_name , self_value , ctx , seen = {id (self_value )}
824- )
825- if result is UNINITIALIZED_VALUE :
826- tobj = ctx .get_can_assign_context ().make_type_object (fq_name )
827- if tobj .has_any_base ():
828- return AnyValue (AnySource .from_another )
829- return result
830- return set_self (result , self_value .class_type )
831-
832-
833- def _get_attribute_from_synthetic_class_inner (
834- fq_name : str ,
835- self_value : SyntheticClassObjectValue ,
836- ctx : AttrContext ,
837- * ,
838- seen : set [int ],
839- ) -> Value :
840- direct = _get_direct_attribute_from_synthetic_class (self_value , ctx .attr , ctx )
841- if direct is not UNINITIALIZED_VALUE :
842- direct = dataclass_helpers .maybe_resolve_synthetic_descriptor_attribute (
843- self_value ,
844- ctx .attr ,
845- direct ,
846- ctx ,
847- on_class = True ,
848- descriptor_get_type = _synthetic_descriptor_get_type ,
849- )
850- return direct
851- if _is_instance_only_enum_attr (self_value .class_type , ctx .attr ):
852- return UNINITIALIZED_VALUE
853-
854- tobj = ctx .get_can_assign_context ().make_type_object (self_value .class_type .typ )
855- if not tobj .has_stubs ():
856- for base in tobj .get_direct_bases ():
857- result = _get_attribute_from_synthetic_base (
858- base , self_value , ctx , seen = seen
859- )
860- if result is not UNINITIALIZED_VALUE :
861- return result
862-
863- result , _ = ctx .get_attribute_from_typeshed_recursively (fq_name , on_class = True )
864- return result
766+ return attribute .value
865767
866768
867769def _get_direct_attribute_from_synthetic_class (
@@ -936,17 +838,6 @@ def _should_use_resolved_instance_attribute(attribute: TypeObjectAttribute) -> b
936838 return attribute .value != attribute .declared_value
937839
938840
939- def _should_use_resolved_class_attribute (attribute : TypeObjectAttribute ) -> bool :
940- symbol = attribute .symbol
941- return (
942- attribute .is_metaclass_owner
943- or attribute .is_property
944- or symbol .is_classmethod
945- or symbol .annotation is not None
946- or (not symbol .is_method and not attribute .owner .is_enum ())
947- )
948-
949-
950841def _maybe_use_resolved_typed_instance_attribute (
951842 attribute : TypeObjectAttribute ,
952843 * ,
@@ -974,6 +865,10 @@ def _maybe_use_resolved_typed_instance_attribute(
974865 and not symbol .is_initvar
975866 and not symbol .is_method
976867 ):
868+ # Need this because of:
869+ # pycroscope/test_namedtuple.py::TestNamedTuple
870+ # ::test_specialized_namedtuple_base_after_import_failure
871+ # TODO: something wrong here with generic namedtuples?
977872 if _contains_typevar (attribute .value ):
978873 return None
979874 if (
@@ -1048,6 +943,7 @@ def _synthetic_descriptor_method_match(
1048943 return selected , 0
1049944 # Synthetic dunder methods are often exposed unbound; retry with the
1050945 # descriptor value as an explicit first argument.
946+ # TODO: this is a hack, fix it at the source instead.
1051947 selected = _select_matching_synthetic_signature (signature , [descriptor , * args ], ctx )
1052948 if selected is None :
1053949 return None
@@ -1183,15 +1079,6 @@ def _normalize_synthetic_class_attribute(
11831079 )
11841080
11851081
1186- def _is_instance_only_enum_attr (value : Value , attr_name : str ) -> bool :
1187- class_type = replace_fallback (value )
1188- if not isinstance (class_type , TypedValue ) or not isinstance (class_type .typ , type ):
1189- return False
1190- if not safe_issubclass (class_type .typ , Enum ):
1191- return False
1192- return isinstance (Enum .__dict__ .get (attr_name ), _ENUM_INSTANCE_DESCRIPTOR_TYPES )
1193-
1194-
11951082def _should_deliteralize_synthetic_enum_attr (
11961083 self_value : SyntheticClassObjectValue , attr_name : str , ctx : AttrContext
11971084) -> bool :
@@ -1245,107 +1132,6 @@ def _deliteralize_simple_value(value: SimpleType) -> Value:
12451132 assert_never (value )
12461133
12471134
1248- def _get_attribute_from_synthetic_base (
1249- base : Value ,
1250- self_value : SyntheticClassObjectValue ,
1251- ctx : AttrContext ,
1252- * ,
1253- seen : set [int ],
1254- ) -> Value :
1255- if (
1256- isinstance (base , PartialValue )
1257- and base .operation is PartialValueOperation .SUBSCRIPT
1258- ):
1259- runtime_value = replace_fallback (base .runtime_value )
1260- if isinstance (runtime_value , GenericValue ):
1261- base = runtime_value
1262- else :
1263- root = replace_fallback (base .root )
1264- members = tuple (base .members )
1265- if isinstance (root , SyntheticClassObjectValue ):
1266- class_type = root .class_type
1267- base = GenericValue (class_type .typ , members )
1268- elif isinstance (root , KnownValue ) and isinstance (root .val , type ):
1269- base = GenericValue (root .val , members )
1270- elif isinstance (root , TypedValue ):
1271- base = GenericValue (root .typ , members )
1272-
1273- base = replace_fallback (base )
1274-
1275- if isinstance (base , GenericValue ):
1276- if isinstance (base .typ , str ):
1277- synthetic_base = ctx .get_synthetic_class (base .typ )
1278- if synthetic_base is not None :
1279- base_id = id (synthetic_base )
1280- if base_id not in seen :
1281- seen_with_base = {* seen , base_id }
1282- result = _get_attribute_from_synthetic_class_inner (
1283- base .typ , synthetic_base , ctx , seen = seen_with_base
1284- )
1285- if result is not UNINITIALIZED_VALUE :
1286- return _substitute_typevars (
1287- base .typ , base .args , result , base .typ , ctx
1288- )
1289- result , provider = ctx .get_attribute_from_typeshed_recursively (
1290- base .typ , on_class = True
1291- )
1292- if result is not UNINITIALIZED_VALUE :
1293- return _substitute_typevars (base .typ , base .args , result , provider , ctx )
1294- return UNINITIALIZED_VALUE
1295- elif isinstance (base .typ , type ):
1296- result = _get_attribute_from_subclass (base .typ , self_value .class_type , ctx )
1297- if result is not UNINITIALIZED_VALUE :
1298- return _substitute_typevars (base .typ , base .args , result , base .typ , ctx )
1299- return result
1300- else :
1301- assert_never (base .typ )
1302-
1303- if isinstance (base , SyntheticClassObjectValue ):
1304- base_id = id (base )
1305- if base_id in seen :
1306- return UNINITIALIZED_VALUE
1307- seen_with_base = {* seen , base_id }
1308- if isinstance (base .class_type , TypedDictValue ):
1309- return _get_attribute_from_subclass (dict , self_value .class_type , ctx )
1310- if isinstance (base .class_type .typ , str ):
1311- return _get_attribute_from_synthetic_class_inner (
1312- base .class_type .typ , base , ctx , seen = seen_with_base
1313- )
1314- return _get_attribute_from_subclass (
1315- base .class_type .typ , self_value .class_type , ctx
1316- )
1317-
1318- if isinstance (base , KnownValue ):
1319- if isinstance (base .val , type ):
1320- return _get_attribute_from_subclass (base .val , self_value .class_type , ctx )
1321- origin = get_origin (base .val )
1322- if isinstance (origin , type ):
1323- return _get_attribute_from_subclass (origin , self_value .class_type , ctx )
1324-
1325- if isinstance (base , TypedValue ):
1326- if isinstance (base .typ , str ):
1327- synthetic_base = ctx .get_synthetic_class (base .typ )
1328- if synthetic_base is not None :
1329- base_id = id (synthetic_base )
1330- if base_id not in seen :
1331- seen_with_base = {* seen , base_id }
1332- result = _get_attribute_from_synthetic_class_inner (
1333- base .typ , synthetic_base , ctx , seen = seen_with_base
1334- )
1335- if result is not UNINITIALIZED_VALUE :
1336- return result
1337- result , _ = ctx .get_attribute_from_typeshed_recursively (
1338- base .typ , on_class = True
1339- )
1340- return result
1341- return _get_attribute_from_subclass (base .typ , self_value .class_type , ctx )
1342-
1343- if isinstance (base , AnyValue ):
1344- return AnyValue (AnySource .from_another )
1345-
1346- return UNINITIALIZED_VALUE
1347-
1348-
13491135def _contains_self_typevar (value : Value ) -> bool :
13501136 if isinstance (value , KnownValueWithTypeVars ) and any (
13511137 type_param .is_self for type_param , _ in value .typevars .iter_typevars ()
0 commit comments