Пример #1
0
    def visit_For(self, node, frame):
        # when calculating the nodes for the inner frame we have to exclude
        # the iterator contents from it
        for name in node.find_all(nodes.Name):
            if name.ctx == 'store' and name.name == 'loop':
                self.fail('Can\'t assign to special loop variable '
                          'in for-loop target', name.lineno)

        # We rename the special loop variables, to distinguish them
        # from recursive loop() calls
        for var in node.find_all(nodes.Getattr):
            for name in var.find_all(nodes.Name):
                if name.ctx == 'load':
                    name.name = 'l_loop'

        if node.else_:
            iteration_indicator = self.temporary_identifier()

        special_loop = 'l_loop' in find_undeclared(node.iter_child_nodes(only=('body',)), ('l_loop',))

        if node.recursive:
            self.writeline_js('var loop = function(iter) {', frame, node, whitespace=True, end=True)
            self.indent_js()
        if node.else_:
            self.writeline_js('var %s = 1' % iteration_indicator, frame, node, whitespace=True, end=True)

        # If we're accessing the special loop variables and there's a filter test on the loop,
        # we need to do the filtering beforehand
        if special_loop and node.test is not None:
            filtered_var = self.temporary_identifier()
            self.writeline_js('var %s = _.filter(' % filtered_var, frame, node, whitespace=True)
            if node.recursive:
                self.write_js('iter', frame)
            else:
                self.visit(node.iter, frame)
            self.write_js(', function(item) { return ', frame)
            self.visit(node.test, frame)
            self.write_js_stmt_end(' })', frame, end_quote=True)
        self.writeline_js('_.each(', frame, node, whitespace=True)
        if special_loop and node.test is not None:
            self.write_js(filtered_var, frame)
        elif node.recursive:
            self.write_js('iter', frame)
        else:
            self.visit(node.iter, frame)
        self.write_js(', ', frame)
        self.write_js('function(', frame)
        self.visit(node.target, frame)
        self.write_js_stmt_end(', index0, iter) {', frame, end_quote=True)
        self.indent_js()

        # If we don't access the special loop variables inside this loop, then any filtering of the
        # collection becomes a continue
        if not special_loop and node.test is not None:
            self.writeline_js('if(!(', frame, node, whitespace=True)
            self.visit(node.test, frame)
            self.write_js_stmt_end(')) { continue; }', frame, end_quote=True)
        if special_loop:
            self.writeline_js('var l_loop = {index0: index0, index: index0 + 1, first: index0 == 0, length: iter.length}', frame, node, whitespace=True, end=True)
            self.writeline_js('l_loop.revindex = iter.length - l_loop.index0', frame, node, whitespace=True, end=True)
            self.writeline_js('l_loop.revindex0 = l_loop.revindex - 1', frame, node, whitespace=True, end=True)
            self.writeline_js('l_loop.last = l_loop.revindex0 == 0', frame, node, whitespace=True, end=True)
            self.writeline_js('l_loop.cycle = function() { return arguments.length ? arguments[index0 % arguments.length] : \'\' }}', frame, node, whitespace=True, end=True)
        for body_node in node.body:
            self.visit(body_node, frame)
        if node.else_:
            self.writeline_js('%s = 0' % iteration_indicator, frame, node, whitespace=True, end=True)

        self.outdent_js()
        self.writeline_js('})', frame, node, whitespace=True, end=True)
        if node.else_:
            self.writeline_js('if(%s) {' % iteration_indicator, frame, node, whitespace=True, end=True)
            self.indent_js()
            for else_node in node.else_:
                self.visit(else_node, frame)
            self.outdent_js()
            self.writeline_js('}', frame, node, whitespace=True, end=True)
        if node.recursive:
            self.outdent_js()
            self.writeline_js('}', frame, end=True, whitespace=True)
            self.writeline_js('loop(', frame, node, whitespace=True)
            self.visit(node.iter, frame)
            self.write_js_stmt_end(')', frame, end_quote=True)
Пример #2
0
    def visit_Template(self, node, frame=None):
        eval_ctx = EvalContext(self.environment, self.name)

        # find all blocks
        for block in node.find_all(nodes.Block):
            if block.name in self.blocks:
                self.fail('block %r defined twice' % block.name, block.lineno)
            self.blocks[block.name] = block

        for import_ in node.find_all(nodes.ImportedName):
            assert False, "imports not supported"

        self.safename = self.name.replace(".","_")
        self.writeline('var tpl_%s = new function()' % self.safename)
        self.indent()

        frame = Frame(eval_ctx)
        frame.inspect(node.body)
        frame.toplevel = frame.rootlevel = True
        frame.require_output_check =  not self.has_known_extends

        self.buffer(frame)
        # at this point we now have the blocks collected and can visit them too.
        for name, block in self.blocks.iteritems():
            block_frame = Frame(eval_ctx)
            block_frame.inspect(block.body)
            block_frame.block = name
            block_frame.buffer = frame.buffer
            self.writeline('var block_%s = function(context, %s)' % (name, frame.buffer),
                           block, 1)
            self.indent()
            undeclared = find_undeclared(block.body, ('self', 'super'))
            if 'self' in undeclared:
                block_frame.identifiers.add_special('self')
                self.writeline('l_self = TemplateReference(context)')
            if 'super' in undeclared:
                block_frame.identifiers.add_special('super')
                self.writeline('l_super = context.super_block(block_%s)' % name)
            self.pull_locals(block_frame)
            self.pull_dependencies(block.body)
            self.blockvisit(block.body, block_frame)
            self.outdent()

        self.writeline('var blocks = {%s};' % ', '.join('%r: block_%s' % (x, x)
                                                   for x in self.blocks),
                       extra=1)

        self.writeline("var name = %r"% self.name)
        self.writeline('return')
        self.indent()
        self.writeline('name:  name,')

        self.writeline('root: function(context)', extra=1)


        self.indent()
        self.writeline('if(context.blocks==undefined)')
        self.indent()
        self.writeline("context.blocks=blocks")
        self.outdent()

        self.clear_buffer(frame)
        self.writeline('var parent_template = null;')

        if 'self' in find_undeclared(node.body, ('self',)):
            frame.identifiers.add_special('self')
            self.writeline('l_self = context.call_blocks()')

        self.pull_locals(frame)
        self.pull_dependencies(node.body)
        self.blockvisit(node.body, frame)

        self.writeline("if(parent_template)")
        self.indent()
        self.writeline('return parent_template.root(context)')
        self.outdent()

        self.return_buffer_contents(frame)
        self.outdent()

        """
        if not self.has_known_extends:
            self.indent()
            self.writeline('if parent_template is not None:')
        self.indent()
        """



        self.write(',')
        self.writeline('blocks: blocks')

        self.outdent()
        self.outdent()
        self.writeline('if(typeof(environment)!="undefined")')
        self.indent()
        self.writeline('environment.tpl[%r] = tpl_%s' % (self.name, self.safename))
        self.outdent()
Пример #3
0
    def visit_For(self, node, frame):
        # when calculating the nodes for the inner frame we have to exclude
        # the iterator contents from it
        children = node.iter_child_nodes(exclude=('iter',))
        if node.recursive:
            loop_frame = self.function_scoping(node, frame, children,
                                               find_special=False)
        else:
            loop_frame = frame.inner()
            loop_frame.inspect(children)

        # try to figure out if we have an extended loop.  An extended loop
        # is necessary if the loop is in recursive mode if the special loop
        # variable is accessed in the body.
        extended_loop = node.recursive or 'loop' in \
                        find_undeclared(node.iter_child_nodes(
                            only=('body',)), ('loop',))

        aliases = self.push_scope(loop_frame, ('loop',))

        # make sure the loop variable is a special one and raise a template
        # assertion error if a loop tries to write to loop
        if extended_loop:
            loop_frame.identifiers.add_special('loop')
        for name in node.find_all(nodes.Name):
            if name.ctx == 'store' and name.name == 'loop':
                self.fail('Can\'t assign to special loop variable '
                          'in for-loop target', name.lineno)

        self.pull_locals(loop_frame)
        if node.else_:
            iteration_indicator = self.temporary_identifier()
            self.writeline('%s = 1' % iteration_indicator)

        # Create a fake parent loop if the else or test section of a
        # loop is accessing the special loop variable and no parent loop
        # exists.
        if 'loop' not in aliases and 'loop' in find_undeclared(
           node.iter_child_nodes(only=('else_', 'test')), ('loop',)):
            self.writeline("l_loop = environment.undefined(%r, name='loop')" %
                ("'loop' is undefined. the filter section of a loop as well "
                 "as the else block don't have access to the special 'loop'"
                 " variable of the current loop.  Because there is no parent "
                 "loop it's undefined.  Happened in loop on %s" %
                 self.position(node)))


        self.writeline("var __iter_map=function(")#__current,__i)")
        if not isinstance(node.target, nodes.Tuple):
            self.visit(node.target, loop_frame)
        else:
            self.write("__current")

        self.write(",__i)")

        self.indent()

        #XXX: this sucks
        if extended_loop:
            self.writeline("var l_loop= new environment.Loop(__i,");
            self.visit(node.iter, loop_frame)
            self.write(".length, __iter_map);")


        def setvar(node_target, node_iter, idx=None):
            self.writeline("var ", node_target);
            self.visit(node_target, loop_frame);
            self.write(" = ")
            self.write("__current[%d];"%idx)

        if isinstance(node.target, nodes.Tuple):
            for idx,item in enumerate(node.target.items):
                setvar(item, node.iter, idx)

        if node.test is not None:
            self.writeline('if(! ')
            self.visit(node.test, loop_frame)
            self.write(') return')

        self.blockvisit(node.body, loop_frame)
        if node.else_:
            self.writeline('%s = 0' % iteration_indicator)
        self.outdent()

        self.writeline("if((")
        self.visit(node.iter, loop_frame)
        self.write("!==undefined)&&")
        self.visit(node.iter, loop_frame)
        self.write(".map)")

        self.visit(node.iter, loop_frame)
        self.write(".map(__iter_map)")

        self.writeline("else if((")
        self.visit(node.iter, loop_frame)
        self.write("!==undefined)&&")
        self.visit(node.iter, loop_frame)
        self.write(".length)")
        self.indent()
        self.writeline("for(var __i=0;__i<")
        self.visit(node.iter, loop_frame)
        self.write(".length;__i++)")
        self.indent()
        self.writeline("__iter_map(")
        self.visit(node.iter, loop_frame)
        self.write("[__i], __i)")
        self.outdent()
        self.outdent()

        if node.else_:
            self.writeline('if(%s)' % iteration_indicator)
            self.indent()
            self.blockvisit(node.else_, loop_frame)
            self.outdent()

        self.pop_scope(aliases, loop_frame)
Пример #4
0
    def template_ast(self, node, frame=None):  # pragma: no cover

        """ Shim for Jinja2's default ``Jinja``-sytnax-to-Python AST converter.
        Wraps template code in a module-level ``run`` function that binds it
        to an instance of :py:class:`jinja2.Environment`.

        :param node: Current AST node.
        :param frame: Current code frame.
        :return: ``None``. """

        assert frame is None, "no root frame allowed"
        eval_ctx = EvalContext(self.environment, self.name)

        from jinja2.runtime import __all__ as exported

        self.writeline("# -*- coding: utf-8 -*-")
        self.writeline("")
        self.writeline("from __future__ import division")
        self.writeline("from jinja2.runtime import " + ", ".join(exported))
        if not unoptimize_before_dead_code:
            self.writeline("dummy = lambda *x: None")

        # if we want a deferred initialization we cannot move the
        # environment into a local name
        envenv = not self.defer_init and ", environment=environment" or ""

        # do we have an extends tag at all?  If not, we can save some
        # overhead by just not processing any inheritance code.
        have_extends = node.find(nodes.Extends) is not None

        # find all blocks
        for block in node.find_all(nodes.Block):
            if block.name in self.blocks:
                self.fail("block %r defined twice" % block.name, block.lineno)
            self.blocks[block.name] = block

        # find all imports and import them
        for import_ in node.find_all(nodes.ImportedName):
            if import_.importname not in self.import_aliases:
                imp = import_.importname
                self.import_aliases[imp] = alias = self.temporary_identifier()
                if "." in imp:
                    module, obj = imp.rsplit(".", 1)
                    self.writeline("from %s import %s as %s" % (module, obj, alias))
                else:
                    self.writeline("import %s as %s" % (imp, alias))

        # add the load name
        self.writeline("name = %r" % self.name)

        # generate the deferred init wrapper
        self.writeline("def run(environment):", extra=1)
        self.indent()

        # generate the root render function.
        self.writeline("def root(context%s):" % envenv, extra=1)

        # process the root
        frame = Frame(eval_ctx)
        frame.inspect(node.body)
        frame.toplevel = frame.rootlevel = True
        frame.require_output_check = have_extends and not self.has_known_extends
        self.indent()
        if have_extends:
            self.writeline("parent_template = None")
        if "self" in find_undeclared(node.body, ("self",)):
            frame.identifiers.add_special("self")
            self.writeline("l_self = TemplateReference(context)")
        self.pull_locals(frame)
        self.pull_dependencies(node.body)
        self.blockvisit(node.body, frame)
        self.outdent()

        # make sure that the parent root is called.
        if have_extends:
            if not self.has_known_extends:
                self.indent()
                self.writeline("if parent_template is not None:")
            self.indent()
            self.writeline("for event in parent_template." "root_render_func(context):")
            self.indent()
            self.writeline("yield event")
            self.outdent(2 + (not self.has_known_extends))

        # at this point we now have the blocks collected and can visit them too.
        for name, block in iteritems(self.blocks):
            block_frame = Frame(eval_ctx)
            block_frame.inspect(block.body)
            block_frame.block = name
            self.writeline("def block_%s(context%s):" % (name, envenv), block, 1)
            self.indent()
            undeclared = find_undeclared(block.body, ("self", "super"))
            if "self" in undeclared:
                block_frame.identifiers.add_special("self")
                self.writeline("l_self = TemplateReference(context)")
            if "super" in undeclared:
                block_frame.identifiers.add_special("super")
                self.writeline("l_super = context.super(%r, " "block_%s)" % (name, name))
            self.pull_locals(block_frame)
            self.pull_dependencies(block.body)
            self.blockvisit(block.body, block_frame)
            self.outdent()

        self.writeline("blocks = {%s}" % ", ".join("%r: block_%s" % (x, x) for x in self.blocks), extra=1)

        # add a function that returns the debug info
        self.writeline("debug_info = %r" % "&".join("%s=%s" % x for x in self.debug_info))

        self.writeline("return (root, blocks, debug_info)")
        self.outdent()
        self.writeline("")