root/livinglogic.python.xist/src/ll/ul4c.py @ 5337:53e07b993ab2

Revision 5337:53e07b993ab2, 80.6 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Remove keepws argument from _str(). Fix _str() formatting.

Now that an expresion might be the top level AST in a tag, indentation is output
by the block AST, not by the top level AST nodes themselves.

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
259class AST(Object):
260    """
261    Base class for all syntax tree nodes.
262    """
263    # used in :meth:`format` to decide if we need brackets around an operator
264    precedence = None
265    associative = True
266
267    # Set of attributes available via :meth:`getitem`.
268    fields = {"type", "location"}
269
270    # "Global" functions and methods. Functions in ``functions`` will be exposed to UL4 code
271    functions = {}
272    methods = {}
273
274    def __init__(self, location=None):
275        self.location = location
276
277    def __getitem__(self, key):
278        if key in self.fields:
279            return getattr(self, key)
280        raise KeyError(key)
281
282    def __repr__(self):
283        return "<{0.__class__.__module__}.{0.__class__.__qualname__} at {1:#x}>".format(self, id(self))
284
285    def _repr_pretty_(self, p, cycle):
286        p.text(repr(self))
287
288    def __str__(self):
289        return "".join(self._str(0))
290
291    def _formatop(self, op):
292        bracket = False
293        if op.precedence < self.precedence:
294            bracket = True
295        elif op.precedence == self.precedence and (not isinstance(op, self.__class__) or not self.associative):
296            bracket = True
297        if bracket:
298            yield "("
299        yield from op._str(0)
300        if bracket:
301            yield ")"
302
303    @misc.notimplemented
304    def _str(self, indent):
305        """
306        Format :var:`self` (with the indentation level :var:`indent`).
307
308        This is used by :meth:`__str__.
309        """
310
311    @misc.notimplemented
312    def eval(self, vars):
313        """
314        This evaluates the node.
315
316        This is a generator, which yields the text output of the node. If the
317        node returns a value (as most nodes do), this is done as the value of a
318        :exc:`StopIteration` exception.
319        """
320
321    def ul4ondump(self, encoder):
322        encoder.dump(self.location)
323
324    def ul4onload(self, decoder):
325        self.location = decoder.load()
326
327    @classmethod
328    def makefunction(cls, f):
329        name = f.__name__
330        if name.startswith("_"):
331            name = name[1:]
332        cls.functions[name] = f
333        return f
334
335    @classmethod
336    def makemethod(cls, f):
337        name = f.__name__
338        if name.startswith("_"):
339            name = name[1:]
340        cls.methods[name] = f
341        return f
342
343
344@register("text")
345class Text(AST):
346    """
347    AST node for literal text.
348    """
349
350    def text(self):
351        # If ``keepws`` is true, we output the literal text from the location info.
352        # Otherwise we have to strip linefeeds and indentation
353        text = self.location.code
354        if not self.location.root.keepws:
355            text = "".join(line.lstrip() for line in text.splitlines())
356        return text
357
358    def __repr__(self):
359        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.location.code!r} at {1:#x}>".format(self, id(self))
360
361    def _str(self, indent):
362        yield "text {!r}\n".format(self.text())
363
364    def eval(self, vars):
365        yield self.text()
366
367
368@register("const")
369class Const(AST):
370    """
371    Load a constant
372    """
373    precedence = 11
374    fields = AST.fields.union({"value"})
375
376    def __init__(self, location=None, value=None):
377        super().__init__(location)
378        self.value = value
379
380    def _str(self, indent):
381        yield _repr(self.value)
382
383    def eval(self, vars):
384        yield from ()
385        return self.value
386
387    def ul4ondump(self, encoder):
388        super().ul4ondump(encoder)
389        encoder.dump(self.value)
390
391    def ul4onload(self, decoder):
392        super().ul4onload(decoder)
393        self.value = decoder.load()
394
395    def __repr__(self):
396        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.value!r} at {1:#x}>".format(self, id(self))
397
398
399@register("list")
400class List(AST):
401    """
402    AST nodes for loading a list object.
403    """
404
405    precedence = 11
406    fields = AST.fields.union({"items"})
407
408    def __init__(self, location=None, *items):
409        super().__init__(location)
410        self.items = list(items)
411
412    def __repr__(self):
413        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.items!r} at {1:#x}>".format(self, id(self))
414
415    def _repr_pretty_(self, p, cycle):
416        if cycle:
417            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
418        else:
419            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
420                for (i, item) in enumerate(self.items):
421                    if i:
422                        p.breakable()
423                    else:
424                        p.breakable("")
425                    p.pretty(item)
426                p.breakable()
427                p.text("at {:#x}".format(id(self)))
428
429    def _str(self, indent):
430        yield "["
431        for (i, item) in enumerate(self.items):
432            if i:
433                yield ", "
434            yield from item._str(indent)
435        yield "]"
436
437    @handleeval
438    def eval(self, vars):
439        result = []
440        for item in self.items:
441            item = (yield from item.eval(vars))
442            result.append(item)
443        return result
444
445    def ul4ondump(self, encoder):
446        super().ul4ondump(encoder)
447        encoder.dump(self.items)
448
449    def ul4onload(self, decoder):
450        super().ul4onload(decoder)
451        self.items = decoder.load()
452
453
454@register("listcomp")
455class ListComp(AST):
456    """
457    AST node for list comprehension.
458    """
459
460    precedence = 11
461    fields = AST.fields.union({"item", "varname", "container", "condition"})
462
463
464    def __init__(self, location=None, item=None, varname=None, container=None, condition=None):
465        super().__init__(location)
466        self.item = item
467        self.varname = varname
468        self.container = container
469        self.condition = condition
470
471    def __repr__(self):
472        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} item={0.item!r} varname={0.varname!r} container={0.container!r}".format(self)
473        if self.condition is not None:
474            s += " condition={0.condition!r}".format(self)
475        return s + " at {:#x}>".format(id(self))
476
477    def _repr_pretty_(self, p, cycle):
478        if cycle:
479            p.text("{0.__class__.__module__}.{0.__class__.__qualname__}(...)".format(self))
480        else:
481            with p.group(4, "{0.__class__.__module__}.{0.__class__.__qualname__}(".format(self), ")"):
482                p.breakable("")
483                p.text("item=")
484                p.pretty(self.item)
485                p.text(",")
486                p.breakable()
487                p.text("varname=")
488                p.pretty(self.varname)
489                p.text(",")
490                p.breakable()
491                p.text("container=")
492                p.pretty(self.container)
493                if self.condition is not None:
494                    p.text(",")
495                    p.breakable()
496                    p.text("condition=")
497                    p.pretty(self.condition)
498                p.breakable()
499                p.text("at {:#x}".format(id(self)))
500
501    def _str(self, indent):
502        yield "["
503        yield from self.item._str(indent)
504        yield " for "
505        yield _formatnestednameul4(self.varname)
506        yield " in "
507        yield from self.container._str(indent)
508        if self.condition is not None:
509            yield " if "
510            yield from self.condition._str(indent)
511        yield "]"
512
513    @handleeval
514    def eval(self, vars):
515        container = (yield from self.container.eval(vars))
516        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
517        result = []
518        for item in container:
519            _unpackvar(vars, self.varname, item)
520            if self.condition is None or (yield from self.condition.eval(vars)):
521                item = (yield from self.item.eval(vars))
522                result.append(item)
523        return result
524
525    def ul4ondump(self, encoder):
526        super().ul4ondump(encoder)
527        encoder.dump(self.item)
528        encoder.dump(self.varname)
529        encoder.dump(self.container)
530        encoder.dump(self.condition)
531
532    def ul4onload(self, decoder):
533        super().ul4onload(decoder)
534        self.item = decoder.load()
535        self.varname = decoder.load()
536        self.container = decoder.load()
537        self.condition = decoder.load()
538
539
540@register("dict")
541class Dict(AST):
542    """
543    AST node for loading a dict object.
544    """
545
546    precedence = 11
547    fields = AST.fields.union({"items"})
548
549    def __init__(self, location=None, *items):
550        super().__init__(location)
551        self.items = list(items)
552
553    def __repr__(self):
554        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.items!r} at {1:#x}>".format(self, id(self))
555
556    def _repr_pretty_(self, p, cycle):
557        if cycle:
558            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
559        else:
560            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
561                for item in self.items:
562                    p.breakable()
563                    p.pretty(item[0])
564                    p.text("=")
565                    p.pretty(item[1])
566                p.breakable()
567                p.text("at {:#x}".format(id(self)))
568
569    def _str(self, indent):
570        yield "{"
571        for (i, item) in enumerate(self.items):
572            if i:
573                yield ", "
574            yield from item[0]._str(indent)
575            yield ": "
576            yield from item[1]._str(indent)
577        yield "}"
578
579    @handleeval
580    def eval(self, vars):
581        result = {}
582        for item in self.items:
583            key = (yield from item[0].eval(vars))
584            value = (yield from item[1].eval(vars))
585            result[key] = value
586        return result
587
588    def ul4ondump(self, encoder):
589        super().ul4ondump(encoder)
590        encoder.dump(self.items)
591
592    def ul4onload(self, decoder):
593        super().ul4onload(decoder)
594        self.items = [tuple(item) for item in decoder.load()]
595
596
597@register("dictcomp")
598class DictComp(AST):
599    """
600    AST node for dictionary comprehension.
601    """
602
603    precedence = 11
604    fields = AST.fields.union({"key", "value", "varname", "container", "condition"})
605
606    def __init__(self, location=None, key=None, value=None, varname=None, container=None, condition=None):
607        super().__init__(location)
608        self.key = key
609        self.value = value
610        self.varname = varname
611        self.container = container
612        self.condition = condition
613
614    def __repr__(self):
615        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)
616        if self.condition is not None:
617            s += " {0.condition!r}".format(self)
618        return s + " at {:#x}>".format(id(self))
619
620    def _repr_pretty_(self, p, cycle):
621        if cycle:
622            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
623        else:
624            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
625                p.breakable()
626                p.text("key=")
627                p.pretty(self.key)
628                p.breakable()
629                p.text("value=")
630                p.pretty(self.value)
631                p.breakable()
632                p.text("varname=")
633                p.pretty(self.varname)
634                p.breakable()
635                p.text("container=")
636                p.pretty(self.container)
637                if self.condition is not None:
638                    p.breakable()
639                    p.text("condition=")
640                    p.pretty(self.condition)
641                p.breakable()
642                p.text("at {:#x}".format(id(self)))
643
644    def _str(self, indent):
645        yield "{"
646        yield from self.key._str(indent)
647        yield " : "
648        yield from self.value._str(indent)
649        yield " for "
650        yield _formatnestednameul4(self.varname)
651        yield " in "
652        yield from self.container._str(indent)
653        if self.condition is not None:
654            yield " if "
655            yield from self.condition._str(indent)
656        yield "]"
657
658    @handleeval
659    def eval(self, vars):
660        container = (yield from self.container.eval(vars))
661        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
662        result = {}
663        for item in container:
664            _unpackvar(vars, self.varname, item)
665            if self.condition is None or (yield from self.condition.eval(vars)):
666                key = (yield from self.key.eval(vars))
667                value = (yield from self.value.eval(vars))
668                result[key] = value
669        return result
670
671    def ul4ondump(self, encoder):
672        super().ul4ondump(encoder)
673        encoder.dump(self.key)
674        encoder.dump(self.value)
675        encoder.dump(self.varname)
676        encoder.dump(self.container)
677        encoder.dump(self.condition)
678
679    def ul4onload(self, decoder):
680        super().ul4onload(decoder)
681        self.key = decoder.load()
682        self.value = decoder.load()
683        self.varname = decoder.load()
684        self.container = decoder.load()
685        self.condition = decoder.load()
686
687
688@register("genexpr")
689class GenExpr(AST):
690    """
691    AST node for a generator expression.
692    """
693
694    precedence = 11
695    fields = AST.fields.union({"item", "varname", "container", "condition"})
696
697    def __init__(self, location=None, item=None, varname=None, container=None, condition=None):
698        super().__init__(location)
699        self.item = item
700        self.varname = varname
701        self.container = container
702        self.condition = condition
703
704    def __repr__(self):
705        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} item={0.item!r} varname={0.varname!r} container={0.container!r}".format(self)
706        if self.condition is not None:
707            s += " condition={0.condition!r}".format(self)
708        return s + " at {:#x}>".format(id(self))
709
710    def _repr_pretty_(self, p, cycle):
711        if cycle:
712            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
713        else:
714            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
715                p.breakable()
716                p.text("item=")
717                p.pretty(self.item)
718                p.breakable()
719                p.text("varname=")
720                p.pretty(self.varname)
721                p.breakable()
722                p.text("container=")
723                p.pretty(self.container)
724                if self.condition is not None:
725                    p.breakable()
726                    p.text("condition=")
727                    p.pretty(self.condition)
728                p.breakable()
729                p.text("at {:#x}".format(id(self)))
730
731    def _str(self, indent):
732        yield "("
733        yield from self.item._str(indent)
734        yield " for "
735        yield _formatnestednameul4(self.varname)
736        yield " in "
737        yield from self.container._str(indent)
738        if self.condition is not None:
739            yield " if "
740            yield from self.condition._str(indent)
741        yield ")"
742
743    @handleeval
744    def eval(self, vars):
745        container = (yield from self.container.eval(vars))
746        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
747        def result():
748            for item in container:
749                _unpackvar(vars, self.varname, item)
750                if self.condition is None or (yield from self.condition.eval(vars)):
751                    item = (yield from self.item.eval(vars))
752                    yield item
753        return result()
754
755    def ul4ondump(self, encoder):
756        super().ul4ondump(encoder)
757        encoder.dump(self.item)
758        encoder.dump(self.varname)
759        encoder.dump(self.container)
760        encoder.dump(self.condition)
761
762    def ul4onload(self, decoder):
763        super().ul4onload(decoder)
764        self.item = decoder.load()
765        self.varname = decoder.load()
766        self.container = decoder.load()
767        self.condition = decoder.load()
768
769
770@register("var")
771class Var(AST):
772    """
773    AST nodes for loading a variable.
774    """
775
776    precedence = 11
777    fields = AST.fields.union({"name"})
778
779    def __init__(self, location=None, name=None):
780        super().__init__(location)
781        self.name = name
782
783    def __repr__(self):
784        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.name!r} at {1:#x}>".format(self, id(self))
785
786    def _str(self, indent):
787        yield self.name
788
789    @handleeval
790    def eval(self, vars):
791        yield from ()
792        try:
793            return vars[self.name]
794        except KeyError:
795            try:
796                return self.functions[self.name]
797            except KeyError:
798                return UndefinedVariable(self.name)
799
800    def ul4ondump(self, encoder):
801        super().ul4ondump(encoder)
802        encoder.dump(self.name)
803
804    def ul4onload(self, decoder):
805        super().ul4onload(decoder)
806        self.name = decoder.load()
807
808
809class Block(AST):
810    """
811    Base class for all AST nodes that are blocks.
812
813    A block contains a sequence of AST nodes that are executed sequencially.
814    A block may execute its content zero (e.g. an ``<?if?>`` block) or more times
815    (e.g. a ``<?for?>`` block).
816    """
817
818    fields = AST.fields.union({"endlocation", "content"})
819
820    def __init__(self, location=None):
821        super().__init__(location)
822        self.endlocation = None
823        self.content = []
824
825    def append(self, item):
826        self.content.append(item)
827
828    def _str(self, indent):
829        if self.content:
830            for node in self.content:
831                yield indent*"\t"
832                yield from node._str(indent)
833        else:
834            yield indent*"\t"
835            yield "pass\n"
836
837    @handleeval
838    def eval(self, vars):
839        for node in self.content:
840            yield from node.eval(vars)
841
842    def ul4ondump(self, encoder):
843        super().ul4ondump(encoder)
844        encoder.dump(self.endlocation)
845        encoder.dump(self.content)
846
847    def ul4onload(self, decoder):
848        super().ul4onload(decoder)
849        self.endlocation = decoder.load()
850        self.content = decoder.load()
851
852
853@register("ieie")
854class IfElIfElse(Block):
855    """
856    AST node for an conditional block.
857
858    The content of the :class:`IfElIfElse` block is one :class:`If` block
859    followed by zero or more :class:`ElIf` blocks followed by zero or one
860    :class:`Else` block.
861    """
862    def __init__(self, location=None, condition=None):
863        super().__init__(location)
864        if condition is not None:
865            self.newblock(If(location, condition))
866
867    def __repr__(self):
868        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {1} at {2:#x}>".format(self, repr(self.content)[1:-1], id(self))
869
870    def _repr_pretty_(self, p, cycle):
871        if cycle:
872            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
873        else:
874            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
875                for node in self.content:
876                    p.breakable()
877                    p.pretty(node)
878                p.breakable()
879                p.text("at {:#x}".format(id(self)))
880
881    def append(self, item):
882        self.content[-1].append(item)
883
884    def newblock(self, block):
885        if self.content:
886            self.content[-1].endlocation = block.location
887        self.content.append(block)
888
889    @handleeval
890    def eval(self, vars):
891        for node in self.content:
892            if isinstance(node, Else) or (yield from node.condition.eval(vars)):
893                yield from node.eval(vars)
894                break
895
896
897@register("if")
898class If(Block):
899    """
900    AST node for an ``<?if?>`` block.
901    """
902
903    fields = Block.fields.union({"condition"})
904
905    def __init__(self, location=None, condition=None):
906        super().__init__(location)
907        self.condition = condition
908
909    def __repr__(self):
910        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} {1} at {2:#x}>".format(self, " ..." if self.content else "", id(self))
911
912    def _repr_pretty_(self, p, cycle):
913        if cycle:
914            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
915        else:
916            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
917                p.breakable()
918                p.text("condition=")
919                p.pretty(self.condition)
920                for node in self.content:
921                    p.breakable()
922                    p.pretty(node)
923                p.breakable()
924                p.text("at {:#x}".format(id(self)))
925
926    def _str(self, indent):
927        yield "if "
928        yield from self.condition._str(indent)
929        yield ":\n"
930        yield from super()._str(indent+1)
931
932    def ul4ondump(self, encoder):
933        super().ul4ondump(encoder)
934        encoder.dump(self.condition)
935
936    def ul4onload(self, decoder):
937        super().ul4onload(decoder)
938        self.condition = decoder.load()
939
940
941@register("elif")
942class ElIf(Block):
943    """
944    AST node for an ``<?elif?>`` block.
945    """
946
947    fields = Block.fields.union({"condition"})
948
949    def __init__(self, location=None, condition=None):
950        super().__init__(location)
951        self.condition = condition
952
953    def __repr__(self):
954        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} {1} at {2:#x}>".format(self, " ..." if self.content else "", id(self))
955
956    def _repr_pretty_(self, p, cycle):
957        if cycle:
958            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
959        else:
960            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
961                p.breakable()
962                p.text("condition=")
963                p.pretty(self.condition)
964                for node in self.content:
965                    p.breakable()
966                    p.pretty(node)
967                p.breakable()
968                p.text("at {:#x}".format(id(self)))
969
970    def _str(self, indent):
971        yield "elif "
972        yield from self.condition._str(indent)
973        yield ":\n"
974        yield from super()._str(indent+1)
975
976    def ul4ondump(self, encoder):
977        super().ul4ondump(encoder)
978        encoder.dump(self.condition)
979
980    def ul4onload(self, decoder):
981        super().ul4onload(decoder)
982        self.condition = decoder.load()
983
984
985@register("else")
986class Else(Block):
987    """
988    AST node for an ``<?else?>`` block.
989    """
990
991    def __repr__(self):
992        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} at {1:#x}>".format(self, id(self))
993
994    def _repr_pretty_(self, p, cycle):
995        if cycle:
996            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
997        else:
998            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
999                for node in self.content:
1000                    p.breakable()
1001                    p.pretty(node)
1002                p.breakable()
1003                p.text("at {:#x}".format(id(self)))
1004
1005    def _str(self, indent):
1006        yield "else:\n"
1007        yield from super()._str(indent+1)
1008
1009
1010@register("for")
1011class For(Block):
1012    """
1013    AST node for a ``<?for?>`` loop variable.
1014    """
1015
1016    fields = Block.fields.union({"varname", "container"})
1017
1018    def __init__(self, location=None, varname=None, container=None):
1019        super().__init__(location)
1020        self.varname = varname
1021        self.container = container
1022
1023    def __repr__(self):
1024        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))
1025
1026    def _repr_pretty_(self, p, cycle):
1027        if cycle:
1028            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1029        else:
1030            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1031                p.breakable()
1032                p.text("varname=")
1033                p.pretty(self.varname)
1034                p.breakable()
1035                p.text("container=")
1036                p.pretty(self.container)
1037                for node in self.content:
1038                    p.breakable()
1039                    p.pretty(node)
1040                p.breakable()
1041                p.text("at {:#x}".format(id(self)))
1042
1043    def ul4ondump(self, encoder):
1044        super().ul4ondump(encoder)
1045        encoder.dump(self.varname)
1046        encoder.dump(self.container)
1047
1048    def ul4onload(self, decoder):
1049        super().ul4onload(decoder)
1050        self.varname = decoder.load()
1051        self.container = decoder.load()
1052
1053    def _str(self, indent):
1054        yield "for "
1055        yield _formatnestednameul4(self.varname)
1056        yield " in "
1057        yield from self.container._str(indent)
1058        yield ":\n"
1059        yield from super()._str(indent+1)
1060
1061    @handleeval
1062    def eval(self, vars):
1063        container = (yield from self.container.eval(vars))
1064        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
1065        for item in container:
1066            _unpackvar(vars, self.varname, item)
1067            try:
1068                yield from super().eval(vars)
1069            except BreakException:
1070                break
1071            except ContinueException:
1072                pass
1073
1074
1075@register("break")
1076class Break(AST):
1077    """
1078    AST node for a ``<?break?>`` inside a ``<?for?>`` block.
1079    """
1080
1081    def _str(self, indent):
1082        yield "break\n"
1083
1084    def eval(self, vars):
1085        yield from ()
1086        raise BreakException()
1087
1088
1089@register("continue")
1090class Continue(AST):
1091    """
1092    AST node for a ``<?continue?>`` inside a ``<?for?>`` block.
1093    """
1094
1095    def _str(self, indent):
1096        yield "continue\n"
1097
1098    def eval(self, vars):
1099        yield from ()
1100        raise ContinueException()
1101
1102
1103@register("getattr")
1104class GetAttr(AST):
1105    """
1106    AST node for getting an attribute from an object.
1107
1108    The object is loaded from the AST node :var:`obj` and the attribute name
1109    is stored in the string :var:`attrname`.
1110    """
1111    precedence = 9
1112    associative = False
1113    fields = AST.fields.union({"obj", "attrname"})
1114
1115    def __init__(self, location=None, obj=None, attrname=None):
1116        super().__init__(location)
1117        self.obj = obj
1118        self.attrname = attrname
1119
1120    def __repr__(self):
1121        return "<{0.__class__.__module__}.{0.__class__.__qualname__} obj={0.obj!r}, attrname={0.attrname!r} at {1:#x}>".format(self, id(self))
1122
1123    def _repr_pretty_(self, p, cycle):
1124        if cycle:
1125            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1126        else:
1127            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1128                p.breakable()
1129                p.text("obj=")
1130                p.pretty(self.obj)
1131                p.breakable()
1132                p.text("attrname=")
1133                p.pretty(self.attrname)
1134                p.breakable()
1135                p.text("at {:#x}".format(id(self)))
1136
1137    def _str(self, indent):
1138        yield from self._formatop(self.obj)
1139        yield "."
1140        yield self.attrname
1141
1142    @handleeval
1143    def eval(self, vars):
1144        obj = (yield from self.obj.eval(vars))
1145        try:
1146            return obj[self.attrname]
1147        except KeyError:
1148            return UndefinedKey(self.attrname)
1149
1150    def ul4ondump(self, encoder):
1151        super().ul4ondump(encoder)
1152        encoder.dump(self.obj)
1153        encoder.dump(self.attrname)
1154
1155    def ul4onload(self, decoder):
1156        super().ul4onload(decoder)
1157        self.obj = decoder.load()
1158        self.attrname = decoder.load()
1159
1160
1161@register("getslice")
1162class GetSlice(AST):
1163    """
1164    AST node for getting a slice from a list or string object.
1165
1166    The object is loaded from the AST node :var:`obj` and the start and stop
1167    indices from the AST node :var:`index1` and :var:`index2`. :var:`index1`
1168    and :var:`index2` may also be :const:`None` (for missing slice indices,
1169    which default to the 0 for the start index and the length of the sequence
1170    for the end index).
1171    """
1172
1173    precedence = 8
1174    associative = False
1175    fields = AST.fields.union({"obj", "index1", "index2"})
1176
1177    def __init__(self, location=None, obj=None, index1=None, index2=None):
1178        super().__init__(location)
1179        self.obj = obj
1180        self.index1 = index1
1181        self.index2 = index2
1182
1183    def __repr__(self):
1184        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))
1185
1186    def _repr_pretty_(self, p, cycle):
1187        if cycle:
1188            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1189        else:
1190            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1191                p.breakable()
1192                p.text("obj=")
1193                p.pretty(self.obj)
1194                p.breakable()
1195                p.text("index1=")
1196                p.pretty(self.index1)
1197                p.breakable()
1198                p.text("index2=")
1199                p.pretty(self.index2)
1200                p.breakable()
1201                p.text("at {:#x}".format(id(self)))
1202
1203    def _str(self, indent):
1204        yield from self._formatop(self.obj)
1205        yield "["
1206        if self.index1 is not None:
1207            yield from self.index1._str(indent)
1208        yield ":"
1209        if self.index2 is not None:
1210            yield from self.index2._str(indent)
1211        yield "]"
1212
1213    @handleeval
1214    def eval(self, vars):
1215        obj = (yield from self.obj.eval(vars))
1216        if self.index1 is not None:
1217            index1 = (yield from self.index1.eval(vars))
1218            if self.index2 is not None:
1219                index2 = (yield from self.index2.eval(vars))
1220                return obj[index1:index2]
1221            else:
1222                return obj[index1:]
1223        else:
1224            if self.index2 is not None:
1225                index2 = (yield from self.index2.eval(vars))
1226                return obj[:index2]
1227            else:
1228                return obj[:]
1229
1230    def ul4ondump(self, encoder):
1231        super().ul4ondump(encoder)
1232        encoder.dump(self.obj)
1233        encoder.dump(self.index1)
1234        encoder.dump(self.index2)
1235
1236    def ul4onload(self, decoder):
1237        super().ul4onload(decoder)
1238        self.obj = decoder.load()
1239        self.index1 = decoder.load()
1240        self.index2 = decoder.load()
1241
1242
1243class Unary(AST):
1244    """
1245    Base class for all AST nodes implementing unary operators.
1246    """
1247
1248    fields = AST.fields.union({"obj"})
1249
1250    def __init__(self, location=None, obj=None):
1251        super().__init__(location)
1252        self.obj = obj
1253
1254    def __repr__(self):
1255        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj!r} at {1:#x}>".format(self, id(self))
1256
1257    def _repr_pretty_(self, p, cycle):
1258        if cycle:
1259            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1260        else:
1261            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1262                p.breakable()
1263                p.pretty(self.obj)
1264                p.breakable()
1265                p.text("at {:#x}".format(id(self)))
1266
1267    def ul4ondump(self, encoder):
1268        super().ul4ondump(encoder)
1269        encoder.dump(self.obj)
1270
1271    def ul4onload(self, decoder):
1272        super().ul4onload(decoder)
1273        self.obj = decoder.load()
1274
1275    @handleeval
1276    def eval(self, vars):
1277        obj = (yield from self.obj.eval(vars))
1278        return self.evalfold(obj)
1279
1280    @classmethod
1281    def make(cls, location, obj):
1282        if isinstance(obj, Const):
1283            result = cls.evalfold(obj.value)
1284            if not isinstance(result, Undefined):
1285                return Const(location, result)
1286        return cls(location, obj)
1287
1288
1289@register("not")
1290class Not(Unary):
1291    """
1292    AST node for the unary ``not`` operator.
1293    """
1294
1295    precedence = 2
1296
1297    def _str(self, indent):
1298        yield "not "
1299        yield from self._formatop(self.obj)
1300
1301    @classmethod
1302    def evalfold(cls, obj):
1303        return not obj
1304
1305
1306@register("neg")
1307class Neg(Unary):
1308    """
1309    AST node for the unary negation (i.e. "-") operator.
1310    """
1311
1312    precedence = 7
1313
1314    def _str(self, indent):
1315        yield "-"
1316        yield from self._formatop(self.obj)
1317
1318    @classmethod
1319    def evalfold(cls, obj):
1320        return -obj
1321
1322
1323@register("print")
1324class Print(Unary):
1325    """
1326    AST node for a ``<?print?>`` tag.
1327    """
1328
1329    def _str(self, indent):
1330        yield "print "
1331        yield from self.obj._str(indent)
1332        yield "\n"
1333
1334    @handleeval
1335    def eval(self, vars):
1336        yield _str((yield from self.obj.eval(vars)))
1337
1338
1339@register("printx")
1340class PrintX(Unary):
1341    """
1342    AST node for a ``<?printx?>`` tag.
1343    """
1344
1345    def _str(self, indent):
1346        yield "printx "
1347        yield from self.obj._str(indent)
1348        yield "\n"
1349
1350    @handleeval
1351    def eval(self, vars):
1352        yield _xmlescape((yield from self.obj.eval(vars)))
1353
1354
1355@register("return")
1356class Return(Unary):
1357    """
1358    AST node for a ``<?return?>`` tag.
1359    """
1360
1361    def _str(self, indent):
1362        yield "return "
1363        yield from self.obj._str(indent)
1364        yield "\n"
1365
1366    @handleeval
1367    def eval(self, vars):
1368        value = (yield from self.obj.eval(vars))
1369        raise ReturnException(value)
1370
1371
1372class Binary(AST):
1373    """
1374    Base class for all AST nodes implementing binary operators.
1375    """
1376
1377    fields = AST.fields.union({"obj1", "obj2"})
1378
1379    def __init__(self, location=None, obj1=None, obj2=None):
1380        super().__init__(location)
1381        self.obj1 = obj1
1382        self.obj2 = obj2
1383
1384    def __repr__(self):
1385        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj1!r} {0.obj2!r} at {1:#x}>".format(self, id(self))
1386
1387    def _repr_pretty_(self, p, cycle):
1388        if cycle:
1389            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1390        else:
1391            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1392                p.breakable()
1393                p.pretty(self.obj1)
1394                p.breakable()
1395                p.pretty(self.obj2)
1396                p.breakable()
1397                p.text("at {:#x}".format(id(self)))
1398
1399    def ul4ondump(self, encoder):
1400        super().ul4ondump(encoder)
1401        encoder.dump(self.obj1)
1402        encoder.dump(self.obj2)
1403
1404    def ul4onload(self, decoder):
1405        super().ul4onload(decoder)
1406        self.obj1 = decoder.load()
1407        self.obj2 = decoder.load()
1408
1409    @handleeval
1410    def eval(self, vars):
1411        obj1 = (yield from self.obj1.eval(vars))
1412        obj2 = (yield from self.obj2.eval(vars))
1413        return self.evalfold(obj1, obj2)
1414
1415    @classmethod
1416    def make(cls, location, obj1, obj2):
1417        if isinstance(obj1, Const) and isinstance(obj2, Const):
1418            result = cls.evalfold(obj1.value, obj2.value)
1419            if not isinstance(result, Undefined):
1420                return Const(location, result)
1421        return cls(location, obj1, obj2)
1422
1423
1424@register("getitem")
1425class GetItem(Binary):
1426    """
1427    AST node for subscripting operator.
1428
1429    The object (which must be a list, string or dict) is loaded from the AST
1430    node :var:`obj1` and the index/key is loaded from the AST node :var:`obj2`.
1431    """
1432
1433    precedence = 9
1434    associative = False
1435
1436    @classmethod
1437    def evaluate(cls, obj1, obj2):
1438        return obj1[obj2]
1439
1440    def _str(self, indent):
1441        yield from self.obj1._str(indent)
1442        yield "["
1443        yield from self.obj2._str(indent)
1444        yield "]"
1445
1446    @classmethod
1447    def evalfold(cls, obj1, obj2):
1448        try:
1449            return obj1[obj2]
1450        except KeyError:
1451            return UndefinedKey(obj2)
1452        except IndexError:
1453            return UndefinedIndex(obj2)
1454
1455
1456@register("eq")
1457class EQ(Binary):
1458    """
1459    AST node for the binary ``==`` comparison operator.
1460    """
1461
1462    precedence = 4
1463    associative = False
1464
1465    def _str(self, indent):
1466        yield from self._formatop(self.obj1)
1467        yield " == "
1468        yield from self._formatop(self.obj2)
1469
1470    @classmethod
1471    def evalfold(cls, obj1, obj2):
1472        return obj1 == obj2
1473
1474
1475@register("ne")
1476class NE(Binary):
1477    """
1478    AST node for the binary ``!=`` comparison operator.
1479    """
1480
1481    precedence = 4
1482    associative = False
1483
1484    def _str(self, indent):
1485        yield from self._formatop(self.obj1)
1486        yield " != "
1487        yield from self._formatop(self.obj2)
1488
1489    @classmethod
1490    def evalfold(cls, obj1, obj2):
1491        return obj1 != obj2
1492
1493
1494@register("lt")
1495class LT(Binary):
1496    """
1497    AST node for the binary ``<`` comparison operator.
1498    """
1499
1500    precedence = 4
1501    associative = False
1502
1503    def _str(self, indent):
1504        yield from self._formatop(self.obj1)
1505        yield " < "
1506        yield from self._formatop(self.obj2)
1507
1508    @classmethod
1509    def evalfold(cls, obj1, obj2):
1510        return obj1 < obj2
1511
1512
1513@register("le")
1514class LE(Binary):
1515    """
1516    AST node for the binary ``<=`` comparison operator.
1517    """
1518
1519    precedence = 4
1520    associative = False
1521
1522    def _str(self, indent):
1523        yield from self._formatop(self.obj1)
1524        yield " <= "
1525        yield from self._formatop(self.obj2)
1526
1527    @classmethod
1528    def evalfold(cls, obj1, obj2):
1529        return obj1 <= obj2
1530
1531
1532@register("gt")
1533class GT(Binary):
1534    """
1535    AST node for the binary ``>`` comparison operator.
1536    """
1537
1538    precedence = 4
1539    associative = False
1540
1541    def _str(self, indent):
1542        yield from self._formatop(self.obj1)
1543        yield " > "
1544        yield from self._formatop(self.obj2)
1545
1546    @classmethod
1547    def evalfold(cls, obj1, obj2):
1548        return obj1 > obj2
1549
1550
1551@register("ge")
1552class GE(Binary):
1553    """
1554    AST node for the binary ``>=`` comparison operator.
1555    """
1556
1557    precedence = 4
1558    associative = False
1559
1560    def _str(self, indent):
1561        yield from self._formatop(self.obj1)
1562        yield " >= "
1563        yield from self._formatop(self.obj2)
1564
1565    @classmethod
1566    def evalfold(cls, obj1, obj2):
1567        return obj1 >= obj2
1568
1569
1570@register("contains")
1571class Contains(Binary):
1572    """
1573    AST node for the binary containment testing operator.
1574
1575    The item/key object is loaded from the AST node :var:`obj1` and the container
1576    object (which must be a list, string or dict) is loaded from the AST node
1577    :var:`obj2`.
1578    """
1579
1580    precedence = 3
1581    associative = False
1582
1583    def _str(self, indent):
1584        yield from self._formatop(self.obj1)
1585        yield " in "
1586        yield from self._formatop(self.obj2)
1587
1588    @classmethod
1589    def evalfold(cls, obj1, obj2):
1590        return obj1 in obj2
1591
1592
1593@register("notcontains")
1594class NotContains(Binary):
1595    """
1596    AST node for the inverted containment testing operator.
1597
1598    The item/key object is loaded from the AST node :var:`obj1` and the container
1599    object (which must be a list, string or dict) is loaded from the AST node
1600    :var:`obj2`.
1601    """
1602
1603    precedence = 3
1604    associative = False
1605
1606    def _str(self, indent):
1607        yield from self._formatop(self.obj1)
1608        yield " not in "
1609        yield from self._formatop(self.obj2)
1610
1611    @classmethod
1612    def evalfold(cls, obj1, obj2):
1613        return obj1 not in obj2
1614
1615
1616@register("add")
1617class Add(Binary):
1618    """
1619    AST node for the binary addition operator.
1620    """
1621
1622    precedence = 5
1623
1624    def _str(self, indent):
1625        yield from self._formatop(self.obj1)
1626        yield "+"
1627        yield from self._formatop(self.obj2)
1628
1629    @classmethod
1630    def evalfold(cls, obj1, obj2):
1631        return obj1 + obj2
1632
1633
1634@register("sub")
1635class Sub(Binary):
1636    """
1637    AST node for the binary substraction operator.
1638    """
1639
1640    precedence = 5
1641    associative = False
1642
1643    def _str(self, indent):
1644        yield from self._formatop(self.obj1)
1645        yield "-"
1646        yield from self._formatop(self.obj2)
1647
1648    @classmethod
1649    def evalfold(cls, obj1, obj2):
1650        return obj1 - obj2
1651
1652
1653@register("mul")
1654class Mul(Binary):
1655    """
1656    AST node for the binary multiplication operator.
1657    """
1658
1659    precedence = 6
1660
1661    def _str(self, indent):
1662        yield from self._formatop(self.obj1)
1663        yield "*"
1664        yield from self._formatop(self.obj2)
1665
1666    @classmethod
1667    def evalfold(cls, obj1, obj2):
1668        return obj1 * obj2
1669
1670
1671@register("floordiv")
1672class FloorDiv(Binary):
1673    """
1674    AST node for the binary truncating division operator.
1675    """
1676
1677    precedence = 6
1678    associative = False
1679
1680    def _str(self, indent):
1681        yield from self._formatop(self.obj1)
1682        yield "//"
1683        yield from self._formatop(self.obj2)
1684
1685    @classmethod
1686    def evalfold(cls, obj1, obj2):
1687        return obj1 // obj2
1688
1689
1690@register("truediv")
1691class TrueDiv(Binary):
1692    """
1693    AST node for the binary true division operator.
1694    """
1695
1696    precedence = 6
1697    associative = False
1698
1699    def _str(self, indent):
1700        yield from self._formatop(self.obj1)
1701        yield "/"
1702        yield from self._formatop(self.obj2)
1703
1704    @classmethod
1705    def evalfold(cls, obj1, obj2):
1706        return obj1 / obj2
1707
1708
1709@register("and")
1710class And(Binary):
1711    """
1712    AST node for the binary ``and`` operator.
1713    """
1714
1715    precedence = 1
1716
1717    def _str(self, indent):
1718        yield from self._formatop(self.obj1)
1719        yield " and "
1720        yield from self._formatop(self.obj2)
1721
1722    @classmethod
1723    def evalfold(cls, obj1, obj2):
1724        # This is not called from ``eval``, as it doesn't short-circuit
1725        return obj1 and obj2
1726
1727    @handleeval
1728    def eval(self, vars):
1729        obj1 = (yield from self.obj1.eval(vars))
1730        if not obj1:
1731            return obj1
1732        return (yield from self.obj2.eval(vars))
1733
1734
1735
1736@register("or")
1737class Or(Binary):
1738    """
1739    AST node for the binary ``or`` operator.
1740    """
1741
1742    precedence = 0
1743
1744    def _str(self, indent):
1745        yield from self._formatop(self.obj1)
1746        yield " or "
1747        yield from self._formatop(self.obj2)
1748
1749    @classmethod
1750    def evalfold(cls, obj1, obj2):
1751        # This is not called from ``eval``, as it doesn't short-circuit
1752        return obj1 or obj2
1753
1754    @handleeval
1755    def eval(self, vars):
1756        obj1 = (yield from self.obj1.eval(vars))
1757        if obj1:
1758            return obj1
1759        return (yield from self.obj2.eval(vars))
1760
1761
1762@register("mod")
1763class Mod(Binary):
1764    """
1765    AST node for the binary modulo operator.
1766    """
1767
1768    precedence = 6
1769    associative = False
1770
1771    def _str(self, indent):
1772        yield from self._formatop(self.obj1)
1773        yield "%"
1774        yield from self._formatop(self.obj2)
1775
1776    @classmethod
1777    def evalfold(cls, obj1, obj2):
1778        return obj1 % obj2
1779
1780
1781class ChangeVar(AST):
1782    """
1783    Baseclass for all AST nodes that store or modify a variable.
1784
1785    The variable name is stored in the string :var:`varname` and the value that
1786    will be stored or be used to modify the stored value is loaded from the
1787    AST node :var:`value`.
1788    """
1789
1790    fields = AST.fields.union({"varname", "value"})
1791
1792    def __init__(self, location=None, varname=None, value=None):
1793        super().__init__(location)
1794        self.varname = varname
1795        self.value = value
1796
1797    def __repr__(self):
1798        return "<{0.__class__.__module__}.{0.__class__.__qualname__} varname={0.varname!r} value={0.value!r} at {1:#x}>".format(self, id(self))
1799
1800    def _repr_pretty_(self, p, cycle):
1801        if cycle:
1802            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1803        else:
1804            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1805                p.breakable()
1806                p.text("varname=")
1807                p.pretty(self.obj1)
1808                p.text("value=")
1809                p.breakable()
1810                p.pretty(self.obj2)
1811                p.breakable()
1812                p.text("at {:#x}".format(id(self)))
1813
1814    def ul4ondump(self, encoder):
1815        super().ul4ondump(encoder)
1816        encoder.dump(self.varname)
1817        encoder.dump(self.value)
1818
1819    def ul4onload(self, decoder):
1820        super().ul4onload(decoder)
1821        self.varname = decoder.load()
1822        self.value = decoder.load()
1823
1824
1825@register("storevar")
1826class StoreVar(ChangeVar):
1827    """
1828    AST node that stores a value into a variable.
1829    """
1830
1831    def _str(self, indent):
1832        yield _formatnestednameul4(self.varname)
1833        yield " = "
1834        yield from self.value._str(indent)
1835        yield "\n"
1836
1837    @handleeval
1838    def eval(self, vars):
1839        value = (yield from self.value.eval(vars))
1840        _unpackvar(vars, self.varname, value)
1841
1842
1843@register("addvar")
1844class AddVar(ChangeVar):
1845    """
1846    AST node that adds a value to a variable (i.e. the ``+=`` operator).
1847    """
1848
1849    def _str(self, indent):
1850        yield _formatnestednameul4(self.varname)
1851        yield " += "
1852        yield from self.value._str(indent)
1853        yield "\n"
1854
1855    @handleeval
1856    def eval(self, vars):
1857        value = (yield from self.value.eval(vars))
1858        vars[self.varname] += value
1859
1860
1861@register("subvar")
1862class SubVar(ChangeVar):
1863    """
1864    AST node that substracts a value from a variable (i.e. the ``-=`` operator).
1865    """
1866
1867    def _str(self, indent):
1868        yield _formatnestednameul4(self.varname)
1869        yield " -= "
1870        yield from self.value._str(indent)
1871        yield "\n"
1872
1873    @handleeval
1874    def eval(self, vars):
1875        value = (yield from self.value.eval(vars))
1876        vars[self.varname] -= value
1877
1878
1879@register("mulvar")
1880class MulVar(ChangeVar):
1881    """
1882    AST node that multiplies a variable by a value (i.e. the ``*=`` operator).
1883    """
1884
1885    def _str(self, indent):
1886        yield _formatnestednameul4(self.varname)
1887        yield " *= "
1888        yield from self.value._str(indent)
1889        yield "\n"
1890
1891    @handleeval
1892    def eval(self, vars):
1893        value = (yield from self.value.eval(vars))
1894        vars[self.varname] *= value
1895
1896
1897@register("floordivvar")
1898class FloorDivVar(ChangeVar):
1899    """
1900    AST node that divides a variable by a value (truncating to an integer value;
1901    i.e. the ``//=`` operator).
1902    """
1903
1904    def _str(self, indent):
1905        yield _formatnestednameul4(self.varname)
1906        yield " //= "
1907        yield from self.value._str(indent)
1908        yield "\n"
1909
1910    @handleeval
1911    def eval(self, vars):
1912        value = (yield from self.value.eval(vars))
1913        vars[self.varname] //= value
1914
1915
1916@register("truedivvar")
1917class TrueDivVar(ChangeVar):
1918    """
1919    AST node that divides a variable by a value (i.e. the ``/=`` operator).
1920    """
1921
1922    def _str(self, indent):
1923        yield _formatnestednameul4(self.varname)
1924        yield " /= "
1925        yield from self.value._str(indent)
1926        yield "\n"
1927
1928    @handleeval
1929    def eval(self, vars):
1930        value = (yield from self.value.eval(vars))
1931        vars[self.varname] /= value
1932
1933
1934@register("modvar")
1935class ModVar(ChangeVar):
1936    """
1937    AST node for the ``%=`` operator.
1938    """
1939
1940    def _str(self, indent):
1941        yield _formatnestednameul4(self.varname)
1942        yield " %= "
1943        yield from self.value._str(indent)
1944        yield "\n"
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, indent):
2013        yield from self.obj._str(indent)
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(indent)
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(indent)
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(indent)
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(indent)
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, indent):
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(indent)
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(indent)
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(indent)
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(indent)
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", "endlocation"})
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 ``<?template?>`` tag
2263        # in :meth:`_compile` and ``endlocation`` will be the location of the ``<?end template?>`` 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, indent):
2286        yield "def "
2287        yield self.name if self.name is not None else "unnamed"
2288        yield ":\n"
2289        yield from super()._str(indent+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, item):
3342    return obj.append(item)
3343
3344
3345@AST.makemethod
3346def _insert(obj, pos, item):
3347    return obj.insert(pos, item)
3348
3349
3350@AST.makemethod
3351def _pop(obj, pos=-1):
3352    return obj.pop(pos)
3353
3354
3355class TemplateClosure(Object):
3356    fields = {"location", "endlocation", "name", "source", "startdelim", "enddelim", "content"}
3357
3358    def __init__(self, template, vars):
3359        self.template = template
3360        # Freeze variables of the currently running templates/functions
3361        self.vars = vars.copy()
3362
3363    def render(self, **vars):
3364        return self.template.render(**collections.ChainMap(vars, self.vars))
3365
3366    def renders(self, **vars):
3367        return self.template.renders(**collections.ChainMap(vars, self.vars))
3368
3369    def __call__(self, **vars):
3370        return self.template(**collections.ChainMap(vars, self.vars))
3371
3372    def __getattr__(self, name):
3373        return getattr(self.template, name)
3374
3375    def __repr__(self):
3376        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} name={0.name!r} keepws={0.keepws!r}".format(self)
3377        if self.startdelim != "<?":
3378            s += " startdelim={0.startdelim!r}".format(self)
3379        if self.enddelim != "?>":
3380            s += " enddelim={0.enddelim!r}".format(self)
3381        if self.content:
3382            s + " ..."
3383        return s + " at {:#x}>".format(id(self))
3384
3385    def _repr_pretty_(self, p, cycle):
3386        if cycle:
3387            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
3388        else:
3389            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
3390                p.breakable()
3391                p.text("name=")
3392                p.pretty(self.name)
3393                p.breakable()
3394                p.text("keepws=")
3395                p.pretty(self.keepws)
3396                if self.startdelim != "<?":
3397                    p.breakable()
3398                    p.text("startdelim=")
3399                    p.pretty(self.startdelim)
3400                if self.enddelim != "?>":
3401                    p.breakable()
3402                    p.text("enddelim=")
3403                    p.pretty(self.enddelim)
3404                for node in self.content:
3405                    p.breakable()
3406                    p.pretty(node)
3407                p.breakable()
3408                p.text("at {:#x}".format(id(self)))
3409
3410
3411###
3412### Helper classes/functions used at runtime
3413###
3414
3415def _formatnestednameul4(name):
3416    if isinstance(name, str):
3417        return name
3418    elif len(name) == 1:
3419        return "({},)".format(_formatnestednameul4(name[0]))
3420    else:
3421        return "({})".format(", ".join(_formatnestednameul4(name) for name in name))
3422
3423
3424def _unpackvar(vars, name, value):
3425    if isinstance(name, str):
3426        vars[name] = value
3427    else:
3428        if len(name) > len(value):
3429            raise TypeError("too many values to unpack (expected {})".format(len(name)))
3430        elif len(name) < len(value):
3431            raise TypeError("need more than {} value{} to unpack)".format(len(values), "ss" if len(values) != 1 else ""))
3432        for (name, value) in zip(name, value):
3433            _unpackvar(vars, name, value)
Note: See TracBrowser for help on using the browser.