Rev 6288: (gz) Add _PotExporter and other refactorings to export_pot module (Martin in file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/

Patch Queue Manager pqm at pqm.ubuntu.com
Thu Nov 24 13:40:44 UTC 2011


At file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 6288 [merge]
revision-id: pqm at pqm.ubuntu.com-20111124134044-fxzjs2iro5obaax9
parent: pqm at pqm.ubuntu.com-20111124131551-u7xzxgto1p1yfz57
parent: martin.packman at canonical.com-20111121130048-tnw5gyty1b59qrpn
committer: Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2011-11-24 13:40:44 +0000
message:
  (gz) Add _PotExporter and other refactorings to export_pot module (Martin
   Packman)
modified:
  bzrlib/export_pot.py           bzrgettext-20110429104643-3wjy38532whc21yj-2
  bzrlib/tests/test_export_pot.py test_export_pot.py-20110509102137-efovgz233s9uk2b2-1
=== modified file 'bzrlib/export_pot.py'
--- a/bzrlib/export_pot.py	2011-09-27 11:31:35 +0000
+++ b/bzrlib/export_pot.py	2011-11-21 13:00:48 +0000
@@ -18,6 +18,12 @@
 # with Python under the Python License, which is GPL compatible.
 
 """Extract docstrings from Bazaar commands.
+
+This module only handles bzrlib objects that use strings not directly wrapped
+by a gettext() call. To generate a complete translation template file, this
+output needs to be combined with that of xgettext or a similar command for
+extracting those strings, as is done in the bzr Makefile. Sorting the output
+is also left to that stage of the process.
 """
 
 import inspect
@@ -62,30 +68,39 @@
     return s
 
 
-_FOUND_MSGID = None # set by entry function.
-
-def _poentry(outf, path, lineno, s, comment=None):
-    if s in _FOUND_MSGID:
-        return
-    _FOUND_MSGID.add(s)
-    if comment is None:
-        comment = ''
-    else:
-        comment = "# %s\n" % comment
-    mutter("Exporting msg %r at line %d in %r", s[:20], lineno, path)
-    print >>outf, ('#: %s:%d\n' % (path, lineno) +
-           comment+
-           'msgid %s\n' % _normalize(s) +
-           'msgstr ""\n')
-
-def _poentry_per_paragraph(outf, path, lineno, msgid, filter=lambda x: False):
-    # TODO: How to split long help?
-    paragraphs = msgid.split('\n\n')
-    for p in paragraphs:
-        if filter(p):
-            continue
-        _poentry(outf, path, lineno, p)
-        lineno += p.count('\n') + 2
+class _PotExporter(object):
+    """Write message details to output stream in .pot file format"""
+
+    def __init__(self, outf):
+        self.outf = outf
+        self._msgids = set()
+
+    def poentry(self, path, lineno, s, comment=None):
+        if s in self._msgids:
+            return
+        self._msgids.add(s)
+        if comment is None:
+            comment = ''
+        else:
+            comment = "# %s\n" % comment
+        mutter("Exporting msg %r at line %d in %r", s[:20], lineno, path)
+        self.outf.write(
+            "#: {path}:{lineno}\n"
+            "{comment}"
+            "msgid {msg}\n"
+            "msgstr \"\"\n"
+            "\n".format(
+                path=path, lineno=lineno, comment=comment, msg=_normalize(s)))
+
+    def poentry_per_paragraph(self, path, lineno, msgid, include=None):
+        # TODO: How to split long help?
+        paragraphs = msgid.split('\n\n')
+        if include is not None:
+            paragraphs = filter(include, paragraphs)
+        for p in paragraphs:
+            self.poentry(path, lineno, p)
+            lineno += p.count('\n') + 2
+
 
 _LAST_CACHE = _LAST_CACHED_SRC = None
 
@@ -106,7 +121,7 @@
     _LAST_CACHE = offsets.copy()
     return offsets
 
-def _standard_options(outf):
+def _standard_options(exporter):
     from bzrlib.option import Option
     src = inspect.findsource(Option)[0]
     src = ''.join(src)
@@ -121,16 +136,16 @@
             lineno = offsets.get(opt.title, 9999)
             if lineno == 9999:
                 note(gettext("%r is not found in bzrlib/option.py") % opt.title)
-            _poentry(outf, path, lineno, opt.title,
+            exporter.poentry(path, lineno, opt.title,
                      'title of %r option' % name)
         if getattr(opt, 'help', None):
             lineno = offsets.get(opt.help, 9999)
             if lineno == 9999:
                 note(gettext("%r is not found in bzrlib/option.py") % opt.help)
-            _poentry(outf, path, lineno, opt.help,
+            exporter.poentry(path, lineno, opt.help,
                      'help of %r option' % name)
 
-def _command_options(outf, path, cmd):
+def _command_options(exporter, path, cmd):
     src, default_lineno = inspect.findsource(cmd.__class__)
     offsets = _offsets_of_literal(''.join(src))
     for opt in cmd.takes_options:
@@ -141,15 +156,15 @@
         name = opt.name
         if getattr(opt, 'title', None):
             lineno = offsets.get(opt.title, default_lineno)
-            _poentry(outf, path, lineno, opt.title,
+            exporter.poentry(path, lineno, opt.title,
                      'title of %r option of %r command' % (name, cmd.name()))
         if getattr(opt, 'help', None):
             lineno = offsets.get(opt.help, default_lineno)
-            _poentry(outf, path, lineno, opt.help,
+            exporter.poentry(path, lineno, opt.help,
                      'help of %r option of %r command' % (name, cmd.name()))
 
 
-def _write_command_help(outf, cmd):
+def _write_command_help(exporter, cmd):
     path = inspect.getfile(cmd.__class__)
     if path.endswith('.pyc'):
         path = path[:-1]
@@ -159,17 +174,17 @@
     lineno = offsets[cmd.__doc__]
     doc = inspect.getdoc(cmd)
 
-    def filter(p):
+    def exclude_usage(p):
         # ':Usage:' has special meaning in help topics.
         # This is usage example of command and should not be translated.
-        if p.splitlines()[0] == ':Usage:':
+        if p.splitlines()[0] != ':Usage:':
             return True
 
-    _poentry_per_paragraph(outf, path, lineno, doc, filter)
-    _command_options(outf, path, cmd)
-
-
-def _command_helps(outf, plugin_name=None):
+    exporter.poentry_per_paragraph(path, lineno, doc, exclude_usage)
+    _command_options(exporter, path, cmd)
+
+
+def _command_helps(exporter, plugin_name=None):
     """Extract docstrings from path.
 
     This respects the Bazaar cmdtable/table convention and will
@@ -186,7 +201,7 @@
             # only export builtins if we are not exporting plugin commands
             continue
         note(gettext("Exporting messages from builtin command: %s"), cmd_name)
-        _write_command_help(outf, command)
+        _write_command_help(exporter, command)
 
     plugin_path = plugin.get_core_plugin_path()
     core_plugins = glob(plugin_path + '/*/__init__.py')
@@ -206,10 +221,10 @@
             continue
         note(gettext("Exporting messages from plugin command: {0} in {1}").format(
              cmd_name, command.plugin_name() ))
-        _write_command_help(outf, command)
-
-
-def _error_messages(outf):
+        _write_command_help(exporter, command)
+
+
+def _error_messages(exporter):
     """Extract fmt string from bzrlib.errors."""
     path = errors.__file__
     if path.endswith('.pyc'):
@@ -230,35 +245,32 @@
         fmt = getattr(klass, "_fmt", None)
         if fmt:
             note(gettext("Exporting message from error: %s"), name)
-            _poentry(outf, 'bzrlib/errors.py',
+            exporter.poentry('bzrlib/errors.py',
                      offsets.get(fmt, 9999), fmt)
 
-def _help_topics(outf):
+def _help_topics(exporter):
     topic_registry = help_topics.topic_registry
     for key in topic_registry.keys():
         doc = topic_registry.get(key)
         if isinstance(doc, str):
-            _poentry_per_paragraph(
-                    outf,
+            exporter.poentry_per_paragraph(
                     'dummy/help_topics/'+key+'/detail.txt',
                     1, doc)
         elif callable(doc): # help topics from files
-            _poentry_per_paragraph(
-                    outf,
+            exporter.poentry_per_paragraph(
                     'en/help_topics/'+key+'.txt',
                     1, doc(key))
         summary = topic_registry.get_summary(key)
         if summary is not None:
-            _poentry(outf, 'dummy/help_topics/'+key+'/summary.txt',
+            exporter.poentry('dummy/help_topics/'+key+'/summary.txt',
                      1, summary)
 
 def export_pot(outf, plugin=None):
-    global _FOUND_MSGID
-    _FOUND_MSGID = set()
+    exporter = _PotExporter(outf)
     if plugin is None:
-        _standard_options(outf)
-        _command_helps(outf)
-        _error_messages(outf)
-        _help_topics(outf)
+        _standard_options(exporter)
+        _command_helps(exporter)
+        _error_messages(exporter)
+        _help_topics(exporter)
     else:
-        _command_helps(outf, plugin)
+        _command_helps(exporter, plugin)

=== modified file 'bzrlib/tests/test_export_pot.py'
--- a/bzrlib/tests/test_export_pot.py	2011-06-28 10:28:29 +0000
+++ b/bzrlib/tests/test_export_pot.py	2011-11-21 13:00:48 +0000
@@ -70,21 +70,20 @@
 class PoEntryTestCase(tests.TestCase):
 
     def setUp(self):
-        self.overrideAttr(export_pot, '_FOUND_MSGID', set())
-        self._outf = StringIO()
         super(PoEntryTestCase, self).setUp()
+        self.exporter = export_pot._PotExporter(StringIO())
 
     def check_output(self, expected):
         self.assertEqual(
-                self._outf.getvalue(),
+                self.exporter.outf.getvalue(),
                 textwrap.dedent(expected)
                 )
 
 class TestPoEntry(PoEntryTestCase):
 
     def test_simple(self):
-        export_pot._poentry(self._outf, 'dummy', 1, "spam")
-        export_pot._poentry(self._outf, 'dummy', 2, "ham", 'EGG')
+        self.exporter.poentry('dummy', 1, "spam")
+        self.exporter.poentry('dummy', 2, "ham", 'EGG')
         self.check_output('''\
                 #: dummy:1
                 msgid "spam"
@@ -98,9 +97,9 @@
                 ''')
 
     def test_duplicate(self):
-        export_pot._poentry(self._outf, 'dummy', 1, "spam")
+        self.exporter.poentry('dummy', 1, "spam")
         # This should be ignored.
-        export_pot._poentry(self._outf, 'dummy', 2, "spam", 'EGG')
+        self.exporter.poentry('dummy', 2, "spam", 'EGG')
 
         self.check_output('''\
                 #: dummy:1
@@ -112,8 +111,7 @@
 class TestPoentryPerPergraph(PoEntryTestCase):
 
     def test_single(self):
-        export_pot._poentry_per_paragraph(
-                self._outf,
+        self.exporter.poentry_per_paragraph(
                 'dummy',
                 10,
                 '''foo\nbar\nbaz\n'''
@@ -128,8 +126,7 @@
                 ''')
 
     def test_multi(self):
-        export_pot._poentry_per_paragraph(
-                self._outf,
+        self.exporter.poentry_per_paragraph(
                 'dummy',
                 10,
                 '''spam\nham\negg\n\nSPAM\nHAM\nEGG\n'''
@@ -169,8 +166,8 @@
             Blah Blah Blah
             """
 
-        export_pot._write_command_help(self._outf, cmd_Demo())
-        result = self._outf.getvalue()
+        export_pot._write_command_help(self.exporter, cmd_Demo())
+        result = self.exporter.outf.getvalue()
         # We don't care about filename and lineno here.
         result = re.sub(r'(?m)^#: [^\n]+\n', '', result)
 




More information about the bazaar-commits mailing list