root/livinglogic.python.xist/src/ll/ul4c.py @ 5344:9d821bd3f8aa

Revision 5344:9d821bd3f8aa, 80.5 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Move _formatnestednameul4().

Line 
1# -*- coding: utf-8 -*-
2
3## Copyright 2009-2013 by LivingLogic AG, Bayreuth/Germany
4## Copyright 2009-2013 by Walter Dörwald
5##
6## All Rights Reserved
7##
8## See ll/xist/__init__.py for the license
9
10
11"""
12:mod:`ll.ul4c` provides templating for XML/HTML as well as any other text-based
13format. A template defines placeholders for data output and basic logic (like
14loops and conditional blocks), that define how the final rendered output will
15look.
16
17:mod:`ll.ul4c` compiles a template to an internal format, which makes it
18possible to implement template renderers in multiple programming languages.
19"""
20
21
22__docformat__ = "reStructuredText"
23
24
25import re, types, datetime, urllib.parse as urlparse, json, collections, locale, itertools, random, datetime, unicodedata
26
27import antlr3
28
29from ll import color, misc
30
31
32# Regular expression used for splitting dates in isoformat
33datesplitter = re.compile("[-T:.]")
34
35
36def register(name):
37    from ll import ul4on
38    def registration(cls):
39        ul4on.register("de.livinglogic.ul4." + name)(cls)
40        cls.type = name
41        return cls
42    return registration
43
44
45class Object:
46    fields = {}
47
48    def __getitem__(self, key):
49        if key in self.fields:
50            return getattr(self, key)
51        raise KeyError(key)
52
53
54###
55### Location information
56###
57
58@register("location")
59class Location(Object):
60    """
61    A :class:`Location` object contains information about the location of a
62    template tag.
63    """
64    __slots__ = ("root", "source", "type", "starttag", "endtag", "startcode", "endcode")
65    fields = {"root", "source", "type", "starttag", "endtag", "startcode", "endcode", "tag", "code"}
66
67    def __init__(self, root=None, source=None, type=None, starttag=None, endtag=None, startcode=None, endcode=None):
68        """
69        Create a new :class:`Location` object. The arguments have the following
70        meaning:
71
72            :var:`root`
73                The :class:`Template` object
74
75            :var:`source`
76                The complete source string
77
78            :var:`type`
79                The tag type (i.e. ``"for"``, ``"if"``, etc. or ``None`` for
80                literal text)
81
82            :var:`starttag`
83                The start position of the start delimiter.
84
85            :var:`endtag`
86                The end position of the end delimiter.
87
88            :var:`startcode`
89                The start position of the tag code.
90
91            :var:`endcode`
92                The end position of the tag code.
93        """
94        self.root = root
95        self.source = source
96        self.type = type
97        self.starttag = starttag
98        self.endtag = endtag
99        self.startcode = startcode
100        self.endcode = endcode
101
102    @property
103    def code(self):
104        return self.source[self.startcode:self.endcode]
105
106    @property
107    def tag(self):
108        return self.source[self.starttag:self.endtag]
109
110    def __repr__(self):
111        return "<{}.{} {} at {:#x}>".format(self.__class__.__module__, self.__class__.__name__, self, id(self))
112
113    def pos(self):
114        lastlinefeed = self.source.rfind("\n", 0, self.starttag)
115        if lastlinefeed >= 0:
116            return (self.source.count("\n", 0, self.starttag)+1, self.starttag-lastlinefeed)
117        else:
118            return (1, self.starttag + 1)
119
120    def __str__(self):
121        (line, col) = self.pos()
122        return "{!r} at {}:{} (line {}, col {})".format(self.tag, self.starttag, self.endtag, line, col)
123
124    def ul4ondump(self, encoder):
125        encoder.dump(self.root)
126        encoder.dump(self.source)
127        encoder.dump(self.type)
128        encoder.dump(self.starttag)
129        encoder.dump(self.endtag)
130        encoder.dump(self.startcode)
131        encoder.dump(self.endcode)
132
133    def ul4onload(self, decoder):
134        self.root = decoder.load()
135        self.source = decoder.load()
136        self.type = decoder.load()
137        self.starttag = decoder.load()
138        self.endtag = decoder.load()
139        self.startcode = decoder.load()
140        self.endcode = decoder.load()
141
142
143###
144### Exceptions
145###
146
147class Error(Exception):
148    """
149    Exception class that wraps another exception and provides a location.
150    """
151    def __init__(self, location):
152        self.location = location
153
154    def __repr__(self):
155        return "<{}.{} in {} at {:#x}>".format(self.__class__.__module__, self.__class__.__name__, self.location, id(self))
156
157    def __str__(self):
158        if isinstance(self.location, (Template, TemplateClosure)):
159            if self.location.name is not None:
160                return "in template named {}".format(self.location.name)
161            else:
162                return "in unnamed template"
163        elif isinstance(self.location, AST):
164            return "in expression {}".format(self.location)
165        else:
166            return "in {}".format(self.location)
167
168
169class BlockError(Exception):
170    """
171    Exception that is raised by the compiler when an illegal block structure is
172    detected (e.g. an ``<?end if?>`` without a previous ``<?if?>``).
173    """
174
175    def __init__(self, message):
176        self.message = message
177
178    def __str__(self):
179        return self.message
180
181
182###
183### Exceptions used by the interpreted code for flow control
184###
185
186class BreakException(Exception):
187    pass
188
189
190class ContinueException(Exception):
191    pass
192
193
194class ReturnException(Exception):
195    def __init__(self, value):
196        self.value = value
197
198
199###
200### Various versions of undefined objects
201###
202
203class Undefined(object):
204    def __bool__(self):
205        return False
206
207    def __iter__(self):
208        raise TypeError("{!r} doesn't support iteration".format(self))
209
210    def __len__(self):
211        raise AttributeError("{!r} has no len()".format(self))
212
213    def __getattr__(self, key):
214        raise AttributeError("{!r} has no attribute {!r}".format(self, key))
215
216    def __getitem__(self, key):
217        raise TypeError("{!r} doesn't support indexing (key={!r})".format(self, key))
218
219
220class UndefinedKey(Undefined):
221    def __init__(self, key):
222        self.__key = key
223
224    def __repr__(self):
225        return "undefined object for key {!r}".format(self.__key)
226
227
228class UndefinedVariable(Undefined):
229    def __init__(self, name):
230        self.__name = name
231
232    def __repr__(self):
233        return "undefined variable {!r}".format(self.__name)
234
235
236class UndefinedIndex(Undefined):
237    def __init__(self, index):
238        self.__index = index
239
240    def __repr__(self):
241        return "undefined object at index {!r}".format(self.__index)
242
243
244###
245### Compiler stuff: Nodes for the AST
246###
247
248def handleeval(f):
249    def wrapped(self, vars):
250        try:
251            return (yield from f(self, vars))
252        except (BreakException, ContinueException, ReturnException) as ex:
253            raise
254        except Exception as ex:
255            raise Error(self) from ex
256    return wrapped
257
258
259def _formatnestednameul4(name):
260    if isinstance(name, str):
261        return name
262    elif len(name) == 1:
263        return "({},)".format(_formatnestednameul4(name[0]))
264    else:
265        return "({})".format(", ".join(_formatnestednameul4(name) for name in name))
266
267
268class AST(Object):
269    """
270    Base class for all syntax tree nodes.
271    """
272    # used in :meth:`format` to decide if we need brackets around an operator
273    precedence = None
274    associative = True
275
276    # Set of attributes available via :meth:`getitem`.
277    fields = {"type", "location"}
278
279    # "Global" functions and methods. Functions in ``functions`` will be exposed to UL4 code
280    functions = {}
281    methods = {}
282
283    def __init__(self, location=None):
284        self.location = location
285
286    def __getitem__(self, key):
287        if key in self.fields:
288            return getattr(self, key)
289        raise KeyError(key)
290
291    def __repr__(self):
292        return "<{0.__class__.__module__}.{0.__class__.__qualname__} at {1:#x}>".format(self, id(self))
293
294    def _repr_pretty_(self, p, cycle):
295        p.text(repr(self))
296
297    def __str__(self):
298        return "".join(self._str(0))
299
300    def _formatop(self, op):
301        bracket = False
302        if op.precedence < self.precedence:
303            bracket = True
304        elif op.precedence == self.precedence and (not isinstance(op, self.__class__) or not self.associative):
305            bracket = True
306        if bracket:
307            yield "("
308        yield from op._str(0)
309        if bracket:
310            yield ")"
311
312    @misc.notimplemented
313    def _str(self, level):
314        """
315        Format :var:`self` (with the indentation level :var:`level`).
316
317        This is used by :meth:`__str__.
318        """
319
320    @misc.notimplemented
321    def eval(self, vars):
322        """
323        This evaluates the node.
324
325        This is a generator, which yields the text output of the node. If the
326        node returns a value (as most nodes do), this is done as the value of a
327        :exc:`StopIteration` exception.
328        """
329
330    def ul4ondump(self, encoder):
331        encoder.dump(self.location)
332
333    def ul4onload(self, decoder):
334        self.location = decoder.load()
335
336    @classmethod
337    def makefunction(cls, f):
338        name = f.__name__
339        if name.startswith("_"):
340            name = name[1:]
341        cls.functions[name] = f
342        return f
343
344    @classmethod
345    def makemethod(cls, f):
346        name = f.__name__
347        if name.startswith("_"):
348            name = name[1:]
349        cls.methods[name] = f
350        return f
351
352
353@register("text")
354class Text(AST):
355    """
356    AST node for literal text.
357    """
358
359    def text(self):
360        # If ``keepws`` is true, we output the literal text from the location info.
361        # Otherwise we have to strip linefeeds and indentation
362        text = self.location.code
363        if not self.location.root.keepws:
364            text = "".join(line.lstrip() for line in text.splitlines())
365        return text
366
367    def __repr__(self):
368        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {1!r} at {2:#x}>".format(self, self.text(), id(self))
369
370    def _str(self, level):
371        yield "text {!r}\n".format(self.text())
372
373    def eval(self, vars):
374        yield self.text()
375
376
377@register("const")
378class Const(AST):
379    """
380    Load a constant
381    """
382    precedence = 11
383    fields = AST.fields.union({"value"})
384
385    def __init__(self, location=None, value=None):
386        super().__init__(location)
387        self.value = value
388
389    def _str(self, level):
390        yield _repr(self.value)
391
392    def eval(self, vars):
393        yield from ()
394        return self.value
395
396    def ul4ondump(self, encoder):
397        super().ul4ondump(encoder)
398        encoder.dump(self.value)
399
400    def ul4onload(self, decoder):
401        super().ul4onload(decoder)
402        self.value = decoder.load()
403
404    def __repr__(self):
405        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.value!r} at {1:#x}>".format(self, id(self))
406
407
408@register("list")
409class List(AST):
410    """
411    AST nodes for loading a list object.
412    """
413
414    precedence = 11
415    fields = AST.fields.union({"items"})
416
417    def __init__(self, location=None, *items):
418        super().__init__(location)
419        self.items = list(items)
420
421    def __repr__(self):
422        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.items!r} at {1:#x}>".format(self, id(self))
423
424    def _repr_pretty_(self, p, cycle):
425        if cycle:
426            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
427        else:
428            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
429                for (i, item) in enumerate(self.items):
430                    if i:
431                        p.breakable()
432                    else:
433                        p.breakable("")
434                    p.pretty(item)
435                p.breakable()
436                p.text("at {:#x}".format(id(self)))
437
438    def _str(self, level):
439        yield "["
440        for (i, item) in enumerate(self.items):
441            if i:
442                yield ", "
443            yield from item._str(level)
444        yield "]"
445
446    @handleeval
447    def eval(self, vars):
448        result = []
449        for item in self.items:
450            item = (yield from item.eval(vars))
451            result.append(item)
452        return result
453
454    def ul4ondump(self, encoder):
455        super().ul4ondump(encoder)
456        encoder.dump(self.items)
457
458    def ul4onload(self, decoder):
459        super().ul4onload(decoder)
460        self.items = decoder.load()
461
462
463@register("listcomp")
464class ListComp(AST):
465    """
466    AST node for list comprehension.
467    """
468
469    precedence = 11
470    fields = AST.fields.union({"item", "varname", "container", "condition"})
471
472
473    def __init__(self, location=None, item=None, varname=None, container=None, condition=None):
474        super().__init__(location)
475        self.item = item
476        self.varname = varname
477        self.container = container
478        self.condition = condition
479
480    def __repr__(self):
481        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} item={0.item!r} varname={0.varname!r} container={0.container!r}".format(self)
482        if self.condition is not None:
483            s += " condition={0.condition!r}".format(self)
484        return s + " at {:#x}>".format(id(self))
485
486    def _repr_pretty_(self, p, cycle):
487        if cycle:
488            p.text("{0.__class__.__module__}.{0.__class__.__qualname__}(...)".format(self))
489        else:
490            with p.group(4, "{0.__class__.__module__}.{0.__class__.__qualname__}(".format(self), ")"):
491                p.breakable("")
492                p.text("item=")
493                p.pretty(self.item)
494                p.text(",")
495                p.breakable()
496                p.text("varname=")
497                p.pretty(self.varname)
498                p.text(",")
499                p.breakable()
500                p.text("container=")
501                p.pretty(self.container)
502                if self.condition is not None:
503                    p.text(",")
504                    p.breakable()
505                    p.text("condition=")
506                    p.pretty(self.condition)
507                p.breakable()
508                p.text("at {:#x}".format(id(self)))
509
510    def _str(self, level):
511        yield "["
512        yield from self.item._str(level)
513        yield " for "
514        yield _formatnestednameul4(self.varname)
515        yield " in "
516        yield from self.container._str(level)
517        if self.condition is not None:
518            yield " if "
519            yield from self.condition._str(level)
520        yield "]"
521
522    @handleeval
523    def eval(self, vars):
524        container = (yield from self.container.eval(vars))
525        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
526        result = []
527        for item in container:
528            _unpackvar(vars, self.varname, item)
529            if self.condition is None or (yield from self.condition.eval(vars)):
530                item = (yield from self.item.eval(vars))
531                result.append(item)
532        return result
533
534    def ul4ondump(self, encoder):
535        super().ul4ondump(encoder)
536        encoder.dump(self.item)
537        encoder.dump(self.varname)
538        encoder.dump(self.container)
539        encoder.dump(self.condition)
540
541    def ul4onload(self, decoder):
542        super().ul4onload(decoder)
543        self.item = decoder.load()
544        self.varname = decoder.load()
545        self.container = decoder.load()
546        self.condition = decoder.load()
547
548
549@register("dict")
550class Dict(AST):
551    """
552    AST node for loading a dict object.
553    """
554
555    precedence = 11
556    fields = AST.fields.union({"items"})
557
558    def __init__(self, location=None, *items):
559        super().__init__(location)
560        self.items = list(items)
561
562    def __repr__(self):
563        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.items!r} at {1:#x}>".format(self, id(self))
564
565    def _repr_pretty_(self, p, cycle):
566        if cycle:
567            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
568        else:
569            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
570                for item in self.items:
571                    p.breakable()
572                    p.pretty(item[0])
573                    p.text("=")
574                    p.pretty(item[1])
575                p.breakable()
576                p.text("at {:#x}".format(id(self)))
577
578    def _str(self, level):
579        yield "{"
580        for (i, item) in enumerate(self.items):
581            if i:
582                yield ", "
583            yield from item[0]._str(level)
584            yield ": "
585            yield from item[1]._str(level)
586        yield "}"
587
588    @handleeval
589    def eval(self, vars):
590        result = {}
591        for item in self.items:
592            key = (yield from item[0].eval(vars))
593            value = (yield from item[1].eval(vars))
594            result[key] = value
595        return result
596
597    def ul4ondump(self, encoder):
598        super().ul4ondump(encoder)
599        encoder.dump(self.items)
600
601    def ul4onload(self, decoder):
602        super().ul4onload(decoder)
603        self.items = [tuple(item) for item in decoder.load()]
604
605
606@register("dictcomp")
607class DictComp(AST):
608    """
609    AST node for dictionary comprehension.
610    """
611
612    precedence = 11
613    fields = AST.fields.union({"key", "value", "varname", "container", "condition"})
614
615    def __init__(self, location=None, key=None, value=None, varname=None, container=None, condition=None):
616        super().__init__(location)
617        self.key = key
618        self.value = value
619        self.varname = varname
620        self.container = container
621        self.condition = condition
622
623    def __repr__(self):
624        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} key={0.key!r} value={0.value!r} varname={0.varname!r} container={0.container!r}".format(self)
625        if self.condition is not None:
626            s += " {0.condition!r}".format(self)
627        return s + " at {:#x}>".format(id(self))
628
629    def _repr_pretty_(self, p, cycle):
630        if cycle:
631            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
632        else:
633            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
634                p.breakable()
635                p.text("key=")
636                p.pretty(self.key)
637                p.breakable()
638                p.text("value=")
639                p.pretty(self.value)
640                p.breakable()
641                p.text("varname=")
642                p.pretty(self.varname)
643                p.breakable()
644                p.text("container=")
645                p.pretty(self.container)
646                if self.condition is not None:
647                    p.breakable()
648                    p.text("condition=")
649                    p.pretty(self.condition)
650                p.breakable()
651                p.text("at {:#x}".format(id(self)))
652
653    def _str(self, level):
654        yield "{"
655        yield from self.key._str(level)
656        yield " : "
657        yield from self.value._str(level)
658        yield " for "
659        yield _formatnestednameul4(self.varname)
660        yield " in "
661        yield from self.container._str(level)
662        if self.condition is not None:
663            yield " if "
664            yield from self.condition._str(level)
665        yield "]"
666
667    @handleeval
668    def eval(self, vars):
669        container = (yield from self.container.eval(vars))
670        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
671        result = {}
672        for item in container:
673            _unpackvar(vars, self.varname, item)
674            if self.condition is None or (yield from self.condition.eval(vars)):
675                key = (yield from self.key.eval(vars))
676                value = (yield from self.value.eval(vars))
677                result[key] = value
678        return result
679
680    def ul4ondump(self, encoder):
681        super().ul4ondump(encoder)
682        encoder.dump(self.key)
683        encoder.dump(self.value)
684        encoder.dump(self.varname)
685        encoder.dump(self.container)
686        encoder.dump(self.condition)
687
688    def ul4onload(self, decoder):
689        super().ul4onload(decoder)
690        self.key = decoder.load()
691        self.value = decoder.load()
692        self.varname = decoder.load()
693        self.container = decoder.load()
694        self.condition = decoder.load()
695
696
697@register("genexpr")
698class GenExpr(AST):
699    """
700    AST node for a generator expression.
701    """
702
703    precedence = 11
704    fields = AST.fields.union({"item", "varname", "container", "condition"})
705
706    def __init__(self, location=None, item=None, varname=None, container=None, condition=None):
707        super().__init__(location)
708        self.item = item
709        self.varname = varname
710        self.container = container
711        self.condition = condition
712
713    def __repr__(self):
714        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} item={0.item!r} varname={0.varname!r} container={0.container!r}".format(self)
715        if self.condition is not None:
716            s += " condition={0.condition!r}".format(self)
717        return s + " at {:#x}>".format(id(self))
718
719    def _repr_pretty_(self, p, cycle):
720        if cycle:
721            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
722        else:
723            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
724                p.breakable()
725                p.text("item=")
726                p.pretty(self.item)
727                p.breakable()
728                p.text("varname=")
729                p.pretty(self.varname)
730                p.breakable()
731                p.text("container=")
732                p.pretty(self.container)
733                if self.condition is not None:
734                    p.breakable()
735                    p.text("condition=")
736                    p.pretty(self.condition)
737                p.breakable()
738                p.text("at {:#x}".format(id(self)))
739
740    def _str(self, level):
741        yield "("
742        yield from self.item._str(level)
743        yield " for "
744        yield _formatnestednameul4(self.varname)
745        yield " in "
746        yield from self.container._str(level)
747        if self.condition is not None:
748            yield " if "
749            yield from self.condition._str(level)
750        yield ")"
751
752    @handleeval
753    def eval(self, vars):
754        container = (yield from self.container.eval(vars))
755        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
756        def result():
757            for item in container:
758                _unpackvar(vars, self.varname, item)
759                if self.condition is None or (yield from self.condition.eval(vars)):
760                    item = (yield from self.item.eval(vars))
761                    yield item
762        return result()
763
764    def ul4ondump(self, encoder):
765        super().ul4ondump(encoder)
766        encoder.dump(self.item)
767        encoder.dump(self.varname)
768        encoder.dump(self.container)
769        encoder.dump(self.condition)
770
771    def ul4onload(self, decoder):
772        super().ul4onload(decoder)
773        self.item = decoder.load()
774        self.varname = decoder.load()
775        self.container = decoder.load()
776        self.condition = decoder.load()
777
778
779@register("var")
780class Var(AST):
781    """
782    AST nodes for loading a variable.
783    """
784
785    precedence = 11
786    fields = AST.fields.union({"name"})
787
788    def __init__(self, location=None, name=None):
789        super().__init__(location)
790        self.name = name
791
792    def __repr__(self):
793        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.name!r} at {1:#x}>".format(self, id(self))
794
795    def _str(self, level):
796        yield self.name
797
798    @handleeval
799    def eval(self, vars):
800        yield from ()
801        try:
802            return vars[self.name]
803        except KeyError:
804            try:
805                return self.functions[self.name]
806            except KeyError:
807                return UndefinedVariable(self.name)
808
809    def ul4ondump(self, encoder):
810        super().ul4ondump(encoder)
811        encoder.dump(self.name)
812
813    def ul4onload(self, decoder):
814        super().ul4onload(decoder)
815        self.name = decoder.load()
816
817
818class Block(AST):
819    """
820    Base class for all AST nodes that are blocks.
821
822    A block contains a sequence of AST nodes that are executed sequencially.
823    A block may execute its content zero (e.g. an ``<?if?>`` block) or more times
824    (e.g. a ``<?for?>`` block).
825    """
826
827    fields = AST.fields.union({"endlocation", "content"})
828
829    def __init__(self, location=None):
830        super().__init__(location)
831        self.endlocation = None
832        self.content = []
833
834    def append(self, item):
835        self.content.append(item)
836
837    def _str(self, level):
838        if self.content:
839            for node in self.content:
840                yield level*"\t"
841                yield from node._str(level)
842                yield "\n"
843        else:
844            yield level*"\t"
845            yield "pass\n"
846
847    @handleeval
848    def eval(self, vars):
849        for node in self.content:
850            yield from node.eval(vars)
851
852    def ul4ondump(self, encoder):
853        super().ul4ondump(encoder)
854        encoder.dump(self.endlocation)
855        encoder.dump(self.content)
856
857    def ul4onload(self, decoder):
858        super().ul4onload(decoder)
859        self.endlocation = decoder.load()
860        self.content = decoder.load()
861
862
863@register("ieie")
864class IfElIfElse(Block):
865    """
866    AST node for an conditional block.
867
868    The content of the :class:`IfElIfElse` block is one :class:`If` block
869    followed by zero or more :class:`ElIf` blocks followed by zero or one
870    :class:`Else` block.
871    """
872    def __init__(self, location=None, condition=None):
873        super().__init__(location)
874        if condition is not None:
875            self.newblock(If(location, condition))
876
877    def __repr__(self):
878        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {1} at {2:#x}>".format(self, repr(self.content)[1:-1], id(self))
879
880    def _repr_pretty_(self, p, cycle):
881        if cycle:
882            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
883        else:
884            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
885                for node in self.content:
886                    p.breakable()
887                    p.pretty(node)
888                p.breakable()
889                p.text("at {:#x}".format(id(self)))
890
891    def append(self, item):
892        self.content[-1].append(item)
893
894    def newblock(self, block):
895        if self.content:
896            self.content[-1].endlocation = block.location
897        self.content.append(block)
898
899    @handleeval
900    def eval(self, vars):
901        for node in self.content:
902            if isinstance(node, Else) or (yield from node.condition.eval(vars)):
903                yield from node.eval(vars)
904                break
905
906
907@register("if")
908class If(Block):
909    """
910    AST node for an ``<?if?>`` block.
911    """
912
913    fields = Block.fields.union({"condition"})
914
915    def __init__(self, location=None, condition=None):
916        super().__init__(location)
917        self.condition = condition
918
919    def __repr__(self):
920        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} {1} at {2:#x}>".format(self, " ..." if self.content else "", id(self))
921
922    def _repr_pretty_(self, p, cycle):
923        if cycle:
924            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
925        else:
926            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
927                p.breakable()
928                p.text("condition=")
929                p.pretty(self.condition)
930                for node in self.content:
931                    p.breakable()
932                    p.pretty(node)
933                p.breakable()
934                p.text("at {:#x}".format(id(self)))
935
936    def _str(self, level):
937        yield "if "
938        yield from self.condition._str(level)
939        yield ":\n"
940        yield from super()._str(level+1)
941
942    def ul4ondump(self, encoder):
943        super().ul4ondump(encoder)
944        encoder.dump(self.condition)
945
946    def ul4onload(self, decoder):
947        super().ul4onload(decoder)
948        self.condition = decoder.load()
949
950
951@register("elif")
952class ElIf(Block):
953    """
954    AST node for an ``<?elif?>`` block.
955    """
956
957    fields = Block.fields.union({"condition"})
958
959    def __init__(self, location=None, condition=None):
960        super().__init__(location)
961        self.condition = condition
962
963    def __repr__(self):
964        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} {1} at {2:#x}>".format(self, " ..." if self.content else "", id(self))
965
966    def _repr_pretty_(self, p, cycle):
967        if cycle:
968            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
969        else:
970            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
971                p.breakable()
972                p.text("condition=")
973                p.pretty(self.condition)
974                for node in self.content:
975                    p.breakable()
976                    p.pretty(node)
977                p.breakable()
978                p.text("at {:#x}".format(id(self)))
979
980    def _str(self, level):
981        yield "elif "
982        yield from self.condition._str(level)
983        yield ":\n"
984        yield from super()._str(level+1)
985
986    def ul4ondump(self, encoder):
987        super().ul4ondump(encoder)
988        encoder.dump(self.condition)
989
990    def ul4onload(self, decoder):
991        super().ul4onload(decoder)
992        self.condition = decoder.load()
993
994
995@register("else")
996class Else(Block):
997    """
998    AST node for an ``<?else?>`` block.
999    """
1000
1001    def __repr__(self):
1002        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} at {1:#x}>".format(self, id(self))
1003
1004    def _repr_pretty_(self, p, cycle):
1005        if cycle:
1006            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1007        else:
1008            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1009                for node in self.content:
1010                    p.breakable()
1011                    p.pretty(node)
1012                p.breakable()
1013                p.text("at {:#x}".format(id(self)))
1014
1015    def _str(self, level):
1016        yield "else:\n"
1017        yield from super()._str(level+1)
1018
1019
1020@register("for")
1021class For(Block):
1022    """
1023    AST node for a ``<?for?>`` loop variable.
1024    """
1025
1026    fields = Block.fields.union({"varname", "container"})
1027
1028    def __init__(self, location=None, varname=None, container=None):
1029        super().__init__(location)
1030        self.varname = varname
1031        self.container = container
1032
1033    def __repr__(self):
1034        return "<{0.__class__.__module__}.{0.__class__.__qualname__} varname={0.varname!r} container={0.container!r} {1} at {2:#x}>".format(self, " ..." if self.content else "", id(self))
1035
1036    def _repr_pretty_(self, p, cycle):
1037        if cycle:
1038            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1039        else:
1040            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1041                p.breakable()
1042                p.text("varname=")
1043                p.pretty(self.varname)
1044                p.breakable()
1045                p.text("container=")
1046                p.pretty(self.container)
1047                for node in self.content:
1048                    p.breakable()
1049                    p.pretty(node)
1050                p.breakable()
1051                p.text("at {:#x}".format(id(self)))
1052
1053    def ul4ondump(self, encoder):
1054        super().ul4ondump(encoder)
1055        encoder.dump(self.varname)
1056        encoder.dump(self.container)
1057
1058    def ul4onload(self, decoder):
1059        super().ul4onload(decoder)
1060        self.varname = decoder.load()
1061        self.container = decoder.load()
1062
1063    def _str(self, level):
1064        yield "for "
1065        yield _formatnestednameul4(self.varname)
1066        yield " in "
1067        yield from self.container._str(level)
1068        yield ":\n"
1069        yield from super()._str(level+1)
1070
1071    @handleeval
1072    def eval(self, vars):
1073        container = (yield from self.container.eval(vars))
1074        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
1075        for item in container:
1076            _unpackvar(vars, self.varname, item)
1077            try:
1078                yield from super().eval(vars)
1079            except BreakException:
1080                break
1081            except ContinueException:
1082                pass
1083
1084
1085@register("break")
1086class Break(AST):
1087    """
1088    AST node for a ``<?break?>`` inside a ``<?for?>`` block.
1089    """
1090
1091    def _str(self, level):
1092        yield "break\n"
1093
1094    def eval(self, vars):
1095        yield from ()
1096        raise BreakException()
1097
1098
1099@register("continue")
1100class Continue(AST):
1101    """
1102    AST node for a ``<?continue?>`` inside a ``<?for?>`` block.
1103    """
1104
1105    def _str(self, level):
1106        yield "continue\n"
1107
1108    def eval(self, vars):
1109        yield from ()
1110        raise ContinueException()
1111
1112
1113@register("getattr")
1114class GetAttr(AST):
1115    """
1116    AST node for getting an attribute from an object.
1117
1118    The object is loaded from the AST node :var:`obj` and the attribute name
1119    is stored in the string :var:`attrname`.
1120    """
1121    precedence = 9
1122    associative = False
1123    fields = AST.fields.union({"obj", "attrname"})
1124
1125    def __init__(self, location=None, obj=None, attrname=None):
1126        super().__init__(location)
1127        self.obj = obj
1128        self.attrname = attrname
1129
1130    def __repr__(self):
1131        return "<{0.__class__.__module__}.{0.__class__.__qualname__} obj={0.obj!r}, attrname={0.attrname!r} at {1:#x}>".format(self, id(self))
1132
1133    def _repr_pretty_(self, p, cycle):
1134        if cycle:
1135            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1136        else:
1137            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1138                p.breakable()
1139                p.text("obj=")
1140                p.pretty(self.obj)
1141                p.breakable()
1142                p.text("attrname=")
1143                p.pretty(self.attrname)
1144                p.breakable()
1145                p.text("at {:#x}".format(id(self)))
1146
1147    def _str(self, level):
1148        yield from self._formatop(self.obj)
1149        yield "."
1150        yield self.attrname
1151
1152    @handleeval
1153    def eval(self, vars):
1154        obj = (yield from self.obj.eval(vars))
1155        try:
1156            return obj[self.attrname]
1157        except KeyError:
1158            return UndefinedKey(self.attrname)
1159
1160    def ul4ondump(self, encoder):
1161        super().ul4ondump(encoder)
1162        encoder.dump(self.obj)
1163        encoder.dump(self.attrname)
1164
1165    def ul4onload(self, decoder):
1166        super().ul4onload(decoder)
1167        self.obj = decoder.load()
1168        self.attrname = decoder.load()
1169
1170
1171@register("getslice")
1172class GetSlice(AST):
1173    """
1174    AST node for getting a slice from a list or string object.
1175
1176    The object is loaded from the AST node :var:`obj` and the start and stop
1177    indices from the AST node :var:`index1` and :var:`index2`. :var:`index1`
1178    and :var:`index2` may also be :const:`None` (for missing slice indices,
1179    which default to the 0 for the start index and the length of the sequence
1180    for the end index).
1181    """
1182
1183    precedence = 8
1184    associative = False
1185    fields = AST.fields.union({"obj", "index1", "index2"})
1186
1187    def __init__(self, location=None, obj=None, index1=None, index2=None):
1188        super().__init__(location)
1189        self.obj = obj
1190        self.index1 = index1
1191        self.index2 = index2
1192
1193    def __repr__(self):
1194        return "<{0.__class__.__module__}.{0.__class__.__qualname__} obj={0.obj!r} index1={0.index1!r} index2={0.index2!r} at {1:#x}>".format(self, id(self))
1195
1196    def _repr_pretty_(self, p, cycle):
1197        if cycle:
1198            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1199        else:
1200            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1201                p.breakable()
1202                p.text("obj=")
1203                p.pretty(self.obj)
1204                p.breakable()
1205                p.text("index1=")
1206                p.pretty(self.index1)
1207                p.breakable()
1208                p.text("index2=")
1209                p.pretty(self.index2)
1210                p.breakable()
1211                p.text("at {:#x}".format(id(self)))
1212
1213    def _str(self, level):
1214        yield from self._formatop(self.obj)
1215        yield "["
1216        if self.index1 is not None:
1217            yield from self.index1._str(level)
1218        yield ":"
1219        if self.index2 is not None:
1220            yield from self.index2._str(level)
1221        yield "]"
1222
1223    @handleeval
1224    def eval(self, vars):
1225        obj = (yield from self.obj.eval(vars))
1226        if self.index1 is not None:
1227            index1 = (yield from self.index1.eval(vars))
1228            if self.index2 is not None:
1229                index2 = (yield from self.index2.eval(vars))
1230                return obj[index1:index2]
1231            else:
1232                return obj[index1:]
1233        else:
1234            if self.index2 is not None:
1235                index2 = (yield from self.index2.eval(vars))
1236                return obj[:index2]
1237            else:
1238                return obj[:]
1239
1240    def ul4ondump(self, encoder):
1241        super().ul4ondump(encoder)
1242        encoder.dump(self.obj)
1243        encoder.dump(self.index1)
1244        encoder.dump(self.index2)
1245
1246    def ul4onload(self, decoder):
1247        super().ul4onload(decoder)
1248        self.obj = decoder.load()
1249        self.index1 = decoder.load()
1250        self.index2 = decoder.load()
1251
1252
1253class Unary(AST):
1254    """
1255    Base class for all AST nodes implementing unary operators.
1256    """
1257
1258    fields = AST.fields.union({"obj"})
1259
1260    def __init__(self, location=None, obj=None):
1261        super().__init__(location)
1262        self.obj = obj
1263
1264    def __repr__(self):
1265        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj!r} at {1:#x}>".format(self, id(self))
1266
1267    def _repr_pretty_(self, p, cycle):
1268        if cycle:
1269            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1270        else:
1271            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1272                p.breakable()
1273                p.pretty(self.obj)
1274                p.breakable()
1275                p.text("at {:#x}".format(id(self)))
1276
1277    def ul4ondump(self, encoder):
1278        super().ul4ondump(encoder)
1279        encoder.dump(self.obj)
1280
1281    def ul4onload(self, decoder):
1282        super().ul4onload(decoder)
1283        self.obj = decoder.load()
1284
1285    @handleeval
1286    def eval(self, vars):
1287        obj = (yield from self.obj.eval(vars))
1288        return self.evalfold(obj)
1289
1290    @classmethod
1291    def make(cls, location, obj):
1292        if isinstance(obj, Const):
1293            result = cls.evalfold(obj.value)
1294            if not isinstance(result, Undefined):
1295                return Const(location, result)
1296        return cls(location, obj)
1297
1298
1299@register("not")
1300class Not(Unary):
1301    """
1302    AST node for the unary ``not`` operator.
1303    """
1304
1305    precedence = 2
1306
1307    def _str(self, level):
1308        yield "not "
1309        yield from self._formatop(self.obj)
1310
1311    @classmethod
1312    def evalfold(cls, obj):
1313        return not obj
1314
1315
1316@register("neg")
1317class Neg(Unary):
1318    """
1319    AST node for the unary negation (i.e. "-") operator.
1320    """
1321
1322    precedence = 7
1323
1324    def _str(self, level):
1325        yield "-"
1326        yield from self._formatop(self.obj)
1327
1328    @classmethod
1329    def evalfold(cls, obj):
1330        return -obj
1331
1332
1333@register("print")
1334class Print(Unary):
1335    """
1336    AST node for a ``<?print?>`` tag.
1337    """
1338
1339    def _str(self, level):
1340        yield "print "
1341        yield from self.obj._str(level)
1342
1343    @handleeval
1344    def eval(self, vars):
1345        yield _str((yield from self.obj.eval(vars)))
1346
1347
1348@register("printx")
1349class PrintX(Unary):
1350    """
1351    AST node for a ``<?printx?>`` tag.
1352    """
1353
1354    def _str(self, level):
1355        yield "printx "
1356        yield from self.obj._str(level)
1357
1358    @handleeval
1359    def eval(self, vars):
1360        yield _xmlescape((yield from self.obj.eval(vars)))
1361
1362
1363@register("return")
1364class Return(Unary):
1365    """
1366    AST node for a ``<?return?>`` tag.
1367    """
1368
1369    def _str(self, level):
1370        yield "return "
1371        yield from self.obj._str(level)
1372
1373    @handleeval
1374    def eval(self, vars):
1375        value = (yield from self.obj.eval(vars))
1376        raise ReturnException(value)
1377
1378
1379class Binary(AST):
1380    """
1381    Base class for all AST nodes implementing binary operators.
1382    """
1383
1384    fields = AST.fields.union({"obj1", "obj2"})
1385
1386    def __init__(self, location=None, obj1=None, obj2=None):
1387        super().__init__(location)
1388        self.obj1 = obj1
1389        self.obj2 = obj2
1390
1391    def __repr__(self):
1392        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj1!r} {0.obj2!r} at {1:#x}>".format(self, id(self))
1393
1394    def _repr_pretty_(self, p, cycle):
1395        if cycle:
1396            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1397        else:
1398            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1399                p.breakable()
1400                p.pretty(self.obj1)
1401                p.breakable()
1402                p.pretty(self.obj2)
1403                p.breakable()
1404                p.text("at {:#x}".format(id(self)))
1405
1406    def ul4ondump(self, encoder):
1407        super().ul4ondump(encoder)
1408        encoder.dump(self.obj1)
1409        encoder.dump(self.obj2)
1410
1411    def ul4onload(self, decoder):
1412        super().ul4onload(decoder)
1413        self.obj1 = decoder.load()
1414        self.obj2 = decoder.load()
1415
1416    @handleeval
1417    def eval(self, vars):
1418        obj1 = (yield from self.obj1.eval(vars))
1419        obj2 = (yield from self.obj2.eval(vars))
1420        return self.evalfold(obj1, obj2)
1421
1422    @classmethod
1423    def make(cls, location, obj1, obj2):
1424        if isinstance(obj1, Const) and isinstance(obj2, Const):
1425            result = cls.evalfold(obj1.value, obj2.value)
1426            if not isinstance(result, Undefined):
1427                return Const(location, result)
1428        return cls(location, obj1, obj2)
1429
1430
1431@register("getitem")
1432class GetItem(Binary):
1433    """
1434    AST node for subscripting operator.
1435
1436    The object (which must be a list, string or dict) is loaded from the AST
1437    node :var:`obj1` and the index/key is loaded from the AST node :var:`obj2`.
1438    """
1439
1440    precedence = 9
1441    associative = False
1442
1443    @classmethod
1444    def evaluate(cls, obj1, obj2):
1445        return obj1[obj2]
1446
1447    def _str(self, level):
1448        yield from self.obj1._str(level)
1449        yield "["
1450        yield from self.obj2._str(level)
1451        yield "]"
1452
1453    @classmethod
1454    def evalfold(cls, obj1, obj2):
1455        try:
1456            return obj1[obj2]
1457        except KeyError:
1458            return UndefinedKey(obj2)
1459        except IndexError:
1460            return UndefinedIndex(obj2)
1461
1462
1463@register("eq")
1464class EQ(Binary):
1465    """
1466    AST node for the binary ``==`` comparison operator.
1467    """
1468
1469    precedence = 4
1470    associative = False
1471
1472    def _str(self, level):
1473        yield from self._formatop(self.obj1)
1474        yield " == "
1475        yield from self._formatop(self.obj2)
1476
1477    @classmethod
1478    def evalfold(cls, obj1, obj2):
1479        return obj1 == obj2
1480
1481
1482@register("ne")
1483class NE(Binary):
1484    """
1485    AST node for the binary ``!=`` comparison operator.
1486    """
1487
1488    precedence = 4
1489    associative = False
1490
1491    def _str(self, level):
1492        yield from self._formatop(self.obj1)
1493        yield " != "
1494        yield from self._formatop(self.obj2)
1495
1496    @classmethod
1497    def evalfold(cls, obj1, obj2):
1498        return obj1 != obj2
1499
1500
1501@register("lt")
1502class LT(Binary):
1503    """
1504    AST node for the binary ``<`` comparison operator.
1505    """
1506
1507    precedence = 4
1508    associative = False
1509
1510    def _str(self, level):
1511        yield from self._formatop(self.obj1)
1512        yield " < "
1513        yield from self._formatop(self.obj2)
1514
1515    @classmethod
1516    def evalfold(cls, obj1, obj2):
1517        return obj1 < obj2
1518
1519
1520@register("le")
1521class LE(Binary):
1522    """
1523    AST node for the binary ``<=`` comparison operator.
1524    """
1525
1526    precedence = 4
1527    associative = False
1528
1529    def _str(self, level):
1530        yield from self._formatop(self.obj1)
1531        yield " <= "
1532        yield from self._formatop(self.obj2)
1533
1534    @classmethod
1535    def evalfold(cls, obj1, obj2):
1536        return obj1 <= obj2
1537
1538
1539@register("gt")
1540class GT(Binary):
1541    """
1542    AST node for the binary ``>`` comparison operator.
1543    """
1544
1545    precedence = 4
1546    associative = False
1547
1548    def _str(self, level):
1549        yield from self._formatop(self.obj1)
1550        yield " > "
1551        yield from self._formatop(self.obj2)
1552
1553    @classmethod
1554    def evalfold(cls, obj1, obj2):
1555        return obj1 > obj2
1556
1557
1558@register("ge")
1559class GE(Binary):
1560    """
1561    AST node for the binary ``>=`` comparison operator.
1562    """
1563
1564    precedence = 4
1565    associative = False
1566
1567    def _str(self, level):
1568        yield from self._formatop(self.obj1)
1569        yield " >= "
1570        yield from self._formatop(self.obj2)
1571
1572    @classmethod
1573    def evalfold(cls, obj1, obj2):
1574        return obj1 >= obj2
1575
1576
1577@register("contains")
1578class Contains(Binary):
1579    """
1580    AST node for the binary containment testing operator.
1581
1582    The item/key object is loaded from the AST node :var:`obj1` and the container
1583    object (which must be a list, string or dict) is loaded from the AST node
1584    :var:`obj2`.
1585    """
1586
1587    precedence = 3
1588    associative = False
1589
1590    def _str(self, level):
1591        yield from self._formatop(self.obj1)
1592        yield " in "
1593        yield from self._formatop(self.obj2)
1594
1595    @classmethod
1596    def evalfold(cls, obj1, obj2):
1597        return obj1 in obj2
1598
1599
1600@register("notcontains")
1601class NotContains(Binary):
1602    """
1603    AST node for the inverted containment testing operator.
1604
1605    The item/key object is loaded from the AST node :var:`obj1` and the container
1606    object (which must be a list, string or dict) is loaded from the AST node
1607    :var:`obj2`.
1608    """
1609
1610    precedence = 3
1611    associative = False
1612
1613    def _str(self, level):
1614        yield from self._formatop(self.obj1)
1615        yield " not in "
1616        yield from self._formatop(self.obj2)
1617
1618    @classmethod
1619    def evalfold(cls, obj1, obj2):
1620        return obj1 not in obj2
1621
1622
1623@register("add")
1624class Add(Binary):
1625    """
1626    AST node for the binary addition operator.
1627    """
1628
1629    precedence = 5
1630
1631    def _str(self, level):
1632        yield from self._formatop(self.obj1)
1633        yield "+"
1634        yield from self._formatop(self.obj2)
1635
1636    @classmethod
1637    def evalfold(cls, obj1, obj2):
1638        return obj1 + obj2
1639
1640
1641@register("sub")
1642class Sub(Binary):
1643    """
1644    AST node for the binary substraction operator.
1645    """
1646
1647    precedence = 5
1648    associative = False
1649
1650    def _str(self, level):
1651        yield from self._formatop(self.obj1)
1652        yield "-"
1653        yield from self._formatop(self.obj2)
1654
1655    @classmethod
1656    def evalfold(cls, obj1, obj2):
1657        return obj1 - obj2
1658
1659
1660@register("mul")
1661class Mul(Binary):
1662    """
1663    AST node for the binary multiplication operator.
1664    """
1665
1666    precedence = 6
1667
1668    def _str(self, level):
1669        yield from self._formatop(self.obj1)
1670        yield "*"
1671        yield from self._formatop(self.obj2)
1672
1673    @classmethod
1674    def evalfold(cls, obj1, obj2):
1675        return obj1 * obj2
1676
1677
1678@register("floordiv")
1679class FloorDiv(Binary):
1680    """
1681    AST node for the binary truncating division operator.
1682    """
1683
1684    precedence = 6
1685    associative = False
1686
1687    def _str(self, level):
1688        yield from self._formatop(self.obj1)
1689        yield "//"
1690        yield from self._formatop(self.obj2)
1691
1692    @classmethod
1693    def evalfold(cls, obj1, obj2):
1694        return obj1 // obj2
1695
1696
1697@register("truediv")
1698class TrueDiv(Binary):
1699    """
1700    AST node for the binary true division operator.
1701    """
1702
1703    precedence = 6
1704    associative = False
1705
1706    def _str(self, level):
1707        yield from self._formatop(self.obj1)
1708        yield "/"
1709        yield from self._formatop(self.obj2)
1710
1711    @classmethod
1712    def evalfold(cls, obj1, obj2):
1713        return obj1 / obj2
1714
1715
1716@register("and")
1717class And(Binary):
1718    """
1719    AST node for the binary ``and`` operator.
1720    """
1721
1722    precedence = 1
1723
1724    def _str(self, level):
1725        yield from self._formatop(self.obj1)
1726        yield " and "
1727        yield from self._formatop(self.obj2)
1728
1729    @classmethod
1730    def evalfold(cls, obj1, obj2):
1731        # This is not called from ``eval``, as it doesn't short-circuit
1732        return obj1 and obj2
1733
1734    @handleeval
1735    def eval(self, vars):
1736        obj1 = (yield from self.obj1.eval(vars))
1737        if not obj1:
1738            return obj1
1739        return (yield from self.obj2.eval(vars))
1740
1741
1742
1743@register("or")
1744class Or(Binary):
1745    """
1746    AST node for the binary ``or`` operator.
1747    """
1748
1749    precedence = 0
1750
1751    def _str(self, level):
1752        yield from self._formatop(self.obj1)
1753        yield " or "
1754        yield from self._formatop(self.obj2)
1755
1756    @classmethod
1757    def evalfold(cls, obj1, obj2):
1758        # This is not called from ``eval``, as it doesn't short-circuit
1759        return obj1 or obj2
1760
1761    @handleeval
1762    def eval(self, vars):
1763        obj1 = (yield from self.obj1.eval(vars))
1764        if obj1:
1765            return obj1
1766        return (yield from self.obj2.eval(vars))
1767
1768
1769@register("mod")
1770class Mod(Binary):
1771    """
1772    AST node for the binary modulo operator.
1773    """
1774
1775    precedence = 6
1776    associative = False
1777
1778    def _str(self, level):
1779        yield from self._formatop(self.obj1)
1780        yield "%"
1781        yield from self._formatop(self.obj2)
1782
1783    @classmethod
1784    def evalfold(cls, obj1, obj2):
1785        return obj1 % obj2
1786
1787
1788class ChangeVar(AST):
1789    """
1790    Baseclass for all AST nodes that store or modify a variable.
1791
1792    The variable name is stored in the string :var:`varname` and the value that
1793    will be stored or be used to modify the stored value is loaded from the
1794    AST node :var:`value`.
1795    """
1796
1797    fields = AST.fields.union({"varname", "value"})
1798
1799    def __init__(self, location=None, varname=None, value=None):
1800        super().__init__(location)
1801        self.varname = varname
1802        self.value = value
1803
1804    def __repr__(self):
1805        return "<{0.__class__.__module__}.{0.__class__.__qualname__} varname={0.varname!r} value={0.value!r} at {1:#x}>".format(self, id(self))
1806
1807    def _repr_pretty_(self, p, cycle):
1808        if cycle:
1809            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1810        else:
1811            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1812                p.breakable()
1813                p.text("varname=")
1814                p.pretty(self.obj1)
1815                p.text("value=")
1816                p.breakable()
1817                p.pretty(self.obj2)
1818                p.breakable()
1819                p.text("at {:#x}".format(id(self)))
1820
1821    def ul4ondump(self, encoder):
1822        super().ul4ondump(encoder)
1823        encoder.dump(self.varname)
1824        encoder.dump(self.value)
1825
1826    def ul4onload(self, decoder):
1827        super().ul4onload(decoder)
1828        self.varname = decoder.load()
1829        self.value = decoder.load()
1830
1831
1832@register("storevar")
1833class StoreVar(ChangeVar):
1834    """
1835    AST node that stores a value into a variable.
1836    """
1837
1838    def _str(self, level):
1839        yield _formatnestednameul4(self.varname)
1840        yield " = "
1841        yield from self.value._str(level)
1842
1843    @handleeval
1844    def eval(self, vars):
1845        value = (yield from self.value.eval(vars))
1846        _unpackvar(vars, self.varname, value)
1847
1848
1849@register("addvar")
1850class AddVar(ChangeVar):
1851    """
1852    AST node that adds a value to a variable (i.e. the ``+=`` operator).
1853    """
1854
1855    def _str(self, level):
1856        yield _formatnestednameul4(self.varname)
1857        yield " += "
1858        yield from self.value._str(level)
1859
1860    @handleeval
1861    def eval(self, vars):
1862        value = (yield from self.value.eval(vars))
1863        vars[self.varname] += value
1864
1865
1866@register("subvar")
1867class SubVar(ChangeVar):
1868    """
1869    AST node that substracts a value from a variable (i.e. the ``-=`` operator).
1870    """
1871
1872    def _str(self, level):
1873        yield _formatnestednameul4(self.varname)
1874        yield " -= "
1875        yield from self.value._str(level)
1876
1877    @handleeval
1878    def eval(self, vars):
1879        value = (yield from self.value.eval(vars))
1880        vars[self.varname] -= value
1881
1882
1883@register("mulvar")
1884class MulVar(ChangeVar):
1885    """
1886    AST node that multiplies a variable by a value (i.e. the ``*=`` operator).
1887    """
1888
1889    def _str(self, level):
1890        yield _formatnestednameul4(self.varname)
1891        yield " *= "
1892        yield from self.value._str(level)
1893
1894    @handleeval
1895    def eval(self, vars):
1896        value = (yield from self.value.eval(vars))
1897        vars[self.varname] *= value
1898
1899
1900@register("floordivvar")
1901class FloorDivVar(ChangeVar):
1902    """
1903    AST node that divides a variable by a value (truncating to an integer value;
1904    i.e. the ``//=`` operator).
1905    """
1906
1907    def _str(self, level):
1908        yield _formatnestednameul4(self.varname)
1909        yield " //= "
1910        yield from self.value._str(level)
1911
1912    @handleeval
1913    def eval(self, vars):
1914        value = (yield from self.value.eval(vars))
1915        vars[self.varname] //= value
1916
1917
1918@register("truedivvar")
1919class TrueDivVar(ChangeVar):
1920    """
1921    AST node that divides a variable by a value (i.e. the ``/=`` operator).
1922    """
1923
1924    def _str(self, level):
1925        yield _formatnestednameul4(self.varname)
1926        yield " /= "
1927        yield from self.value._str(level)
1928
1929    @handleeval
1930    def eval(self, vars):
1931        value = (yield from self.value.eval(vars))
1932        vars[self.varname] /= value
1933
1934
1935@register("modvar")
1936class ModVar(ChangeVar):
1937    """
1938    AST node for the ``%=`` operator.
1939    """
1940
1941    def _str(self, level):
1942        yield _formatnestednameul4(self.varname)
1943        yield " %= "
1944        yield from self.value._str(level)
1945
1946    @handleeval
1947    def eval(self, vars):
1948        value = (yield from self.value.eval(vars))
1949        vars[self.varname] %= value
1950
1951
1952@register("callfunc")
1953class CallFunc(AST):
1954    """
1955    AST node for calling an function.
1956
1957    The object to be called is stored in the attribute :var:`obj`. The list of
1958    positional arguments is loaded from the list of AST nodes :var:`args`.
1959    Keyword arguments are in :var:`kwargs`. `var`:remargs` is the AST node
1960    for the ``*`` argument (and may by ``None`` if there is no ``*`` argument).
1961    `var`:remkwargs` is the AST node for the ``**`` argument (and may by ``None``
1962    if there is no ``**`` argument)
1963    """
1964
1965    precedence = 10
1966    associative = False
1967    fields = AST.fields.union({"obj", "args", "kwargs", "remargs", "remkwargs"})
1968
1969    def __init__(self, location=None, obj=None):
1970        super().__init__(location)
1971        self.obj = obj
1972        self.args = []
1973        self.kwargs = []
1974        self.remargs = None
1975        self.remkwargs = None
1976
1977    def __repr__(self):
1978        return "<{0.__class__.__module__}.{0.__class__.__qualname__} obj={0.obj!r}{1}{2}{3}{4} at {5:#x}>".format(
1979            self,
1980            "".join(" {!r}".format(arg) for arg in self.args),
1981            "".join(" {}={!r}".format(argname, argvalue) for (argname, argvalue) in self.kwargs),
1982            " *{!r}".format(self.remargs) if self.remargs is not None else "",
1983            " **{!r}".format(self.remkwargs) if self.remargs is not None else "",
1984            id(self))
1985
1986    def _repr_pretty_(self, p, cycle):
1987        if cycle:
1988            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1989        else:
1990            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1991                p.breakable()
1992                p.text("obj=")
1993                p.pretty(self.obj)
1994                for arg in self.args:
1995                    p.breakable()
1996                    p.pretty(arg)
1997                for (argname, arg) in self.kwargs:
1998                    p.breakable()
1999                    p.text("{}=".format(argname))
2000                    p.pretty(arg)
2001                if self.remargs is not None:
2002                    p.breakable()
2003                    p.text("*")
2004                    p.pretty(self.remargs)
2005                if self.remkwargs is not None:
2006                    p.breakable()
2007                    p.text("**")
2008                    p.pretty(self.remkwargs)
2009                p.breakable()
2010                p.text("at {:#x}".format(id(self)))
2011
2012    def _str(self, level):
2013        yield from self.obj._str(level)
2014        yield "("
2015        first = True
2016        for arg in self.args:
2017            if first:
2018                first = False
2019            else:
2020                yield ", "
2021            yield from arg._str(level)
2022        for (argname, argvalue) in self.kwargs:
2023            if first:
2024                first = False
2025            else:
2026                yield ", "
2027            yield argname
2028            yield "="
2029            yield from argvalue._str(level)
2030        if self.remargs is not None:
2031            if first:
2032                first = False
2033            else:
2034                yield ", "
2035            yield "*"
2036            yield from self.remargs._str(level)
2037        if self.remkwargs is not None:
2038            if first:
2039                first = False
2040            else:
2041                yield ", "
2042            yield "**"
2043            yield from self.remkwargs._str(level)
2044        yield ")"
2045
2046    @handleeval
2047    def eval(self, vars):
2048        obj = (yield from self.obj.eval(vars))
2049        args = []
2050        for arg in self.args:
2051            arg = (yield from arg.eval(vars))
2052            args.append(arg)
2053        kwargs = {}
2054        for (argname, arg) in self.kwargs:
2055            kwargs[argname] = (yield from arg.eval(vars))
2056        if self.remargs is not None:
2057            args.extend((yield from self.remargs.eval(vars)))
2058        if self.remkwargs is not None:
2059            kwargs.update((yield from self.remkwargs.eval(vars)))
2060        result = obj(*args, **kwargs)
2061        if isinstance(result, types.GeneratorType):
2062            return (yield from result)
2063        else:
2064            return result
2065
2066    def ul4ondump(self, encoder):
2067        super().ul4ondump(encoder)
2068        encoder.dump(self.obj)
2069        encoder.dump(self.args)
2070        encoder.dump(self.kwargs)
2071        encoder.dump(self.remargs)
2072        encoder.dump(self.remkwargs)
2073
2074    def ul4onload(self, decoder):
2075        super().ul4onload(decoder)
2076        self.obj = decoder.load()
2077        self.args = decoder.load()
2078        self.kwargs = [tuple(arg) for arg in decoder.load()]
2079        self.remargs = decoder.load()
2080        self.remkwargs = decoder.load()
2081
2082
2083@register("callmeth")
2084class CallMeth(AST):
2085    """
2086    AST node for calling a method.
2087
2088    The method name is stored in the string :var:`methname`. The object for which
2089    the method will be called is loaded from the AST node :var:`obj` and the list
2090    of arguments is loaded from the list of AST nodes :var:`args`. Keyword
2091    arguments are in :var:`kwargs`. `var`:remargs` is the AST node for the ``*``
2092    argument (and may by ``None`` if there is no ``*`` argument).
2093    `var`:remkwargs` is the AST node for the ``**`` argument (and may by ``None``
2094    if there is no ``**`` argument)
2095    """
2096
2097    precedence = 9
2098    associative = False
2099    fields = AST.fields.union({"obj", "methname", "args", "kwargs", "remargs", "remkwargs"})
2100
2101    def __init__(self, location=None, obj=None, methname=None):
2102        super().__init__(location)
2103        self.obj = obj
2104        self.methname = methname
2105        self.args = []
2106        self.kwargs = []
2107        self.remargs = None
2108        self.remkwargs = None
2109
2110    def __repr__(self):
2111        return "<{0.__class__.__module__}.{0.__class__.__qualname__} methname={0.methname!r} obj={0.obj!r}{1}{2}{3}{4} at {5:#x}>".format(
2112            self,
2113            "".join(" {!r}".format(arg) for arg in self.args),
2114            "".join(" {}={!r}".format(argname, argvalue) for (argname, argvalue) in self.kwargs),
2115            " *{!r}".format(self.remargs) if self.remargs is not None else "",
2116            " **{!r}".format(self.remkwargs) if self.remargs is not None else "",
2117            id(self))
2118
2119    def _repr_pretty_(self, p, cycle):
2120        if cycle:
2121            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
2122        else:
2123            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
2124                p.breakable()
2125                p.text("methname=")
2126                p.pretty(self.methname)
2127                p.breakable()
2128                p.text("obj=")
2129                p.pretty(self.obj)
2130                for arg in self.args:
2131                    p.breakable()
2132                    p.pretty(arg)
2133                for (argname, arg) in self.kwargs:
2134                    p.breakable()
2135                    p.text("{}=".format(argname))
2136                    p.pretty(arg)
2137                if self.remargs is not None:
2138                    p.breakable()
2139                    p.text("*")
2140                    p.pretty(self.remargs)
2141                if self.remkwargs is not None:
2142                    p.breakable()
2143                    p.text("**")
2144                    p.pretty(self.remkwargs)
2145                p.breakable()
2146                p.text("at {:#x}".format(id(self)))
2147
2148    def _str(self, level):
2149        yield from self._formatop(self.obj)
2150        yield "."
2151        yield self.methname
2152        yield "("
2153        first = True
2154        for arg in self.args:
2155            if first:
2156                first = False
2157            else:
2158                yield ", "
2159            yield from arg._str(level)
2160        for (argname, argvalue) in self.kwargs:
2161            if first:
2162                first = False
2163            else:
2164                yield ", "
2165            yield argname
2166            yield "="
2167            yield from argvalue._str(level)
2168        if self.remargs is not None:
2169            if first:
2170                first = False
2171            else:
2172                yield ", "
2173            yield "*"
2174            yield from self.remargs._str(level)
2175        if self.remkwargs is not None:
2176            if first:
2177                first = False
2178            else:
2179                yield ", "
2180            yield "**"
2181            yield from self.remkwargs._str(level)
2182        yield ")"
2183
2184    @handleeval
2185    def eval(self, vars):
2186        obj = (yield from self.obj.eval(vars))
2187        args = []
2188        for arg in self.args:
2189            arg = (yield from arg.eval(vars))
2190            args.append(arg)
2191        kwargs = {}
2192        for (argname, arg) in self.kwargs:
2193            kwargs[argname] = (yield from arg.eval(vars))
2194        if self.remargs is not None:
2195            args.extend((yield from self.remargs.eval(vars)))
2196        if self.remkwargs is not None:
2197            kwargs.update((yield from self.remkwargs.eval(vars)))
2198        result = self.methods[self.methname](obj, *args, **kwargs)
2199        if isinstance(result, types.GeneratorType):
2200            return (yield from result)
2201        else:
2202            return result
2203
2204    def ul4ondump(self, encoder):
2205        super().ul4ondump(encoder)
2206        encoder.dump(self.methname)
2207        encoder.dump(self.obj)
2208        encoder.dump(self.args)
2209        encoder.dump(self.kwargs)
2210        encoder.dump(self.remargs)
2211        encoder.dump(self.remkwargs)
2212
2213    def ul4onload(self, decoder):
2214        super().ul4onload(decoder)
2215        self.methname = decoder.load()
2216        self.obj = decoder.load()
2217        self.args = decoder.load()
2218        self.kwargs = [tuple(arg) for arg in decoder.load()]
2219        self.remargs = decoder.load()
2220        self.remkwargs = decoder.load()
2221
2222
2223@register("template")
2224class Template(Block):
2225    """
2226    A template object is normally created by passing the template source to the
2227    constructor. It can also be loaded from the compiled format via the class
2228    methods :meth:`load` (from a stream) or :meth:`loads` (from a string).
2229
2230    The compiled format can be generated with the methods :meth:`dump` (which
2231    dumps the format to a stream) or :meth:`dumps` (which returns a string with
2232    the compiled format).
2233
2234    Rendering the template can be done with the methods :meth:`render` (which
2235    is a generator) or :meth:`renders` (which returns a string).
2236
2237    A :class:`Template` object is itself an AST node. Evaluating it will store
2238    the template object under its name in the local variables.
2239
2240    A :class:`Template` can also be called as a function (returning the result
2241    of the first ``<?return?>`` tag encountered. In this case all output of the
2242    template will be ignored.
2243    """
2244    fields = Block.fields.union({"source", "name", "keepws", "startdelim", "enddelim"})
2245
2246    version = "24"
2247
2248    def __init__(self, source=None, name=None, keepws=True, startdelim="<?", enddelim="?>"):
2249        """
2250        Create a :class:`Template` object. If :var:`source` is ``None``, the
2251        :class:`Template` remains uninitialized, otherwise :var:`source` will be
2252        compiled (using :var:`startdelim` and :var:`enddelim` as the tag
2253        delimiters). :var:`name` is the name of the template. It will be used in
2254        exception messages and should be a valid Python identifier. If
2255        :var:`keepws` is false linefeeds and indentation will be ignored in the
2256        literal text in templates (i.e. the text between the tags). However
2257        trailing whitespace at the end of the line will be honored regardless of
2258        the value of :var:`keepws`. Output will always be ignored when calling
2259        a template as a function.
2260        """
2261        # ``location``/``endlocation`` will remain ``None`` for a top level template
2262        # For a subtemplate/subfunction ``location`` will be set to the location of the ``<?def?>`` tag in :meth:`_compile`
2263        # and ``endlocation`` will be the location of the ``<?end def?>`` tag
2264        super().__init__(None)
2265        self.keepws = keepws
2266        self.startdelim = startdelim
2267        self.enddelim = enddelim
2268        self.name = name
2269        self.source = None
2270
2271        # If we have source code compile it
2272        if source is not None:
2273            self._compile(source, name, startdelim, enddelim)
2274
2275    def __repr__(self):
2276        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} name={0.name!r} keepws={0.keepws!r}".format(self)
2277        if self.startdelim != "<?":
2278            s += " startdelim={0.startdelim!r}".format(self)
2279        if self.enddelim != "?>":
2280            s += " enddelim={0.enddelim!r}".format(self)
2281        if self.content:
2282            s + " ..."
2283        return s + " at {:#x}>".format(id(self))
2284
2285    def _str(self, level):
2286        yield "def "
2287        yield self.name if self.name is not None else "unnamed"
2288        yield ":\n"
2289        yield from super()._str(level+1)
2290
2291    def _repr_pretty_(self, p, cycle):
2292        if cycle:
2293            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
2294        else:
2295            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
2296                p.breakable()
2297                p.text("name=")
2298                p.pretty(self.name)
2299                p.breakable()
2300                p.text("keepws=")
2301                p.pretty(self.keepws)
2302                if self.startdelim != "<?":
2303                    p.breakable()
2304                    p.text("startdelim=")
2305                    p.pretty(self.startdelim)
2306                if self.enddelim != "?>":
2307                    p.breakable()
2308                    p.text("enddelim=")
2309                    p.pretty(self.enddelim)
2310                for node in self.content:
2311                    p.breakable()
2312                    p.pretty(node)
2313                p.breakable()
2314                p.text("at {:#x}".format(id(self)))
2315
2316    def ul4ondump(self, encoder):
2317        # Don't call ``super().ul4ondump()``, as we want the version to be first
2318        encoder.dump(self.version)
2319        encoder.dump(self.source)
2320        encoder.dump(self.name)
2321        encoder.dump(self.keepws)
2322        encoder.dump(self.startdelim)
2323        encoder.dump(self.enddelim)
2324        encoder.dump(self.location)
2325        encoder.dump(self.endlocation)
2326        encoder.dump(self.content)
2327
2328    def ul4onload(self, decoder):
2329        version = decoder.load()
2330        if version != self.version:
2331            raise ValueError("invalid version, expected {!r}, got {!r}".format(self.version, version))
2332        self.source = decoder.load()
2333        self.name = decoder.load()
2334        self.keepws = decoder.load()
2335        self.startdelim = decoder.load()
2336        self.enddelim = decoder.load()
2337        self.location = decoder.load()
2338        self.endlocation = decoder.load()
2339        self.content = decoder.load()
2340
2341    @classmethod
2342    def loads(cls, data):
2343        """
2344        The class method :meth:`loads` loads the template/function from string
2345        :var:`data`. :var:`data` must contain the template/function in compiled
2346        UL4ON format.
2347        """
2348        from ll import ul4on
2349        return ul4on.loads(data)
2350
2351    @classmethod
2352    def load(cls, stream):
2353        """
2354        The class method :meth:`load` loads the template/function from the stream
2355        :var:`stream`. The stream must contain the template/function in compiled
2356        UL4ON format.
2357        """
2358        from ll import ul4on
2359        return ul4on.load(stream)
2360
2361    def dump(self, stream):
2362        """
2363        :meth:`dump` dumps the template/function in compiled UL4ON format to the
2364        stream :var:`stream`.
2365        """
2366        from ll import ul4on
2367        ul4on.dump(self, stream)
2368
2369    def dumps(self):
2370        """
2371        :meth:`dumps` returns the template/function in compiled UL4ON format
2372        (as a string).
2373        """
2374        from ll import ul4on
2375        return ul4on.dumps(self)
2376
2377    def render(self, **vars):
2378        """
2379        Render the template iteratively (i.e. this is a generator).
2380        :var:`vars` contains the top level variables available to the
2381        template code.
2382        """
2383        yield from super().eval(vars) # Bypass ``self.eval()`` which simply stores the object as a local variable
2384
2385    def renders(self, **vars):
2386        """
2387        Render the template as a string. :var:`vars` contains the top level
2388        variables available to the template code.
2389        """
2390        return "".join(self.render(**vars))
2391
2392    def __call__(self, **vars):
2393        """
2394        Call the template as a function and return the resulting value.
2395        :var:`vars` contains the top level variables available to the template code.
2396        """
2397        try:
2398            for output in super().eval(vars): # Bypass ``self.eval()`` which simply stores the object as a local variable
2399                pass # Ignore all output
2400        except ReturnException as ex:
2401            return ex.value
2402
2403    def jssource(self):
2404        """
2405        Return the template as the source code of a Javascript function.
2406        """
2407        return "ul4.Template.loads({})".format(_asjson(self.dumps()))
2408
2409    def javasource(self):
2410        """
2411        Return the template as Java source code.
2412        """
2413        return "com.livinglogic.ul4.InterpretedTemplate.loads({})".format(misc.javaexpr(self.dumps()))
2414
2415    def _tokenize(self, source, startdelim, enddelim):
2416        """
2417        Tokenize the template/function source code :var:`source` into tags and
2418        non-tag text. :var:`startdelim` and :var:`enddelim` are used as the tag
2419        delimiters.
2420
2421        This is a generator which produces :class:`Location` objects for each tag
2422        or non-tag text. It will be called by :meth:`_compile` internally.
2423        """
2424        pattern = "{}(printx|print|code|for|if|elif|else|end|break|continue|def|return|note)(\s*((.|\\n)*?)\s*)?{}".format(re.escape(startdelim), re.escape(enddelim))
2425        pos = 0
2426        for match in re.finditer(pattern, source):
2427            if match.start() != pos:
2428                yield Location(self, source, None, pos, match.start(), pos, match.start())
2429            type = source[match.start(1):match.end(1)]
2430            if type != "note":
2431                yield Location(self, source, type, match.start(), match.end(), match.start(3), match.end(3))
2432            pos = match.end()
2433        end = len(source)
2434        if pos != end:
2435            yield Location(self, source, None, pos, end, pos, end)
2436
2437    def _parser(self, location, error):
2438        from ll import UL4Lexer, UL4Parser
2439        source = location.code
2440        if not source:
2441            raise ValueError(error)
2442        stream = antlr3.ANTLRStringStream(source)
2443        lexer = UL4Lexer.UL4Lexer(stream)
2444        lexer.location = location
2445        tokens = antlr3.CommonTokenStream(lexer)
2446        parser = UL4Parser.UL4Parser(tokens)
2447        parser.location = location
2448        return parser
2449
2450    def _compile(self, source, name, startdelim, enddelim):
2451        """
2452        Compile the template source code :var:`source` into an AST.
2453        :var:`startdelim` and :var:`enddelim` are used as the tag delimiters.
2454        """
2455        self.name = name
2456        self.startdelim = startdelim
2457        self.enddelim = enddelim
2458
2459        # This stack stores the nested for/if/elif/else/def blocks
2460        stack = [self]
2461
2462        self.source = source
2463
2464        if source is None:
2465            return
2466
2467        def parseexpr(location):
2468            return self._parser(location, "expression required").expression()
2469
2470        def parsestmt(location):
2471            return self._parser(location, "statement required").statement()
2472
2473        def parsefor(location):
2474            return self._parser(location, "loop expression required").for_()
2475
2476        for location in self._tokenize(source, startdelim, enddelim):
2477            try:
2478                if location.type is None:
2479                    stack[-1].append(Text(location))
2480                elif location.type == "print":
2481                    stack[-1].append(Print(location, parseexpr(location)))
2482                elif location.type == "printx":
2483                    stack[-1].append(PrintX(location, parseexpr(location)))
2484                elif location.type == "code":
2485                    stack[-1].append(parsestmt(location))
2486                elif location.type == "if":
2487                    block = IfElIfElse(location, parseexpr(location))
2488                    stack[-1].append(block)
2489                    stack.append(block)
2490                elif location.type == "elif":
2491                    if not isinstance(stack[-1], IfElIfElse):
2492                        raise BlockError("elif doesn't match and if")
2493                    elif isinstance(stack[-1].content[-1], Else):
2494                        raise BlockError("else already seen in if")
2495                    stack[-1].newblock(ElIf(location, parseexpr(location)))
2496                elif location.type == "else":
2497                    if not isinstance(stack[-1], IfElIfElse):
2498                        raise BlockError("else doesn't match any if")
2499                    elif isinstance(stack[-1].content[-1], Else):
2500                        raise BlockError("else already seen in if")
2501                    stack[-1].newblock(Else(location))
2502                elif location.type == "end":
2503                    if len(stack) <= 1:
2504                        raise BlockError("not in any block")
2505                    code = location.code
2506                    if code:
2507                        if code == "if":
2508                            if not isinstance(stack[-1], IfElIfElse):
2509                                raise BlockError("endif doesn't match any if")
2510                        elif code == "for":
2511                            if not isinstance(stack[-1], For):
2512                                raise BlockError("endfor doesn't match any for")
2513                        elif code == "def":
2514                            if not isinstance(stack[-1], Template):
2515                                raise BlockError("enddef doesn't match any def")
2516                        else:
2517                            raise BlockError("illegal end value {!r}".format(code))
2518                    last = stack.pop()
2519                    # Set ``endlocation`` of block
2520                    last.endlocation = location
2521                    if isinstance(last, IfElIfElse):
2522                        last.content[-1].endlocation = location
2523                elif location.type == "for":
2524                    block = parsefor(location)
2525                    stack[-1].append(block)
2526                    stack.append(block)
2527                elif location.type == "break":
2528                    for block in reversed(stack):
2529                        if isinstance(block, For):
2530                            break
2531                        elif isinstance(block, Template):
2532                            raise BlockError("break outside of for loop")
2533                    stack[-1].append(Break(location))
2534                elif location.type == "continue":
2535                    for block in reversed(stack):
2536                        if isinstance(block, For):
2537                            break
2538                        elif isinstance(block, Template):
2539                            raise BlockError("continue outside of for loop")
2540                    stack[-1].append(Continue(location))
2541                elif location.type == "def":
2542                    block = Template(None, location.code, self.keepws, self.startdelim, self.enddelim)
2543                    block.location = location # Set start ``location`` of sub template
2544                    block.source = self.source # The source of the top level template (so that the offsets in :class:`Location` are correct)
2545                    stack[-1].append(block)
2546                    stack.append(block)
2547                elif location.type == "return":
2548                    stack[-1].append(Return(location, parseexpr(location)))
2549                else: # Can't happen
2550                    raise ValueError("unknown tag {!r}".format(location.type))
2551            except Exception as exc:
2552                raise Error(location) from exc
2553        if len(stack) > 1:
2554            raise Error(stack[-1].location) from BlockError("block unclosed")
2555
2556    @handleeval
2557    def eval(self, vars):
2558        yield from ()
2559        vars[self.name] = TemplateClosure(self, vars)
2560
2561
2562###
2563### Functions & methods
2564###
2565
2566@AST.makefunction
2567def _print(*values):
2568    for (i, value) in enumerate(values):
2569        if i:
2570            yield " "
2571        yield _str(value)
2572
2573
2574@AST.makefunction
2575def _printx(*values):
2576    for (i, value) in enumerate(values):
2577        if i:
2578            yield " "
2579        yield _xmlescape(value)
2580
2581
2582@AST.makefunction
2583def _str(obj=""):
2584    if obj is None:
2585        return ""
2586    elif isinstance(obj, Undefined):
2587        return ""
2588    else:
2589        return str(obj)
2590
2591
2592@AST.makefunction
2593def _repr(obj):
2594    if isinstance(obj, str):
2595        return repr(obj)
2596    elif isinstance(obj, datetime.datetime):
2597        s = str(obj.isoformat())
2598        if s.endswith("T00:00:00"):
2599            s = s[:-9]
2600        return "@({})".format(s)
2601    elif isinstance(obj, datetime.date):
2602        return "@({})".format(obj.isoformat())
2603    elif isinstance(obj, datetime.timedelta):
2604        return repr(obj).partition(".")[-1]
2605    elif isinstance(obj, color.Color):
2606        if obj[3] == 0xff:
2607            s = "#{:02x}{:02x}{:02x}".format(obj[0], obj[1], obj[2])
2608            if s[1]==s[2] and s[3]==s[4] and s[5]==s[6]:
2609                return "#{}{}{}".format(s[1], s[3], s[5])
2610            return s
2611        else:
2612            s = "#{:02x}{:02x}{:02x}{:02x}".format(*obj)
2613            if s[1]==s[2] and s[3]==s[4] and s[5]==s[6] and s[7]==s[8]:
2614                return "#{}{}{}{}".format(s[1], s[3], s[5], s[7])
2615            return s
2616    elif isinstance(obj, collections.Sequence):
2617        return "[{}]".format(", ".join(_repr(item) for item in obj))
2618    elif isinstance(obj, collections.Mapping):
2619        return "{{{}}}".format(", ".join("{}: {}".format(_repr(key), _repr(value)) for (key, value) in obj.items()))
2620    else:
2621        return repr(obj)
2622
2623
2624@AST.makefunction
2625def _now():
2626    return datetime.datetime.now()
2627
2628
2629@AST.makefunction
2630def _utcnow():
2631    return datetime.datetime.utcnow()
2632
2633
2634@AST.makefunction
2635def _date(year, month, day, hour=0, minute=0, second=0, microsecond=0):
2636    return datetime.datetime(year, month, day, hour, minute, second, microsecond)
2637
2638
2639@AST.makefunction
2640def _timedelta(days=0, seconds=0, microseconds=0):
2641    return datetime.timedelta(days, seconds, microseconds)
2642
2643
2644@AST.makefunction
2645def _monthdelta(months=0):
2646    return misc.monthdelta(months)
2647
2648
2649@AST.makefunction
2650def _random():
2651    return random.random()
2652
2653
2654@AST.makefunction
2655def _xmlescape(obj):
2656    if obj is None:
2657        return ""
2658    elif isinstance(obj, Undefined):
2659        return ""
2660    else:
2661        return misc.xmlescape(str(obj))
2662
2663
2664@AST.makefunction
2665def _csv(obj):
2666    if obj is None:
2667        return ""
2668    elif isinstance(obj, Undefined):
2669        return ""
2670    elif not isinstance(obj, str):
2671        obj = _repr(obj)
2672    if any(c in obj for c in ',"\n'):
2673        return '"{}"'.format(obj.replace('"', '""'))
2674    return obj
2675
2676
2677@AST.makefunction
2678def _asjson(obj):
2679    if obj is None:
2680        return "null"
2681    elif isinstance(obj, Undefined):
2682        return "{}.undefined"
2683    if isinstance(obj, (bool, int, float, str)):
2684        return json.dumps(obj)
2685    elif isinstance(obj, datetime.datetime):
2686        return "new Date({}, {}, {}, {}, {}, {}, {})".format(obj.year, obj.month-1, obj.day, obj.hour, obj.minute, obj.second, obj.microsecond//1000)
2687    elif isinstance(obj, datetime.date):
2688        return "new Date({}, {}, {})".format(obj.year, obj.month-1, obj.day)
2689    elif isinstance(obj, datetime.timedelta):
2690        return "ul4.TimeDelta.create({}, {}, {})".format(obj.days, obj.seconds, obj.microseconds)
2691    elif isinstance(obj, misc.monthdelta):
2692        return "ul4.MonthDelta.create({})".format(obj.months)
2693    elif isinstance(obj, color.Color):
2694        return "ul4.Color.create({}, {}, {}, {})".format(*obj)
2695    elif isinstance(obj, collections.Mapping):
2696        return "{{{}}}".format(", ".join("{}: {}".format(_asjson(key), _asjson(value)) for (key, value) in obj.items()))
2697    elif isinstance(obj, collections.Sequence):
2698        return "[{}]".format(", ".join(_asjson(item) for item in obj))
2699    elif isinstance(obj, Template):
2700        return obj.jssource()
2701    else:
2702        raise TypeError("can't handle object of type {}".format(type(obj)))
2703
2704
2705@AST.makefunction
2706def _fromjson(string):
2707    from ll import ul4on
2708    return json.loads(string)
2709
2710
2711@AST.makefunction
2712def _asul4on(obj):
2713    from ll import ul4on
2714    return ul4on.dumps(obj)
2715
2716
2717@AST.makefunction
2718def _fromul4on(string):
2719    from ll import ul4on
2720    return ul4on.loads(string)
2721
2722
2723@AST.makefunction
2724def _int(obj=0, base=None):
2725    if base is None:
2726        return int(obj)
2727    else:
2728        return int(obj, base)
2729
2730
2731@AST.makefunction
2732def _float(obj=0.0):
2733    return float(obj)
2734
2735
2736@AST.makefunction
2737def _bool(obj=False):
2738    return bool(obj)
2739
2740
2741@AST.makefunction
2742def _len(sequence):
2743    return len(sequence)
2744
2745
2746@AST.makefunction
2747def _abs(number):
2748    return abs(number)
2749
2750
2751@AST.makefunction
2752def _any(iterable):
2753    return any(iterable)
2754
2755
2756@AST.makefunction
2757def _all(iterable):
2758    return all(iterable)
2759
2760
2761@AST.makefunction
2762def _enumerate(iterable, start=0):
2763    yield from ()
2764    return enumerate(iterable, start)
2765
2766
2767@AST.makefunction
2768def _enumfl(iterable, start=0):
2769    yield from ()
2770    def result(iterable):
2771        lastitem = None
2772        first = True
2773        i = start
2774        it = iter(iterable)
2775        try:
2776            item = next(it)
2777        except StopIteration:
2778            return
2779        while True:
2780            try:
2781                (lastitem, item) = (item, next(it))
2782            except StopIteration:
2783                yield (i, first, True, item) # Items haven't been swapped yet
2784                return
2785            else:
2786                yield (i, first, False, lastitem)
2787                first = False
2788            i += 1
2789    return result(iterable)
2790
2791
2792@AST.makefunction
2793def _isfirstlast(iterable):
2794    yield from ()
2795    def result(iterable):
2796        lastitem = None
2797        first = True
2798        it = iter(iterable)
2799        try:
2800            item = next(it)
2801        except StopIteration:
2802            return
2803        while True:
2804            try:
2805                (lastitem, item) = (item, next(it))
2806            except StopIteration:
2807                yield (first, True, item) # Items haven't been swapped yet
2808                return
2809            else:
2810                yield (first, False, lastitem)
2811                first = False
2812    return result(iterable)
2813
2814
2815@AST.makefunction
2816def _isfirst(iterable):
2817    yield from ()
2818    def result(iterable):
2819        first = True
2820        for item in iterable:
2821            yield (first, item)
2822            first = False
2823    return result(iterable)
2824
2825
2826@AST.makefunction
2827def _islast(iterable):
2828    yield from ()
2829    def result(iterable):
2830        lastitem = None
2831        it = iter(iterable)
2832        try:
2833            item = next(it)
2834        except StopIteration:
2835            return
2836        while True:
2837            try:
2838                (lastitem, item) = (item, next(it))
2839            except StopIteration:
2840                yield (True, item) # Items haven't been swapped yet
2841                return
2842            else:
2843                yield (False, lastitem)
2844    return result(iterable)
2845
2846
2847@AST.makefunction
2848def _isundefined(obj):
2849    return isinstance(obj, Undefined)
2850
2851
2852@AST.makefunction
2853def _isdefined(obj):
2854    return not isinstance(obj, Undefined)
2855
2856
2857@AST.makefunction
2858def _isnone(obj):
2859    return obj is None
2860
2861
2862@AST.makefunction
2863def _isstr(obj):
2864    return isinstance(obj, str)
2865
2866
2867@AST.makefunction
2868def _isint(obj):
2869    return isinstance(obj, int) and not isinstance(obj, bool)
2870
2871
2872@AST.makefunction
2873def _isfloat(obj):
2874    return isinstance(obj, float)
2875
2876
2877@AST.makefunction
2878def _isbool(obj):
2879    return isinstance(obj, bool)
2880
2881
2882@AST.makefunction
2883def _isdate(obj):
2884    return isinstance(obj, (datetime.datetime, datetime.date))
2885
2886
2887@AST.makefunction
2888def _istimedelta(obj):
2889    return isinstance(obj, datetime.timedelta)
2890
2891
2892@AST.makefunction
2893def _ismonthdelta(obj):
2894    return isinstance(obj, misc.monthdelta)
2895
2896
2897@AST.makefunction
2898def _islist(obj):
2899    return isinstance(obj, collections.Sequence) and not isinstance(obj, str) and not isinstance(obj, color.Color)
2900
2901
2902@AST.makefunction
2903def _isdict(obj):
2904    return isinstance(obj, collections.Mapping) and not isinstance(obj, Template)
2905
2906
2907@AST.makefunction
2908def _iscolor(obj):
2909    return isinstance(obj, color.Color)
2910
2911
2912@AST.makefunction
2913def _istemplate(obj):
2914    return isinstance(obj, (Template, TemplateClosure))
2915
2916
2917@AST.makefunction
2918def _isfunction(obj):
2919    return callable(obj)
2920
2921
2922@AST.makefunction
2923def _chr(i):
2924    return chr(i)
2925
2926
2927@AST.makefunction
2928def _ord(c):
2929    return ord(c)
2930
2931
2932@AST.makefunction
2933def _hex(number):
2934    return hex(number)
2935
2936
2937@AST.makefunction
2938def _oct(number):
2939    return oct(number)
2940
2941
2942@AST.makefunction
2943def _bin(number):
2944    return bin(number)
2945
2946
2947@AST.makefunction
2948def _min(*args):
2949    return min(*args)
2950
2951
2952@AST.makefunction
2953def _max(*args):
2954    return max(*args)
2955
2956
2957@AST.makefunction
2958def _sorted(iterable):
2959    return sorted(iterable)
2960
2961
2962@AST.makefunction
2963def _range(*args):
2964    return range(*args)
2965
2966
2967@AST.makefunction
2968def _type(obj):
2969    if obj is None:
2970        return "none"
2971    elif isinstance(obj, Undefined):
2972        return "undefined"
2973    elif isinstance(obj, str):
2974        return "str"
2975    elif isinstance(obj, bool):
2976        return "bool"
2977    elif isinstance(obj, int):
2978        return "int"
2979    elif isinstance(obj, float):
2980        return "float"
2981    elif isinstance(obj, (datetime.datetime, datetime.date)):
2982        return "date"
2983    elif isinstance(obj, datetime.timedelta):
2984        return "timedelta"
2985    elif isinstance(obj, misc.monthdelta):
2986        return "monthdelta"
2987    elif isinstance(obj, color.Color):
2988        return "color"
2989    elif isinstance(obj, (Template, TemplateClosure)):
2990        return "template"
2991    elif isinstance(obj, collections.Mapping):
2992        return "dict"
2993    elif isinstance(obj, color.Color):
2994        return "color"
2995    elif isinstance(obj, collections.Sequence):
2996        return "list"
2997    elif callable(obj):
2998        return "function"
2999    return None
3000
3001
3002@AST.makefunction
3003def _reversed(sequence):
3004    yield from ()
3005    return reversed(sequence)
3006
3007
3008@AST.makefunction
3009def _randrange(*args):
3010    return random.randrange(*args)
3011
3012
3013@AST.makefunction
3014def _randchoice(sequence):
3015    return random.choice(sequence)
3016
3017
3018@AST.makefunction
3019def _format(obj, fmt, lang=None):
3020    if isinstance(obj, (datetime.date, datetime.time, datetime.timedelta)):
3021        if lang is None:
3022            lang = "en"
3023        oldlocale = locale.getlocale()
3024        try:
3025            for candidate in (locale.normalize(lang), locale.normalize("en"), ""):
3026                try:
3027                    locale.setlocale(locale.LC_ALL, candidate)
3028                    return format(obj, fmt)
3029                except locale.Error:
3030                    if not candidate:
3031                        return format(obj, fmt)
3032        finally:
3033            try:
3034                locale.setlocale(locale.LC_ALL, oldlocale)
3035            except locale.Error:
3036                pass
3037    else:
3038        return format(obj, fmt)
3039
3040
3041@AST.makefunction
3042def _zip(*iterables):
3043    return zip(*iterables)
3044
3045
3046@AST.makefunction
3047def _urlquote(string):
3048    return urlparse.quote_plus(string)
3049
3050
3051@AST.makefunction
3052def _urlunquote(string):
3053    return urlparse.unquote_plus(string)
3054
3055
3056@AST.makefunction
3057def _rgb(r, g, b, a=1.0):
3058    return color.Color.fromrgb(r, g, b, a)
3059
3060
3061@AST.makefunction
3062def _hls(h, l, s, a=1.0):
3063    return color.Color.fromhls(h, l, s, a)
3064
3065
3066@AST.makefunction
3067def _hsv(h, s, v, a=1.0):
3068    return color.Color.fromhsv(h, s, v, a)
3069
3070
3071@AST.makemethod
3072def _split(obj, sep=None, count=None):
3073    return obj.split(sep, count if count is not None else -1)
3074
3075
3076@AST.makemethod
3077def _rsplit(obj, sep=None, count=None):
3078    return obj.rsplit(sep, count if count is not None else -1)
3079
3080
3081@AST.makemethod
3082def _strip(obj, chars=None):
3083    return obj.strip(chars)
3084
3085
3086@AST.makemethod
3087def _lstrip(obj, chars=None):
3088    return obj.lstrip(chars)
3089
3090
3091@AST.makemethod
3092def _rstrip(obj, chars=None):
3093    return obj.rstrip(chars)
3094
3095
3096@AST.makemethod
3097def _find(obj, sub, start=None, end=None):
3098    if isinstance(obj, str):
3099        return obj.find(sub, start, end)
3100    else:
3101        try:
3102            if end is None:
3103                if start is None:
3104                    return obj.index(sub)
3105                return obj.index(sub, start)
3106            return obj.index(sub, start, end)
3107        except ValueError:
3108            return -1
3109
3110
3111@AST.makemethod
3112def _rfind(obj, sub, start=None, end=None):
3113    if isinstance(obj, str):
3114        return obj.rfind(sub, start, end)
3115    else:
3116        for i in reversed(range(*slice(start, end).indices(len(obj)))):
3117            if obj[i] == sub:
3118                return i
3119        return -1
3120
3121
3122@AST.makemethod
3123def _startswith(obj, prefix):
3124    return obj.startswith(prefix)
3125
3126
3127@AST.makemethod
3128def _endswith(obj, suffix):
3129    return obj.endswith(suffix)
3130
3131
3132@AST.makemethod
3133def _upper(obj):
3134    return obj.upper()
3135
3136
3137@AST.makemethod
3138def _lower(obj):
3139    return obj.lower()
3140
3141
3142@AST.makemethod
3143def _capitalize(obj):
3144    return obj.capitalize()
3145
3146
3147@AST.makemethod
3148def _replace(obj, old, new, count=None):
3149    if count is None:
3150        return obj.replace(old, new)
3151    else:
3152        return obj.replace(old, new, count)
3153
3154
3155@AST.makemethod
3156def _r(obj):
3157    return obj.r()
3158
3159
3160@AST.makemethod
3161def _g(obj):
3162    return obj.g()
3163
3164
3165@AST.makemethod
3166def _b(obj):
3167    return obj.b()
3168
3169
3170@AST.makemethod
3171def _a(obj):
3172    return obj.a()
3173
3174
3175@AST.makemethod
3176def _hls(obj):
3177    return obj.hls()
3178
3179
3180@AST.makemethod
3181def _hlsa(obj):
3182    return obj.hlsa()
3183
3184
3185@AST.makemethod
3186def _hsv(obj):
3187    return obj.hsv()
3188
3189
3190@AST.makemethod
3191def _hsva(obj):
3192    return obj.hsva()
3193
3194
3195@AST.makemethod
3196def _lum(obj):
3197    return obj.lum()
3198
3199
3200@AST.makemethod
3201def _weekday(obj):
3202    return obj.weekday()
3203
3204
3205@AST.makemethod
3206def _week(obj, firstweekday=None):
3207    if firstweekday is None:
3208        firstweekday = 0
3209    else:
3210        firstweekday %= 7
3211    jan1 = obj.__class__(obj.year, 1, 1)
3212    yearday = (obj - jan1).days+7
3213    jan1weekday = jan1.weekday()
3214    while jan1weekday != firstweekday:
3215        yearday -= 1
3216        jan1weekday += 1
3217        if jan1weekday == 7:
3218            jan1weekday = 0
3219    return yearday//7
3220
3221
3222@AST.makemethod
3223def _items(obj):
3224    yield from ()
3225    return obj.items()
3226
3227
3228@AST.makemethod
3229def _values(obj):
3230    yield from ()
3231    return obj.values()
3232
3233
3234@AST.makemethod
3235def _join(obj, iterable):
3236    return obj.join(iterable)
3237
3238
3239@AST.makemethod
3240def _render(obj, **vars):
3241    yield from obj.render(**vars)
3242
3243
3244@AST.makemethod
3245def _renders(obj, **vars):
3246    return obj.renders(**vars)
3247
3248
3249@AST.makemethod
3250def _mimeformat(obj):
3251    weekdayname = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
3252    monthname = (None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
3253    return "{1}, {0.day:02d} {2:3} {0.year:4} {0.hour:02}:{0.minute:02}:{0.second:02} GMT".format(obj, weekdayname[obj.weekday()], monthname[obj.month])
3254
3255
3256@AST.makemethod
3257def _isoformat(obj):
3258    result = obj.isoformat()
3259    suffix = "T00:00:00"
3260    if result.endswith(suffix):
3261        return result[:-len(suffix)]
3262    return result
3263
3264
3265@AST.makemethod
3266def _yearday(obj):
3267    return (obj - obj.__class__(obj.year, 1, 1)).days+1
3268
3269
3270@AST.makemethod
3271def _get(obj, key, default=None):
3272    return obj.get(key, default)
3273
3274
3275@AST.makemethod
3276def _withlum(obj, lum):
3277    return obj.withlum(lum)
3278
3279
3280@AST.makemethod
3281def _witha(obj, a):
3282    return obj.witha(a)
3283
3284
3285@AST.makemethod
3286def _day(obj):
3287    return obj.day
3288
3289
3290@AST.makemethod
3291def _month(obj):
3292    return obj.month
3293
3294
3295@AST.makemethod
3296def _year(obj):
3297    return obj.year
3298
3299
3300@AST.makemethod
3301def _hour(obj):
3302    return obj.hour
3303
3304
3305@AST.makemethod
3306def _minute(obj):
3307    return obj.minute
3308
3309
3310@AST.makemethod
3311def _second(obj):
3312    return obj.second
3313
3314
3315@AST.makemethod
3316def _microsecond(obj):
3317    return obj.microsecond
3318
3319
3320@AST.makemethod
3321def _days(obj):
3322    return obj.days
3323
3324
3325@AST.makemethod
3326def _seconds(obj):
3327    return obj.seconds
3328
3329
3330@AST.makemethod
3331def _microseconds(obj):
3332    return obj.microseconds
3333
3334
3335@AST.makemethod
3336def _months(obj):
3337    return obj.months
3338
3339
3340@AST.makemethod
3341def _append(obj, *items):
3342    obj.extend(items)
3343
3344
3345@AST.makemethod
3346def _insert(obj, pos, *items):
3347    obj[pos:pos] = items
3348
3349
3350@AST.makemethod
3351def _pop(obj, pos=-1):
3352    return obj.pop(pos)
3353
3354
3355@AST.makemethod
3356def _update(obj, *others, **kwargs):
3357    for other in others:
3358        obj.update(other)
3359    obj.update(**kwargs)
3360
3361
3362class TemplateClosure(Object):
3363    fields = {"location", "endlocation", "name", "source", "startdelim", "enddelim", "content"}
3364
3365    def __init__(self, template, vars):
3366        self.template = template
3367        # Freeze variables of the currently running templates/functions
3368        self.vars = vars.copy()
3369
3370    def render(self, **vars):
3371        return self.template.render(**collections.ChainMap(vars, self.vars))
3372
3373    def renders(self, **vars):
3374        return self.template.renders(**collections.ChainMap(vars, self.vars))
3375
3376    def __call__(self, **vars):
3377        return self.template(**collections.ChainMap(vars, self.vars))
3378
3379    def __getattr__(self, name):
3380        return getattr(self.template, name)
3381
3382    def __repr__(self):
3383        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} name={0.name!r} keepws={0.keepws!r}".format(self)
3384        if self.startdelim != "<?":
3385            s += " startdelim={0.startdelim!r}".format(self)
3386        if self.enddelim != "?>":
3387            s += " enddelim={0.enddelim!r}".format(self)
3388        if self.content:
3389            s + " ..."
3390        return s + " at {:#x}>".format(id(self))
3391
3392    def _repr_pretty_(self, p, cycle):
3393        if cycle:
3394            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
3395        else:
3396            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
3397                p.breakable()
3398                p.text("name=")
3399                p.pretty(self.name)
3400                p.breakable()
3401                p.text("keepws=")
3402                p.pretty(self.keepws)
3403                if self.startdelim != "<?":
3404                    p.breakable()
3405                    p.text("startdelim=")
3406                    p.pretty(self.startdelim)
3407                if self.enddelim != "?>":
3408                    p.breakable()
3409                    p.text("enddelim=")
3410                    p.pretty(self.enddelim)
3411                for node in self.content:
3412                    p.breakable()
3413                    p.pretty(node)
3414                p.breakable()
3415                p.text("at {:#x}".format(id(self)))
3416
3417
3418###
3419### Helper classes/functions used at runtime
3420###
3421
3422def _unpackvar(vars, name, value):
3423    if isinstance(name, str):
3424        vars[name] = value
3425    else:
3426        if len(name) > len(value):
3427            raise TypeError("too many values to unpack (expected {})".format(len(name)))
3428        elif len(name) < len(value):
3429            raise TypeError("need more than {} value{} to unpack)".format(len(values), "ss" if len(values) != 1 else ""))
3430        for (name, value) in zip(name, value):
3431            _unpackvar(vars, name, value)
Note: See TracBrowser for help on using the browser.