diff options
author | Attila Oláh <attilaolah@gmail.com> | 2013-07-05 13:55:09 +0200 |
---|---|---|
committer | Attila Oláh <attilaolah@gmail.com> | 2013-07-05 13:55:09 +0200 |
commit | b373a73a7fcf05c29255f60c58f0b84094f03c81 (patch) | |
tree | 7c2a6cef7468115abf4a670d162473e55e22ac9d | |
parent | c57a450f15e9f61d169b3178f5ed21564ce28257 (diff) | |
download | pyflakes-b373a73a7fcf05c29255f60c58f0b84094f03c81.tar.gz |
catch return with arguments inside generator (fixes #1198132)
-rw-r--r-- | pyflakes/checker.py | 46 | ||||
-rw-r--r-- | pyflakes/messages.py | 7 |
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' |