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
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