Exemple #1
0
    def parse(self, parser):
        lineno = parser.stream.__next__().lineno
        value = parser.parse_expression()

        items_per_page_obj = parser.stream.next_if('integer')
        items_per_page = items_per_page_obj.value if items_per_page_obj else DEFAULT_PAGINATION

        if parser.stream.skip_if('name:as'):
            name = parser.stream.expect('name').value
        elif hasattr(value, 'name'):
            name = value.name
        else:
            raise TemplateSyntaxError("Cannot determine the name of objects you want to paginate, use 'as foobar' syntax", lineno)

        while not parser.stream.current.type == 'block_end':
            parser.stream.skip()

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

            nodes.Assign(nodes.Name(name, 'store'),
                nodes.Getattr(nodes.Name(name + '_pages', 'load'), 'object_list', nodes.Impossible())
            ).set_lineno(lineno),
        ]
Exemple #2
0
 def parse_subscript(self, node):
     token = next(self.stream)
     if token.type == 'dot':
         attr_token = self.stream.current
         next(self.stream)
         if attr_token.type == 'name':
             return nodes.Getattr(node,
                                  attr_token.value,
                                  'load',
                                  lineno=token.lineno)
         elif attr_token.type != 'integer':
             self.fail('expected name or number', attr_token.lineno)
         arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
         return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
     if token.type == 'lbracket':
         args = []
         while self.stream.current.type != 'rbracket':
             if args:
                 self.stream.expect('comma')
             args.append(self.parse_subscribed())
         self.stream.expect('rbracket')
         if len(args) == 1:
             arg = args[0]
         else:
             arg = nodes.Tuple(args, 'load', lineno=token.lineno)
         return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
     self.fail('expected subscript expression', self.lineno)
Exemple #3
0
    def parse_part(self, parser, token):

        node = nodes.Macro(lineno=token.lineno)
        part_name = parser.stream.expect('name').value
        node.name = "compopart_" + part_name
        parser.parse_signature(node)
        node.args = [
            nodes.Name("self", "param"),
            nodes.Name("has_caller", "param")
        ] + node.args  # + [nodes.Name("caller", "param")]

        assign_node = nodes.Assign()
        assign_node.target = nodes.Name("dummy", "store")

        call_node = nodes.Call()
        call_node.node = nodes.Getattr()
        call_node.node.node = nodes.Name("self", "load")
        call_node.node.attr = "overwrite_compopart"  # calls the method "self.overwrite_compopart()" from the components
        call_node.node.ctx = "load"
        call_node.args = [
            nodes.Const(part_name),
            nodes.Name('compopart_' + part_name, 'load')
        ]
        call_node.kwargs = []
        call_node.dyn_args = None
        call_node.dyn_kwargs = None

        assign_node.node = call_node

        node.body = parser.parse_statements(('name:endcompopart', ),
                                            drop_needle=True)

        return [node, assign_node]
Exemple #4
0
 def parse_subscript(self, node):
     token = next(self.stream)
     if token.type == "dot":
         attr_token = self.stream.current
         next(self.stream)
         if attr_token.type == "name":
             return nodes.Getattr(node,
                                  attr_token.value,
                                  "load",
                                  lineno=token.lineno)
         elif attr_token.type != "integer":
             self.fail("expected name or number", attr_token.lineno)
         arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
         return nodes.Getitem(node, arg, "load", lineno=token.lineno)
     if token.type == "lbracket":
         args = []
         while self.stream.current.type != "rbracket":
             if args:
                 self.stream.expect("comma")
             args.append(self.parse_subscribed())
         self.stream.expect("rbracket")
         if len(args) == 1:
             arg = args[0]
         else:
             arg = nodes.Tuple(args, "load", lineno=token.lineno)
         return nodes.Getitem(node, arg, "load", lineno=token.lineno)
     self.fail("expected subscript expression", self.lineno)
Exemple #5
0
    def parse(self, parser):
        node = nodes.ExprStmt(lineno=next(parser.stream).lineno)
        modules = []
        while parser.stream.current.type != 'block_end':
            lineno = parser.stream.current.lineno
            if modules:
                parser.stream.expect('comma')
            expr = parser.parse_expression()
            module = expr.as_const()
            modules.append(module)

        assignments = []
        from djinja.template.defaultfunctions import Load
        for m in modules:
            target = nodes.Name(m, 'store')
            func = nodes.Call(nodes.Name('load', 'load'), [nodes.Const(m)], [],
                              None, None)
            assignments.append(nodes.Assign(target, func, lineno=lineno))

            for i in Load(m).globals.keys():
                target = nodes.Name(i, 'store')
                f = nodes.Getattr(nodes.Name(m, 'load'), i, 'load')

                assignments.append(nodes.Assign(target, f, lineno=lineno))

        return assignments
Exemple #6
0
 def parse(self, parser):
     self.parser = parser
     lineno = parser.stream.expect('name:csrf_token_raw').lineno
     call = self.call_method('_csrf_token', [
         nodes.Getattr(nodes.Name('request', 'load'), 'csrf_token', 'load')
     ],
                             lineno=lineno)
     return nodes.Output([nodes.MarkSafe(call)])
    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 #8
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):
        # Get the component for the tag name that we matched on
        tag_name = parser.stream.current[2]
        component_class = self.environment.components[tag_name]
        field_names = [f.name for f in dataclasses.fields(component_class)]
        has_children = CHILDREN_FIELD_NAME in field_names

        lineno = next(parser.stream).lineno

        node = nodes.Scope(lineno=lineno)

        # list of `Pair` nodes for tag properties to update "component" dictionary
        component_dict_update_items = []

        while parser.stream.current.type != 'block_end':
            lineno = parser.stream.current.lineno
            if component_dict_update_items:
                parser.stream.expect('comma')
            name = parser.stream.expect('name')
            parser.stream.expect('assign')
            value = parser.parse_expression()
            component_dict_update_items.append(
                nodes.Pair(nodes.Const(name.value), value))

        # dictionary initialization in the "component" name
        prepare_component_dict = [
            self._initialize_component_dict(component_class, lineno)
        ]

        if component_dict_update_items:
            component_dict_delta = nodes.Dict(component_dict_update_items)
            # `Getattr` for "update" function of the dictionary "component"
            update_component_dict_fun = nodes.Getattr(
                nodes.Name(TMP_COMPONENT_DICT_NAME, 'load'), 'update', 'load')
            # `Call` for `component.update(<prop name>, <prop value>)`
            call_component_dict_update = nodes.Call(update_component_dict_fun,
                                                    [component_dict_delta], [],
                                                    None, None)
            prepare_component_dict.append(
                nodes.ExprStmt(call_component_dict_update))

        # assign `component = __component` and `__component = None`
        prepare_component_dict.extend([
            nodes.Assign(nodes.Name(COMPONENT_DICT_NAME,
                                    'store',
                                    lineno=lineno),
                         nodes.Name(TMP_COMPONENT_DICT_NAME,
                                    'load',
                                    lineno=lineno),
                         lineno=lineno),
            nodes.Assign(nodes.Name(TMP_COMPONENT_DICT_NAME,
                                    'store',
                                    lineno=lineno),
                         nodes.Const(None, lineno=lineno),
                         lineno=lineno)
        ])

        if has_children:
            inner_block = list(
                parser.parse_statements(('name:end' + tag_name, ),
                                        drop_needle=True))
            # create children() macro
            children_macro = nodes.Macro()
            children_macro.name = CHILDREN_MACRO_NAME
            children_macro.args = []
            children_macro.defaults = []
            children_macro.body = inner_block
            children_macro_nodes = [children_macro]
        else:
            children_macro_nodes = []

        # include tag template
        include_tag = nodes.Include()
        # use `template` item of the "component" dictionary for template path
        include_tag.template = nodes.Getitem(nodes.Name(COMPONENT_DICT_NAME,
                                                        'load',
                                                        lineno=lineno),
                                             nodes.Const(TEMPLATE_FIELD_NAME,
                                                         lineno=lineno),
                                             'load',
                                             lineno=lineno)
        include_tag.ignore_missing = False
        include_tag.with_context = True

        node.body = prepare_component_dict + children_macro_nodes + [
            include_tag,
        ]

        return node
Exemple #10
0
 def process_cache_arguments(self, args):
     args.append(nodes.Getattr(nodes.ContextReference(), 'request', 'load'))
Exemple #11
0
def tablerow(
    token: "Token", parser: "Parser"
) -> Union[nodes.Node, List[nodes.Node]]:
    """The tablerow tag {% tablerow ... %} ... {% endtablerow %}

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

    Returns:
        The parsed node
    """
    target = parser.parse_assign_target(extra_end_rules=("name:in", ))
    parser.stream.expect("name:in")
    iter_ = parser.parse_tuple(
        with_condexpr=False,
        extra_end_rules=("name:cols", "name:limit", "name:offset"),
    )

    cols = parse_tag_args(parser.stream, "cols", token.lineno)
    limit = parse_tag_args(parser.stream, "limit", token.lineno)
    offset = parse_tag_args(parser.stream, "offset", token.lineno)

    if limit and offset:
        limit = nodes.Add(offset, limit)
    if limit or offset:
        iter_ = nodes.Getitem(iter_, nodes.Slice(offset, limit, None), "load")

    if cols:
        slice_start = nodes.Mul(nodes.Name("_tablerow_i", "load"), cols)
        inner_iter = nodes.Getitem(
            iter_,
            nodes.Slice(
                slice_start,
                nodes.Add(slice_start, cols),
                None,
            ),
            "load",
        )
    else:
        inner_iter: nodes.Getitem = iter_

    inner_body = [
        nodes.Output(
            [
                nodes.Const('<td class="col'),
                nodes.Getattr(nodes.Name("loop", "load"), "index", "load"),
                nodes.Const('">'),
            ]
        ),
        *parser.parse_statements(("name:endtablerow",), drop_needle=True),
        nodes.Output([nodes.Const("</td>")]),
    ]
    tr_begin = nodes.Output(
        [
            nodes.Const('<tr class="row'),
            nodes.CondExpr(
                nodes.Name("loop", "load"),
                nodes.Getattr(nodes.Name("loop", "load"), "index", "load"),
                nodes.Const(1),
            ),
            nodes.Const('">'),
        ]
    )
    tr_end = nodes.Output([nodes.Const("</tr>")])
    inner_loop = nodes.For(
        target, inner_iter, inner_body, [], None, False, lineno=token.lineno
    )
    if not cols:
        return [tr_begin, inner_loop, tr_end]

    # (iter_ | length) / cols
    iter_length = nodes.Div(
        nodes.Filter(iter_, "length", [], [], None, None),
        cols,
    )  # float
    # int(iter_length)
    iter_length_int = nodes.Filter(iter_length, "int", [], [], None, None)

    # implement ceil, as jinja's ceil is implemented as round(..., "ceil")
    # while liquid has a ceil filter
    # iter_length_int if iter_length == iter_length_int
    # else iter_length_int + 1
    iter_length = nodes.CondExpr(
        nodes.Compare(iter_length, [nodes.Operand("eq", iter_length_int)]),
        iter_length_int,
        nodes.Add(iter_length_int, nodes.Const(1)),
    )

    return nodes.For(
        nodes.Name("_tablerow_i", "store"),
        nodes.Call(nodes.Name("range", "load"), [iter_length], [], None, None),
        [tr_begin, inner_loop, tr_end],
        [],
        None,
        False,
        lineno=token.lineno,
    )