def __call__(self, stream, ctxt, directives): matched, frame = ctxt._find('_choose.matched') if not frame: raise TemplateRuntimeError( '"when" directives can only be used ' 'inside a "choose" directive', self.filename, *stream.next()[2][1:]) if matched: return [] if not self.expr and '_choose.value' not in frame: raise TemplateRuntimeError( 'either "choose" or "when" directive ' 'must have a test expression', self.filename, *stream.next()[2][1:]) if '_choose.value' in frame: value = frame['_choose.value'] if self.expr: matched = value == self.expr.evaluate(ctxt) else: matched = bool(value) else: matched = bool(self.expr.evaluate(ctxt)) frame['_choose.matched'] = matched if not matched: return [] return _apply_directives(stream, ctxt, directives)
def __call__(self, stream, ctxt, directives): frame = dict({'_choose.matched': False}) if self.expr: frame['_choose.value'] = self.expr.evaluate(ctxt) ctxt.push(frame) for event in _apply_directives(stream, ctxt, directives): yield event ctxt.pop()
def __call__(self, stream, ctxt, directives): frame = {} ctxt.push(frame) for targets, expr in self.vars: value = expr.evaluate(ctxt) for assign in targets: assign(frame, value) for event in _apply_directives(stream, ctxt, directives): yield event ctxt.pop()
def __call__(self, stream, ctxt, directives): matched, frame = ctxt._find('_choose.matched') if not frame: raise TemplateRuntimeError( 'an "otherwise" directive can only be ' 'used inside a "choose" directive', self.filename, *stream.next()[2][1:]) if matched: return [] frame['_choose.matched'] = True return _apply_directives(stream, ctxt, directives)
def __call__(self, stream, ctxt, directives): def _generate(): if self.expr.evaluate(ctxt): stream.next() # skip start tag previous = stream.next() for event in stream: yield previous previous = event else: for event in stream: yield event return _apply_directives(_generate(), ctxt, directives)
def __call__(self, stream, ctxt, directives): iterable = self.expr.evaluate(ctxt) if iterable is None: return assign = self.assign scope = {} stream = list(stream) try: iterator = iter(iterable) for item in iterator: assign(scope, item) ctxt.push(scope) for event in _apply_directives(stream, ctxt, directives): yield event ctxt.pop() except TypeError, e: raise TemplateRuntimeError(str(e), self.filename, *stream[0][2][1:])
def function(*args, **kwargs): scope = {} args = list(args) # make mutable for name in self.args: if args: scope[name] = args.pop(0) else: if name in kwargs: val = kwargs.pop(name) else: val = self.defaults.get(name).evaluate(ctxt) scope[name] = val if not self.star_args is None: scope[self.star_args] = args if not self.dstar_args is None: scope[self.dstar_args] = kwargs ctxt.push(scope) for event in _apply_directives(stream, ctxt, directives): yield event ctxt.pop()
def __call__(self, stream, ctxt, directives): def _generate(): kind, (tag, attrib), pos = stream.next() attrs = self.expr.evaluate(ctxt) if attrs: if isinstance(attrs, Stream): try: attrs = iter(attrs).next() except StopIteration: attrs = [] elif not isinstance(attrs, list): # assume it's a dict attrs = attrs.items() attrib -= [name for name, val in attrs if val is None] attrib |= [(QName(name), unicode(val).strip()) for name, val in attrs if val is not None] yield kind, (tag, attrib), pos for event in stream: yield event return _apply_directives(_generate(), ctxt, directives)
def __call__(self, stream, ctxt, directives): if self.expr.evaluate(ctxt): return _apply_directives(stream, ctxt, directives) return []
def _match(self, stream, ctxt, match_templates=None): """Internal stream filter that applies any defined match templates to the stream. """ if match_templates is None: match_templates = ctxt._match_templates tail = [] def _strip(stream): depth = 1 while 1: event = stream.next() if event[0] is START: depth += 1 elif event[0] is END: depth -= 1 if depth > 0: yield event else: tail[:] = [event] break for event in stream: # We (currently) only care about start and end events for matching # We might care about namespace events in the future, though if not match_templates or (event[0] is not START and event[0] is not END): yield event continue for idx, (test, path, template, namespaces, directives) in \ enumerate(match_templates): if test(event, namespaces, ctxt) is True: # Let the remaining match templates know about the event so # they get a chance to update their internal state for test in [mt[0] for mt in match_templates[idx + 1:]]: test(event, namespaces, ctxt, updateonly=True) # Consume and store all events until an end event # corresponding to this start event is encountered content = chain([event], self._match(_strip(stream), ctxt, [match_templates[idx]]), tail) content = list(self._include(content, ctxt)) for test in [mt[0] for mt in match_templates]: test(tail[0], namespaces, ctxt, updateonly=True) # Make the select() function available in the body of the # match template def select(path): return Stream(content).select(path, namespaces, ctxt) ctxt.push(dict(select=select)) # Recursively process the output template = _apply_directives(template, ctxt, directives) for event in self._match( self._eval(self._flatten(template, ctxt), ctxt), ctxt, match_templates[:idx] + match_templates[idx + 1:]): yield event ctxt.pop() break else: # no matches yield event