Exemple #1
0
    def parse(self, parser):
        lineno = next(parser.stream).lineno
        expr = parser.parse_expression()
        args = [expr]
        kwargs = [nodes.Keyword('func', expr)]
        if parser.stream.skip_if('comma'):
            # Optional 'note' for function docstring
            if (parser.stream.current.type == 'name'
                    and parser.stream.current.value
                    in ('note', 'cond_for', 'depends_on')):
                stream_type = parser.stream.current.value
                next(parser.stream)
                parser.stream.expect('assign')
                # Depends meta is always a list
                if stream_type == 'depends_on':
                    c_expr = parser.parse_list()
                else:
                    c_expr = parser.parse_expression()
                args.append(c_expr)
                kwargs.append(nodes.Keyword(stream_type, c_expr))

        body = parser.parse_statements(['name:endsql', 'name:endquery'],
                                       drop_needle=True)
        raw_template = self.environment.sql_params['raws'][parser.name]

        # Lines range of original raw template
        raw_lines = slice(lineno, parser.stream.current.lineno - 1)
        self.environment.sql_params.setdefault('funcs', {}).update(
            {expr.value: {
                'raw_sql': '\n '.join(raw_template[raw_lines])
            }})
        call_node = nodes.Call(self.attr('_sql_process', lineno=lineno), args,
                               kwargs, None, None)
        return nodes.CallBlock(call_node, [], [], body)
    def parse(self, parser):
        # the first token is the token that started the tag.  In our case
        # we only listen to ``'script'`` so this will be a name token with
        # `script` as value.  We get the line number so that we can give
        # that line number to the nodes we create by hand.
        lineno = next(parser.stream).lineno

        # Get the current context and pass along
        kwargs = [nodes.Keyword('ctx', nodes.ContextReference())]

        # Parse until we are done with optional script tag attributes
        while parser.stream.current.value in SCRIPT_ATTRS:
            attr_name = parser.stream.current.value
            parser.stream.skip(2)
            kwargs.append(
                nodes.Keyword(attr_name, parser.parse_expression()))

        # now we parse the body of the script block up to `endscript` and
        # drop the needle (which would always be `endscript` in that case)
        body = parser.parse_statements(['name:endscript'], drop_needle=True)

        # now return a `CallBlock` node that calls our _render_script
        # helper method on this extension.
        return nodes.CallBlock(
            self.call_method('_render_script', kwargs=kwargs),
            [], [], body).set_lineno(lineno)
Exemple #3
0
        def parse_formrow(self, parser, tag):
            lineno = tag.lineno
            field = parser.parse_expression()
            template_name = None
            if not parser.stream.current.test('block_end'):
                template_name = parser.parse_expression()
            else:
                template_name = nodes.Call(
                    nodes.Name('get_formrow_template', 'load'),
                    [],
                    [
                        nodes.Keyword('caller_template',
                                      nodes.Const(parser.name)),
                        nodes.Keyword('form',
                                      nodes.Name('form_utils_form', 'load'))
                    ],
                    None,
                    None,
                )
            if not parser.stream.current.test('block_end'):
                raise TemplateSyntaxError("Too many arguments", lineno)

            node = nodes.Scope(lineno=lineno)
            assignments = [nodes.Assign(nodes.Name('field', 'store'), field)]
            node.body = assignments + [
                nodes.Include(template_name, True, False)
            ]
            return node.set_lineno(lineno)
Exemple #4
0
    def parse_trs(self, parser, lineno):
        lineno = lineno
        args = [parser.parse_expression()]
        variables = {}

        while parser.stream.current.type != 'block_end':
            parser.stream.expect('comma')
            name = parser.stream.expect('name')
            if name.value in variables:
                parser.fail('translatable variable %r defined twice.' %
                            name.value,
                            name.lineno,
                            exc=TemplateAssertionError)
            if parser.stream.current.type == 'assign':
                next(parser.stream)
                variables[name.value] = var = parser.parse_expression()
            else:
                variables[name.value] = var = nodes.Name(name.value, 'load')
        kwargs = []
        if 'description' in variables:
            kwargs = [
                nodes.Keyword('description', variables.get('description', ''))
            ]

        return nodes.Output([
            nodes.Call(nodes.Name('translate_trs', 'load'), args, kwargs, None,
                       None)
        ]).set_lineno(lineno)
Exemple #5
0
    def _make_node(self, singular, plural, variables, plural_expr,
                   vars_referenced, num_called_num):
        """Generates a useful node from the data provided."""
        if not vars_referenced and not self.environment.newstyle_gettext:
            singular = singular.replace('%%', '%')
            if plural:
                plural = plural.replace('%%', '%')
        if plural_expr is None:
            gettext = nodes.Name('gettext', 'load')
            node = nodes.Call(gettext, [nodes.Const(singular)], [], None, None)
        else:
            ngettext = nodes.Name('ngettext', 'load')
            node = nodes.Call(
                ngettext,
                [nodes.Const(singular),
                 nodes.Const(plural), plural_expr], [], None, None)
        if self.environment.newstyle_gettext:
            for key, value in variables.iteritems():
                if num_called_num and key == 'num':
                    continue
                node.kwargs.append(nodes.Keyword(key, value))

        else:
            node = nodes.MarkSafeIfAutoescape(node)
            if variables:
                node = nodes.Mod(
                    node,
                    nodes.Dict([
                        nodes.Pair(nodes.Const(key), value)
                        for key, value in variables.items()
                    ]))
        return nodes.Output([node])
    def parse_args(self, parser):
        args = []
        kwargs = []
        require_comma = False
        target = None

        while parser.stream.current.type != 'block_end':
            if parser.stream.current.test('name:as'):
                parser.stream.skip(1)
                target = parser.stream.expect('name').value
                if parser.stream.current.type != 'block_end':
                    parser.fail('Invalid assignment target',
                                parser.stream.current.lineno)
                break

            if require_comma:
                parser.stream.expect('comma')

            if (parser.stream.current.type == 'name'
                    and parser.stream.look().type == 'assign'):
                key = parser.stream.current.value
                parser.stream.skip(2)
                value = parser.parse_expression()
                kwargs.append(nodes.Keyword(key, value, lineno=value.lineno))
            else:
                if kwargs:
                    parser.fail('Invalid argument syntax',
                                parser.stream.current.lineno)
                args.append(parser.parse_expression())

            require_comma = True

        return args, kwargs, target
Exemple #7
0
    def parse_args(self, parser):
        args = []
        kwargs = []
        require_comma = False

        while parser.stream.current.type != 'block_end':
            if require_comma:
                parser.stream.expect('comma')

            if parser.stream.current.type == 'name' and parser.stream.look(
            ).type == 'assign':
                key = parser.stream.current.value
                parser.stream.skip(2)
                value = parser.parse_expression()
                kwargs.append(nodes.Keyword(key, value, lineno=value.lineno))
            else:
                if kwargs:
                    parser.fail(
                        'Invalid argument syntax for CacheopsExtension tag',
                        parser.stream.current.lineno)
                args.append(parser.parse_expression())

            require_comma = True

        return args, kwargs
Exemple #8
0
 def parse(self, parser):
     node = nodes.ScopedEvalContextModifier(
         lineno=next(parser.stream).lineno)
     node.options = [nodes.Keyword('autoescape', parser.parse_expression())]
     node.body = parser.parse_statements(('name:endautoescape', ),
                                         drop_needle=True)
     return nodes.Scope([node])
Exemple #9
0
    def parse(self, parser):
        '''parse content of extension'''
        # line number of token that started the tag
        lineno = next(parser.stream).lineno

        # template context
        context = nodes.ContextReference()

        # parse keyword arguments
        kwargs = []

        while parser.stream.look().type == lexer.TOKEN_ASSIGN:
            key = parser.stream.expect(lexer.TOKEN_NAME)
            next(parser.stream)
            kwargs.append(nodes.Keyword(key.value,
                                        parser.parse_expression()), )
            parser.stream.skip_if('comma')
        # parse content of the activeurl block up to endactiveurl
        body = parser.parse_statements(['name:endactiveurl'], drop_needle=True)

        args = [context]

        call_method = self.call_method(
            'render_tag',
            args=args,
            kwargs=kwargs,
        )

        return nodes.CallBlock(call_method, [], [], body).set_lineno(lineno)
Exemple #10
0
    def parse_tropts(self, parser, lineno):
        """
        {% tropts source="index" %}
        {% tr %} {% endtr %}
        {% tr %} {% endtr %}
        {% tr %} {% endtr %}
        {% endtropts %}
        """
        node = nodes.Scope(lineno=lineno)
        assignments = []
        while parser.stream.current.type != 'block_end':
            lineno = parser.stream.current.lineno
            if assignments:
                parser.stream.expect('comma')
            key = parser.parse_assign_target()   # a=b (a is key)
            parser.stream.expect('assign')
            value = parser.parse_expression()  # a=b (b is expression)
            assignments.append(nodes.Keyword(key.name, value))


        node.body = parser.parse_statements(('name:endtropts',), drop_needle=True)
        for item in node.body:
            if isinstance(item, (nodes.Call, nodes.CallBlock)) and item.call.node.name in ('_translate_trs', '_translate_tr'):
                used_keys = set(arg.key for arg in item.call.args)
                allowed_assignments = [assign for assign in assignments
                                       if not assign.key in used_keys]
                item.call.args += allowed_assignments
        return node
 def parse(self, parser):
     lineno = parser.stream.current.lineno
     tag_name = parser.stream.current.value
     additional_params = [
         nodes.Keyword('_context', nodes.ContextReference()),
         nodes.Keyword('_template', nodes.Const(parser.name)),
         nodes.Keyword('_lineno', nodes.Const(lineno)),
         nodes.Keyword('_tag_name', nodes.Const(tag_name)),
     ]
     self.init_parser(parser)
     args, kwargs, target = self.parse_args(parser)
     kwargs.extend(additional_params)
     block_call = self.call_method('render_wrapper', args, kwargs)
     return self.output(parser,
                        block_call,
                        target,
                        tag_name=tag_name,
                        lineno=lineno)
Exemple #12
0
    def _make_node(
        self, singular, plural, variables, plural_expr, vars_referenced, num_called_num
    ):
        """Generates a useful node from the data provided."""
        # no variables referenced?  no need to escape for old style
        # gettext invocations only if there are vars.
        if not vars_referenced and not self.environment.newstyle_gettext:
            singular = singular.replace("%%", "%")
            if plural:
                plural = plural.replace("%%", "%")

        # singular only:
        if plural_expr is None:
            gettext = nodes.Name("gettext", "load")
            node = nodes.Call(gettext, [nodes.Const(singular)], [], None, None)

        # singular and plural
        else:
            ngettext = nodes.Name("ngettext", "load")
            node = nodes.Call(
                ngettext,
                [nodes.Const(singular), nodes.Const(plural), plural_expr],
                [],
                None,
                None,
            )

        # in case newstyle gettext is used, the method is powerful
        # enough to handle the variable expansion and autoescape
        # handling itself
        if self.environment.newstyle_gettext:
            for key, value in iteritems(variables):
                # the function adds that later anyways in case num was
                # called num, so just skip it.
                if num_called_num and key == "num":
                    continue
                node.kwargs.append(nodes.Keyword(key, value))

        # otherwise do that here
        else:
            # mark the return value as safe if we are in an
            # environment with autoescaping turned on
            node = nodes.MarkSafeIfAutoescape(node)
            if variables:
                node = nodes.Mod(
                    node,
                    nodes.Dict(
                        [
                            nodes.Pair(nodes.Const(key), value)
                            for key, value in variables.items()
                        ]
                    ),
                )
        return nodes.Output([node])
Exemple #13
0
    def parse(self, parser):
        stream = parser.stream

        tag = stream.next()

        # get view name
        if stream.current.test('string'):
            viewname = parser.parse_primary()
        else:
            # parse valid tokens and manually build a string from them
            bits = []
            name_allowed = True
            while True:
                if stream.current.test_any('dot', 'sub'):
                    bits.append(stream.next())
                    name_allowed = True
                elif stream.current.test('name') and name_allowed:
                    bits.append(stream.next())
                    name_allowed = False
                else:
                    break
            viewname = nodes.Const("".join([b.value for b in bits]))
            if not bits:
                raise TemplateSyntaxError(
                    "'%s' requires path to view" % tag.value, tag.lineno)

        # get arguments
        args = []
        kwargs = []
        while not stream.current.test_any('block_end', 'name:as'):
            if args or kwargs:
                stream.expect('comma')
            if stream.current.test('name') and stream.look().test('assign'):
                key = nodes.Const(stream.next().value)
                stream.skip()
                value = parser.parse_expression()
                kwargs.append(nodes.Pair(key, value, lineno=key.lineno))
            else:
                args.append(parser.parse_expression())

        make_call_node = lambda *kw: \
            self.call_method('_reverse',
                             args=[viewname, nodes.List(args), nodes.Dict(kwargs)],
                             kwargs=kw)

        # if an as-clause is specified, write the result to context...
        if stream.next_if('name:as'):
            var = nodes.Name(stream.expect('name').value, 'store')
            call_node = make_call_node(
                nodes.Keyword('fail', nodes.Const(False)))
            return nodes.Assign(var, call_node)
        # ...otherwise print it out.
        else:
            return nodes.Output([make_call_node()]).set_lineno(tag.lineno)
Exemple #14
0
    def _get_named_params(self, expressions):
        '''This method transform a list of expressions into a dictionary. It is mandatory that the given list has even number
        of expressions otherwise an exception is raised.

        :param expressions: A list of jinja2 expressions.
        :type expressions: list
        :returns: A tuple (list of kwargs nodes, dict of missing_arguments).'''

        named_params = []
        missing_params = {
            Component.COMP_ARG_TEMPLATE: True,
            Component.COMP_ARG_URL: True,
            Component.COMP_ARG_RUNTIME: True
        }

        last_lineno = -1
        expr_iterator = iter(expressions)

        for expr_name in expr_iterator:
            expr_value = next(expr_iterator)

            missing_params[expr_name.name] = False

            last_lineno = expr_value.lineno
            named_params.append(
                nodes.Keyword(expr_name.name, expr_value, lineno=last_lineno))

        if missing_params[Component.COMP_ARG_TEMPLATE]:
            named_params.insert(
                0,
                nodes.Keyword(Component.COMP_ARG_TEMPLATE,
                              Const(Component.COMP_TEMPLATE_DEFAULT),
                              lineno=last_lineno))

        if missing_params[Component.COMP_ARG_RUNTIME]:
            named_params.append(
                nodes.Keyword(Component.COMP_ARG_RUNTIME,
                              Const(Component.COMP_RUNTIME_DEFAULT),
                              lineno=last_lineno))

        return named_params, missing_params
Exemple #15
0
    def parse_call(self, node):
        token = self.stream.expect('lparen')
        args = []
        kwargs = []
        dyn_args = dyn_kwargs = None
        require_comma = False

        def ensure(expr):
            if not expr:
                self.fail('invalid syntax for function call expression',
                          token.lineno)

        while self.stream.current.type != 'rparen':
            if require_comma:
                self.stream.expect('comma')
                # support for trailing comma
                if self.stream.current.type == 'rparen':
                    break
            if self.stream.current.type == 'mul':
                ensure(dyn_args is None and dyn_kwargs is None)
                next(self.stream)
                dyn_args = self.parse_expression()
            elif self.stream.current.type == 'pow':
                ensure(dyn_kwargs is None)
                next(self.stream)
                dyn_kwargs = self.parse_expression()
            else:
                if self.stream.current.type == 'name' and \
                   self.stream.look().type == 'assign':
                    # Parsing a kwarg
                    ensure(dyn_kwargs is None)
                    key = self.stream.current.value
                    self.stream.skip(2)
                    value = self.parse_expression()
                    kwargs.append(
                        nodes.Keyword(key, value, lineno=value.lineno))
                else:
                    # Parsing an arg
                    ensure(dyn_args is None and dyn_kwargs is None
                           and not kwargs)
                    args.append(self.parse_expression())

            require_comma = True
        self.stream.expect('rparen')

        if node is None:
            return args, kwargs, dyn_args, dyn_kwargs
        return nodes.Call(node,
                          args,
                          kwargs,
                          dyn_args,
                          dyn_kwargs,
                          lineno=token.lineno)
Exemple #16
0
        def parse_form(self, parser, tag):
            lineno = tag.lineno
            form_instance = parser.parse_expression()
            template_name = nodes.Call(
                nodes.Name('get_formlayout_template', 'load'),
                [],
                [
                    nodes.Keyword('caller_template', nodes.Const(parser.name)),
                    nodes.Keyword('form', form_instance),
                ],
                None,
                None,
            )
            has_body = False
            if not parser.stream.current.test('block_end'):
                parser.stream.expect('name:using')
                if parser.stream.current.test('block_end'):
                    has_body = True
            if not parser.stream.current.test('block_end'):
                template_name = parser.parse_expression()
            if not parser.stream.current.test('block_end'):
                raise TemplateSyntaxError("Too many arguments", lineno)

            body = None
            if has_body:
                body = parser.parse_statements(['name:endform'],
                                               drop_needle=True)
            else:
                body = nodes.Include(template_name, True, False)
                body = [body]

            node = nodes.Scope(lineno=lineno)
            assignments = [
                nodes.Assign(nodes.Name('form_utils_form', 'store'),
                             form_instance)
            ]
            node.body = assignments + body
            return node.set_lineno(lineno)
Exemple #17
0
    def parse_call(self, node):
        token = self.stream.expect("lparen")
        args = []
        kwargs = []
        dyn_args = dyn_kwargs = None
        require_comma = False

        def ensure(expr):
            if not expr:
                self.fail("invalid syntax for function call expression",
                          token.lineno)

        while self.stream.current.type != "rparen":
            if require_comma:
                self.stream.expect("comma")
                # support for trailing comma
                if self.stream.current.type == "rparen":
                    break
            if self.stream.current.type == "mul":
                ensure(dyn_args is None and dyn_kwargs is None)
                next(self.stream)
                dyn_args = self.parse_expression()
            elif self.stream.current.type == "pow":
                ensure(dyn_kwargs is None)
                next(self.stream)
                dyn_kwargs = self.parse_expression()
            else:
                ensure(dyn_args is None and dyn_kwargs is None)
                if (self.stream.current.type == "name"
                        and self.stream.look().type == "assign"):
                    key = self.stream.current.value
                    self.stream.skip(2)
                    value = self.parse_expression()
                    kwargs.append(
                        nodes.Keyword(key, value, lineno=value.lineno))
                else:
                    ensure(not kwargs)
                    args.append(self.parse_expression())

            require_comma = True
        self.stream.expect("rparen")

        if node is None:
            return args, kwargs, dyn_args, dyn_kwargs
        return nodes.Call(node,
                          args,
                          kwargs,
                          dyn_args,
                          dyn_kwargs,
                          lineno=token.lineno)
Exemple #18
0
 def parse_tr(self, parser, lineno):
     node = nodes.Scope(lineno=lineno)
     assignments = []
     while parser.stream.current.type != 'block_end':
         lineno = parser.stream.current.lineno
         if assignments:
             parser.stream.expect('comma')
         target = parser.parse_assign_target(name_only=True)
         parser.stream.expect('assign')
         expr = parser.parse_expression()
         assignments.append(nodes.Keyword(target.name, expr, lineno=lineno))
     body = parser.parse_statements(('name:endtr', ), drop_needle=True)
     return nodes.CallBlock(
         nodes.Call(nodes.Name('translate_tr', 'load'), [], assignments,
                    None, None), [], [], body).set_lineno(lineno)
Exemple #19
0
def parse_macro_tag_signature(parser):
    args = []
    kwargs = []

    while parser.stream.current.type != "block_end":
        if parser.stream.current.type == "name" and \
           parser.stream.look().type == "assign":
            key = parser.stream.current.value
            parser.stream.skip(2)
            value = parser.parse_expression()
            kwargs.append(nodes.Keyword(key, value, lineno=value.lineno))
        else:
            args.append(parser.parse_expression())

    return args, kwargs
Exemple #20
0
    def parse(self, parser):
        lineno = next(parser.stream).lineno
        view_name = parser.stream.expect(lexer.TOKEN_STRING)
        view_name = nodes.Const(view_name.value, lineno=view_name.lineno)

        args = None
        kwargs = None
        as_var = None

        while parser.stream.current.type != lexer.TOKEN_BLOCK_END:
            token = parser.stream.current
            if token.test("name:as"):
                next(parser.stream)
                token = parser.stream.expect(lexer.TOKEN_NAME)
                as_var = nodes.Name(token.value, "store", lineno=token.lineno)
                break
            if args is not None:
                args.append(self.parse_expression(parser))
            elif kwargs is not None:
                if token.type != lexer.TOKEN_NAME:
                    parser.fail(
                        "got '{}', expected name for keyword argument" "".format(lexer.describe_token(token)),
                        lineno=token.lineno,
                    )
                arg = token.value
                next(parser.stream)
                parser.stream.expect(lexer.TOKEN_ASSIGN)
                token = parser.stream.current
                kwargs[arg] = self.parse_expression(parser)
            else:
                if parser.stream.look().type == lexer.TOKEN_ASSIGN:
                    kwargs = {}
                else:
                    args = []
                continue

        if args is None:
            args = []
        args.insert(0, view_name)

        if kwargs is not None:
            kwargs = [nodes.Keyword(key, val) for key, val in kwargs.items()]

        call = self.call_method("_url_reverse", args, kwargs, lineno=lineno)
        if as_var is None:
            return nodes.Output([call], lineno=lineno)
        else:
            return nodes.Assign(as_var, call, lineno=lineno)
Exemple #21
0
 def _parse_kwargs(self, parser):
     lineno = next(parser.stream).lineno
     # XXX Is env required?
     #env = nodes.Name()
     #env.name = 'env'
     #env.ctx = 'load'
     #kwargs = [nodes.Keyword('env', env)]
     kwargs = []
     while parser.stream.current.type != 'block_end':
         if len(kwargs) > 1:
             parser.stream.expect('comma')
         key = parser.stream.expect('name').value
         parser.stream.expect('assign')
         value = parser.parse_expression()
         kwargs.append(nodes.Keyword(key, value))
     return kwargs
    def parse(self, parser):
        lineno = parser.stream.next().lineno
        object_list = parser.parse_expression()
        if parser.stream.skip_if('name:as'):
            name = parser.stream.expect('name').value
        elif hasattr(object_list, 'name'):
            name = object_list.name
        else:
            raise TemplateSyntaxError(
                "Cannot determine the name of objects " \
                    "you want to paginate, use 'as foobar' syntax", lineno)

        kwargs = [] # wait... what?
        loops = 0
        while parser.stream.current.type != 'block_end':
            lineno = parser.stream.current.lineno
            if loops:
                parser.stream.expect('comma')
            key = parser.parse_assign_target().name
            if key not in self.default_kwargs.keys():
                raise TemplateSyntaxError(
                    "Unknown keyword argument for autopaginate. "\
                        "Your options are: %s" % (
                            ", ".join(self.default_kwargs.keys())
                            ))
            parser.stream.expect('assign')
            value = parser.parse_expression()
            kwargs.append(nodes.Keyword(key, value))
            loops += 1

        return [
            nodes.Assign(nodes.Name(name + '_pages', 'store'),
                         self.call_method('_render_pages',
                                          [object_list, nodes.Name('request', 'load')],
                                          kwargs)
                         ).set_lineno(lineno),

            nodes.Assign(nodes.Name(name, 'store'),
                         nodes.Getattr(nodes.Name(name + '_pages', 'load'),
                                       'object_list',
                                       nodes.Impossible())
                         ).set_lineno(lineno),
            ]
Exemple #23
0
def _empty_extension_parse(self, open_token_condition, parser):
    args = [
        nodes.ContextReference(),
        nodes.Const(parser.filename),
        nodes.Const(parser.stream.current.lineno)
    ]
    kwargs = {}
    name_token = parser.stream.expect(open_token_condition)
    automata_state = AutomataState.Expect_Name

    while parser.stream.current.type != TOKEN_BLOCK_END:
        if automata_state == AutomataState.Expect_Name:
            name_token = parser.stream.expect(TOKEN_NAME)
            automata_state = AutomataState.Expect_Assign
        elif automata_state == AutomataState.Expect_Assign:
            parser.stream.skip_if(TOKEN_ASSIGN)
            automata_state = AutomataState.Expect_Value
        elif automata_state == AutomataState.Expect_Value:
            value_token = parser.stream.next_if(TOKEN_FLOAT)

            if value_token:
                kwargs[name_token.value] = value_token.value
            else:
                value_token = parser.stream.next_if(TOKEN_INTEGER)

                if value_token:
                    kwargs[name_token.value] = value_token.value
                else:
                    value_token = parser.stream.expect(TOKEN_STRING)
                    kwargs[name_token.value] = value_token.value

            automata_state = AutomataState.Expect_Comma
        elif automata_state == AutomataState.Expect_Comma:
            parser.stream.skip_if(TOKEN_COMMA)
            automata_state = AutomataState.Expect_Name

    lineno = parser.stream.current.lineno

    return nodes.CallBlock(
        self.call_method('_process_markup', args, [
            nodes.Keyword(name, nodes.Const(value))
            for name, value in kwargs.items()
        ]), [], [], []).set_lineno(lineno)
Exemple #24
0
def cycle(token: "Token", parser: "Parser") -> nodes.Node:
    """The cycle tag {% cycle ... %}

    With name: {% cycle "name": "one", "two", "three" %}
    Without: {% cycle "one", "two", "three" %}

    Turn these to
    {{ loop.liquid_cycle("one", "two", "three", name=...) }}

    Args:
        token: The token matches tag name
        parser: The parser

    Returns:
        The parsed node
    """
    tokens_ahead = peek_tokens(parser.stream, 2)
    if (
        len(tokens_ahead) == 2
        and tokens_ahead[0].type is TOKEN_STRING
        and tokens_ahead[1].type is TOKEN_COLON
    ):
        parser.stream.skip(2)
        cycler_name = tokens_ahead[0].value
    else:
        cycler_name = ""

    args = parser.parse_tuple(with_condexpr=False, simplified=True)
    return nodes.Output(
        [
            nodes.Call(
                nodes.Getattr(
                    nodes.Name("loop", "load"), "liquid_cycle", "load"
                ),
                args.items if isinstance(args, nodes.Tuple) else [args],
                [nodes.Keyword("name", nodes.Const(cycler_name))],
                None,
                None,
                lineno=token.lineno,
            )
        ]
    )
    def parse(self, parser):
        stream = parser.stream

        tag = stream.next()

        # get view name
        if stream.current.test('string'):
            bundle_name = parser.parse_primary()
        else:
            bundle_name = parser.parse_expression()

        # get arguments
        args = []
        kwargs = []
        while not stream.current.test_any('block_end', 'name:as'):
            if args or kwargs:
                stream.expect('comma')
            if stream.current.test('name') and stream.look().test('assign'):
                key = nodes.Const(stream.next().value)
                stream.skip()
                value = parser.parse_expression()
                kwargs.append(nodes.Pair(key, value, lineno=key.lineno))
            else:
                args.append(parser.parse_expression())

        make_call_node = lambda *kw: \
            self.call_method('_build_tag',
                             args=[bundle_name,
                             nodes.List(args), nodes.Dict(kwargs)],
                             kwargs=kw)

        # if an as-clause is specified, write the result to context...
        if stream.next_if('name:as'):
            var = nodes.Name(stream.expect('name').value, 'store')
            call_node = make_call_node(
                nodes.Keyword('fail', nodes.Const(False)))
            return nodes.Assign(var, call_node)
        # ...otherwise print it out.
        else:
            return nodes.Output([make_call_node()]).set_lineno(tag.lineno)
Exemple #26
0
 def parse_args(self, parser):
     args = []
     kwargs = []
     require_comma = False
     while parser.stream.current.type != "block_end":
         if require_comma:
             parser.stream.expect("comma")
         if (parser.stream.current.type == "name"
                 and parser.stream.look().type == "assign"):
             key = parser.stream.current.value
             parser.stream.skip(2)
             value = parser.parse_expression()
             kwargs.append(nodes.Keyword(key, value, lineno=value.lineno))
         else:
             if kwargs:
                 parser.fail(
                     "Invalid argument syntax for WrapExtension tag",
                     parser.stream.current.lineno,
                 )
             args.append(parser.parse_expression())
         require_comma = True
     return args, kwargs
Exemple #27
0
    def parse(self, parser):
        token = parser.stream.next()
        args = [parser.parse_expression()]
        kwargs = []
        while parser.stream.current.type != 'block_end':
            if kwargs:
                parser.stream.expect('comma')

            if parser.stream.skip_if('colon'):
                break

            name = parser.stream.expect('name')
            if name.value in kwargs:
                parser.fail('variable %r defined twice.' % name.value,
                            name.lineno,
                            exc=TemplateAssertionError)
            parser.stream.expect('assign')
            key = name.value
            value = parser.parse_expression()
            kwargs.append(nodes.Keyword(key, value, lineno=value.lineno))
        return nodes.Output([self.call_method('_render', args, kwargs)
                             ]).set_lineno(token.lineno)
Exemple #28
0
    def parse(self, parser):
        stream = parser.stream

        tag = stream.next()

        # get view name
        if stream.current.test('string'):
            # Need to work around Jinja2 syntax here. Jinja by default acts
            # like Python and concats subsequent strings. In this case
            # though, we want {% url "app.views.post" "1" %} to be treated
            # as view + argument, while still supporting
            # {% url "app.views.post"|filter %}. Essentially, what we do is
            # rather than let ``parser.parse_primary()`` deal with a "string"
            # token, we do so ourselves, and let parse_expression() handle all
            # other cases.
            if stream.look().test('string'):
                token = stream.next()
                viewname = nodes.Const(token.value, lineno=token.lineno)
            else:
                viewname = parser.parse_expression()
        else:
            # parse valid tokens and manually build a string from them
            bits = []
            name_allowed = True
            while True:
                if stream.current.test_any('dot', 'sub', 'colon'):
                    bits.append(stream.next())
                    name_allowed = True
                elif stream.current.test('name') and name_allowed:
                    bits.append(stream.next())
                    name_allowed = False
                else:
                    break
            viewname = nodes.Const("".join([b.value for b in bits]))
            if not bits:
                raise TemplateSyntaxError(
                    "'%s' requires path to view" % tag.value, tag.lineno)

        # get arguments
        args = []
        kwargs = []
        while not stream.current.test_any('block_end', 'name:as'):
            if args or kwargs:
                stream.expect('comma')
            if stream.current.test('name') and stream.look().test('assign'):
                key = nodes.Const(stream.next().value)
                stream.skip()
                value = parser.parse_expression()
                kwargs.append(nodes.Pair(key, value, lineno=key.lineno))
            else:
                args.append(parser.parse_expression())

        def make_call_node(*kw):
            return self.call_method('_reverse',
                                    args=[
                                        viewname,
                                        nodes.List(args),
                                        nodes.Dict(kwargs),
                                        nodes.Name('_current_app', 'load'),
                                    ],
                                    kwargs=kw)

        # if an as-clause is specified, write the result to context...
        if stream.next_if('name:as'):
            var = nodes.Name(stream.expect('name').value, 'store')
            call_node = make_call_node(
                nodes.Keyword('fail', nodes.Const(False)))
            return nodes.Assign(var, call_node)
        # ...otherwise print it out.
        else:
            return nodes.Output([make_call_node()]).set_lineno(tag.lineno)
    def _parse_blocktrans(self, parser, lineno):
        with_vars = {}
        count = None
        context = None
        trimmed = False
        as_var = None

        if parser.stream.skip_if('name:trimmed'):
            trimmed = True

        if parser.stream.skip_if('name:asvar'):
            as_var = parser.stream.expect(lexer.TOKEN_NAME)
            as_var = nodes.Name(as_var.value, 'store', lineno=as_var.lineno)

        if parser.stream.skip_if('name:with'):
            while parser.stream.look().type == lexer.TOKEN_ASSIGN:
                token = parser.stream.expect(lexer.TOKEN_NAME)
                key = token.value
                next(parser.stream)
                with_vars[key] = parser.parse_expression(False)

        if parser.stream.skip_if('name:count'):
            name = parser.stream.expect(lexer.TOKEN_NAME).value
            parser.stream.expect(lexer.TOKEN_ASSIGN)
            value = parser.parse_expression(False)
            count = (name, value)

        if parser.stream.skip_if('name:context'):
            context = parser.stream.expect(lexer.TOKEN_STRING).value

        parser.stream.expect(lexer.TOKEN_BLOCK_END)

        body_singular = None
        body = []
        additional_vars = set()
        for token in parser.stream:
            if token is lexer.TOKEN_EOF:
                parser.fail(
                    'unexpected end of template, expected endblocktrans tag')
            if token.type is lexer.TOKEN_DATA:
                body.append(token.value)
            elif token.type is lexer.TOKEN_VARIABLE_BEGIN:
                name = parser.stream.expect(lexer.TOKEN_NAME).value
                if name not in with_vars and (count is None
                                              or count[0] != name):
                    additional_vars.add(name)
                parser.stream.expect(lexer.TOKEN_VARIABLE_END)
                # django converts variables inside the blocktrans tag into
                # "%(var_name)s" format, so we do the same.
                body.append('%({})s'.format(name))
            elif token.type is lexer.TOKEN_BLOCK_BEGIN:
                if body_singular is None and parser.stream.skip_if(
                        'name:plural'):
                    if count is None:
                        parser.fail('used plural without specifying count')
                    parser.stream.expect(lexer.TOKEN_BLOCK_END)
                    body_singular = body
                    body = []
                else:
                    parser.stream.expect('name:endblocktrans')
                    break

        if count is not None and body_singular is None:
            parser.fail('plural form not found')

        trans_vars = [
            nodes.Pair(nodes.Const(key), val, lineno=lineno)
            for key, val in with_vars.items()
        ]

        if count is not None:
            trans_vars.append(
                nodes.Pair(nodes.Const(count[0]), count[1], lineno=lineno))

        trans_vars.extend(
            nodes.Pair(nodes.Const(key),
                       nodes.Name(key, 'load', lineno=lineno),
                       lineno=lineno) for key in additional_vars)

        kwargs = [
            nodes.Keyword('trans_vars',
                          nodes.Dict(trans_vars, lineno=lineno),
                          lineno=lineno)
        ]

        if context is not None:
            kwargs.append(
                nodes.Keyword('context',
                              nodes.Const(context, lineno=lineno),
                              lineno=lineno))
        if count is not None:
            kwargs.append(
                nodes.Keyword('count_var',
                              nodes.Const(count[0], lineno=lineno),
                              lineno=lineno))

        body = ''.join(body)
        if trimmed:
            body = ' '.join(map(lambda s: s.strip(),
                                body.strip().splitlines()))

        if body_singular is not None:
            body_singular = ''.join(body_singular)
            if trimmed:
                body_singular = ' '.join(
                    map(lambda s: s.strip(),
                        body_singular.strip().splitlines()))

        if body_singular is None:
            args = []
        else:
            args = [nodes.TemplateData(body_singular, lineno=lineno)]
        args.append(nodes.TemplateData(body, lineno=lineno))
        call = nodes.MarkSafe(self.call_method('_make_blocktrans', args,
                                               kwargs),
                              lineno=lineno)

        if as_var is None:
            return nodes.Output([call], lineno=lineno)
        else:
            return nodes.Assign(as_var, call)
Exemple #30
0
def _embed_extension_parse(self, open_token_condition, close_token_condition,
                           parser):
    args = [
        nodes.ContextReference(),
        nodes.Const(parser.filename),
        nodes.Const(parser.stream.current.lineno)
    ]
    kwargs = {}
    name_token = parser.stream.expect(open_token_condition)
    automata_state = AutomataState.Expect_Name
    content_path = None

    while parser.stream.current.type != TOKEN_BLOCK_END:
        if automata_state == AutomataState.Expect_Name:
            name_token = parser.stream.expect(TOKEN_NAME)
            automata_state = AutomataState.Expect_Assign
        elif automata_state == AutomataState.Expect_Assign:
            parser.stream.skip_if(TOKEN_ASSIGN)
            automata_state = AutomataState.Expect_Value
        elif automata_state == AutomataState.Expect_Value:
            value_token = parser.stream.next_if(TOKEN_FLOAT)

            if value_token:
                kwargs[name_token.value] = value_token.value
            else:
                value_token = parser.stream.next_if(TOKEN_INTEGER)

                if value_token:
                    kwargs[name_token.value] = value_token.value
                else:
                    value_token = parser.stream.expect(TOKEN_STRING)

                    if name_token.value == 'absolute_path':
                        content_path = normpath(
                            abspath(
                                join(parser.environment.globals['source_path'],
                                     value_token.value)))
                    elif name_token.value == 'relative_path':
                        content_path = normpath(
                            abspath(
                                join(dirname(parser.filename),
                                     value_token.value)))
                    else:
                        kwargs[name_token.value] = value_token.value

            automata_state = AutomataState.Expect_Comma
        elif automata_state == AutomataState.Expect_Comma:
            parser.stream.skip_if(TOKEN_COMMA)
            automata_state = AutomataState.Expect_Name

    lineno = parser.stream.current.lineno

    if content_path is not None:
        if not isfile(content_path):
            raise TemplateSyntaxError(
                f'Cannot find content file "{content_path}".', lineno,
                parser.filename)

        kwargs['content_path'] = content_path
        body = []
    else:
        body = parser.parse_statements([close_token_condition],
                                       drop_needle=True)

    return nodes.CallBlock(
        self.call_method('_process_markup', args, [
            nodes.Keyword(name, nodes.Const(value))
            for name, value in kwargs.items()
        ]), [], [], body).set_lineno(lineno)