Skip to content

Commit

Permalink
Pass an inference context to metaclass() when inferring an object type
Browse files Browse the repository at this point in the history
This should prevent a bunch of recursion errors happening in pylint.
Also refactor the inference of `IfExp` nodes to use separate contexts
for each potential branch.

Close pylint-dev/pylint#3152
Close pylint-dev/pylint#3159
  • Loading branch information
PCManticore committed Oct 18, 2019
1 parent 0088cc0 commit ed42e0c
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 6 deletions.
10 changes: 10 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ Release Date: TBA
Close PyCQA/pylint#3174


* Pass an inference context to `metaclass()` when inferring an object type

This should prevent a bunch of recursion errors happening in pylint.
Also refactor the inference of `IfExp` nodes to use separate contexts
for each potential branch.

Close PyCQA/pylint#3152
Close PyCQA/pylint#3159


What's New in astroid 2.3.1?
============================
Release Date: 2019-09-30
Expand Down
2 changes: 1 addition & 1 deletion astroid/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _object_type(node, context=None):
for inferred in node.infer(context=context):
if isinstance(inferred, scoped_nodes.ClassDef):
if inferred.newstyle:
metaclass = inferred.metaclass()
metaclass = inferred.metaclass(context=context)
if metaclass:
yield metaclass
continue
Expand Down
17 changes: 12 additions & 5 deletions astroid/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -916,21 +916,28 @@ def infer_ifexp(self, context=None):
depending on the condition.
"""
both_branches = False
# We use two separate contexts for evaluating lhs and rhs because
# evaluating lhs may leave some undesired entries in context.path
# which may not let us infer right value of rhs.

context = context or contextmod.InferenceContext()
lhs_context = contextmod.copy_context(context)
rhs_context = contextmod.copy_context(context)
try:
test = next(self.test.infer(context=context))
test = next(self.test.infer(context=context.clone()))
except exceptions.InferenceError:
both_branches = True
else:
if test is not util.Uninferable:
if test.bool_value():
yield from self.body.infer(context=context)
yield from self.body.infer(context=lhs_context)
else:
yield from self.orelse.infer(context=context)
yield from self.orelse.infer(context=rhs_context)
else:
both_branches = True
if both_branches:
yield from self.body.infer(context=context)
yield from self.orelse.infer(context=context)
yield from self.body.infer(context=lhs_context)
yield from self.orelse.infer(context=rhs_context)


nodes.IfExp._infer = infer_ifexp

0 comments on commit ed42e0c

Please sign in to comment.