From 275f508414607deef0c5fe8dfdc945be92b0151f Mon Sep 17 00:00:00 2001 From: temyurchenko <44875844+temyurchenko@users.noreply.github.com> Date: Mon, 7 Oct 2024 01:08:43 -0400 Subject: [PATCH] Clarification on non-Module roots (#2536) * remove last instances of Unknown parents (and None parents in tests) It's a part of the campaign to get rid of non-module roots * assert that the root() is always a Module The nodes are often created in an ad-hoc way, and their parent is not always set. We can't control for that invariant fully in the constructor, since the parent is sometimes set outside of the constructor. The previous commits did their best to clean up such situations, but let's add an assert just in case. --- astroid/brain/brain_argparse.py | 2 +- astroid/brain/brain_builtin_inference.py | 4 ++-- astroid/brain/brain_namedtuple_enum.py | 4 ++-- astroid/manager.py | 4 ++-- astroid/nodes/node_ng.py | 9 +++++---- astroid/nodes/scoped_nodes/scoped_nodes.py | 6 ++---- astroid/objects.py | 2 +- astroid/raw_building.py | 6 ++---- tests/test_nodes.py | 5 ++++- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/astroid/brain/brain_argparse.py b/astroid/brain/brain_argparse.py index 2e6b742c38..f7ba5f92e7 100644 --- a/astroid/brain/brain_argparse.py +++ b/astroid/brain/brain_argparse.py @@ -21,7 +21,7 @@ def infer_namespace(node, context: InferenceContext | None = None): "Namespace", lineno=node.lineno, col_offset=node.col_offset, - parent=AstroidManager().adhoc_module, # this class is not real + parent=AstroidManager().synthetic_root, # this class is not real end_lineno=node.end_lineno, end_col_offset=node.end_col_offset, ) diff --git a/astroid/brain/brain_builtin_inference.py b/astroid/brain/brain_builtin_inference.py index 821261933b..7d11f8815a 100644 --- a/astroid/brain/brain_builtin_inference.py +++ b/astroid/brain/brain_builtin_inference.py @@ -165,7 +165,7 @@ def _extend_builtins(class_transforms): def on_bootstrap(): """Called by astroid_bootstrapping().""" - AstroidManager().cache_module(build_module("__astroid_adhoc")) + AstroidManager().cache_module(build_module("__astroid_synthetic")) _extend_builtins( { @@ -653,7 +653,7 @@ def infer_property( # node.frame. It's somewhere in the builtins module, but we are special # casing it for each "property()" call, so we are making up the # definition on the spot, ad-hoc. - parent=AstroidManager().adhoc_module, + parent=AstroidManager().synthetic_root, ) prop_func.postinit( body=[], diff --git a/astroid/brain/brain_namedtuple_enum.py b/astroid/brain/brain_namedtuple_enum.py index 0c51b8b368..34f0501bc3 100644 --- a/astroid/brain/brain_namedtuple_enum.py +++ b/astroid/brain/brain_namedtuple_enum.py @@ -194,7 +194,7 @@ def infer_named_tuple( """Specific inference function for namedtuple Call node.""" tuple_base: nodes.Name = _extract_single_node("tuple") class_node, name, attributes = infer_func_form( - node, tuple_base, parent=AstroidManager().adhoc_module, context=context + node, tuple_base, parent=AstroidManager().synthetic_root, context=context ) call_site = arguments.CallSite.from_call(node, context=context) @@ -360,7 +360,7 @@ def value(self): class_node = infer_func_form( node, enum_meta, - parent=AstroidManager().adhoc_module, + parent=AstroidManager().synthetic_root, context=context, enum=True, )[0] diff --git a/astroid/manager.py b/astroid/manager.py index 3ed9ca39c4..aed586c04b 100644 --- a/astroid/manager.py +++ b/astroid/manager.py @@ -116,8 +116,8 @@ def builtins_module(self) -> nodes.Module: return self.astroid_cache["builtins"] @property - def adhoc_module(self) -> nodes.Module: - return self.astroid_cache["__astroid_adhoc"] + def synthetic_root(self) -> nodes.Module: + return self.astroid_cache["__astroid_synthetic"] @property def prefer_stubs(self) -> bool: diff --git a/astroid/nodes/node_ng.py b/astroid/nodes/node_ng.py index 99120bb65f..c6a044f5a4 100644 --- a/astroid/nodes/node_ng.py +++ b/astroid/nodes/node_ng.py @@ -21,7 +21,7 @@ overload, ) -from astroid import util +from astroid import nodes, util from astroid.context import InferenceContext from astroid.exceptions import ( AstroidError, @@ -43,7 +43,6 @@ if TYPE_CHECKING: - from astroid import nodes from astroid.nodes import _base_nodes @@ -332,11 +331,13 @@ def root(self) -> nodes.Module: :returns: The root node. """ if not (parent := self.parent): - return self # type: ignore[return-value] # Only 'Module' does not have a parent node. + assert isinstance(self, nodes.Module) + return self while parent.parent: parent = parent.parent - return parent # type: ignore[return-value] # Only 'Module' does not have a parent node. + assert isinstance(parent, nodes.Module) + return parent def child_sequence(self, child): """Search for the sequence that contains this child. diff --git a/astroid/nodes/scoped_nodes/scoped_nodes.py b/astroid/nodes/scoped_nodes/scoped_nodes.py index 176cb8dbd4..0a80eb8aac 100644 --- a/astroid/nodes/scoped_nodes/scoped_nodes.py +++ b/astroid/nodes/scoped_nodes/scoped_nodes.py @@ -44,7 +44,6 @@ Arguments, Const, NodeNG, - Unknown, _base_nodes, const_factory, node_classes, @@ -1603,7 +1602,7 @@ def infer_call_result( col_offset=0, end_lineno=0, end_col_offset=0, - parent=AstroidManager().adhoc_module, + parent=AstroidManager().synthetic_root, ) new_class.hide = True new_class.postinit( @@ -2037,7 +2036,7 @@ def _infer_type_call(self, caller, context): col_offset=0, end_lineno=0, end_col_offset=0, - parent=Unknown(), + parent=caller.parent, ) # Get the bases of the class. @@ -2071,7 +2070,6 @@ def _infer_type_call(self, caller, context): if isinstance(attr, node_classes.Const) and isinstance(attr.value, str): result.locals[attr.value] = [value] - result.parent = caller.parent return result def infer_call_result( diff --git a/astroid/objects.py b/astroid/objects.py index 4a6b58d749..829cbf1900 100644 --- a/astroid/objects.py +++ b/astroid/objects.py @@ -279,7 +279,7 @@ def __init__(self, call, name=None, lineno=None, col_offset=None, parent=None): name, lineno=lineno, col_offset=col_offset, - parent=AstroidManager().adhoc_module, + parent=AstroidManager().synthetic_root, end_col_offset=0, end_lineno=0, ) diff --git a/astroid/raw_building.py b/astroid/raw_building.py index 2d46706745..c1f7ec158d 100644 --- a/astroid/raw_building.py +++ b/astroid/raw_building.py @@ -670,9 +670,8 @@ def _astroid_bootstrapping() -> None: col_offset=0, end_lineno=0, end_col_offset=0, - parent=nodes.Unknown(), + parent=astroid_builtin, ) - _UnionTypeType.parent = astroid_builtin union_type_doc_node = ( nodes.Const(value=types.UnionType.__doc__) if types.UnionType.__doc__ @@ -707,9 +706,8 @@ def _astroid_bootstrapping() -> None: col_offset=0, end_lineno=0, end_col_offset=0, - parent=nodes.Unknown(), + parent=astroid_builtin, ) - klass.parent = astroid_builtin doc = _type.__doc__ if isinstance(_type.__doc__, str) else None klass.postinit( bases=[], diff --git a/tests/test_nodes.py b/tests/test_nodes.py index 644ceb1500..deb3b7fef5 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -37,6 +37,7 @@ ParentMissingError, StatementMissing, ) +from astroid.manager import AstroidManager from astroid.nodes.node_classes import ( AssignAttr, AssignName, @@ -1960,7 +1961,9 @@ def test_str_repr_no_warnings(node): if name == "self": continue - if "int" in param_type.annotation: + if name == "parent" and "NodeNG" in param_type.annotation: + args[name] = AstroidManager().synthetic_root + elif "int" in param_type.annotation: args[name] = random.randint(0, 50) elif ( "NodeNG" in param_type.annotation