diff options
author | Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com> | 2021-11-08 13:25:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-08 12:25:14 +0100 |
commit | e1ecb6d3d5a6555a807ab3db0f2f938d8d73e95c (patch) | |
tree | ec71ec435466dca43936f5418a3c9663bc2e0e6a | |
parent | b62f243b16b7f435c8be869577959e95a7927a91 (diff) | |
download | astroid-e1ecb6d3d5a6555a807ab3db0f2f938d8d73e95c.tar.gz |
Fix crash on inference of __len__ (#1234)
Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | astroid/helpers.py | 2 | ||||
-rw-r--r-- | tests/unittest_brain.py | 53 |
3 files changed, 58 insertions, 1 deletions
@@ -12,6 +12,10 @@ What's New in astroid 2.8.5? ============================ Release date: TBA +* Fix crash on inference of ``__len__``. + + Closes PyCQA/pylint#5244 + * Added missing ``kind`` (for ``Const``) and ``conversion`` (for ``FormattedValue``) fields to repr. diff --git a/astroid/helpers.py b/astroid/helpers.py index 567b2e04..32fb796e 100644 --- a/astroid/helpers.py +++ b/astroid/helpers.py @@ -258,7 +258,7 @@ def object_len(node, context=None): 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 --git a/tests/unittest_brain.py b/tests/unittest_brain.py index d3bf12bc..a33647fe 100644 --- a/tests/unittest_brain.py +++ b/tests/unittest_brain.py @@ -3112,6 +3112,8 @@ def test_str_and_bytes(code, expected_class, expected_value): 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( @@ -3126,5 +3128,56 @@ def test_no_recursionerror_on_self_referential_length_check() -> None: 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() + + if __name__ == "__main__": unittest.main() |