##// END OF EJS Templates
hggettext: ensure correct Mercurial is imported
Martin Geisler -
r8626:1fc1c77d default
parent child Browse files
Show More
@@ -1,118 +1,123
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, incorporated herein by reference.
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 from mercurial import demandimport; demandimport.enable()
24 import sys, inspect
23 import os, sys, inspect
25 24
26 25
27 26 def escape(s):
28 27 # The order is important, the backslash must be escaped first
29 28 # since the other replacements introduce new backslashes
30 29 # themselves.
31 30 s = s.replace('\\', '\\\\')
32 31 s = s.replace('\n', '\\n')
33 32 s = s.replace('\r', '\\r')
34 33 s = s.replace('\t', '\\t')
35 34 s = s.replace('"', '\\"')
36 35 return s
37 36
38 37
39 38 def normalize(s):
40 39 # This converts the various Python string types into a format that
41 40 # is appropriate for .po files, namely much closer to C style.
42 41 lines = s.split('\n')
43 42 if len(lines) == 1:
44 43 s = '"' + escape(s) + '"'
45 44 else:
46 45 if not lines[-1]:
47 46 del lines[-1]
48 47 lines[-1] = lines[-1] + '\n'
49 48 lines = map(escape, lines)
50 49 lineterm = '\\n"\n"'
51 50 s = '""\n"' + lineterm.join(lines) + '"'
52 51 return s
53 52
54 53
55 54 def poentry(path, lineno, s):
56 55 return ('#: %s:%d\n' % (path, lineno) +
57 56 'msgid %s\n' % normalize(s) +
58 57 'msgstr ""\n')
59 58
60 59
61 60 def offset(src, doc, name, default):
62 61 """Compute offset or issue a warning on stdout."""
63 62 # Backslashes in doc appear doubled in src.
64 63 end = src.find(doc.replace('\\', '\\\\'))
65 64 if end == -1:
66 65 # This can happen if the docstring contains unnecessary escape
67 66 # sequences such as \" in a triple-quoted string. The problem
68 67 # is that \" is turned into " and so doc wont appear in src.
69 68 sys.stderr.write("warning: unknown offset in %s, assuming %d lines\n"
70 69 % (name, default))
71 70 return default
72 71 else:
73 72 return src.count('\n', 0, end)
74 73
75 74
76 75 def importpath(path):
77 76 """Import a path like foo/bar/baz.py and return the baz module."""
78 77 if path.endswith('.py'):
79 78 path = path[:-3]
80 79 if path.endswith('/__init__'):
81 80 path = path[:-9]
82 81 path = path.replace('/', '.')
83 82 mod = __import__(path)
84 83 for comp in path.split('.')[1:]:
85 84 mod = getattr(mod, comp)
86 85 return mod
87 86
88 87
89 88 def docstrings(path):
90 89 """Extract docstrings from path.
91 90
92 91 This respects the Mercurial cmdtable/table convention and will
93 92 only extract docstrings from functions mentioned in these tables.
94 93 """
95 94 mod = importpath(path)
96 95 if mod.__doc__:
97 96 src = open(path).read()
98 97 lineno = 1 + offset(src, mod.__doc__, path, 7)
99 98 print poentry(path, lineno, mod.__doc__)
100 99
101 100 cmdtable = getattr(mod, 'cmdtable', {})
102 101 if not cmdtable:
103 102 # Maybe we are processing mercurial.commands?
104 103 cmdtable = getattr(mod, 'table', {})
105 104
106 105 for entry in cmdtable.itervalues():
107 106 func = entry[0]
108 107 if func.__doc__:
109 108 src = inspect.getsource(func)
110 109 name = "%s.%s" % (path, func.__name__)
111 110 lineno = func.func_code.co_firstlineno
112 111 lineno += offset(src, func.__doc__, name, 1)
113 112 print poentry(path, lineno, func.__doc__)
114 113
115 114
116 115 if __name__ == "__main__":
116 # It is very important that we import the Mercurial modules from
117 # the source tree where hggettext is executed. Otherwise we might
118 # accidentally import and extract strings from a Mercurial
119 # installation mentioned in PYTHONPATH.
120 sys.path.insert(0, os.getcwd())
121 from mercurial import demandimport; demandimport.enable()
117 122 for path in sys.argv[1:]:
118 123 docstrings(path)
General Comments 0
You need to be logged in to leave comments. Login now