changeset 561:21b473243e63 trunk

Move code for extracting messages from bytecode into a separate function.
author cmlenz
date Thu, 05 Jul 2007 17:05:33 +0000
parents 7e83be231f96
children b3dc05d88751
files genshi/filters/i18n.py
diffstat 1 files changed, 51 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/filters/i18n.py
+++ b/genshi/filters/i18n.py
@@ -275,11 +275,6 @@
             if kind is START and not skip:
                 tag, attrs = data
 
-                if msgbuf:
-                    msgbuf.append(kind, data, pos)
-                elif i18n_msg in attrs:
-                    msgbuf = MessageBuffer(pos[1])
-
                 if tag in self.ignore_tags or \
                         isinstance(attrs.get(xml_lang), basestring):
                     skip += 1
@@ -297,6 +292,11 @@
                                 search_text=False):
                             yield lineno, funcname, text
 
+                if msgbuf:
+                    msgbuf.append(kind, data, pos)
+                elif i18n_msg in attrs:
+                    msgbuf = MessageBuffer(pos[1])
+
             elif not skip and search_text and kind is TEXT:
                 if not msgbuf:
                     text = data.strip()
@@ -312,33 +312,8 @@
                     msgbuf = None
 
             elif kind is EXPR or kind is EXEC:
-                consts = dict([(n, chr(i) + '\x00') for i, n in
-                               enumerate(data.code.co_consts)])
-                gettext_locs = [consts[n] for n in gettext_functions
-                                if n in consts]
-                ops = [
-                    _LOAD_CONST, '(', '|'.join(gettext_locs), ')',
-                    _CALL_FUNCTION, '.\x00',
-                    '((?:', _BINARY_ADD, '|', _LOAD_CONST, '.\x00)+)'
-                ]
-                for loc, opcodes in re.findall(''.join(ops), data.code.co_code):
-                    funcname = data.code.co_consts[ord(loc[0])]
-                    strings = []
-                    opcodes = iter(opcodes)
-                    for opcode in opcodes:
-                        if opcode == _BINARY_ADD:
-                            arg = strings.pop()
-                            strings[-1] += arg
-                        else:
-                            arg = data.code.co_consts[ord(opcodes.next())]
-                            opcodes.next() # skip second byte
-                            if not isinstance(arg, basestring):
-                                break
-                            strings.append(unicode(arg))
-                    if len(strings) == 1:
-                        strings = strings[0]
-                    else:
-                        strings = tuple(strings)
+                for funcname, strings in extract_from_code(data.code,
+                                                           gettext_functions):
                     yield pos[1], funcname, strings
 
             elif kind is SUB:
@@ -398,6 +373,50 @@
                     yield event
 
 
+def extract_from_code(code, gettext_functions):
+    """Extract strings from Python bytecode.
+    
+    >>> from genshi.template.eval import Expression
+    
+    >>> expr = Expression('_("Hello")')
+    >>> list(extract_from_code(expr.code, Translator.GETTEXT_FUNCTIONS))
+    [('_', u'Hello')]
+
+    >>> expr = Expression('ngettext("You have %(num)s item", '
+    ...                            '"You have %(num)s items", num)')
+    >>> list(extract_from_code(expr.code, Translator.GETTEXT_FUNCTIONS))
+    [('ngettext', (u'You have %(num)s item', u'You have %(num)s items'))]
+    
+    :param code: the code object
+    :param gettext_functions: a sequence of function names
+    """
+    consts = dict([(n, chr(i) + '\x00') for i, n in enumerate(code.co_consts)])
+    gettext_locs = [consts[n] for n in gettext_functions if n in consts]
+    ops = [
+        _LOAD_CONST, '(', '|'.join(gettext_locs), ')',
+        _CALL_FUNCTION, '.\x00',
+        '((?:', _BINARY_ADD, '|', _LOAD_CONST, '.\x00)+)'
+    ]
+    for loc, opcodes in re.findall(''.join(ops), code.co_code):
+        funcname = code.co_consts[ord(loc[0])]
+        strings = []
+        opcodes = iter(opcodes)
+        for opcode in opcodes:
+            if opcode == _BINARY_ADD:
+                arg = strings.pop()
+                strings[-1] += arg
+            else:
+                arg = code.co_consts[ord(opcodes.next())]
+                opcodes.next() # skip second byte
+                if not isinstance(arg, basestring):
+                    break
+                strings.append(unicode(arg))
+        if len(strings) == 1:
+            strings = strings[0]
+        else:
+            strings = tuple(strings)
+        yield funcname, strings
+
 def parse_msg(string, regex=re.compile(r'(?:\[(\d+)\:)|\]')):
     """Parse a message using Genshi compound message formatting.
 
Copyright (C) 2012-2017 Edgewall Software