Пример #1
0
    def visit_Assignment(self, node):
        for name in node.names:
            if name in COMPILER_INTERNALS_OR_DISALLOWED:
                raise TranslationError(
                    "Name disallowed by compiler.", name
                    )

            if name.startswith('__'):
                raise TranslationError(
                    "Name disallowed by compiler (double underscore).",
                    name
                    )

        assignment = self._engine(node.expression, store("__value"))

        if len(node.names) != 1:
            target = ast.Tuple(
                elts=[store_econtext(name) for name in node.names],
                ctx=ast.Store(),
            )
        else:
            target = store_econtext(node.names[0])

        assignment.append(ast.Assign(targets=[target], value=load("__value")))

        for name in node.names:
            if not node.local:
                assignment += template(
                    "rcontext[KEY] = __value", KEY=ast.Str(s=native_string(name))
                    )

        return assignment
Пример #2
0
    def visit_Assignment(self, node):
        for name in node.names:
            if name in COMPILER_INTERNALS_OR_DISALLOWED:
                raise TranslationError("Name disallowed by compiler.", name)

            if name.startswith('__'):
                raise TranslationError(
                    "Name disallowed by compiler (double underscore).", name)

        assignment = self._engine(node.expression, store("__value"))

        if len(node.names) != 1:
            target = ast.Tuple(
                elts=[store_econtext(name) for name in node.names],
                ctx=ast.Store(),
            )
        else:
            target = store_econtext(node.names[0])

        assignment.append(ast.Assign(targets=[target], value=load("__value")))

        for name in node.names:
            if not node.local:
                assignment += template("rcontext[KEY] = __value",
                                       KEY=ast.Str(s=native_string(name)))

        return assignment
Пример #3
0
 def _leave_assignment(self, names):
     for name in names:
         for stmt in template(
             "deleteitem(econtext, KEY, BACKUP, __marker)",
             deleteitem=Symbol(deleteitem),
             BACKUP=identifier("backup_%s" % name, id(names)),
             KEY=ast.Str(s=native_string(name)),
             ):
             yield stmt
Пример #4
0
 def _leave_assignment(self, names):
     for name in names:
         for stmt in template(
                 "deleteitem(econtext, KEY, BACKUP, __marker)",
                 deleteitem=Symbol(deleteitem),
                 BACKUP=identifier("backup_%s" % name, id(names)),
                 KEY=ast.Str(s=native_string(name)),
         ):
             yield stmt
Пример #5
0
    def visit_Repeat(self, node):
        # Used for loop variable definition and restore
        self._scopes.append(set())

        # Variable assignment and repeat key for single- and
        # multi-variable repeat clause
        if node.local:
            contexts = "econtext",
        else:
            contexts = "econtext", "rcontext"

        for name in node.names:
            if name in COMPILER_INTERNALS_OR_DISALLOWED:
                raise TranslationError(
                    "Name disallowed by compiler.", name
                    )

        if len(node.names) > 1:
            targets = [
                ast.Tuple(elts=[
                    subscript(native_string(name), load(context), ast.Store())
                    for name in node.names], ctx=ast.Store())
                for context in contexts
                ]

            key = ast.Tuple(
                elts=[ast.Str(s=name) for name in node.names],
                ctx=ast.Load())
        else:
            name = node.names[0]
            targets = [
                subscript(native_string(name), load(context), ast.Store())
                for context in contexts
                ]

            key = ast.Str(s=node.names[0])

        repeat = identifier("__repeat", id(node))
        index = identifier("__index", id(node))
        iterator = identifier("__iterator", id(node))
        assignment = [ast.Assign(targets=targets, value=load("__item"))]

        # Make repeat assignment in outer loop
        names = node.names
        local = node.local

        outer = self._engine(node.expression, store(iterator))

        if local:
            outer[:] = list(self._enter_assignment(names)) + outer

        outer += template(
            "REPEAT = econtext['repeat'](key, ITERATOR)",
            key=key, INDEX=index, REPEAT=repeat, ITERATOR=iterator
            )
        outer += template(
            "INDEX = REPEAT.length",
            INDEX=index, REPEAT=repeat
        )

        # Set a trivial default value for each name assigned to make
        # sure we assign a value even if the iteration is empty
        for name in node.names:
            outer += [ast.Assign(
                targets=[store_econtext(name)],
                value=load("None"))
                  ]

        inner = template(
            "REPEAT._next()", REPEAT=repeat
        )
        # Compute inner body
        inner += self.visit(node.node)

        # After each iteration, decrease the index
        inner += template("index -= 1", index=index)

        # For items up to N - 1, emit repeat whitespace
        inner += template(
            "if INDEX > 0: STACK.t(WHITESPACE)", STACK=self._current_stack,
            INDEX=index, WHITESPACE=ast.Str(s=node.whitespace)
            )

        # Main repeat loop
        outer += [ast.For(
            target=store("__item"),
            iter=load(iterator),
            body=assignment + inner,
            )]

        # Finally, clean up assignment if it's local
        if outer:
            outer += self._leave_assignment(names)

        self._scopes.pop()

        return outer
Пример #6
0
def store_rcontext(name):
    name = native_string(name)
    return subscript(name, load("rcontext"), ast.Store())
Пример #7
0
    def visit_Translate(self, node):
        """Translation.

        Visit items and assign output to a default value.

        Finally, compile a translation expression and use either
        result or default.
        """

        body = []

        # Track the blocks of this translation
        self._translations.append(set())

        # Prepare new stream
        append = identifier("append", id(node))
        stream = identifier("stream", id(node))
        body += template("s = new_list", s=stream, new_list=LIST) + \
                template("a = s.append", a=append, s=stream)

        # Visit body to generate the message body
        code = self.visit(node.node)
        swap(ast.Suite(body=code), load(append), "__append")
        body += code

        # Reduce white space and assign as message id
        msgid = identifier("msgid", id(node))
        body += template(
            "msgid = __re_whitespace(''.join(stream)).strip()",
            msgid=msgid, stream=stream
        )

        default = msgid

        # Compute translation block mapping if applicable
        names = self._translations[-1]
        if names:
            keys = []
            values = []

            for name in names:
                stream, append = self._get_translation_identifiers(name)
                keys.append(ast.Str(s=name))
                values.append(load(stream))

                # Initialize value
                body.insert(
                    0, ast.Assign(
                        targets=[store(stream)],
                        value=ast.Str(s=native_string(""))))

            mapping = ast.Dict(keys=keys, values=values)
        else:
            mapping = None

        # if this translation node has a name, use it as the message id
        if node.msgid:
            msgid = ast.Str(s=node.msgid)

        # emit the translation expression
        body += template(
            "STACK.t(translate("
            "msgid, mapping=mapping, default=default, domain=__i18n_domain))",
            stack=self._current_stack,msgid=msgid, default=default, mapping=mapping
            )

        # pop away translation block reference
        self._translations.pop()

        return body
Пример #8
0
    def visit_Repeat(self, node):
        # Used for loop variable definition and restore
        self._scopes.append(set())

        # Variable assignment and repeat key for single- and
        # multi-variable repeat clause
        if node.local:
            contexts = "econtext",
        else:
            contexts = "econtext", "rcontext"

        for name in node.names:
            if name in COMPILER_INTERNALS_OR_DISALLOWED:
                raise TranslationError("Name disallowed by compiler.", name)

        if len(node.names) > 1:
            targets = [
                ast.Tuple(elts=[
                    subscript(native_string(name), load(context), ast.Store())
                    for name in node.names
                ],
                          ctx=ast.Store()) for context in contexts
            ]

            key = ast.Tuple(elts=[ast.Str(s=name) for name in node.names],
                            ctx=ast.Load())
        else:
            name = node.names[0]
            targets = [
                subscript(native_string(name), load(context), ast.Store())
                for context in contexts
            ]

            key = ast.Str(s=node.names[0])

        repeat = identifier("__repeat", id(node))
        index = identifier("__index", id(node))
        iterator = identifier("__iterator", id(node))
        assignment = [ast.Assign(targets=targets, value=load("__item"))]

        # Make repeat assignment in outer loop
        names = node.names
        local = node.local

        outer = self._engine(node.expression, store(iterator))

        if local:
            outer[:] = list(self._enter_assignment(names)) + outer

        outer += template("REPEAT = econtext['repeat'](key, ITERATOR)",
                          key=key,
                          INDEX=index,
                          REPEAT=repeat,
                          ITERATOR=iterator)
        outer += template("INDEX = REPEAT.length", INDEX=index, REPEAT=repeat)

        # Set a trivial default value for each name assigned to make
        # sure we assign a value even if the iteration is empty
        for name in node.names:
            outer += [
                ast.Assign(targets=[store_econtext(name)], value=load("None"))
            ]

        inner = template("REPEAT._next()", REPEAT=repeat)
        # Compute inner body
        inner += self.visit(node.node)

        # After each iteration, decrease the index
        inner += template("index -= 1", index=index)

        # For items up to N - 1, emit repeat whitespace
        inner += template("if INDEX > 0: STACK.t(WHITESPACE)",
                          STACK=self._current_stack,
                          INDEX=index,
                          WHITESPACE=ast.Str(s=node.whitespace))

        # Main repeat loop
        outer += [
            ast.For(
                target=store("__item"),
                iter=load(iterator),
                body=assignment + inner,
            )
        ]

        # Finally, clean up assignment if it's local
        if outer:
            outer += self._leave_assignment(names)

        self._scopes.pop()

        return outer
Пример #9
0
    def visit_Translate(self, node):
        """Translation.

        Visit items and assign output to a default value.

        Finally, compile a translation expression and use either
        result or default.
        """

        body = []

        # Track the blocks of this translation
        self._translations.append(set())

        # Prepare new stream
        append = identifier("append", id(node))
        stream = identifier("stream", id(node))
        body += template("s = new_list", s=stream, new_list=LIST) + \
                template("a = s.append", a=append, s=stream)

        # Visit body to generate the message body
        code = self.visit(node.node)
        swap(ast.Suite(body=code), load(append), "__append")
        body += code

        # Reduce white space and assign as message id
        msgid = identifier("msgid", id(node))
        body += template("msgid = __re_whitespace(''.join(stream)).strip()",
                         msgid=msgid,
                         stream=stream)

        default = msgid

        # Compute translation block mapping if applicable
        names = self._translations[-1]
        if names:
            keys = []
            values = []

            for name in names:
                stream, append = self._get_translation_identifiers(name)
                keys.append(ast.Str(s=name))
                values.append(load(stream))

                # Initialize value
                body.insert(
                    0,
                    ast.Assign(targets=[store(stream)],
                               value=ast.Str(s=native_string(""))))

            mapping = ast.Dict(keys=keys, values=values)
        else:
            mapping = None

        # if this translation node has a name, use it as the message id
        if node.msgid:
            msgid = ast.Str(s=node.msgid)

        # emit the translation expression
        body += template(
            "STACK.t(translate("
            "msgid, mapping=mapping, default=default, domain=__i18n_domain))",
            stack=self._current_stack,
            msgid=msgid,
            default=default,
            mapping=mapping)

        # pop away translation block reference
        self._translations.pop()

        return body
Пример #10
0
def store_rcontext(name):
    name = native_string(name)
    return subscript(name, load("rcontext"), ast.Store())