18
18
# with Python under the Python License, which is GPL compatible.
20
20
"""Extract docstrings from Bazaar commands.
22
This module only handles bzrlib objects that use strings not directly wrapped
23
by a gettext() call. To generate a complete translation template file, this
24
output needs to be combined with that of xgettext or a similar command for
25
extracting those strings, as is done in the bzr Makefile. Sorting the output
26
is also left to that stage of the process.
65
_FOUND_MSGID = None # set by entry function.
67
def _poentry(outf, path, lineno, s, comment=None):
74
comment = "# %s\n" % comment
75
mutter("Exporting msg %r at line %d in %r", s[:20], lineno, path)
76
print >>outf, ('#: %s:%d\n' % (path, lineno) +
78
'msgid %s\n' % _normalize(s) +
81
def _poentry_per_paragraph(outf, path, lineno, msgid, filter=lambda x: False):
82
# TODO: How to split long help?
83
paragraphs = msgid.split('\n\n')
87
_poentry(outf, path, lineno, p)
88
lineno += p.count('\n') + 2
71
class _PotExporter(object):
72
"""Write message details to output stream in .pot file format"""
74
def __init__(self, outf):
78
def poentry(self, path, lineno, s, comment=None):
85
comment = "# %s\n" % comment
86
mutter("Exporting msg %r at line %d in %r", s[:20], lineno, path)
88
"#: {path}:{lineno}\n"
93
path=path, lineno=lineno, comment=comment, msg=_normalize(s)))
95
def poentry_per_paragraph(self, path, lineno, msgid, include=None):
96
# TODO: How to split long help?
97
paragraphs = msgid.split('\n\n')
98
if include is not None:
99
paragraphs = filter(include, paragraphs)
101
self.poentry(path, lineno, p)
102
lineno += p.count('\n') + 2
90
105
_LAST_CACHE = _LAST_CACHED_SRC = None
106
121
_LAST_CACHE = offsets.copy()
109
def _standard_options(outf):
124
def _standard_options(exporter):
110
125
from bzrlib.option import Option
111
126
src = inspect.findsource(Option)[0]
112
127
src = ''.join(src)
121
136
lineno = offsets.get(opt.title, 9999)
122
137
if lineno == 9999:
123
138
note(gettext("%r is not found in bzrlib/option.py") % opt.title)
124
_poentry(outf, path, lineno, opt.title,
139
exporter.poentry(path, lineno, opt.title,
125
140
'title of %r option' % name)
126
141
if getattr(opt, 'help', None):
127
142
lineno = offsets.get(opt.help, 9999)
128
143
if lineno == 9999:
129
144
note(gettext("%r is not found in bzrlib/option.py") % opt.help)
130
_poentry(outf, path, lineno, opt.help,
145
exporter.poentry(path, lineno, opt.help,
131
146
'help of %r option' % name)
133
def _command_options(outf, path, cmd):
148
def _command_options(exporter, path, cmd):
134
149
src, default_lineno = inspect.findsource(cmd.__class__)
135
150
offsets = _offsets_of_literal(''.join(src))
136
151
for opt in cmd.takes_options:
142
157
if getattr(opt, 'title', None):
143
158
lineno = offsets.get(opt.title, default_lineno)
144
_poentry(outf, path, lineno, opt.title,
159
exporter.poentry(path, lineno, opt.title,
145
160
'title of %r option of %r command' % (name, cmd.name()))
146
161
if getattr(opt, 'help', None):
147
162
lineno = offsets.get(opt.help, default_lineno)
148
_poentry(outf, path, lineno, opt.help,
163
exporter.poentry(path, lineno, opt.help,
149
164
'help of %r option of %r command' % (name, cmd.name()))
152
def _write_command_help(outf, cmd):
167
def _write_command_help(exporter, cmd):
153
168
path = inspect.getfile(cmd.__class__)
154
169
if path.endswith('.pyc'):
159
174
lineno = offsets[cmd.__doc__]
160
175
doc = inspect.getdoc(cmd)
177
def exclude_usage(p):
163
178
# ':Usage:' has special meaning in help topics.
164
179
# This is usage example of command and should not be translated.
165
if p.splitlines()[0] == ':Usage:':
180
if p.splitlines()[0] != ':Usage:':
168
_poentry_per_paragraph(outf, path, lineno, doc, filter)
169
_command_options(outf, path, cmd)
172
def _command_helps(outf, plugin_name=None):
183
exporter.poentry_per_paragraph(path, lineno, doc, exclude_usage)
184
_command_options(exporter, path, cmd)
187
def _command_helps(exporter, plugin_name=None):
173
188
"""Extract docstrings from path.
175
190
This respects the Bazaar cmdtable/table convention and will
186
201
# only export builtins if we are not exporting plugin commands
188
203
note(gettext("Exporting messages from builtin command: %s"), cmd_name)
189
_write_command_help(outf, command)
204
_write_command_help(exporter, command)
191
206
plugin_path = plugin.get_core_plugin_path()
192
207
core_plugins = glob(plugin_path + '/*/__init__.py')
207
222
note(gettext("Exporting messages from plugin command: {0} in {1}").format(
208
223
cmd_name, command.plugin_name() ))
209
_write_command_help(outf, command)
212
def _error_messages(outf):
224
_write_command_help(exporter, command)
227
def _error_messages(exporter):
213
228
"""Extract fmt string from bzrlib.errors."""
214
229
path = errors.__file__
215
230
if path.endswith('.pyc'):
230
245
fmt = getattr(klass, "_fmt", None)
232
247
note(gettext("Exporting message from error: %s"), name)
233
_poentry(outf, 'bzrlib/errors.py',
248
exporter.poentry('bzrlib/errors.py',
234
249
offsets.get(fmt, 9999), fmt)
236
def _help_topics(outf):
251
def _help_topics(exporter):
237
252
topic_registry = help_topics.topic_registry
238
253
for key in topic_registry.keys():
239
254
doc = topic_registry.get(key)
240
255
if isinstance(doc, str):
241
_poentry_per_paragraph(
256
exporter.poentry_per_paragraph(
243
257
'dummy/help_topics/'+key+'/detail.txt',
245
259
elif callable(doc): # help topics from files
246
_poentry_per_paragraph(
260
exporter.poentry_per_paragraph(
248
261
'en/help_topics/'+key+'.txt',
250
263
summary = topic_registry.get_summary(key)
251
264
if summary is not None:
252
_poentry(outf, 'dummy/help_topics/'+key+'/summary.txt',
265
exporter.poentry('dummy/help_topics/'+key+'/summary.txt',
255
268
def export_pot(outf, plugin=None):
269
exporter = _PotExporter(outf)
258
270
if plugin is None:
259
_standard_options(outf)
261
_error_messages(outf)
271
_standard_options(exporter)
272
_command_helps(exporter)
273
_error_messages(exporter)
274
_help_topics(exporter)
264
_command_helps(outf, plugin)
276
_command_helps(exporter, plugin)