/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to tools/bzrgettext

  • Committer: INADA Naoki
  • Date: 2011-05-05 12:53:46 UTC
  • mto: This revision was merged to the branch mainline in revision 5891.
  • Revision ID: songofacandy@gmail.com-20110505125346-glducdbkzy4cw45x
Add build_mo command to setup. It makes .mo files into bzrlib/<lang>/LC_MESSAGES/bzr.mo
The mo files is installed as a bzrlib's package_data.

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
MSGID_FOUND = set()
 
62
 
 
63
def poentry(path, lineno, s, comment=None):
 
64
    if s in MSGID_FOUND:
 
65
        return
 
66
    MSGID_FOUND.add(s)
 
67
    if comment is None:
 
68
        comment = ''
 
69
    else:
 
70
        comment = "# %s\n" % comment
 
71
    print ('#: %s:%d\n' % (path, lineno) +
 
72
           comment+
 
73
           'msgid %s\n' % normalize(s) +
 
74
           'msgstr ""\n')
 
75
 
 
76
def poentry_per_paragraph(path, lineno, msgid):
 
77
    paragraphs = msgid.split('\n\n')
 
78
    for p in paragraphs:
 
79
        poentry(path, lineno, p)
 
80
        lineno += p.count('\n') + 2
 
81
 
 
82
def offset(src, doc, name, default):
 
83
    """Compute offset or issue a warning on stdout."""
 
84
    # Backslashes in doc appear doubled in src.
 
85
    end = src.find(doc.replace('\\', '\\\\'))
 
86
    if end == -1:
 
87
        # This can happen if the docstring contains unnecessary escape
 
88
        # sequences such as \" in a triple-quoted string. The problem
 
89
        # is that \" is turned into " and so doc wont appear in src.
 
90
        sys.stderr.write("warning: unknown offset in %s, assuming %d lines\n"
 
91
                         % (name, default))
 
92
        return default
 
93
    else:
 
94
        return src.count('\n', 0, end)
 
95
 
 
96
 
 
97
def importpath(path):
 
98
    """Import a path like foo/bar/baz.py and return the baz module."""
 
99
    if path.endswith('.py'):
 
100
        path = path[:-3]
 
101
    if path.endswith('/__init__'):
 
102
        path = path[:-9]
 
103
    path = path.replace('/', '.')
 
104
    mod = __import__(path)
 
105
    for comp in path.split('.')[1:]:
 
106
        mod = getattr(mod, comp)
 
107
    return mod
 
108
 
 
109
def options(path, lineno, cmdklass):
 
110
    cmd = cmdklass()
 
111
    for name, opt in cmd.options().iteritems():
 
112
        poentry(path, lineno, opt.help,
 
113
                "help of '%s' option of '%s' command" % (name, cmd.name()))
 
114
 
 
115
 
 
116
def docstrings(path):
 
117
    """Extract docstrings from path.
 
118
 
 
119
    This respects the Bazaar cmdtable/table convention and will
 
120
    only extract docstrings from functions mentioned in these tables.
 
121
    """
 
122
    from bzrlib.commands import Command as cmd_klass
 
123
    mod = importpath(path)
 
124
    for name in dir(mod):
 
125
        if not name.startswith('cmd_'):
 
126
            continue
 
127
        obj = getattr(mod, name)
 
128
        try:
 
129
            doc = obj.__doc__
 
130
            if doc:
 
131
                doc = inspect.cleandoc(doc)
 
132
            else:
 
133
                continue
 
134
        except AttributeError:
 
135
            continue
 
136
        if (inspect.isclass(obj) and issubclass(obj, cmd_klass)
 
137
                and not obj is cmd_klass):
 
138
            lineno = inspect.findsource(obj)[1]
 
139
            poentry_per_paragraph(path, lineno, doc)
 
140
            options(path, lineno, obj)
 
141
 
 
142
def bzrerrors():
 
143
    """Extract fmt string from bzrlib.errors."""
 
144
    from bzrlib import errors
 
145
    base_klass = errors.BzrError
 
146
    for name in dir(errors):
 
147
        klass = getattr(errors, name)
 
148
        if not inspect.isclass(klass):
 
149
            continue
 
150
        if not issubclass(klass, base_klass):
 
151
            continue
 
152
        if klass is base_klass:
 
153
            continue
 
154
        if klass.internal_error:
 
155
            continue
 
156
        fmt = getattr(klass, "_fmt", None)
 
157
        if fmt:
 
158
            poentry('bzrlib/erros.py', inspect.findsource(klass)[1], fmt)
 
159
 
 
160
 
 
161
def rawtext(path):
 
162
    src = open(path).read()
 
163
    poentry_per_paragraph(path, 1, src)
 
164
 
 
165
 
 
166
if __name__ == "__main__":
 
167
    # It is very important that we import the Bazaar modules from
 
168
    # the source tree where bzrgettext is executed. Otherwise we might
 
169
    # accidentally import and extract strings from a Bazaar
 
170
    # installation mentioned in PYTHONPATH.
 
171
    sys.path.insert(0, os.getcwd())
 
172
    import bzrlib.lazy_import
 
173
    for path in sys.argv[1:]:
 
174
        if path.endswith('.txt'):
 
175
            rawtext(path)
 
176
        else:
 
177
            docstrings(path)
 
178
    bzrerrors()