diff --git a/HACKING.rst b/HACKING.rst index 881d8de006..03e2d7ade5 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -53,6 +53,7 @@ Nova Specific Commandments - [N340] Check nova.utils.spawn() is used instead of greenthread.spawn() and eventlet.spawn() - [N341] contextlib.nested is deprecated - [N342] Config options should be in the central location ``nova/conf/`` +- [N343] Check for common double word typos Creating Unit Tests ------------------- diff --git a/nova/cmd/manage.py b/nova/cmd/manage.py index f2d7cf205b..c6def45bd8 100644 --- a/nova/cmd/manage.py +++ b/nova/cmd/manage.py @@ -1277,7 +1277,7 @@ class CellV2Commands(object): if cell_uuid is None: raise Exception(_("cell_uuid must be set")) else: - # Validate the the cell exists + # Validate the cell exists cell_mapping = objects.CellMapping.get_by_uuid(ctxt, cell_uuid) filters = {} instances = objects.InstanceList.get_by_filters( diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 684e5aa2d4..b0fbd33c43 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1913,7 +1913,7 @@ def instance_get_all_by_filters(context, filters, sort_key, sort_dir, def instance_get_all_by_filters_sort(context, filters, limit=None, marker=None, columns_to_join=None, use_slave=False, sort_keys=None, sort_dirs=None): - """Return instances that match all filters sorted the the given keys. + """Return instances that match all filters sorted by the given keys. Deleted instances will be returned by default, unless there's a filter that says otherwise. diff --git a/nova/hacking/checks.py b/nova/hacking/checks.py index 8d1237299e..856eac91da 100644 --- a/nova/hacking/checks.py +++ b/nova/hacking/checks.py @@ -101,6 +101,8 @@ http_not_implemented_re = re.compile(r"raise .*HTTPNotImplemented\(") spawn_re = re.compile( r".*(eventlet|greenthread)\.(?Pspawn(_n)?)\(.*\)") contextlib_nested = re.compile(r"^with (contextlib\.)?nested\(") +doubled_words_re = re.compile( + r"\b(then?|[iao]n|i[fst]|but|f?or|at|and|[dt]o)\s+\1\b") class BaseASTChecker(ast.NodeVisitor): @@ -576,6 +578,19 @@ def check_config_option_in_central_place(logical_line, filename): yield(0, msg) +def check_doubled_words(physical_line, filename): + """Check for the common doubled-word typos + + N343 + """ + msg = ("N343: Doubled word '%(word)s' typo found") + + match = re.search(doubled_words_re, physical_line) + + if match: + return (0, msg % {'word': match.group(1)}) + + def factory(register): register(import_no_db_in_virt) register(no_db_session_in_public_api) @@ -605,3 +620,4 @@ def factory(register): register(check_no_contextlib_nested) register(check_greenthread_spawns) register(check_config_option_in_central_place) + register(check_doubled_words) diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py index 1096da6db2..13908da926 100644 --- a/nova/tests/unit/compute/test_compute_mgr.py +++ b/nova/tests/unit/compute/test_compute_mgr.py @@ -2748,7 +2748,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase): uuids.instance, 'fake-mac', start_period=0, use_slave=True) # NOTE(sdague): bw_usage_update happens at some time in - # the future, so what last_refreshed is is irrelevant. + # the future, so what last_refreshed is irrelevant. bw_usage_update.assert_called_once_with(self.context, uuids.instance, 'fake-mac', 0, 4, 6, 1, 2, diff --git a/nova/tests/unit/test_hacking.py b/nova/tests/unit/test_hacking.py index 0469095e51..a3040e55af 100644 --- a/nova/tests/unit/test_hacking.py +++ b/nova/tests/unit/test_hacking.py @@ -628,3 +628,14 @@ class HackingTestCase(test.NoDBTestCase): checks.check_config_option_in_central_place, filename="nova/cmd/serialproxy.py", expected_errors=errors) + + def test_check_doubled_words(self): + errors = [(1, 0, "N343")] + + # Artificial break to stop pep8 detecting the test ! + code = "This is the" + " the best comment" + self._assert_has_errors(code, checks.check_doubled_words, + expected_errors=errors) + + code = "This is the then best comment" + self._assert_has_no_errors(code, checks.check_doubled_words) diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 43bf17ba26..2d8bd9922b 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -1351,7 +1351,7 @@ class ComputeDriver(object): :param nova.objects.aggregate.Aggregate aggregate: The aggregate which should add the given `host` :param str host: - The name of the host to add to the the given `aggregate`. + The name of the host to add to the given `aggregate`. :param dict kwargs: A free-form thingy... @@ -1370,7 +1370,7 @@ class ComputeDriver(object): :param nova.objects.aggregate.Aggregate aggregate: The aggregate which should remove the given `host` :param str host: - The name of the host to remove from the the given `aggregate`. + The name of the host to remove from the given `aggregate`. :param dict kwargs: A free-form thingy... diff --git a/nova/virt/hardware.py b/nova/virt/hardware.py index c51aebca4f..1000241466 100644 --- a/nova/virt/hardware.py +++ b/nova/virt/hardware.py @@ -1373,7 +1373,7 @@ def get_host_numa_usage_from_instance(host, instance, free=False, :param host: nova.objects.ComputeNode instance, or a db object or dict :param instance: nova.objects.Instance instance, or a db object or dict - :param free: if True the the returned topology will have it's usage + :param free: if True the returned topology will have it's usage decreased instead. :param never_serialize_result: if True result will always be an instance of objects.NUMATopology class. diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py index 1e93a8e1f8..1fefb5e788 100644 --- a/nova/virt/libvirt/utils.py +++ b/nova/virt/libvirt/utils.py @@ -454,7 +454,7 @@ def get_instance_path(instance, forceold=False, relative=False): def get_instance_path_at_destination(instance, migrate_data=None): - """Get the the instance path on destination node while live migration. + """Get the instance path on destination node while live migration. This method determines the directory name for instance storage on destination node, while live migration. diff --git a/nova/virt/vmwareapi/ds_util.py b/nova/virt/vmwareapi/ds_util.py index aa2cb8cfd6..e46c335f0a 100644 --- a/nova/virt/vmwareapi/ds_util.py +++ b/nova/virt/vmwareapi/ds_util.py @@ -40,7 +40,7 @@ DcInfo = collections.namedtuple('DcInfo', ['ref', 'name', 'vmFolder']) # A cache for datastore/datacenter mappings. The key will be -# the datastore moref. The value will the the DcInfo object. +# the datastore moref. The value will be the DcInfo object. _DS_DC_MAPPING = {} diff --git a/nova/wsgi.py b/nova/wsgi.py index 529583b60b..a692c511f0 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -330,7 +330,7 @@ class Application(object): res = exc.HTTPForbidden(explanation='Nice try') # Option 3: a webob Response object (in case you need to play with - # headers, or you want to be treated like an iterable, or or or) + # headers, or you want to be treated like an iterable, or ...) res = Response() res.app_iter = open('somefile')