28
28
import pprint
29
29
import types
30
30
from functools import lru_cache
31
- from typing import TYPE_CHECKING
31
+ from typing import TYPE_CHECKING , Any
32
32
33
33
import astroid
34
- from astroid import util
34
+ from astroid import bases , nodes , util
35
35
from astroid .context import InferenceContext , copy_context
36
36
from astroid .exceptions import AttributeInferenceError , InferenceError , NoDefault
37
37
from astroid .manager import AstroidManager
38
38
from astroid .nodes import node_classes
39
39
40
40
objects = util .lazy_import ("objects" )
41
+ builder = util .lazy_import ("builder" )
41
42
42
43
if TYPE_CHECKING :
44
+ from astroid import builder
43
45
from astroid .objects import Property
44
46
45
47
IMPL_PREFIX = "attr_"
@@ -63,6 +65,14 @@ def _dunder_dict(instance, attributes):
63
65
return obj
64
66
65
67
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
+
66
76
class ObjectModel :
67
77
def __init__ (self ):
68
78
self ._instance = None
@@ -119,17 +129,31 @@ def lookup(self, name):
119
129
raise AttributeInferenceError (target = self ._instance , attribute = name )
120
130
121
131
@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" ]
124
140
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 ))
133
157
134
158
135
159
class ModuleModel (ObjectModel ):
@@ -300,9 +324,6 @@ def attr___module__(self):
300
324
301
325
@property
302
326
def attr___get__ (self ):
303
- # pylint: disable=import-outside-toplevel; circular import
304
- from astroid import bases
305
-
306
327
func = self ._instance
307
328
308
329
class DescriptorBoundMethod (bases .BoundMethod ):
@@ -409,7 +430,6 @@ def attr___ne__(self):
409
430
attr___delattr___ = attr___ne__
410
431
attr___getattribute__ = attr___ne__
411
432
attr___hash__ = attr___ne__
412
- attr___init__ = attr___ne__
413
433
attr___dir__ = attr___ne__
414
434
attr___call__ = attr___ne__
415
435
attr___class__ = attr___ne__
@@ -455,9 +475,6 @@ def attr_mro(self):
455
475
if not self ._instance .newstyle :
456
476
raise AttributeInferenceError (target = self ._instance , attribute = "mro" )
457
477
458
- # pylint: disable=import-outside-toplevel; circular import
459
- from astroid import bases
460
-
461
478
other_self = self
462
479
463
480
# 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):
492
509
This looks only in the current module for retrieving the subclasses,
493
510
thus it might miss a couple of them.
494
511
"""
495
- # pylint: disable=import-outside-toplevel; circular import
496
- from astroid import bases
497
- from astroid .nodes import scoped_nodes
498
-
499
512
if not self ._instance .newstyle :
500
513
raise AttributeInferenceError (
501
514
target = self ._instance , attribute = "__subclasses__"
@@ -505,7 +518,7 @@ def attr___subclasses__(self):
505
518
root = self ._instance .root ()
506
519
classes = [
507
520
cls
508
- for cls in root .nodes_of_class (scoped_nodes .ClassDef )
521
+ for cls in root .nodes_of_class (nodes .ClassDef )
509
522
if cls != self ._instance and cls .is_subtype_of (qname , context = self .context )
510
523
]
511
524
@@ -778,12 +791,8 @@ def attr_values(self):
778
791
class PropertyModel (ObjectModel ):
779
792
"""Model for a builtin property"""
780
793
781
- # pylint: disable=import-outside-toplevel
782
794
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 ()
787
796
args .postinit (
788
797
args = [],
789
798
defaults = [],
@@ -795,18 +804,16 @@ def _init_function(self, name):
795
804
kwonlyargs_annotations = [],
796
805
)
797
806
798
- function = FunctionDef (name = name , parent = self ._instance )
807
+ function = nodes . FunctionDef (name = name , parent = self ._instance )
799
808
800
809
function .postinit (args = args , body = [])
801
810
return function
802
811
803
812
@property
804
813
def attr_fget (self ):
805
- from astroid .nodes .scoped_nodes import FunctionDef
806
-
807
814
func = self ._instance
808
815
809
- class PropertyFuncAccessor (FunctionDef ):
816
+ class PropertyFuncAccessor (nodes . FunctionDef ):
810
817
def infer_call_result (self , caller = None , context = None ):
811
818
nonlocal func
812
819
if caller and len (caller .args ) != 1 :
@@ -824,8 +831,6 @@ def infer_call_result(self, caller=None, context=None):
824
831
825
832
@property
826
833
def attr_fset (self ):
827
- from astroid .nodes .scoped_nodes import FunctionDef
828
-
829
834
func = self ._instance
830
835
831
836
def find_setter (func : Property ) -> astroid .FunctionDef | None :
@@ -849,7 +854,7 @@ def find_setter(func: Property) -> astroid.FunctionDef | None:
849
854
f"Unable to find the setter of property { func .function .name } "
850
855
)
851
856
852
- class PropertyFuncAccessor (FunctionDef ):
857
+ class PropertyFuncAccessor (nodes . FunctionDef ):
853
858
def infer_call_result (self , caller = None , context = None ):
854
859
nonlocal func_setter
855
860
if caller and len (caller .args ) != 2 :
0 commit comments