47
46
# This converts the various Python string types into a format that
48
47
# is appropriate for .po files, namely much closer to C style.
49
48
lines = s.split('\n')
50
49
if len(lines) == 1:
51
s = '"' + escape(s) + '"'
50
s = '"' + _escape(s) + '"'
55
54
lines[-1] = lines[-1] + '\n'
56
lines = map(escape, lines)
55
lines = map(_escape, lines)
57
56
lineterm = '\\n"\n"'
58
57
s = '""\n"' + lineterm.join(lines) + '"'
61
_FOUND_MSGID = None # set by entry function.
64
def poentry(path, lineno, s, comment=None):
63
def _poentry(outf, path, lineno, s, comment=None):
68
67
if comment is None:
71
70
comment = "# %s\n" % comment
72
print ('#: %s:%d\n' % (path, lineno) +
71
print >>outf, ('#: %s:%d\n' % (path, lineno) +
74
'msgid %s\n' % normalize(s) +
73
'msgid %s\n' % _normalize(s) +
77
def poentry_per_paragraph(path, lineno, msgid):
76
def _poentry_per_paragraph(outf, path, lineno, msgid):
78
77
paragraphs = msgid.split('\n\n')
79
78
for p in paragraphs:
80
poentry(path, lineno, p)
79
_poentry(outf, path, lineno, p)
81
80
lineno += p.count('\n') + 2
83
def offset(src, doc, name, default):
82
def _offset(src, doc, default):
84
83
"""Compute offset or issue a warning on stdout."""
85
84
# Backslashes in doc appear doubled in src.
86
85
end = src.find(doc.replace('\\', '\\\\'))
88
# This can happen if the docstring contains unnecessary escape
89
# sequences such as \" in a triple-quoted string. The problem
90
# is that \" is turned into " and so doc wont appear in src.
91
sys.stderr.write("warning: unknown offset in %s, assuming %d lines\n"
95
89
return src.count('\n', 0, end)
99
"""Import a path like foo/bar/baz.py and return the baz module."""
100
if path.endswith('.py'):
102
if path.endswith('/__init__'):
104
path = path.replace('/', '.')
105
mod = __import__(path)
106
for comp in path.split('.')[1:]:
107
mod = getattr(mod, comp)
110
def options(path, lineno, cmdklass):
92
def _command_options(outf, path, cmd):
112
93
for name, opt in cmd.options().iteritems():
113
poentry(path, lineno, opt.help,
94
src, lineno = inspect.findsource(cmd.__class__)
95
lineno = _offset(''.join(src), opt.help, lineno)
96
_poentry(outf, path, lineno, opt.help,
114
97
"help of '%s' option of '%s' command" % (name, cmd.name()))
117
def docstrings(path):
100
def _write_command_help(outf, cmd_name, cmd):
101
path = inspect.getfile(cmd.__class__)
102
if path.endswith('.pyc'):
104
path = os.path.relpath(path)
105
lineno = inspect.findsource(cmd.__class__)[1]
106
doc = inspect.getdoc(cmd)
108
_poentry_per_paragraph(outf, path, lineno, doc)
109
_command_options(outf, path, cmd)
111
def _command_helps(outf):
118
112
"""Extract docstrings from path.
120
114
This respects the Bazaar cmdtable/table convention and will
121
115
only extract docstrings from functions mentioned in these tables.
123
from bzrlib.commands import Command as cmd_klass
125
mod = importpath(path)
126
except Exception as e:
127
# some module raises exception (ex. bzrlib.transport.ftp._gssapi
128
print >>sys.stderr, "Can't import %r: %s" % (path, e)
130
for name in dir(mod):
131
if not name.startswith('cmd_'):
133
obj = getattr(mod, name)
137
doc = inspect.cleandoc(doc)
140
except AttributeError:
142
if (inspect.isclass(obj) and issubclass(obj, cmd_klass)
143
and not obj is cmd_klass):
144
lineno = inspect.findsource(obj)[1]
145
poentry_per_paragraph(path, lineno, doc)
146
options(path, lineno, obj)
118
from glob import glob
121
for cmd_name in _mod_commands.builtin_command_names():
122
command = _mod_commands.get_cmd_object(cmd_name, False)
123
_write_command_help(outf, cmd_name, command)
125
plugin_path = bzrlib.plugin.get_core_plugin_path()
126
core_plugins = glob(plugin_path + '/*/__init__.py')
127
core_plugins = [os.path.basename(os.path.dirname(p))
128
for p in core_plugins]
130
for cmd_name in _mod_commands.plugin_command_names():
131
command = _mod_commands.get_cmd_object(cmd_name, False)
132
if command.plugin_name() not in core_plugins:
133
# skip non-core plugins
134
# TODO: Support extracting from third party plugins.
136
_write_command_help(outf, cmd_name, command)
139
def _error_messages(outf):
149
140
"""Extract fmt string from bzrlib.errors."""
150
141
from bzrlib import errors
151
142
base_klass = errors.BzrError
162
153
fmt = getattr(klass, "_fmt", None)
164
poentry('bzrlib/erros.py', inspect.findsource(klass)[1], fmt)
155
_poentry(outf, 'bzrlib/errors.py', inspect.findsource(klass)[1], fmt)
166
def bzr_helptopics():
157
def _help_topics(outf):
167
158
from bzrlib.help_topics import topic_registry
168
159
for key in topic_registry.keys():
169
160
doc = topic_registry.get(key)
170
161
if isinstance(doc, str):
171
poentry_per_paragraph(
162
_poentry_per_paragraph(
172
164
'dummy/help_topics/'+key+'/detail.txt',
175
167
summary = topic_registry.get_summary(key)
176
168
if summary is not None:
177
poentry('dummy/help_topics/'+key+'/summary.txt',
182
src = open(path).read()
183
poentry_per_paragraph(path, 1, src)
186
if __name__ == "__main__":
187
# It is very important that we import the Bazaar modules from
188
# the source tree where bzrgettext is executed. Otherwise we might
189
# accidentally import and extract strings from a Bazaar
190
# installation mentioned in PYTHONPATH.
191
sys.path.insert(0, os.getcwd())
194
with bzrlib.initialize():
195
for path in sys.argv[1:]:
196
if path.endswith('.txt'):
169
_poentry(outf, 'dummy/help_topics/'+key+'/summary.txt',
172
def export_pot(outf):
176
_error_messages(outf)