diff --git a/openstack/_hacking.py b/openstack/_hacking/checks.py similarity index 66% rename from openstack/_hacking.py rename to openstack/_hacking/checks.py index 01b05adfc..0325be2dd 100644 --- a/openstack/_hacking.py +++ b/openstack/_hacking/checks.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import os import re from hacking import core @@ -26,7 +27,7 @@ Guidelines for writing new hacking checks - Keep the test method code in the source file ordered based on the O3xx value. - List the new rule in the top level HACKING.rst file - - Add test cases for each new rule to nova/tests/unit/test_hacking.py + - Add test cases for each new rule to openstack/tests/unit/test_hacking.py """ @@ -41,3 +42,23 @@ def assert_no_setupclass(logical_line): """ if SETUPCLASS_RE.match(logical_line): yield (0, "O300: setUpClass not allowed") + + +@core.flake8ext +def assert_no_deprecated_exceptions(logical_line, filename): + """Check for use of deprecated cloud-layer exceptions + + 0310 + """ + if filename.endswith(os.path.join('openstack', 'cloud', 'exc.py')): + return + + for exception in ( + 'OpenStackCloudTimeout', + 'OpenStackCloudHTTPError', + 'OpenStackCloudBadRequest', + 'OpenStackCloudURINotFound', + 'OpenStackCloudResourceNotFound', + ): + if re.search(fr'\b{exception}\b', logical_line): + yield (0, 'O310: Use of deprecated Exception class') diff --git a/openstack/cloud/exc.py b/openstack/cloud/exc.py index cc831f402..68ffb35fc 100644 --- a/openstack/cloud/exc.py +++ b/openstack/cloud/exc.py @@ -37,7 +37,7 @@ class OpenStackCloudUnavailableFeature(OpenStackCloudException): pass -# Backwards compat +# Backwards compat. These are deprecated and should not be used in new code. OpenStackCloudTimeout = exceptions.ResourceTimeout OpenStackCloudHTTPError = exceptions.HttpException OpenStackCloudBadRequest = exceptions.BadRequestException diff --git a/openstack/tests/unit/test_hacking.py b/openstack/tests/unit/test_hacking.py index bf719d11d..df4ce222f 100644 --- a/openstack/tests/unit/test_hacking.py +++ b/openstack/tests/unit/test_hacking.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -from openstack import _hacking +from openstack._hacking import checks from openstack.tests.unit import base @@ -52,20 +52,45 @@ class HackingTestCase(base.TestCase): def test_assert_no_setupclass(self): self.assertEqual( - len(list(_hacking.assert_no_setupclass("def setUpClass(cls)"))), 1 + len(list(checks.assert_no_setupclass("def setUpClass(cls)"))), 1 ) self.assertEqual( - len(list(_hacking.assert_no_setupclass("# setUpClass is evil"))), 0 + len(list(checks.assert_no_setupclass("# setUpClass is evil"))), 0 ) self.assertEqual( len( list( - _hacking.assert_no_setupclass( + checks.assert_no_setupclass( "def setUpClassyDrinkingLocation(cls)" ) ) ), 0, ) + + def test_assert_no_deprecated_exceptions(self): + self.assertEqual( + len( + list( + checks.assert_no_deprecated_exceptions( + "raise exc.OpenStackCloudTimeout", + "openstack/cloud/compute.py", + ) + ) + ), + 1, + ) + + self.assertEqual( + len( + list( + checks.assert_no_deprecated_exceptions( + "raise exc.OpenStackCloudTimeout", + "openstack/cloud/exc.py", + ) + ) + ), + 0, + ) diff --git a/tox.ini b/tox.ini index 693535a1c..3d287e1d2 100644 --- a/tox.ini +++ b/tox.ini @@ -159,8 +159,9 @@ exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,openstack/_services_m [flake8:local-plugins] extension = - O300 = _hacking:assert_no_setupclass -paths = ./openstack + O300 = checks:assert_no_setupclass + O310 = checks:assert_no_deprecated_exceptions +paths = ./openstack/_hacking [doc8] extensions = .rst, .yaml