diff options
author | HoverHell <hoverhell@gmail.com> | 2018-04-24 13:10:26 +0300 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2018-04-24 12:10:26 +0200 |
commit | ceeee09743079d07ffc3918969ab203f766b29e0 (patch) | |
tree | 1276a95208f7294b5c2eafadfb148ad39ccc2293 /astroid/protocols.py | |
parent | 8575ac1c0bd247bc314f6752355d1ea647dec911 (diff) | |
download | astroid-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.
Diffstat (limited to 'astroid/protocols.py')
-rw-r--r-- | astroid/protocols.py | 39 |
1 files changed, 24 insertions, 15 deletions
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 |