root/livinglogic.python.xist/src/ll/ul4c.py @ 5342:2ca278f69ba8

Revision 5342:2ca278f69ba8, 80.4 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Fix _str formatting (linefeeds were missing if the block contained expressions).

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, level):
305        """
306        Format :var:`self` (with the indentation level :var:`level`).
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__} {1!r} at {2:#x}>".format(self, self.text(), id(self))
360
361    def _str(self, level):
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, level):
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, level):
430        yield "["
431        for (i, item) in enumerate(self.items):
432            if i:
433                yield ", "
434            yield from item._str(level)
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, level):
502        yield "["
503        yield from self.item._str(level)
504        yield " for "
505        yield _formatnestednameul4(self.varname)
506        yield " in "
507        yield from self.container._str(level)
508        if self.condition is not None:
509            yield " if "
510            yield from self.condition._str(level)
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, level):
570        yield "{"
571        for (i, item) in enumerate(self.items):
572            if i:
573                yield ", "
574            yield from item[0]._str(level)
575            yield ": "
576            yield from item[1]._str(level)
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, level):
645        yield "{"
646        yield from self.key._str(level)
647        yield " : "
648        yield from self.value._str(level)
649        yield " for "
650        yield _formatnestednameul4(self.varname)
651        yield " in "
652        yield from self.container._str(level)
653        if self.condition is not None:
654            yield " if "
655            yield from self.condition._str(level)
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, level):
732        yield "("
733        yield from self.item._str(level)
734        yield " for "
735        yield _formatnestednameul4(self.varname)
736        yield " in "
737        yield from self.container._str(level)
738        if self.condition is not None:
739            yield " if "
740            yield from self.condition._str(level)
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, level):
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, level):
829        if self.content:
830            for node in self.content:
831                yield level*"\t"
832                yield from node._str(level)
833                yield "\n"
834        else:
835            yield level*"\t"
836            yield "pass\n"
837
838    @handleeval
839    def eval(self, vars):
840        for node in self.content:
841            yield from node.eval(vars)
842
843    def ul4ondump(self, encoder):
844        super().ul4ondump(encoder)
845        encoder.dump(self.endlocation)
846        encoder.dump(self.content)
847
848    def ul4onload(self, decoder):
849        super().ul4onload(decoder)
850        self.endlocation = decoder.load()
851        self.content = decoder.load()
852
853
854@register("ieie")
855class IfElIfElse(Block):
856    """
857    AST node for an conditional block.
858
859    The content of the :class:`IfElIfElse` block is one :class:`If` block
860    followed by zero or more :class:`ElIf` blocks followed by zero or one
861    :class:`Else` block.
862    """
863    def __init__(self, location=None, condition=None):
864        super().__init__(location)
865        if condition is not None:
866            self.newblock(If(location, condition))
867
868    def __repr__(self):
869        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {1} at {2:#x}>".format(self, repr(self.content)[1:-1], id(self))
870
871    def _repr_pretty_(self, p, cycle):
872        if cycle:
873            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
874        else:
875            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
876                for node in self.content:
877                    p.breakable()
878                    p.pretty(node)
879                p.breakable()
880                p.text("at {:#x}".format(id(self)))
881
882    def append(self, item):
883        self.content[-1].append(item)
884
885    def newblock(self, block):
886        if self.content:
887            self.content[-1].endlocation = block.location
888        self.content.append(block)
889
890    @handleeval
891    def eval(self, vars):
892        for node in self.content:
893            if isinstance(node, Else) or (yield from node.condition.eval(vars)):
894                yield from node.eval(vars)
895                break
896
897
898@register("if")
899class If(Block):
900    """
901    AST node for an ``<?if?>`` block.
902    """
903
904    fields = Block.fields.union({"condition"})
905
906    def __init__(self, location=None, condition=None):
907        super().__init__(location)
908        self.condition = condition
909
910    def __repr__(self):
911        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} {1} at {2:#x}>".format(self, " ..." if self.content else "", id(self))
912
913    def _repr_pretty_(self, p, cycle):
914        if cycle:
915            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
916        else:
917            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
918                p.breakable()
919                p.text("condition=")
920                p.pretty(self.condition)
921                for node in self.content:
922                    p.breakable()
923                    p.pretty(node)
924                p.breakable()
925                p.text("at {:#x}".format(id(self)))
926
927    def _str(self, level):
928        yield "if "
929        yield from self.condition._str(level)
930        yield ":\n"
931        yield from super()._str(level+1)
932
933    def ul4ondump(self, encoder):
934        super().ul4ondump(encoder)
935        encoder.dump(self.condition)
936
937    def ul4onload(self, decoder):
938        super().ul4onload(decoder)
939        self.condition = decoder.load()
940
941
942@register("elif")
943class ElIf(Block):
944    """
945    AST node for an ``<?elif?>`` block.
946    """
947
948    fields = Block.fields.union({"condition"})
949
950    def __init__(self, location=None, condition=None):
951        super().__init__(location)
952        self.condition = condition
953
954    def __repr__(self):
955        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} {1} at {2:#x}>".format(self, " ..." if self.content else "", id(self))
956
957    def _repr_pretty_(self, p, cycle):
958        if cycle:
959            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
960        else:
961            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
962                p.breakable()
963                p.text("condition=")
964                p.pretty(self.condition)
965                for node in self.content:
966                    p.breakable()
967                    p.pretty(node)
968                p.breakable()
969                p.text("at {:#x}".format(id(self)))
970
971    def _str(self, level):
972        yield "elif "
973        yield from self.condition._str(level)
974        yield ":\n"
975        yield from super()._str(level+1)
976
977    def ul4ondump(self, encoder):
978        super().ul4ondump(encoder)
979        encoder.dump(self.condition)
980
981    def ul4onload(self, decoder):
982        super().ul4onload(decoder)
983        self.condition = decoder.load()
984
985
986@register("else")
987class Else(Block):
988    """
989    AST node for an ``<?else?>`` block.
990    """
991
992    def __repr__(self):
993        return "<{0.__class__.__module__}.{0.__class__.__qualname__} condition={0.condition!r} at {1:#x}>".format(self, id(self))
994
995    def _repr_pretty_(self, p, cycle):
996        if cycle:
997            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
998        else:
999            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1000                for node in self.content:
1001                    p.breakable()
1002                    p.pretty(node)
1003                p.breakable()
1004                p.text("at {:#x}".format(id(self)))
1005
1006    def _str(self, level):
1007        yield "else:\n"
1008        yield from super()._str(level+1)
1009
1010
1011@register("for")
1012class For(Block):
1013    """
1014    AST node for a ``<?for?>`` loop variable.
1015    """
1016
1017    fields = Block.fields.union({"varname", "container"})
1018
1019    def __init__(self, location=None, varname=None, container=None):
1020        super().__init__(location)
1021        self.varname = varname
1022        self.container = container
1023
1024    def __repr__(self):
1025        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))
1026
1027    def _repr_pretty_(self, p, cycle):
1028        if cycle:
1029            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1030        else:
1031            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1032                p.breakable()
1033                p.text("varname=")
1034                p.pretty(self.varname)
1035                p.breakable()
1036                p.text("container=")
1037                p.pretty(self.container)
1038                for node in self.content:
1039                    p.breakable()
1040                    p.pretty(node)
1041                p.breakable()
1042                p.text("at {:#x}".format(id(self)))
1043
1044    def ul4ondump(self, encoder):
1045        super().ul4ondump(encoder)
1046        encoder.dump(self.varname)
1047        encoder.dump(self.container)
1048
1049    def ul4onload(self, decoder):
1050        super().ul4onload(decoder)
1051        self.varname = decoder.load()
1052        self.container = decoder.load()
1053
1054    def _str(self, level):
1055        yield "for "
1056        yield _formatnestednameul4(self.varname)
1057        yield " in "
1058        yield from self.container._str(level)
1059        yield ":\n"
1060        yield from super()._str(level+1)
1061
1062    @handleeval
1063    def eval(self, vars):
1064        container = (yield from self.container.eval(vars))
1065        vars = collections.ChainMap({}, vars) # Don't let loop variables leak into the surrounding scope
1066        for item in container:
1067            _unpackvar(vars, self.varname, item)
1068            try:
1069                yield from super().eval(vars)
1070            except BreakException:
1071                break
1072            except ContinueException:
1073                pass
1074
1075
1076@register("break")
1077class Break(AST):
1078    """
1079    AST node for a ``<?break?>`` inside a ``<?for?>`` block.
1080    """
1081
1082    def _str(self, level):
1083        yield "break\n"
1084
1085    def eval(self, vars):
1086        yield from ()
1087        raise BreakException()
1088
1089
1090@register("continue")
1091class Continue(AST):
1092    """
1093    AST node for a ``<?continue?>`` inside a ``<?for?>`` block.
1094    """
1095
1096    def _str(self, level):
1097        yield "continue\n"
1098
1099    def eval(self, vars):
1100        yield from ()
1101        raise ContinueException()
1102
1103
1104@register("getattr")
1105class GetAttr(AST):
1106    """
1107    AST node for getting an attribute from an object.
1108
1109    The object is loaded from the AST node :var:`obj` and the attribute name
1110    is stored in the string :var:`attrname`.
1111    """
1112    precedence = 9
1113    associative = False
1114    fields = AST.fields.union({"obj", "attrname"})
1115
1116    def __init__(self, location=None, obj=None, attrname=None):
1117        super().__init__(location)
1118        self.obj = obj
1119        self.attrname = attrname
1120
1121    def __repr__(self):
1122        return "<{0.__class__.__module__}.{0.__class__.__qualname__} obj={0.obj!r}, attrname={0.attrname!r} at {1:#x}>".format(self, id(self))
1123
1124    def _repr_pretty_(self, p, cycle):
1125        if cycle:
1126            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1127        else:
1128            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1129                p.breakable()
1130                p.text("obj=")
1131                p.pretty(self.obj)
1132                p.breakable()
1133                p.text("attrname=")
1134                p.pretty(self.attrname)
1135                p.breakable()
1136                p.text("at {:#x}".format(id(self)))
1137
1138    def _str(self, level):
1139        yield from self._formatop(self.obj)
1140        yield "."
1141        yield self.attrname
1142
1143    @handleeval
1144    def eval(self, vars):
1145        obj = (yield from self.obj.eval(vars))
1146        try:
1147            return obj[self.attrname]
1148        except KeyError:
1149            return UndefinedKey(self.attrname)
1150
1151    def ul4ondump(self, encoder):
1152        super().ul4ondump(encoder)
1153        encoder.dump(self.obj)
1154        encoder.dump(self.attrname)
1155
1156    def ul4onload(self, decoder):
1157        super().ul4onload(decoder)
1158        self.obj = decoder.load()
1159        self.attrname = decoder.load()
1160
1161
1162@register("getslice")
1163class GetSlice(AST):
1164    """
1165    AST node for getting a slice from a list or string object.
1166
1167    The object is loaded from the AST node :var:`obj` and the start and stop
1168    indices from the AST node :var:`index1` and :var:`index2`. :var:`index1`
1169    and :var:`index2` may also be :const:`None` (for missing slice indices,
1170    which default to the 0 for the start index and the length of the sequence
1171    for the end index).
1172    """
1173
1174    precedence = 8
1175    associative = False
1176    fields = AST.fields.union({"obj", "index1", "index2"})
1177
1178    def __init__(self, location=None, obj=None, index1=None, index2=None):
1179        super().__init__(location)
1180        self.obj = obj
1181        self.index1 = index1
1182        self.index2 = index2
1183
1184    def __repr__(self):
1185        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))
1186
1187    def _repr_pretty_(self, p, cycle):
1188        if cycle:
1189            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1190        else:
1191            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1192                p.breakable()
1193                p.text("obj=")
1194                p.pretty(self.obj)
1195                p.breakable()
1196                p.text("index1=")
1197                p.pretty(self.index1)
1198                p.breakable()
1199                p.text("index2=")
1200                p.pretty(self.index2)
1201                p.breakable()
1202                p.text("at {:#x}".format(id(self)))
1203
1204    def _str(self, level):
1205        yield from self._formatop(self.obj)
1206        yield "["
1207        if self.index1 is not None:
1208            yield from self.index1._str(level)
1209        yield ":"
1210        if self.index2 is not None:
1211            yield from self.index2._str(level)
1212        yield "]"
1213
1214    @handleeval
1215    def eval(self, vars):
1216        obj = (yield from self.obj.eval(vars))
1217        if self.index1 is not None:
1218            index1 = (yield from self.index1.eval(vars))
1219            if self.index2 is not None:
1220                index2 = (yield from self.index2.eval(vars))
1221                return obj[index1:index2]
1222            else:
1223                return obj[index1:]
1224        else:
1225            if self.index2 is not None:
1226                index2 = (yield from self.index2.eval(vars))
1227                return obj[:index2]
1228            else:
1229                return obj[:]
1230
1231    def ul4ondump(self, encoder):
1232        super().ul4ondump(encoder)
1233        encoder.dump(self.obj)
1234        encoder.dump(self.index1)
1235        encoder.dump(self.index2)
1236
1237    def ul4onload(self, decoder):
1238        super().ul4onload(decoder)
1239        self.obj = decoder.load()
1240        self.index1 = decoder.load()
1241        self.index2 = decoder.load()
1242
1243
1244class Unary(AST):
1245    """
1246    Base class for all AST nodes implementing unary operators.
1247    """
1248
1249    fields = AST.fields.union({"obj"})
1250
1251    def __init__(self, location=None, obj=None):
1252        super().__init__(location)
1253        self.obj = obj
1254
1255    def __repr__(self):
1256        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj!r} at {1:#x}>".format(self, id(self))
1257
1258    def _repr_pretty_(self, p, cycle):
1259        if cycle:
1260            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1261        else:
1262            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1263                p.breakable()
1264                p.pretty(self.obj)
1265                p.breakable()
1266                p.text("at {:#x}".format(id(self)))
1267
1268    def ul4ondump(self, encoder):
1269        super().ul4ondump(encoder)
1270        encoder.dump(self.obj)
1271
1272    def ul4onload(self, decoder):
1273        super().ul4onload(decoder)
1274        self.obj = decoder.load()
1275
1276    @handleeval
1277    def eval(self, vars):
1278        obj = (yield from self.obj.eval(vars))
1279        return self.evalfold(obj)
1280
1281    @classmethod
1282    def make(cls, location, obj):
1283        if isinstance(obj, Const):
1284            result = cls.evalfold(obj.value)
1285            if not isinstance(result, Undefined):
1286                return Const(location, result)
1287        return cls(location, obj)
1288
1289
1290@register("not")
1291class Not(Unary):
1292    """
1293    AST node for the unary ``not`` operator.
1294    """
1295
1296    precedence = 2
1297
1298    def _str(self, level):
1299        yield "not "
1300        yield from self._formatop(self.obj)
1301
1302    @classmethod
1303    def evalfold(cls, obj):
1304        return not obj
1305
1306
1307@register("neg")
1308class Neg(Unary):
1309    """
1310    AST node for the unary negation (i.e. "-") operator.
1311    """
1312
1313    precedence = 7
1314
1315    def _str(self, level):
1316        yield "-"
1317        yield from self._formatop(self.obj)
1318
1319    @classmethod
1320    def evalfold(cls, obj):
1321        return -obj
1322
1323
1324@register("print")
1325class Print(Unary):
1326    """
1327    AST node for a ``<?print?>`` tag.
1328    """
1329
1330    def _str(self, level):
1331        yield "print "
1332        yield from self.obj._str(level)
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, level):
1346        yield "printx "
1347        yield from self.obj._str(level)
1348
1349    @handleeval
1350    def eval(self, vars):
1351        yield _xmlescape((yield from self.obj.eval(vars)))
1352
1353
1354@register("return")
1355class Return(Unary):
1356    """
1357    AST node for a ``<?return?>`` tag.
1358    """
1359
1360    def _str(self, level):
1361        yield "return "
1362        yield from self.obj._str(level)
1363
1364    @handleeval
1365    def eval(self, vars):
1366        value = (yield from self.obj.eval(vars))
1367        raise ReturnException(value)
1368
1369
1370class Binary(AST):
1371    """
1372    Base class for all AST nodes implementing binary operators.
1373    """
1374
1375    fields = AST.fields.union({"obj1", "obj2"})
1376
1377    def __init__(self, location=None, obj1=None, obj2=None):
1378        super().__init__(location)
1379        self.obj1 = obj1
1380        self.obj2 = obj2
1381
1382    def __repr__(self):
1383        return "<{0.__class__.__module__}.{0.__class__.__qualname__} {0.obj1!r} {0.obj2!r} at {1:#x}>".format(self, id(self))
1384
1385    def _repr_pretty_(self, p, cycle):
1386        if cycle:
1387            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1388        else:
1389            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1390                p.breakable()
1391                p.pretty(self.obj1)
1392                p.breakable()
1393                p.pretty(self.obj2)
1394                p.breakable()
1395                p.text("at {:#x}".format(id(self)))
1396
1397    def ul4ondump(self, encoder):
1398        super().ul4ondump(encoder)
1399        encoder.dump(self.obj1)
1400        encoder.dump(self.obj2)
1401
1402    def ul4onload(self, decoder):
1403        super().ul4onload(decoder)
1404        self.obj1 = decoder.load()
1405        self.obj2 = decoder.load()
1406
1407    @handleeval
1408    def eval(self, vars):
1409        obj1 = (yield from self.obj1.eval(vars))
1410        obj2 = (yield from self.obj2.eval(vars))
1411        return self.evalfold(obj1, obj2)
1412
1413    @classmethod
1414    def make(cls, location, obj1, obj2):
1415        if isinstance(obj1, Const) and isinstance(obj2, Const):
1416            result = cls.evalfold(obj1.value, obj2.value)
1417            if not isinstance(result, Undefined):
1418                return Const(location, result)
1419        return cls(location, obj1, obj2)
1420
1421
1422@register("getitem")
1423class GetItem(Binary):
1424    """
1425    AST node for subscripting operator.
1426
1427    The object (which must be a list, string or dict) is loaded from the AST
1428    node :var:`obj1` and the index/key is loaded from the AST node :var:`obj2`.
1429    """
1430
1431    precedence = 9
1432    associative = False
1433
1434    @classmethod
1435    def evaluate(cls, obj1, obj2):
1436        return obj1[obj2]
1437
1438    def _str(self, level):
1439        yield from self.obj1._str(level)
1440        yield "["
1441        yield from self.obj2._str(level)
1442        yield "]"
1443
1444    @classmethod
1445    def evalfold(cls, obj1, obj2):
1446        try:
1447            return obj1[obj2]
1448        except KeyError:
1449            return UndefinedKey(obj2)
1450        except IndexError:
1451            return UndefinedIndex(obj2)
1452
1453
1454@register("eq")
1455class EQ(Binary):
1456    """
1457    AST node for the binary ``==`` comparison operator.
1458    """
1459
1460    precedence = 4
1461    associative = False
1462
1463    def _str(self, level):
1464        yield from self._formatop(self.obj1)
1465        yield " == "
1466        yield from self._formatop(self.obj2)
1467
1468    @classmethod
1469    def evalfold(cls, obj1, obj2):
1470        return obj1 == obj2
1471
1472
1473@register("ne")
1474class NE(Binary):
1475    """
1476    AST node for the binary ``!=`` comparison operator.
1477    """
1478
1479    precedence = 4
1480    associative = False
1481
1482    def _str(self, level):
1483        yield from self._formatop(self.obj1)
1484        yield " != "
1485        yield from self._formatop(self.obj2)
1486
1487    @classmethod
1488    def evalfold(cls, obj1, obj2):
1489        return obj1 != obj2
1490
1491
1492@register("lt")
1493class LT(Binary):
1494    """
1495    AST node for the binary ``<`` comparison operator.
1496    """
1497
1498    precedence = 4
1499    associative = False
1500
1501    def _str(self, level):
1502        yield from self._formatop(self.obj1)
1503        yield " < "
1504        yield from self._formatop(self.obj2)
1505
1506    @classmethod
1507    def evalfold(cls, obj1, obj2):
1508        return obj1 < obj2
1509
1510
1511@register("le")
1512class LE(Binary):
1513    """
1514    AST node for the binary ``<=`` comparison operator.
1515    """
1516
1517    precedence = 4
1518    associative = False
1519
1520    def _str(self, level):
1521        yield from self._formatop(self.obj1)
1522        yield " <= "
1523        yield from self._formatop(self.obj2)
1524
1525    @classmethod
1526    def evalfold(cls, obj1, obj2):
1527        return obj1 <= obj2
1528
1529
1530@register("gt")
1531class GT(Binary):
1532    """
1533    AST node for the binary ``>`` comparison operator.
1534    """
1535
1536    precedence = 4
1537    associative = False
1538
1539    def _str(self, level):
1540        yield from self._formatop(self.obj1)
1541        yield " > "
1542        yield from self._formatop(self.obj2)
1543
1544    @classmethod
1545    def evalfold(cls, obj1, obj2):
1546        return obj1 > obj2
1547
1548
1549@register("ge")
1550class GE(Binary):
1551    """
1552    AST node for the binary ``>=`` comparison operator.
1553    """
1554
1555    precedence = 4
1556    associative = False
1557
1558    def _str(self, level):
1559        yield from self._formatop(self.obj1)
1560        yield " >= "
1561        yield from self._formatop(self.obj2)
1562
1563    @classmethod
1564    def evalfold(cls, obj1, obj2):
1565        return obj1 >= obj2
1566
1567
1568@register("contains")
1569class Contains(Binary):
1570    """
1571    AST node for the binary containment testing operator.
1572
1573    The item/key object is loaded from the AST node :var:`obj1` and the container
1574    object (which must be a list, string or dict) is loaded from the AST node
1575    :var:`obj2`.
1576    """
1577
1578    precedence = 3
1579    associative = False
1580
1581    def _str(self, level):
1582        yield from self._formatop(self.obj1)
1583        yield " in "
1584        yield from self._formatop(self.obj2)
1585
1586    @classmethod
1587    def evalfold(cls, obj1, obj2):
1588        return obj1 in obj2
1589
1590
1591@register("notcontains")
1592class NotContains(Binary):
1593    """
1594    AST node for the inverted containment testing operator.
1595
1596    The item/key object is loaded from the AST node :var:`obj1` and the container
1597    object (which must be a list, string or dict) is loaded from the AST node
1598    :var:`obj2`.
1599    """
1600
1601    precedence = 3
1602    associative = False
1603
1604    def _str(self, level):
1605        yield from self._formatop(self.obj1)
1606        yield " not in "
1607        yield from self._formatop(self.obj2)
1608
1609    @classmethod
1610    def evalfold(cls, obj1, obj2):
1611        return obj1 not in obj2
1612
1613
1614@register("add")
1615class Add(Binary):
1616    """
1617    AST node for the binary addition operator.
1618    """
1619
1620    precedence = 5
1621
1622    def _str(self, level):
1623        yield from self._formatop(self.obj1)
1624        yield "+"
1625        yield from self._formatop(self.obj2)
1626
1627    @classmethod
1628    def evalfold(cls, obj1, obj2):
1629        return obj1 + obj2
1630
1631
1632@register("sub")
1633class Sub(Binary):
1634    """
1635    AST node for the binary substraction operator.
1636    """
1637
1638    precedence = 5
1639    associative = False
1640
1641    def _str(self, level):
1642        yield from self._formatop(self.obj1)
1643        yield "-"
1644        yield from self._formatop(self.obj2)
1645
1646    @classmethod
1647    def evalfold(cls, obj1, obj2):
1648        return obj1 - obj2
1649
1650
1651@register("mul")
1652class Mul(Binary):
1653    """
1654    AST node for the binary multiplication operator.
1655    """
1656
1657    precedence = 6
1658
1659    def _str(self, level):
1660        yield from self._formatop(self.obj1)
1661        yield "*"
1662        yield from self._formatop(self.obj2)
1663
1664    @classmethod
1665    def evalfold(cls, obj1, obj2):
1666        return obj1 * obj2
1667
1668
1669@register("floordiv")
1670class FloorDiv(Binary):
1671    """
1672    AST node for the binary truncating division operator.
1673    """
1674
1675    precedence = 6
1676    associative = False
1677
1678    def _str(self, level):
1679        yield from self._formatop(self.obj1)
1680        yield "//"
1681        yield from self._formatop(self.obj2)
1682
1683    @classmethod
1684    def evalfold(cls, obj1, obj2):
1685        return obj1 // obj2
1686
1687
1688@register("truediv")
1689class TrueDiv(Binary):
1690    """
1691    AST node for the binary true division operator.
1692    """
1693
1694    precedence = 6
1695    associative = False
1696
1697    def _str(self, level):
1698        yield from self._formatop(self.obj1)
1699        yield "/"
1700        yield from self._formatop(self.obj2)
1701
1702    @classmethod
1703    def evalfold(cls, obj1, obj2):
1704        return obj1 / obj2
1705
1706
1707@register("and")
1708class And(Binary):
1709    """
1710    AST node for the binary ``and`` operator.
1711    """
1712
1713    precedence = 1
1714
1715    def _str(self, level):
1716        yield from self._formatop(self.obj1)
1717        yield " and "
1718        yield from self._formatop(self.obj2)
1719
1720    @classmethod
1721    def evalfold(cls, obj1, obj2):
1722        # This is not called from ``eval``, as it doesn't short-circuit
1723        return obj1 and obj2
1724
1725    @handleeval
1726    def eval(self, vars):
1727        obj1 = (yield from self.obj1.eval(vars))
1728        if not obj1:
1729            return obj1
1730        return (yield from self.obj2.eval(vars))
1731
1732
1733
1734@register("or")
1735class Or(Binary):
1736    """
1737    AST node for the binary ``or`` operator.
1738    """
1739
1740    precedence = 0
1741
1742    def _str(self, level):
1743        yield from self._formatop(self.obj1)
1744        yield " or "
1745        yield from self._formatop(self.obj2)
1746
1747    @classmethod
1748    def evalfold(cls, obj1, obj2):
1749        # This is not called from ``eval``, as it doesn't short-circuit
1750        return obj1 or obj2
1751
1752    @handleeval
1753    def eval(self, vars):
1754        obj1 = (yield from self.obj1.eval(vars))
1755        if obj1:
1756            return obj1
1757        return (yield from self.obj2.eval(vars))
1758
1759
1760@register("mod")
1761class Mod(Binary):
1762    """
1763    AST node for the binary modulo operator.
1764    """
1765
1766    precedence = 6
1767    associative = False
1768
1769    def _str(self, level):
1770        yield from self._formatop(self.obj1)
1771        yield "%"
1772        yield from self._formatop(self.obj2)
1773
1774    @classmethod
1775    def evalfold(cls, obj1, obj2):
1776        return obj1 % obj2
1777
1778
1779class ChangeVar(AST):
1780    """
1781    Baseclass for all AST nodes that store or modify a variable.
1782
1783    The variable name is stored in the string :var:`varname` and the value that
1784    will be stored or be used to modify the stored value is loaded from the
1785    AST node :var:`value`.
1786    """
1787
1788    fields = AST.fields.union({"varname", "value"})
1789
1790    def __init__(self, location=None, varname=None, value=None):
1791        super().__init__(location)
1792        self.varname = varname
1793        self.value = value
1794
1795    def __repr__(self):
1796        return "<{0.__class__.__module__}.{0.__class__.__qualname__} varname={0.varname!r} value={0.value!r} at {1:#x}>".format(self, id(self))
1797
1798    def _repr_pretty_(self, p, cycle):
1799        if cycle:
1800            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1801        else:
1802            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1803                p.breakable()
1804                p.text("varname=")
1805                p.pretty(self.obj1)
1806                p.text("value=")
1807                p.breakable()
1808                p.pretty(self.obj2)
1809                p.breakable()
1810                p.text("at {:#x}".format(id(self)))
1811
1812    def ul4ondump(self, encoder):
1813        super().ul4ondump(encoder)
1814        encoder.dump(self.varname)
1815        encoder.dump(self.value)
1816
1817    def ul4onload(self, decoder):
1818        super().ul4onload(decoder)
1819        self.varname = decoder.load()
1820        self.value = decoder.load()
1821
1822
1823@register("storevar")
1824class StoreVar(ChangeVar):
1825    """
1826    AST node that stores a value into a variable.
1827    """
1828
1829    def _str(self, level):
1830        yield _formatnestednameul4(self.varname)
1831        yield " = "
1832        yield from self.value._str(level)
1833
1834    @handleeval
1835    def eval(self, vars):
1836        value = (yield from self.value.eval(vars))
1837        _unpackvar(vars, self.varname, value)
1838
1839
1840@register("addvar")
1841class AddVar(ChangeVar):
1842    """
1843    AST node that adds a value to a variable (i.e. the ``+=`` operator).
1844    """
1845
1846    def _str(self, level):
1847        yield _formatnestednameul4(self.varname)
1848        yield " += "
1849        yield from self.value._str(level)
1850
1851    @handleeval
1852    def eval(self, vars):
1853        value = (yield from self.value.eval(vars))
1854        vars[self.varname] += value
1855
1856
1857@register("subvar")
1858class SubVar(ChangeVar):
1859    """
1860    AST node that substracts a value from a variable (i.e. the ``-=`` operator).
1861    """
1862
1863    def _str(self, level):
1864        yield _formatnestednameul4(self.varname)
1865        yield " -= "
1866        yield from self.value._str(level)
1867
1868    @handleeval
1869    def eval(self, vars):
1870        value = (yield from self.value.eval(vars))
1871        vars[self.varname] -= value
1872
1873
1874@register("mulvar")
1875class MulVar(ChangeVar):
1876    """
1877    AST node that multiplies a variable by a value (i.e. the ``*=`` operator).
1878    """
1879
1880    def _str(self, level):
1881        yield _formatnestednameul4(self.varname)
1882        yield " *= "
1883        yield from self.value._str(level)
1884
1885    @handleeval
1886    def eval(self, vars):
1887        value = (yield from self.value.eval(vars))
1888        vars[self.varname] *= value
1889
1890
1891@register("floordivvar")
1892class FloorDivVar(ChangeVar):
1893    """
1894    AST node that divides a variable by a value (truncating to an integer value;
1895    i.e. the ``//=`` operator).
1896    """
1897
1898    def _str(self, level):
1899        yield _formatnestednameul4(self.varname)
1900        yield " //= "
1901        yield from self.value._str(level)
1902
1903    @handleeval
1904    def eval(self, vars):
1905        value = (yield from self.value.eval(vars))
1906        vars[self.varname] //= value
1907
1908
1909@register("truedivvar")
1910class TrueDivVar(ChangeVar):
1911    """
1912    AST node that divides a variable by a value (i.e. the ``/=`` operator).
1913    """
1914
1915    def _str(self, level):
1916        yield _formatnestednameul4(self.varname)
1917        yield " /= "
1918        yield from self.value._str(level)
1919
1920    @handleeval
1921    def eval(self, vars):
1922        value = (yield from self.value.eval(vars))
1923        vars[self.varname] /= value
1924
1925
1926@register("modvar")
1927class ModVar(ChangeVar):
1928    """
1929    AST node for the ``%=`` operator.
1930    """
1931
1932    def _str(self, level):
1933        yield _formatnestednameul4(self.varname)
1934        yield " %= "
1935        yield from self.value._str(level)
1936
1937    @handleeval
1938    def eval(self, vars):
1939        value = (yield from self.value.eval(vars))
1940        vars[self.varname] %= value
1941
1942
1943@register("callfunc")
1944class CallFunc(AST):
1945    """
1946    AST node for calling an function.
1947
1948    The object to be called is stored in the attribute :var:`obj`. The list of
1949    positional arguments is loaded from the list of AST nodes :var:`args`.
1950    Keyword arguments are in :var:`kwargs`. `var`:remargs` is the AST node
1951    for the ``*`` argument (and may by ``None`` if there is no ``*`` argument).
1952    `var`:remkwargs` is the AST node for the ``**`` argument (and may by ``None``
1953    if there is no ``**`` argument)
1954    """
1955
1956    precedence = 10
1957    associative = False
1958    fields = AST.fields.union({"obj", "args", "kwargs", "remargs", "remkwargs"})
1959
1960    def __init__(self, location=None, obj=None):
1961        super().__init__(location)
1962        self.obj = obj
1963        self.args = []
1964        self.kwargs = []
1965        self.remargs = None
1966        self.remkwargs = None
1967
1968    def __repr__(self):
1969        return "<{0.__class__.__module__}.{0.__class__.__qualname__} obj={0.obj!r}{1}{2}{3}{4} at {5:#x}>".format(
1970            self,
1971            "".join(" {!r}".format(arg) for arg in self.args),
1972            "".join(" {}={!r}".format(argname, argvalue) for (argname, argvalue) in self.kwargs),
1973            " *{!r}".format(self.remargs) if self.remargs is not None else "",
1974            " **{!r}".format(self.remkwargs) if self.remargs is not None else "",
1975            id(self))
1976
1977    def _repr_pretty_(self, p, cycle):
1978        if cycle:
1979            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
1980        else:
1981            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
1982                p.breakable()
1983                p.text("obj=")
1984                p.pretty(self.obj)
1985                for arg in self.args:
1986                    p.breakable()
1987                    p.pretty(arg)
1988                for (argname, arg) in self.kwargs:
1989                    p.breakable()
1990                    p.text("{}=".format(argname))
1991                    p.pretty(arg)
1992                if self.remargs is not None:
1993                    p.breakable()
1994                    p.text("*")
1995                    p.pretty(self.remargs)
1996                if self.remkwargs is not None:
1997                    p.breakable()
1998                    p.text("**")
1999                    p.pretty(self.remkwargs)
2000                p.breakable()
2001                p.text("at {:#x}".format(id(self)))
2002
2003    def _str(self, level):
2004        yield from self.obj._str(level)
2005        yield "("
2006        first = True
2007        for arg in self.args:
2008            if first:
2009                first = False
2010            else:
2011                yield ", "
2012            yield from arg._str(level)
2013        for (argname, argvalue) in self.kwargs:
2014            if first:
2015                first = False
2016            else:
2017                yield ", "
2018            yield argname
2019            yield "="
2020            yield from argvalue._str(level)
2021        if self.remargs is not None:
2022            if first:
2023                first = False
2024            else:
2025                yield ", "
2026            yield "*"
2027            yield from self.remargs._str(level)
2028        if self.remkwargs is not None:
2029            if first:
2030                first = False
2031            else:
2032                yield ", "
2033            yield "**"
2034            yield from self.remkwargs._str(level)
2035        yield ")"
2036
2037    @handleeval
2038    def eval(self, vars):
2039        obj = (yield from self.obj.eval(vars))
2040        args = []
2041        for arg in self.args:
2042            arg = (yield from arg.eval(vars))
2043            args.append(arg)
2044        kwargs = {}
2045        for (argname, arg) in self.kwargs:
2046            kwargs[argname] = (yield from arg.eval(vars))
2047        if self.remargs is not None:
2048            args.extend((yield from self.remargs.eval(vars)))
2049        if self.remkwargs is not None:
2050            kwargs.update((yield from self.remkwargs.eval(vars)))
2051        result = obj(*args, **kwargs)
2052        if isinstance(result, types.GeneratorType):
2053            return (yield from result)
2054        else:
2055            return result
2056
2057    def ul4ondump(self, encoder):
2058        super().ul4ondump(encoder)
2059        encoder.dump(self.obj)
2060        encoder.dump(self.args)
2061        encoder.dump(self.kwargs)
2062        encoder.dump(self.remargs)
2063        encoder.dump(self.remkwargs)
2064
2065    def ul4onload(self, decoder):
2066        super().ul4onload(decoder)
2067        self.obj = decoder.load()
2068        self.args = decoder.load()
2069        self.kwargs = [tuple(arg) for arg in decoder.load()]
2070        self.remargs = decoder.load()
2071        self.remkwargs = decoder.load()
2072
2073
2074@register("callmeth")
2075class CallMeth(AST):
2076    """
2077    AST node for calling a method.
2078
2079    The method name is stored in the string :var:`methname`. The object for which
2080    the method will be called is loaded from the AST node :var:`obj` and the list
2081    of arguments is loaded from the list of AST nodes :var:`args`. Keyword
2082    arguments are in :var:`kwargs`. `var`:remargs` is the AST node for the ``*``
2083    argument (and may by ``None`` if there is no ``*`` argument).
2084    `var`:remkwargs` is the AST node for the ``**`` argument (and may by ``None``
2085    if there is no ``**`` argument)
2086    """
2087
2088    precedence = 9
2089    associative = False
2090    fields = AST.fields.union({"obj", "methname", "args", "kwargs", "remargs", "remkwargs"})
2091
2092    def __init__(self, location=None, obj=None, methname=None):
2093        super().__init__(location)
2094        self.obj = obj
2095        self.methname = methname
2096        self.args = []
2097        self.kwargs = []
2098        self.remargs = None
2099        self.remkwargs = None
2100
2101    def __repr__(self):
2102        return "<{0.__class__.__module__}.{0.__class__.__qualname__} methname={0.methname!r} obj={0.obj!r}{1}{2}{3}{4} at {5:#x}>".format(
2103            self,
2104            "".join(" {!r}".format(arg) for arg in self.args),
2105            "".join(" {}={!r}".format(argname, argvalue) for (argname, argvalue) in self.kwargs),
2106            " *{!r}".format(self.remargs) if self.remargs is not None else "",
2107            " **{!r}".format(self.remkwargs) if self.remargs is not None else "",
2108            id(self))
2109
2110    def _repr_pretty_(self, p, cycle):
2111        if cycle:
2112            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
2113        else:
2114            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
2115                p.breakable()
2116                p.text("methname=")
2117                p.pretty(self.methname)
2118                p.breakable()
2119                p.text("obj=")
2120                p.pretty(self.obj)
2121                for arg in self.args:
2122                    p.breakable()
2123                    p.pretty(arg)
2124                for (argname, arg) in self.kwargs:
2125                    p.breakable()
2126                    p.text("{}=".format(argname))
2127                    p.pretty(arg)
2128                if self.remargs is not None:
2129                    p.breakable()
2130                    p.text("*")
2131                    p.pretty(self.remargs)
2132                if self.remkwargs is not None:
2133                    p.breakable()
2134                    p.text("**")
2135                    p.pretty(self.remkwargs)
2136                p.breakable()
2137                p.text("at {:#x}".format(id(self)))
2138
2139    def _str(self, level):
2140        yield from self._formatop(self.obj)
2141        yield "."
2142        yield self.methname
2143        yield "("
2144        first = True
2145        for arg in self.args:
2146            if first:
2147                first = False
2148            else:
2149                yield ", "
2150            yield from arg._str(level)
2151        for (argname, argvalue) in self.kwargs:
2152            if first:
2153                first = False
2154            else:
2155                yield ", "
2156            yield argname
2157            yield "="
2158            yield from argvalue._str(level)
2159        if self.remargs is not None:
2160            if first:
2161                first = False
2162            else:
2163                yield ", "
2164            yield "*"
2165            yield from self.remargs._str(level)
2166        if self.remkwargs is not None:
2167            if first:
2168                first = False
2169            else:
2170                yield ", "
2171            yield "**"
2172            yield from self.remkwargs._str(level)
2173        yield ")"
2174
2175    @handleeval
2176    def eval(self, vars):
2177        obj = (yield from self.obj.eval(vars))
2178        args = []
2179        for arg in self.args:
2180            arg = (yield from arg.eval(vars))
2181            args.append(arg)
2182        kwargs = {}
2183        for (argname, arg) in self.kwargs:
2184            kwargs[argname] = (yield from arg.eval(vars))
2185        if self.remargs is not None:
2186            args.extend((yield from self.remargs.eval(vars)))
2187        if self.remkwargs is not None:
2188            kwargs.update((yield from self.remkwargs.eval(vars)))
2189        result = self.methods[self.methname](obj, *args, **kwargs)
2190        if isinstance(result, types.GeneratorType):
2191            return (yield from result)
2192        else:
2193            return result
2194
2195    def ul4ondump(self, encoder):
2196        super().ul4ondump(encoder)
2197        encoder.dump(self.methname)
2198        encoder.dump(self.obj)
2199        encoder.dump(self.args)
2200        encoder.dump(self.kwargs)
2201        encoder.dump(self.remargs)
2202        encoder.dump(self.remkwargs)
2203
2204    def ul4onload(self, decoder):
2205        super().ul4onload(decoder)
2206        self.methname = decoder.load()
2207        self.obj = decoder.load()
2208        self.args = decoder.load()
2209        self.kwargs = [tuple(arg) for arg in decoder.load()]
2210        self.remargs = decoder.load()
2211        self.remkwargs = decoder.load()
2212
2213
2214@register("template")
2215class Template(Block):
2216    """
2217    A template object is normally created by passing the template source to the
2218    constructor. It can also be loaded from the compiled format via the class
2219    methods :meth:`load` (from a stream) or :meth:`loads` (from a string).
2220
2221    The compiled format can be generated with the methods :meth:`dump` (which
2222    dumps the format to a stream) or :meth:`dumps` (which returns a string with
2223    the compiled format).
2224
2225    Rendering the template can be done with the methods :meth:`render` (which
2226    is a generator) or :meth:`renders` (which returns a string).
2227
2228    A :class:`Template` object is itself an AST node. Evaluating it will store
2229    the template object under its name in the local variables.
2230
2231    A :class:`Template` can also be called as a function (returning the result
2232    of the first ``<?return?>`` tag encountered. In this case all output of the
2233    template will be ignored.
2234    """
2235    fields = Block.fields.union({"source", "name", "keepws", "startdelim", "enddelim"})
2236
2237    version = "24"
2238
2239    def __init__(self, source=None, name=None, keepws=True, startdelim="<?", enddelim="?>"):
2240        """
2241        Create a :class:`Template` object. If :var:`source` is ``None``, the
2242        :class:`Template` remains uninitialized, otherwise :var:`source` will be
2243        compiled (using :var:`startdelim` and :var:`enddelim` as the tag
2244        delimiters). :var:`name` is the name of the template. It will be used in
2245        exception messages and should be a valid Python identifier. If
2246        :var:`keepws` is false linefeeds and indentation will be ignored in the
2247        literal text in templates (i.e. the text between the tags). However
2248        trailing whitespace at the end of the line will be honored regardless of
2249        the value of :var:`keepws`. Output will always be ignored when calling
2250        a template as a function.
2251        """
2252        # ``location``/``endlocation`` will remain ``None`` for a top level template
2253        # For a subtemplate/subfunction ``location`` will be set to the location of the ``<?def?>`` tag in :meth:`_compile`
2254        # and ``endlocation`` will be the location of the ``<?end def?>`` tag
2255        super().__init__(None)
2256        self.keepws = keepws
2257        self.startdelim = startdelim
2258        self.enddelim = enddelim
2259        self.name = name
2260        self.source = None
2261
2262        # If we have source code compile it
2263        if source is not None:
2264            self._compile(source, name, startdelim, enddelim)
2265
2266    def __repr__(self):
2267        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} name={0.name!r} keepws={0.keepws!r}".format(self)
2268        if self.startdelim != "<?":
2269            s += " startdelim={0.startdelim!r}".format(self)
2270        if self.enddelim != "?>":
2271            s += " enddelim={0.enddelim!r}".format(self)
2272        if self.content:
2273            s + " ..."
2274        return s + " at {:#x}>".format(id(self))
2275
2276    def _str(self, level):
2277        yield "def "
2278        yield self.name if self.name is not None else "unnamed"
2279        yield ":\n"
2280        yield from super()._str(level+1)
2281
2282    def _repr_pretty_(self, p, cycle):
2283        if cycle:
2284            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
2285        else:
2286            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
2287                p.breakable()
2288                p.text("name=")
2289                p.pretty(self.name)
2290                p.breakable()
2291                p.text("keepws=")
2292                p.pretty(self.keepws)
2293                if self.startdelim != "<?":
2294                    p.breakable()
2295                    p.text("startdelim=")
2296                    p.pretty(self.startdelim)
2297                if self.enddelim != "?>":
2298                    p.breakable()
2299                    p.text("enddelim=")
2300                    p.pretty(self.enddelim)
2301                for node in self.content:
2302                    p.breakable()
2303                    p.pretty(node)
2304                p.breakable()
2305                p.text("at {:#x}".format(id(self)))
2306
2307    def ul4ondump(self, encoder):
2308        # Don't call ``super().ul4ondump()``, as we want the version to be first
2309        encoder.dump(self.version)
2310        encoder.dump(self.source)
2311        encoder.dump(self.name)
2312        encoder.dump(self.keepws)
2313        encoder.dump(self.startdelim)
2314        encoder.dump(self.enddelim)
2315        encoder.dump(self.location)
2316        encoder.dump(self.endlocation)
2317        encoder.dump(self.content)
2318
2319    def ul4onload(self, decoder):
2320        version = decoder.load()
2321        if version != self.version:
2322            raise ValueError("invalid version, expected {!r}, got {!r}".format(self.version, version))
2323        self.source = decoder.load()
2324        self.name = decoder.load()
2325        self.keepws = decoder.load()
2326        self.startdelim = decoder.load()
2327        self.enddelim = decoder.load()
2328        self.location = decoder.load()
2329        self.endlocation = decoder.load()
2330        self.content = decoder.load()
2331
2332    @classmethod
2333    def loads(cls, data):
2334        """
2335        The class method :meth:`loads` loads the template/function from string
2336        :var:`data`. :var:`data` must contain the template/function in compiled
2337        UL4ON format.
2338        """
2339        from ll import ul4on
2340        return ul4on.loads(data)
2341
2342    @classmethod
2343    def load(cls, stream):
2344        """
2345        The class method :meth:`load` loads the template/function from the stream
2346        :var:`stream`. The stream must contain the template/function in compiled
2347        UL4ON format.
2348        """
2349        from ll import ul4on
2350        return ul4on.load(stream)
2351
2352    def dump(self, stream):
2353        """
2354        :meth:`dump` dumps the template/function in compiled UL4ON format to the
2355        stream :var:`stream`.
2356        """
2357        from ll import ul4on
2358        ul4on.dump(self, stream)
2359
2360    def dumps(self):
2361        """
2362        :meth:`dumps` returns the template/function in compiled UL4ON format
2363        (as a string).
2364        """
2365        from ll import ul4on
2366        return ul4on.dumps(self)
2367
2368    def render(self, **vars):
2369        """
2370        Render the template iteratively (i.e. this is a generator).
2371        :var:`vars` contains the top level variables available to the
2372        template code.
2373        """
2374        yield from super().eval(vars) # Bypass ``self.eval()`` which simply stores the object as a local variable
2375
2376    def renders(self, **vars):
2377        """
2378        Render the template as a string. :var:`vars` contains the top level
2379        variables available to the template code.
2380        """
2381        return "".join(self.render(**vars))
2382
2383    def __call__(self, **vars):
2384        """
2385        Call the template as a function and return the resulting value.
2386        :var:`vars` contains the top level variables available to the template code.
2387        """
2388        try:
2389            for output in super().eval(vars): # Bypass ``self.eval()`` which simply stores the object as a local variable
2390                pass # Ignore all output
2391        except ReturnException as ex:
2392            return ex.value
2393
2394    def jssource(self):
2395        """
2396        Return the template as the source code of a Javascript function.
2397        """
2398        return "ul4.Template.loads({})".format(_asjson(self.dumps()))
2399
2400    def javasource(self):
2401        """
2402        Return the template as Java source code.
2403        """
2404        return "com.livinglogic.ul4.InterpretedTemplate.loads({})".format(misc.javaexpr(self.dumps()))
2405
2406    def _tokenize(self, source, startdelim, enddelim):
2407        """
2408        Tokenize the template/function source code :var:`source` into tags and
2409        non-tag text. :var:`startdelim` and :var:`enddelim` are used as the tag
2410        delimiters.
2411
2412        This is a generator which produces :class:`Location` objects for each tag
2413        or non-tag text. It will be called by :meth:`_compile` internally.
2414        """
2415        pattern = "{}(printx|print|code|for|if|elif|else|end|break|continue|def|return|note)(\s*((.|\\n)*?)\s*)?{}".format(re.escape(startdelim), re.escape(enddelim))
2416        pos = 0
2417        for match in re.finditer(pattern, source):
2418            if match.start() != pos:
2419                yield Location(self, source, None, pos, match.start(), pos, match.start())
2420            type = source[match.start(1):match.end(1)]
2421            if type != "note":
2422                yield Location(self, source, type, match.start(), match.end(), match.start(3), match.end(3))
2423            pos = match.end()
2424        end = len(source)
2425        if pos != end:
2426            yield Location(self, source, None, pos, end, pos, end)
2427
2428    def _parser(self, location, error):
2429        from ll import UL4Lexer, UL4Parser
2430        source = location.code
2431        if not source:
2432            raise ValueError(error)
2433        stream = antlr3.ANTLRStringStream(source)
2434        lexer = UL4Lexer.UL4Lexer(stream)
2435        lexer.location = location
2436        tokens = antlr3.CommonTokenStream(lexer)
2437        parser = UL4Parser.UL4Parser(tokens)
2438        parser.location = location
2439        return parser
2440
2441    def _compile(self, source, name, startdelim, enddelim):
2442        """
2443        Compile the template source code :var:`source` into an AST.
2444        :var:`startdelim` and :var:`enddelim` are used as the tag delimiters.
2445        """
2446        self.name = name
2447        self.startdelim = startdelim
2448        self.enddelim = enddelim
2449
2450        # This stack stores the nested for/if/elif/else/def blocks
2451        stack = [self]
2452
2453        self.source = source
2454
2455        if source is None:
2456            return
2457
2458        def parseexpr(location):
2459            return self._parser(location, "expression required").expression()
2460
2461        def parsestmt(location):
2462            return self._parser(location, "statement required").statement()
2463
2464        def parsefor(location):
2465            return self._parser(location, "loop expression required").for_()
2466
2467        for location in self._tokenize(source, startdelim, enddelim):
2468            try:
2469                if location.type is None:
2470                    stack[-1].append(Text(location))
2471                elif location.type == "print":
2472                    stack[-1].append(Print(location, parseexpr(location)))
2473                elif location.type == "printx":
2474                    stack[-1].append(PrintX(location, parseexpr(location)))
2475                elif location.type == "code":
2476                    stack[-1].append(parsestmt(location))
2477                elif location.type == "if":
2478                    block = IfElIfElse(location, parseexpr(location))
2479                    stack[-1].append(block)
2480                    stack.append(block)
2481                elif location.type == "elif":
2482                    if not isinstance(stack[-1], IfElIfElse):
2483                        raise BlockError("elif doesn't match and if")
2484                    elif isinstance(stack[-1].content[-1], Else):
2485                        raise BlockError("else already seen in if")
2486                    stack[-1].newblock(ElIf(location, parseexpr(location)))
2487                elif location.type == "else":
2488                    if not isinstance(stack[-1], IfElIfElse):
2489                        raise BlockError("else doesn't match any if")
2490                    elif isinstance(stack[-1].content[-1], Else):
2491                        raise BlockError("else already seen in if")
2492                    stack[-1].newblock(Else(location))
2493                elif location.type == "end":
2494                    if len(stack) <= 1:
2495                        raise BlockError("not in any block")
2496                    code = location.code
2497                    if code:
2498                        if code == "if":
2499                            if not isinstance(stack[-1], IfElIfElse):
2500                                raise BlockError("endif doesn't match any if")
2501                        elif code == "for":
2502                            if not isinstance(stack[-1], For):
2503                                raise BlockError("endfor doesn't match any for")
2504                        elif code == "def":
2505                            if not isinstance(stack[-1], Template):
2506                                raise BlockError("enddef doesn't match any def")
2507                        else:
2508                            raise BlockError("illegal end value {!r}".format(code))
2509                    last = stack.pop()
2510                    # Set ``endlocation`` of block
2511                    last.endlocation = location
2512                    if isinstance(last, IfElIfElse):
2513                        last.content[-1].endlocation = location
2514                elif location.type == "for":
2515                    block = parsefor(location)
2516                    stack[-1].append(block)
2517                    stack.append(block)
2518                elif location.type == "break":
2519                    for block in reversed(stack):
2520                        if isinstance(block, For):
2521                            break
2522                        elif isinstance(block, Template):
2523                            raise BlockError("break outside of for loop")
2524                    stack[-1].append(Break(location))
2525                elif location.type == "continue":
2526                    for block in reversed(stack):
2527                        if isinstance(block, For):
2528                            break
2529                        elif isinstance(block, Template):
2530                            raise BlockError("continue outside of for loop")
2531                    stack[-1].append(Continue(location))
2532                elif location.type == "def":
2533                    block = Template(None, location.code, self.keepws, self.startdelim, self.enddelim)
2534                    block.location = location # Set start ``location`` of sub template
2535                    block.source = self.source # The source of the top level template (so that the offsets in :class:`Location` are correct)
2536                    stack[-1].append(block)
2537                    stack.append(block)
2538                elif location.type == "return":
2539                    stack[-1].append(Return(location, parseexpr(location)))
2540                else: # Can't happen
2541                    raise ValueError("unknown tag {!r}".format(location.type))
2542            except Exception as exc:
2543                raise Error(location) from exc
2544        if len(stack) > 1:
2545            raise Error(stack[-1].location) from BlockError("block unclosed")
2546
2547    @handleeval
2548    def eval(self, vars):
2549        yield from ()
2550        vars[self.name] = TemplateClosure(self, vars)
2551
2552
2553###
2554### Functions & methods
2555###
2556
2557@AST.makefunction
2558def _print(*values):
2559    for (i, value) in enumerate(values):
2560        if i:
2561            yield " "
2562        yield _str(value)
2563
2564
2565@AST.makefunction
2566def _printx(*values):
2567    for (i, value) in enumerate(values):
2568        if i:
2569            yield " "
2570        yield _xmlescape(value)
2571
2572
2573@AST.makefunction
2574def _str(obj=""):
2575    if obj is None:
2576        return ""
2577    elif isinstance(obj, Undefined):
2578        return ""
2579    else:
2580        return str(obj)
2581
2582
2583@AST.makefunction
2584def _repr(obj):
2585    if isinstance(obj, str):
2586        return repr(obj)
2587    elif isinstance(obj, datetime.datetime):
2588        s = str(obj.isoformat())
2589        if s.endswith("T00:00:00"):
2590            s = s[:-9]
2591        return "@({})".format(s)
2592    elif isinstance(obj, datetime.date):
2593        return "@({})".format(obj.isoformat())
2594    elif isinstance(obj, datetime.timedelta):
2595        return repr(obj).partition(".")[-1]
2596    elif isinstance(obj, color.Color):
2597        if obj[3] == 0xff:
2598            s = "#{:02x}{:02x}{:02x}".format(obj[0], obj[1], obj[2])
2599            if s[1]==s[2] and s[3]==s[4] and s[5]==s[6]:
2600                return "#{}{}{}".format(s[1], s[3], s[5])
2601            return s
2602        else:
2603            s = "#{:02x}{:02x}{:02x}{:02x}".format(*obj)
2604            if s[1]==s[2] and s[3]==s[4] and s[5]==s[6] and s[7]==s[8]:
2605                return "#{}{}{}{}".format(s[1], s[3], s[5], s[7])
2606            return s
2607    elif isinstance(obj, collections.Sequence):
2608        return "[{}]".format(", ".join(_repr(item) for item in obj))
2609    elif isinstance(obj, collections.Mapping):
2610        return "{{{}}}".format(", ".join("{}: {}".format(_repr(key), _repr(value)) for (key, value) in obj.items()))
2611    else:
2612        return repr(obj)
2613
2614
2615@AST.makefunction
2616def _now():
2617    return datetime.datetime.now()
2618
2619
2620@AST.makefunction
2621def _utcnow():
2622    return datetime.datetime.utcnow()
2623
2624
2625@AST.makefunction
2626def _date(year, month, day, hour=0, minute=0, second=0, microsecond=0):
2627    return datetime.datetime(year, month, day, hour, minute, second, microsecond)
2628
2629
2630@AST.makefunction
2631def _timedelta(days=0, seconds=0, microseconds=0):
2632    return datetime.timedelta(days, seconds, microseconds)
2633
2634
2635@AST.makefunction
2636def _monthdelta(months=0):
2637    return misc.monthdelta(months)
2638
2639
2640@AST.makefunction
2641def _random():
2642    return random.random()
2643
2644
2645@AST.makefunction
2646def _xmlescape(obj):
2647    if obj is None:
2648        return ""
2649    elif isinstance(obj, Undefined):
2650        return ""
2651    else:
2652        return misc.xmlescape(str(obj))
2653
2654
2655@AST.makefunction
2656def _csv(obj):
2657    if obj is None:
2658        return ""
2659    elif isinstance(obj, Undefined):
2660        return ""
2661    elif not isinstance(obj, str):
2662        obj = _repr(obj)
2663    if any(c in obj for c in ',"\n'):
2664        return '"{}"'.format(obj.replace('"', '""'))
2665    return obj
2666
2667
2668@AST.makefunction
2669def _asjson(obj):
2670    if obj is None:
2671        return "null"
2672    elif isinstance(obj, Undefined):
2673        return "{}.undefined"
2674    if isinstance(obj, (bool, int, float, str)):
2675        return json.dumps(obj)
2676    elif isinstance(obj, datetime.datetime):
2677        return "new Date({}, {}, {}, {}, {}, {}, {})".format(obj.year, obj.month-1, obj.day, obj.hour, obj.minute, obj.second, obj.microsecond//1000)
2678    elif isinstance(obj, datetime.date):
2679        return "new Date({}, {}, {})".format(obj.year, obj.month-1, obj.day)
2680    elif isinstance(obj, datetime.timedelta):
2681        return "ul4.TimeDelta.create({}, {}, {})".format(obj.days, obj.seconds, obj.microseconds)
2682    elif isinstance(obj, misc.monthdelta):
2683        return "ul4.MonthDelta.create({})".format(obj.months)
2684    elif isinstance(obj, color.Color):
2685        return "ul4.Color.create({}, {}, {}, {})".format(*obj)
2686    elif isinstance(obj, collections.Mapping):
2687        return "{{{}}}".format(", ".join("{}: {}".format(_asjson(key), _asjson(value)) for (key, value) in obj.items()))
2688    elif isinstance(obj, collections.Sequence):
2689        return "[{}]".format(", ".join(_asjson(item) for item in obj))
2690    elif isinstance(obj, Template):
2691        return obj.jssource()
2692    else:
2693        raise TypeError("can't handle object of type {}".format(type(obj)))
2694
2695
2696@AST.makefunction
2697def _fromjson(string):
2698    from ll import ul4on
2699    return json.loads(string)
2700
2701
2702@AST.makefunction
2703def _asul4on(obj):
2704    from ll import ul4on
2705    return ul4on.dumps(obj)
2706
2707
2708@AST.makefunction
2709def _fromul4on(string):
2710    from ll import ul4on
2711    return ul4on.loads(string)
2712
2713
2714@AST.makefunction
2715def _int(obj=0, base=None):
2716    if base is None:
2717        return int(obj)
2718    else:
2719        return int(obj, base)
2720
2721
2722@AST.makefunction
2723def _float(obj=0.0):
2724    return float(obj)
2725
2726
2727@AST.makefunction
2728def _bool(obj=False):
2729    return bool(obj)
2730
2731
2732@AST.makefunction
2733def _len(sequence):
2734    return len(sequence)
2735
2736
2737@AST.makefunction
2738def _abs(number):
2739    return abs(number)
2740
2741
2742@AST.makefunction
2743def _any(iterable):
2744    return any(iterable)
2745
2746
2747@AST.makefunction
2748def _all(iterable):
2749    return all(iterable)
2750
2751
2752@AST.makefunction
2753def _enumerate(iterable, start=0):
2754    yield from ()
2755    return enumerate(iterable, start)
2756
2757
2758@AST.makefunction
2759def _enumfl(iterable, start=0):
2760    yield from ()
2761    def result(iterable):
2762        lastitem = None
2763        first = True
2764        i = start
2765        it = iter(iterable)
2766        try:
2767            item = next(it)
2768        except StopIteration:
2769            return
2770        while True:
2771            try:
2772                (lastitem, item) = (item, next(it))
2773            except StopIteration:
2774                yield (i, first, True, item) # Items haven't been swapped yet
2775                return
2776            else:
2777                yield (i, first, False, lastitem)
2778                first = False
2779            i += 1
2780    return result(iterable)
2781
2782
2783@AST.makefunction
2784def _isfirstlast(iterable):
2785    yield from ()
2786    def result(iterable):
2787        lastitem = None
2788        first = True
2789        it = iter(iterable)
2790        try:
2791            item = next(it)
2792        except StopIteration:
2793            return
2794        while True:
2795            try:
2796                (lastitem, item) = (item, next(it))
2797            except StopIteration:
2798                yield (first, True, item) # Items haven't been swapped yet
2799                return
2800            else:
2801                yield (first, False, lastitem)
2802                first = False
2803    return result(iterable)
2804
2805
2806@AST.makefunction
2807def _isfirst(iterable):
2808    yield from ()
2809    def result(iterable):
2810        first = True
2811        for item in iterable:
2812            yield (first, item)
2813            first = False
2814    return result(iterable)
2815
2816
2817@AST.makefunction
2818def _islast(iterable):
2819    yield from ()
2820    def result(iterable):
2821        lastitem = None
2822        it = iter(iterable)
2823        try:
2824            item = next(it)
2825        except StopIteration:
2826            return
2827        while True:
2828            try:
2829                (lastitem, item) = (item, next(it))
2830            except StopIteration:
2831                yield (True, item) # Items haven't been swapped yet
2832                return
2833            else:
2834                yield (False, lastitem)
2835    return result(iterable)
2836
2837
2838@AST.makefunction
2839def _isundefined(obj):
2840    return isinstance(obj, Undefined)
2841
2842
2843@AST.makefunction
2844def _isdefined(obj):
2845    return not isinstance(obj, Undefined)
2846
2847
2848@AST.makefunction
2849def _isnone(obj):
2850    return obj is None
2851
2852
2853@AST.makefunction
2854def _isstr(obj):
2855    return isinstance(obj, str)
2856
2857
2858@AST.makefunction
2859def _isint(obj):
2860    return isinstance(obj, int) and not isinstance(obj, bool)
2861
2862
2863@AST.makefunction
2864def _isfloat(obj):
2865    return isinstance(obj, float)
2866
2867
2868@AST.makefunction
2869def _isbool(obj):
2870    return isinstance(obj, bool)
2871
2872
2873@AST.makefunction
2874def _isdate(obj):
2875    return isinstance(obj, (datetime.datetime, datetime.date))
2876
2877
2878@AST.makefunction
2879def _istimedelta(obj):
2880    return isinstance(obj, datetime.timedelta)
2881
2882
2883@AST.makefunction
2884def _ismonthdelta(obj):
2885    return isinstance(obj, misc.monthdelta)
2886
2887
2888@AST.makefunction
2889def _islist(obj):
2890    return isinstance(obj, collections.Sequence) and not isinstance(obj, str) and not isinstance(obj, color.Color)
2891
2892
2893@AST.makefunction
2894def _isdict(obj):
2895    return isinstance(obj, collections.Mapping) and not isinstance(obj, Template)
2896
2897
2898@AST.makefunction
2899def _iscolor(obj):
2900    return isinstance(obj, color.Color)
2901
2902
2903@AST.makefunction
2904def _istemplate(obj):
2905    return isinstance(obj, (Template, TemplateClosure))
2906
2907
2908@AST.makefunction
2909def _isfunction(obj):
2910    return callable(obj)
2911
2912
2913@AST.makefunction
2914def _chr(i):
2915    return chr(i)
2916
2917
2918@AST.makefunction
2919def _ord(c):
2920    return ord(c)
2921
2922
2923@AST.makefunction
2924def _hex(number):
2925    return hex(number)
2926
2927
2928@AST.makefunction
2929def _oct(number):
2930    return oct(number)
2931
2932
2933@AST.makefunction
2934def _bin(number):
2935    return bin(number)
2936
2937
2938@AST.makefunction
2939def _min(*args):
2940    return min(*args)
2941
2942
2943@AST.makefunction
2944def _max(*args):
2945    return max(*args)
2946
2947
2948@AST.makefunction
2949def _sorted(iterable):
2950    return sorted(iterable)
2951
2952
2953@AST.makefunction
2954def _range(*args):
2955    return range(*args)
2956
2957
2958@AST.makefunction
2959def _type(obj):
2960    if obj is None:
2961        return "none"
2962    elif isinstance(obj, Undefined):
2963        return "undefined"
2964    elif isinstance(obj, str):
2965        return "str"
2966    elif isinstance(obj, bool):
2967        return "bool"
2968    elif isinstance(obj, int):
2969        return "int"
2970    elif isinstance(obj, float):
2971        return "float"
2972    elif isinstance(obj, (datetime.datetime, datetime.date)):
2973        return "date"
2974    elif isinstance(obj, datetime.timedelta):
2975        return "timedelta"
2976    elif isinstance(obj, misc.monthdelta):
2977        return "monthdelta"
2978    elif isinstance(obj, color.Color):
2979        return "color"
2980    elif isinstance(obj, (Template, TemplateClosure)):
2981        return "template"
2982    elif isinstance(obj, collections.Mapping):
2983        return "dict"
2984    elif isinstance(obj, color.Color):
2985        return "color"
2986    elif isinstance(obj, collections.Sequence):
2987        return "list"
2988    elif callable(obj):
2989        return "function"
2990    return None
2991
2992
2993@AST.makefunction
2994def _reversed(sequence):
2995    yield from ()
2996    return reversed(sequence)
2997
2998
2999@AST.makefunction
3000def _randrange(*args):
3001    return random.randrange(*args)
3002
3003
3004@AST.makefunction
3005def _randchoice(sequence):
3006    return random.choice(sequence)
3007
3008
3009@AST.makefunction
3010def _format(obj, fmt, lang=None):
3011    if isinstance(obj, (datetime.date, datetime.time, datetime.timedelta)):
3012        if lang is None:
3013            lang = "en"
3014        oldlocale = locale.getlocale()
3015        try:
3016            for candidate in (locale.normalize(lang), locale.normalize("en"), ""):
3017                try:
3018                    locale.setlocale(locale.LC_ALL, candidate)
3019                    return format(obj, fmt)
3020                except locale.Error:
3021                    if not candidate:
3022                        return format(obj, fmt)
3023        finally:
3024            try:
3025                locale.setlocale(locale.LC_ALL, oldlocale)
3026            except locale.Error:
3027                pass
3028    else:
3029        return format(obj, fmt)
3030
3031
3032@AST.makefunction
3033def _zip(*iterables):
3034    return zip(*iterables)
3035
3036
3037@AST.makefunction
3038def _urlquote(string):
3039    return urlparse.quote_plus(string)
3040
3041
3042@AST.makefunction
3043def _urlunquote(string):
3044    return urlparse.unquote_plus(string)
3045
3046
3047@AST.makefunction
3048def _rgb(r, g, b, a=1.0):
3049    return color.Color.fromrgb(r, g, b, a)
3050
3051
3052@AST.makefunction
3053def _hls(h, l, s, a=1.0):
3054    return color.Color.fromhls(h, l, s, a)
3055
3056
3057@AST.makefunction
3058def _hsv(h, s, v, a=1.0):
3059    return color.Color.fromhsv(h, s, v, a)
3060
3061
3062@AST.makemethod
3063def _split(obj, sep=None, count=None):
3064    return obj.split(sep, count if count is not None else -1)
3065
3066
3067@AST.makemethod
3068def _rsplit(obj, sep=None, count=None):
3069    return obj.rsplit(sep, count if count is not None else -1)
3070
3071
3072@AST.makemethod
3073def _strip(obj, chars=None):
3074    return obj.strip(chars)
3075
3076
3077@AST.makemethod
3078def _lstrip(obj, chars=None):
3079    return obj.lstrip(chars)
3080
3081
3082@AST.makemethod
3083def _rstrip(obj, chars=None):
3084    return obj.rstrip(chars)
3085
3086
3087@AST.makemethod
3088def _find(obj, sub, start=None, end=None):
3089    if isinstance(obj, str):
3090        return obj.find(sub, start, end)
3091    else:
3092        try:
3093            if end is None:
3094                if start is None:
3095                    return obj.index(sub)
3096                return obj.index(sub, start)
3097            return obj.index(sub, start, end)
3098        except ValueError:
3099            return -1
3100
3101
3102@AST.makemethod
3103def _rfind(obj, sub, start=None, end=None):
3104    if isinstance(obj, str):
3105        return obj.rfind(sub, start, end)
3106    else:
3107        for i in reversed(range(*slice(start, end).indices(len(obj)))):
3108            if obj[i] == sub:
3109                return i
3110        return -1
3111
3112
3113@AST.makemethod
3114def _startswith(obj, prefix):
3115    return obj.startswith(prefix)
3116
3117
3118@AST.makemethod
3119def _endswith(obj, suffix):
3120    return obj.endswith(suffix)
3121
3122
3123@AST.makemethod
3124def _upper(obj):
3125    return obj.upper()
3126
3127
3128@AST.makemethod
3129def _lower(obj):
3130    return obj.lower()
3131
3132
3133@AST.makemethod
3134def _capitalize(obj):
3135    return obj.capitalize()
3136
3137
3138@AST.makemethod
3139def _replace(obj, old, new, count=None):
3140    if count is None:
3141        return obj.replace(old, new)
3142    else:
3143        return obj.replace(old, new, count)
3144
3145
3146@AST.makemethod
3147def _r(obj):
3148    return obj.r()
3149
3150
3151@AST.makemethod
3152def _g(obj):
3153    return obj.g()
3154
3155
3156@AST.makemethod
3157def _b(obj):
3158    return obj.b()
3159
3160
3161@AST.makemethod
3162def _a(obj):
3163    return obj.a()
3164
3165
3166@AST.makemethod
3167def _hls(obj):
3168    return obj.hls()
3169
3170
3171@AST.makemethod
3172def _hlsa(obj):
3173    return obj.hlsa()
3174
3175
3176@AST.makemethod
3177def _hsv(obj):
3178    return obj.hsv()
3179
3180
3181@AST.makemethod
3182def _hsva(obj):
3183    return obj.hsva()
3184
3185
3186@AST.makemethod
3187def _lum(obj):
3188    return obj.lum()
3189
3190
3191@AST.makemethod
3192def _weekday(obj):
3193    return obj.weekday()
3194
3195
3196@AST.makemethod
3197def _week(obj, firstweekday=None):
3198    if firstweekday is None:
3199        firstweekday = 0
3200    else:
3201        firstweekday %= 7
3202    jan1 = obj.__class__(obj.year, 1, 1)
3203    yearday = (obj - jan1).days+7
3204    jan1weekday = jan1.weekday()
3205    while jan1weekday != firstweekday:
3206        yearday -= 1
3207        jan1weekday += 1
3208        if jan1weekday == 7:
3209            jan1weekday = 0
3210    return yearday//7
3211
3212
3213@AST.makemethod
3214def _items(obj):
3215    yield from ()
3216    return obj.items()
3217
3218
3219@AST.makemethod
3220def _values(obj):
3221    yield from ()
3222    return obj.values()
3223
3224
3225@AST.makemethod
3226def _join(obj, iterable):
3227    return obj.join(iterable)
3228
3229
3230@AST.makemethod
3231def _render(obj, **vars):
3232    yield from obj.render(**vars)
3233
3234
3235@AST.makemethod
3236def _renders(obj, **vars):
3237    return obj.renders(**vars)
3238
3239
3240@AST.makemethod
3241def _mimeformat(obj):
3242    weekdayname = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
3243    monthname = (None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
3244    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])
3245
3246
3247@AST.makemethod
3248def _isoformat(obj):
3249    result = obj.isoformat()
3250    suffix = "T00:00:00"
3251    if result.endswith(suffix):
3252        return result[:-len(suffix)]
3253    return result
3254
3255
3256@AST.makemethod
3257def _yearday(obj):
3258    return (obj - obj.__class__(obj.year, 1, 1)).days+1
3259
3260
3261@AST.makemethod
3262def _get(obj, key, default=None):
3263    return obj.get(key, default)
3264
3265
3266@AST.makemethod
3267def _withlum(obj, lum):
3268    return obj.withlum(lum)
3269
3270
3271@AST.makemethod
3272def _witha(obj, a):
3273    return obj.witha(a)
3274
3275
3276@AST.makemethod
3277def _day(obj):
3278    return obj.day
3279
3280
3281@AST.makemethod
3282def _month(obj):
3283    return obj.month
3284
3285
3286@AST.makemethod
3287def _year(obj):
3288    return obj.year
3289
3290
3291@AST.makemethod
3292def _hour(obj):
3293    return obj.hour
3294
3295
3296@AST.makemethod
3297def _minute(obj):
3298    return obj.minute
3299
3300
3301@AST.makemethod
3302def _second(obj):
3303    return obj.second
3304
3305
3306@AST.makemethod
3307def _microsecond(obj):
3308    return obj.microsecond
3309
3310
3311@AST.makemethod
3312def _days(obj):
3313    return obj.days
3314
3315
3316@AST.makemethod
3317def _seconds(obj):
3318    return obj.seconds
3319
3320
3321@AST.makemethod
3322def _microseconds(obj):
3323    return obj.microseconds
3324
3325
3326@AST.makemethod
3327def _months(obj):
3328    return obj.months
3329
3330
3331@AST.makemethod
3332def _append(obj, item):
3333    return obj.append(item)
3334
3335
3336@AST.makemethod
3337def _insert(obj, pos, item):
3338    return obj.insert(pos, item)
3339
3340
3341@AST.makemethod
3342def _pop(obj, pos=-1):
3343    return obj.pop(pos)
3344
3345
3346class TemplateClosure(Object):
3347    fields = {"location", "endlocation", "name", "source", "startdelim", "enddelim", "content"}
3348
3349    def __init__(self, template, vars):
3350        self.template = template
3351        # Freeze variables of the currently running templates/functions
3352        self.vars = vars.copy()
3353
3354    def render(self, **vars):
3355        return self.template.render(**collections.ChainMap(vars, self.vars))
3356
3357    def renders(self, **vars):
3358        return self.template.renders(**collections.ChainMap(vars, self.vars))
3359
3360    def __call__(self, **vars):
3361        return self.template(**collections.ChainMap(vars, self.vars))
3362
3363    def __getattr__(self, name):
3364        return getattr(self.template, name)
3365
3366    def __repr__(self):
3367        s = "<{0.__class__.__module__}.{0.__class__.__qualname__} name={0.name!r} keepws={0.keepws!r}".format(self)
3368        if self.startdelim != "<?":
3369            s += " startdelim={0.startdelim!r}".format(self)
3370        if self.enddelim != "?>":
3371            s += " enddelim={0.enddelim!r}".format(self)
3372        if self.content:
3373            s + " ..."
3374        return s + " at {:#x}>".format(id(self))
3375
3376    def _repr_pretty_(self, p, cycle):
3377        if cycle:
3378            p.text("<{0.__class__.__module__}.{0.__class__.__qualname__} ... at {1:#x}>".format(self, id(self)))
3379        else:
3380            with p.group(4, "<{0.__class__.__module__}.{0.__class__.__qualname__}".format(self), ">"):
3381                p.breakable()
3382                p.text("name=")
3383                p.pretty(self.name)
3384                p.breakable()
3385                p.text("keepws=")
3386                p.pretty(self.keepws)
3387                if self.startdelim != "<?":
3388                    p.breakable()
3389                    p.text("startdelim=")
3390                    p.pretty(self.startdelim)
3391                if self.enddelim != "?>":
3392                    p.breakable()
3393                    p.text("enddelim=")
3394                    p.pretty(self.enddelim)
3395                for node in self.content:
3396                    p.breakable()
3397                    p.pretty(node)
3398                p.breakable()
3399                p.text("at {:#x}".format(id(self)))
3400
3401
3402###
3403### Helper classes/functions used at runtime
3404###
3405
3406def _formatnestednameul4(name):
3407    if isinstance(name, str):
3408        return name
3409    elif len(name) == 1:
3410        return "({},)".format(_formatnestednameul4(name[0]))
3411    else:
3412        return "({})".format(", ".join(_formatnestednameul4(name) for name in name))
3413
3414
3415def _unpackvar(vars, name, value):
3416    if isinstance(name, str):
3417        vars[name] = value
3418    else:
3419        if len(name) > len(value):
3420            raise TypeError("too many values to unpack (expected {})".format(len(name)))
3421        elif len(name) < len(value):
3422            raise TypeError("need more than {} value{} to unpack)".format(len(values), "ss" if len(values) != 1 else ""))
3423        for (name, value) in zip(name, value):
3424            _unpackvar(vars, name, value)
Note: See TracBrowser for help on using the browser.