root/livinglogic.python.xist/docs/UL4.rst @ 3448:199c07ee0ba6

Revision 3448:199c07ee0ba6, 16.5 KB (checked in by Walter Doerwald <walter@…>, 11 years ago)

Update the UL4 howto to the new parameter passing method.

Line 
1:mod:`ll.ul4c` provides templating for XML/HTML as well as any other text-based
2format. A template defines placeholders for data output and basic logic (like
3loops and conditional blocks), that define how the final rendered output will
4look.
5
6:mod:`ll.ul4c` compiles a template to a bytecode format, which makes it possible
7to implement renderers for these templates in multiple programming languages.
8
9
10Embedding
11=========
12
13In the template source any text surrounded by ``<?`` and ``?>`` is a "template
14tag". The first word inside the tag is the tag type. It defines what the tag
15does. For example ``<?print foo?>`` is a print tag (it prints the value of the
16variable ``foo``). A complete example template looks like this::
17
18    <?if data?>
19    <ul>
20    <?for item in data?>
21    <li><?print xmlescape(item)?></li>
22    <?end for?>
23    </ul>
24    <?end if?>
25
26(For text formats where the delimiters ``<?`` and ``?>`` collide with elements
27that are used often or where using these delimiters is inconvenient it's
28possible to specify a different delimiter pair when compiling the template.)
29
30A complete Python program that compiles a template and renders it might look
31like this::
32
33    from ll import ul4c
34
35    code = u'''<?if data?>
36    <ul>
37    <?for item in data?>
38    <li><?print xmlescape(item)?></li>
39    <?end for?>
40    </ul>
41    <?end if?>'''
42
43    tmpl = ul4c.compile(code)
44
45    print tmpl.renders(data=[u"Python", u"Java", u"PHP"])
46
47The variables that should be available to the template code can be passed to the
48method :meth:`Template.renders` as keyword arguments. :meth:`renders` returns
49the final rendered output as a string. Alternatively the method :meth:`render`
50can be used, which is a generator and returns the output piecewise.
51
52
53Supported data types
54====================
55
56The following object types can be passed as variables to be used by the template
57code:
58
59    *   strings
60    *   integers
61    *   floats
62    *   date objects
63    *   The "null" value (``None``)
64    *   boolean values (``True`` and ``False``)
65    *   lists
66    *   dictionaries
67
68This is similar to what JSON_ supports (except for date objects).
69
70    .. _JSON: http://www.json.org/
71
72Note that depending on the implementation language of the renderer additional
73types might be supported, e.g. a Python renderer will probably support tuples
74and lists and anything supporting :meth:`__getitem__` (or :meth:`__iter__` when
75the list is used in a loop) for lists, Java might support anything implementing
76the ``List`` interface (or the ``Collection`` interface if the list is used in a
77loop).
78
79Objects the these types can either be passed to the template in the call to the
80render function, or the template can create objects of thoses types itself. The
81syntax for creating such a constant is very similar to Python's syntax.
82
83
84The "null" constant
85-------------------
86
87The "null" constant can be referred to via ``None``.
88
89
90Boolean constants
91-----------------
92
93The boolean constants can be referred to via ``True`` and ``False``.
94
95
96Integer constants
97-----------------
98
99Integer constants can be written in decimal, hexadecimal, octal and binary:
100``42``, ``0x2a``, ``0o52`` and ``0b101010`` all refer to the integer value 42.
101
102
103Float constants
104---------------
105
106Float constants must contain a decimal point or an exponential specifier,
107e.g. ``42.``, ``4e23``.
108
109
110String constants
111----------------
112
113Strings are delimited with single or double quotes and support all escape
114sequences that Python supports (except ``\N{}``). Strings constants are always
115unicode objects, so ``\uXXXX`` escaping is possible. Examples:
116
117    * ``"abc"`` and ``'abc'``;
118
119    *   ``"'"`` and ``'\''`` are single quotes;
120
121    *   ``'"'`` and ``"\""`` are double quotes;
122
123    *   ``"\n"`` is a line feed and ``"\t"`` is a tab;
124
125    *   ``"\x61"`` and ``"\u0061"`` are lowercase "a"s;
126
127
128Date constants
129--------------
130
131Date constants can be created like this:
132
133    *   ``2008-12-24T``
134
135    *   ``2008-12-24T12:34``
136
137    *   ``2008-12-24T12:34:56``
138
139    *   ``2008-12-24T12:34:56.987654``
140
141
142List constants
143--------------
144
145Lists can be created like this:
146
147    *   ``[]``
148
149    *   ``[1, 2, 3]``
150
151    *   ``[None, 42, "foo", [False, True]]``
152
153
154Dictionary constants
155--------------------
156
157Dictionaries can be created like this:
158
159    *   ``{}``
160
161    *   ``{1: 2, 3: 4}``
162
163    *   ``{"foo": 17, "bar": 23}``
164
165
166
167
168Template code
169=============
170
171The template code tries to mimic Python syntax as far as possible, but is
172limited to what is required for templates and does not allow executing arbitrary
173Python statements.
174
175:mod:`ll.ul4c` supports the following tag types:
176
177
178``print``
179---------
180
181The ``print`` tag outputs the value of a variable or any other expression. If
182the expression doesn't evaluate to a string it will be converted to a string
183first. The format of the string depends on the renderer, but should follow
184Python's ``unicode()`` output as much as possible (except that for ``None`` no
185output may be produced)::
186
187    <h1><?print person.lastname?>, <?print person.firstname?></h1>
188
189
190``for``
191-------
192
193The ``for`` tag can be used to loop over the items in a list, the characters in
194a string or the keys in a dictionary. The end of the loop body must be marked
195with an ``<?end for?>`` tag::
196
197    <ul>
198    <?for person in data.persons?>
199    <li><?print person.lastname?>, <?person.firstname?></li>
200    <?end for?>
201    </ul>
202
203In ``for`` loops tuple unpacking is supported for tuples of length 1 and 2, so
204you can do the following::
205
206    <?for (key, value) in data.items?>
207
208if ``items`` is an iterable containing lists with two elements.
209
210
211``if``
212------
213
214The ``if`` tag can be used to output a part of the template only when a
215condition is true. The end of the ``if`` block must be marked with an
216``<?end if?>`` tag. The truth value of an object is the same as in Python:
217
218    *   ``None`` is false.
219    *   The integer ``0`` and the float value ``0.0`` are false.
220    *   Empty strings, lists and dictionaries are false.
221    *   ``False`` is false.
222    *   Anything else is true.
223
224For example we can output the person list only if there are any persons::
225
226    <?if data.persons?>
227    <ul>
228    <?for person in data.persons?>
229    <li><?print person.lastname?>, <?person.firstname?></li>
230    <?end for?>
231    </ul>
232    <?end if?>
233
234``elif`` and ``else`` are supported too::
235
236    <?if data.persons?>
237    <ul>
238    <?for person in data.persons?>
239    <li><?print person.lastname?>, <?person.firstname?></li>
240    <?end for?>
241    </ul>
242    <?else?>
243    <p>No persons found!</p>
244    <?end if?>
245
246or::
247
248    <?if len(data.persons)==0?>
249    No persons found!
250    <?elif len(data.persons)==1?>
251    One person found!
252    <?else?>
253    <?print len(data.persons)?> persons found!
254    <?end if?>
255
256
257``code``
258--------
259
260The ``code`` tag can be used to define or modify variables. Apart from the
261assigment operator ``=``, the following augmented assignment operators are
262supported:
263
264    *   ``+=`` (adds a value to the variable)
265    *   ``-=`` (subtracts a value from the variable)
266    *   ``*=`` (multiplies the variable by a value)
267    *   ``/=`` (divides the variable by a value)
268    *   ``//=`` (divides the variable by a value, rounding down to the next
269        smallest integer)
270    *   ``&=`` (Does a modulo operation and replaces the variable value with the
271        result)
272
273For example the following template will output ``40``::
274
275    <?code x = 17?>
276    <?code x += 23?>
277    <?print x?>
278
279
280``render``
281----------
282
283The render tag allows one template to call other templates. The following Python
284code demonstrates this::
285
286    from ll import ul4c
287
288    # Template 1
289    source1 = u"""\
290    <?if data?>\
291    <ul>
292    <?for item in data?><?render itemtmpl(item)?><?end for?>\
293    </ul>
294    <?end if?>\
295    """
296
297    tmpl1 = ul4c.compile(source1)
298
299    # Template 2
300    source2 = u"<li><?print xmlescape(data)?></li>\n"
301
302    tmpl2 = ul4c.compile(source2)
303
304    # Data object for the outer template
305    data = [u"Python", u"Java", u"PHP"]
306
307    # Dictionary of subtemplates for the outer template
308    templates = dict(itemtmpl=tmpl2)
309
310    print tmpl1.renders(data, templates)
311
312This will output::
313
314    <ul>
315    <li>Python</li>
316    <li>Java</li>
317    <li>PHP</li>
318    </ul>
319
320I.e. a dictionary of templates can be passed to the :meth:`renders` method as
321a additional argument. The keys in this dictionary are the names of the
322templates, which can be used in the ``<?render?>`` tag.
323``<?render itemtmpl(item)?>`` renders the ``itemtmpl`` template and passed the
324``item`` variable as the data object. All templates available in the outer
325template will be available in the inner template too.
326
327
328Expressions
329-----------
330
331:mod:`ll.ul4c` supports many of the operators supported by Python. Getitem style
332element access is available, i.e. in the expression ``a[b]`` the following type
333combinations are supported:
334
335    *   string, integer: Returns the ``b``\th character from the string ``a``.
336        Note that negative ``b`` values are supported and are relative to the end,
337        so ``a[-1]`` is the last character.
338
339    *   list, integer: Returns the ``b``\th list entry of the list ``a``. Negative
340        ``b`` values are supported too.
341
342    *   dict, string: Return the value from the dictionary ``a`` corresponding to
343        the key ``b``. (Note that some implementations might support keys other
344        than strings too.)
345
346Slices are also supported (for list and string objects). As in Python one or
347both of the indexes may be missing to start at the first or end at the last
348character/item. Negative indexes are relative to the end. Indexes that are out
349of bounds are simply clipped:
350
351    *   ``<?print "Hello, World!"[7:-1]?>`` prints ``World``.
352
353    *   ``<?print "Hello, World!"[:-8]?>`` prints ``Hello``.
354
355The following binary operators are supported: ``+``, ``-``, ``*``, ``/`` (floor
356division), ``//`` (truncating division) and ``&`` (modulo).
357
358The usual boolean operators ``not``, ``and`` and ``or`` are supported. However
359``and`` and ``or`` don't short-circuit (but they always return one of the
360operands). For example, the following code will output the ``data.title``
361object if it's true, else ``data.id`` will be output::
362
363    <?print xmlescape(data.title or data.id)?>
364
365The two comparison operators ``==`` and ``!=`` are supported.
366
367Containment test via the ``in`` operator can be done, in the expression
368``a in b`` the following type combinations are supported:
369
370    *   string, string: Checks whether ``a`` is a substring of ``b``.
371    *   any object, list: Checks whether the object ``a`` is in the list ``b``
372        (comparison is done by value not by identity)
373    *   string, dict: Checks whether the key ``a`` is in the dictionary ``b``.
374        (Note that some implementations might support keys other than strings too.)
375
376The inverted containment test (via ``not in``) is available too.
377
378Attribute access in the template code maps the dictionary style getitem access
379in the data object::
380
381    from ll import ul4c
382    tmpl = ul4c.compile("<?print data.foo?>")
383    print tmpl.renders(dict(foo="bar"))
384
385However getitem style access in the template is still possible::
386
387    from ll import ul4c
388    tmpl = ul4c.compile("<?print data['foo']?>")
389    print tmpl.renders(dict(foo="bar"))
390
391
392Functions
393---------
394
395:mod:`ll.ul4c` supports a number of functions.
396
397
398``now``
399:::::::
400
401``now()`` returns the current date and time as a data object.
402
403
404``isnone``
405::::::::::
406
407``isnone(foo)`` returns ``True`` if ``foo`` is ``None``, else ``False`` is
408returned::
409
410    data is <?if isnone(data)?>None<?else?>something else<?end if?>!
411
412
413``isbool``
414::::::::::
415
416``isbool(foo)`` returns ``True`` if ``foo`` is ``True`` or ``False``, else
417``False`` is returned.
418
419
420``isint``
421:::::::::
422
423``isint(foo)`` returns ``True`` if ``foo`` is an integer object, else ``False``
424is returned.
425
426
427``isfloat``
428:::::::::::
429
430``isfloat(foo)`` returns ``True`` if ``foo`` is a float object, else ``False``
431is returned.
432
433
434``isstr``
435:::::::::
436
437``isstr(foo)`` returns ``True`` if ``foo`` is a string object, else ``False``
438is returned.
439
440
441``isdate``
442::::::::::
443
444``isdate(foo)`` returns ``True`` if ``foo`` is a date object, else ``False``
445is returned.
446
447
448``islist``
449::::::::::
450
451``islist(foo)`` returns ``True`` if ``foo`` is a list object, else ``False``
452is returned.
453
454
455``isdict``
456::::::::::::
457
458``isdict(foo)`` returns ``True`` if ``foo`` is a dictionary object, else
459``False`` is returned.
460
461
462``bool``
463::::::::
464
465``bool(foo)`` converts ``foo`` to an boolean. I.e. ``True`` or ``False`` is
466returned according to the truth value of ``foo``.
467
468
469``int``
470:::::::
471
472``int(foo)`` converts ``foo`` to an integer. ``foo`` can be a string, a float,
473a boolean or an integer.
474
475
476``str``
477:::::::
478
479``str(foo)`` converts ``foo`` to a string. If ``foo`` is ``None`` the result
480will be the empty string. For lists and dictionaries the exact format is
481undefined, but should follow Python's repr format.
482
483
484``repr``
485::::::::
486
487``repr(foo)`` converts ``foo`` to a string representation that is useful for
488debugging proposes. The output is a constant expression that could be used to
489recreate the object (except for list and dict, where ``repr`` follows the format
490of Python's :func:`repr` function).
491
492
493``len``
494:::::::
495
496``len(foo)`` returns the length of a string, or the number of items in a list
497or dictionary.
498
499
500``enumerate``
501:::::::::::::
502
503Enumerates the items of the argument (which must be iterable, i.e. a string,
504a list or dictionary). For example the following code::
505
506    <?for (i, c) in enumerate("foo")?><?print i?>=<?print c?>;<?end for?>
507
508prints::
509
510    0=f;1=o;2=o
511   
512
513``xmlescape``
514:::::::::::::
515
516``xmlescape`` takes a string as an argument. It returns a new string where the
517characters ``&``, ``<``, ``>``, ``'`` and ``"`` are replaced with the
518appropriate XML entity references. For example::
519
520    <?print xmlescape("<'foo' & 'bar'>")?>
521
522prints::
523
524    ``&lt;&#39;foo&#39; &amp; ;&#39;bar&#39&gt;``
525
526If the argument is not a string, it will be converted to a string first.
527
528
529``sorted``
530::::::::::
531
532``sorted`` returns a sorted list with the items from it's argument. For example::
533
534    <?for c in sorted('bar')?><?print c?><?end for?>
535
536prints::
537
538    abr
539
540Supported arguments are iterable objects, i.e. strings, lists and dictionaries.
541
542
543``chr``
544:::::::
545
546``chr(x)`` returns a one-character string with a character with the codepoint
547``x``. ``x`` must be an integer.
548
549
550``ord``
551:::::::
552
553The argument for ``ord`` must be a one-character string. ``ord`` returns the
554codepoint of that character as an integer.
555
556
557``hex``
558:::::::
559
560Return the hexadecimal representation of the integer argument (with a leading
561``0x``). For example ``<?print hex(42)?>`` outputs ``0x2a``.
562
563
564``oct``
565:::::::
566
567Return the octal representation of the integer argument (with a leading ``0o``).
568For example ``<?print oct(42)?>`` outputs ``0o52``.
569
570
571``bin``
572:::::::
573
574Return the binary representation of the integer argument (with a leading ``0b``).
575For example ``<?print bin(42)?>`` outputs ``0b101010``.
576
577
578``range``
579::::::::::
580
581``range`` returns an object that can be iterated and will produce consecutive
582integers up to the specified argument. With two arguments the first is the start
583value and the second is the stop value. With three arguments the third one is
584the step size (which can be negative).
585
586
587Methods
588-------
589
590Objects in :mod:`ll.ul4c` support some methods too (depending on the type of the
591object).
592
593
594``upper``
595:::::::::
596
597The ``upper`` method of strings returns an uppercase version of the string for
598which it's called::
599
600    <?print 'foo'.upper()?>
601
602prints::
603
604    FOO
605
606
607``lower``
608:::::::::
609
610The ``lower`` method of strings returns an lowercase version of the string for
611which it's called.
612
613
614``startswith``
615::::::::::::::
616
617``x.startswith(y)`` returns ``True`` if the string ``x`` starts with the string
618``y`` and ``False`` otherwise.
619
620
621``endswith``
622::::::::::::::
623
624``x.endswith(y)`` returns ``True`` if the string ``x`` ends with the string
625``y`` and ``False`` otherwise.
626
627
628``strip``
629:::::::::
630
631The string method ``strip`` returns a copy of the string with leading and
632trailing whitespace removed. If an argument ``chars`` is given and not ``None``,
633characters in ``chars`` will be removed instead.
634
635
636``lstrip``
637::::::::::
638
639The string method ``lstrip`` returns a copy of the string with leading
640whitespace removed. If an argument ``chars`` is given and not ``None``,
641characters in ``chars`` will be removed instead.
642
643
644``rstrip``
645::::::::::
646
647The string method ``rstrip`` returns a copy of the string with trailing
648whitespace removed. If an argument ``chars`` is given and not ``None``,
649characters in ``chars`` will be removed instead.
650
651
652``split``
653:::::::::
654The string method ``split`` splits the string into separate "words" and returns
655the resulting list. Without any arguments, the string is split on whitespace
656characters. With one argument the argument specifies the soprator to use. The
657second optional argument specifies the maximum number of splits to do.
658
659
660``rsplit``
661::::::::::
662The string method ``rsplit`` works like ``split``, except that splitting start
663from the end (which is only relevant when the maximum number of splits is
664given).
665
666
667``find``
668::::::::
669
670This string method search for a substring of the object for which it's called
671and returns the position of the first appearance of the substring or -1 if
672the string can't be found. For example ``"foobar".find("foo")`` returns 3.
673The optional second and third argument specify the start and end position for
674the search.
Note: See TracBrowser for help on using the browser.