2828import pprint
2929import types
3030from functools import lru_cache
31- from typing import TYPE_CHECKING
31+ from typing import TYPE_CHECKING , Any
3232
3333import astroid
34- from astroid import util
34+ from astroid import bases , nodes , util
3535from astroid .context import InferenceContext , copy_context
3636from astroid .exceptions import AttributeInferenceError , InferenceError , NoDefault
3737from astroid .manager import AstroidManager
3838from astroid .nodes import node_classes
3939
4040objects = util .lazy_import ("objects" )
41+ builder = util .lazy_import ("builder" )
4142
4243if TYPE_CHECKING :
44+ from astroid import builder
4345 from astroid .objects import Property
4446
4547IMPL_PREFIX = "attr_"
@@ -63,6 +65,14 @@ def _dunder_dict(instance, attributes):
6365 return obj
6466
6567
68+ def _get_bound_node (model : ObjectModel ) -> Any :
69+ # TODO: Use isinstance instead of try ... except after _instance has typing
70+ try :
71+ return model ._instance ._proxied
72+ except AttributeError :
73+ return model ._instance
74+
75+
6676class ObjectModel :
6777 def __init__ (self ):
6878 self ._instance = None
@@ -119,17 +129,31 @@ def lookup(self, name):
119129 raise AttributeInferenceError (target = self ._instance , attribute = name )
120130
121131 @property
122- def attr___new__ (self ):
123- """Calling cls.__new__(cls) on an object returns an instance of that object.
132+ def attr___new__ (self ) -> bases .BoundMethod :
133+ """Calling cls.__new__(type) on an object returns an instance of 'type'."""
134+ node : nodes .FunctionDef = builder .extract_node (
135+ """def __new__(self, cls): return cls()"""
136+ )
137+ # We set the parent as being the ClassDef of 'object' as that
138+ # triggers correct inference as a call to __new__ in bases.py
139+ node .parent : nodes .ClassDef = AstroidManager ().builtins_module ["object" ]
124140
125- Instance is either an instance or a class definition of the instance to be
126- created.
127- """
128- # TODO: Use isinstance instead of try ... except after _instance has typing
129- try :
130- return self ._instance ._proxied .instantiate_class ()
131- except AttributeError :
132- return self ._instance .instantiate_class ()
141+ return bases .BoundMethod (proxy = node , bound = _get_bound_node (self ))
142+
143+ @property
144+ def attr___init__ (self ) -> bases .BoundMethod :
145+ """Calling cls.__init__() normally returns None."""
146+ # The *args and **kwargs are necessary not to trigger warnings about missing
147+ # or extra parameters for '__init__' methods we don't infer correctly.
148+ # This BoundMethod is the fallback value for those.
149+ node : nodes .FunctionDef = builder .extract_node (
150+ """def __init__(self, *args, **kwargs): return None"""
151+ )
152+ # We set the parent as being the ClassDef of 'object' as that
153+ # is where this method originally comes from
154+ node .parent : nodes .ClassDef = AstroidManager ().builtins_module ["object" ]
155+
156+ return bases .BoundMethod (proxy = node , bound = _get_bound_node (self ))
133157
134158
135159class ModuleModel (ObjectModel ):
@@ -300,9 +324,6 @@ def attr___module__(self):
300324
301325 @property
302326 def attr___get__ (self ):
303- # pylint: disable=import-outside-toplevel; circular import
304- from astroid import bases
305-
306327 func = self ._instance
307328
308329 class DescriptorBoundMethod (bases .BoundMethod ):
@@ -409,7 +430,6 @@ def attr___ne__(self):
409430 attr___delattr___ = attr___ne__
410431 attr___getattribute__ = attr___ne__
411432 attr___hash__ = attr___ne__
412- attr___init__ = attr___ne__
413433 attr___dir__ = attr___ne__
414434 attr___call__ = attr___ne__
415435 attr___class__ = attr___ne__
@@ -455,9 +475,6 @@ def attr_mro(self):
455475 if not self ._instance .newstyle :
456476 raise AttributeInferenceError (target = self ._instance , attribute = "mro" )
457477
458- # pylint: disable=import-outside-toplevel; circular import
459- from astroid import bases
460-
461478 other_self = self
462479
463480 # Cls.mro is a method and we need to return one in order to have a proper inference.
@@ -492,10 +509,6 @@ def attr___subclasses__(self):
492509 This looks only in the current module for retrieving the subclasses,
493510 thus it might miss a couple of them.
494511 """
495- # pylint: disable=import-outside-toplevel; circular import
496- from astroid import bases
497- from astroid .nodes import scoped_nodes
498-
499512 if not self ._instance .newstyle :
500513 raise AttributeInferenceError (
501514 target = self ._instance , attribute = "__subclasses__"
@@ -505,7 +518,7 @@ def attr___subclasses__(self):
505518 root = self ._instance .root ()
506519 classes = [
507520 cls
508- for cls in root .nodes_of_class (scoped_nodes .ClassDef )
521+ for cls in root .nodes_of_class (nodes .ClassDef )
509522 if cls != self ._instance and cls .is_subtype_of (qname , context = self .context )
510523 ]
511524
@@ -778,12 +791,8 @@ def attr_values(self):
778791class PropertyModel (ObjectModel ):
779792 """Model for a builtin property"""
780793
781- # pylint: disable=import-outside-toplevel
782794 def _init_function (self , name ):
783- from astroid .nodes .node_classes import Arguments
784- from astroid .nodes .scoped_nodes import FunctionDef
785-
786- args = Arguments ()
795+ args = nodes .Arguments ()
787796 args .postinit (
788797 args = [],
789798 defaults = [],
@@ -795,18 +804,16 @@ def _init_function(self, name):
795804 kwonlyargs_annotations = [],
796805 )
797806
798- function = FunctionDef (name = name , parent = self ._instance )
807+ function = nodes . FunctionDef (name = name , parent = self ._instance )
799808
800809 function .postinit (args = args , body = [])
801810 return function
802811
803812 @property
804813 def attr_fget (self ):
805- from astroid .nodes .scoped_nodes import FunctionDef
806-
807814 func = self ._instance
808815
809- class PropertyFuncAccessor (FunctionDef ):
816+ class PropertyFuncAccessor (nodes . FunctionDef ):
810817 def infer_call_result (self , caller = None , context = None ):
811818 nonlocal func
812819 if caller and len (caller .args ) != 1 :
@@ -824,8 +831,6 @@ def infer_call_result(self, caller=None, context=None):
824831
825832 @property
826833 def attr_fset (self ):
827- from astroid .nodes .scoped_nodes import FunctionDef
828-
829834 func = self ._instance
830835
831836 def find_setter (func : Property ) -> astroid .FunctionDef | None :
@@ -849,7 +854,7 @@ def find_setter(func: Property) -> astroid.FunctionDef | None:
849854 f"Unable to find the setter of property { func .function .name } "
850855 )
851856
852- class PropertyFuncAccessor (FunctionDef ):
857+ class PropertyFuncAccessor (nodes . FunctionDef ):
853858 def infer_call_result (self , caller = None , context = None ):
854859 nonlocal func_setter
855860 if caller and len (caller .args ) != 2 :
0 commit comments