diff --git a/HACKING.rst b/HACKING.rst index 10442d28..a0d0befa 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -10,3 +10,6 @@ Mistral Specific Commandments like assertIsNone(A) - [M327] Do not use xrange(). xrange() is not compatible with Python 3. Use range() or six.moves.range() instead. +- [M328] Python 3: do not use dict.iteritems. +- [M329] Python 3: do not use dict.iterkeys. +- [M330] Python 3: do not use dict.itervalues. diff --git a/mistral/hacking/checks.py b/mistral/hacking/checks.py index ae2a0f06..2f48bb95 100644 --- a/mistral/hacking/checks.py +++ b/mistral/hacking/checks.py @@ -73,6 +73,27 @@ def check_python3_xrange(logical_line): "with Python 3. Use range() or six.moves.range() instead.") +def check_python3_no_iteritems(logical_line): + msg = ("M328: Use six.iteritems() instead of dict.iteritems().") + + if re.search(r".*\.iteritems\(\)", logical_line): + yield(0, msg) + + +def check_python3_no_iterkeys(logical_line): + msg = ("M329: Use six.iterkeys() instead of dict.iterkeys().") + + if re.search(r".*\.iterkeys\(\)", logical_line): + yield(0, msg) + + +def check_python3_no_itervalues(logical_line): + msg = ("M330: Use six.itervalues() instead of dict.itervalues().") + + if re.search(r".*\.itervalues\(\)", logical_line): + yield(0, msg) + + class BaseASTChecker(ast.NodeVisitor): """Provides a simple framework for writing AST-based checks. @@ -236,3 +257,7 @@ def factory(register): register(assert_equal_none) register(check_oslo_namespace_imports) register(CheckForLoggingIssues) + register(check_python3_no_iteritems) + register(check_python3_no_iterkeys) + register(check_python3_no_itervalues) + register(check_python3_xrange) diff --git a/mistral/tests/unit/hacking/test_checks.py b/mistral/tests/unit/hacking/test_checks.py index c41c3217..4ecffa01 100644 --- a/mistral/tests/unit/hacking/test_checks.py +++ b/mistral/tests/unit/hacking/test_checks.py @@ -76,6 +76,27 @@ class BaseLoggingCheckTest(base.BaseTest): self.assertEqual(0, len(list(func('for i in range(10)')))) self.assertEqual(0, len(list(func('for i in six.moves.range(10)')))) + def test_dict_iteritems(self): + self.assertEqual(1, len(list(checks.check_python3_no_iteritems( + "obj.iteritems()")))) + + self.assertEqual(0, len(list(checks.check_python3_no_iteritems( + "six.iteritems(ob))")))) + + def test_dict_iterkeys(self): + self.assertEqual(1, len(list(checks.check_python3_no_iterkeys( + "obj.iterkeys()")))) + + self.assertEqual(0, len(list(checks.check_python3_no_iterkeys( + "six.iterkeys(ob))")))) + + def test_dict_itervalues(self): + self.assertEqual(1, len(list(checks.check_python3_no_itervalues( + "obj.itervalues()")))) + + self.assertEqual(0, len(list(checks.check_python3_no_itervalues( + "six.itervalues(ob))")))) + class TestLoggingWithWarn(BaseLoggingCheckTest): diff --git a/mistral_tempest_tests/tests/api/v2/test_tasks.py b/mistral_tempest_tests/tests/api/v2/test_tasks.py index c4fc5c42..0585b33c 100644 --- a/mistral_tempest_tests/tests/api/v2/test_tasks.py +++ b/mistral_tempest_tests/tests/api/v2/test_tasks.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import six + from oslo_concurrency.fixture import lockutils from tempest import test @@ -77,7 +79,7 @@ class TaskTypesTestsV2(base.TestCase): self.assertEqual(200, resp.status) bt = body['tasks'] - ll = [[v for k, v in d.iteritems() if 'type' in k] for d in bt] + ll = [[v for k, v in six.iteritems(d) if 'type' in k] for d in bt] types_list = [item for sublist in ll for item in sublist] self.assertIn(