summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAttila Oláh <attilaolah@gmail.com>2013-07-05 13:55:09 +0200
committerAttila Oláh <attilaolah@gmail.com>2013-07-05 13:55:09 +0200
commitb373a73a7fcf05c29255f60c58f0b84094f03c81 (patch)
tree7c2a6cef7468115abf4a670d162473e55e22ac9d
parentc57a450f15e9f61d169b3178f5ed21564ce28257 (diff)
downloadpyflakes-b373a73a7fcf05c29255f60c58f0b84094f03c81.tar.gz
catch return with arguments inside generator (fixes #1198132)
-rw-r--r--pyflakes/checker.py46
-rw-r--r--pyflakes/messages.py7
2 files changed, 53 insertions, 0 deletions
diff --git a/pyflakes/checker.py b/pyflakes/checker.py
index d59b8c9..eb68015 100644
--- a/pyflakes/checker.py
+++ b/pyflakes/checker.py
@@ -587,6 +587,38 @@ class Checker(object):
self.offset = node_offset
self.popScope()
+ def findReturnWithArgument(self, node):
+ """
+ Finds and returns a return statment that has an argument.
+
+ Note that we should use node.returns in Python 3, but this method is
+ never called in Python 3 so we don't bother checking.
+ """
+ for item in node.body:
+ if isinstance(item, ast.Return) and item.value:
+ return item
+ if hasattr(item, 'body'):
+ found = self.findReturnWithArgument(item)
+ if found is not None:
+ return found
+
+ def isGenerator(self, node):
+ """
+ Checks whether a function is a generator by looking for a yield
+ statement or expression.
+ """
+ if not isinstance(node.body, list):
+ # lambdas can not be generators
+ return False
+ for item in node.body:
+ if isinstance(item, (ast.Assign, ast.Expr)):
+ if isinstance(item.value, ast.Yield):
+ return True
+ if hasattr(item, 'body'):
+ if self.isGenerator(item):
+ return True
+ return False
+
def ignore(self, node):
pass
@@ -760,7 +792,21 @@ class Checker(object):
"""
for name, binding in self.scope.unusedAssignments():
self.report(messages.UnusedVariable, binding.source, name)
+
self.deferAssignment(checkUnusedAssignments)
+
+ if PY2:
+ def checkReturnWithArgumentInsideGenerator():
+ """
+ Check to see if there are any return statements with
+ arguments but the function is a generator.
+ """
+ if self.isGenerator(node):
+ stmt = self.findReturnWithArgument(node)
+ if stmt is not None:
+ self.report(messages.ReturnWithArgsInsideGenerator,
+ stmt)
+ self.deferAssignment(checkReturnWithArgumentInsideGenerator)
self.popScope()
self.deferFunction(runFunction)
diff --git a/pyflakes/messages.py b/pyflakes/messages.py
index b7cc177..1f799ec 100644
--- a/pyflakes/messages.py
+++ b/pyflakes/messages.py
@@ -126,3 +126,10 @@ class UnusedVariable(Message):
def __init__(self, filename, loc, names):
Message.__init__(self, filename, loc)
self.message_args = (names,)
+
+
+class ReturnWithArgsInsideGenerator(Message):
+ """
+ Indicates a return statement with arguments inside a generator.
+ """
+ message = '\'return\' with argument inside generator'