/breezy/3.0

To get this branch, use:
bzr branch https://code.breezy-vcs.org/breezy/3.0

« back to all changes in this revision

Viewing changes to tools/bzrgettext

  • Committer: INADA Naoki
  • Date: 2011-05-05 09:15:34 UTC
  • mto: (5830.3.3 i18n-msgfmt)
  • mto: This revision was merged to the branch mainline in revision 5873.
  • Revision ID: songofacandy@gmail.com-20110505091534-7sv835xpofwrmpt4
Add update-pot command to Makefile and tools/bzrgettext script that
extracts help text from bzr commands.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
#
 
3
# bzrgettext - extract docstrings for Bazaar commands
 
4
#
 
5
# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
 
6
# Copyright 2011 Canonical Ltd
 
7
#
 
8
# This program is free software; you can redistribute it and/or modify
 
9
# it under the terms of the GNU General Public License as published by
 
10
# the Free Software Foundation; either version 2 of the License, or
 
11
# (at your option) any later version.
 
12
#
 
13
# This program is distributed in the hope that it will be useful,
 
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
# GNU General Public License for more details.
 
17
#
 
18
# You should have received a copy of the GNU General Public License
 
19
# along with this program; if not, write to the Free Software
 
20
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
21
 
 
22
# This script is copied from mercurial/i18n/hggettext and modified
 
23
# for Bazaar.
 
24
 
 
25
# The normalize function is taken from pygettext which is distributed
 
26
# with Python under the Python License, which is GPL compatible.
 
27
 
 
28
 
 
29
"""Extract docstrings from Bazaar commands.
 
30
"""
 
31
 
 
32
import os, sys, inspect
 
33
 
 
34
 
 
35
def escape(s):
 
36
    s = (s.replace('\\', '\\\\')
 
37
        .replace('\n', '\\n')
 
38
        .replace('\r', '\\r')
 
39
        .replace('\t', '\\t')
 
40
        .replace('"', '\\"')
 
41
        )
 
42
    return s
 
43
 
 
44
 
 
45
def normalize(s):
 
46
    # This converts the various Python string types into a format that
 
47
    # is appropriate for .po files, namely much closer to C style.
 
48
    lines = s.split('\n')
 
49
    if len(lines) == 1:
 
50
        s = '"' + escape(s) + '"'
 
51
    else:
 
52
        if not lines[-1]:
 
53
            del lines[-1]
 
54
            lines[-1] = lines[-1] + '\n'
 
55
        lines = map(escape, lines)
 
56
        lineterm = '\\n"\n"'
 
57
        s = '""\n"' + lineterm.join(lines) + '"'
 
58
    return s
 
59
 
 
60
 
 
61
def poentry(path, lineno, s):
 
62
    return ('#: %s:%d\n' % (path, lineno) +
 
63
            'msgid %s\n' % normalize(s) +
 
64
            'msgstr ""\n')
 
65
 
 
66
 
 
67
def offset(src, doc, name, default):
 
68
    """Compute offset or issue a warning on stdout."""
 
69
    # Backslashes in doc appear doubled in src.
 
70
    end = src.find(doc.replace('\\', '\\\\'))
 
71
    if end == -1:
 
72
        # This can happen if the docstring contains unnecessary escape
 
73
        # sequences such as \" in a triple-quoted string. The problem
 
74
        # is that \" is turned into " and so doc wont appear in src.
 
75
        sys.stderr.write("warning: unknown offset in %s, assuming %d lines\n"
 
76
                         % (name, default))
 
77
        return default
 
78
    else:
 
79
        return src.count('\n', 0, end)
 
80
 
 
81
 
 
82
def importpath(path):
 
83
    """Import a path like foo/bar/baz.py and return the baz module."""
 
84
    if path.endswith('.py'):
 
85
        path = path[:-3]
 
86
    if path.endswith('/__init__'):
 
87
        path = path[:-9]
 
88
    path = path.replace('/', '.')
 
89
    mod = __import__(path)
 
90
    for comp in path.split('.')[1:]:
 
91
        mod = getattr(mod, comp)
 
92
    return mod
 
93
 
 
94
 
 
95
def docstrings(path):
 
96
    """Extract docstrings from path.
 
97
 
 
98
    This respects the Bazaar cmdtable/table convention and will
 
99
    only extract docstrings from functions mentioned in these tables.
 
100
    """
 
101
    from bzrlib.commands import Command as cmd_klass
 
102
    mod = importpath(path)
 
103
    for name in dir(mod):
 
104
        if not name.startswith('cmd_'):
 
105
            continue
 
106
        obj = getattr(mod, name)
 
107
        try:
 
108
            doc = obj.__doc__
 
109
            if doc:
 
110
                doc = inspect.cleandoc(doc)
 
111
            else:
 
112
                continue
 
113
        except AttributeError:
 
114
            continue
 
115
        if (inspect.isclass(obj) and issubclass(obj, cmd_klass)
 
116
                and not obj is cmd_klass):
 
117
            print poentry(path, inspect.findsource(obj)[1], doc)
 
118
 
 
119
def bzrerrors():
 
120
    """Extract fmt string from bzrlib.errors."""
 
121
    from bzrlib import errors
 
122
    base_klass = errors.BzrError
 
123
    for name in dir(errors):
 
124
        klass = getattr(errors, name)
 
125
        if not inspect.isclass(klass):
 
126
            continue
 
127
        if not issubclass(klass, base_klass):
 
128
            continue
 
129
        if klass is base_klass:
 
130
            continue
 
131
        if klass.internal_error:
 
132
            continue
 
133
        fmt = getattr(klass, "_fmt", None)
 
134
        if fmt:
 
135
            print poentry('bzrlib/erros.py',
 
136
                    inspect.findsource(klass)[1], fmt)
 
137
 
 
138
 
 
139
def rawtext(path):
 
140
    src = open(path).read()
 
141
    print poentry(path, 1, src)
 
142
 
 
143
 
 
144
if __name__ == "__main__":
 
145
    # It is very important that we import the Bazaar modules from
 
146
    # the source tree where bzrgettext is executed. Otherwise we might
 
147
    # accidentally import and extract strings from a Bazaar
 
148
    # installation mentioned in PYTHONPATH.
 
149
    sys.path.insert(0, os.getcwd())
 
150
    import bzrlib.lazy_import
 
151
    for path in sys.argv[1:]:
 
152
        if path.endswith('.txt'):
 
153
            rawtext(path)
 
154
        else:
 
155
            docstrings(path)
 
156
    bzrerrors()