/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
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):
5830.2.3 by INADA Naoki
bzrgettext extracts help message of command option too.
138
            lineno = inspect.findsource(obj)[1]
139
            poentry_per_paragraph(path, lineno, doc)
140
            options(path, lineno, obj)
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
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:
5830.2.3 by INADA Naoki
bzrgettext extracts help message of command option too.
158
            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
159
160
161
def rawtext(path):
162
    src = open(path).read()
5830.2.2 by INADA Naoki
Split command's docstring per paragraph.
163
    poentry_per_paragraph(path, 1, src)
5830.2.1 by INADA Naoki
Add update-pot command to Makefile and tools/bzrgettext script that
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()