Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-astroid for openSUSE:Factory checked in at 2021-11-15 15:26:20 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-astroid (Old) and /work/SRC/openSUSE:Factory/.python-astroid.new.1890 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-astroid" Mon Nov 15 15:26:20 2021 rev:33 rq:931287 version:2.8.5 Changes: -------- --- /work/SRC/openSUSE:Factory/python-astroid/python-astroid.changes 2021-10-30 23:14:29.351091800 +0200 +++ /work/SRC/openSUSE:Factory/.python-astroid.new.1890/python-astroid.changes 2021-11-15 15:27:58.321849907 +0100 @@ -1,0 +2,13 @@ +Sat Nov 13 20:22:06 UTC 2021 - Dirk M??ller <dmuel...@suse.com> + +- update to 2.8.5: + * Use more permissive versions for the ``typed-ast`` dependencie + (<2.0 instead of <1.5) + * Fix crash on inference of ``__len__``. + * Added missing ``kind`` (for ``Const``) and ``conversion`` + (for ``FormattedValue``) fields to repr. + * Fix crash with assignment expressions, nested if expressions + and filtering of statements + * Fix incorrect filtering of assignment expressions statements + +------------------------------------------------------------------- Old: ---- astroid-2.8.4-gh.tar.gz New: ---- astroid-2.8.5-gh.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-astroid.spec ++++++ --- /var/tmp/diff_new_pack.08OFef/_old 2021-11-15 15:27:58.893850068 +0100 +++ /var/tmp/diff_new_pack.08OFef/_new 2021-11-15 15:27:58.897850068 +0100 @@ -19,7 +19,7 @@ %define skip_python2 1 %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-astroid -Version: 2.8.4 +Version: 2.8.5 Release: 0 Summary: Representation of Python source as an AST for pylint License: LGPL-2.1-or-later ++++++ astroid-2.8.4-gh.tar.gz -> astroid-2.8.5-gh.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/.pre-commit-config.yaml new/astroid-2.8.5/.pre-commit-config.yaml --- old/astroid-2.8.4/.pre-commit-config.yaml 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/.pre-commit-config.yaml 2021-11-12 16:09:39.000000000 +0100 @@ -27,7 +27,7 @@ exclude: tests/testdata args: [--py36-plus] - repo: https://github.com/PyCQA/isort - rev: 5.9.3 + rev: 5.10.0 hooks: - id: isort exclude: tests/testdata @@ -36,7 +36,7 @@ hooks: - id: black-disable-checker - repo: https://github.com/psf/black - rev: 21.9b0 + rev: 21.10b0 hooks: - id: black args: [--safe, --quiet] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/ChangeLog new/astroid-2.8.5/ChangeLog --- old/astroid-2.8.4/ChangeLog 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/ChangeLog 2021-11-12 16:09:39.000000000 +0100 @@ -8,12 +8,33 @@ -What's New in astroid 2.8.5? +What's New in astroid 2.8.6? ============================ Release date: TBA +What's New in astroid 2.8.5? +============================ +Release date: 2021-11-12 + +* Use more permissive versions for the ``typed-ast`` dependencie (<2.0 instead of <1.5) + + Closes #1237 + +* Fix crash on inference of ``__len__``. + + Closes PyCQA/pylint#5244 + +* Added missing ``kind`` (for ``Const``) and ``conversion`` (for ``FormattedValue``) fields to repr. + +* Fix crash with assignment expressions, nested if expressions and filtering of statements + + Closes PyCQA/pylint#5178 + +* Fix incorrect filtering of assignment expressions statements + + What's New in astroid 2.8.4? ============================ Release date: 2021-10-25 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/astroid/__pkginfo__.py new/astroid-2.8.5/astroid/__pkginfo__.py --- old/astroid-2.8.4/astroid/__pkginfo__.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/astroid/__pkginfo__.py 2021-11-12 16:09:39.000000000 +0100 @@ -24,5 +24,5 @@ # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE -__version__ = "2.8.4" +__version__ = "2.8.5" version = __version__ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/astroid/brain/brain_typing.py new/astroid-2.8.5/astroid/brain/brain_typing.py --- old/astroid-2.8.4/astroid/brain/brain_typing.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/astroid/brain/brain_typing.py 2021-11-12 16:09:39.000000000 +0100 @@ -5,8 +5,8 @@ # Copyright (c) 2017 ??ukasz Rogalski <rogalski...@gmail.com> # Copyright (c) 2017 David Euresti <git...@euresti.com> # Copyright (c) 2018 Bryce Guinta <bryce.paul.gui...@gmail.com> -# Copyright (c) 2021 Redoubts <redou...@users.noreply.github.com> # Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> +# Copyright (c) 2021 Redoubts <redou...@users.noreply.github.com> # Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Copyright (c) 2021 Tim Martin <t...@asymptotic.co.uk> # Copyright (c) 2021 hippo91 <guillaume.peil...@gmail.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/astroid/decorators.py new/astroid-2.8.5/astroid/decorators.py --- old/astroid-2.8.4/astroid/decorators.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/astroid/decorators.py 2021-11-12 16:09:39.000000000 +0100 @@ -9,9 +9,9 @@ # Copyright (c) 2018 Bryce Guinta <bryce.paul.gui...@gmail.com> # Copyright (c) 2020-2021 hippo91 <guillaume.peil...@gmail.com> # Copyright (c) 2020 Ram Rachum <r...@rachum.com> +# Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> -# Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE @@ -197,7 +197,7 @@ ) ): warnings.warn( - f"'{arg}' will be a required attribute for " + f"'{arg}' will be a required argument for " f"'{args[0].__class__.__qualname__}.{func.__name__}' in astroid {astroid_version} " f"('{arg}' should be of type: '{type_annotation}')", DeprecationWarning, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/astroid/exceptions.py new/astroid-2.8.5/astroid/exceptions.py --- old/astroid-2.8.4/astroid/exceptions.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/astroid/exceptions.py 2021-11-12 16:09:39.000000000 +0100 @@ -5,8 +5,8 @@ # Copyright (c) 2016 Derek Gustafson <degus...@gmail.com> # Copyright (c) 2018 Bryce Guinta <bryce.paul.gui...@gmail.com> # Copyright (c) 2020-2021 hippo91 <guillaume.peil...@gmail.com> -# Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> +# Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Copyright (c) 2021 Andrew Haigh <he...@nelf.in> @@ -272,6 +272,24 @@ super().__init__(message=f"Parent not found on {target!r}.") +class StatementMissing(ParentMissingError): + """Raised when a call to node.statement() does not return a node. This is because + a node in the chain does not have a parent attribute and therefore does not + return a node for statement(). + + Standard attributes: + target: The node for which the parent lookup failed. + """ + + def __init__(self, target: "nodes.NodeNG") -> None: + # pylint: disable-next=bad-super-call + # https://github.com/PyCQA/pylint/issues/2903 + # https://github.com/PyCQA/astroid/pull/1217#discussion_r744149027 + super(ParentMissingError, self).__init__( + message=f"Statement not found on {target!r}" + ) + + # Backwards-compatibility aliases OperationError = util.BadOperationMessage UnaryOperationError = util.BadUnaryOperationMessage diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/astroid/helpers.py new/astroid-2.8.5/astroid/helpers.py --- old/astroid-2.8.4/astroid/helpers.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/astroid/helpers.py 2021-11-12 16:09:39.000000000 +0100 @@ -5,6 +5,7 @@ # Copyright (c) 2020 Simon Hewitt <s...@sjhewitt.co.uk> # Copyright (c) 2020 Bryce Guinta <bryce.gui...@protonmail.com> # Copyright (c) 2020 Ram Rachum <r...@rachum.com> +# Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> # Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 David Liu <da...@cs.toronto.edu> # Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> @@ -258,7 +259,7 @@ if ( isinstance(node_frame, scoped_nodes.FunctionDef) and node_frame.name == "__len__" - and inferred_node is not None + and hasattr(inferred_node, "_proxied") and inferred_node._proxied == node_frame.parent ): message = ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/astroid/nodes/node_classes.py new/astroid-2.8.5/astroid/nodes/node_classes.py --- old/astroid-2.8.4/astroid/nodes/node_classes.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/astroid/nodes/node_classes.py 2021-11-12 16:09:39.000000000 +0100 @@ -24,8 +24,8 @@ # Copyright (c) 2020 Raphael Gaschignard <raph...@rtpg.co> # Copyright (c) 2020 Bryce Guinta <bryce.gui...@protonmail.com> # Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> -# Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> +# Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 David Liu <da...@cs.toronto.edu> # Copyright (c) 2021 Alphadelta14 <alpha@alphaservcomputing.solutions> # Copyright (c) 2021 Andrew Haigh <he...@nelf.in> @@ -486,8 +486,28 @@ continue if isinstance(assign_type, NamedExpr): - _stmts = [node] - continue + # If the NamedExpr is in an if statement we do some basic control flow inference + if_parent = _get_if_statement_ancestor(assign_type) + if if_parent: + # If the if statement is within another if statement we append the node + # to possible statements + if _get_if_statement_ancestor(if_parent): + optional_assign = False + _stmts.append(node) + _stmt_parents.append(stmt.parent) + # If the if statement is first-level and not within an orelse block + # we know that it will be evaluated + elif not if_parent.is_orelse: + _stmts = [node] + _stmt_parents = [stmt.parent] + # Else we do not known enough about the control flow to be 100% certain + # and we append to possible statements + else: + _stmts.append(node) + _stmt_parents.append(stmt.parent) + else: + _stmts = [node] + _stmt_parents = [stmt.parent] # XXX comment various branches below!!! try: @@ -534,7 +554,7 @@ # An AssignName node overrides previous assignments if: # 1. node's statement always assigns # 2. node and self are in the same block (i.e., has the same parent as self) - if isinstance(node, AssignName): + if isinstance(node, (NamedExpr, AssignName)): if isinstance(stmt, ExceptHandler): # If node's statement is an ExceptHandler, then it is the variable # bound to the caught exception. If self is not contained within @@ -1846,7 +1866,7 @@ <Const.bytes l.1 at 0x7f23b2e35a20>] """ - _other_fields = ("value",) + _other_fields = ("value", "kind") def __init__( self, @@ -2798,6 +2818,9 @@ self.orelse: typing.List[NodeNG] = [] """The contents of the ``else`` block.""" + self.is_orelse: bool = False + """Whether the if-statement is the orelse-block of another if statement.""" + super().__init__(lineno=lineno, col_offset=col_offset, parent=parent) def postinit( @@ -2819,6 +2842,8 @@ self.body = body if orelse is not None: self.orelse = orelse + if isinstance(self.parent, If) and self in self.parent.orelse: + self.is_orelse = True @decorators.cachedproperty def blockstart_tolineno(self): @@ -4076,6 +4101,7 @@ """ _astroid_fields = ("value", "format_spec") + _other_fields = ("conversion",) def __init__( self, @@ -4196,6 +4222,11 @@ _astroid_fields = ("target", "value") + optional_assign = True + """Whether this node optionally assigns a variable. + + Since NamedExpr are not always called they do not always assign.""" + def __init__( self, lineno: Optional[int] = None, @@ -4794,3 +4825,11 @@ if isinstance(parent, Decorators): return True return False + + +def _get_if_statement_ancestor(node: NodeNG) -> Optional[If]: + """Return the first parent node that is an If node (or None)""" + for parent in node.node_ancestors(): + if isinstance(parent, If): + return parent + return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/astroid/nodes/node_ng.py new/astroid-2.8.5/astroid/nodes/node_ng.py --- old/astroid-2.8.4/astroid/nodes/node_ng.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/astroid/nodes/node_ng.py 2021-11-12 16:09:39.000000000 +0100 @@ -1,5 +1,7 @@ import pprint +import sys import typing +import warnings from functools import singledispatch as _singledispatch from typing import ( TYPE_CHECKING, @@ -10,6 +12,7 @@ Type, TypeVar, Union, + cast, overload, ) @@ -18,6 +21,7 @@ AstroidError, InferenceError, ParentMissingError, + StatementMissing, UseInferenceDefault, ) from astroid.manager import AstroidManager @@ -27,6 +31,17 @@ if TYPE_CHECKING: from astroid import nodes +if sys.version_info >= (3, 6, 2): + from typing import NoReturn +else: + from typing_extensions import NoReturn + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal + + # Types for 'NodeNG.nodes_of_class()' T_Nodes = TypeVar("T_Nodes", bound="NodeNG") T_Nodes2 = TypeVar("T_Nodes2", bound="NodeNG") @@ -248,15 +263,41 @@ return True return False - def statement(self): + @overload + def statement( + self, *, future: Literal[None] = ... + ) -> Union["nodes.Statement", "nodes.Module"]: + ... + + @overload + def statement(self, *, future: Literal[True]) -> "nodes.Statement": + ... + + def statement( + self, *, future: Literal[None, True] = None + ) -> Union["nodes.Statement", "nodes.Module", NoReturn]: """The first parent node, including self, marked as statement node. - :returns: The first parent statement. - :rtype: NodeNG + 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 """ if self.is_statement: - return self - return self.parent.statement() + return cast("nodes.Statement", self) + if not self.parent: + 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. AttributeError will no longer be raised. " + "This behaviour can already be triggered " + "by passing 'future=True' to a statement() call.", + DeprecationWarning, + ) + raise AttributeError(f"{self} object has no attribute 'parent'") + return self.parent.statement(future=future) def frame( self, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/astroid/nodes/scoped_nodes.py new/astroid-2.8.5/astroid/nodes/scoped_nodes.py --- old/astroid-2.8.4/astroid/nodes/scoped_nodes.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/astroid/nodes/scoped_nodes.py 2021-11-12 16:09:39.000000000 +0100 @@ -44,8 +44,10 @@ import io import itertools import os +import sys import typing -from typing import List, Optional, TypeVar +import warnings +from typing import List, Optional, TypeVar, Union, overload from astroid import bases from astroid import decorators as decorators_mod @@ -65,6 +67,7 @@ InconsistentMroError, InferenceError, MroError, + StatementMissing, TooManyLevelsError, ) from astroid.interpreter.dunder_lookup import lookup @@ -72,6 +75,18 @@ from astroid.manager import AstroidManager from astroid.nodes import Arguments, Const, node_classes +if sys.version_info >= (3, 6, 2): + from typing import NoReturn +else: + from typing_extensions import NoReturn + + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from typing_extensions import Literal + + ITER_METHODS = ("__iter__", "__getitem__") EXCEPTION_BASE_CLASSES = frozenset({"Exception", "BaseException"}) objects = util.lazy_import("objects") @@ -637,12 +652,34 @@ """ return self.file is not None and self.file.endswith(".py") - def statement(self): + @overload + def statement(self, *, future: Literal[None] = ...) -> "Module": + ... + + @overload + def statement(self, *, future: Literal[True]) -> NoReturn: + ... + + def statement( + self, *, future: Literal[None, True] = None + ) -> Union[NoReturn, "Module"]: """The first parent node, including self, marked as statement node. - :returns: The first parent statement. - :rtype: NodeNG + 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 """ + 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, + ) return self def previous_sibling(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/setup.cfg new/astroid-2.8.5/setup.cfg --- old/astroid-2.8.4/setup.cfg 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/setup.cfg 2021-11-12 16:09:39.000000000 +0100 @@ -39,7 +39,7 @@ lazy_object_proxy>=1.4.0 wrapt>=1.11,<1.14 setuptools>=20.0 - typed-ast>=1.4.0,<1.5;implementation_name=="cpython" and python_version<"3.8" + typed-ast>=1.4.0,<2.0;implementation_name=="cpython" and python_version<"3.8" typing-extensions>=3.10;python_version<"3.10" python_requires = ~=3.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/tbump.toml new/astroid-2.8.5/tbump.toml --- old/astroid-2.8.4/tbump.toml 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/tbump.toml 2021-11-12 16:09:39.000000000 +0100 @@ -1,7 +1,7 @@ github_url = "https://github.com/PyCQA/astroid" [version] -current = "2.8.4" +current = "2.8.5" regex = ''' ^(?P<major>0|[1-9]\d*) \. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/tests/unittest_brain.py new/astroid-2.8.5/tests/unittest_brain.py --- old/astroid-2.8.4/tests/unittest_brain.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/tests/unittest_brain.py 2021-11-12 16:09:39.000000000 +0100 @@ -24,12 +24,12 @@ # Copyright (c) 2019 Grygorii Iermolenko <gyermole...@gmail.com> # Copyright (c) 2020 David Gilman <davidgilm...@gmail.com> # Copyright (c) 2020 Peter Kolbus <peter.kol...@gmail.com> -# Copyright (c) 2021 Joshua Cannon <joshua.can...@ni.com> +# Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> # Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> +# Copyright (c) 2021 Joshua Cannon <joshua.can...@ni.com> # Copyright (c) 2021 Craig Franklin <craigjfrank...@gmail.com> # Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Copyright (c) 2021 Jonathan Striebel <jstrie...@users.noreply.github.com> -# Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> # Copyright (c) 2021 Dimitri Prybysh <dm...@yandex.ru> # Copyright (c) 2021 David Liu <da...@cs.toronto.edu> # Copyright (c) 2021 pre-commit-ci[bot] <b...@noreply.github.com> @@ -3112,6 +3112,8 @@ def test_no_recursionerror_on_self_referential_length_check() -> None: """ Regression test for https://github.com/PyCQA/astroid/issues/777 + + This test should only raise an InferenceError and no RecursionError. """ with pytest.raises(InferenceError): node = astroid.extract_node( @@ -3123,6 +3125,57 @@ """ ) assert isinstance(node, nodes.NodeNG) + node.inferred() + + +def test_inference_on_outer_referential_length_check() -> None: + """ + Regression test for https://github.com/PyCQA/pylint/issues/5244 + See also https://github.com/PyCQA/astroid/pull/1234 + + This test should succeed without any error. + """ + node = astroid.extract_node( + """ + class A: + def __len__(self) -> int: + return 42 + + class Crash: + def __len__(self) -> int: + a = A() + return len(a) + + len(Crash()) #@ + """ + ) + inferred = node.inferred() + assert len(inferred) == 1 + assert isinstance(inferred[0], nodes.Const) + assert inferred[0].value == 42 + + +def test_no_attributeerror_on_self_referential_length_check() -> None: + """ + Regression test for https://github.com/PyCQA/pylint/issues/5244 + See also https://github.com/PyCQA/astroid/pull/1234 + + This test should only raise an InferenceError and no AttributeError. + """ + with pytest.raises(InferenceError): + node = astroid.extract_node( + """ + class MyClass: + def some_func(self): + return lambda: 42 + + def __len__(self): + return len(self.some_func()) + + len(MyClass()) #@ + """ + ) + assert isinstance(node, nodes.NodeNG) node.inferred() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/tests/unittest_builder.py new/astroid-2.8.5/tests/unittest_builder.py --- old/astroid-2.8.4/tests/unittest_builder.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/tests/unittest_builder.py 2021-11-12 16:09:39.000000000 +0100 @@ -12,8 +12,8 @@ # Copyright (c) 2019 Ashley Whetter <ash...@awhetter.co.uk> # Copyright (c) 2019 Hugo van Kemenade <hug...@users.noreply.github.com> # Copyright (c) 2020-2021 hippo91 <guillaume.peil...@gmail.com> -# Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> +# Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Copyright (c) 2021 Andrew Haigh <he...@nelf.in> # Copyright (c) 2021 pre-commit-ci[bot] <b...@noreply.github.com> @@ -38,6 +38,7 @@ AstroidSyntaxError, AttributeInferenceError, InferenceError, + StatementMissing, ) from astroid.nodes.scoped_nodes import Module @@ -614,7 +615,11 @@ self.assertEqual(module.package, 0) self.assertFalse(module.is_statement) self.assertEqual(module.statement(), module) - self.assertEqual(module.statement(), module) + with pytest.warns(DeprecationWarning) as records: + module.statement() + assert len(records) == 1 + with self.assertRaises(StatementMissing): + module.statement(future=True) def test_module_locals(self) -> None: """test the 'locals' dictionary of an astroid module""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/tests/unittest_inference.py new/astroid-2.8.5/tests/unittest_inference.py --- old/astroid-2.8.4/tests/unittest_inference.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/tests/unittest_inference.py 2021-11-12 16:09:39.000000000 +0100 @@ -26,9 +26,9 @@ # Copyright (c) 2020 Peter Kolbus <peter.kol...@gmail.com> # Copyright (c) 2020 Karthikeyan Singaravelan <tir.kar...@gmail.com> # Copyright (c) 2020 Bryce Guinta <bryce.gui...@protonmail.com> +# Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> -# Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Copyright (c) 2021 Andrew Haigh <he...@nelf.in> # Copyright (c) 2021 doranid <dda...@gmail.com> # Copyright (c) 2021 Francis Charette Migneault <francis.charette.mignea...@gmail.com> @@ -1191,7 +1191,11 @@ # (__name__ == '__main__') and through pytest (__name__ == # 'unittest_inference') self.assertEqual( - value, [f"Instance of {__name__}.myarray", "Const.int(value=5)"] + value, + [ + f"Instance of {__name__}.myarray", + "Const.int(value=5,\n kind=None)", + ], ) def test_nonregr_lambda_arg(self) -> None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/tests/unittest_nodes.py new/astroid-2.8.5/tests/unittest_nodes.py --- old/astroid-2.8.4/tests/unittest_nodes.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/tests/unittest_nodes.py 2021-11-12 16:09:39.000000000 +0100 @@ -55,6 +55,7 @@ AstroidBuildingError, AstroidSyntaxError, AttributeInferenceError, + StatementMissing, ) from astroid.nodes.node_classes import ( AssignAttr, @@ -626,6 +627,12 @@ self.assertIs(node.value, value) self.assertTrue(node._proxied.parent) self.assertEqual(node._proxied.root().name, value.__class__.__module__) + with self.assertRaises(AttributeError): + with pytest.warns(DeprecationWarning) as records: + node.statement() + assert len(records) == 1 + with self.assertRaises(StatementMissing): + node.statement(future=True) def test_none(self) -> None: self._test(None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/tests/unittest_regrtest.py new/astroid-2.8.5/tests/unittest_regrtest.py --- old/astroid-2.8.4/tests/unittest_regrtest.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/tests/unittest_regrtest.py 2021-11-12 16:09:39.000000000 +0100 @@ -10,8 +10,8 @@ # Copyright (c) 2019, 2021 hippo91 <guillaume.peil...@gmail.com> # Copyright (c) 2019 Ashley Whetter <ash...@awhetter.co.uk> # Copyright (c) 2020 David Gilman <davidgilm...@gmail.com> -# Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Dani??l van Noord <13665637+danielno...@users.noreply.github.com> +# Copyright (c) 2021 Pierre Sassoulas <pierre.sassou...@gmail.com> # Copyright (c) 2021 Marc Mueller <30130371+cdc...@users.noreply.github.com> # Copyright (c) 2021 Andrew Haigh <he...@nelf.in> @@ -22,8 +22,11 @@ import textwrap import unittest +import pytest + from astroid import MANAGER, Instance, nodes, test_utils from astroid.builder import AstroidBuilder, extract_node +from astroid.const import PY38_PLUS from astroid.exceptions import InferenceError from astroid.raw_building import build_module @@ -156,6 +159,38 @@ base = next(result._proxied.bases[0].infer()) self.assertEqual(base.name, "int") + @pytest.mark.skipif(not PY38_PLUS, reason="needs assignment expressions") + def test_filter_stmts_nested_if(self) -> None: + builder = AstroidBuilder() + data = """ +def test(val): + variable = None + + if val == 1: + variable = "value" + if variable := "value": + pass + + elif val == 2: + variable = "value_two" + variable = "value_two" + + return variable +""" + module = builder.string_build(data, __name__, __file__) + test_func = module["test"] + result = list(test_func.infer_call_result(module)) + assert len(result) == 3 + assert isinstance(result[0], nodes.Const) + assert result[0].value is None + assert result[0].lineno == 3 + assert isinstance(result[1], nodes.Const) + assert result[1].value == "value" + assert result[1].lineno == 7 + assert isinstance(result[1], nodes.Const) + assert result[2].value == "value_two" + assert result[2].lineno == 12 + def test_ancestors_patching_class_recursion(self) -> None: node = AstroidBuilder().string_build( textwrap.dedent( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/astroid-2.8.4/tests/unittest_scoped_nodes.py new/astroid-2.8.5/tests/unittest_scoped_nodes.py --- old/astroid-2.8.4/tests/unittest_scoped_nodes.py 2021-10-25 22:02:34.000000000 +0200 +++ new/astroid-2.8.5/tests/unittest_scoped_nodes.py 2021-11-12 16:09:39.000000000 +0100 @@ -323,6 +323,7 @@ def test_navigation(self) -> None: function = self.module["global_access"] self.assertEqual(function.statement(), function) + self.assertEqual(function.statement(future=True), function) l_sibling = function.previous_sibling() # check taking parent if child is not a stmt self.assertIsInstance(l_sibling, nodes.Assign) @@ -821,6 +822,7 @@ def test_navigation(self) -> None: klass = self.module["YO"] self.assertEqual(klass.statement(), klass) + self.assertEqual(klass.statement(future=True), klass) l_sibling = klass.previous_sibling() self.assertTrue(isinstance(l_sibling, nodes.FunctionDef), l_sibling) self.assertEqual(l_sibling.name, "global_access")