diff --git a/ChangeLog b/ChangeLog index af0c97ace6..ec63e2dade 100644 --- a/ChangeLog +++ b/ChangeLog @@ -146,6 +146,14 @@ Release date: TBA Refs #2141 +* ``frame()`` raises ``ParentMissingError`` and ``statement()`` raises ``StatementMissing`` for + missing parents regardless of the value of the ``future`` argument (which gave this behavior + already). + + The ``future`` argument to each method is deprecated and will be removed in astroid 4.0. + + Refs #1217 + * Remove deprecated ``Ellipsis``, ``ExtSlice``, ``Index`` nodes. Refs #2152 diff --git a/astroid/arguments.py b/astroid/arguments.py index 734af1ab57..f016823a98 100644 --- a/astroid/arguments.py +++ b/astroid/arguments.py @@ -211,7 +211,7 @@ def infer_argument( return positional[0].infer(context=context) if boundnode is None: # XXX can do better ? - boundnode = funcnode.parent.frame(future=True) + boundnode = funcnode.parent.frame() if isinstance(boundnode, nodes.ClassDef): # Verify that we're accessing a method diff --git a/astroid/bases.py b/astroid/bases.py index 8d07ae665a..2f756a615e 100644 --- a/astroid/bases.py +++ b/astroid/bases.py @@ -430,7 +430,7 @@ class UnboundMethod(Proxy): def __repr__(self) -> str: assert self._proxied.parent, "Expected a parent node" - frame = self._proxied.parent.frame(future=True) + frame = self._proxied.parent.frame() return "<{} {} of {} at 0x{}".format( self.__class__.__name__, self._proxied.name, frame.qname(), id(self) ) @@ -472,7 +472,7 @@ def infer_call_result( # instance of the class given as first argument. if self._proxied.name == "__new__": assert self._proxied.parent, "Expected a parent node" - qname = self._proxied.parent.frame(future=True).qname() + qname = self._proxied.parent.frame().qname() # Avoid checking builtins.type: _infer_type_new_call() does more validation if qname.startswith("builtins.") and qname != "builtins.type": return self._infer_builtin_new(caller, context or InferenceContext()) diff --git a/astroid/brain/brain_dataclasses.py b/astroid/brain/brain_dataclasses.py index 29e8d6f61b..f37c09a628 100644 --- a/astroid/brain/brain_dataclasses.py +++ b/astroid/brain/brain_dataclasses.py @@ -482,7 +482,7 @@ def _looks_like_dataclass_field_call( If check_scope is False, skips checking the statement and body. """ if check_scope: - stmt = node.statement(future=True) + stmt = node.statement() scope = stmt.scope() if not ( isinstance(stmt, nodes.AnnAssign) diff --git a/astroid/brain/brain_namedtuple_enum.py b/astroid/brain/brain_namedtuple_enum.py index 84bb0fcd7b..1fd64fe629 100644 --- a/astroid/brain/brain_namedtuple_enum.py +++ b/astroid/brain/brain_namedtuple_enum.py @@ -406,7 +406,7 @@ def infer_enum_class(node: nodes.ClassDef) -> nodes.ClassDef: if any(not isinstance(value, nodes.AssignName) for value in values): continue - stmt = values[0].statement(future=True) + stmt = values[0].statement() if isinstance(stmt, nodes.Assign): if isinstance(stmt.targets[0], nodes.Tuple): targets = stmt.targets[0].itered() diff --git a/astroid/builder.py b/astroid/builder.py index d654cea77b..cd2fb1f82e 100644 --- a/astroid/builder.py +++ b/astroid/builder.py @@ -233,7 +233,7 @@ def delayed_assattr(self, node: nodes.AssignAttr) -> None: from astroid import objects # pylint: disable=import-outside-toplevel try: - frame = node.frame(future=True) + frame = node.frame() for inferred in node.expr.infer(): if isinstance(inferred, util.UninferableBase): continue @@ -268,7 +268,7 @@ def delayed_assattr(self, node: nodes.AssignAttr) -> None: if ( frame.name == "__init__" and values - and values[0].frame(future=True).name != "__init__" + and values[0].frame().name != "__init__" ): values.insert(0, node) else: diff --git a/astroid/filter_statements.py b/astroid/filter_statements.py index 3585474449..7f040dd4ed 100644 --- a/astroid/filter_statements.py +++ b/astroid/filter_statements.py @@ -18,7 +18,7 @@ def _get_filtered_node_statements( base_node: nodes.NodeNG, stmt_nodes: list[nodes.NodeNG] ) -> list[tuple[nodes.NodeNG, nodes.Statement]]: - statements = [(node, node.statement(future=True)) for node in stmt_nodes] + statements = [(node, node.statement()) for node in stmt_nodes] # Next we check if we have ExceptHandlers that are parent # of the underlying variable, in which case the last one survives if len(statements) > 1 and all( @@ -83,16 +83,12 @@ def _filter_stmts( # # def test(b=1): # ... - if ( - base_node.parent - and base_node.statement(future=True) is myframe - and myframe.parent - ): + if base_node.parent and base_node.statement() is myframe and myframe.parent: myframe = myframe.parent.frame() mystmt: nodes.Statement | None = None if base_node.parent: - mystmt = base_node.statement(future=True) + mystmt = base_node.statement() # line filtering if we are in the same frame # diff --git a/astroid/helpers.py b/astroid/helpers.py index 40bbf7e069..ab5ada3715 100644 --- a/astroid/helpers.py +++ b/astroid/helpers.py @@ -266,7 +266,7 @@ def object_len(node, context: InferenceContext | None = None): # prevent self referential length calls from causing a recursion error # see https://github.com/pylint-dev/astroid/issues/777 - node_frame = node.frame(future=True) + node_frame = node.frame() if ( isinstance(node_frame, scoped_nodes.FunctionDef) and node_frame.name == "__len__" diff --git a/astroid/inference.py b/astroid/inference.py index 6dcfa49f1b..0b84d64bdd 100644 --- a/astroid/inference.py +++ b/astroid/inference.py @@ -1264,7 +1264,7 @@ def infer_functiondef( # of the wrapping frame. This means that every time we infer a property, the locals # are mutated with a new instance of the property. To avoid this, we detect this # scenario and avoid passing the `parent` argument to the constructor. - parent_frame = self.parent.frame(future=True) + parent_frame = self.parent.frame() property_already_in_parent_locals = self.name in parent_frame.locals and any( isinstance(val, objects.Property) for val in parent_frame.locals[self.name] ) diff --git a/astroid/nodes/_base_nodes.py b/astroid/nodes/_base_nodes.py index c79fec799b..15cc6a9ad1 100644 --- a/astroid/nodes/_base_nodes.py +++ b/astroid/nodes/_base_nodes.py @@ -68,7 +68,7 @@ class FilterStmtsBaseNode(NodeNG): def _get_filtered_stmts(self, _, node, _stmts, mystmt: Statement | None): """Method used in _filter_stmts to get statements and trigger break.""" - if self.statement(future=True) is mystmt: + if self.statement() is mystmt: # original node's statement is the assignment, only keep # current node (gen exp, list comp) return [node], True @@ -88,7 +88,7 @@ def _get_filtered_stmts(self, lookup_node, node, _stmts, mystmt: Statement | Non """Method used in filter_stmts.""" if self is mystmt: return _stmts, True - if self.statement(future=True) is mystmt: + if self.statement() is mystmt: # original node's statement is the assignment, only keep # current node (gen exp, list comp) return [node], True diff --git a/astroid/nodes/node_classes.py b/astroid/nodes/node_classes.py index 6b7544c78b..84d8cbe15d 100644 --- a/astroid/nodes/node_classes.py +++ b/astroid/nodes/node_classes.py @@ -1528,7 +1528,7 @@ def _get_filtered_stmts( if isinstance(lookup_node, (Const, Name)): return [lookup_node], True - elif self.statement(future=True) is mystmt: + elif self.statement() is mystmt: # original node's statement is the assignment, only keeps # current node (gen exp, list comp) @@ -3814,6 +3814,12 @@ def frame( :returns: The first parent frame node. """ + if future is not None: + warnings.warn( + "The future arg will be removed in astroid 4.0.", + DeprecationWarning, + stacklevel=2, + ) if not self.parent: raise ParentMissingError(target=self) @@ -3823,9 +3829,9 @@ def frame( raise ParentMissingError(target=self.parent) if not self.parent.parent.parent: raise ParentMissingError(target=self.parent.parent) - return self.parent.parent.parent.frame(future=True) + return self.parent.parent.parent.frame() - return self.parent.frame(future=True) + return self.parent.frame() def scope(self) -> LocalsDictNodeNG: """The first parent node defining a new scope. @@ -3857,7 +3863,7 @@ def set_local(self, name: str, stmt: NodeNG) -> None: :param stmt: The statement that defines the given name. """ - self.frame(future=True).set_local(name, stmt) + self.frame().set_local(name, stmt) class Unknown(_base_nodes.AssignTypeNode): diff --git a/astroid/nodes/node_ng.py b/astroid/nodes/node_ng.py index af2d270e1b..08860e3621 100644 --- a/astroid/nodes/node_ng.py +++ b/astroid/nodes/node_ng.py @@ -288,40 +288,22 @@ def parent_of(self, node) -> bool: """ return any(self is parent for parent in node.node_ancestors()) - @overload - def statement(self, *, future: None = ...) -> nodes.Statement | nodes.Module: - ... - - @overload - def statement(self, *, future: Literal[True]) -> nodes.Statement: - ... - - def statement( - self, *, future: Literal[None, True] = None - ) -> nodes.Statement | nodes.Module: + def statement(self, *, future: Literal[None, True] = None) -> nodes.Statement: """The first parent node, including self, marked as statement node. - TODO: Deprecate the future parameter and only raise StatementMissing and return - nodes.Statement - - :raises AttributeError: If self has no parent attribute - :raises StatementMissing: If self has no parent attribute and future is True + :raises StatementMissing: If self has no parent attribute. """ - if self.is_statement: - return cast("nodes.Statement", self) - if not self.parent: - if future: - raise StatementMissing(target=self) + if future is not None: warnings.warn( - "In astroid 3.0.0 NodeNG.statement() will return either a nodes.Statement " - "or raise a StatementMissing exception. AttributeError will no longer be raised. " - "This behaviour can already be triggered " - "by passing 'future=True' to a statement() call.", + "The future arg will be removed in astroid 4.0.", DeprecationWarning, stacklevel=2, ) - raise AttributeError(f"{self} object has no attribute 'parent'") - return self.parent.statement(future=future) + if self.is_statement: + return cast("nodes.Statement", self) + if not self.parent: + raise StatementMissing(target=self) + return self.parent.statement() def frame( self, *, future: Literal[None, True] = None @@ -332,20 +314,16 @@ def frame( :class:`ClassDef` or :class:`Lambda`. :returns: The first parent frame node. + :raises ParentMissingError: If self has no parent attribute. """ - if self.parent is None: - if future: - raise ParentMissingError(target=self) + if future is not None: warnings.warn( - "In astroid 3.0.0 NodeNG.frame() will return either a Frame node, " - "or raise ParentMissingError. AttributeError will no longer be raised. " - "This behaviour can already be triggered " - "by passing 'future=True' to a frame() call.", + "The future arg will be removed in astroid 4.0.", DeprecationWarning, stacklevel=2, ) - raise AttributeError(f"{self} object has no attribute 'parent'") - + if self.parent is None: + raise ParentMissingError(target=self) return self.parent.frame(future=future) def scope(self) -> nodes.LocalsDictNodeNG: diff --git a/astroid/nodes/scoped_nodes/mixin.py b/astroid/nodes/scoped_nodes/mixin.py index df4e7bcfc2..fa6aad412e 100644 --- a/astroid/nodes/scoped_nodes/mixin.py +++ b/astroid/nodes/scoped_nodes/mixin.py @@ -41,7 +41,7 @@ def qname(self) -> str: # pylint: disable=no-member; github.com/pylint-dev/astroid/issues/278 if self.parent is None or isinstance(self.parent, node_classes.Unknown): return self.name - return f"{self.parent.frame(future=True).qname()}.{self.name}" + return f"{self.parent.frame().qname()}.{self.name}" def scope(self: _T) -> _T: """The first parent node defining a new scope. diff --git a/astroid/nodes/scoped_nodes/scoped_nodes.py b/astroid/nodes/scoped_nodes/scoped_nodes.py index bfe1462fd3..0ae2141741 100644 --- a/astroid/nodes/scoped_nodes/scoped_nodes.py +++ b/astroid/nodes/scoped_nodes/scoped_nodes.py @@ -16,7 +16,7 @@ import warnings from collections.abc import Generator, Iterable, Iterator, Sequence from functools import cached_property, lru_cache -from typing import TYPE_CHECKING, ClassVar, Literal, NoReturn, TypeVar, overload +from typing import TYPE_CHECKING, ClassVar, Literal, NoReturn, TypeVar from astroid import bases, util from astroid.const import IS_PYPY, PY38, PY39_PLUS, PYPY_7_3_11_PLUS @@ -377,34 +377,18 @@ def fully_defined(self) -> bool: """ return self.file is not None and self.file.endswith(".py") - @overload - def statement(self, *, future: None = ...) -> Module: - ... - - @overload - def statement(self, *, future: Literal[True]) -> NoReturn: - ... - - def statement(self, *, future: Literal[None, True] = None) -> Module | NoReturn: + def statement(self, *, future: Literal[None, True] = None) -> NoReturn: """The first parent node, including self, marked as statement node. - When called on a :class:`Module` with the future parameter this raises an error. - - TODO: Deprecate the future parameter and only raise StatementMissing - - :raises StatementMissing: If no self has no parent attribute and future is True + When called on a :class:`Module` this raises a StatementMissing. """ - if future: - raise StatementMissing(target=self) - warnings.warn( - "In astroid 3.0.0 NodeNG.statement() will return either a nodes.Statement " - "or raise a StatementMissing exception. nodes.Module will no longer be " - "considered a statement. This behaviour can already be triggered " - "by passing 'future=True' to a statement() call.", - DeprecationWarning, - stacklevel=2, - ) - return self + if future is not None: + warnings.warn( + "The future arg will be removed in astroid 4.0.", + DeprecationWarning, + stacklevel=2, + ) + raise StatementMissing(target=self) def previous_sibling(self): """The previous sibling statement. @@ -991,7 +975,7 @@ def scope_lookup( if (self.args.defaults and node in self.args.defaults) or ( self.args.kw_defaults and node in self.args.kw_defaults ): - frame = self.parent.frame(future=True) + frame = self.parent.frame() # line offset to avoid that def func(f=func) resolve the default # value to the defined function offset = -1 @@ -1133,7 +1117,7 @@ def __init__( parent=parent, ) if parent and not isinstance(parent, Unknown): - frame = parent.frame(future=True) + frame = parent.frame() frame.set_local(name, self) def postinit( @@ -1183,7 +1167,7 @@ def extra_decorators(self) -> list[node_classes.Call]: The property will return all the callables that are used for decoration. """ - frame = self.parent.frame(future=True) + frame = self.parent.frame() if not isinstance(frame, ClassDef): return [] @@ -1210,7 +1194,7 @@ def extra_decorators(self) -> list[node_classes.Call]: # original method. if ( isinstance(meth, FunctionDef) - and assign_node.frame(future=True) == frame + and assign_node.frame() == frame ): decorators.append(assign.value) return decorators @@ -1281,7 +1265,7 @@ def type(self) -> str: # pylint: disable=too-many-return-statements # noqa: C90 if decorator.func.name in BUILTIN_DESCRIPTORS: return decorator.func.name - frame = self.parent.frame(future=True) + frame = self.parent.frame() type_name = "function" if isinstance(frame, ClassDef): if self.name == "__new__": @@ -1395,9 +1379,7 @@ def is_method(self) -> bool: """ # check we are defined in a ClassDef, because this is usually expected # (e.g. pylint...) when is_method() return True - return self.type != "function" and isinstance( - self.parent.frame(future=True), ClassDef - ) + return self.type != "function" and isinstance(self.parent.frame(), ClassDef) def decoratornames(self, context: InferenceContext | None = None) -> set[str]: """Get the qualified names of each of the decorators on this function. @@ -1608,14 +1590,14 @@ def scope_lookup( # if any methods in a class body refer to either __class__ or super. # In our case, we want to be able to look it up in the current scope # when `__class__` is being used. - frame = self.parent.frame(future=True) + frame = self.parent.frame() if isinstance(frame, ClassDef): return self, [frame] if (self.args.defaults and node in self.args.defaults) or ( self.args.kw_defaults and node in self.args.kw_defaults ): - frame = self.parent.frame(future=True) + frame = self.parent.frame() # line offset to avoid that def func(f=func) resolve the default # value to the defined function offset = -1 @@ -1730,12 +1712,12 @@ def get_wrapping_class(node): :rtype: ClassDef or None """ - klass = node.frame(future=True) + klass = node.frame() while klass is not None and not isinstance(klass, ClassDef): if klass.parent is None: klass = None else: - klass = klass.parent.frame(future=True) + klass = klass.parent.frame() return klass @@ -1833,7 +1815,7 @@ def __init__( parent=parent, ) if parent and not isinstance(parent, Unknown): - parent.frame(future=True).set_local(name, self) + parent.frame().set_local(name, self) for local_name, node in self.implicit_locals(): self.add_local_node(node, local_name) @@ -2108,7 +2090,7 @@ def scope_lookup( # class A(name.Name): # def name(self): ... - frame = self.parent.frame(future=True) + frame = self.parent.frame() # line offset to avoid that class A(A) resolve the ancestor to # the defined class offset = -1 @@ -2326,7 +2308,7 @@ def getattr( # Remove AnnAssigns without value, which are not attributes in the purest sense. for value in values.copy(): if isinstance(value, node_classes.AssignName): - stmt = value.statement(future=True) + stmt = value.statement() if isinstance(stmt, node_classes.AnnAssign) and stmt.value is None: values.pop(values.index(value)) diff --git a/astroid/protocols.py b/astroid/protocols.py index 07d11092cf..e3b89b7ef7 100644 --- a/astroid/protocols.py +++ b/astroid/protocols.py @@ -462,7 +462,7 @@ def arguments_assigned_stmts( callee = callee._proxied else: return _arguments_infer_argname(self, node_name, context) - if node and getattr(callee, "name", None) == node.frame(future=True).name: + if node and getattr(callee, "name", None) == node.frame().name: # reset call context/name callcontext = context.callcontext context = copy_context(context) @@ -755,7 +755,7 @@ def _determine_starred_iteration_lookups( lookups.append((index, len(element.itered()))) _determine_starred_iteration_lookups(starred, element, lookups) - stmt = self.statement(future=True) + stmt = self.statement() if not isinstance(stmt, (nodes.Assign, nodes.For)): raise InferenceError( "Statement {stmt!r} enclosing {node!r} must be an Assign or For node.", diff --git a/tests/test_builder.py b/tests/test_builder.py index ff83eceabe..c025afa8a2 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -756,17 +756,18 @@ def test_module_base_props(self) -> None: self.assertEqual(module.fromlineno, 0) self.assertIsNone(module.parent) self.assertEqual(module.frame(), module) - self.assertEqual(module.frame(future=True), module) + self.assertEqual(module.frame(), module) self.assertEqual(module.root(), module) self.assertEqual(module.file, os.path.abspath(resources.find("data/module.py"))) self.assertEqual(module.pure_python, 1) self.assertEqual(module.package, 0) self.assertFalse(module.is_statement) - with pytest.warns(DeprecationWarning) as records: - self.assertEqual(module.statement(), module) - assert len(records) == 1 with self.assertRaises(StatementMissing): - module.statement(future=True) + with pytest.warns(DeprecationWarning) as records: + self.assertEqual(module.statement(future=True), module) + assert len(records) == 1 + with self.assertRaises(StatementMissing): + module.statement() def test_module_locals(self) -> None: """Test the 'locals' dictionary of an astroid module.""" @@ -800,8 +801,8 @@ def test_function_base_props(self) -> None: self.assertTrue(function.parent) self.assertEqual(function.frame(), function) self.assertEqual(function.parent.frame(), module) - self.assertEqual(function.frame(future=True), function) - self.assertEqual(function.parent.frame(future=True), module) + self.assertEqual(function.frame(), function) + self.assertEqual(function.parent.frame(), module) self.assertEqual(function.root(), module) self.assertEqual([n.name for n in function.args.args], ["key", "val"]) self.assertEqual(function.type, "function") @@ -824,8 +825,8 @@ def test_class_base_props(self) -> None: self.assertTrue(klass.parent) self.assertEqual(klass.frame(), klass) self.assertEqual(klass.parent.frame(), module) - self.assertEqual(klass.frame(future=True), klass) - self.assertEqual(klass.parent.frame(future=True), module) + self.assertEqual(klass.frame(), klass) + self.assertEqual(klass.parent.frame(), module) self.assertEqual(klass.root(), module) self.assertEqual(klass.basenames, []) self.assertTrue(klass.newstyle) diff --git a/tests/test_filter_statements.py b/tests/test_filter_statements.py index 3fc14bd5e8..2accf6e74f 100644 --- a/tests/test_filter_statements.py +++ b/tests/test_filter_statements.py @@ -11,7 +11,5 @@ def test_empty_node() -> None: enum_mod = extract_node("import enum") empty = EmptyNode(parent=enum_mod) empty.is_statement = True - filtered_statements = _filter_stmts( - empty, [empty.statement(future=True)], empty.frame(future=True), 0 - ) + filtered_statements = _filter_stmts(empty, [empty.statement()], empty.frame(), 0) assert filtered_statements[0] is empty diff --git a/tests/test_inference.py b/tests/test_inference.py index 6760f9c91b..22b75e9924 100644 --- a/tests/test_inference.py +++ b/tests/test_inference.py @@ -315,7 +315,7 @@ def test_unbound_method_inference(self) -> None: self.assertIsInstance(meth1, UnboundMethod) self.assertEqual(meth1.name, "meth1") self.assertEqual(meth1.parent.frame().name, "C") - self.assertEqual(meth1.parent.frame(future=True).name, "C") + self.assertEqual(meth1.parent.frame().name, "C") self.assertRaises(StopIteration, partial(next, inferred)) def test_bound_method_inference(self) -> None: @@ -324,7 +324,7 @@ def test_bound_method_inference(self) -> None: self.assertIsInstance(meth1, BoundMethod) self.assertEqual(meth1.name, "meth1") self.assertEqual(meth1.parent.frame().name, "C") - self.assertEqual(meth1.parent.frame(future=True).name, "C") + self.assertEqual(meth1.parent.frame().name, "C") self.assertRaises(StopIteration, partial(next, inferred)) def test_args_default_inference1(self) -> None: diff --git a/tests/test_manager.py b/tests/test_manager.py index ef0c0699e1..56b09945ba 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -321,12 +321,12 @@ def test_ast_from_class(self) -> None: ast = self.manager.ast_from_class(int) self.assertEqual(ast.name, "int") self.assertEqual(ast.parent.frame().name, "builtins") - self.assertEqual(ast.parent.frame(future=True).name, "builtins") + self.assertEqual(ast.parent.frame().name, "builtins") ast = self.manager.ast_from_class(object) self.assertEqual(ast.name, "object") self.assertEqual(ast.parent.frame().name, "builtins") - self.assertEqual(ast.parent.frame(future=True).name, "builtins") + self.assertEqual(ast.parent.frame().name, "builtins") self.assertIn("__setattr__", ast) def test_ast_from_class_with_module(self) -> None: @@ -334,12 +334,12 @@ def test_ast_from_class_with_module(self) -> None: ast = self.manager.ast_from_class(int, int.__module__) self.assertEqual(ast.name, "int") self.assertEqual(ast.parent.frame().name, "builtins") - self.assertEqual(ast.parent.frame(future=True).name, "builtins") + self.assertEqual(ast.parent.frame().name, "builtins") ast = self.manager.ast_from_class(object, object.__module__) self.assertEqual(ast.name, "object") self.assertEqual(ast.parent.frame().name, "builtins") - self.assertEqual(ast.parent.frame(future=True).name, "builtins") + self.assertEqual(ast.parent.frame().name, "builtins") self.assertIn("__setattr__", ast) def test_ast_from_class_attr_error(self) -> None: diff --git a/tests/test_nodes.py b/tests/test_nodes.py index d5c017dfc4..2a34d50455 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -541,19 +541,19 @@ def _test(self, value: Any) -> None: self.assertIs(node.value, value) self.assertTrue(node._proxied.parent) self.assertEqual(node._proxied.root().name, value.__class__.__module__) - with self.assertRaises(AttributeError): + with self.assertRaises(StatementMissing): with pytest.warns(DeprecationWarning) as records: - node.statement() + node.statement(future=True) assert len(records) == 1 with self.assertRaises(StatementMissing): - node.statement(future=True) + node.statement() - with self.assertRaises(AttributeError): + with self.assertRaises(ParentMissingError): with pytest.warns(DeprecationWarning) as records: - node.frame() + node.frame(future=True) assert len(records) == 1 with self.assertRaises(ParentMissingError): - node.frame(future=True) + node.frame() def test_none(self) -> None: self._test(None) @@ -641,35 +641,35 @@ def func_with_lambda( ) function = module.body[0] assert function.args.frame() == function - assert function.args.frame(future=True) == function + assert function.args.frame() == function function_two = module.body[1] assert function_two.args.args[0].frame() == function_two - assert function_two.args.args[0].frame(future=True) == function_two + assert function_two.args.args[0].frame() == function_two + assert function_two.args.args[1].frame() == function_two assert function_two.args.args[1].frame() == function_two - assert function_two.args.args[1].frame(future=True) == function_two assert function_two.args.defaults[0].frame() == module - assert function_two.args.defaults[0].frame(future=True) == module + assert function_two.args.defaults[0].frame() == module inherited_class = module.body[3] assert inherited_class.keywords[0].frame() == inherited_class - assert inherited_class.keywords[0].frame(future=True) == inherited_class + assert inherited_class.keywords[0].frame() == inherited_class + assert inherited_class.keywords[0].value.frame() == module assert inherited_class.keywords[0].value.frame() == module - assert inherited_class.keywords[0].value.frame(future=True) == module lambda_assignment = module.body[4].value assert lambda_assignment.args.args[0].frame() == lambda_assignment - assert lambda_assignment.args.args[0].frame(future=True) == lambda_assignment + assert lambda_assignment.args.args[0].frame() == lambda_assignment + assert lambda_assignment.args.defaults[0].frame() == module assert lambda_assignment.args.defaults[0].frame() == module - assert lambda_assignment.args.defaults[0].frame(future=True) == module lambda_named_expr = module.body[5].args.defaults[0] assert lambda_named_expr.value.args.defaults[0].frame() == module - assert lambda_named_expr.value.args.defaults[0].frame(future=True) == module + assert lambda_named_expr.value.args.defaults[0].frame() == module comprehension = module.body[6].value assert comprehension.generators[0].ifs[0].frame() == module - assert comprehension.generators[0].ifs[0].frame(future=True) == module + assert comprehension.generators[0].ifs[0].frame() == module @staticmethod def test_scope() -> None: diff --git a/tests/test_scoped_nodes.py b/tests/test_scoped_nodes.py index aee0450c54..462494e853 100644 --- a/tests/test_scoped_nodes.py +++ b/tests/test_scoped_nodes.py @@ -368,7 +368,7 @@ def test_default_value(self) -> None: def test_navigation(self) -> None: function = self.module["global_access"] self.assertEqual(function.statement(), function) - self.assertEqual(function.statement(future=True), function) + self.assertEqual(function.statement(), function) l_sibling = function.previous_sibling() # check taking parent if child is not a stmt self.assertIsInstance(l_sibling, nodes.Assign) @@ -1053,7 +1053,7 @@ def test_instance_special_attributes(self) -> None: def test_navigation(self) -> None: klass = self.module["YO"] self.assertEqual(klass.statement(), klass) - self.assertEqual(klass.statement(future=True), klass) + self.assertEqual(klass.statement(), klass) l_sibling = klass.previous_sibling() self.assertTrue(isinstance(l_sibling, nodes.FunctionDef), l_sibling) self.assertEqual(l_sibling.name, "global_access") @@ -2813,24 +2813,24 @@ def method(): ) function = module.body[0] assert function.frame() == function - assert function.frame(future=True) == function + assert function.frame() == function + assert function.body[0].frame() == function assert function.body[0].frame() == function - assert function.body[0].frame(future=True) == function class_node = module.body[1] assert class_node.frame() == class_node - assert class_node.frame(future=True) == class_node + assert class_node.frame() == class_node + assert class_node.body[0].frame() == class_node assert class_node.body[0].frame() == class_node - assert class_node.body[0].frame(future=True) == class_node assert class_node.body[1].frame() == class_node.body[1] - assert class_node.body[1].frame(future=True) == class_node.body[1] + assert class_node.body[1].frame() == class_node.body[1] lambda_assignment = module.body[2].value assert lambda_assignment.args.args[0].frame() == lambda_assignment - assert lambda_assignment.args.args[0].frame(future=True) == lambda_assignment + assert lambda_assignment.args.args[0].frame() == lambda_assignment assert module.frame() == module - assert module.frame(future=True) == module + assert module.frame() == module @staticmethod def test_non_frame_node(): @@ -2843,7 +2843,7 @@ def test_non_frame_node(): """ ) assert module.body[0].frame() == module - assert module.body[0].frame(future=True) == module + assert module.body[0].frame() == module assert module.body[1].value.locals["x"][0].frame() == module - assert module.body[1].value.locals["x"][0].frame(future=True) == module + assert module.body[1].value.locals["x"][0].frame() == module