Skip to content

Commit

Permalink
igetattr raises InferenceError on re-inference of the same ob…
Browse files Browse the repository at this point in the history
…ject

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 pylint-dev#663
  • Loading branch information
PCManticore committed Apr 9, 2019
1 parent c87bea1 commit 55076ca
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
11 changes: 11 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion astroid/bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,11 @@ def igetattr(self, name, context=None):
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)
Expand Down
25 changes: 25 additions & 0 deletions astroid/tests/unittest_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -5188,5 +5188,30 @@ class Cls:
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()

0 comments on commit 55076ca

Please sign in to comment.