summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2019-04-09 16:11:16 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2019-04-09 16:17:28 +0200
commit55076ca06018dd3a5d2748610c5aa81efbb96563 (patch)
tree67f7d301e8eacb7940b33b19dcf135bdeedb6bcc
parentc87bea17b9d389d06edf0b7e7e7e435b007c94d5 (diff)
downloadastroid-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--ChangeLog11
-rw-r--r--astroid/bases.py6
-rw-r--r--astroid/tests/unittest_inference.py25
3 files changed, 41 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index a691d803..79ebc06e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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()