def compile_call(self, srcnode, parent):
        fn = srcnode.function
        if '(' not in fn:
            fn += '()'
        call = parse_and_strip(fn)[0].value
        leftovers = im.ContainerNode()
        for item in srcnode.children:
            if isinstance(item, im.CallKeyword):
                funcname = self.unique_id(item.name)
                self._compile_function(item, parent, funcname)
                call.keywords.append(keyword(arg=item.name,
                                             value=LoadName(funcname)))
            elif isinstance(item, im.TextNode) and re.match('^\s*$', item.content, re.S):
                continue
            else:
                leftovers.children.append(item)

        if leftovers.children:
            funcname = self.unique_id()
            self._compile_function(leftovers, parent, funcname)
            call.args.append(make_arg(funcname))
        parent.body.append(
            self.annotate_runtime_errors(
                Expr(value=Yield(Call(func=LoadName('str'),
                                      args=[call],
                                      starargs=None,
                                      kwargs=None,
                                      keywords=[]))), srcnode))
def _compile_element_with_directives(orig, directives, remaining):

    container = working_node = im.ContainerNode()
    inner_directives = [(d, dd, pos) for d, dd, pos in directives if d.inner]
    outer_directives = [(d, dd, pos) for d, dd, pos in directives
                        if not d.inner]

    # Add outer directives
    working_node = append_directive_nodes(orig, outer_directives, container)
    if not isinstance(working_node, im.ContainerNode):
        working_node = im.NullNode()
        container.append(working_node)

    # Add tag
    extra_attrs = []
    strip_condition = None
    for d, dd, pos in directives:
        extras = d.get_extra_attrs(dd, remaining)
        if extras:
            extra_attrs.append(extras)
        strip_condition = (d.get_strip_condition(dd, remaining)
                           or strip_condition)
        tagname_expr = d.get_tagname_expr(dd, remaining)

    working_node.append(
        _compile_open_tag(remaining,
                          tagname_expr=tagname_expr,
                          strip_condition=strip_condition,
                          extra_attrs=extra_attrs))

    # Add inner directives
    inner_working_node = append_directive_nodes(orig, inner_directives,
                                                working_node)

    if not isinstance(inner_working_node, im.ContainerNode):
        inner_working_node = im.NullNode()
        working_node.append(inner_working_node)

    inner_working_node.extend(map(_compile_node, remaining.children))

    working_node.append(
        _compile_close_tag(remaining,
                           tagname_expr=tagname_expr,
                           strip_condition=strip_condition))

    return container
Exemplo n.º 3
0
def _compile_node(node):
    """
    Compile a single node to intermediate representation
    """

    if isinstance(node, Container):
        root = im.ContainerNode()
        root.extend(map(_compile_node, node.children))
        return root

    elif isinstance(node, parse.Text):
        return cx._compile_text(node)

    elif isinstance(node, Statement):
        args = split_args(node.args)
        return DIRECTIVES[node.name](node, *args)

    else:
        raise NotImplementedError(node)
def _compile_close_tag(node, tagname_expr=None, strip_condition=None):
    if not node.close_tag or (isinstance(node, Fragment) and not tagname_expr):
        return im.TextNode('', pos=node.close_tag_pos)

    if tagname_expr:
        closetag = im.ContainerNode(children=[
            im.TextNode.factory('</', pos=node.close_tag_pos),
            im.InterpolateNode(value=tagname_expr, pos=node.close_tag_pos),
            im.TextNode.factory('>', pos=node.close_tag_pos),
        ])
    else:
        closetag = im.TextNode(node.close_tag, pos=node.close_tag_pos)
    if strip_condition:
        if strip_condition in {'True', '1'}:
            return im.NullNode(children=[closetag])
        else:
            return im.IfNode(test='not ({})'.format(strip_condition),
                             children=[closetag],
                             pos=node.close_tag_pos)
    return closetag
def _compile_text(node):
    """
    Compile :class:`piglet.parse.Text` object ``node`` into intermediate Text
    and Interpolation nodes.

    :param node: the :class:`piglet.parse.Text` object
    """
    items = interpolate.parse_interpolations(node.content)
    container = im.ContainerNode()
    pos = node.pos
    for i in items:
        if isinstance(i, (str, ustr)):
            container.append(im.TextNode(i, pos=pos))
            pos = pos.advance(i)
        elif isinstance(i, interpolate.Interpolation):
            container.append(
                im.InterpolateNode.factory(value=unescape(i.value),
                                           pos=pos,
                                           autoescape=i.autoescape
                                           and (not node.cdata)))
            pos = pos.advance(i.source)
    return container
def _compile_vanilla_element(node):
    container = im.ContainerNode()
    container.append(_compile_open_tag(node))
    container.extend(map(_compile_node, node.children))
    container.append(_compile_close_tag(node))
    return container
def _compile_open_tag(node,
                      tagname_expr=None,
                      extra_attrs=None,
                      strip_condition=None):
    """
    Compile the open tag attributes.
    This needs special casing when interpolations are present, eg in the case:

        <option selected="1 if item == 'foo' else None">

    The selected attribute should be entirely omitted if the expression
    evaluates to None.

    :param node: the parse.Element node to compile
    :param tagname_expr: a python expression to replace the tag name
    :param extra_attrs: A list of python source expressions, each returning a
                        list of attributes
    :param strip_condition: a python boolean expression to decide whether
                            to output the open tag at all
    """
    if isinstance(node, Fragment) and not tagname_expr:
        return im.ContainerNode(pos=node.pos)

    container = wn = im.ContainerNode(pos=node.pos)

    if strip_condition:
        if strip_condition in {'True', '1'}:
            container.append(im.NullNode(pos=node.pos))
        else:
            container.append(
                im.IfNode(test='not ({})'.format(strip_condition),
                          children=[],
                          pos=node.pos))
        wn = container.tip()

    wn.append(im.TextNode.factory('<', pos=node.pos))
    if tagname_expr:
        wn.append(im.InterpolateNode(value=tagname_expr, pos=node.end_pos))
    else:
        wn.append(im.TextNode.factory(node.qname, pos=node.pos))
    wn.append(im.TextNode.factory(node.space, pos=node.pos))
    if extra_attrs:
        wn.append(im.InlineCodeNode(pysrc='__piglet_attrs = {}', pos=node.pos))
        for item in extra_attrs:
            wn.append(
                im.InlineCodeNode(
                    pysrc='__piglet_attrs.update({})'.format(item),
                    pos=node.pos))

    for a in node.attrs.values():
        if node.attrs and extra_attrs:
            wn.append(
                im.IfNode(test="'{}' not in __piglet_attrs".format(a.name),
                          pos=a.pos))
            _compile_attr(a, wn.tip())
        else:
            _compile_attr(a, wn)

    if extra_attrs:
        for_ = im.ForNode(each=('__piglet_attr_k, __piglet_attr_v '
                                'in __piglet_attrs.items()'),
                          pos=node.end_pos,
                          children=[])
        if_ = im.IfNode(test='__piglet_attr_v is not None',
                        pos=node.end_pos,
                        children=[
                            im.TextNode(' ', pos=node.end_pos),
                            im.InterpolateNode(value='__piglet_attr_k',
                                               pos=node.end_pos),
                            im.TextNode('="', pos=node.end_pos),
                            im.InterpolateNode(value='__piglet_attr_v',
                                               pos=node.end_pos),
                            im.TextNode('"', pos=node.end_pos)
                        ])
        for_.children.append(if_)
        wn.append(for_)
    wn.append(im.TextNode(content=node.end, pos=node.end_pos))
    return container