diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2019-04-09 16:11:16 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2019-04-09 16:17:28 +0200 |
commit | 55076ca06018dd3a5d2748610c5aa81efbb96563 (patch) | |
tree | 67f7d301e8eacb7940b33b19dcf135bdeedb6bcc | |
parent | c87bea17b9d389d06edf0b7e7e7e435b007c94d5 (diff) | |
download | astroid-git-55076ca06018dd3a5d2748610c5aa81efbb96563.tar.gz |
``igetattr`` raises ``InferenceError`` on re-inference of the same object
This prevents ``StopIteration`` from leaking when we encounter the same
object in the current context, which could result in various ``RuntimeErrors``
leaking in other parts of the inference.
Until we get a global context per inference, the solution is sort of a hack,
as with the suggested global context improvement, we could theoretically
reuse the same inference object.
Close #663
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | astroid/bases.py | 6 | ||||
-rw-r--r-- | astroid/tests/unittest_inference.py | 25 |
3 files changed, 41 insertions, 1 deletions
@@ -6,6 +6,17 @@ What's New in astroid 2.3.0? ============================ Release Date: TBA +* ``igetattr`` raises ``InferenceError`` on re-inference of the same object + + This prevents ``StopIteration`` from leaking when we encounter the same + object in the current context, which could result in various ``RuntimeErrors`` + leaking in other parts of the inference. + Until we get a global context per inference, the solution is sort of a hack, + as with the suggested global context improvement, we could theoretically + reuse the same inference object. + + Close #663 + * Variable annotations can no longer be retrieved with `ClassDef.getattr` Unless they have an attached value, class variable annotations can no longer diff --git a/astroid/bases.py b/astroid/bases.py index 077a4a36..caf7d882 100644 --- a/astroid/bases.py +++ b/astroid/bases.py @@ -211,7 +211,11 @@ class BaseInstance(Proxy): try: # avoid recursively inferring the same attr on the same class if context.push((self._proxied, name)): - return + raise exceptions.InferenceError( + message="Cannot infer the same attribute again", + node=self, + context=context, + ) # XXX frame should be self._proxied, or not ? get_attr = self.getattr(name, context, lookupclass=False) diff --git a/astroid/tests/unittest_inference.py b/astroid/tests/unittest_inference.py index c52926a1..0dd23d87 100644 --- a/astroid/tests/unittest_inference.py +++ b/astroid/tests/unittest_inference.py @@ -5188,5 +5188,30 @@ def test_cannot_getattr_ann_assigns(): assert len(values) == 1 +def test_prevent_recursion_error_in_igetattr_and_context_manager_inference(): + code = """ + class DummyContext(object): + def method(self, msg): # pylint: disable=C0103 + pass + def __enter__(self): + pass + def __exit__(self, ex_type, ex_value, ex_tb): + return True + + class CallMeMaybe(object): + def __call__(self): + while False: + with DummyContext() as con: + f_method = con.method + break + + with DummyContext() as con: + con #@ + f_method = con.method + """ + node = extract_node(code) + assert next(node.infer()) is util.Uninferable + + if __name__ == "__main__": unittest.main() |