Skip to content

Commit e33b04a

Browse files
committed
WIP removed Unknown as a parent node
1 parent 261ca0b commit e33b04a

20 files changed

+149
-144
lines changed

astroid/bases.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
"""This module contains base classes and functions for the nodes and some
66
inference utils.
77
"""
8+
# isort: off
9+
810
from __future__ import annotations
911

1012
import collections
@@ -273,27 +275,26 @@ def igetattr(
273275
try:
274276
context.lookupname = name
275277
# XXX frame should be self._proxied, or not ?
276-
get_attr = self.getattr(name, context, lookupclass=False)
277-
yield from _infer_stmts(
278-
self._wrap_attr(get_attr, context), context, frame=self
279-
)
278+
attrs = self.getattr(name, context, lookupclass=False)
279+
iattrs = self._proxied._infer_attrs(attrs, context, class_context=False)
280+
yield from self._wrap_attr(iattrs)
280281
except AttributeInferenceError:
281282
try:
282283
# fallback to class.igetattr since it has some logic to handle
283284
# descriptors
284285
# But only if the _proxied is the Class.
285286
if self._proxied.__class__.__name__ != "ClassDef":
286287
raise
287-
attrs = self._proxied.igetattr(name, context, class_context=False)
288-
yield from self._wrap_attr(attrs, context)
288+
iattrs = self._proxied.igetattr(name, context, class_context=False)
289+
yield from self._wrap_attr(iattrs, context)
289290
except AttributeInferenceError as error:
290291
raise InferenceError(**vars(error)) from error
291292

292293
def _wrap_attr(
293-
self, attrs: Iterable[InferenceResult], context: InferenceContext | None = None
294+
self, iattrs: Iterable[InferenceResult], context: InferenceContext | None = None
294295
) -> Iterator[InferenceResult]:
295296
"""Wrap bound methods of attrs in a InstanceMethod proxies."""
296-
for attr in attrs:
297+
for attr in iattrs:
297298
if isinstance(attr, UnboundMethod):
298299
if _is_property(attr):
299300
yield from attr.infer_call_result(self, context)

astroid/brain/brain_argparse.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,10 @@ def infer_namespace(node, context: InferenceContext | None = None):
2020
"Namespace",
2121
lineno=node.lineno,
2222
col_offset=node.col_offset,
23-
parent=nodes.Unknown(),
23+
parent=AstroidManager().adhoc_module, # this class is not real
2424
end_lineno=node.end_lineno,
2525
end_col_offset=node.end_col_offset,
2626
)
27-
# Set parent manually until ClassDef constructor fixed:
28-
# https://github.com/pylint-dev/astroid/issues/1490
29-
class_node.parent = node.parent
3027
for attr in set(callsite.keyword_arguments):
3128
fake_node = nodes.EmptyNode()
3229
fake_node.parent = class_node

astroid/brain/brain_builtin_inference.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
"""Astroid hooks for various builtins."""
66

7+
# isort: off
8+
79
from __future__ import annotations
810

911
import itertools
@@ -23,6 +25,7 @@
2325
)
2426
from astroid.manager import AstroidManager
2527
from astroid.nodes import scoped_nodes
28+
from astroid.raw_building import build_module
2629
from astroid.typing import (
2730
ConstFactoryResult,
2831
InferenceResult,
@@ -163,6 +166,8 @@ def _extend_builtins(class_transforms):
163166

164167
def on_bootstrap():
165168
"""Called by astroid_bootstrapping()."""
169+
AstroidManager().cache_module(build_module("__astroid_adhoc"))
170+
166171
_extend_builtins(
167172
{
168173
"bytes": partial(_extend_string_class, code=BYTES_CLASS, rvalue="b''"),
@@ -641,12 +646,13 @@ def infer_property(
641646

642647
prop_func = objects.Property(
643648
function=inferred,
644-
name=inferred.name,
649+
name="<property>",
645650
lineno=node.lineno,
646651
col_offset=node.col_offset,
652+
# ↓ semantically, the definition of this property isn't within
653+
# node.frame (or anywhere else, really)
654+
parent=AstroidManager().adhoc_module,
647655
)
648-
# Set parent outside __init__: https://github.com/pylint-dev/astroid/issues/1490
649-
prop_func.parent = node
650656
prop_func.postinit(
651657
body=[],
652658
args=inferred.args,

astroid/brain/brain_namedtuple_enum.py

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ def _extract_namedtuple_arg_or_keyword( # pylint: disable=inconsistent-return-s
7373

7474
def infer_func_form(
7575
node: nodes.Call,
76-
base_type: list[nodes.NodeNG],
76+
base_type: nodes.NodeNG,
77+
*,
78+
parent: nodes.NodeNG,
7779
context: InferenceContext | None = None,
7880
enum: bool = False,
7981
) -> tuple[nodes.ClassDef, str, list[str]]:
@@ -146,15 +148,11 @@ def infer_func_form(
146148
col_offset=node.col_offset,
147149
end_lineno=node.end_lineno,
148150
end_col_offset=node.end_col_offset,
149-
parent=nodes.Unknown(),
151+
parent=parent,
150152
)
151-
# A typical ClassDef automatically adds its name to the parent scope,
152-
# but doing so causes problems, so defer setting parent until after init
153-
# see: https://github.com/pylint-dev/pylint/issues/5982
154-
class_node.parent = node.parent
155153
class_node.postinit(
156154
# set base class=tuple
157-
bases=base_type,
155+
bases=[base_type],
158156
body=[],
159157
decorators=None,
160158
)
@@ -194,25 +192,18 @@ def infer_named_tuple(
194192
node: nodes.Call, context: InferenceContext | None = None
195193
) -> Iterator[nodes.ClassDef]:
196194
"""Specific inference function for namedtuple Call node."""
197-
tuple_base_name: list[nodes.NodeNG] = [
198-
nodes.Name(
199-
name="tuple",
200-
parent=node.root(),
201-
lineno=0,
202-
col_offset=0,
203-
end_lineno=None,
204-
end_col_offset=None,
205-
)
206-
]
195+
tuple_base = util.safe_infer(_extract_single_node("tuple"))
196+
assert isinstance(tuple_base, nodes.NodeNG)
197+
207198
class_node, name, attributes = infer_func_form(
208-
node, tuple_base_name, context=context
199+
node, tuple_base, parent=AstroidManager().adhoc_module, context=context
209200
)
201+
210202
call_site = arguments.CallSite.from_call(node, context=context)
211-
node = extract_node("import collections; collections.namedtuple")
212-
try:
213-
func = next(node.infer())
214-
except StopIteration as e:
215-
raise InferenceError(node=node) from e
203+
func = util.safe_infer(
204+
_extract_single_node("import collections; collections.namedtuple")
205+
)
206+
assert isinstance(func, nodes.NodeNG)
216207
try:
217208
rename = next(
218209
call_site.infer_argument(func, "rename", context or InferenceContext())
@@ -363,7 +354,17 @@ def value(self):
363354
__members__ = ['']
364355
"""
365356
)
366-
class_node = infer_func_form(node, [enum_meta], context=context, enum=True)[0]
357+
358+
# FIXME arguably, the base here shouldn't be the EnumMeta class definition
359+
# itself, but a reference (Name) to it. Otherwise, the invariant that all
360+
# children of a node have that node as their parent is broken.
361+
class_node = infer_func_form(
362+
node,
363+
enum_meta,
364+
parent=AstroidManager().adhoc_module,
365+
context=context,
366+
enum=True,
367+
)[0]
367368
return iter([class_node.instantiate_class()])
368369

369370

astroid/helpers.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ def safe_infer(
3737

3838

3939
def _build_proxy_class(cls_name: str, builtins: nodes.Module) -> nodes.ClassDef:
40-
proxy = raw_building.build_class(cls_name)
41-
proxy.parent = builtins
40+
proxy = raw_building.build_class(cls_name, builtins)
4241
return proxy
4342

4443

astroid/interpreter/objectmodel.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
mechanism.
2222
"""
2323

24+
# isort: off
25+
2426
from __future__ import annotations
2527

2628
import itertools
@@ -493,7 +495,7 @@ def __init__(self):
493495
super().__init__()
494496

495497
@property
496-
def attr___annotations__(self) -> node_classes.Unkown:
498+
def attr___annotations__(self) -> node_classes.Unknown:
497499
return node_classes.Unknown()
498500

499501
@property

astroid/manager.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ def unregister_transform(self):
115115
def builtins_module(self) -> nodes.Module:
116116
return self.astroid_cache["builtins"]
117117

118+
@property
119+
def adhoc_module(self) -> nodes.Module:
120+
return self.astroid_cache["__astroid_adhoc"]
121+
118122
@property
119123
def prefer_stubs(self) -> bool:
120124
return AstroidManager.brain["prefer_stubs"]

astroid/nodes/node_ng.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
33
# Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
44

5+
# isort: off
6+
57
from __future__ import annotations
68

79
import pprint
@@ -43,7 +45,6 @@
4345

4446

4547
if TYPE_CHECKING:
46-
from astroid import nodes
4748
from astroid.nodes import _base_nodes
4849

4950

0 commit comments

Comments
 (0)