summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoverHell <hoverhell@gmail.com>2018-04-24 13:10:26 +0300
committerClaudiu Popa <pcmanticore@gmail.com>2018-04-24 12:10:26 +0200
commitceeee09743079d07ffc3918969ab203f766b29e0 (patch)
tree1276a95208f7294b5c2eafadfb148ad39ccc2293
parent8575ac1c0bd247bc314f6752355d1ea647dec911 (diff)
downloadastroid-git-ceeee09743079d07ffc3918969ab203f766b29e0.tar.gz
Fix StopIteration raising for python3.7 (#534)
Because we don't support Python 2 any longer in the master branch, we can return values from generators to signal that we want to throw a StopIteration, without actually raising the StopIteration itself.
-rw-r--r--astroid/decorators.py5
-rw-r--r--astroid/inference.py22
-rw-r--r--astroid/node_classes.py6
-rw-r--r--astroid/protocols.py39
-rw-r--r--astroid/scoped_nodes.py2
5 files changed, 44 insertions, 30 deletions
diff --git a/astroid/decorators.py b/astroid/decorators.py
index baec43b9..a0625f2c 100644
--- a/astroid/decorators.py
+++ b/astroid/decorators.py
@@ -99,9 +99,8 @@ def path_wrapper(func):
# Explicit StopIteration to return error information, see
# comment in raise_if_nothing_inferred.
if error.args:
- raise StopIteration(error.args[0])
- else:
- raise StopIteration
+ return error.args[0]
+ return
return wrapped
diff --git a/astroid/inference.py b/astroid/inference.py
index a0a933eb..5467736e 100644
--- a/astroid/inference.py
+++ b/astroid/inference.py
@@ -202,7 +202,7 @@ def infer_call(self, context=None):
continue
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, context=context))
+ return dict(node=self, context=context)
nodes.Call._infer = infer_call
@@ -292,7 +292,7 @@ def infer_attribute(self, context=None):
context.boundnode = None
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, context=context))
+ return dict(node=self, context=context)
nodes.Attribute._infer = decorators.path_wrapper(infer_attribute)
nodes.AssignAttr.infer_lhs = infer_attribute # # won't work with a path wrapper
@@ -324,12 +324,18 @@ def infer_subscript(self, context=None):
handle each supported index type accordingly.
"""
- value = next(self.value.infer(context))
+ try:
+ value = next(self.value.infer(context))
+ except StopIteration:
+ return
if value is util.Uninferable:
yield util.Uninferable
return
- index = next(self.slice.infer(context))
+ try:
+ index = next(self.slice.infer(context))
+ except StopIteration:
+ return
if index is util.Uninferable:
yield util.Uninferable
return
@@ -367,7 +373,7 @@ def infer_subscript(self, context=None):
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, context=context))
+ return dict(node=self, context=context)
nodes.Subscript._infer = decorators.path_wrapper(infer_subscript)
nodes.Subscript.infer_lhs = infer_subscript
@@ -425,7 +431,7 @@ def _infer_boolop(self, context=None):
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, context=context))
+ return dict(node=self, context=context)
nodes.BoolOp._infer = _infer_boolop
@@ -506,7 +512,7 @@ def infer_unaryop(self, context=None):
yield inferred
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, context=context))
+ return dict(node=self, context=context)
nodes.UnaryOp._infer_unaryop = _infer_unaryop
nodes.UnaryOp._infer = infer_unaryop
@@ -822,7 +828,7 @@ def instance_getitem(self, index, context=None):
new_context.callcontext = contextmod.CallContext(args=[index])
new_context.boundnode = self
- method = next(self.igetattr('__getitem__', context=context))
+ method = next(self.igetattr('__getitem__', context=context), None)
if not isinstance(method, bases.BoundMethod):
raise exceptions.InferenceError(
'Could not find __getitem__ for {node!r}.',
diff --git a/astroid/node_classes.py b/astroid/node_classes.py
index c9b70102..4f2f439d 100644
--- a/astroid/node_classes.py
+++ b/astroid/node_classes.py
@@ -46,14 +46,14 @@ def unpack_infer(stmt, context=None):
yield inferred_elt
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=stmt, context=context))
+ return dict(node=stmt, context=context)
# if inferred is a final node, return it and stop
inferred = next(stmt.infer(context))
if inferred is stmt:
yield inferred
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=stmt, context=context))
+ return dict(node=stmt, context=context)
# else, infer recursively, except Uninferable object that should be returned as is
for inferred in stmt.infer(context):
if inferred is util.Uninferable:
@@ -61,7 +61,7 @@ def unpack_infer(stmt, context=None):
else:
for inf_inf in unpack_infer(inferred, context):
yield inf_inf
- raise StopIteration(dict(node=stmt, context=context))
+ return dict(node=stmt, context=context)
def are_exclusive(stmt1, stmt2, exceptions=None): # pylint: disable=redefined-outer-name
diff --git a/astroid/protocols.py b/astroid/protocols.py
index bd1d594f..7ae93976 100644
--- a/astroid/protocols.py
+++ b/astroid/protocols.py
@@ -246,8 +246,8 @@ def _resolve_looppart(parts, asspath, context):
def for_assigned_stmts(self, node=None, context=None, asspath=None):
if isinstance(self, nodes.AsyncFor) or getattr(self, 'is_async', False):
# Skip inferring of async code for now
- raise StopIteration(dict(node=self, unknown=node,
- assign_path=asspath, context=context))
+ return dict(node=self, unknown=node,
+ assign_path=asspath, context=context)
if asspath is None:
for lst in self.iter.infer(context):
if isinstance(lst, (nodes.Tuple, nodes.List)):
@@ -259,8 +259,8 @@ def for_assigned_stmts(self, node=None, context=None, asspath=None):
yield inferred
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, unknown=node,
- assign_path=asspath, context=context))
+ return dict(node=self, unknown=node,
+ assign_path=asspath, context=context)
nodes.For.assigned_stmts = for_assigned_stmts
nodes.Comprehension.assigned_stmts = for_assigned_stmts
@@ -359,8 +359,8 @@ def assign_assigned_stmts(self, node=None, context=None, asspath=None):
yield inferred
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, unknown=node,
- assign_path=asspath, context=context))
+ return dict(node=self, unknown=node,
+ assign_path=asspath, context=context)
def assign_annassigned_stmts(self, node=None, context=None, asspath=None):
@@ -414,8 +414,8 @@ def excepthandler_assigned_stmts(self, node=None, context=None, asspath=None):
yield assigned
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, unknown=node,
- assign_path=asspath, context=context))
+ return dict(node=self, unknown=node,
+ assign_path=asspath, context=context)
nodes.ExceptHandler.assigned_stmts = excepthandler_assigned_stmts
@@ -424,7 +424,7 @@ nodes.ExceptHandler.assigned_stmts = excepthandler_assigned_stmts
def _infer_context_manager(self, mgr, context):
try:
inferred = next(mgr.infer(context=context))
- except exceptions.InferenceError:
+ except (StopIteration, exceptions.InferenceError):
return
if isinstance(inferred, bases.Generator):
# Check if it is decorated with contextlib.contextmanager.
@@ -432,7 +432,10 @@ def _infer_context_manager(self, mgr, context):
if not func.decorators:
return
for decorator_node in func.decorators.nodes:
- decorator = next(decorator_node.infer(context))
+ try:
+ decorator = next(decorator_node.infer(context))
+ except StopIteration:
+ return
if isinstance(decorator, nodes.FunctionDef):
if decorator.qname() == _CONTEXTLIB_MGR:
break
@@ -446,7 +449,8 @@ def _infer_context_manager(self, mgr, context):
possible_yield_points = func.nodes_of_class(nodes.Yield)
# Ignore yields in nested functions
yield_point = next((node for node in possible_yield_points
- if node.scope() == func), None)
+ if node.scope() == func),
+ None)
if yield_point:
if not yield_point.value:
# TODO(cpopa): an empty yield. Should be wrapped to Const.
@@ -460,7 +464,7 @@ def _infer_context_manager(self, mgr, context):
elif isinstance(inferred, bases.Instance):
try:
enter = next(inferred.igetattr('__enter__', context=context))
- except (exceptions.InferenceError, exceptions.AttributeInferenceError):
+ except (StopIteration, exceptions.InferenceError, exceptions.AttributeInferenceError):
return
if not isinstance(enter, bases.BoundMethod):
return
@@ -496,7 +500,10 @@ def with_assigned_stmts(self, node=None, context=None, asspath=None):
context: TODO
asspath: TODO
"""
- mgr = next(mgr for (mgr, vars) in self.items if vars == node)
+ try:
+ mgr = next(mgr for (mgr, vars) in self.items if vars == node)
+ except StopIteration:
+ return
if asspath is None:
for result in _infer_context_manager(self, mgr, context):
yield result
@@ -525,8 +532,8 @@ def with_assigned_stmts(self, node=None, context=None, asspath=None):
yield obj
# Explicit StopIteration to return error information, see comment
# in raise_if_nothing_inferred.
- raise StopIteration(dict(node=self, unknown=node,
- assign_path=asspath, context=context))
+ return dict(node=self, unknown=node,
+ assign_path=asspath, context=context)
nodes.With.assigned_stmts = with_assigned_stmts
@@ -561,6 +568,8 @@ def starred_assigned_stmts(self, node=None, context=None, asspath=None):
context = contextmod.InferenceContext()
try:
rhs = next(value.infer(context))
+ except StopIteration:
+ return
except exceptions.InferenceError:
yield util.Uninferable
return
diff --git a/astroid/scoped_nodes.py b/astroid/scoped_nodes.py
index 31494adc..f4975d5e 100644
--- a/astroid/scoped_nodes.py
+++ b/astroid/scoped_nodes.py
@@ -2542,7 +2542,7 @@ class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG,
if not values:
# Stop the iteration, because the class
# has an empty list of slots.
- raise StopIteration(values)
+ return values
for elt in values:
try: