From 836717c49a2bc10411a792e5764ef52a4d6326e8 Mon Sep 17 00:00:00 2001 From: Gary Kotton Date: Thu, 1 May 2014 06:10:57 -0700 Subject: [PATCH] Add missing translation support Update a number of files to add missing translation support. The patch adds a new hacking check - N320. This ensures that all log messages, except debug ones, have translations. A '# noqa' indicates that the validation will not be done on the specific log message. This should be used in cases where the translations do not need to be done, for example, the log message is logging raw data. Change-Id: I3e1fdd04d87b09dff50950b5e85f5cacfb29afdc Closes-bug: #1314994 --- HACKING.rst | 2 +- neutron/agent/securitygroups_rpc.py | 7 +-- neutron/hacking/__init__.py | 0 neutron/hacking/checks.py | 50 +++++++++++++++++++ .../hyperv/agent/security_groups_driver.py | 12 +++-- neutron/plugins/hyperv/agent/utilsfactory.py | 4 +- .../plumgrid_plugin/plumgrid_plugin.py | 4 +- neutron/tests/unit/test_hacking.py | 43 ++++++++++++++++ tox.ini | 3 ++ 9 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 neutron/hacking/__init__.py create mode 100644 neutron/hacking/checks.py create mode 100644 neutron/tests/unit/test_hacking.py diff --git a/HACKING.rst b/HACKING.rst index 1246575d84..84f6f3e1c7 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -8,7 +8,7 @@ Neutron Style Commandments Neutron Specific Commandments -------------------------- -None so far +- [N320] Validate that LOG messages, except debug ones, have translations Creating Unit Tests ------------------- diff --git a/neutron/agent/securitygroups_rpc.py b/neutron/agent/securitygroups_rpc.py index e8dc68209b..7d476729c4 100644 --- a/neutron/agent/securitygroups_rpc.py +++ b/neutron/agent/securitygroups_rpc.py @@ -56,7 +56,8 @@ def _is_valid_driver_combination(): def is_firewall_enabled(): if not _is_valid_driver_combination(): - LOG.warn("Driver configuration don't match with enable_security_group") + LOG.warn(_("Driver configuration doesn't match with " + "enable_security_group")) return cfg.CONF.SECURITYGROUP.enable_security_group @@ -139,8 +140,8 @@ class SecurityGroupAgentRpcMixin(object): firewall_driver = cfg.CONF.SECURITYGROUP.firewall_driver LOG.debug(_("Init firewall settings (driver=%s)"), firewall_driver) if not _is_valid_driver_combination(): - LOG.warn("Driver configuration doesn't match " - "with enable_security_group") + LOG.warn(_("Driver configuration doesn't match " + "with enable_security_group")) if not firewall_driver: firewall_driver = 'neutron.agent.firewall.NoopFirewallDriver' self.firewall = importutils.import_object(firewall_driver) diff --git a/neutron/hacking/__init__.py b/neutron/hacking/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/neutron/hacking/checks.py b/neutron/hacking/checks.py new file mode 100644 index 0000000000..899d762430 --- /dev/null +++ b/neutron/hacking/checks.py @@ -0,0 +1,50 @@ +# Copyright (c) 2014 OpenStack Foundation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import re + +import pep8 + +""" +Guidelines for writing new hacking checks + + - Use only for Neutron specific tests. OpenStack general tests + should be submitted to the common 'hacking' module. + - Pick numbers in the range N3xx. Find the current test with + the highest allocated number and then pick the next value. + - Keep the test method code in the source file ordered based + on the N3xx value. + - List the new rule in the top level HACKING.rst file + - Add test cases for each new rule to + neutron/tests/unit/test_hacking.py + +""" + +log_translation = re.compile( + r"(.)*LOG\.(audit|error|info|warn|warning|critical|exception)\(\s*('|\")") + + +def validate_log_translations(logical_line, physical_line, filename): + # Translations are not required in the test directory + if "neutron/tests" in filename: + return + if pep8.noqa(physical_line): + return + msg = "N320: Log messages require translations!" + if log_translation.match(logical_line): + yield (0, msg) + + +def factory(register): + register(validate_log_translations) diff --git a/neutron/plugins/hyperv/agent/security_groups_driver.py b/neutron/plugins/hyperv/agent/security_groups_driver.py index 9c997f18ba..755ab5270e 100644 --- a/neutron/plugins/hyperv/agent/security_groups_driver.py +++ b/neutron/plugins/hyperv/agent/security_groups_driver.py @@ -89,10 +89,10 @@ class HyperVSecurityGroupsDriver(firewall.FirewallDriver): } def apply_port_filter(self, port): - LOG.info('Aplying port filter.') + LOG.info(_('Aplying port filter.')) def update_port_filter(self, port): - LOG.info('Updating port rules.') + LOG.info(_('Updating port rules.')) if port['device'] not in self._security_ports: self.prepare_port_filter(port) @@ -105,8 +105,10 @@ class HyperVSecurityGroupsDriver(firewall.FirewallDriver): new_rules = [r for r in param_port_rules if r not in rules] remove_rules = [r for r in rules if r not in param_port_rules] - LOG.info("Creating %s new rules, removing %s old rules." % ( - len(new_rules), len(remove_rules))) + LOG.info(_("Creating %(new)s new rules, removing %(old)s " + "old rules."), + {'new': len(new_rules), + 'old': len(remove_rules)}) self._remove_port_rules(old_port['id'], remove_rules) self._create_port_rules(port['id'], new_rules) @@ -114,7 +116,7 @@ class HyperVSecurityGroupsDriver(firewall.FirewallDriver): self._security_ports[port['device']] = port def remove_port_filter(self, port): - LOG.info('Removing port filter') + LOG.info(_('Removing port filter')) self._security_ports.pop(port['device'], None) @property diff --git a/neutron/plugins/hyperv/agent/utilsfactory.py b/neutron/plugins/hyperv/agent/utilsfactory.py index 8b6ae77293..5698255c33 100644 --- a/neutron/plugins/hyperv/agent/utilsfactory.py +++ b/neutron/plugins/hyperv/agent/utilsfactory.py @@ -60,8 +60,8 @@ def get_hypervutils(): force_v1_flag = CONF.hyperv.force_hyperv_utils_v1 if _check_min_windows_version(6, 3): if force_v1_flag: - LOG.warning('V1 virtualization namespace no longer supported on ' - 'Windows Server / Hyper-V Server 2012 R2 or above.') + LOG.warning(_('V1 virtualization namespace no longer supported on ' + 'Windows Server / Hyper-V Server 2012 R2 or above.')) cls = utilsv2.HyperVUtilsV2R2 elif not force_v1_flag and _check_min_windows_version(6, 2): cls = utilsv2.HyperVUtilsV2 diff --git a/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py b/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py index 330c98b41f..d28b90ae0e 100644 --- a/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py +++ b/neutron/plugins/plumgrid/plumgrid_plugin/plumgrid_plugin.py @@ -570,8 +570,8 @@ class NeutronPluginPLUMgridV2(db_base_plugin_v2.NeutronDbPluginV2, def _network_admin_state(self, network): if network["network"].get("admin_state_up") is False: - LOG.warning("Networks with admin_state_up=False are not " - "supported by PLUMgrid plugin yet.") + LOG.warning(_("Networks with admin_state_up=False are not " + "supported by PLUMgrid plugin yet.")) return network def _allocate_pools_for_subnet(self, context, subnet): diff --git a/neutron/tests/unit/test_hacking.py b/neutron/tests/unit/test_hacking.py new file mode 100644 index 0000000000..a5cebd1aaf --- /dev/null +++ b/neutron/tests/unit/test_hacking.py @@ -0,0 +1,43 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from neutron.hacking import checks +from neutron.tests import base + + +class HackingTestCase(base.BaseTestCase): + + def test_log_translations(self): + logs = ['audit', 'error', 'info', 'warn', 'warning', 'critical', + 'exception'] + levels = ['_LI', '_LW', '_LE', '_LC'] + debug = "LOG.debug('OK')" + self.assertEqual( + 0, len(list(checks.validate_log_translations(debug, debug, 'f')))) + for log in logs: + bad = 'LOG.%s("Bad")' % log + self.assertEqual( + 1, len(list(checks.validate_log_translations(bad, bad, 'f')))) + ok = "LOG.%s(_('OK'))" % log + self.assertEqual( + 0, len(list(checks.validate_log_translations(ok, ok, 'f')))) + ok = "LOG.%s('OK') # noqa" % log + self.assertEqual( + 0, len(list(checks.validate_log_translations(ok, ok, 'f')))) + ok = "LOG.%s(variable)" % log + self.assertEqual( + 0, len(list(checks.validate_log_translations(ok, ok, 'f')))) + for level in levels: + ok = "LOG.%s(%s('OK'))" % (log, level) + self.assertEqual( + 0, len(list(checks.validate_log_translations(ok, + ok, 'f')))) diff --git a/tox.ini b/tox.ini index 028f8865f2..297998a8c2 100644 --- a/tox.ini +++ b/tox.ini @@ -46,3 +46,6 @@ ignore = E125,H404 show-source = true builtins = _ exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools,.ropeproject + +[hacking] +local-check-factory = neutron.hacking.checks.factory