@@ -61,13 +61,17 @@ def _add_dunder_class(func, parent: nodes.NodeNG, member) -> None:
6161 func .instance_attrs ["__class__" ] = [ast_klass ]
6262
6363
64+ def build_dummy (runtime_object ) -> nodes .EmptyNode :
65+ enode = nodes .EmptyNode ()
66+ enode .object = runtime_object
67+ return enode
68+
69+
6470def attach_dummy_node (node , name : str , runtime_object = _EMPTY_OBJECT_MARKER ) -> None :
6571 """create a dummy node and register it in the locals of the given
6672 node with the specified name
6773 """
68- enode = nodes .EmptyNode ()
69- enode .object = runtime_object
70- _attach_local_node (node , enode , name )
74+ _attach_local_node (node , build_dummy (runtime_object ), name )
7175
7276
7377def attach_const_node (node , name : str , value ) -> None :
@@ -262,11 +266,11 @@ def register_arguments(func: nodes.FunctionDef, args: list | None = None) -> Non
262266
263267
264268def object_build_class (
265- node : nodes .Module | nodes .ClassDef , member : type , localname : str
269+ node : nodes .Module | nodes .ClassDef , member : type
266270) -> nodes .ClassDef :
267271 """create astroid for a living class object"""
268272 basenames = [base .__name__ for base in member .__bases__ ]
269- return _base_class_object_build (node , member , basenames , localname = localname )
273+ return _base_class_object_build (node , member , basenames )
270274
271275
272276def _get_args_info_from_callable (
@@ -304,8 +308,8 @@ def _get_args_info_from_callable(
304308
305309
306310def object_build_function (
307- node : nodes .Module | nodes .ClassDef , member : _FunctionTypes , localname : str
308- ) -> None :
311+ node : nodes .Module | nodes .ClassDef , member : _FunctionTypes
312+ ) -> nodes . FunctionDef :
309313 """create astroid for a living function object"""
310314 (
311315 args ,
@@ -315,8 +319,8 @@ def object_build_function(
315319 kwonly_defaults ,
316320 ) = _get_args_info_from_callable (member )
317321
318- func = build_function (
319- getattr (member , "__name__" , None ) or localname ,
322+ return build_function (
323+ getattr (member , "__name__" , "<no-name>" ) ,
320324 args ,
321325 posonlyargs ,
322326 defaults ,
@@ -325,44 +329,37 @@ def object_build_function(
325329 kwonlydefaults = kwonly_defaults ,
326330 )
327331
328- node .add_local_node (func , localname )
329-
330332
331333def object_build_datadescriptor (
332- node : nodes .Module | nodes .ClassDef , member : type , name : str
334+ node : nodes .Module | nodes .ClassDef , member : type
333335) -> nodes .ClassDef :
334336 """create astroid for a living data descriptor object"""
335- return _base_class_object_build (node , member , [], name )
337+ return _base_class_object_build (node , member , [])
336338
337339
338340def object_build_methoddescriptor (
339341 node : nodes .Module | nodes .ClassDef ,
340342 member : _FunctionTypes ,
341- localname : str ,
342- ) -> None :
343+ ) -> nodes .FunctionDef :
343344 """create astroid for a living method descriptor object"""
344345 # FIXME get arguments ?
345- func = build_function (
346- getattr (member , "__name__" , None ) or localname , doc = member .__doc__
347- )
348- node .add_local_node (func , localname )
346+ name = getattr (member , "__name__" , "<no-name>" )
347+ func = build_function (name , doc = member .__doc__ )
349348 _add_dunder_class (func , node , member )
349+ return func
350350
351351
352352def _base_class_object_build (
353353 node : nodes .Module | nodes .ClassDef ,
354354 member : type ,
355355 basenames : list [str ],
356- name : str | None = None ,
357- localname : str | None = None ,
358356) -> nodes .ClassDef :
359357 """create astroid for a living class object, with a given set of base names
360358 (e.g. ancestors)
361359 """
362- class_name = name or getattr (member , "__name__" , None ) or localname
363- assert isinstance (class_name , str )
360+ name = getattr (member , "__name__" , "<no-name>" )
364361 doc = member .__doc__ if isinstance (member .__doc__ , str ) else None
365- klass = build_class (class_name , node , basenames , doc )
362+ klass = build_class (name , node , basenames , doc )
366363 klass ._newstyle = isinstance (member , type )
367364 try :
368365 # limit the instantiation trick since it's too dangerous
@@ -387,10 +384,9 @@ def _base_class_object_build(
387384
388385def _build_from_function (
389386 node : nodes .Module | nodes .ClassDef ,
390- name : str ,
391387 member : _FunctionTypes ,
392388 module : types .ModuleType ,
393- ) -> None :
389+ ) -> nodes . FunctionDef | nodes . EmptyNode :
394390 # verify this is not an imported function
395391 try :
396392 code = member .__code__ # type: ignore[union-attr]
@@ -400,12 +396,10 @@ def _build_from_function(
400396 code = None
401397 filename = getattr (code , "co_filename" , None )
402398 if filename is None :
403- assert isinstance (member , object )
404- object_build_methoddescriptor (node , member , name )
405- elif filename != getattr (module , "__file__" , None ):
406- attach_dummy_node (node , name , member )
407- else :
408- object_build_function (node , member , name )
399+ return object_build_methoddescriptor (node , member )
400+ if filename == getattr (module , "__file__" , None ):
401+ return object_build_function (node , member )
402+ return build_dummy (member )
409403
410404
411405def _safe_has_attribute (obj , member : str ) -> bool :
@@ -472,58 +466,57 @@ def object_build(
472466 if obj in self ._done :
473467 return None
474468 self ._done [obj ] = node
475- for name in dir (obj ):
469+ for alias in dir (obj ):
476470 # inspect.ismethod() and inspect.isbuiltin() in PyPy return
477471 # the opposite of what they do in CPython for __class_getitem__.
478- pypy__class_getitem__ = IS_PYPY and name == "__class_getitem__"
472+ pypy__class_getitem__ = IS_PYPY and alias == "__class_getitem__"
479473 try :
480474 with warnings .catch_warnings ():
481475 warnings .simplefilter ("ignore" )
482- member = getattr (obj , name )
476+ member = getattr (obj , alias )
483477 except AttributeError :
484478 # damned ExtensionClass.Base, I know you're there !
485- attach_dummy_node (node , name )
479+ attach_dummy_node (node , alias )
486480 continue
487481 if inspect .ismethod (member ) and not pypy__class_getitem__ :
488482 member = member .__func__
489483 if inspect .isfunction (member ):
490- _build_from_function (node , name , member , self ._module )
484+ child = _build_from_function (node , member , self ._module )
491485 elif inspect .isbuiltin (member ) or pypy__class_getitem__ :
492- if self .imported_member (node , member , name ):
486+ if self .imported_member (node , member , alias ):
493487 continue
494- object_build_methoddescriptor (node , member , name )
488+ child = object_build_methoddescriptor (node , member )
495489 elif inspect .isclass (member ):
496- if self .imported_member (node , member , name ):
490+ if self .imported_member (node , member , alias ):
497491 continue
498492 if member in self ._done :
499- class_node = self ._done [member ]
500- assert isinstance (class_node , nodes .ClassDef )
501- if class_node not in node .locals .get (name , ()):
502- node .add_local_node (class_node , name )
493+ child = self ._done [member ]
494+ assert isinstance (child , nodes .ClassDef )
503495 else :
504- class_node = object_build_class (node , member , name )
496+ child = object_build_class (node , member )
505497 # recursion
506- self .object_build (class_node , member )
507- if name == "__class__" and class_node .parent is None :
508- class_node .parent = self ._done [self ._module ]
498+ self .object_build (child , member )
509499 elif inspect .ismethoddescriptor (member ):
510- object_build_methoddescriptor (node , member , name )
500+ child : nodes . NodeNG = object_build_methoddescriptor (node , member )
511501 elif inspect .isdatadescriptor (member ):
512- object_build_datadescriptor (node , member , name )
502+ child = object_build_datadescriptor (node , member )
513503 elif isinstance (member , _CONSTANTS ):
514- attach_const_node (node , name , member )
504+ if alias in node .special_attributes :
505+ continue
506+ child = nodes .const_factory (member )
515507 elif inspect .isroutine (member ):
516508 # This should be called for Jython, where some builtin
517509 # methods aren't caught by isbuiltin branch.
518- _build_from_function (node , name , member , self ._module )
510+ child = _build_from_function (node , member , self ._module )
519511 elif _safe_has_attribute (member , "__all__" ):
520- module = build_module (name )
521- _attach_local_node (node , module , name )
512+ child : nodes .NodeNG = build_module (alias )
522513 # recursion
523- self .object_build (module , member )
514+ self .object_build (child , member )
524515 else :
525516 # create an empty node so that the name is actually defined
526- attach_dummy_node (node , name , member )
517+ child : nodes .NodeNG = build_dummy (member )
518+ if child not in node .locals .get (alias , ()):
519+ node .add_local_node (child , alias )
527520 return None
528521
529522 def imported_member (self , node , member , name : str ) -> bool :
@@ -629,6 +622,7 @@ def _astroid_bootstrapping() -> None:
629622 end_col_offset = 0 ,
630623 parent = astroid_builtin ,
631624 )
625+ astroid_builtin .set_local (_GeneratorType .name , _GeneratorType )
632626 generator_doc_node = (
633627 nodes .Const (value = types .GeneratorType .__doc__ )
634628 if types .GeneratorType .__doc__
@@ -652,6 +646,7 @@ def _astroid_bootstrapping() -> None:
652646 end_col_offset = 0 ,
653647 parent = astroid_builtin ,
654648 )
649+ astroid_builtin .set_local (_AsyncGeneratorType .name , _AsyncGeneratorType )
655650 async_generator_doc_node = (
656651 nodes .Const (value = types .AsyncGeneratorType .__doc__ )
657652 if types .AsyncGeneratorType .__doc__
0 commit comments