def test_it_compiles_replace():
    assert c('<py:replace value="foo">bar</py:replace>') == [
        im.InterpolateNode(pos=P(1, 1), value='foo')
    ]
    assert c('<img py:replace="img_tag()"/>') == [
        im.InterpolateNode(pos=P(1, 18), value='img_tag()')
    ]
def test_it_compiles_regular_attr_interpolation():

    assert c('<div class="x $foo"></div>') == [
        im.TextNode(pos=P(1, 1), content='<div class="x '),
        im.InterpolateNode(pos=P(1, 15), value='foo'),
        im.TextNode(pos=P(1, 19), content='"></div>')
    ]
def make_i18n_substitution(name, expr=None):
    """
    Turn a <i18n:s name="foo" expr="foo"/> into intermediate nodes
    """
    if expr and not name:
        name = expr
    n = im.TranslationPlaceholder(name=name)
    if expr:
        n.append(im.InterpolateNode(value=expr))
    return n
def _compile_attr(a, container):
    """
    Compile a single parse.Attribute
    """
    intro_text = im.TextNode.factory(
        '{0.name}{0.space1}={0.space2}{0.quote}'.format(a), pos=a.pos)
    outro_text = im.TextNode.factory('{0.quote}{0.space3}'.format(a),
                                     pos=a.value_pos.advance(a.value))

    items = interpolate.parse_interpolations(a.value)

    if a.name in HTML_EMPTY_ATTRS and \
       len(items) == 1 and \
       isinstance(items[0], interpolate.Interpolation):
        interp = items[0]
        container.append(
            im.WithNode(vars=[('__piglet_tmp', interp.value)],
                        pos=a.pos,
                        children=[
                            im.IfNode(test='__piglet_tmp is not None',
                                      pos=a.pos,
                                      children=[
                                          intro_text,
                                          im.InterpolateNode(
                                              value='__piglet_tmp',
                                              pos=a.value_pos), outro_text
                                      ])
                        ]))
    else:
        container.append(intro_text)
        pos = a.value_pos
        for i in items:
            if isinstance(i, (str, ustr)):
                container.append(im.TextNode.factory(i, pos))
                pos = pos.advance(i)
            else:
                container.append(
                    im.InterpolateNode(value=unescape(i.value), pos=pos))
                pos = pos.advance(i.source)
        outro_text.pos = pos
        container.append(outro_text)
def test_it_compiles_conditional_attr_interpolation():

    assert c('<input selected="$foo"/>') == [
        im.TextNode(pos=P(1, 1), content='<input '),
        im.WithNode(pos=P(1, 8),
                    vars=[('__piglet_tmp', 'foo')],
                    children=[
                        im.IfNode(pos=P(1, 8),
                                  test='__piglet_tmp is not None',
                                  children=[
                                      im.TextNode(pos=P(1, 8),
                                                  content='selected="'),
                                      im.InterpolateNode(pos=P(1, 18),
                                                         value='__piglet_tmp'),
                                      im.TextNode(pos=P(1, 22), content='"')
                                  ])
                    ]),
        im.TextNode(pos=P(1, 23), content='/>')
    ]
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 test_it_compiles_interpolations_with_entities():
    assert c('${1 &gt; 0}') == [im.InterpolateNode(pos=P(1, 1), value='1 > 0')]
def test_it_compiles_inline_interpolation():
    assert c('<div>$a</div>') == [
        im.TextNode(pos=P(1, 1), content='<div>'),
        im.InterpolateNode(pos=P(1, 6), value='a'),
        im.TextNode(pos=P(1, 8), content='</div>')
    ]
def test_it_compiles_content():
    assert c('<div py:content="body">foo</div>') == [
        im.TextNode(pos=P(1, 1), content='<div>'),
        im.InterpolateNode(pos=P(1, 18), value='body'),
        im.TextNode(pos=P(1, 27), content='</div>')
    ]
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