/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
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
5830.2.3 by INADA Naoki
bzrgettext extracts help message of command option too.
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')
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
75
5830.2.2 by INADA Naoki
Split command's docstring per paragraph.
76
def poentry_per_paragraph(path, lineno, msgid):
77
    paragraphs = msgid.split('\n\n')
78
    for p in paragraphs:
5830.2.3 by INADA Naoki
bzrgettext extracts help message of command option too.
79
        poentry(path, lineno, p)
5830.2.2 by INADA Naoki
Split command's docstring per paragraph.
80
        lineno += p.count('\n') + 2
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
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
5830.2.3 by INADA Naoki
bzrgettext extracts help message of command option too.
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
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
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
5830.2.6 by INADA Naoki
Add target of bzrgettext.py
123
    try:
124
        mod = importpath(path)
5830.2.8 by INADA Naoki
Print path and exception when fail to import a module.
125
    except Exception as e:
5830.2.6 by INADA Naoki
Add target of bzrgettext.py
126
        # some module raises exception (ex. bzrlib.transport.ftp._gssapi
5830.2.8 by INADA Naoki
Print path and exception when fail to import a module.
127
        print >>sys.stderr, "Can't import %r: %s" % (path, e)
5830.2.6 by INADA Naoki
Add target of bzrgettext.py
128
        return
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
129
    for name in dir(mod):
130
        if not name.startswith('cmd_'):
131
            continue
132
        obj = getattr(mod, name)
133
        try:
134
            doc = obj.__doc__
135
            if doc:
136
                doc = inspect.cleandoc(doc)
137
            else:
138
                continue
139
        except AttributeError:
140
            continue
141
        if (inspect.isclass(obj) and issubclass(obj, cmd_klass)
142
                and not obj is cmd_klass):
5830.2.3 by INADA Naoki
bzrgettext extracts help message of command option too.
143
            lineno = inspect.findsource(obj)[1]
144
            poentry_per_paragraph(path, lineno, doc)
145
            options(path, lineno, obj)
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
146
147
def bzrerrors():
148
    """Extract fmt string from bzrlib.errors."""
149
    from bzrlib import errors
150
    base_klass = errors.BzrError
151
    for name in dir(errors):
152
        klass = getattr(errors, name)
153
        if not inspect.isclass(klass):
154
            continue
155
        if not issubclass(klass, base_klass):
156
            continue
157
        if klass is base_klass:
158
            continue
159
        if klass.internal_error:
160
            continue
161
        fmt = getattr(klass, "_fmt", None)
162
        if fmt:
5830.2.3 by INADA Naoki
bzrgettext extracts help message of command option too.
163
            poentry('bzrlib/erros.py', inspect.findsource(klass)[1], fmt)
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
164
165
166
def rawtext(path):
167
    src = open(path).read()
5830.2.2 by INADA Naoki
Split command's docstring per paragraph.
168
    poentry_per_paragraph(path, 1, src)
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
169
170
171
if __name__ == "__main__":
172
    # It is very important that we import the Bazaar modules from
173
    # the source tree where bzrgettext is executed. Otherwise we might
174
    # accidentally import and extract strings from a Bazaar
175
    # installation mentioned in PYTHONPATH.
176
    sys.path.insert(0, os.getcwd())
177
    import bzrlib.lazy_import
178
    for path in sys.argv[1:]:
179
        if path.endswith('.txt'):
180
            rawtext(path)
181
        else:
182
            docstrings(path)
183
    bzrerrors()