From acfdab1a8a8e1e73ef2dd0cadf87f242f570e5d7 Mon Sep 17 00:00:00 2001 From: "Li, Chen" Date: Wed, 14 Oct 2015 10:05:55 +0800 Subject: [PATCH] Fix `raise` section in docstrings The correct format is: :raises Exception: conditions This patch fix all docstrings across the project and add hacking rule to check it. Change-Id: I40cc20f8d555082e284c1683522932aaa68f575c Closes-Bug: 1470901 --- rally/plugins/openstack/scenarios/heat/utils.py | 2 +- tests/hacking/README.rst | 1 + tests/hacking/checks.py | 17 +++++++++++++++++ tests/unit/fakes.py | 2 +- tests/unit/test_hacking.py | 9 +++++++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/rally/plugins/openstack/scenarios/heat/utils.py b/rally/plugins/openstack/scenarios/heat/utils.py index 0bface8c..9d1ba610 100644 --- a/rally/plugins/openstack/scenarios/heat/utils.py +++ b/rally/plugins/openstack/scenarios/heat/utils.py @@ -331,7 +331,7 @@ class HeatScenario(scenario.OpenStackScenario): :param stack: stack to call a webhook on :param output_key: The name of the output to get the URL from - :raises: InvalidConfigException if the output key is not found + :raises InvalidConfigException: if the output key is not found """ url = None for output in stack.outputs: diff --git a/tests/hacking/README.rst b/tests/hacking/README.rst index 49dd2240..fa4cb074 100644 --- a/tests/hacking/README.rst +++ b/tests/hacking/README.rst @@ -27,3 +27,4 @@ Rally Specific Commandments * [N351] - Ensure that data structs (i.e Lists and Dicts) are declared literally rather than using constructors * [N352] - Ensure that string formatting only uses a mapping if multiple mapping keys are used. * [N353] - Ensure that unicode() function is not uset because of absence in py3 +* [N354] - Ensure that ``:raises: Exception`` is not used diff --git a/tests/hacking/checks.py b/tests/hacking/checks.py index 3291f841..00239f48 100644 --- a/tests/hacking/checks.py +++ b/tests/hacking/checks.py @@ -59,6 +59,8 @@ re_str_format = re.compile(r""" [hLl]? # optional length modifier [A-z%] # conversion modifier """, re.X) +re_raises = re.compile( + r"\s:raise[^s] *.*$|\s:raises *:.*$|\s:raises *[^:]+$") def skip_ignored_lines(func): @@ -441,6 +443,20 @@ def check_using_unicode(logical_line, filename): "use 'six.text_type' instead.") +def check_raises(physical_line, filename): + """Check raises usage + + N354 + """ + + ignored_files = ["./tests/unit/test_hacking.py", + "./tests/hacking/checks.py"] + if filename not in ignored_files: + if re_raises.search(physical_line): + return (0, "N354 ':Please use ':raises Exception: conditions' " + "in docstrings.") + + def factory(register): register(check_assert_methods_from_mock) register(check_import_of_logging) @@ -457,3 +473,4 @@ def factory(register): register(check_no_constructor_data_struct) register(check_dict_formatting_in_string) register(check_using_unicode) + register(check_raises) diff --git a/tests/unit/fakes.py b/tests/unit/fakes.py index d28c3594..6a587c9f 100644 --- a/tests/unit/fakes.py +++ b/tests/unit/fakes.py @@ -68,7 +68,7 @@ def setup_dict(data, required=None, defaults=None): :param required: list, mandatory keys to check :param defaults: dict, default data :returns: dict, with all keys set - :raises: IndexError, ValueError + :raises IndexError, ValueError: If input data is incorrect """ required = required or [] for i in set(required) - set(data): diff --git a/tests/unit/test_hacking.py b/tests/unit/test_hacking.py index a4589156..b76df7cb 100644 --- a/tests/unit/test_hacking.py +++ b/tests/unit/test_hacking.py @@ -319,3 +319,12 @@ class HackingTestCase(test.TestCase): "text = process(unicode('sometext'))", "fakefile") self.assertIsNotNone(next(checkres)) self.assertEqual([], list(checkres)) + + def test_check_raises(self): + checkres = checks.check_raises( + "text = :raises: Exception if conditions", "fakefile") + self.assertIsNotNone(checkres) + + checkres = checks.check_raises( + "text = :raises Exception: if conditions", "fakefile") + self.assertIsNone(checkres)