diff options
-rw-r--r-- | pylint/checkers/classes.py | 11 | ||||
-rw-r--r-- | pylint/test/functional/non_iterator_returned.py | 21 | ||||
-rw-r--r-- | pylint/test/functional/non_iterator_returned.txt | 9 | ||||
-rw-r--r-- | tox.ini | 5 |
4 files changed, 27 insertions, 19 deletions
diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py index 3d9144d..24b862f 100644 --- a/pylint/checkers/classes.py +++ b/pylint/checkers/classes.py @@ -1067,12 +1067,15 @@ class SpecialMethodsChecker(BaseChecker): def _check_iter(self, node): try: - infered = node.infer_call_result(node) + infered_values = list(node.infer_call_result(node)) except astroid.InferenceError: return - - if not all(map(self._is_iterator, infered)): - self.add_message('non-iterator-returned', node=node) + # cases when there're multiple values infered + # are skipped to reduce the number of false positives + if len(infered_values) == 1: + infered = infered_values[0] + if not self._is_iterator(infered): + self.add_message('non-iterator-returned', node=node) def _ancestors_to_call(klass_node, method='__init__'): diff --git a/pylint/test/functional/non_iterator_returned.py b/pylint/test/functional/non_iterator_returned.py index 804ceee..d2fa758 100644 --- a/pylint/test/functional/non_iterator_returned.py +++ b/pylint/test/functional/non_iterator_returned.py @@ -56,6 +56,19 @@ class FifthGoodIterator(object): def __iter__(self): return IteratorClass +class FileBasedIterator(object): + def __init__(self, path): + self.path = path + self.file = None + + def __iter__(self): + if self.file is not None: + self.file.close() + self.file = open(self.path) + # self file has two infered values: None and <instance of 'file'> + # we don't want to emit error in this case + return self.file + class FirstBadIterator(object): """ __iter__ returns a list """ @@ -80,11 +93,3 @@ class FourthBadIterator(object): def __iter__(self): # [non-iterator-returned] return ThirdBadIterator - -class FifthBadIterator(object): - """All branches should return an iterator.""" - - def __iter__(self): # [non-iterator-returned] - if self: - return 1 - return SecondGoodIterator() diff --git a/pylint/test/functional/non_iterator_returned.txt b/pylint/test/functional/non_iterator_returned.txt index fe3db10..fa1d5be 100644 --- a/pylint/test/functional/non_iterator_returned.txt +++ b/pylint/test/functional/non_iterator_returned.txt @@ -1,5 +1,4 @@ -non-iterator-returned:63:FirstBadIterator.__iter__:__iter__ returns non-iterator -non-iterator-returned:69:SecondBadIterator.__iter__:__iter__ returns non-iterator -non-iterator-returned:75:ThirdBadIterator.__iter__:__iter__ returns non-iterator -non-iterator-returned:81:FourthBadIterator.__iter__:__iter__ returns non-iterator -non-iterator-returned:87:FifthBadIterator.__iter__:__iter__ returns non-iterator
\ No newline at end of file +non-iterator-returned:76:FirstBadIterator.__iter__:__iter__ returns non-iterator +non-iterator-returned:82:SecondBadIterator.__iter__:__iter__ returns non-iterator +non-iterator-returned:88:ThirdBadIterator.__iter__:__iter__ returns non-iterator +non-iterator-returned:94:FourthBadIterator.__iter__:__iter__ returns non-iterator @@ -1,7 +1,7 @@ [tox] # official list is #envlist = py27, py32, py33, py34 -envlist = py27, py33, pylint +envlist = py27, py34, pylint [testenv:pylint] deps = @@ -14,5 +14,6 @@ commands = pylint -rn --rcfile={toxinidir}/pylintrc {envsitepackagesdir}/pylint deps = hg+https://bitbucket.org/logilab/astroid@master six + pudb commands = python -Wi -m unittest discover -s {envsitepackagesdir}/pylint/test/ -p {posargs:*test_*}.py -changedir = {toxworkdir}
\ No newline at end of file +changedir = {toxworkdir} |