Mercurial > babel > mirror
annotate babel/messages/extract.py @ 54:7dbcbc3f07e0 trunk
Rename the `babel.catalog` package to `babel.messages` for consistency with the other package names.
author | cmlenz |
---|---|
date | Fri, 08 Jun 2007 09:16:32 +0000 |
parents | babel/catalog/extract.py@f8469ab4b257 |
children | f40fc143439c |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
3 # Copyright (C) 2007 Edgewall Software | |
4 # All rights reserved. | |
5 # | |
6 # This software is licensed as described in the file COPYING, which | |
7 # you should have received as part of this distribution. The terms | |
8 # are also available at http://babel.edgewall.org/wiki/License. | |
9 # | |
10 # This software consists of voluntary contributions made by many | |
11 # individuals. For the exact contribution history, see the revision | |
12 # history and logs, available at http://babel.edgewall.org/log/. | |
13 | |
14 """Basic infrastructure for extracting localizable messages from source files. | |
15 | |
16 This module defines an extensible system for collecting localizable message | |
17 strings from a variety of sources. A native extractor for Python source files | |
18 is builtin, extractors for other sources can be added using very simple plugins. | |
19 | |
20 The main entry points into the extraction functionality are the functions | |
21 `extract_from_dir` and `extract_from_file`. | |
22 """ | |
23 | |
24 import os | |
44 | 25 try: |
26 set | |
27 except NameError: | |
28 from sets import Set as set | |
1 | 29 import sys |
30 from tokenize import generate_tokens, NAME, OP, STRING | |
31 | |
44 | 32 from babel.util import pathmatch, relpath |
1 | 33 |
34 __all__ = ['extract', 'extract_from_dir', 'extract_from_file'] | |
35 __docformat__ = 'restructuredtext en' | |
36 | |
37 GROUP_NAME = 'babel.extractors' | |
38 | |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
39 DEFAULT_KEYWORDS = { |
10
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
40 '_': None, |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
41 'gettext': None, |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
42 'ngettext': (1, 2), |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
43 'ugettext': None, |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
44 'ungettext': (1, 2), |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
45 'dgettext': (2,), |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
46 'dngettext': (2, 3), |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
47 } |
1 | 48 |
49 DEFAULT_MAPPING = { | |
44 | 50 '**.html': 'genshi', |
51 '**.py': 'python' | |
1 | 52 } |
53 | |
47
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
54 def extract_from_dir(dirname=os.getcwd(), method_map=DEFAULT_MAPPING, |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
55 options_map=None, keywords=DEFAULT_KEYWORDS, |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
56 callback=None): |
1 | 57 """Extract messages from any source files found in the given directory. |
58 | |
59 This function generates tuples of the form: | |
60 | |
61 ``(filename, lineno, funcname, message)`` | |
62 | |
44 | 63 Which extraction method is used per file is determined by the `method_map` |
64 parameter, which maps extended glob patterns to extraction method names. | |
65 For example, the following is the default mapping: | |
1 | 66 |
44 | 67 >>> method_map = { |
68 ... '**.py': 'python' | |
1 | 69 ... } |
70 | |
71 This basically says that files with the filename extension ".py" at any | |
72 level inside the directory should be processed by the "python" extraction | |
44 | 73 method. Files that don't match any of the mapping patterns are ignored. See |
74 the documentation of the `pathmatch` function for details on the pattern | |
75 syntax. | |
1 | 76 |
77 The following extended mapping would also use the "genshi" extraction method | |
78 on any file in "templates" subdirectory: | |
79 | |
44 | 80 >>> method_map = { |
81 ... '**/templates/**.*': 'genshi', | |
82 ... '**.py': 'python' | |
83 ... } | |
84 | |
85 The dictionary provided by the optional `options_map` parameter augments | |
86 the mapping data. It too uses extended glob patterns as keys, but the values | |
87 are dictionaries mapping options names to option values (both strings). | |
88 | |
89 The glob patterns of the `options_map` do not necessarily need to be the | |
90 same as those used in the pattern. For example, while all files in the | |
91 ``templates`` folders in an application may be Genshi applications, the | |
92 options for those files may differ based on extension: | |
93 | |
94 >>> options_map = { | |
95 ... '**/templates/**.txt': { | |
96 ... 'template_class': 'genshi.template.text.TextTemplate', | |
97 ... 'encoding': 'latin-1' | |
98 ... }, | |
99 ... '**/templates/**.html': { | |
100 ... 'include_attrs': '' | |
101 ... } | |
1 | 102 ... } |
103 | |
104 :param dirname: the path to the directory to extract messages from | |
44 | 105 :param method_map: a mapping of extraction method names to extended glob |
106 patterns | |
107 :param options_map: a dictionary of additional options (optional) | |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
108 :param keywords: a dictionary mapping keywords (i.e. names of functions |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
109 that should be recognized as translation functions) to |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
110 tuples that specify which of their arguments contain |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
111 localizable strings |
47
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
112 :param callback: a function that is called for every file that message are |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
113 extracted from, just before the extraction itself is |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
114 performed; the function is passed the filename and the |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
115 options dictionary as positional arguments, in that order |
1 | 116 :return: an iterator over ``(filename, lineno, funcname, message)`` tuples |
117 :rtype: ``iterator`` | |
44 | 118 :see: `pathmatch` |
1 | 119 """ |
44 | 120 if options_map is None: |
121 options_map = {} | |
122 absname = os.path.abspath(dirname) | |
123 for root, dirnames, filenames in os.walk(absname): | |
124 for subdir in dirnames: | |
125 if subdir.startswith('.') or subdir.startswith('_'): | |
126 dirnames.remove(subdir) | |
127 for filename in filenames: | |
128 filename = relpath( | |
129 os.path.join(root, filename).replace(os.sep, '/'), | |
130 dirname | |
131 ) | |
132 for pattern, method in method_map.items(): | |
133 if pathmatch(pattern, filename): | |
134 filepath = os.path.join(absname, filename) | |
135 options = {} | |
136 for opattern, odict in options_map.items(): | |
137 if pathmatch(opattern, filename): | |
138 options = odict | |
47
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
139 if callback: |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
140 callback(filename, options) |
44 | 141 for line, func, key in extract_from_file(method, filepath, |
142 keywords=keywords, | |
143 options=options): | |
47
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
144 yield filename, line, func, key |
1 | 145 |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
146 def extract_from_file(method, filename, keywords=DEFAULT_KEYWORDS, |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
147 options=None): |
1 | 148 """Extract messages from a specific file. |
149 | |
150 This function returns a list of tuples of the form: | |
151 | |
152 ``(lineno, funcname, message)`` | |
153 | |
154 :param filename: the path to the file to extract messages from | |
155 :param method: a string specifying the extraction method (.e.g. "python") | |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
156 :param keywords: a dictionary mapping keywords (i.e. names of functions |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
157 that should be recognized as translation functions) to |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
158 tuples that specify which of their arguments contain |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
159 localizable strings |
1 | 160 :param options: a dictionary of additional options (optional) |
161 :return: the list of extracted messages | |
162 :rtype: `list` | |
163 """ | |
164 fileobj = open(filename, 'U') | |
165 try: | |
166 return list(extract(method, fileobj, keywords, options=options)) | |
167 finally: | |
168 fileobj.close() | |
169 | |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
170 def extract(method, fileobj, keywords=DEFAULT_KEYWORDS, options=None): |
1 | 171 """Extract messages from the given file-like object using the specified |
172 extraction method. | |
173 | |
174 This function returns a list of tuples of the form: | |
175 | |
176 ``(lineno, funcname, message)`` | |
177 | |
178 The implementation dispatches the actual extraction to plugins, based on the | |
179 value of the ``method`` parameter. | |
180 | |
181 >>> source = '''# foo module | |
182 ... def run(argv): | |
183 ... print _('Hello, world!') | |
184 ... ''' | |
10
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
185 |
1 | 186 >>> from StringIO import StringIO |
187 >>> for message in extract('python', StringIO(source)): | |
188 ... print message | |
189 (3, '_', 'Hello, world!') | |
190 | |
191 :param method: a string specifying the extraction method (.e.g. "python") | |
192 :param fileobj: the file-like object the messages should be extracted from | |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
193 :param keywords: a dictionary mapping keywords (i.e. names of functions |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
194 that should be recognized as translation functions) to |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
195 tuples that specify which of their arguments contain |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
196 localizable strings |
1 | 197 :param options: a dictionary of additional options (optional) |
198 :return: the list of extracted messages | |
199 :rtype: `list` | |
200 :raise ValueError: if the extraction method is not registered | |
201 """ | |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
202 from pkg_resources import working_set |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
203 |
1 | 204 for entry_point in working_set.iter_entry_points(GROUP_NAME, method): |
205 func = entry_point.load(require=True) | |
10
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
206 m = [] |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
207 for lineno, funcname, messages in func(fileobj, keywords.keys(), |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
208 options=options or {}): |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
209 if isinstance(messages, (list, tuple)): |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
210 msgs = [] |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
211 for index in keywords[funcname]: |
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
212 msgs.append(messages[index - 1]) |
10
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
213 messages = tuple(msgs) |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
214 if len(messages) == 1: |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
215 messages = messages[0] |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
216 yield lineno, funcname, messages |
4130d9c6cb34
Both Babel's [source:trunk/babel/catalog/frontend.py frontend] and [source:trunk/babel/catalog/extract.py extract] now handle keyword indices. Also added an extra boolean flag so that the default keywords defined by Babel are not included in the keywords to search for when extracting strings.
palgarvio
parents:
1
diff
changeset
|
217 return |
12
e6ba3e878b10
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
10
diff
changeset
|
218 |
1 | 219 raise ValueError('Unknown extraction method %r' % method) |
220 | |
221 def extract_genshi(fileobj, keywords, options): | |
222 """Extract messages from Genshi templates. | |
223 | |
224 :param fileobj: the file-like object the messages should be extracted from | |
225 :param keywords: a list of keywords (i.e. function names) that should be | |
226 recognized as translation functions | |
227 :param options: a dictionary of additional options (optional) | |
228 :return: an iterator over ``(lineno, funcname, message)`` tuples | |
229 :rtype: ``iterator`` | |
230 """ | |
231 from genshi.filters.i18n import Translator | |
232 from genshi.template import MarkupTemplate | |
47
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
233 |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
234 template_class = options.get('template_class', MarkupTemplate) |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
235 if isinstance(template_class, basestring): |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
236 module, clsname = template_class.split(':', 1) |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
237 template_class = getattr(__import__(module, {}, {}, [clsname]), clsname) |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
238 encoding = options.get('encoding', None) |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
239 |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
240 ignore_tags = options.get('ignore_tags', Translator.IGNORE_TAGS) |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
241 if isinstance(ignore_tags, basestring): |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
242 ignore_tags = ignore_tags.split() |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
243 include_attrs = options.get('include_attrs', Translator.INCLUDE_ATTRS) |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
244 if isinstance(include_attrs, basestring): |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
245 include_attrs = include_attrs.split() |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
246 |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
247 tmpl = template_class(fileobj, filename=getattr(fileobj, 'name'), |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
248 encoding=encoding) |
f8469ab4b257
Support passing extraction method mapping and options from the frontends (see #4). No distutils/setuptools keyword supported yet, but the rest seems to be working okay.
cmlenz
parents:
44
diff
changeset
|
249 translator = Translator(None, ignore_tags, include_attrs) |
1 | 250 for message in translator.extract(tmpl.stream, gettext_functions=keywords): |
251 yield message | |
252 | |
253 def extract_python(fileobj, keywords, options): | |
254 """Extract messages from Python source code. | |
255 | |
256 :param fileobj: the file-like object the messages should be extracted from | |
257 :param keywords: a list of keywords (i.e. function names) that should be | |
258 recognized as translation functions | |
259 :param options: a dictionary of additional options (optional) | |
260 :return: an iterator over ``(lineno, funcname, message)`` tuples | |
261 :rtype: ``iterator`` | |
262 """ | |
263 funcname = None | |
264 lineno = None | |
265 buf = [] | |
266 messages = [] | |
267 in_args = False | |
268 | |
269 tokens = generate_tokens(fileobj.readline) | |
270 for tok, value, (lineno, _), _, _ in tokens: | |
271 if funcname and tok == OP and value == '(': | |
272 in_args = True | |
273 elif funcname and in_args: | |
274 if tok == OP and value == ')': | |
275 in_args = False | |
276 if buf: | |
277 messages.append(''.join(buf)) | |
278 del buf[:] | |
279 if filter(None, messages): | |
280 if len(messages) > 1: | |
281 messages = tuple(messages) | |
282 else: | |
283 messages = messages[0] | |
284 yield lineno, funcname, messages | |
285 funcname = lineno = None | |
286 messages = [] | |
287 elif tok == STRING: | |
288 if lineno is None: | |
289 lineno = stup[0] | |
36
cfd15b7921f9
Fix for #8: fix extraction of strings from Python source using prefixes ('u' or 'r') or triple quotes.
cmlenz
parents:
12
diff
changeset
|
290 # Unwrap quotes in a safe manner |
cfd15b7921f9
Fix for #8: fix extraction of strings from Python source using prefixes ('u' or 'r') or triple quotes.
cmlenz
parents:
12
diff
changeset
|
291 buf.append(eval(value, {'__builtins__':{}}, {})) |
1 | 292 elif tok == OP and value == ',': |
293 messages.append(''.join(buf)) | |
294 del buf[:] | |
295 elif funcname: | |
296 funcname = None | |
297 elif tok == NAME and value in keywords: | |
298 funcname = value |