From 44b5f310c503aee821b7898d952f1eca05b60c6c Mon Sep 17 00:00:00 2001 From: "li,chen" Date: Wed, 31 Dec 2014 08:18:48 +0800 Subject: [PATCH] use function next() instead of next() method on iterator objects Python 3 introduced a next() function to replace the next() method on iterator objects. Rather than calling the method on the iterator, the next() function is called with the iterable object as it's sole parameter, which calls the underlying __next__() method. The next() function was backported to Python 2.6 which allows us to use either the 2.x or 3.x way simultaneously. Change-Id: I945225b1b0c6c39842a77f4a136e9431b798229f Closes-Bug: #1403074 --- tests/hacking/README.rst | 1 + tests/hacking/checks.py | 17 +++++++++++++++++ tests/unit/test_hacking.py | 7 +++++++ 3 files changed, 25 insertions(+) diff --git a/tests/hacking/README.rst b/tests/hacking/README.rst index fc6cf806..48ad3bb6 100644 --- a/tests/hacking/README.rst +++ b/tests/hacking/README.rst @@ -29,4 +29,5 @@ Rally Specific Commandments * [N334] - Ensure that ``itertools.imap`` is not used * [N335] - Ensure that ``xrange`` is not used * [N336] - Ensure that ``string.lowercase`` and ``string.uppercase`` are not used + * [N337] - Ensure that ``next()`` method on iterator objects is not used * [N340] - Ensure that we are importing always ``from rally import objects`` diff --git a/tests/hacking/checks.py b/tests/hacking/checks.py index e88a70d7..a2234916 100644 --- a/tests/hacking/checks.py +++ b/tests/hacking/checks.py @@ -53,6 +53,7 @@ re_itertools_imap_method = re.compile(r"(^|[\s=])itertools\.imap\(") re_xrange_method = re.compile(r"(^|[\s=])xrange\(") re_string_lower_upper_case_method = re.compile( r"(^|[(,\s=])string\.(lower|upper)case([)\[,\s]|$)") +re_next_on_iterator_method = re.compile(r"\.next\(\)") def _parse_assert_mock_str(line): @@ -322,6 +323,21 @@ def check_string_lower_upper_case_method(logical_line): "rather than string.lowercase or string.uppercase.") +def check_next_on_iterator_method(logical_line): + """Check if next() method on iterator objects are properly called + + Python 3 introduced a next() function to replace the next() method on + iterator objects. Rather than calling the method on the iterator, + the next() function is called with the iterable object as it's sole + parameter, which calls the underlying __next__() method. + + N337 + """ + res = re_next_on_iterator_method.search(logical_line) + if res: + yield (0, "N337: Use next(iterator) rather than iterator.next().") + + def check_no_direct_rally_objects_import(logical_line, filename): """Check if rally.objects are properly imported. @@ -356,4 +372,5 @@ def factory(register): register(check_itertools_imap_method) register(check_xrange_method) register(check_string_lower_upper_case_method) + register(check_next_on_iterator_method) register(check_no_direct_rally_objects_import) diff --git a/tests/unit/test_hacking.py b/tests/unit/test_hacking.py index 82855906..8442ac0e 100644 --- a/tests/unit/test_hacking.py +++ b/tests/unit/test_hacking.py @@ -176,6 +176,13 @@ class HackingTestCase(test.TestCase): self.assertEqual(len(list(checks.check_string_lower_upper_case_method( "string.ascii_uppercase[:16]"))), 0) + def test_check_next_on_iterator_method(self): + self.assertEqual(len(list(checks.check_next_on_iterator_method( + "iterator.next()"))), 1) + + self.assertEqual(len(list(checks.check_next_on_iterator_method( + "next(iterator)"))), 0) + def test_assert_equal_none(self): self.assertEqual(len(list(checks.assert_equal_none( "self.assertEqual(A, None)"))), 1)