diff options
author | cpopa <devnull@localhost> | 2013-10-10 14:49:19 +0300 |
---|---|---|
committer | cpopa <devnull@localhost> | 2013-10-10 14:49:19 +0300 |
commit | 7aa994aad907e9e2b0727fac8e1d81fc953f60db (patch) | |
tree | eaad50ad864805b4d93500045fe6a1b8606a1bdc | |
parent | b24484fd0b3fd43c5714f982a161cd91cf4793b8 (diff) | |
download | pylint-7aa994aad907e9e2b0727fac8e1d81fc953f60db.tar.gz |
Mappings aren't accepted by reversed().
-rw-r--r-- | checkers/base.py | 37 | ||||
-rw-r--r-- | test/input/func_bad_reversed_sequence.py | 48 | ||||
-rw-r--r-- | test/messages/func_bad_reversed_sequence.txt | 8 |
3 files changed, 82 insertions, 11 deletions
diff --git a/checkers/base.py b/checkers/base.py index 12bc8b3..2ec6fe9 100644 --- a/checkers/base.py +++ b/checkers/base.py @@ -700,18 +700,33 @@ functions, methods except NoSuchArgumentError: self.add_message('missing-reversed-argument', node=node) else: - if not argument: - return - - for methods in REVERSED_METHODS: - for meth in methods: - try: - argument.getattr(meth) - except astroid.NotFoundError: + if argument is None: + # nothing was infered + return + + if isinstance(argument, astroid.Instance): + if (argument._proxied.name == 'dict' and + is_builtin_object(argument._proxied)): + self.add_message('bad-reversed-sequence', node=node) + return + elif any(ancestor.name == 'dict' and is_builtin_object(ancestor) + for ancestor in argument._proxied.ancestors()): + # mappings aren't accepted by reversed() + self.add_message('bad-reversed-sequence', node=node) + return + + for methods in REVERSED_METHODS: + for meth in methods: + try: + argument.getattr(meth) + except astroid.NotFoundError: + break + else: break - else: - break - else: + else: + self.add_message('bad-reversed-sequence', node=node) + elif not isinstance(argument, (astroid.List, astroid.Tuple)): + # everything else is not a proper sequence for reversed() self.add_message('bad-reversed-sequence', node=node) class NameChecker(_BasicChecker): diff --git a/test/input/func_bad_reversed_sequence.py b/test/input/func_bad_reversed_sequence.py new file mode 100644 index 0000000..3bab9b9 --- /dev/null +++ b/test/input/func_bad_reversed_sequence.py @@ -0,0 +1,48 @@ +""" Checks that reversed() receive proper argument """ + +# pylint: disable-msg=too-few-public-methods,no-self-use,incomplete-protocol +__revision__ = 0 + +class GoodReversed(object): + """ Implements __reversed__ """ + def __reversed__(self): + return [1, 2, 3] + +class SecondGoodReversed(object): + """ Implements __len__ and __getitem__ """ + def __len__(self): + return 3 + + def __getitem__(self, index): + return index + +class BadReversed(object): + """ implements only len() """ + def __len__(self): + return 3 + +class SecondBadReversed(object): + """ implements only __getitem__ """ + def __getitem__(self, index): + return index + +class ThirdBadReversed(dict): + """ dict subclass """ + +def test(): + """ test function """ + seq = reversed() + seq = reversed(None) + seq = reversed([1, 2, 3]) + seq = reversed((1, 2, 3)) + seq = reversed(set()) + seq = reversed({'a': 1, 'b': 2}) + seq = reversed(iter([1, 2, 3])) + seq = reversed(GoodReversed()) + seq = reversed(SecondGoodReversed()) + seq = reversed(BadReversed()) + seq = reversed(SecondBadReversed()) + seq = reversed(range(100)) + seq = reversed(ThirdBadReversed()) + seq = reversed(lambda: None) + return seq diff --git a/test/messages/func_bad_reversed_sequence.txt b/test/messages/func_bad_reversed_sequence.txt new file mode 100644 index 0000000..87771ac --- /dev/null +++ b/test/messages/func_bad_reversed_sequence.txt @@ -0,0 +1,8 @@ +E: 34:test: Missing argument to reversed()
+E: 35:test: The first reversed() argument is not a sequence
+E: 38:test: The first reversed() argument is not a sequence
+E: 39:test: The first reversed() argument is not a sequence
+E: 43:test: The first reversed() argument is not a sequence
+E: 44:test: The first reversed() argument is not a sequence
+E: 46:test: The first reversed() argument is not a sequence
+E: 47:test: The first reversed() argument is not a sequence
\ No newline at end of file |