31
31
from typing import TYPE_CHECKING
32
32
33
33
import astroid
34
- from astroid import nodes , 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_"
@@ -119,21 +121,41 @@ def lookup(self, name):
119
121
raise AttributeInferenceError (target = self ._instance , attribute = name )
120
122
121
123
@property
122
- def attr___new__ (self ):
123
- """Calling cls.__new__(cls) on an object returns an instance of that object.
124
+ def attr___new__ (self ) -> bases .BoundMethod :
125
+ """Calling cls.__new__(type) on an object returns an instance of 'type'."""
126
+ node : nodes .FunctionDef = builder .extract_node (
127
+ """def __new__(self, cls): return cls()"""
128
+ )
129
+ # We set the parent as being the ClassDef of 'object' as that
130
+ # triggers correct inference as a call to __new__ in bases.py
131
+ node .parent : nodes .ClassDef = AstroidManager ().builtins_module ["object" ]
124
132
125
- Instance is either an instance or a class definition of the instance to be
126
- created.
127
- """
128
133
# TODO: Use isinstance instead of try ... except after _instance has typing
129
134
try :
130
- return self ._instance ._proxied . instantiate_class ()
135
+ bound = self ._instance ._proxied
131
136
except AttributeError :
132
- return self ._instance .instantiate_class ()
137
+ bound = self ._instance
138
+ return bases .BoundMethod (proxy = node , bound = bound )
133
139
134
140
@property
135
- def attr___init__ (self ) -> nodes .Const :
136
- return nodes .Const (None )
141
+ def attr___init__ (self ) -> bases .BoundMethod :
142
+ """Calling cls.__init__() normally returns None."""
143
+ # The *args and **kwargs are necessary not too trigger warnings about missing
144
+ # or extra parameters for '__init__' methods we don't infer correctly.
145
+ # This BoundMethod is the fallback value for those.
146
+ node : nodes .FunctionDef = builder .extract_node (
147
+ """def __init__(self, *args, **kwargs): return None"""
148
+ )
149
+ # We set the parent as being the ClassDef of 'object' as that
150
+ # is where this method originally comes from
151
+ node .parent : nodes .ClassDef = AstroidManager ().builtins_module ["object" ]
152
+
153
+ # TODO: Use isinstance instead of try ... except after _instance has typing
154
+ try :
155
+ bound = self ._instance ._proxied
156
+ except AttributeError :
157
+ bound = self ._instance
158
+ return bases .BoundMethod (proxy = node , bound = bound )
137
159
138
160
139
161
class ModuleModel (ObjectModel ):
@@ -304,9 +326,6 @@ def attr___module__(self):
304
326
305
327
@property
306
328
def attr___get__ (self ):
307
- # pylint: disable=import-outside-toplevel; circular import
308
- from astroid import bases
309
-
310
329
func = self ._instance
311
330
312
331
class DescriptorBoundMethod (bases .BoundMethod ):
@@ -458,9 +477,6 @@ def attr_mro(self):
458
477
if not self ._instance .newstyle :
459
478
raise AttributeInferenceError (target = self ._instance , attribute = "mro" )
460
479
461
- # pylint: disable=import-outside-toplevel; circular import
462
- from astroid import bases
463
-
464
480
other_self = self
465
481
466
482
# Cls.mro is a method and we need to return one in order to have a proper inference.
@@ -483,7 +499,7 @@ def attr___bases__(self):
483
499
484
500
@property
485
501
def attr___class__ (self ):
486
- # pylint: disable=import-outside-toplevel; circular import
502
+ # pylint: disable=import-outside-toplevel; circular importdd
487
503
from astroid import helpers
488
504
489
505
return helpers .object_type (self ._instance )
@@ -495,10 +511,6 @@ def attr___subclasses__(self):
495
511
This looks only in the current module for retrieving the subclasses,
496
512
thus it might miss a couple of them.
497
513
"""
498
- # pylint: disable=import-outside-toplevel; circular import
499
- from astroid import bases
500
- from astroid .nodes import scoped_nodes
501
-
502
514
if not self ._instance .newstyle :
503
515
raise AttributeInferenceError (
504
516
target = self ._instance , attribute = "__subclasses__"
@@ -508,7 +520,7 @@ def attr___subclasses__(self):
508
520
root = self ._instance .root ()
509
521
classes = [
510
522
cls
511
- for cls in root .nodes_of_class (scoped_nodes .ClassDef )
523
+ for cls in root .nodes_of_class (nodes .ClassDef )
512
524
if cls != self ._instance and cls .is_subtype_of (qname , context = self .context )
513
525
]
514
526
@@ -781,12 +793,8 @@ def attr_values(self):
781
793
class PropertyModel (ObjectModel ):
782
794
"""Model for a builtin property"""
783
795
784
- # pylint: disable=import-outside-toplevel
785
796
def _init_function (self , name ):
786
- from astroid .nodes .node_classes import Arguments
787
- from astroid .nodes .scoped_nodes import FunctionDef
788
-
789
- args = Arguments ()
797
+ args = nodes .Arguments ()
790
798
args .postinit (
791
799
args = [],
792
800
defaults = [],
@@ -798,18 +806,16 @@ def _init_function(self, name):
798
806
kwonlyargs_annotations = [],
799
807
)
800
808
801
- function = FunctionDef (name = name , parent = self ._instance )
809
+ function = nodes . FunctionDef (name = name , parent = self ._instance )
802
810
803
811
function .postinit (args = args , body = [])
804
812
return function
805
813
806
814
@property
807
815
def attr_fget (self ):
808
- from astroid .nodes .scoped_nodes import FunctionDef
809
-
810
816
func = self ._instance
811
817
812
- class PropertyFuncAccessor (FunctionDef ):
818
+ class PropertyFuncAccessor (nodes . FunctionDef ):
813
819
def infer_call_result (self , caller = None , context = None ):
814
820
nonlocal func
815
821
if caller and len (caller .args ) != 1 :
@@ -827,8 +833,6 @@ def infer_call_result(self, caller=None, context=None):
827
833
828
834
@property
829
835
def attr_fset (self ):
830
- from astroid .nodes .scoped_nodes import FunctionDef
831
-
832
836
func = self ._instance
833
837
834
838
def find_setter (func : Property ) -> astroid .FunctionDef | None :
@@ -852,7 +856,7 @@ def find_setter(func: Property) -> astroid.FunctionDef | None:
852
856
f"Unable to find the setter of property { func .function .name } "
853
857
)
854
858
855
- class PropertyFuncAccessor (FunctionDef ):
859
+ class PropertyFuncAccessor (nodes . FunctionDef ):
856
860
def infer_call_result (self , caller = None , context = None ):
857
861
nonlocal func_setter
858
862
if caller and len (caller .args ) != 2 :
0 commit comments