Improved localization testing.

Moved localization tests to tools/hacking.py.

Change-Id: I903b90dfb09a46a72b1c64c30301f90661999f5b
This commit is contained in:
Yuriy Taraday
2012-02-24 16:13:44 +04:00
parent 95712e3eef
commit 76a3b47bc8
8 changed files with 17 additions and 112 deletions

View File

@@ -74,6 +74,6 @@ if __name__ == '__main__':
try: try:
servers.append(service.Service.create(binary=binary)) servers.append(service.Service.create(binary=binary))
except (Exception, SystemExit): except (Exception, SystemExit):
LOG.exception(_('Failed to load %s' % binary)) LOG.exception(_('Failed to load %s'), binary)
service.serve(*servers) service.serve(*servers)
service.wait() service.wait()

View File

@@ -1113,8 +1113,9 @@ class VersionCommands(object):
pass pass
def list(self): def list(self):
print _("%s (%s)") %\ print _("%(version)s (%(vcs)s)") % \
(version.version_string(), version.version_string_with_vcs()) {'version': version.version_string(),
'vcs': version.version_string_with_vcs()}
def __call__(self): def __call__(self):
self.list() self.list()
@@ -1680,8 +1681,9 @@ def main():
script_name = argv.pop(0) script_name = argv.pop(0)
if len(argv) < 1: if len(argv) < 1:
print _("\nOpenStack Nova version: %s (%s)\n") %\ print _("\nOpenStack Nova version: %(version)s (%(vcs)s)\n") % \
(version.version_string(), version.version_string_with_vcs()) {'version': version.version_string(),
'vcs': version.version_string_with_vcs()}
print script_name + " category action [<args>]" print script_name + " category action [<args>]"
print _("Available categories:") print _("Available categories:")
for k, _v in CATEGORIES: for k, _v in CATEGORIES:

View File

@@ -62,7 +62,7 @@ def notify(message):
driver.notify(message) driver.notify(message)
except Exception as e: except Exception as e:
LOG.exception(_("Problem '%(e)s' attempting to send to " LOG.exception(_("Problem '%(e)s' attempting to send to "
"notification driver %(driver)s." % locals())) "notification driver %(driver)s."), locals())
def _reset_drivers(): def _reset_drivers():

View File

@@ -43,4 +43,4 @@ def notify(message):
rpc.notify(context, topic, message) rpc.notify(context, topic, message)
except Exception, e: except Exception, e:
LOG.exception(_("Could not send notification to %(topic)s. " LOG.exception(_("Could not send notification to %(topic)s. "
"Payload=%(message)s" % locals())) "Payload=%(message)s"), locals())

View File

@@ -427,8 +427,8 @@ class Connection(object):
self.channel._new_queue('ae.undeliver') self.channel._new_queue('ae.undeliver')
for consumer in self.consumers: for consumer in self.consumers:
consumer.reconnect(self.channel) consumer.reconnect(self.channel)
LOG.info(_('Connected to AMQP server on ' LOG.info(_('Connected to AMQP server on %(hostname)s:%(port)d'),
'%(hostname)s:%(port)d') % self.params) self.params)
def reconnect(self): def reconnect(self):
"""Handles reconnecting and re-establishing queues. """Handles reconnecting and re-establishing queues.

View File

@@ -338,12 +338,12 @@ class Connection(object):
try: try:
self.connection.open() self.connection.open()
except qpid.messaging.exceptions.ConnectionError, e: except qpid.messaging.exceptions.ConnectionError, e:
LOG.error(_('Unable to connect to AMQP server: %s ') % e) LOG.error(_('Unable to connect to AMQP server: %s'), e)
time.sleep(FLAGS.qpid_reconnect_interval or 1) time.sleep(FLAGS.qpid_reconnect_interval or 1)
else: else:
break break
LOG.info(_('Connected to AMQP server on %s') % self.broker) LOG.info(_('Connected to AMQP server on %s'), self.broker)
self.session = self.connection.session() self.session = self.connection.session()

View File

@@ -1,97 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2011 OpenStack LLC
#
# 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 os
import re
import nova
from nova import test
class LocalizationTestCase(test.TestCase):
def test_multiple_positional_format_placeholders(self):
pat = re.compile("\W_\(")
single_pat = re.compile("\W%\W")
root_path = os.path.dirname(nova.__file__)
problems = {}
for root, dirs, files in os.walk(root_path):
for fname in files:
if not fname.endswith(".py"):
continue
pth = os.path.join(root, fname)
txt = fulltext = file(pth).read()
txt_lines = fulltext.splitlines()
if not pat.search(txt):
continue
problems[pth] = []
pos = txt.find("_(")
while pos > -1:
# Make sure that this isn't part of a dunder;
# e.g., __init__(...
# or something like 'self.assert_(...'
test_txt = txt[pos - 1: pos + 10]
if not (pat.search(test_txt)):
txt = txt[pos + 2:]
pos = txt.find("_(")
continue
pos += 2
txt = txt[pos:]
innerChars = []
# Count pairs of open/close parens until _() closing
# paren is found.
parenCount = 1
pos = 0
while parenCount > 0:
char = txt[pos]
if char == "(":
parenCount += 1
elif char == ")":
parenCount -= 1
innerChars.append(char)
pos += 1
inner_all = "".join(innerChars)
# Filter out '%%' and '%('
inner = inner_all.replace("%%", "").replace("%(", "")
# Filter out the single '%' operators
inner = single_pat.sub("", inner)
# Within the remaining content, count %
fmtCount = inner.count("%")
if fmtCount > 1:
inner_first = inner_all.splitlines()[0]
lns = ["%s" % (p + 1)
for p, t in enumerate(txt_lines)
if inner_first in t]
lnums = ", ".join(lns)
# Using ugly string concatenation to avoid having
# this test fail itself.
inner_all = "_" + "(" + "%s" % inner_all
problems[pth].append("Line: %s Text: %s" %
(lnums, inner_all))
# Look for more
pos = txt.find("_(")
if not problems[pth]:
del problems[pth]
if problems:
out = ["Problem(s) found in localized string formatting",
"(see http://www.gnu.org/software/hello/manual/"
"gettext/Python.html for more information)",
"",
" ------------ Files to fix ------------"]
for pth in problems:
out.append(" %s:" % pth)
for val in set(problems[pth]):
out.append(" %s" % val)
raise AssertionError("\n".join(out))

View File

@@ -623,8 +623,8 @@ class XenAPIVMTestCase(test.TestCase):
# mount point will be the last item of the command list # mount point will be the last item of the command list
self._tmpdir = cmd[len(cmd) - 1] self._tmpdir = cmd[len(cmd) - 1]
LOG.debug(_('Creating files in %s to simulate guest agent') % LOG.debug(_('Creating files in %s to simulate guest agent'),
self._tmpdir) self._tmpdir)
os.makedirs(os.path.join(self._tmpdir, 'usr', 'sbin')) os.makedirs(os.path.join(self._tmpdir, 'usr', 'sbin'))
# Touch the file using open # Touch the file using open
open(os.path.join(self._tmpdir, 'usr', 'sbin', open(os.path.join(self._tmpdir, 'usr', 'sbin',
@@ -634,8 +634,8 @@ class XenAPIVMTestCase(test.TestCase):
def _umount_handler(cmd, *ignore_args, **ignore_kwargs): def _umount_handler(cmd, *ignore_args, **ignore_kwargs):
# Umount would normall make files in the m,ounted filesystem # Umount would normall make files in the m,ounted filesystem
# disappear, so do that here # disappear, so do that here
LOG.debug(_('Removing simulated guest agent files in %s') % LOG.debug(_('Removing simulated guest agent files in %s'),
self._tmpdir) self._tmpdir)
os.remove(os.path.join(self._tmpdir, 'usr', 'sbin', os.remove(os.path.join(self._tmpdir, 'usr', 'sbin',
'xe-update-networking')) 'xe-update-networking'))
os.rmdir(os.path.join(self._tmpdir, 'usr', 'sbin')) os.rmdir(os.path.join(self._tmpdir, 'usr', 'sbin'))