##// END OF EJS Templates
i18n: ignore docstring for modules under mercurial...
FUJIWARA Katsunori -
r33818:d5ef1760 default
parent child Browse files
Show More
@@ -1,161 +1,161 b''
1 1 #!/usr/bin/env python
2 2 #
3 3 # hggettext - carefully extract docstrings for Mercurial
4 4 #
5 5 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 # The normalize function is taken from pygettext which is distributed
11 11 # with Python under the Python License, which is GPL compatible.
12 12
13 13 """Extract docstrings from Mercurial commands.
14 14
15 15 Compared to pygettext, this script knows about the cmdtable and table
16 16 dictionaries used by Mercurial, and will only extract docstrings from
17 17 functions mentioned therein.
18 18
19 19 Use xgettext like normal to extract strings marked as translatable and
20 20 join the message cataloges to get the final catalog.
21 21 """
22 22
23 23 from __future__ import absolute_import, print_function
24 24
25 25 import inspect
26 26 import os
27 27 import re
28 28 import sys
29 29
30 30
31 31 def escape(s):
32 32 # The order is important, the backslash must be escaped first
33 33 # since the other replacements introduce new backslashes
34 34 # themselves.
35 35 s = s.replace('\\', '\\\\')
36 36 s = s.replace('\n', '\\n')
37 37 s = s.replace('\r', '\\r')
38 38 s = s.replace('\t', '\\t')
39 39 s = s.replace('"', '\\"')
40 40 return s
41 41
42 42
43 43 def normalize(s):
44 44 # This converts the various Python string types into a format that
45 45 # is appropriate for .po files, namely much closer to C style.
46 46 lines = s.split('\n')
47 47 if len(lines) == 1:
48 48 s = '"' + escape(s) + '"'
49 49 else:
50 50 if not lines[-1]:
51 51 del lines[-1]
52 52 lines[-1] = lines[-1] + '\n'
53 53 lines = map(escape, lines)
54 54 lineterm = '\\n"\n"'
55 55 s = '""\n"' + lineterm.join(lines) + '"'
56 56 return s
57 57
58 58
59 59 def poentry(path, lineno, s):
60 60 return ('#: %s:%d\n' % (path, lineno) +
61 61 'msgid %s\n' % normalize(s) +
62 62 'msgstr ""\n')
63 63
64 64 doctestre = re.compile(r'^ +>>> ', re.MULTILINE)
65 65
66 66 def offset(src, doc, name, default):
67 67 """Compute offset or issue a warning on stdout."""
68 68 # remove doctest part, in order to avoid backslash mismatching
69 69 m = doctestre.search(doc)
70 70 if m:
71 71 doc = doc[:m.start()]
72 72
73 73 # Backslashes in doc appear doubled in src.
74 74 end = src.find(doc.replace('\\', '\\\\'))
75 75 if end == -1:
76 76 # This can happen if the docstring contains unnecessary escape
77 77 # sequences such as \" in a triple-quoted string. The problem
78 78 # is that \" is turned into " and so doc wont appear in src.
79 79 sys.stderr.write("warning: unknown offset in %s, assuming %d lines\n"
80 80 % (name, default))
81 81 return default
82 82 else:
83 83 return src.count('\n', 0, end)
84 84
85 85
86 86 def importpath(path):
87 87 """Import a path like foo/bar/baz.py and return the baz module."""
88 88 if path.endswith('.py'):
89 89 path = path[:-3]
90 90 if path.endswith('/__init__'):
91 91 path = path[:-9]
92 92 path = path.replace('/', '.')
93 93 mod = __import__(path)
94 94 for comp in path.split('.')[1:]:
95 95 mod = getattr(mod, comp)
96 96 return mod
97 97
98 98
99 99 def docstrings(path):
100 100 """Extract docstrings from path.
101 101
102 102 This respects the Mercurial cmdtable/table convention and will
103 103 only extract docstrings from functions mentioned in these tables.
104 104 """
105 105 mod = importpath(path)
106 if mod.__doc__:
106 if not path.startswith('mercurial/') and mod.__doc__:
107 107 src = open(path).read()
108 108 lineno = 1 + offset(src, mod.__doc__, path, 7)
109 109 print(poentry(path, lineno, mod.__doc__))
110 110
111 111 functions = list(getattr(mod, 'i18nfunctions', []))
112 112 functions = [(f, True) for f in functions]
113 113
114 114 cmdtable = getattr(mod, 'cmdtable', {})
115 115 if not cmdtable:
116 116 # Maybe we are processing mercurial.commands?
117 117 cmdtable = getattr(mod, 'table', {})
118 118 functions.extend((c[0], False) for c in cmdtable.itervalues())
119 119
120 120 for func, rstrip in functions:
121 121 if func.__doc__:
122 122 docobj = func # this might be a proxy to provide formatted doc
123 123 func = getattr(func, '_origfunc', func)
124 124 funcmod = inspect.getmodule(func)
125 125 extra = ''
126 126 if funcmod.__package__ == funcmod.__name__:
127 127 extra = '/__init__'
128 128 actualpath = '%s%s.py' % (funcmod.__name__.replace('.', '/'), extra)
129 129
130 130 src = inspect.getsource(func)
131 131 name = "%s.%s" % (actualpath, func.__name__)
132 132 lineno = inspect.getsourcelines(func)[1]
133 133 doc = docobj.__doc__
134 134 origdoc = getattr(docobj, '_origdoc', '')
135 135 if rstrip:
136 136 doc = doc.rstrip()
137 137 origdoc = origdoc.rstrip()
138 138 if origdoc:
139 139 lineno += offset(src, origdoc, name, 1)
140 140 else:
141 141 lineno += offset(src, doc, name, 1)
142 142 print(poentry(actualpath, lineno, doc))
143 143
144 144
145 145 def rawtext(path):
146 146 src = open(path).read()
147 147 print(poentry(path, 1, src))
148 148
149 149
150 150 if __name__ == "__main__":
151 151 # It is very important that we import the Mercurial modules from
152 152 # the source tree where hggettext is executed. Otherwise we might
153 153 # accidentally import and extract strings from a Mercurial
154 154 # installation mentioned in PYTHONPATH.
155 155 sys.path.insert(0, os.getcwd())
156 156 from mercurial import demandimport; demandimport.enable()
157 157 for path in sys.argv[1:]:
158 158 if path.endswith('.txt'):
159 159 rawtext(path)
160 160 else:
161 161 docstrings(path)
General Comments 0
You need to be logged in to leave comments. Login now