root/livinglogic.python.xist/test/test_ul4.py @ 5343:8ea8a9784e51

Revision 5343:8ea8a9784e51, 120.6 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Allow multiple arguments in UL4 list methods append and insert. Add UL4 dict method update.

Line 
1#! /usr/bin/env/python
2# -*- coding: utf-8 -*-
3
4## Copyright 2009-2013 by LivingLogic AG, Bayreuth/Germany
5## Copyright 2009-2013 by Walter Dörwald
6##
7## All Rights Reserved
8##
9## See ll/xist/__init__.py for the license
10
11
12import sys, os, re, datetime, io, json, contextlib, tempfile, collections, shutil, subprocess
13
14import pytest
15
16from ll import ul4c, color, misc, ul4on
17from ll.xist.ns import html, ul4
18
19
20class PseudoDict(collections.Mapping):
21    def __init__(self, dict):
22        self.dict = dict
23
24    def __getitem__(self, key):
25        return self.dict[key]
26
27    def __iter__(self):
28        return iter(self.dict)
29
30    def __len__(self):
31        return len(self.dict)
32
33
34class PseudoList(collections.Sequence):
35    def __init__(self, list):
36        self.list = list
37
38    def __getitem__(self, index):
39        return self.list[index]
40
41    def __len__(self):
42        return len(self.list)
43
44
45def render_python(__, *, keepws=True, **variables):
46    """
47    Compile the template from the source ``__`` and render it with the variables ``variables``.
48    """
49    template = ul4c.Template(__, keepws=keepws)
50    f = sys._getframe(1)
51    print("Testing Python template ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
52    print(template)
53    print("with variables:")
54    print(repr(variables))
55    return template.renders(**variables)
56
57
58def render_python_dumps(__, *, keepws=True, **variables):
59    """
60    Compile the template from the source ``__``, create a string dump from it,
61    recreate the template from the dump string and render it with the variables
62    ``variables``.
63    """
64    template = ul4c.Template(__, keepws=keepws)
65    template = ul4c.Template.loads(template.dumps()) # Recreate the template from the binary dump
66    f = sys._getframe(1)
67    print("Testing Python template loaded from string ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
68    print(template)
69    print("with variables:")
70    print(repr(variables))
71    return template.renders(**variables)
72
73
74def render_python_dump(__, *, keepws=True, **variables):
75    """
76    Compile the template from the source ``__``, dump it to a stream, recreate
77    the template from the dump and render it with the variables ``variables``.
78    """
79    template = ul4c.Template(__, keepws=keepws)
80    stream = io.StringIO()
81    template.dump(stream)
82    stream.seek(0)
83    f = sys._getframe(1)
84    template = ul4c.Template.load(stream) # Recreate the template from the stream
85    print("Testing Python template loaded from stream ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
86    print(template)
87    print("with variables:")
88    print(repr(variables))
89    return template.renders(**variables)
90
91
92def render_js(__, *, keepws=True, **variables):
93    """
94    Compile the template from the source ``__``, and generate Javascript source
95    from it that renders the template with the variables ``variables``.
96
97    (this requires an installed ``d8`` shell from V8 (http://code.google.com/p/v8/))
98    """
99    template = ul4c.Template(__, keepws=keepws)
100    js = template.jssource()
101    js = "template = {};\ndata = {};\nprint(template.renders(data));\n".format(js, ul4c._asjson(variables))
102    f = sys._getframe(1)
103    print("Testing Javascript template compiled by Python ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
104    print(js)
105    with tempfile.NamedTemporaryFile(mode="wb", suffix=".js") as f:
106        f.write(js.encode("utf-8"))
107        f.flush()
108        dir = os.path.expanduser("~/checkouts/LivingLogic.Javascript.ul4")
109        proc = subprocess.Popen("d8 {dir}/ul4on.js {dir}/ul4.js {fn}".format(dir=dir, fn=f.name), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
110        (stdout, stderr) = proc.communicate()
111    stdout = stdout.decode("utf-8")
112    stderr = stderr.decode("utf-8")
113    # Check if we have an exception
114    if proc.returncode:
115        print(stdout, file=sys.stdout)
116        print(stderr, file=sys.stderr)
117        raise RuntimeError((stderr or stdout).splitlines()[0])
118    return stdout[:-1] # Drop the "\n"
119
120
121def render_php(__, **variables):
122    template = ul4c.Template(__)
123    php = r"""<?php
124    include_once 'com/livinglogic/ul4/ul4.php';
125    $template = \com\livinglogic\ul4\InterpretedTemplate::loads({});
126    $variables = {};
127    print $template->renders($variables);
128    ?>""".format(phpexpr(template.dumps()), phpexpr(variables))
129    f = sys._getframe(1)
130    print("Testing PHP template compiled by Python ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
131    print(php)
132    with tempfile.NamedTemporaryFile(mode="wb", suffix=".php") as f:
133        f.write(php.encode("utf-8"))
134        f.flush()
135        dir = os.path.expanduser("~/checkouts/LivingLogic.PHP.ul4")
136        # dir = os.path.expanduser("~/eclipse/workspace/LivingLogic.PHP.ul4")
137        proc = subprocess.Popen("php -n -d include_path={dir} -d date.timezone=Europe/Berlin {fn}".format(dir=dir, fn=f.name), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
138        (stdout, stderr) = proc.communicate()
139    stdout = stdout.decode("utf-8")
140    stderr = stderr.decode("utf-8")
141    # Check if we have an exception
142    if proc.returncode:
143        print(stdout, file=sys.stdout)
144        print(stderr, file=sys.stderr)
145        raise RuntimeError((stderr.strip() or stdout.strip()).splitlines()[0])
146    return stdout
147
148
149def phpexpr(obj):
150    if obj is None:
151        return "null"
152    elif isinstance(obj, bool):
153        return "true" if obj else "false"
154    elif isinstance(obj, int):
155        return str(obj)
156    elif isinstance(obj, float):
157        return str(obj)
158    elif isinstance(obj, str):
159        v = ['"']
160        for c in obj:
161            if c == '\n':
162                c = '\\n'
163            elif c == '\t':
164                c = '\\t'
165            elif c == '"':
166                c = '\\"'
167            elif ord(c) < 32:
168                c = '\\x{:02x}'.format(ord(c))
169            v.append(c)
170        v.append('"')
171        return "".join(v)
172    elif isinstance(obj, datetime.datetime):
173        return r"\com\livinglogic\ul4\Utils::date({}, {}, {}, {}, {}, {}, {})".format(obj.year, obj.month, obj.day, obj.hour, obj.minute, obj.second, obj.microsecond)
174    elif isinstance(obj, datetime.date):
175        return r"\com\livinglogic\ul4\Utils::date({}, {}, {})".format(obj.year, obj.month, obj.day)
176    elif isinstance(obj, datetime.timedelta):
177        return r"new \com\livinglogic\ul4\TimeDelta({}, {}, {})".format(obj.days, obj.seconds, obj.microseconds)
178    elif isinstance(obj, misc.monthdelta):
179        return r"new \com\livinglogic\ul4\MonthDelta({})".format(obj.months)
180    elif isinstance(obj, color.Color):
181        return r"new \com\livinglogic\ul4\Color({}, {}, {}, {})".format(obj.r(), obj.g(), obj.b(), obj.a())
182    elif isinstance(obj, ul4c.Template):
183        return r"\com\livinglogic\ul4\InterpretedTemplate::loads({})".format(phpexpr(obj.dumps()))
184    elif isinstance(obj, collections.Mapping):
185        return "array({})".format(", ".join("{} => {}".format(phpexpr(key), phpexpr(value)) for (key, value) in obj.items()))
186    elif isinstance(obj, collections.Sequence):
187        return "array({})".format(", ".join(phpexpr(item) for item in obj))
188    else:
189        raise ValueError("Can't convert {!r} to PHP".format(obj))
190
191
192def java_findexception(output):
193    lines = output.splitlines()
194    msg = None
195    for line in lines:
196        prefix1 = 'Exception in thread "main"'
197        prefix2 = "Caused by:"
198        if line.startswith(prefix1):
199            msg = line[len(prefix1):].strip()
200        elif line.startswith(prefix2):
201            msg = line[len(prefix2):].strip()
202    if msg is not None:
203        print(output, file=sys.stderr)
204        raise RuntimeError(msg)
205
206
207def java_formatsource(string):
208    """
209    Reindents the Java source.
210    """
211    indent = 0
212    newlines = []
213    for line in string.strip().splitlines(False):
214        line = line.strip()
215        if line in {"}", ")", "};", "},", ");", "),"}:
216            indent -= 1
217        if line:
218            newlines.append(indent*"\t" + line + "\n")
219        if line == "{" or line.endswith("("):
220            indent += 1
221    return "".join(newlines)
222
223
224def java_runsource(source):
225    """
226    Compile the Java source :var:`source`, run it and return the output
227    """
228    maincodetemplate = """
229    public class UL4Test
230    {
231        @SuppressWarnings("unchecked")
232        public static void main(String[] args) throws java.io.IOException, java.io.UnsupportedEncodingException, org.antlr.runtime.RecognitionException
233        {
234            %(source)s
235        }
236    }
237    """
238
239    tempdir = tempfile.mkdtemp()
240    try:
241        source = maincodetemplate % dict(source=source)
242        source = java_formatsource(source)
243        print(source)
244        with open(os.path.join(tempdir, "UL4Test.java"), "wb") as f:
245            f.write(source.encode("utf-8"))
246        proc = subprocess.Popen("cd {}; javac -encoding utf-8 UL4Test.java".format(tempdir), stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
247        (stdout, stderr) = proc.communicate()
248        if proc.returncode:
249            stderr = stderr.decode("utf-8")
250            print(stderr, file=sys.stderr)
251            raise RuntimeError(stderr.splitlines()[0])
252        proc = subprocess.Popen("cd {}; java UL4Test".format(tempdir), stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
253        (stdout, stderr) = proc.communicate()
254        # Check if we have an exception
255        java_findexception(stderr.decode("utf-8"))
256    finally:
257        shutil.rmtree(tempdir)
258    if stderr:
259        print(stderr, file=sys.stderr)
260    return stdout.decode("utf-8")
261
262
263
264def render_java_interpretedtemplate_by_python(__, *, keepws=True, **variables):
265    """
266    Compile the template from the source ``__``, and generate Java source that
267    recreates the template from the Python generated dump and renders the
268    template with the variables ``variables``.
269
270    (this requires an installed Java compiler and the Java UL4 jar)
271    """
272
273    codetemplate = """
274    com.livinglogic.ul4.InterpretedTemplate template = %(template)s;
275    java.util.Map<String, Object> variables = %(variables)s;
276    String output = template.renders(variables);
277    // We can't use ``System.out.print`` here, because this gives us no control over the encoding
278    // Use ``System.out.write`` to make sure the output is in UTF-8
279    byte[] outputBytes = output.getBytes("utf-8");
280    System.out.write(outputBytes, 0, outputBytes.length);
281    """
282
283    f = sys._getframe(1)
284    print("Testing Java InterpretedTemplate (compiled by Python) ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
285    templatesource = ul4c.Template(__, keepws=keepws).javasource()
286    java = codetemplate % dict(variables=misc.javaexpr(variables), template=templatesource)
287    return java_runsource(java)
288
289
290def render_java_interpretedtemplate_by_java(__, keepws=True, **variables):
291    """
292    Generate Java source that compiles the template source ``__`` and renders the
293    template with the variables ``variables``.
294
295    (this requires an installed Java compiler and the Java UL4 jar)
296    """
297
298    codetemplate = """
299    com.livinglogic.ul4.InterpretedTemplate template = new com.livinglogic.ul4.InterpretedTemplate(%(source)s, %(keepws)s);
300    java.util.Map<String, Object> variables = %(variables)s;
301    String output = template.renders(variables);
302    // We can't use ``System.out.print`` here, because this gives us no control over the encoding
303    // Use ``System.out.write`` to make sure the output is in UTF-8
304    byte[] outputBytes = output.getBytes("utf-8");
305    System.out.write(outputBytes, 0, outputBytes.length);
306    """
307
308    f = sys._getframe(1)
309    print("Testing Java InterpretedTemplate (compiled by Java) ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
310    java = codetemplate % dict(source=misc.javaexpr(__), variables=misc.javaexpr(variables), keepws=misc.javaexpr(keepws))
311    return java_runsource(java)
312
313
314def call_python(__, *, keepws=True, **variables):
315    """
316    Compile the template from the source ``__``, call it as a function with the variables ``variables`` and return the result.
317    """
318    template = ul4c.Template(__, keepws=keepws)
319    f = sys._getframe(1)
320    print("Testing Python template ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
321    print(template)
322    print("with variables:")
323    print(repr(variables))
324    return template(**variables)
325
326
327def call_python_dumps(__, *, keepws=True, **variables):
328    """
329    Compile the template from the source ``__``, create a string dump from it,
330    recreate the template from the dump string, call it as a function with the
331    variables ``variables`` and return the result.
332    """
333    template = ul4c.Template(__, keepws=keepws)
334    template = ul4c.Template.loads(template.dumps()) # Recreate the template from the binary dump
335    f = sys._getframe(1)
336    print("Testing Python template loaded from string ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
337    print(template)
338    print("with variables:")
339    print(repr(variables))
340    return template(**variables)
341
342
343def call_python_dump(__, *, keepws=True, **variables):
344    """
345    Compile the template from the source ``__``, dump it to a stream, recreate
346    the template from the dump, call it as a function with the variables
347    ``variables`` and return the result.
348    """
349    template = ul4c.Template(__, keepws=keepws)
350    stream = io.StringIO()
351    template.dump(stream)
352    stream.seek(0)
353    f = sys._getframe(1)
354    template = ul4c.Template.load(stream) # Recreate the template from the stream
355    print("Testing Python template loaded from stream ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
356    print(template)
357    print("with variables:")
358    print(repr(variables))
359    return template(**variables)
360
361
362def call_js(__, *, keepws=True, **variables):
363    """
364    Compile the template from the source ``__``, and generate Javascript source
365    from it and call it as a function with the variables ``variables``.
366
367    (this requires an installed ``d8`` shell from V8 (http://code.google.com/p/v8/))
368    """
369    template = ul4c.Template(__, keepws=keepws)
370    js = template.jssource()
371    js = "template = {};\ndata = {};\nprint(ul4on.dumps(template.call(data)));\n".format(js, ul4c._asjson(variables))
372    f = sys._getframe(1)
373    print("Testing Javascript template compiled by Python ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
374    print(js)
375    with tempfile.NamedTemporaryFile(mode="wb", suffix=".js") as f:
376        f.write(js.encode("utf-8"))
377        f.flush()
378        dir = os.path.expanduser("~/checkouts/LivingLogic.Javascript.ul4")
379        proc = subprocess.Popen("d8 {dir}/ul4on.js {dir}/ul4.js {fn}".format(dir=dir, fn=f.name), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
380        (stdout, stderr) = proc.communicate()
381    stdout = stdout.decode("utf-8")
382    stderr = stderr.decode("utf-8")
383    # Check if we have an exception
384    if proc.returncode:
385        print(stdout, file=sys.stdout)
386        print(stderr, file=sys.stderr)
387        raise RuntimeError((stderr or stdout).splitlines()[0])
388    return ul4on.loads(stdout)
389
390
391def call_java_interpretedtemplate_by_python(__, *, keepws=True, **variables):
392    """
393    Compile the function from the source ``__``, and generate Java source that
394    recreates the function from the Python generated dump and executes the
395    function with the variables ``variables``.
396
397    (this requires an installed Java compiler and the Java UL4 jar)
398    """
399
400    codetemplate = """
401    com.livinglogic.ul4.InterpretedFunction function = %(function)s;
402    java.util.Map<String, Object> variables = %(variables)s;
403    Object output = function.call(variables);
404    // We can't use ``System.out.print`` here, because this gives us no control over the encoding
405    // Use ``System.out.write`` to make sure the output is in UTF-8
406    byte[] outputBytes = com.livinglogic.ul4on.Utils.dumps(output).getBytes("utf-8");
407    System.out.write(outputBytes, 0, outputBytes.length);
408    """
409
410    f = sys._getframe(1)
411    print("Testing Java InterpretedFunction (compiled by Python) ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
412    functionsource = ul4c.Function(__, keepws=keepws).javasource()
413    java = codetemplate % dict(variables=misc.javaexpr(variables), function=functionsource)
414    return ul4on.loads(java_runsource(java))
415
416
417def call_java_interpretedtemplate_by_java(__, keepws=True, **variables):
418    """
419    Generate Java source that compiles the function source ``__`` and executes the
420    function with the variables ``variables``.
421
422    (this requires an installed Java compiler and the Java UL4 jar)
423    """
424
425    codetemplate = """
426    com.livinglogic.ul4.InterpretedFunction function = new com.livinglogic.ul4.InterpretedFunction(%(source)s, %(keepws)s);
427    java.util.Map<String, Object> variables = %(variables)s;
428    Object output = function.call(variables);
429    // We can't use ``System.out.print`` here, because this gives us no control over the encoding
430    // Use ``System.out.write`` to make sure the output is in UTF-8
431    byte[] outputBytes = com.livinglogic.ul4on.Utils.dumps(output).getBytes("utf-8");
432    System.out.write(outputBytes, 0, outputBytes.length);
433    """
434
435    f = sys._getframe(1)
436    print("Testing Java InterpretedFunction (compiled by Java) ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
437    java = codetemplate % dict(source=misc.javaexpr(__), variables=misc.javaexpr(variables), keepws=misc.javaexpr(keepws))
438    return ul4on.loads(java_runsource(java))
439
440
441all_renderers = [
442    ("python", render_python),
443    ("python_dumps", render_python_dumps),
444    ("python_dump", render_python_dump),
445    # ("js", render_js),
446    # ("php", render_php),
447    # ("java_interpreted_by_python", render_java_interpretedtemplate_by_python),
448    # ("java_interpreted_by_java", render_java_interpretedtemplate_by_java),
449]
450
451
452all_callers = [
453    ("python", call_python),
454    ("python_dumps", call_python_dumps),
455    ("python_dump", call_python_dump),
456    # ("js", call_js),
457    # ("php", call_php),
458    # ("java_interpreted_by_python", call_java_interpretedtemplate_by_python),
459    # ("java_interpreted_by_java", call_java_interpretedtemplate_by_java),
460]
461
462
463def pytest_generate_tests(metafunc):
464    if "r" in metafunc.fixturenames:
465        metafunc.parametrize("r", [r for (id, r) in all_renderers], ids=[id for (id, r) in all_renderers])
466    if "c" in metafunc.fixturenames:
467        metafunc.parametrize("c", [c for (id, c) in all_callers], ids=[id for (id, c) in all_callers])
468
469
470argumentmismatchmessage = [
471    # Python argument mismatch exception messages
472    "takes exactly \\d+ (positional )?arguments?", # < 3.3
473    "got an unexpected keyword argument",
474    "expected \\d+ arguments?",
475    "Required argument .* not found",
476    "takes exactly (one|\\d+) arguments?",
477    "expected at least \\d+ arguments", # < 3.3
478    "takes at most \\d+ (positional )?arguments?",
479    "takes at least \\d+ argument", #  < 3.3
480    "takes no arguments",
481    "expected at least \\d+ arguments?",
482    "expected at most \\d+ arguments?, got \\d+",
483    "missing \\d+ required positional arguments?", # 3.3
484    "takes \\d+ positional arguments? but \\d+ (was|were) given", # 3.3
485    "takes from \\d+ to \\d+ positional arguments but \\d+ (was|were) given", # 3.3
486    # Javascript argument mismatch exception messages
487    "requires (at least \\d+|\\d+(-\\d+)?) arguments?, \\d+ given",
488    "required \\w+\\(\\) argument missing",
489    # Java exception messages for argument mismatches
490    "required \\w+\\(\\) argument \"\\w+\" \\(position \\d+\\) missing",
491    "\\w+\\(\\) doesn't support an argument named \"\\w+\"",
492    "\\w+\\(\\) doesn't support keyword arguments",
493    "expects (at least \\d+|at most \\d+ positional|exactly \\d+|\\d+-\\d+) arguments?, \\d+ given",
494]
495argumentmismatchmessage = "({})".format("|".join(argumentmismatchmessage))
496
497
498class raises(object):
499    def __init__(self, msg):
500        self.msg = re.compile(msg)
501
502    def exceptionchain(self, exc):
503        while exc is not None:
504            yield exc
505            exc = exc.__cause__
506
507    def __enter__(self):
508        pass
509
510    def __exit__(self, type, value, traceback):
511        if value is None:
512            pytest.fail("failed to raise exception")
513        # Check that any exception in the ``__cause__`` chain of the raised one matches a regexp
514        exceptionmsgs = [str(exc) for exc in self.exceptionchain(value)]
515        assert any(self.msg.search(msg) is not None for msg in exceptionmsgs)
516        return True # Don't propagate exception
517
518
519@pytest.mark.ul4
520def test_text(r):
521    assert 'gurk' == r('gurk')
522    assert 'g\xfcrk' ==  r('g\xfcrk')
523    assert 'gurk' == r('gurk', keepws=False)
524    assert 'g\tu rk' == r('g\t\n\t u \n  r\n\t\tk', keepws=False)
525
526
527@pytest.mark.ul4
528def test_undefined(r):
529    assert '' == r('<?print Undefined?>')
530    assert 'no' == r('<?if Undefined?>yes<?else?>no<?end if?>')
531
532
533@pytest.mark.ul4
534def test_none(r):
535    assert '' == r('<?print None?>')
536    assert 'no' == r('<?if None?>yes<?else?>no<?end if?>')
537
538
539@pytest.mark.ul4
540def test_false(r):
541    assert 'False' == r('<?print False?>')
542    assert 'no' == r('<?if False?>yes<?else?>no<?end if?>')
543
544
545@pytest.mark.ul4
546def test_true(r):
547    assert 'True' == r('<?print True?>')
548    assert 'yes' == r('<?if True?>yes<?else?>no<?end if?>')
549
550
551@pytest.mark.ul4
552def test_int(r):
553    values = (0, 42, -42, 0x7ffffff, 0x8000000, -0x8000000, -0x8000001)
554    if r is not render_js and r is not render_php:
555        # Since Javascript has no real integers the following would lead to rounding errors
556        # And PHP doesn't have any support for big integers (except for some GMP wrappers, that may not be installed)
557        values += (0x7ffffffffffffff, 0x800000000000000, -0x800000000000000, -0x800000000000001, 9999999999, -9999999999, 99999999999999999999, -99999999999999999999)
558    for value in values:
559        assert str(value) == r('<?print {}?>'.format(value))
560    assert '255' == r('<?print 0xff?>')
561    assert '255' == r('<?print 0Xff?>')
562    assert '-255' == r('<?print -0xff?>')
563    assert '-255' == r('<?print -0Xff?>')
564    assert '63' == r('<?print 0o77?>')
565    assert '63' == r('<?print 0O77?>')
566    assert '-63' == r('<?print -0o77?>')
567    assert '-63' == r('<?print -0O77?>')
568    assert '7' == r('<?print 0b111?>')
569    assert '7' == r('<?print 0B111?>')
570    assert '-7' == r('<?print -0b111?>')
571    assert '-7' == r('<?print -0B111?>')
572
573    assert 'no' == r('<?if 0?>yes<?else?>no<?end if?>')
574    assert 'yes' == r('<?if 1?>yes<?else?>no<?end if?>')
575    assert 'yes' == r('<?if -1?>yes<?else?>no<?end if?>')
576
577
578@pytest.mark.ul4
579def test_float(r):
580    # str() output might differ slightly between Python and JS, so eval the output again for tests
581    assert 0.0 == eval(r('<?print 0.?>'))
582    assert 42.0 == eval(r('<?print 42.?>'))
583    assert -42.0 == eval(r('<?print -42.?>'))
584    assert -42.5 == eval(r('<?print -42.5?>'))
585    assert 1e42 == eval(r('<?print 1E42?>'))
586    assert 1e42 == eval(r('<?print 1e42?>'))
587    assert -1e42 == eval(r('<?print -1E42?>'))
588    assert -1e42 == eval(r('<?print -1e42?>'))
589
590    assert 'no' == r('<?if 0.?>yes<?else?>no<?end if?>')
591    assert 'yes' == r('<?if 1.?>yes<?else?>no<?end if?>')
592    assert 'yes' == r('<?if -1.?>yes<?else?>no<?end if?>')
593
594
595@pytest.mark.ul4
596def test_string(r):
597    with raises("Unterminated string|mismatched character|MismatchedTokenException"):
598        r('<?print "?>')
599    assert 'foo' == r('<?print "foo"?>')
600    assert '\n' == r('<?print "\\n"?>')
601    assert '\r' == r('<?print "\\r"?>')
602    assert '\t' == r('<?print "\\t"?>')
603    assert '\f' == r('<?print "\\f"?>')
604    assert '\b' == r('<?print "\\b"?>')
605    assert '\a' == r('<?print "\\a"?>')
606    assert '\x00' == r('<?print "\\x00"?>')
607    assert '"' == r('<?print "\\""?>')
608    assert "'" == r('<?print "\\\'"?>')
609    assert '\u20ac' == r('<?print "\u20ac"?>')
610    assert '\xff' == r('<?print "\\xff"?>')
611    assert '\u20ac' == r('''<?print "\\u20ac"?>''')
612    for c in "\x00\x80\u0100\u3042\n\r\t\f\b\a\"":
613        assert c == r('<?print obj?>', obj=c) # This tests :func:`misc.javaexpr` for Java and :func:`ul4c._asjson` for JS
614
615    # Test literal control characters (but '\r' and '\n' are not allowed)
616    assert 'gu\trk' == r("<?print 'gu\trk'?>")
617    assert 'gu\t\\rk' == r(r"<?print 'gu\t\\rk'?>")
618
619    assert 'no' == r('<?if ""?>yes<?else?>no<?end if?>')
620    assert 'yes' == r('<?if "foo"?>yes<?else?>no<?end if?>')
621
622
623@pytest.mark.ul4
624def test_date(r):
625    assert '2000-02-29' == r('<?print @(2000-02-29).isoformat()?>')
626    assert '2000-02-29' == r('<?print @(2000-02-29T).isoformat()?>')
627    assert '2000-02-29T12:34:00' == r('<?print @(2000-02-29T12:34).isoformat()?>')
628    assert '2000-02-29T12:34:56' == r('<?print @(2000-02-29T12:34:56).isoformat()?>')
629    if r is not render_php:
630        assert '2000-02-29T12:34:56.987000' == r('<?print @(2000-02-29T12:34:56.987000).isoformat()?>') # JS and Java only supports milliseconds
631    assert 'yes' == r('<?if @(2000-02-29T12:34:56.987654)?>yes<?else?>no<?end if?>')
632
633
634@pytest.mark.ul4
635def test_color(r):
636    assert '255,255,255,255' == r('<?code c = #fff?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
637    assert '255,255,255,255' == r('<?code c = #ffffff?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
638    assert '18,52,86,255' == r('<?code c = #123456?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
639    assert '17,34,51,68' == r('<?code c = #1234?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
640    assert '18,52,86,120' == r('<?code c = #12345678?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
641    assert 'yes' == r('<?if #fff?>yes<?else?>no<?end if?>')
642
643
644@pytest.mark.ul4
645def test_list(r):
646    assert '' == r('<?for item in []?><?print item?>;<?end for?>')
647    assert '1;' == r('<?for item in [1]?><?print item?>;<?end for?>')
648    assert '1;' == r('<?for item in [1,]?><?print item?>;<?end for?>')
649    assert '1;2;' == r('<?for item in [1, 2]?><?print item?>;<?end for?>')
650    assert '1;2;' == r('<?for item in [1, 2,]?><?print item?>;<?end for?>')
651    assert 'no' == r('<?if []?>yes<?else?>no<?end if?>')
652    assert 'yes' == r('<?if [1]?>yes<?else?>no<?end if?>')
653
654
655@pytest.mark.ul4
656def test_listcomp(r):
657    assert "[2, 6]" == r("<?code d = [2*i for i in range(4) if i%2]?><?print d?>")
658    assert "[0, 2, 4, 6]" == r("<?code d = [2*i for i in range(4)]?><?print d?>")
659
660    # Make sure that the loop variables doesn't leak into the surrounding scope
661    assert "undefined" == r("<?code d = [2*i for i in range(4)]?><?print type(i)?>")
662
663
664@pytest.mark.ul4
665def test_genexpr(r):
666    assert "2, 6:" == r("<?code ge = (str(2*i) for i in range(4) if i%2)?><?print ', '.join(ge)?>:<?print ', '.join(ge)?>")
667    assert "2, 6" == r("<?print ', '.join(str(2*i) for i in range(4) if i%2)?>")
668    assert "0, 2, 4, 6" == r("<?print ', '.join(str(2*i) for i in range(4))?>")
669    assert "0, 2, 4, 6" == r("<?print ', '.join((str(2*i) for i in range(4)))?>")
670    assert "0:g; 1:r; 2:k" == r("<?for (i, c2) in enumerate(c for c in 'gurk' if c != 'u')?><?if i?>; <?end if?><?print i?>:<?print c2?><?end for?>")
671
672    # Make sure that the loop variables doesn't leak into the surrounding scope
673    assert "undefined" == r("<?code d = (2*i for i in range(4))?><?print type(i)?>")
674
675
676@pytest.mark.ul4
677def test_dict(r):
678    assert '' == r('<?for (key, value) in {}.items()?><?print key?>:<?print value?>\n<?end for?>')
679    assert '1:2\n' == r('<?for (key, value) in {1:2}.items()?><?print key?>:<?print value?>\n<?end for?>')
680    assert '1:#fff\n' == r('<?for (key, value) in {1:#fff}.items()?><?print key?>:<?print value?>\n<?end for?>')
681    assert '1:2\n' == r('<?for (key, value) in {1:2,}.items()?><?print key?>:<?print value?>\n<?end for?>')
682    # With duplicate keys, later ones simply overwrite earlier ones
683    assert '1:3\n' == r('<?for (key, value) in {1:2, 1: 3}.items()?><?print key?>:<?print value?>\n<?end for?>')
684    assert 'no' == r('<?if {}?>yes<?else?>no<?end if?>')
685    assert 'yes' == r('<?if {1:2}?>yes<?else?>no<?end if?>')
686
687    # Make sure that the loop variables doesn't leak into the surrounding scope
688    assert "undefined" == r("<?code d = {i: 2*i for i in range(4)}?><?print type(i)?>")
689
690
691@pytest.mark.ul4
692def test_dictcomp(r):
693    # JS only supports string keys
694    assert "" == r("<?code d = {str(i):2*i for i in range(10) if i%2}?><?if '2' in d?><?print d['2']?><?end if?>")
695    assert "6" == r("<?code d = {str(i):2*i for i in range(10) if i%2}?><?if '3' in d?><?print d['3']?><?end if?>")
696    assert "6" == r("<?code d = {str(i):2*i for i in range(10)}?><?print d['3']?>")
697
698
699@pytest.mark.ul4
700def test_print(r):
701    assert "" == r("<?print None?>")
702    assert "<foo>" == r("<?print '<foo>'?>")
703
704
705@pytest.mark.ul4
706def test_printx(r):
707    assert "" == r("<?printx None?>")
708    assert "&lt;foo&gt;" == r("<?printx '<foo>'?>")
709
710
711@pytest.mark.ul4
712def test_storevar(r):
713    assert '42' == r('<?code x = 42?><?print x?>')
714    assert 'xyzzy' == r('<?code x = "xyzzy"?><?print x?>')
715    assert 'x,y' == r('<?code (x, y) = "xy"?><?print x?>,<?print y?>')
716    assert '42' == r('<?code (x,) = [42]?><?print x?>')
717    assert '17,23' == r('<?code (x,y) = [17, 23]?><?print x?>,<?print y?>')
718    assert '17,23,37,42,105' == r('<?code ((v, w), (x,), (y,), z) = [[17, 23], [37], [42], 105]?><?print v?>,<?print w?>,<?print x?>,<?print y?>,<?print z?>')
719
720
721@pytest.mark.ul4
722def test_addvar(r):
723    for x in (17, 17., False, True):
724        for y in (23, 23., False, True):
725            assert x + y == eval(r('<?code x = {}?><?code x += {}?><?print x?>'.format(x, y)))
726    assert 'xyzzy' == r('<?code x = "xyz"?><?code x += "zy"?><?print x?>')
727
728
729@pytest.mark.ul4
730def test_subvar(r):
731    for x in (17, 17., False, True):
732        for y in (23, 23., False, True):
733            assert x - y == eval(r('<?code x = {}?><?code x -= {}?><?print x?>'.format(x, y)))
734
735
736@pytest.mark.ul4
737def test_mulvar(r):
738    for x in (17, 17., False, True):
739        for y in (23, 23., False, True):
740            assert x * y == eval(r('<?code x = {}?><?code x *= {}?><?print x?>'.format(x, y)))
741    for x in (17, False, True):
742        y = "xyzzy"
743        assert x * y == r('<?code x = {}?><?code x *= {!r}?><?print x?>'.format(x, y))
744    assert 17*"xyzzy" == r('<?code x = "xyzzy"?><?code x *= 17?><?print x?>')
745
746
747@pytest.mark.ul4
748def test_floordivvar(r):
749    for x in (5, -5, 5.0, -5.0, 4, -4, 4.0, -4.0, False, True):
750        for y in (2, -2, 2.0, -2.0, True):
751            assert x // y == eval(r('<?code x = {}?><?code x //= {}?><?print x?>'.format(x, y)))
752
753
754@pytest.mark.ul4
755def test_truedivvar(r):
756    for x in (5, -5, 5.0, -5.0, 4, -4, 4.0, -4.0, False, True):
757        for y in (2, -2, 2.0, -2.0, True):
758            assert x / y == eval(r('<?code x = {}?><?code x /= {}?><?print x?>'.format(x, y)))
759
760
761@pytest.mark.ul4
762def test_modvar(r):
763    for x in (1729, 1729.0, -1729, -1729.0, False, True):
764        for y in (23, 23., -23, -23.0, True):
765            assert x % y == eval(r('<?code x = {}?><?code x %= {}?><?print x?>'.format(x, y)))
766
767
768@pytest.mark.ul4
769def test_for_string(r):
770    assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data="")
771    assert '(g)(u)(r)(k)' == r('<?for c in data?>(<?print c?>)<?end for?>', data="gurk")
772
773
774@pytest.mark.ul4
775def test_for_list(r):
776    assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data="")
777    assert '(g)(u)(r)(k)' == r('<?for c in data?>(<?print c?>)<?end for?>', data=["g", "u", "r", "k"])
778
779
780@pytest.mark.ul4
781def test_for_dict(r):
782    assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data={})
783    assert '(a)(b)(c)' == r('<?for c in sorted(data)?>(<?print c?>)<?end for?>', data=dict(a=1, b=2, c=3))
784
785
786@pytest.mark.ul4
787def test_for_nested_loop(r):
788    assert '[(1)(2)][(3)(4)]' == r('<?for list in data?>[<?for n in list?>(<?print n?>)<?end for?>]<?end for?>', data=[[1, 2], [3, 4]])
789
790
791@pytest.mark.ul4
792def test_for_unpacking(r):
793    data = [
794        ("spam", "eggs", 17),
795        ("gurk", "hurz", 23),
796        ("hinz", "kunz", 42),
797    ]
798
799    assert '(spam)(gurk)(hinz)' == r('<?for (a,) in data?>(<?print a?>)<?end for?>', data=[item[:1] for item in data])
800    assert '(spam,eggs)(gurk,hurz)(hinz,kunz)' == r('<?for (a, b) in data?>(<?print a?>,<?print b?>)<?end for?>', data=[item[:2] for item in data])
801    assert '(spam,eggs,17)(gurk,hurz,23)(hinz,kunz,42)' == r('<?for (a, b, c) in data?>(<?print a?>,<?print b?>,<?print c?>)<?end for?>', data=data)
802
803
804@pytest.mark.ul4
805def test_for_nested_unpacking(r):
806    data = [
807        (("spam", "eggs"), (17,), None),
808        (("gurk", "hurz"), (23,), False),
809        (("hinz", "kunz"), (42,), True),
810    ]
811
812    assert '(spam,eggs,17,)(gurk,hurz,23,False)(hinz,kunz,42,True)' == r('<?for ((a, b), (c,), d) in data?>(<?print a?>,<?print b?>,<?print c?>,<?print d?>)<?end for?>', data=data)
813
814
815@pytest.mark.ul4
816def test_break(r):
817    assert '1, 2, ' == r('<?for i in [1,2,3]?><?print i?>, <?if i==2?><?break?><?end if?><?end for?>')
818
819
820@pytest.mark.ul4
821def test_break_nested(r):
822    assert '1, 1, 2, 1, 2, 3, ' == r('<?for i in [1,2,3,4]?><?for j in [1,2,3,4]?><?print j?>, <?if j>=i?><?break?><?end if?><?end for?><?if i>=3?><?break?><?end if?><?end for?>')
823
824
825@pytest.mark.ul4
826def test_continue(r):
827    assert '1, 3, ' == r('<?for i in [1,2,3]?><?if i==2?><?continue?><?end if?><?print i?>, <?end for?>')
828
829
830@pytest.mark.ul4
831def test_continue_nested(r):
832    assert '1, 3, \n1, 3, \n' == r('<?for i in [1,2,3]?><?if i==2?><?continue?><?end if?><?for j in [1,2,3]?><?if j==2?><?continue?><?end if?><?print j?>, <?end for?>\n<?end for?>')
833
834
835@pytest.mark.ul4
836def test_if(r):
837    assert '42' == r('<?if data?><?print data?><?end if?>', data=42)
838
839
840@pytest.mark.ul4
841def test_else(r):
842    assert '42' == r('<?if data?><?print data?><?else?>no<?end if?>', data=42)
843    assert 'no' == r('<?if data?><?print data?><?else?>no<?end if?>', data=0)
844
845
846@pytest.mark.ul4
847def test_block_errors(r):
848    with raises("block unclosed"):
849        r('<?for x in data?>')
850    with raises("for ended by endif|endif doesn't match any if"):
851        r('<?for x in data?><?end if?>')
852    with raises("not in any block"):
853        r('<?end?>')
854    with raises("not in any block"):
855        r('<?end for?>')
856    with raises("not in any block"):
857        r('<?end if?>')
858    with raises("else doesn't match any if"):
859        r('<?else?>')
860    with raises("block unclosed"):
861        r('<?if data?>')
862    with raises("block unclosed"):
863        r('<?if data?><?else?>')
864    with raises("duplicate else in if/elif/else chain|else already seen in if"):
865        r('<?if data?><?else?><?else?>')
866    with raises("elif can't follow else in if/elif/else chain|else already seen in if"):
867        r('<?if data?><?else?><?elif data?>')
868    with raises("elif can't follow else in if/elif/else chain|else already seen in if"):
869        r('<?if data?><?elif data?><?elif data?><?else?><?elif data?>')
870
871
872@pytest.mark.ul4
873def test_empty():
874    with raises("expression required"):
875        render_python('<?print?>')
876    with raises("expression required"):
877        render_python('<?if?>')
878    with raises("expression required"):
879        render_python('<<?if x?><?elif?><?end if?>')
880    with raises("loop expression required"):
881        render_python('<?for?>')
882    with raises("statement required"):
883        render_python('<?code?>')
884
885
886@pytest.mark.ul4
887def test_add(r):
888    code = '<?print x + y?>'
889    values = (17, 23, 1., -1.)
890
891    for x in values:
892        for y in values:
893            assert x + y == eval(r(code, x=x, y=y)) # Using ``evaleq`` avoids problem with the nonexistant int/float distinction in JS
894    assert 'foobar' == r('<?code x="foo"?><?code y="bar"?><?print x+y?>')
895    assert '(f)(o)(o)(b)(a)(r)' == r('<?for i in data.foo+data.bar?>(<?print i?>)<?end for?>', data=dict(foo="foo", bar="bar"))
896    assert "2012-10-18 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(1))
897    assert "2013-10-17 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(365))
898    assert "2012-10-17 12:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 12*60*60))
899    assert "2012-10-17 00:00:01" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 1))
900    if r is not render_php:
901        assert "2012-10-17 00:00:00.500000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 500000))
902        assert "2012-10-17 00:00:00.001000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 1000))
903    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
904    assert "1 day, 0:00:01" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 1))
905    assert "1 day, 0:00:00.000001" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 0, 1))
906    assert "2 months" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
907    assert "2000-02-01 00:00:00" == r(code, x=datetime.datetime(2000, 1, 1), y=misc.monthdelta(1))
908    assert "1999-11-30 00:00:00" == r(code, x=datetime.datetime(2000, 1, 31), y=misc.monthdelta(-2))
909    assert "2000-03-29 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(1))
910    assert "2001-02-28 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(12))
911    assert "2001-02-28 00:00:00" == r(code, x=misc.monthdelta(12), y=datetime.datetime(2000, 2, 29))
912
913
914@pytest.mark.ul4
915def test_sub(r):
916    code = '<?print x - y?>'
917    values = (17, 23, 1., -1.)
918
919    for x in values:
920        for y in values:
921            assert x - y == eval(r(code, x=x, y=y))
922
923    assert "2012-10-16 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(1))
924    assert "2011-10-17 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(366))
925    assert "2012-10-16 12:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 12*60*60))
926    assert "2012-10-16 23:59:59" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 1))
927    if r is not render_php:
928        assert "2012-10-16 23:59:59.500000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 500000))
929        assert "2012-10-16 23:59:59.999000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 1000))
930    assert "0:00:00" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
931    assert "1 day, 0:00:00" == r(code, x=datetime.timedelta(2), y=datetime.timedelta(1))
932    assert "23:59:59" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 1))
933    assert "23:59:59.999999" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 0, 1))
934    assert "-1 day, 23:59:59" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
935    assert "-1 day, 23:59:59.999999" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
936    assert "2000-01-01 00:00:00" == r(code, x=datetime.datetime(2000, 2, 1), y=misc.monthdelta(1))
937    assert "2000-02-29 00:00:00" == r(code, x=datetime.datetime(1999, 12, 31), y=misc.monthdelta(-2))
938    assert "2000-02-29 00:00:00" == r(code, x=datetime.datetime(2000, 3, 29), y=misc.monthdelta(1))
939    assert "1999-02-28 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(12))
940    assert "-1 month" == r(code, x=misc.monthdelta(2), y=misc.monthdelta(3))
941
942
943@pytest.mark.ul4
944def test_neg(r):
945    code = "<?print -x?>"
946
947    assert "0" == r(code, x=False)
948    assert "-1" == r(code, x=True)
949    assert "-17" == r(code, x=17)
950    assert "-42.5" == r(code, x=42.5)
951    assert "0:00:00" == r(code, x=datetime.timedelta())
952    assert "-1 day, 0:00:00" == r(code, x=datetime.timedelta(1))
953    assert "-1 day, 23:59:59" == r(code, x=datetime.timedelta(0, 1))
954    assert "-1 day, 23:59:59.999999" == r(code, x=datetime.timedelta(0, 0, 1))
955    assert "0 months" == r(code, x=misc.monthdelta())
956    assert "-1 month" == r(code, x=misc.monthdelta(1))
957    # This checks constant folding
958    assert "0" == r("<?print -False?>")
959    assert "-1" == r("<?print -True?>")
960    assert "-2" == r("<?print -2?>")
961    assert "-2.5" == r("<?print -2.5?>")
962
963@pytest.mark.ul4
964def test_mul(r):
965    code = '<?print x * y?>'
966    values = (17, 23, 1., -1.)
967
968    for x in values:
969        for y in values:
970            assert x * y == eval(r(code, x=x, y=y))
971    assert 17*"foo" == r('<?print 17*"foo"?>')
972    assert 17*"foo" == r('<?code x=17?><?code y="foo"?><?print x*y?>')
973    assert "foo"*17 == r('<?code x="foo"?><?code y=17?><?print x*y?>')
974    assert "foo"*17 == r('<?print "foo"*17?>')
975    assert "(foo)(bar)(foo)(bar)(foo)(bar)" == r('<?for i in 3*data?>(<?print i?>)<?end for?>', data=["foo", "bar"])
976    assert "0:00:00" == r(code, x=4, y=datetime.timedelta())
977    assert "4 days, 0:00:00" == r(code, x=4, y=datetime.timedelta(1))
978    assert "2 days, 0:00:00" == r(code, x=4, y=datetime.timedelta(0, 12*60*60))
979    assert "0:00:02" == r(code, x=4, y=datetime.timedelta(0, 0, 500000))
980    assert "12:00:00" == r(code, x=0.5, y=datetime.timedelta(1))
981    assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
982    assert "4 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=4)
983    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(0, 12*60*60), y=4)
984    assert "0:00:02" == r(code, x=datetime.timedelta(0, 0, 500000), y=4)
985    assert "12:00:00" == r(code, x=datetime.timedelta(1), y=0.5)
986    assert "4 months" == r(code, x=4, y=misc.monthdelta(1))
987    assert "4 months" == r(code, x=misc.monthdelta(1), y=4)
988
989
990@pytest.mark.ul4
991def test_truediv(r):
992    code = "<?print x / y?>"
993
994    assert "0.5" == r('<?print 1/2?>')
995    assert "0.5" == r('<?code x=1?><?code y=2?><?print x/y?>')
996    assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
997    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(8), y=4)
998    assert "12:00:00" == r(code, x=datetime.timedelta(4), y=8)
999    assert "0:00:00.500000" == r(code, x=datetime.timedelta(0, 4), y=8)
1000    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=0.5)
1001    assert "9:36:00" == r(code, x=datetime.timedelta(1), y=2.5)
1002    assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
1003    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(8), y=4)
1004    assert "12:00:00" == r(code, x=datetime.timedelta(4), y=8)
1005    assert "0:00:00.500000" == r(code, x=datetime.timedelta(0, 4), y=8)
1006    assert 2.0 == eval(r(code, x=datetime.timedelta(4), y=datetime.timedelta(2)))
1007    assert 2.0 == eval(r(code, x=misc.monthdelta(4), y=misc.monthdelta(2)))
1008
1009
1010@pytest.mark.ul4
1011def test_floordiv(r):
1012    assert "0" == r('<?print 1//2?>')
1013    assert "0" == r('<?code x=1?><?code y=2?><?print x//y?>')
1014    assert "1 month" == r('<?print x//y?>', x=misc.monthdelta(3), y=2)
1015
1016
1017@pytest.mark.ul4
1018def test_mod(r):
1019    values = (17, 23, 17., 23.)
1020
1021    for x in values:
1022        for y in values:
1023            assert x % y == eval(r('<?print {} % {}?>'.format(x, y)))
1024            assert x % y == eval(r('<?print x % y?>', x=x, y=y))
1025
1026
1027@pytest.mark.ul4
1028def test_eq(r):
1029    code = '<?print x == y?>'
1030    numbervalues = (17, 23, 17., 23.)
1031
1032    for x in numbervalues:
1033        for y in numbervalues:
1034            assert str(x == y) == r('<?print {} == {}?>'.format(x, y))
1035            assert str(x == y) == r(code, x=x, y=y)
1036
1037    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
1038    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
1039    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
1040    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
1041    assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
1042    assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))
1043
1044
1045@pytest.mark.ul4
1046def test_ne(r):
1047    code = '<?print x != y?>'
1048    values = (17, 23, 17., 23.)
1049
1050    for x in values:
1051        for y in values:
1052            assert str(x != y) == r('<?print {} != {}?>'.format(x, y))
1053            assert str(x != y) == r(code, x=x, y=y)
1054
1055    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
1056    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
1057    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
1058    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
1059    assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
1060    assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))
1061
1062
1063@pytest.mark.ul4
1064def test_lt(r):
1065    code = '<?print x < y?>'
1066    values = (17, 23, 17., 23.)
1067
1068    for x in values:
1069        for y in values:
1070            assert str(x < y) == r('<?print {} < {}?>'.format(x, y))
1071            assert str(x < y) == r(code, x=x, y=y)
1072
1073    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
1074    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
1075    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
1076    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
1077    assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
1078    assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))
1079
1080
1081@pytest.mark.ul4
1082def test_le(r):
1083    code = '<?print x <= y?>'
1084    values = (17, 23, 17., 23.)
1085
1086    for x in values:
1087        for y in values:
1088            assert str(x <= y) == r('<?print {} <= {}?>'.format(x, y))
1089            assert str(x <= y) == r(code, x=x, y=y)
1090
1091    assert "True" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
1092    assert "False" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0))
1093    assert "False" == r(code, x=datetime.timedelta(0, 1), y=datetime.timedelta(0))
1094    assert "False" == r(code, x=datetime.timedelta(0, 0, 1), y=datetime.timedelta(0))
1095    assert "True" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
1096    assert "False" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(0))
1097
1098
1099@pytest.mark.ul4
1100def test_gt(r):
1101    code = '<?print x > y?>'
1102    values = (17, 23, 17., 23.)
1103
1104    for x in values:
1105        for y in values:
1106            assert str(x > y) == r('<?print {} > {}?>'.format(x, y))
1107            assert str(x > y) == r(code, x=x, y=y)
1108
1109    assert "False" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
1110    assert "True" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0))
1111    assert "True" == r(code, x=datetime.timedelta(0, 1), y=datetime.timedelta(0))
1112    assert "True" == r(code, x=datetime.timedelta(0, 0, 1), y=datetime.timedelta(0))
1113    assert "False" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
1114    assert "True" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(0))
1115
1116
1117@pytest.mark.ul4
1118def test_ge(r):
1119    code = '<?print x >= y?>'
1120    values = (17, 23, 17., 23.)
1121
1122    for x in values:
1123        for y in values:
1124            assert str(x >= y) == r('<?print {} >= {}?>'.format(x, y))
1125            assert str(x >= y) == r(code, x=x, y=y)
1126
1127    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
1128    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
1129    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
1130    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
1131    assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
1132    assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))
1133
1134
1135@pytest.mark.ul4
1136def test_contains(r):
1137    code = '<?print x in y?>'
1138
1139    assert "True" == r(code, x=2, y=[1, 2, 3])
1140    assert "False" == r(code, x=4, y=[1, 2, 3])
1141    assert "True" == r(code, x="ur", y="gurk")
1142    assert "False" == r(code, x="un", y="gurk")
1143    assert "True" == r(code, x="a", y={"a": 1, "b": 2})
1144    assert "False" == r(code, x="c", y={"a": 1, "b": 2})
1145    assert "True" == r(code, x=0xff, y=color.Color(0x00, 0x80, 0xff, 0x42))
1146    assert "False" == r(code, x=0x23, y=color.Color(0x00, 0x80, 0xff, 0x42))
1147
1148
1149@pytest.mark.ul4
1150def test_notcontains(r):
1151    code = '<?print x not in y?>'
1152
1153    assert "False" == r(code, x=2, y=[1, 2, 3])
1154    assert "True" == r(code, x=4, y=[1, 2, 3])
1155    assert "False" == r(code, x="ur", y="gurk")
1156    assert "True" == r(code, x="un", y="gurk")
1157    assert "False" == r(code, x="a", y={"a": 1, "b": 2})
1158    assert "True" == r(code, x="c", y={"a": 1, "b": 2})
1159    assert "False" == r(code, x=0xff, y=color.Color(0x00, 0x80, 0xff, 0x42))
1160    assert "True" == r(code, x=0x23, y=color.Color(0x00, 0x80, 0xff, 0x42))
1161
1162
1163@pytest.mark.ul4
1164def test_and(r):
1165    assert "False" == r('<?print x and y?>', x=False, y=False)
1166    assert "False" == r('<?print x and y?>', x=False, y=True)
1167    assert "0" == r('<?print x and y?>', x=0, y=True)
1168
1169
1170@pytest.mark.ul4
1171def test_or(r):
1172    assert "False" == r('<?print x or y?>', x=False, y=False)
1173    assert "True" == r('<?print x or y?>', x=False, y=True)
1174    assert "42" == r('<?print x or y?>', x=42, y=True)
1175
1176
1177@pytest.mark.ul4
1178def test_not(r):
1179    assert "True" == r('<?print not x?>', x=False)
1180    assert "False" == r('<?print not x?>', x=42)
1181
1182
1183@pytest.mark.ul4
1184def test_getitem(r):
1185    assert "u" == r("<?print 'gurk'[1]?>")
1186    assert "u" == r("<?print x[1]?>", x="gurk")
1187    assert "u" == r("<?print 'gurk'[-3]?>")
1188    assert "u" == r("<?print x[-3]?>", x="gurk")
1189    assert "" == r("<?print 'gurk'[4]?>")
1190    assert "" == r("<?print x[4]?>", x="gurk")
1191    assert "" == r("<?print 'gurk'[-5]?>")
1192    assert "" == r("<?print x[-5]?>", x="gurk")
1193
1194
1195@pytest.mark.ul4
1196def test_getslice12(r):
1197    assert "ur" == r("<?print 'gurk'[1:3]?>")
1198    assert "ur" == r("<?print x[1:3]?>", x="gurk")
1199    assert "ur" == r("<?print 'gurk'[-3:-1]?>")
1200    assert "ur" == r("<?print x[-3:-1]?>", x="gurk")
1201    assert "" == r("<?print 'gurk'[4:10]?>")
1202    assert "" == r("<?print x[4:10]?>", x="gurk")
1203    assert "" == r("<?print 'gurk'[-10:-5]?>")
1204    assert "" == r("<?print x[-10:-5]?>", x="gurk")
1205
1206
1207@pytest.mark.ul4
1208def test_getslice1(r):
1209    assert "urk" == r("<?print 'gurk'[1:]?>")
1210    assert "urk" == r("<?print x[1:]?>", x="gurk")
1211    assert "urk" == r("<?print 'gurk'[-3:]?>")
1212    assert "urk" == r("<?print x[-3:]?>", x="gurk")
1213    assert "" == r("<?print 'gurk'[4:]?>")
1214    assert "" == r("<?print x[4:]?>", x="gurk")
1215    assert "gurk" == r("<?print 'gurk'[-10:]?>")
1216    assert "gurk" == r("<?print x[-10:]?>", x="gurk")
1217
1218
1219@pytest.mark.ul4
1220def test_getslice2(r):
1221    assert "gur" == r("<?print 'gurk'[:3]?>")
1222    assert "gur" == r("<?print x[:3]?>", x="gurk")
1223    assert "gur" == r("<?print 'gurk'[:-1]?>")
1224    assert "gur" == r("<?print x[:-1]?>", x="gurk")
1225    assert "gurk" == r("<?print 'gurk'[:10]?>")
1226    assert "gurk" == r("<?print x[:10]?>", x="gurk")
1227    assert "" == r("<?print 'gurk'[:-5]?>")
1228    assert "" == r("<?print x[:-5]?>", x="gurk")
1229    assert "05" == r("<?print ('0' + str(x))[-2:]?>", x=5)
1230    assert "15" == r("<?print ('0' + str(x))[-2:]?>", x=15)
1231
1232
1233@pytest.mark.ul4
1234def test_getslice(r):
1235    assert "gurk" == r("<?print 'gurk'[:]?>")
1236    assert "gurk" == r("<?print x[:]?>", x="gurk")
1237    assert "[1, 2]" == r("<?print x[:]?>", x=[1, 2])
1238
1239
1240@pytest.mark.ul4
1241def test_nested(r):
1242    sc = "4"
1243    sv = "x"
1244    n = 4
1245    # when using 8 Java will output "An irrecoverable stack overflow has occurred"
1246    depth = 7
1247    for i in range(depth):
1248        sc = "({})+({})".format(sc, sc)
1249        sv = "({})+({})".format(sv, sv)
1250        n = n + n
1251
1252    assert str(n) == r('<?print {}?>'.format(sc))
1253    assert str(n) == r('<?code x=4?><?print {}?>'.format(sv))
1254
1255
1256@pytest.mark.ul4
1257def test_precedence(r):
1258    assert "14" == r('<?print 2+3*4?>')
1259    assert "20" == r('<?print (2+3)*4?>')
1260    assert "10" == r('<?print -2+-3*-4?>')
1261    assert "14" == r('<?print --2+--3*--4?>')
1262    assert "14" == r('<?print (-(-2))+(-((-3)*-(-4)))?>')
1263    assert "42" == r('<?print 2*data.value?>', data=dict(value=21))
1264    assert "42" == r('<?print data.value[0]?>', data=dict(value=[42]))
1265    assert "42" == r('<?print data[0].value?>', data=[dict(value=42)])
1266    assert "42" == r('<?print data[0][0][0]?>', data=[[[42]]])
1267    assert "42" == r('<?print data.value.value[0]?>', data=dict(value=dict(value=[42])))
1268    assert "42" == r('<?print data.value.value[0].value.value[0]?>', data=dict(value=dict(value=[dict(value=dict(value=[42]))])))
1269
1270@pytest.mark.ul4
1271def test_associativity(r):
1272    assert "9" == r('<?print 2+3+4?>')
1273    assert "-5" == r('<?print 2-3-4?>')
1274    assert "24" == r('<?print 2*3*4?>')
1275    if r is not render_js:
1276        assert "2.0" == r('<?print 24/6/2?>')
1277        assert "2" == r('<?print 24//6//2?>')
1278    else:
1279        assert 2.0 == eval(r('<?print 24/6/2?>'))
1280        assert 2 == eval(r('<?print 24//6//2?>'))
1281
1282@pytest.mark.ul4
1283def test_bracket(r):
1284    sc = "4"
1285    sv = "x"
1286    for i in range(10):
1287        sc = "({})".format(sc)
1288        sv = "({})".format(sv)
1289
1290    assert "4" == r('<?print {}?>'.format(sc))
1291    assert "4" == r('<?code x=4?><?print {}?>'.format(sv))
1292
1293
1294@pytest.mark.ul4
1295def test_callfunc_args(r):
1296    assert "@(2013-01-07)" == r("<?print repr(date(2013, 1, 7))?>")
1297    assert "@(2013-01-07)" == r("<?print repr(date(2013, 1, day=7))?>")
1298    assert "@(2013-01-07)" == r("<?print repr(date(2013, month=1, day=7))?>")
1299    assert "@(2013-01-07)" == r("<?print repr(date(year=2013, month=1, day=7))?>")
1300    assert "@(2013-01-07)" == r("<?print repr(date(2013, *[1, 7]))?>")
1301    assert "@(2013-01-07)" == r("<?print repr(date(*[2013, 1, 7]))?>")
1302    assert "@(2013-01-07)" == r("<?print repr(date(year=2013, **{'month': 1, 'day': 7}))?>")
1303    assert "@(2013-01-07)" == r("<?print repr(date(2013, *[1], **{'day': 7}))?>")
1304
1305
1306@pytest.mark.ul4
1307def test_function_now(r):
1308    now = str(datetime.datetime.now())
1309
1310    with raises(argumentmismatchmessage):
1311        r("<?print now(1)?>")
1312    with raises(argumentmismatchmessage):
1313        r("<?print now(1, 2)?>")
1314    with raises(argumentmismatchmessage):
1315        r("<?print now(foo=1)?>")
1316    assert now <= r("<?print now()?>")
1317
1318
1319@pytest.mark.ul4
1320def test_function_utcnow(r):
1321    utcnow = str(datetime.datetime.utcnow())
1322
1323    with raises(argumentmismatchmessage):
1324        r("<?print utcnow(1)?>")
1325    with raises(argumentmismatchmessage):
1326        r("<?print utcnow(1, 2)?>")
1327    with raises(argumentmismatchmessage):
1328        r("<?print utcnow(foo=1)?>")
1329    # JS and Java only have milliseconds precision, but this shouldn't lead to problems here, as rendering the template takes longer than a millisecond
1330    assert utcnow <= r("<?print utcnow()?>")
1331
1332
1333@pytest.mark.ul4
1334def test_function_date(r):
1335    assert "@(2012-10-06)" == r("<?print repr(date(2012, 10, 6))?>")
1336    assert "@(2012-10-06T12:00:00)" == r("<?print repr(date(2012, 10, 6, 12))?>")
1337    assert "@(2012-10-06T12:34:00)" == r("<?print repr(date(2012, 10, 6, 12, 34))?>")
1338    assert "@(2012-10-06T12:34:56)" == r("<?print repr(date(2012, 10, 6, 12, 34, 56))?>")
1339    if r is not render_php:
1340        assert "@(2012-10-06T12:34:56.987000)" == r("<?print repr(date(2012, 10, 6, 12, 34, 56, 987000))?>")
1341
1342    # Make sure that the parameters have the same name in all implementations
1343    assert "@(2012-10-06T12:34:56)" == r("<?print repr(date(year=2012, month=10, day=6, hour=12, minute=34, second=56, microsecond=0))?>")
1344
1345
1346@pytest.mark.ul4
1347def test_function_timedelta(r):
1348    with raises(argumentmismatchmessage):
1349        r("<?print timedelta(1, 2, 3, 4)?>")
1350    assert "1 day, 0:00:00" == r("<?print timedelta(1)?>")
1351    assert "-1 day, 0:00:00" == r("<?print timedelta(-1)?>")
1352    assert "2 days, 0:00:00" == r("<?print timedelta(2)?>")
1353    assert "0:00:01" == r("<?print timedelta(0, 0, 1000000)?>")
1354    assert "1 day, 0:00:00" == r("<?print timedelta(0, 0, 24*60*60*1000000)?>")
1355    assert "1 day, 0:00:00" == r("<?print timedelta(0, 24*60*60)?>")
1356    assert "12:00:00" == r("<?print timedelta(0.5)?>")
1357    assert "0:00:00.500000" == r("<?print timedelta(0, 0.5)?>")
1358    assert "0:00:00.500000" == r("<?print timedelta(0.5/(24*60*60))?>")
1359    assert "-1 day, 12:00:00" == r("<?print timedelta(-0.5)?>")
1360    assert "-1 day, 23:59:59.500000" == r("<?print timedelta(0, -0.5)?>")
1361    assert "0:00:01" == r("<?print timedelta(0, 1)?>")
1362    assert "0:01:00" == r("<?print timedelta(0, 60)?>")
1363    assert "1:00:00" == r("<?print timedelta(0, 60*60)?>")
1364    assert "1 day, 1:01:01.000001" == r("<?print timedelta(1, 60*60+60+1, 1)?>")
1365    assert "0:00:00.000001" == r("<?print timedelta(0, 0, 1)?>")
1366    assert "-1 day, 23:59:59" == r("<?print timedelta(0, -1)?>")
1367    assert "-1 day, 23:59:59.999999" == r("<?print timedelta(0, 0, -1)?>")
1368
1369    # Make sure that the parameters have the same name in all implementations
1370    assert "0:00:00.000001" == r("<?print timedelta(days=0, seconds=0, microseconds=1)?>")
1371
1372
1373@pytest.mark.ul4
1374def test_function_monthdelta(r):
1375    with raises(argumentmismatchmessage):
1376        r("<?print monthdelta(1, 2)?>")
1377    assert "0 months" == r("<?print monthdelta()?>")
1378    assert "2 months" == r("<?print monthdelta(2)?>")
1379    assert "1 month" == r("<?print monthdelta(1)?>")
1380    assert "-1 month" == r("<?print monthdelta(-1)?>")
1381
1382    # Make sure that the parameters have the same name in all implementations
1383    assert "1 month" == r("<?print monthdelta(months=1)?>")
1384
1385
1386@pytest.mark.ul4
1387def test_function_random(r):
1388    with raises(argumentmismatchmessage):
1389        r("<?print random(1)?>")
1390    with raises(argumentmismatchmessage):
1391        r("<?print random(1, 2)?>")
1392    with raises(argumentmismatchmessage):
1393        r("<?print random(foo=1)?>")
1394    assert "ok" == r("<?code r = random()?><?if r>=0 and r<1?>ok<?else?>fail<?end if?>")
1395
1396
1397@pytest.mark.ul4
1398def test_function_randrange(r):
1399    with raises(argumentmismatchmessage):
1400        r("<?print randrange()?>")
1401    with raises(argumentmismatchmessage):
1402        r("<?print randrange(foo=1)?>")
1403    assert "ok" == r("<?code r = randrange(4)?><?if r>=0 and r<4?>ok<?else?>fail<?end if?>")
1404    assert "ok" == r("<?code r = randrange(17, 23)?><?if r>=17 and r<23?>ok<?else?>fail<?end if?>")
1405    assert "ok" == r("<?code r = randrange(17, 23, 2)?><?if r>=17 and r<23 and r%2?>ok<?else?>fail<?end if?>")
1406
1407
1408@pytest.mark.ul4
1409def test_function_randchoice(r):
1410    with raises(argumentmismatchmessage):
1411        r("<?print randchoice()?>")
1412    assert "ok" == r("<?code r = randchoice('abc')?><?if r in 'abc'?>ok<?else?>fail<?end if?>")
1413    assert "ok" == r("<?code s = [17, 23, 42]?><?code r = randchoice(s)?><?if r in s?>ok<?else?>fail<?end if?>")
1414    assert "ok" == r("<?code s = #12345678?><?code sl = [0x12, 0x34, 0x56, 0x78]?><?code r = randchoice(s)?><?if r in sl?>ok<?else?>fail<?end if?>")
1415
1416    # Make sure that the parameters have the same name in all implementations
1417    assert "ok" == r("<?code s = [17, 23, 42]?><?code r = randchoice(sequence=s)?><?if r in s?>ok<?else?>fail<?end if?>")
1418
1419
1420@pytest.mark.ul4
1421def test_function_xmlescape(r):
1422    with raises(argumentmismatchmessage):
1423        r("<?print xmlescape()?>")
1424    with raises(argumentmismatchmessage):
1425        r("<?print xmlescape(1, 2)?>")
1426    assert "&lt;&lt;&gt;&gt;&amp;&#39;&quot;gurk" == r("<?print xmlescape(data)?>", data='<<>>&\'"gurk')
1427
1428    # Make sure that the parameters have the same name in all implementations
1429    assert "42" == r("<?print xmlescape(obj=data)?>", data=42)
1430
1431
1432@pytest.mark.ul4
1433def test_function_csv(r):
1434    with raises(argumentmismatchmessage):
1435        r("<?print csv()?>")
1436    with raises(argumentmismatchmessage):
1437        r("<?print csv(1, 2)?>")
1438    assert "" == r("<?print csv(data)?>", data=None)
1439    assert "False" == r("<?print csv(data)?>", data=False)
1440    assert "True" == r("<?print csv(data)?>", data=True)
1441    assert "42" == r("<?print csv(data)?>", data=42)
1442    # no check for float
1443    assert "abc" == r("<?print csv(data)?>", data="abc")
1444    assert '"a,b,c"' == r("<?print csv(data)?>", data="a,b,c")
1445    assert '"a""b""c"' == r("<?print csv(data)?>", data='a"b"c')
1446    assert '"a\nb\nc"' == r("<?print csv(data)?>", data="a\nb\nc")
1447
1448    # Make sure that the parameters have the same name in all implementations
1449    assert "42" == r("<?print csv(obj=data)?>", data=42)
1450
1451
1452@pytest.mark.ul4
1453def test_function_asjson(r):
1454    with raises(argumentmismatchmessage):
1455        r("<?print asjson()?>")
1456    with raises(argumentmismatchmessage):
1457        r("<?print asjson(1, 2)?>")
1458    assert "null" == r("<?print asjson(data)?>", data=None)
1459    assert "false" == r("<?print asjson(data)?>", data=False)
1460    assert "true" == r("<?print asjson(data)?>", data=True)
1461    assert "42" == r("<?print asjson(data)?>", data=42)
1462    # no check for float
1463    assert '"abc"' == r("<?print asjson(data)?>", data="abc")
1464    assert '[1, 2, 3]' == r("<?print asjson(data)?>", data=[1, 2, 3])
1465    assert '[1, 2, 3]' == r("<?print asjson(data)?>", data=PseudoList([1, 2, 3]))
1466    assert '{"one": 1}' == r("<?print asjson(data)?>", data={"one": 1})
1467    assert '{"one": 1}' == r("<?print asjson(data)?>", data=PseudoDict({"one": 1}))
1468
1469    # Make sure that the parameters have the same name in all implementations
1470    assert "42" == r("<?print asjson(obj=data)?>", data=42)
1471
1472
1473@pytest.mark.ul4
1474def test_function_fromjson(r):
1475    code = "<?print repr(fromjson(data))?>"
1476    with raises(argumentmismatchmessage):
1477        r("<?print fromjson()?>")
1478    with raises(argumentmismatchmessage):
1479        r("<?print fromjson(1, 2)?>")
1480    assert "None" == r(code, data="null")
1481    assert "False" == r(code, data="false")
1482    assert "True" == r(code, data="true")
1483    assert "42" == r(code, data="42")
1484    # no check for float
1485    assert r(code, data='"abc"') in ('"abc"', "'abc'")
1486    assert '[1, 2, 3]' == r(code, data="[1, 2, 3]")
1487    assert r(code, data='{"one": 1}') in ('{"one": 1}', "{'one': 1}")
1488
1489    # Make sure that the parameters have the same name in all implementations
1490    assert "42" == r("<?print fromjson(string=data)?>", data="42")
1491
1492
1493@pytest.mark.ul4
1494def test_function_ul4on(r):
1495    code = "<?print repr(fromul4on(asul4on(data)))?>"
1496
1497    with raises(argumentmismatchmessage):
1498        r("<?print asul4on()?>")
1499    with raises(argumentmismatchmessage):
1500        r("<?print asul4on(1, 2)?>")
1501    with raises(argumentmismatchmessage):
1502        r("<?print fromul4on()?>")
1503    with raises(argumentmismatchmessage):
1504        r("<?print fromul4on(1, 2)?>")
1505    assert "None" == r(code, data=None)
1506    assert "False" == r(code, data=False)
1507    assert "True" == r(code, data=True)
1508    assert "42" == r(code, data=42)
1509    # no check for float
1510    assert r(code, data="abc") in ('"abc"', "'abc'")
1511    assert '[1, 2, 3]' == r(code, data=[1, 2, 3])
1512    assert r(code, data={'one': 1}) in ('{"one": 1}', "{'one': 1}")
1513
1514    # Make sure that the parameters have the same name in all implementations
1515    assert "42" == r("<?print repr(fromul4on(string=asul4on(obj=data)))?>", data=42)
1516
1517
1518@pytest.mark.ul4
1519def test_function_str(r):
1520    code = "<?print str(data)?>"
1521
1522    with raises(argumentmismatchmessage):
1523        r("<?print str(1, 2)?>")
1524    assert "" == r("<?print str()?>")
1525    assert "" == r(code, data=None)
1526    assert "True" == r(code, data=True)
1527    assert "False" == r(code, data=False)
1528    assert "42" == r(code, data=42)
1529    assert "4.2" == r(code, data=4.2)
1530    assert "foo" == r(code, data="foo")
1531    assert "2011-02-09 00:00:00" == r(code, data=datetime.datetime(2011, 2, 9))
1532    assert "2011-02-09 12:34:56" == r(code, data=datetime.datetime(2011, 2, 9, 12, 34, 56))
1533    if r is not render_php:
1534        assert "2011-02-09 12:34:56.987000" == r(code, data=datetime.datetime(2011, 2, 9, 12, 34, 56, 987000))
1535    assert "0:00:00" == r(code, data=datetime.timedelta())
1536    assert "1 day, 0:00:00" == r(code, data=datetime.timedelta(1))
1537    assert "-1 day, 0:00:00" == r(code, data=datetime.timedelta(-1))
1538    assert "2 days, 0:00:00" == r(code, data=datetime.timedelta(2))
1539    assert "0:00:01" == r(code, data=datetime.timedelta(0, 1))
1540    assert "0:01:00" == r(code, data=datetime.timedelta(0, 60))
1541    assert "1:00:00" == r(code, data=datetime.timedelta(0, 60*60))
1542    assert "1 day, 1:01:01.000001" == r(code, data=datetime.timedelta(1, 60*60+60+1, 1))
1543    assert "0:00:00.000001" == r(code, data=datetime.timedelta(0, 0, 1))
1544    assert "-1 day, 23:59:59" == r(code, data=datetime.timedelta(0, -1))
1545    assert "-1 day, 23:59:59.999999" == r(code, data=datetime.timedelta(0, 0, -1))
1546
1547    # Make sure that the parameters have the same name in all implementations
1548    assert "42" == r("<?print str(obj=data)?>", data=42)
1549
1550
1551@pytest.mark.ul4
1552def test_function_bool(r):
1553    with raises(argumentmismatchmessage):
1554        r("<?print bool(1, 2)?>")
1555    assert "False" == r("<?print bool()?>")
1556    code = "<?print bool(data)?>"
1557    assert "True" == r(code, data=True)
1558    assert "False" == r(code, data=False)
1559    assert "False" == r(code, data=0)
1560    assert "True" == r(code, data=42)
1561    assert "False" == r(code, data=0.0)
1562    assert "True" == r(code, data=42.5)
1563    assert "False" == r(code, data="")
1564    assert "True" == r(code, data="gurk")
1565    assert "False" == r(code, data=[])
1566    assert "True" == r(code, data=["gurk"])
1567    assert "False" == r(code, data={})
1568    assert "True" == r(code, data={"gurk": "hurz"})
1569    assert "True" == r(code, data=datetime.datetime.now())
1570    assert "False" == r(code, data=datetime.timedelta())
1571    assert "True" == r(code, data=datetime.timedelta(1))
1572    assert "False" == r(code, data=misc.monthdelta())
1573    assert "True" == r(code, data=misc.monthdelta(1))
1574
1575    # Make sure that the parameters have the same name in all implementations
1576    assert "True" == r("<?print bool(obj=data)?>", data=42)
1577
1578
1579@pytest.mark.ul4
1580def test_function_int(r):
1581    with raises(argumentmismatchmessage):
1582        r("<?print int(1, 2, 3)?>")
1583    with raises("int\\(\\) argument must be a string or a number|int\\(null\\) not supported"):
1584        r("<?print int(data)?>", data=None)
1585    with raises("invalid literal for int|NumberFormatException"):
1586        r("<?print int(data)?>", data="foo")
1587    assert "0" == r("<?print int()?>")
1588    assert "1" == r("<?print int(data)?>", data=True)
1589    assert "0" == r("<?print int(data)?>", data=False)
1590    assert "42" == r("<?print int(data)?>", data=42)
1591    assert "4" == r("<?print int(data)?>", data=4.2)
1592    assert "42" == r("<?print int(data)?>", data="42")
1593    assert "66" == r("<?print int(data, 16)?>", data="42")
1594
1595    # Make sure that the parameters have the same name in all implementations
1596    assert "42" == r("<?print int(obj=data, base=None)?>", data=42)
1597
1598
1599@pytest.mark.ul4
1600def test_function_float(r):
1601    code = "<?print float(data)?>"
1602
1603    with raises(argumentmismatchmessage):
1604        r("<?print float(1, 2, 3)?>")
1605    with raises("float\\(\\) argument must be a string or a number|float\\(null\\) not supported"):
1606        r(code, data=None)
1607    assert "4.2" == r(code, data=4.2)
1608    if r is not render_js:
1609        assert "0.0" == r("<?print float()?>")
1610        assert "1.0" == r(code, data=True)
1611        assert "0.0" == r(code, data=False)
1612        assert "42.0" == r(code, data=42)
1613        assert "42.0" == r(code, data="42")
1614
1615        # Make sure that the parameters have the same name in all implementations
1616        assert "42.0" == r("<?print float(obj=data)?>", data=42)
1617    else:
1618        assert 0.0 == eval(r("<?print float()?>"))
1619        assert 1.0 == eval(r(code, data=True))
1620        assert 0.0 == eval(r(code, data=False))
1621        assert 42.0 == eval(r(code, data=42))
1622        assert 42.0 == eval(r(code, data="42"))
1623
1624        # Make sure that the parameters have the same name in all implementations
1625        assert 42.0 == eval(r("<?print float(obj=data)?>", data=42))
1626
1627
1628@pytest.mark.ul4
1629def test_function_len(r):
1630    code = "<?print len(data)?>"
1631
1632    with raises(argumentmismatchmessage):
1633        r("<?print len()?>")
1634    with raises(argumentmismatchmessage):
1635        r("<?print len(1, 2)?>")
1636    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1637        r(code, data=None)
1638    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1639        r(code, data=True)
1640    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1641        r(code, data=False)
1642    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1643        r(code, data=42)
1644    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1645        r(code, data=4.2)
1646    assert "42" == r(code, data=42*"?")
1647    assert "42" == r(code, data=42*[None])
1648    assert "42" == r(code, data=dict.fromkeys(range(42)))
1649
1650    # Make sure that the parameters have the same name in all implementations
1651    assert "42" == r("<?print len(sequence=data)?>", data=42*"?")
1652
1653
1654@pytest.mark.ul4
1655def test_function_any(r):
1656    with raises(argumentmismatchmessage):
1657        r("<?print any()?>")
1658    with raises(argumentmismatchmessage):
1659        r("<?print any(1, 2)?>")
1660    with raises("is not iterable|any\\(.*\\) not supported"):
1661        r("<?print any(data)?>", data=None)
1662    assert "False" == r("<?print any('')?>")
1663    assert "True" == r("<?print any('foo')?>")
1664    assert "True" == r("<?print any(i > 7 for i in range(10))?>")
1665    assert "False" == r("<?print any(i > 17 for i in range(10))?>")
1666
1667    # Make sure that the parameters have the same name in all implementations
1668    assert "False" == r("<?print any(iterable=(i > 17 for i in range(10)))?>")
1669
1670
1671@pytest.mark.ul4
1672def test_function_all(r):
1673    with raises(argumentmismatchmessage):
1674        r("<?print all()?>")
1675    with raises(argumentmismatchmessage):
1676        r("<?print all(1, 2)?>")
1677    with raises("is not iterable|all\\(.*\\) not supported"):
1678        r("<?print all(data)?>", data=None)
1679    assert "True" == r("<?print all('')?>")
1680    assert "True" == r("<?print all('foo')?>")
1681    assert "False" == r("<?print all(i < 7 for i in range(10))?>")
1682    assert "True" == r("<?print all(i < 17 for i in range(10))?>")
1683
1684    # Make sure that the parameters have the same name in all implementations
1685    assert "True" == r("<?print all(iterable=(i < 17 for i in range(10)))?>")
1686
1687
1688@pytest.mark.ul4
1689def test_function_enumerate(r):
1690    code1 = "<?for (i, value) in enumerate(data)?>(<?print value?>=<?print i?>)<?end for?>"
1691    code2 = "<?for (i, value) in enumerate(data, 42)?>(<?print value?>=<?print i?>)<?end for?>"
1692
1693    with raises(argumentmismatchmessage):
1694        r("<?print enumerate()?>")
1695    with raises(argumentmismatchmessage):
1696        r("<?print enumerate(1, 2, 3)?>")
1697    with raises("is not iterable|iter\\(.*\\) not supported"):
1698        r(code1, data=None)
1699    with raises("is not iterable|iter\\(.*\\) not supported"):
1700        r(code1, data=True)
1701    with raises("is not iterable|iter\\(.*\\) not supported"):
1702        r(code1, data=False)
1703    with raises("is not iterable|iter\\(.*\\) not supported"):
1704        r(code1, data=42)
1705    with raises("is not iterable|iter\\(.*\\) not supported"):
1706        r(code1, data=4.2)
1707    assert "(f=0)(o=1)(o=2)" == r(code1, data="foo")
1708    assert "(foo=0)(bar=1)" == r(code1, data=["foo", "bar"])
1709    assert "(foo=0)" == r(code1, data=dict(foo=True))
1710    assert "" == r(code1, data="")
1711    assert "(f=42)(o=43)(o=44)" == r(code2, data="foo")
1712
1713    # Make sure that the parameters have the same name in all implementations
1714    assert "(f=42)(o=43)(o=44)" == r("<?for (i, value) in enumerate(iterable=data, start=42)?>(<?print value?>=<?print i?>)<?end for?>", data="foo")
1715
1716
1717@pytest.mark.ul4
1718def test_function_enumfl(r):
1719    code1 = "<?for (i, f, l, value) in enumfl(data)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>"
1720    code2 = "<?for (i, f, l, value) in enumfl(data, 42)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>"
1721
1722    with raises(argumentmismatchmessage):
1723        r("<?print enumfl()?>")
1724    with raises(argumentmismatchmessage):
1725        r("<?print enumfl(1, 2, 3)?>")
1726    with raises("is not iterable|iter\\(.*\\) not supported"):
1727        r(code1, data=None)
1728    with raises("is not iterable|iter\\(.*\\) not supported"):
1729        r(code1, data=True)
1730    with raises("is not iterable|iter\\(.*\\) not supported"):
1731        r(code1, data=False)
1732    with raises("is not iterable|iter\\(.*\\) not supported"):
1733        r(code1, data=42)
1734    with raises("is not iterable|iter\\(.*\\) not supported"):
1735        r(code1, data=4.2)
1736    assert "[(f=0)(o=1)(o=2)]" == r(code1, data="foo")
1737    assert "[(foo=0)(bar=1)]" == r(code1, data=["foo", "bar"])
1738    assert "[(foo=0)]" == r(code1, data=dict(foo=True))
1739    assert "" == r(code1, data="")
1740    assert "[(f=42)(o=43)(o=44)]" == r(code2, data="foo")
1741
1742    # Make sure that the parameters have the same name in all implementations
1743    assert "[(f=42)(o=43)(o=44)]" == r("<?for (i, f, l, value) in enumfl(iterable=data, start=42)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>", data="foo")
1744
1745
1746@pytest.mark.ul4
1747def test_function_isfirstlast(r):
1748    code = "<?for (f, l, value) in isfirstlast(data)?><?if f?>[<?end if?>(<?print value?>)<?if l?>]<?end if?><?end for?>"
1749
1750    with raises(argumentmismatchmessage):
1751        r("<?print isfirstlast()?>")
1752    with raises(argumentmismatchmessage):
1753        r("<?print isfirstlast(1, 2)?>")
1754    with raises("is not iterable|iter\\(.*\\) not supported"):
1755        r(code, data=None)
1756    with raises("is not iterable|iter\\(.*\\) not supported"):
1757        r(code, data=True)
1758    with raises("is not iterable|iter\\(.*\\) not supported"):
1759        r(code, data=False)
1760    with raises("is not iterable|iter\\(.*\\) not supported"):
1761        r(code, data=42)
1762    with raises("is not iterable|iter\\(.*\\) not supported"):
1763        r(code, data=4.2)
1764    assert "[(f)(o)(o)]" == r(code, data="foo")
1765    assert "[(foo)(bar)]" == r(code, data=["foo", "bar"])
1766    assert "[(foo)]" == r(code, data=dict(foo=True))
1767    assert "" == r(code, data="")
1768
1769    # Make sure that the parameters have the same name in all implementations
1770    assert "[(f)(o)(o)]" == r("<?for (f, l, value) in isfirstlast(iterable=data)?><?if f?>[<?end if?>(<?print value?>)<?if l?>]<?end if?><?end for?>", data="foo")
1771
1772
1773@pytest.mark.ul4
1774def test_function_isfirst(r):
1775    code = "<?for (f, value) in isfirst(data)?><?if f?>[<?end if?>(<?print value?>)<?end for?>"
1776
1777    with raises(argumentmismatchmessage):
1778        r("<?print isfirst()?>")
1779    with raises(argumentmismatchmessage):
1780        r("<?print isfirst(1, 2)?>")
1781    with raises("is not iterable|iter\\(.*\\) not supported"):
1782        r(code, data=None)
1783    with raises("is not iterable|iter\\(.*\\) not supported"):
1784        r(code, data=True)
1785    with raises("is not iterable|iter\\(.*\\) not supported"):
1786        r(code, data=False)
1787    with raises("is not iterable|iter\\(.*\\) not supported"):
1788        r(code, data=42)
1789    with raises("is not iterable|iter\\(.*\\) not supported"):
1790        r(code, data=4.2)
1791    assert "[(f)(o)(o)" == r(code, data="foo")
1792    assert "[(foo)(bar)" == r(code, data=["foo", "bar"])
1793    assert "[(foo)" == r(code, data=dict(foo=True))
1794    assert "" == r(code, data="")
1795
1796    # Make sure that the parameters have the same name in all implementations
1797    assert "[(f)(o)(o)" == r("<?for (f, value) in isfirst(iterable=data)?><?if f?>[<?end if?>(<?print value?>)<?end for?>", data="foo")
1798
1799
1800@pytest.mark.ul4
1801def test_function_islast(r):
1802    code = "<?for (l, value) in islast(data)?>(<?print value?>)<?if l?>]<?end if?><?end for?>"
1803
1804    with raises(argumentmismatchmessage):
1805        r("<?print islast()?>")
1806    with raises(argumentmismatchmessage):
1807        r("<?print islast(1, 2)?>")
1808    with raises("is not iterable|iter\\(.*\\) not supported"):
1809        r(code, data=None)
1810    with raises("is not iterable|iter\\(.*\\) not supported"):
1811        r(code, data=True)
1812    with raises("is not iterable|iter\\(.*\\) not supported"):
1813        r(code, data=False)
1814    with raises("is not iterable|iter\\(.*\\) not supported"):
1815        r(code, data=42)
1816    with raises("is not iterable|iter\\(.*\\) not supported"):
1817        r(code, data=4.2)
1818    assert "(f)(o)(o)]" == r(code, data="foo")
1819    assert "(foo)(bar)]" == r(code, data=["foo", "bar"])
1820    assert "(foo)]" == r(code, data=dict(foo=True))
1821    assert "" == r(code, data="")
1822
1823    # Make sure that the parameters have the same name in all implementations
1824    assert "(f)(o)(o)]" == r("<?for (l, value) in islast(iterable=data)?>(<?print value?>)<?if l?>]<?end if?><?end for?>", data="foo")
1825
1826
1827@pytest.mark.ul4
1828def test_function_isundefined(r):
1829    code = "<?print isundefined(data)?>"
1830
1831    with raises(argumentmismatchmessage):
1832        r("<?print isundefined()?>")
1833    with raises(argumentmismatchmessage):
1834        r("<?print isundefined(1, 2)?>")
1835    assert "True" == r(code)
1836    assert "False" == r(code, data=None)
1837    assert "False" == r(code, data=True)
1838    assert "False" == r(code, data=False)
1839    assert "False" == r(code, data=42)
1840    assert "False" == r(code, data=4.2)
1841    assert "False" == r(code, data="foo")
1842    assert "False" == r(code, data=datetime.datetime.now())
1843    assert "False" == r(code, data=datetime.timedelta(1))
1844    assert "False" == r(code, data=misc.monthdelta(1))
1845    assert "False" == r(code, data=())
1846    assert "False" == r(code, data=[])
1847    assert "False" == r(code, data={})
1848    assert "False" == r("<?print isundefined(repr)?>")
1849    assert "False" == r(code, data=ul4c.Template(""))
1850    assert "False" == r(code, data=color.red)
1851
1852    # Make sure that the parameters have the same name in all implementations
1853    assert "False" == r("<?print isundefined(obj=data)?>", data=None)
1854
1855
1856@pytest.mark.ul4
1857def test_function_isdefined(r):
1858    code = "<?print isdefined(data)?>"
1859
1860    with raises(argumentmismatchmessage):
1861        r("<?print isdefined()?>")
1862    with raises(argumentmismatchmessage):
1863        r("<?print isdefined(1, 2)?>")
1864    assert "False" == r(code)
1865    assert "True" == r(code, data=None)
1866    assert "True" == r(code, data=True)
1867    assert "True" == r(code, data=False)
1868    assert "True" == r(code, data=42)
1869    assert "True" == r(code, data=4.2)
1870    assert "True" == r(code, data="foo")
1871    assert "True" == r(code, data=datetime.datetime.now())
1872    assert "True" == r(code, data=datetime.timedelta(1))
1873    assert "True" == r(code, data=misc.monthdelta(1))
1874    assert "True" == r(code, data=())
1875    assert "True" == r(code, data=[])
1876    assert "True" == r(code, data={})
1877    assert "True" == r(code, data=ul4c.Template(""))
1878    assert "True" == r("<?print isdefined(repr)?>")
1879    assert "True" == r(code, data=color.red)
1880
1881    # Make sure that the parameters have the same name in all implementations
1882    assert "True" == r("<?print isdefined(obj=data)?>", data=None)
1883
1884
1885@pytest.mark.ul4
1886def test_function_isnone(r):
1887    code = "<?print isnone(data)?>"
1888
1889    with raises(argumentmismatchmessage):
1890        r("<?print isnone()?>")
1891    with raises(argumentmismatchmessage):
1892        r("<?print isnone(1, 2)?>")
1893    assert "False" == r(code)
1894    assert "True" == r(code, data=None)
1895    assert "False" == r(code, data=True)
1896    assert "False" == r(code, data=False)
1897    assert "False" == r(code, data=42)
1898    assert "False" == r(code, data=4.2)
1899    assert "False" == r(code, data="foo")
1900    assert "False" == r(code, data=datetime.datetime.now())
1901    assert "False" == r(code, data=datetime.timedelta(1))
1902    assert "False" == r(code, data=misc.monthdelta(1))
1903    assert "False" == r(code, data=())
1904    assert "False" == r(code, data=[])
1905    assert "False" == r(code, data={})
1906    assert "False" == r(code, data=ul4c.Template(""))
1907    assert "False" == r("<?print isnone(repr)?>")
1908    assert "False" == r(code, data=color.red)
1909
1910    # Make sure that the parameters have the same name in all implementations
1911    assert "True" == r("<?print isnone(obj=data)?>", data=None)
1912
1913
1914@pytest.mark.ul4
1915def test_function_isbool(r):
1916    code = "<?print isbool(data)?>"
1917
1918    with raises(argumentmismatchmessage):
1919        r("<?print isbool()?>")
1920    with raises(argumentmismatchmessage):
1921        r("<?print isbool(1, 2)?>")
1922    assert "False" == r(code)
1923    assert "False" == r(code, data=None)
1924    assert "True" == r(code, data=True)
1925    assert "True" == r(code, data=False)
1926    assert "False" == r(code, data=42)
1927    assert "False" == r(code, data=4.2)
1928    assert "False" == r(code, data="foo")
1929    assert "False" == r(code, data=datetime.datetime.now())
1930    assert "False" == r(code, data=datetime.timedelta(1))
1931    assert "False" == r(code, data=misc.monthdelta(1))
1932    assert "False" == r(code, data=())
1933    assert "False" == r(code, data=[])
1934    assert "False" == r(code, data={})
1935    assert "False" == r(code, data=ul4c.Template(""))
1936    assert "False" == r("<?print isbool(repr)?>")
1937    assert "False" == r(code, data=color.red)
1938
1939    # Make sure that the parameters have the same name in all implementations
1940    assert "False" == r("<?print isbool(obj=data)?>", data=None)
1941
1942
1943@pytest.mark.ul4
1944def test_function_isint(r):
1945    code = "<?print isint(data)?>"
1946
1947    with raises(argumentmismatchmessage):
1948        r("<?print isint()?>")
1949    with raises(argumentmismatchmessage):
1950        r("<?print isint(1, 2)?>")
1951    assert "False" == r(code)
1952    assert "False" == r(code, data=None)
1953    assert "False" == r(code, data=True)
1954    assert "False" == r(code, data=False)
1955    assert "True" == r(code, data=42)
1956    assert "False" == r(code, data=4.2)
1957    assert "False" == r(code, data="foo")
1958    assert "False" == r(code, data=datetime.datetime.now())
1959    assert "False" == r(code, data=datetime.timedelta(1))
1960    assert "False" == r(code, data=misc.monthdelta(1))
1961    assert "False" == r(code, data=())
1962    assert "False" == r(code, data=[])
1963    assert "False" == r(code, data={})
1964    assert "False" == r(code, data=ul4c.Template(""))
1965    assert "False" == r("<?print isint(repr)?>")
1966    assert "False" == r(code, data=color.red)
1967
1968    # Make sure that the parameters have the same name in all implementations
1969    assert "False" == r("<?print isint(obj=data)?>", data=None)
1970
1971
1972@pytest.mark.ul4
1973def test_function_isfloat(r):
1974    code = "<?print isfloat(data)?>"
1975
1976    with raises(argumentmismatchmessage):
1977        r("<?print isfloat()?>")
1978    with raises(argumentmismatchmessage):
1979        r("<?print isfloat(1, 2)?>")
1980    assert "False" == r(code)
1981    assert "False" == r(code, data=None)
1982    assert "False" == r(code, data=True)
1983    assert "False" == r(code, data=False)
1984    assert "False" == r(code, data=42)
1985    assert "True" == r(code, data=4.2)
1986    assert "False" == r(code, data="foo")
1987    assert "False" == r(code, data=datetime.datetime.now())
1988    assert "False" == r(code, data=datetime.timedelta(1))
1989    assert "False" == r(code, data=misc.monthdelta(1))
1990    assert "False" == r(code, data=())
1991    assert "False" == r(code, data=[])
1992    assert "False" == r(code, data={})
1993    assert "False" == r(code, data=ul4c.Template(""))
1994    assert "False" == r("<?print isfloat(repr)?>")
1995    assert "False" == r(code, data=color.red)
1996
1997    # Make sure that the parameters have the same name in all implementations
1998    assert "False" == r("<?print isfloat(obj=data)?>", data=None)
1999
2000
2001@pytest.mark.ul4
2002def test_function_isstr(r):
2003    code = "<?print isstr(data)?>"
2004
2005    with raises(argumentmismatchmessage):
2006        r("<?print isstr()?>")
2007    with raises(argumentmismatchmessage):
2008        r("<?print isstr(1, 2)?>")
2009    assert "False" == r(code)
2010    assert "False" == r(code, data=None)
2011    assert "False" == r(code, data=True)
2012    assert "False" == r(code, data=False)
2013    assert "False" == r(code, data=42)
2014    assert "False" == r(code, data=4.2)
2015    assert "True" == r(code, data="foo")
2016    assert "False" == r(code, data=datetime.datetime.now())
2017    assert "False" == r(code, data=datetime.timedelta(1))
2018    assert "False" == r(code, data=misc.monthdelta(1))
2019    assert "False" == r(code, data=())
2020    assert "False" == r(code, data=[])
2021    assert "False" == r(code, data={})
2022    assert "False" == r(code, data=ul4c.Template(""))
2023    assert "False" == r("<?print isstr(repr)?>")
2024    assert "False" == r(code, data=color.red)
2025
2026    # Make sure that the parameters have the same name in all implementations
2027    assert "False" == r("<?print isstr(obj=data)?>", data=None)
2028
2029
2030@pytest.mark.ul4
2031def test_function_isdate(r):
2032    code = "<?print isdate(data)?>"
2033
2034    with raises(argumentmismatchmessage):
2035        r("<?print isdate()?>")
2036    with raises(argumentmismatchmessage):
2037        r("<?print isdate(1, 2)?>")
2038    assert "False" == r(code)
2039    assert "False" == r(code, data=None)
2040    assert "False" == r(code, data=True)
2041    assert "False" == r(code, data=False)
2042    assert "False" == r(code, data=42)
2043    assert "False" == r(code, data=4.2)
2044    assert "False" == r(code, data="foo")
2045    assert "True" == r(code, data=datetime.datetime.now())
2046    assert "False" == r(code, data=datetime.timedelta(1))
2047    assert "False" == r(code, data=misc.monthdelta(1))
2048    assert "False" == r(code, data=())
2049    assert "False" == r(code, data=[])
2050    assert "False" == r(code, data={})
2051    assert "False" == r(code, data=ul4c.Template(""))
2052    assert "False" == r("<?print isdate(repr)?>")
2053    assert "False" == r(code, data=color.red)
2054
2055    # Make sure that the parameters have the same name in all implementations
2056    assert "False" == r("<?print isdate(obj=data)?>", data=None)
2057
2058
2059@pytest.mark.ul4
2060def test_function_islist(r):
2061    code = "<?print islist(data)?>"
2062
2063    with raises(argumentmismatchmessage):
2064        r("<?print islist()?>")
2065    with raises(argumentmismatchmessage):
2066        r("<?print islist(1, 2)?>")
2067    assert "False" == r(code)
2068    assert "False" == r(code, data=None)
2069    assert "False" == r(code, data=True)
2070    assert "False" == r(code, data=False)
2071    assert "False" == r(code, data=42)
2072    assert "False" == r(code, data=4.2)
2073    assert "False" == r(code, data="foo")
2074    assert "False" == r(code, data=datetime.datetime.now())
2075    assert "False" == r(code, data=datetime.timedelta(1))
2076    assert "False" == r(code, data=misc.monthdelta(1))
2077    assert "True" == r(code, data=())
2078    assert "True" == r(code, data=[])
2079    assert "True" == r(code, data=PseudoList([]))
2080    if r is not render_php:
2081        assert "False" == r(code, data={})
2082    assert "False" == r(code, data=ul4c.Template(""))
2083    assert "False" == r("<?print islist(repr)?>")
2084    assert "False" == r(code, data=color.red)
2085
2086    # Make sure that the parameters have the same name in all implementations
2087    assert "False" == r("<?print islist(obj=data)?>", data=None)
2088
2089
2090@pytest.mark.ul4
2091def test_function_isdict(r):
2092    code = "<?print isdict(data)?>"
2093
2094    with raises(argumentmismatchmessage):
2095        r("<?print isdict()?>")
2096    with raises(argumentmismatchmessage):
2097        r("<?print isdict(1, 2)?>")
2098    assert "False" == r(code)
2099    assert "False" == r(code, data=None)
2100    assert "False" == r(code, data=True)
2101    assert "False" == r(code, data=False)
2102    assert "False" == r(code, data=42)
2103    assert "False" == r(code, data=4.2)
2104    assert "False" == r(code, data="foo")
2105    assert "False" == r(code, data=datetime.datetime.now())
2106    assert "False" == r(code, data=datetime.timedelta(1))
2107    assert "False" == r(code, data=misc.monthdelta(1))
2108    if r is not render_php:
2109        assert "False" == r(code, data=())
2110        assert "False" == r(code, data=[])
2111    assert "True" == r(code, data={})
2112    assert "True" == r(code, data=PseudoDict({}))
2113    assert "False" == r(code, data=ul4c.Template(""))
2114    assert "False" == r("<?print isdict(repr)?>")
2115    assert "False" == r(code, data=color.red)
2116
2117    # Make sure that the parameters have the same name in all implementations
2118    assert "False" == r("<?print isdict(obj=data)?>", data=None)
2119
2120
2121@pytest.mark.ul4
2122def test_function_istemplate(r):
2123    code = "<?print istemplate(data)?>"
2124
2125    with raises(argumentmismatchmessage):
2126        r("<?print istemplate()?>")
2127    with raises(argumentmismatchmessage):
2128        r("<?print istemplate(1, 2)?>")
2129    assert "False" == r(code)
2130    assert "False" == r(code, data=None)
2131    assert "False" == r(code, data=True)
2132    assert "False" == r(code, data=False)
2133    assert "False" == r(code, data=42)
2134    assert "False" == r(code, data=4.2)
2135    assert "False" == r(code, data="foo")
2136    assert "False" == r(code, data=datetime.datetime.now())
2137    assert "False" == r(code, data=datetime.timedelta(1))
2138    assert "False" == r(code, data=misc.monthdelta(1))
2139    assert "False" == r(code, data=())
2140    assert "False" == r(code, data=[])
2141    assert "False" == r(code, data={})
2142    assert "True" == r(code, data=ul4c.Template(""))
2143    assert "False" == r("<?print istemplate(repr)?>")
2144    assert "False" == r(code, data=color.red)
2145
2146    # Make sure that the parameters have the same name in all implementations
2147    assert "False" == r("<?print istemplate(obj=data)?>", data=None)
2148
2149
2150@pytest.mark.ul4
2151def test_function_isfunction(r):
2152    code = "<?print isfunction(data)?>"
2153
2154    with raises(argumentmismatchmessage):
2155        r("<?print isfunction()?>")
2156    with raises(argumentmismatchmessage):
2157        r("<?print isfunction(1, 2)?>")
2158    assert "False" == r(code)
2159    assert "False" == r(code, data=None)
2160    assert "False" == r(code, data=True)
2161    assert "False" == r(code, data=False)
2162    assert "False" == r(code, data=42)
2163    assert "False" == r(code, data=4.2)
2164    assert "False" == r(code, data="foo")
2165    assert "False" == r(code, data=datetime.datetime.now())
2166    assert "False" == r(code, data=datetime.timedelta(1))
2167    assert "False" == r(code, data=misc.monthdelta(1))
2168    assert "False" == r(code, data=())
2169    assert "False" == r(code, data=[])
2170    assert "False" == r(code, data={})
2171    assert "True" == r(code, data=ul4c.Template(""))
2172    assert "True" == r("<?print isfunction(repr)?>")
2173    assert "True" == r("<?def f?><?return 42?><?end def?><?print isfunction(f)?>")
2174    assert "False" == r(code, data=color.red)
2175
2176    # Make sure that the parameters have the same name in all implementations
2177    assert "False" == r("<?print istemplate(obj=data)?>", data=None)
2178
2179
2180@pytest.mark.ul4
2181def test_function_iscolor(r):
2182    code = "<?print iscolor(data)?>"
2183
2184    with raises(argumentmismatchmessage):
2185        r("<?print iscolor()?>")
2186    with raises(argumentmismatchmessage):
2187        r("<?print iscolor(1, 2)?>")
2188    assert "False" == r(code)
2189    assert "False" == r(code, data=None)
2190    assert "False" == r(code, data=True)
2191    assert "False" == r(code, data=False)
2192    assert "False" == r(code, data=42)
2193    assert "False" == r(code, data=4.2)
2194    assert "False" == r(code, data="foo")
2195    assert "False" == r(code, data=datetime.datetime.now())
2196    assert "False" == r(code, data=datetime.timedelta(1))
2197    assert "False" == r(code, data=misc.monthdelta(1))
2198    assert "False" == r(code, data=())
2199    assert "False" == r(code, data=[])
2200    assert "False" == r(code, data={})
2201    assert "False" == r(code, data=ul4c.Template(""))
2202    assert "False" == r("<?print iscolor(repr)?>")
2203    assert "True" == r(code, data=color.red)
2204
2205    # Make sure that the parameters have the same name in all implementations
2206    assert "False" == r("<?print iscolor(obj=data)?>", data=None)
2207
2208
2209@pytest.mark.ul4
2210def test_function_istimedelta(r):
2211    code = "<?print istimedelta(data)?>"
2212
2213    with raises(argumentmismatchmessage):
2214        r("<?print istimedelta()?>")
2215    with raises(argumentmismatchmessage):
2216        r("<?print istimedelta(1, 2)?>")
2217    assert "False" == r(code)
2218    assert "False" == r(code, data=None)
2219    assert "False" == r(code, data=True)
2220    assert "False" == r(code, data=False)
2221    assert "False" == r(code, data=42)
2222    assert "False" == r(code, data=4.2)
2223    assert "False" == r(code, data="foo")
2224    assert "False" == r(code, data=datetime.datetime.now())
2225    assert "True" == r(code, data=datetime.timedelta(1))
2226    assert "False" == r(code, data=misc.monthdelta(1))
2227    assert "False" == r(code, data=())
2228    assert "False" == r(code, data=[])
2229    assert "False" == r(code, data={})
2230    assert "False" == r(code, data=ul4c.Template(""))
2231    assert "False" == r("<?print istimedelta(repr)?>")
2232    assert "False" == r(code, data=color.red)
2233
2234    # Make sure that the parameters have the same name in all implementations
2235    assert "False" == r("<?print istimedelta(obj=data)?>", data=None)
2236
2237
2238@pytest.mark.ul4
2239def test_function_ismonthdelta(r):
2240    code = "<?print ismonthdelta(data)?>"
2241
2242    with raises(argumentmismatchmessage):
2243        r("<?print ismonthdelta()?>")
2244    with raises(argumentmismatchmessage):
2245        r("<?print ismonthdelta(1, 2)?>")
2246    assert "False" == r(code)
2247    assert "False" == r(code, data=None)
2248    assert "False" == r(code, data=True)
2249    assert "False" == r(code, data=False)
2250    assert "False" == r(code, data=42)
2251    assert "False" == r(code, data=4.2)
2252    assert "False" == r(code, data="foo")
2253    assert "False" == r(code, data=datetime.datetime.now())
2254    assert "False" == r(code, data=datetime.timedelta(1))
2255    assert "True" == r(code, data=misc.monthdelta(1))
2256    assert "False" == r(code, data=())
2257    assert "False" == r(code, data=[])
2258    assert "False" == r(code, data={})
2259    assert "False" == r(code, data=ul4c.Template(""))
2260    assert "False" == r("<?print ismonthdelta(repr)?>")
2261    assert "False" == r(code, data=color.red)
2262
2263    # Make sure that the parameters have the same name in all implementations
2264    assert "False" == r("<?print ismonthdelta(obj=data)?>", data=None)
2265
2266
2267@pytest.mark.ul4
2268def test_function_repr(r):
2269    code = "<?print repr(data)?>"
2270
2271    with raises(argumentmismatchmessage):
2272        r("<?print repr()?>")
2273    with raises(argumentmismatchmessage):
2274        r("<?print repr(1, 2)?>")
2275    assert "None" == r(code, data=None)
2276    assert "True" == r(code, data=True)
2277    assert "False" == r(code, data=False)
2278    assert "42" == r(code, data=42)
2279    assert 42.5 == eval(r(code, data=42.5))
2280    assert r(code, data="foo") in ('"foo"', "'foo'")
2281    assert [1, 2, 3] == eval(r(code, data=[1, 2, 3]))
2282    if r is not render_js:
2283        assert [1, 2, 3] == eval(r(code, data=(1, 2, 3)))
2284    assert {"a": 1, "b": 2} == eval(r(code, data={"a": 1, "b": 2}))
2285    if r is not render_php:
2286        assert "@(2011-02-07T12:34:56.123000)" == r(code, data=datetime.datetime(2011, 2, 7, 12, 34, 56, 123000))
2287    assert "@(2011-02-07T12:34:56)" == r(code, data=datetime.datetime(2011, 2, 7, 12, 34, 56))
2288    assert "@(2011-02-07)" == r(code, data=datetime.datetime(2011, 2, 7))
2289    assert "@(2011-02-07)" == r(code, data=datetime.date(2011, 2, 7))
2290    assert "timedelta(1)" == r(code, data=datetime.timedelta(1))
2291    assert "timedelta(0, 1)" == r(code, data=datetime.timedelta(0, 1))
2292    assert "timedelta(0, 0, 1)" == r(code, data=datetime.timedelta(0, 0, 1))
2293    assert "timedelta(-1)" == r(code, data=datetime.timedelta(-1))
2294    assert "timedelta(-1, 86399)" == r(code, data=datetime.timedelta(0, -1))
2295    assert "timedelta(-1, 86399, 999999)" == r(code, data=datetime.timedelta(0, 0, -1))
2296    assert "timedelta(0, 43200)" == r(code, data=datetime.timedelta(0.5))
2297    assert "timedelta(0, 0, 500000)" == r(code, data=datetime.timedelta(0, 0.5))
2298    assert "timedelta(-1, 43200)" == r(code, data=datetime.timedelta(-0.5))
2299    assert "timedelta(-1, 86399, 500000)" == r(code, data=datetime.timedelta(0, -0.5))
2300
2301    # Make sure that the parameters have the same name in all implementations
2302    assert "None" == r("<?print repr(obj=data)?>", data=None)
2303
2304
2305@pytest.mark.ul4
2306def test_function_format_date(r):
2307    t = datetime.datetime(2011, 1, 25, 13, 34, 56, 987000)
2308    code2 = "<?print format(data, fmt)?>"
2309    code3 = "<?print format(data, fmt, lang)?>"
2310
2311    assert "2011" == r(code2, fmt="%Y", data=t)
2312    assert "01" == r(code2, fmt="%m", data=t)
2313    assert "25" == r(code2, fmt="%d", data=t)
2314    assert "13" == r(code2, fmt="%H", data=t)
2315    assert "34" == r(code2, fmt="%M", data=t)
2316    assert "56" == r(code2, fmt="%S", data=t)
2317    assert "987000" == r(code2, fmt="%f", data=t)
2318    assert "Tue" == r(code2, fmt="%a", data=t)
2319    assert "Tue" == r(code3, fmt="%a", data=t, lang=None)
2320    assert "Tue" == r(code3, fmt="%a", data=t, lang="en")
2321    assert "Di" == r(code3, fmt="%a", data=t, lang="de")
2322    assert "Di" == r(code3, fmt="%a", data=t, lang="de_DE")
2323    assert "Tuesday" == r(code2, fmt="%A", data=t)
2324    assert "Tuesday" == r(code3, fmt="%A", data=t, lang=None)
2325    assert "Tuesday" == r(code3, fmt="%A", data=t, lang="en")
2326    assert "Dienstag" == r(code3, fmt="%A", data=t, lang="de")
2327    assert "Dienstag" == r(code3, fmt="%A", data=t, lang="de_DE")
2328    assert "Jan" == r(code2, fmt="%b", data=t)
2329    assert "Jan" == r(code3, fmt="%b", data=t, lang=None)
2330    assert "Jan" == r(code3, fmt="%b", data=t, lang="en")
2331    assert "Jan" == r(code3, fmt="%b", data=t, lang="de")
2332    assert "Jan" == r(code3, fmt="%b", data=t, lang="de_DE")
2333    assert "January" == r(code2, fmt="%B", data=t)
2334    assert "January" == r(code3, fmt="%B", data=t, lang=None)
2335    assert "January" == r(code3, fmt="%B", data=t, lang="en")
2336    assert "Januar" == r(code3, fmt="%B", data=t, lang="de")
2337    assert "Januar" == r(code3, fmt="%B", data=t, lang="de_DE")
2338    assert "01" == r(code2, fmt="%I", data=t)
2339    assert "025" == r(code2, fmt="%j", data=t)
2340    assert "PM" == r(code2, fmt="%p", data=t)
2341    assert "04" == r(code2, fmt="%U", data=t)
2342    assert "2" == r(code2, fmt="%w", data=t)
2343    assert "04" == r(code2, fmt="%W", data=t)
2344    assert "11" == r(code2, fmt="%y", data=t)
2345    assert r(code2, fmt="%c", data=t) in ("Tue Jan 25 13:34:56 2011", "Tue 25 Jan 2011 01:34:56 PM", "Tue 25 Jan 2011 01:34:56 PM ")
2346    assert "01/25/2011" == r(code2, fmt="%x", data=t)
2347    assert "01/25/2011" == r(code3, fmt="%x", data=t, lang=None)
2348    assert "01/25/2011" == r(code3, fmt="%x", data=t, lang="en")
2349    assert "25.01.2011" == r(code3, fmt="%x", data=t, lang="de")
2350    assert "25.01.2011" == r(code3, fmt="%x", data=t, lang="de_DE")
2351    assert r(code2, fmt="%X", data=t) in ("13:34:56", "01:34:56 PM")
2352    assert r(code3, fmt="%X", data=t, lang=None) in ("13:34:56", "01:34:56 PM")
2353    assert r(code3, fmt="%X", data=t, lang="en") in ("13:34:56", "01:34:56 PM")
2354    assert "13:34:56" == r(code3, fmt="%X", data=t, lang="de")
2355    assert "13:34:56" == r(code3, fmt="%X", data=t, lang="de_DE")
2356    assert "%" == r(code2, fmt="%%", data=t)
2357
2358
2359@pytest.mark.ul4
2360def test_function_format_int(r):
2361    code2 = "<?print format(data, fmt)?>"
2362    code3 = "<?print format(data, fmt, lang)?>"
2363
2364    formatstrings = [
2365        "",
2366        "",
2367        "5",
2368        "05",
2369        "05",
2370        "+05",
2371        "+8b",
2372        "+#10b",
2373        "o",
2374        "+#x",
2375        "+#X",
2376        "<5",
2377        ">5",
2378        "?>5",
2379        "^5",
2380        "?= 5",
2381        "?= #11b",
2382    ]
2383
2384    for f in formatstrings:
2385        assert format(42, f) == r(code2, data=42, fmt=f)
2386        if "c" not in f:
2387            assert format(-42, f) == r(code2, data=-42, fmt=f)
2388    assert format(True, "05") == r(code2, data=True, fmt="05")
2389
2390
2391@pytest.mark.ul4
2392def test_function_format_kwargs(r):
2393    assert "42" == r("<?print format(obj=data, fmt=fmt, lang=lang)?>", fmt="", data=42, lang="de")
2394
2395
2396@pytest.mark.ul4
2397def test_function_chr(r):
2398    code = "<?print chr(data)?>"
2399
2400    with raises(argumentmismatchmessage):
2401        r("<?print chr()?>")
2402    with raises(argumentmismatchmessage):
2403        r("<?print chr(1, 2)?>")
2404    assert "\x00" == r(code, data=0)
2405    assert "a" == r(code, data=ord("a"))
2406    assert "\u20ac" == r(code, data=0x20ac)
2407
2408    # Make sure that the parameters have the same name in all implementations
2409    assert "\x00" == r("<?print chr(i=data)?>", data=0)
2410
2411
2412@pytest.mark.ul4
2413def test_function_ord(r):
2414    code = "<?print ord(data)?>"
2415
2416    with raises(argumentmismatchmessage):
2417        r("<?print ord()?>")
2418    with raises(argumentmismatchmessage):
2419        r("<?print ord(1, 2)?>")
2420    assert "0" == r(code, data="\x00")
2421    assert str(ord("a")) == r(code, data="a")
2422    assert str(0x20ac) == r(code, data="\u20ac")
2423
2424    # Make sure that the parameters have the same name in all implementations
2425    assert "0" == r("<?print ord(c=data)?>", data="\x00")
2426
2427
2428@pytest.mark.ul4
2429def test_function_hex(r):
2430    code = "<?print hex(data)?>"
2431
2432    with raises(argumentmismatchmessage):
2433        r("<?print hex()?>")
2434    with raises(argumentmismatchmessage):
2435        r("<?print hex(1, 2)?>")
2436    assert "0x0" == r(code, data=0)
2437    assert "0xff" == r(code, data=0xff)
2438    assert "0xffff" == r(code, data=0xffff)
2439    assert "-0xffff" == r(code, data=-0xffff)
2440
2441    # Make sure that the parameters have the same name in all implementations
2442    assert "0x0" == r("<?print hex(number=data)?>", data=0)
2443
2444
2445@pytest.mark.ul4
2446def test_function_oct(r):
2447    code = "<?print oct(data)?>"
2448
2449    with raises(argumentmismatchmessage):
2450        r("<?print oct()?>")
2451    with raises(argumentmismatchmessage):
2452        r("<?print oct(1, 2)?>")
2453    assert "0o0" == r(code, data=0)
2454    assert "0o77" == r(code, data=0o77)
2455    assert "0o7777" == r(code, data=0o7777)
2456    assert "-0o7777" == r(code, data=-0o7777)
2457
2458    # Make sure that the parameters have the same name in all implementations
2459    assert "0o0" == r("<?print oct(number=data)?>", data=0)
2460
2461
2462@pytest.mark.ul4
2463def test_function_bin(r):
2464    code = "<?print bin(data)?>"
2465
2466    with raises(argumentmismatchmessage):
2467        r("<?print bin()?>")
2468    with raises(argumentmismatchmessage):
2469        r("<?print bin(1, 2)?>")
2470    assert "0b0" == r(code, data=0b0)
2471    assert "0b11" == r(code, data=0b11)
2472    assert "-0b1111" == r(code, data=-0b1111)
2473
2474
2475@pytest.mark.ul4
2476def test_function_bin_kwargs(r):
2477    assert "0b0" == r("<?print bin(number=data)?>", data=0)
2478
2479
2480@pytest.mark.ul4
2481def test_function_abs(r):
2482    code = "<?print abs(data)?>"
2483
2484    with raises(argumentmismatchmessage):
2485        r("<?print abs()?>")
2486    with raises(argumentmismatchmessage):
2487        r("<?print abs(1, 2)?>")
2488    assert "0" == r(code, data=0)
2489    assert "42" == r(code, data=42)
2490    assert "42" == r(code, data=-42)
2491    assert "1 month" == r(code, data=misc.monthdelta(-1))
2492    assert "1 day, 0:00:01.000001" == r(code, data=datetime.timedelta(-1, -1, -1))
2493
2494    # Make sure that the parameters have the same name in all implementations
2495    assert "0" == r("<?print abs(number=data)?>", data=0)
2496
2497
2498@pytest.mark.ul4
2499def test_function_sorted(r):
2500    code = "<?for i in sorted(data)?><?print i?><?end for?>"
2501
2502    with raises(argumentmismatchmessage):
2503        r("<?print sorted()?>")
2504    assert "gkru" == r(code, data="gurk")
2505    assert "24679" == r(code, data="92746")
2506    assert "172342" == r(code, data=(42, 17, 23))
2507    assert "012" == r(code, data={0: "zero", 1: "one", 2: "two"})
2508
2509    # Make sure that the parameters have the same name in all implementations
2510    assert "123" == r("<?for i in sorted(iterable=data)?><?print i?><?end for?>", data="321")
2511
2512
2513@pytest.mark.ul4
2514def test_function_range(r):
2515    code1 = "<?for i in range(data)?><?print i?>;<?end for?>"
2516    code2 = "<?for i in range(data[0], data[1])?><?print i?>;<?end for?>"
2517    code3 = "<?for i in range(data[0], data[1], data[2])?><?print i?>;<?end for?>"
2518
2519    with raises(argumentmismatchmessage):
2520        r("<?print range()?>")
2521    with raises(argumentmismatchmessage):
2522        r("<?print range(1, 2, 3, 4)?>")
2523    assert "" == r(code1, data=-10)
2524    assert "" == r(code1, data=0)
2525    assert "0;" == r(code1, data=1)
2526    assert "0;1;2;3;4;" == r(code1, data=5)
2527    assert "" == r(code2, data=[0, -10])
2528    assert "" == r(code2, data=[0, 0])
2529    assert "0;1;2;3;4;" == r(code2, data=[0, 5])
2530    assert "-5;-4;-3;-2;-1;0;1;2;3;4;" == r(code2, data=[-5, 5])
2531    assert "" == r(code3, data=[0, -10, 1])
2532    assert "" == r(code3, data=[0, 0, 1])
2533    assert "0;2;4;6;8;" == r(code3, data=[0, 10, 2])
2534    assert "" == r(code3, data=[0, 10, -2])
2535    assert "10;8;6;4;2;" == r(code3, data=[10, 0, -2])
2536    assert "" == r(code3, data=[10, 0, 2])
2537
2538
2539@pytest.mark.ul4
2540def test_function_urlquote(r):
2541    assert "gurk" == r("<?print urlquote('gurk')?>")
2542    assert "%3C%3D%3E%2B%3F" == r("<?print urlquote('<=>+?')?>")
2543    assert "%7F%C3%BF%EF%BF%BF" == r("<?print urlquote('\u007f\u00ff\uffff')?>")
2544
2545    # Make sure that the parameters have the same name in all implementations
2546    assert "gurk" == r("<?print urlquote(string='gurk')?>")
2547
2548
2549@pytest.mark.ul4
2550def test_function_urlunquote(r):
2551    assert "gurk" == r("<?print urlunquote('gurk')?>")
2552    assert "<=>+?" == r("<?print urlunquote('%3C%3D%3E%2B%3F')?>")
2553    assert "\u007f\u00ff\uffff" == r("<?print urlunquote('%7F%C3%BF%EF%BF%BF')?>")
2554
2555    # Make sure that the parameters have the same name in all implementations
2556    assert "gurk" == r("<?print urlunquote(string='gurk')?>")
2557
2558
2559@pytest.mark.ul4
2560def test_function_zip(r):
2561    code0 = "<?for i in zip()?><?print i?>;<?end for?>"
2562    code1 = "<?for (ix, ) in zip(x)?><?print ix?>;<?end for?>"
2563    code2 = "<?for (ix, iy) in zip(x, y)?><?print ix?>-<?print iy?>;<?end for?>"
2564    code3 = "<?for (ix, iy, iz) in zip(x, y, z)?><?print ix?>-<?print iy?>+<?print iz?>;<?end for?>"
2565
2566    assert "" == r(code0)
2567    assert "1;2;" == r(code1, x=[1, 2])
2568    assert "" == r(code2, x=[], y=[])
2569    assert "1-3;2-4;" == r(code2, x=[1, 2], y=[3, 4])
2570    assert "1-4;2-5;" == r(code2, x=[1, 2, 3], y=[4, 5])
2571    assert "" == r(code3, x=[], y=[], z=[])
2572    assert "1-3+5;2-4+6;" == r(code3, x=[1, 2], y=[3, 4], z=[5, 6])
2573    assert "1-4+6;" == r(code3, x=[1, 2, 3], y=[4, 5], z=[6])
2574
2575
2576@pytest.mark.ul4
2577def test_function_type(r):
2578    code = "<?print type(x)?>"
2579
2580    with raises(argumentmismatchmessage):
2581        r("<?print type()?>")
2582    with raises(argumentmismatchmessage):
2583        r("<?print type(1, 2)?>")
2584    assert "undefined" == r(code)
2585    assert "none" == r(code, x=None)
2586    assert "bool" == r(code, x=False)
2587    assert "bool" == r(code, x=True)
2588    assert "int" == r(code, x=42)
2589    assert "float" == r(code, x=4.2)
2590    assert "str" == r(code, x="foo")
2591    assert "date" == r(code, x=datetime.datetime.now())
2592    assert "date" == r(code, x=datetime.date.today())
2593    assert "timedelta" == r(code, x=datetime.timedelta())
2594    assert "monthdelta" == r(code, x=misc.monthdelta())
2595    assert "list" == r(code, x=(1, 2))
2596    assert "list" == r(code, x=[1, 2])
2597    assert "list" == r(code, x=PseudoList([1, 2]))
2598    assert "dict" == r(code, x={1: 2})
2599    assert "dict" == r(code, x=PseudoDict({1: 2}))
2600    assert "template" == r(code, x=ul4c.Template(""))
2601    assert "template" == r("<?def t?><?end def?><?print type(t)?>")
2602    assert "function" == r("<?print type(repr)?>")
2603    assert "color" == r(code, x=color.red)
2604
2605    # Make sure that the parameters have the same name in all implementations
2606    assert "none" == r("<?print type(obj=x)?>", x=None)
2607
2608
2609@pytest.mark.ul4
2610def test_function_reversed(r):
2611    code = "<?for i in reversed(x)?>(<?print i?>)<?end for?>"
2612
2613    with raises(argumentmismatchmessage):
2614        r("<?print reversed()?>")
2615    with raises(argumentmismatchmessage):
2616        r("<?print reversed(1, 2)?>")
2617    assert "(3)(2)(1)" == r(code, x="123")
2618    assert "(3)(2)(1)" == r(code, x=[1, 2, 3])
2619    assert "(3)(2)(1)" == r(code, x=(1, 2, 3))
2620
2621    # Make sure that the parameters have the same name in all implementations
2622    assert "(3)(2)(1)" == r("<?for i in reversed(sequence=x)?>(<?print i?>)<?end for?>", x=(1, 2, 3))
2623
2624
2625@pytest.mark.ul4
2626def test_function_min(r):
2627    with raises(argumentmismatchmessage):
2628        r("<?print min()?>")
2629    with raises("empty sequence"):
2630        r("<?print min([])?>")
2631    assert "1" == r("<?print min('123')?>")
2632    assert "1" == r("<?print min(1, 2, 3)?>")
2633    assert "0" == r("<?print min(0, False, 1, True)?>")
2634    assert "False" == r("<?print min(False, 0, True, 1)?>")
2635    assert "False" == r("<?print min([False, 0, True, 1])?>")
2636
2637
2638@pytest.mark.ul4
2639def test_function_max(r):
2640    with raises(argumentmismatchmessage):
2641        r("<?print max()?>")
2642    with raises("empty sequence"):
2643        r("<?print max([])?>")
2644    assert "3" == r("<?print max('123')?>")
2645    assert "3" == r("<?print max(1, 2, 3)?>")
2646    assert "1" == r("<?print max(0, False, 1, True)?>")
2647    assert "True" == r("<?print max(False, 0, True, 1)?>")
2648    assert "True" == r("<?print max([False, 0, True, 1])?>")
2649
2650
2651@pytest.mark.ul4
2652def test_function_rgb(r):
2653    assert "#369" == r("<?print repr(rgb(0.2, 0.4, 0.6))?>")
2654    assert "#369c" == r("<?print repr(rgb(0.2, 0.4, 0.6, 0.8))?>")
2655
2656    # Make sure that the parameters have the same name in all implementations
2657    assert "#369c" == r("<?print repr(rgb(r=0.2, g=0.4, b=0.6, a=0.8))?>")
2658
2659
2660@pytest.mark.ul4
2661def test_function_hls(r):
2662    assert "#fff" == r("<?print repr(hls(0, 1, 0))?>")
2663    assert "#fff0" == r("<?print repr(hls(0, 1, 0, 0))?>")
2664
2665    # Make sure that the parameters have the same name in all implementations
2666    assert "#fff0" == r("<?print repr(hls(h=0, l=1, s=0, a=0))?>")
2667
2668
2669@pytest.mark.ul4
2670def test_function_hsv(r):
2671    assert "#fff" == r("<?print repr(hsv(0, 0, 1))?>")
2672    assert "#fff0" == r("<?print repr(hsv(0, 0, 1, 0))?>")
2673
2674    # Make sure that the parameters have the same name in all implementations
2675    assert "#fff0" == r("<?print repr(hsv(h=0, s=0, v=1, a=0))?>")
2676
2677
2678@pytest.mark.ul4
2679def test_method_upper(r):
2680    assert "GURK" == r("<?print 'gurk'.upper()?>")
2681
2682
2683@pytest.mark.ul4
2684def test_method_lower(r):
2685    assert "gurk" == r("<?print 'GURK'.lower()?>")
2686
2687
2688@pytest.mark.ul4
2689def test_method_capitalize(r):
2690    assert "Gurk" == r("<?print 'gURK'.capitalize()?>")
2691
2692
2693@pytest.mark.ul4
2694def test_method_startswith(r):
2695    assert "True" == r("<?print 'gurkhurz'.startswith('gurk')?>")
2696    assert "False" == r("<?print 'gurkhurz'.startswith('hurz')?>")
2697
2698    # Make sure that the parameters have the same name in all implementations
2699    assert "True" == r("<?print 'gurkhurz'.startswith(prefix='gurk')?>")
2700
2701
2702@pytest.mark.ul4
2703def test_method_endswith(r):
2704    assert "True" == r("<?print 'gurkhurz'.endswith('hurz')?>")
2705    assert "False" == r("<?print 'gurkhurz'.endswith('gurk')?>")
2706
2707    # Make sure that the parameters have the same name in all implementations
2708    assert "True" == r("<?print 'gurkhurz'.endswith(suffix='hurz')?>")
2709
2710
2711@pytest.mark.ul4
2712def test_method_strip(r):
2713    assert "gurk" == r(r"<?print obj.strip()?>", obj=' \t\r\ngurk \t\r\n')
2714    assert "gurk" == r(r"<?print obj.strip('xyz')?>", obj='xyzzygurkxyzzy')
2715
2716    # Make sure that the parameters have the same name in all implementations
2717    assert "gurk" == r(r"<?print obj.strip(chars='xyz')?>", obj='xyzzygurkxyzzy')
2718
2719
2720@pytest.mark.ul4
2721def test_method_lstrip(r):
2722    assert "gurk \t\r\n" == r("<?print obj.lstrip()?>", obj=" \t\r\ngurk \t\r\n")
2723    assert "gurkxyzzy" == r("<?print obj.lstrip(arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
2724
2725    # Make sure that the parameters have the same name in all implementations
2726    assert "gurkxyzzy" == r("<?print obj.lstrip(chars=arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
2727
2728
2729@pytest.mark.ul4
2730def test_method_rstrip(r):
2731    assert " \t\r\ngurk" == r("<?print obj.rstrip()?>", obj=" \t\r\ngurk \t\r\n")
2732    assert "xyzzygurk" == r("<?print obj.rstrip(arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
2733
2734    # Make sure that the parameters have the same name in all implementations
2735    assert "xyzzygurk" == r("<?print obj.rstrip(chars=arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
2736
2737
2738@pytest.mark.ul4
2739def test_method_split(r):
2740    assert "(f)(o)(o)" == r("<?for item in obj.split()?>(<?print item?>)<?end for?>", obj=" \t\r\nf \t\r\no \t\r\no \t\r\n")
2741    assert "(f)(o \t\r\no \t\r\n)" == r("<?for item in obj.split(None, 1)?>(<?print item?>)<?end for?>", obj=" \t\r\nf \t\r\no \t\r\no \t\r\n")
2742    assert "()(f)(o)(o)()" == r("<?for item in obj.split(arg)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2743    assert "()(f)(oxxoxx)" == r("<?for item in obj.split(arg, 2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2744
2745    # Make sure that the parameters have the same name in all implementations
2746    assert "()(f)(oxxoxx)" == r("<?for item in obj.split(sep=arg, count=2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2747
2748
2749@pytest.mark.ul4
2750def test_method_rsplit(r):
2751    assert "(f)(o)(o)" == r("<?for item in obj.rsplit()?>(<?print item?>)<?end for?>", obj=" \t\r\nf \t\r\no \t\r\no \t\r\n")
2752    assert "( \t\r\nf \t\r\no)(o)" == r("<?for item in obj.rsplit(None, 1)?>(<?print item?>)<?end for?>", obj=" \t\r\nf \t\r\no \t\r\no \t\r\n")
2753    assert "()(f)(o)(o)()" == r("<?for item in obj.rsplit(arg)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2754    assert "(xxfxxo)(o)()" == r("<?for item in obj.rsplit(arg, 2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2755
2756    # Make sure that the parameters have the same name in all implementations
2757    assert "(xxfxxo)(o)()" == r("<?for item in obj.rsplit(sep=arg, count=2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2758
2759
2760@pytest.mark.ul4
2761def test_method_replace(r):
2762    assert 'goork' == r("<?print 'gurk'.replace('u', 'oo')?>")
2763    assert 'fuuuu' == r("<?print 'foo'.replace('o', 'uu', None)?>")
2764    assert 'fuuo' == r("<?print 'foo'.replace('o', 'uu', 1)?>")
2765
2766    # Make sure that the parameters have the same name in all implementations
2767    assert 'fuuo' == r("<?print 'foo'.replace(old='o', new='uu', count=1)?>")
2768
2769
2770@pytest.mark.ul4
2771def test_method_renders(r):
2772    t = ul4c.Template('(<?print data?>)')
2773    assert '(GURK)' == r("<?print t.renders(data='gurk').upper()?>", t=t)
2774    assert '(GURK)' == r("<?print t.renders(**{'data': 'gurk'}).upper()?>", t=t)
2775
2776    t = ul4c.Template('(gurk)')
2777    assert '(GURK)' == r("<?print t.renders().upper()?>", t=t)
2778
2779
2780@pytest.mark.ul4
2781def test_method_mimeformat(r):
2782    t = datetime.datetime(2010, 2, 22, 12, 34, 56)
2783
2784    assert 'Mon, 22 Feb 2010 12:34:56 GMT' == r(r"<?print data.mimeformat()?>", data=t)
2785
2786
2787@pytest.mark.ul4
2788def test_method_items(r):
2789    assert "a:42;b:17;c:23;" == r("<?for (key, value) in sorted(data.items())?><?print key?>:<?print value?>;<?end for?>", data=dict(a=42, b=17, c=23))
2790
2791
2792@pytest.mark.ul4
2793def test_method_values(r):
2794    assert "17;23;42;" == r("<?for value in sorted(data.values())?><?print value?>;<?end for?>", data=dict(a=42, b=17, c=23))
2795
2796
2797@pytest.mark.ul4
2798def test_method_get(r):
2799    assert "42" == r("<?print {}.get('foo', 42)?>")
2800    assert "17" == r("<?print {'foo': 17}.get('foo', 42)?>")
2801    assert "" == r("<?print {}.get('foo')?>")
2802    assert "17" == r("<?print {'foo': 17}.get('foo')?>")
2803
2804    # Make sure that the parameters have the same name in all implementations
2805    assert "17" == r("<?print {'foo': 17}.get(key='foo', default=42)?>")
2806
2807
2808@pytest.mark.ul4
2809def test_method_r_g_b_a(r):
2810    assert '0x11' == r('<?code c = #123?><?print hex(c.r())?>')
2811    assert '0x22' == r('<?code c = #123?><?print hex(c.g())?>')
2812    assert '0x33' == r('<?code c = #123?><?print hex(c.b())?>')
2813    assert '0xff' == r('<?code c = #123?><?print hex(c.a())?>')
2814
2815
2816@pytest.mark.ul4
2817def test_method_hls(r):
2818    assert '0' == r('<?code c = #fff?><?print int(c.hls()[0])?>')
2819    assert '1' == r('<?code c = #fff?><?print int(c.hls()[1])?>')
2820    assert '0' == r('<?code c = #fff?><?print int(c.hls()[2])?>')
2821
2822
2823@pytest.mark.ul4
2824def test_method_hlsa(r):
2825    assert '0' == r('<?code c = #fff?><?print int(c.hlsa()[0])?>')
2826    assert '1' == r('<?code c = #fff?><?print int(c.hlsa()[1])?>')
2827    assert '0' == r('<?code c = #fff?><?print int(c.hlsa()[2])?>')
2828    assert '1' == r('<?code c = #fff?><?print int(c.hlsa()[3])?>')
2829
2830
2831@pytest.mark.ul4
2832def test_method_hsv(r):
2833    assert '0' == r('<?code c = #fff?><?print int(c.hsv()[0])?>')
2834    assert '0' == r('<?code c = #fff?><?print int(c.hsv()[1])?>')
2835    assert '1' == r('<?code c = #fff?><?print int(c.hsv()[2])?>')
2836
2837
2838@pytest.mark.ul4
2839def test_method_hsva(r):
2840    assert '0' == r('<?code c = #fff?><?print int(c.hsva()[0])?>')
2841    assert '0' == r('<?code c = #fff?><?print int(c.hsva()[1])?>')
2842    assert '1' == r('<?code c = #fff?><?print int(c.hsva()[2])?>')
2843    assert '1' == r('<?code c = #fff?><?print int(c.hsva()[3])?>')
2844
2845
2846@pytest.mark.ul4
2847def test_method_lum(r):
2848    assert 'True' == r('<?print #fff.lum() == 1?>')
2849
2850
2851@pytest.mark.ul4
2852def test_method_withlum(r):
2853    assert '#fff' == r('<?print #000.withlum(1)?>')
2854
2855    # Make sure that the parameters have the same name in all implementations
2856    assert '#fff' == r('<?print #000.withlum(lum=1)?>')
2857
2858
2859@pytest.mark.ul4
2860def test_method_witha(r):
2861    assert '#0063a82a' == r('<?print repr(#0063a8.witha(42))?>')
2862
2863    # Make sure that the parameters have the same name in all implementations
2864    assert '#0063a82a' == r('<?print repr(#0063a8.witha(a=42))?>')
2865
2866
2867@pytest.mark.ul4
2868def test_method_join(r):
2869    assert '1,2,3,4' == r('<?print ",".join("1234")?>')
2870    assert '1,2,3,4' == r('<?print ",".join(["1", "2", "3", "4"])?>')
2871
2872    # Make sure that the parameters have the same name in all implementations
2873    assert '1,2,3,4' == r('<?print ",".join(iterable="1234")?>')
2874
2875
2876@pytest.mark.ul4
2877def test_method_find(r):
2878    s = "gurkgurk"
2879    assert '-1' == r('<?print s.find("ks")?>', s=s)
2880    assert '2' == r('<?print s.find("rk")?>', s=s)
2881    assert '2' == r('<?print s.find("rk", 2)?>', s=s)
2882    assert '6' == r('<?print s.find("rk", -3)?>', s=s)
2883    assert '2' == r('<?print s.find("rk", 2, 4)?>', s=s)
2884    assert '6' == r('<?print s.find("rk", 4, 8)?>', s=s)
2885    assert '5' == r('<?print s.find("ur", -4, -1)?>', s=s)
2886    assert '-1' == r('<?print s.find("rk", 2, 3)?>', s=s)
2887    assert '-1' == r('<?print s.find("rk", 7)?>', s=s)
2888    l = list("gurkgurk")
2889    assert '-1' == r('<?print l.find("x")?>', l=l)
2890    assert '2' == r('<?print l.find("r")?>', l=l)
2891    assert '2' == r('<?print l.find("r", 2)?>', l=l)
2892    assert '6' == r('<?print l.find("r", -3)?>', l=l)
2893    assert '2' == r('<?print l.find("r", 2, 4)?>', l=l)
2894    assert '6' == r('<?print l.find("r", 4, 8)?>', l=l)
2895    assert '6' == r('<?print l.find("r", -3, -1)?>', l=l)
2896    assert '-1' == r('<?print l.find("r", 2, 2)?>', l=l)
2897    assert '-1' == r('<?print l.find("r", 7)?>', l=l)
2898    assert '1' == r('<?print l.find(None)?>', l=[0, None, 1, None, 2, None, 3, None])
2899
2900    # Make sure that the parameters have the same name in all implementations
2901    assert '2' == r('<?print s.find(sub="rk", start=2, end=4)?>', s=s)
2902
2903
2904@pytest.mark.ul4
2905def test_method_rfind(r):
2906    s = "gurkgurk"
2907    assert '-1' == r('<?print s.rfind("ks")?>', s=s)
2908    assert '6' == r('<?print s.rfind("rk")?>', s=s)
2909    assert '6' == r('<?print s.rfind("rk", 2)?>', s=s)
2910    assert '6' == r('<?print s.rfind("rk", -3)?>', s=s)
2911    assert '2' == r('<?print s.rfind("rk", 2, 4)?>', s=s)
2912    assert '6' == r('<?print s.rfind("rk", 4, 8)?>', s=s)
2913    assert '5' == r('<?print s.rfind("ur", -4, -1)?>', s=s)
2914    assert '-1' == r('<?print s.rfind("rk", 2, 3)?>', s=s)
2915    assert '-1' == r('<?print s.rfind("rk", 7)?>', s=s)
2916    l = list("gurkgurk")
2917    assert '-1' == r('<?print l.rfind("x")?>', l=l)
2918    assert '6' == r('<?print l.rfind("r")?>', l=l)
2919    assert '6' == r('<?print l.rfind("r", 2)?>', l=l)
2920    assert '2' == r('<?print l.rfind("r", 2, 4)?>', l=l)
2921    assert '6' == r('<?print l.rfind("r", 4, 8)?>', l=l)
2922    assert '6' == r('<?print l.rfind("r", -3, -1)?>', l=l)
2923    assert '-1' == r('<?print l.rfind("r", 2, 2)?>', l=l)
2924    assert '-1' == r('<?print l.rfind("r", 7)?>', l=l)
2925    assert '7' == r('<?print l.rfind(None)?>', l=[0, None, 1, None, 2, None, 3, None])
2926
2927    # Make sure that the parameters have the same name in all implementations
2928    assert '2' == r('<?print s.rfind(sub="rk", start=2, end=4)?>', s=s)
2929
2930
2931@pytest.mark.ul4
2932def test_method_day(r):
2933    assert '12' == r('<?print @(2010-05-12).day()?>')
2934    assert '12' == r('<?print d.day()?>', d=datetime.date(2010, 5, 12))
2935
2936
2937@pytest.mark.ul4
2938def test_method_month(r):
2939    assert '5' == r('<?print @(2010-05-12).month()?>')
2940    assert '5' == r('<?print d.month()?>', d=datetime.date(2010, 5, 12))
2941
2942
2943@pytest.mark.ul4
2944def test_method_year(r):
2945    assert '5' == r('<?print @(2010-05-12).month()?>')
2946    assert '5' == r('<?print d.month()?>', d=datetime.date(2010, 5, 12))
2947
2948
2949@pytest.mark.ul4
2950def test_method_hour(r):
2951    assert '16' == r('<?print @(2010-05-12T16:47:56).hour()?>')
2952    assert '16' == r('<?print d.hour()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
2953
2954
2955@pytest.mark.ul4
2956def test_method_minute(r):
2957    assert '47' == r('<?print @(2010-05-12T16:47:56).minute()?>')
2958    assert '47' == r('<?print d.minute()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
2959
2960
2961@pytest.mark.ul4
2962def test_method_second(r):
2963    assert '56' == r('<?print @(2010-05-12T16:47:56).second()?>')
2964    assert '56' == r('<?print d.second()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
2965
2966
2967@pytest.mark.ul4
2968def test_method_microsecond(r):
2969    if r is not render_php:
2970        assert '123000' == r('<?print @(2010-05-12T16:47:56.123000).microsecond()?>')
2971        assert '123000' == r('<?print d.microsecond()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56, 123000))
2972
2973
2974@pytest.mark.ul4
2975def test_method_weekday(r):
2976    assert '2' == r('<?print @(2010-05-12).weekday()?>')
2977    assert '2' == r('<?print d.weekday()?>', d=datetime.date(2010, 5, 12))
2978
2979
2980@pytest.mark.ul4
2981def test_method_week(r):
2982    assert '0' == r('<?print @(2012-01-01).week()?>')
2983    assert '0' == r('<?print @(2012-01-01).week(0)?>')
2984    assert '1' == r('<?print @(2012-01-01).week(6)?>')
2985    assert '1' == r('<?print @(2012-01-02).week()?>')
2986    assert '1' == r('<?print @(2012-01-02).week(0)?>')
2987    assert '1' == r('<?print @(2012-01-02).week(6)?>')
2988
2989    # Make sure that the parameters have the same name in all implementations
2990    assert '1' == r('<?print @(2012-01-02).week(firstweekday=0)?>')
2991
2992
2993@pytest.mark.ul4
2994def test_method_yearday(r):
2995    assert '1' == r('<?print @(2010-01-01).yearday()?>')
2996    assert '366' == r('<?print @(2008-12-31).yearday()?>')
2997    assert '365' == r('<?print @(2010-12-31).yearday()?>')
2998    assert '132' == r('<?print @(2010-05-12).yearday()?>')
2999    assert '132' == r('<?print @(2010-05-12T16:47:56).yearday()?>')
3000    assert '132' == r('<?print d.yearday()?>', d=datetime.date(2010, 5, 12))
3001    assert '132' == r('<?print d.yearday()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
3002
3003
3004@pytest.mark.ul4
3005def test_method_days(r):
3006    assert '1' == r('<?print timedelta(1).days()?>')
3007
3008
3009@pytest.mark.ul4
3010def test_method_seconds(r):
3011    assert '42' == r('<?print timedelta(0, 42).seconds()?>')
3012
3013
3014@pytest.mark.ul4
3015def test_method_microseconds(r):
3016    assert '123000' == r('<?print timedelta(0, 0, 123000).microseconds()?>')
3017
3018
3019@pytest.mark.ul4
3020def test_method_months(r):
3021    assert '17' == r('<?print monthdelta(17).months()?>')
3022
3023
3024@pytest.mark.ul4
3025def test_method_append(r):
3026    assert '[17, 23, 42]' == r('<?code l = [17]?><?code l.append(23, 42)?><?print l?>')
3027
3028
3029@pytest.mark.ul4
3030def test_method_insert(r):
3031    assert '[1, 2, 3, 4]' == r('<?code l = [1,4]?><?code l.insert(1, 2, 3)?><?print l?>')
3032
3033
3034@pytest.mark.ul4
3035def test_method_pop(r):
3036    assert '42;17;23;' == r('<?code l = [17, 23, 42]?><?print l.pop()?>;<?print l.pop(-2)?>;<?print l.pop(0)?>;')
3037
3038
3039@pytest.mark.ul4
3040def test_method_update(r):
3041    assert '0' == r('<?code d = {}?><?code d.update()?><?print len(d)?>')
3042    assert '1' == r('<?code d = {}?><?code d.update([["one", 1]])?><?print d.one?>')
3043    assert '1' == r('<?code d = {}?><?code d.update({"one": 1})?><?print d.one?>')
3044    assert '1' == r('<?code d = {}?><?code d.update(one=1)?><?print d.one?>')
3045    assert '1' == r('<?code d = {}?><?code d.update([["one", 0]], {"one": 0}, one=1)?><?print d.one?>')
3046
3047
3048@pytest.mark.ul4
3049def test_render(r):
3050    t = ul4c.Template('<?print prefix?><?print data?><?print suffix?>')
3051
3052    assert '(f)(o)(o)' == r('<?for c in data?><?code t.render(data=c, prefix="(", suffix=")")?><?end for?>', t=t, data='foo')
3053    assert '(f)(o)(o)' == r('<?for c in data?><?code t.render(data=c, **{"prefix": "(", "suffix": ")"})?><?end for?>', t=t, data='foo')
3054
3055
3056@pytest.mark.ul4
3057def test_def(r):
3058    assert 'foo' == r('<?def lower?><?print x.lower()?><?end def?><?print lower.renders(x="FOO")?>')
3059
3060
3061@pytest.mark.ul4
3062def test_pass_function(r):
3063    assert "&lt;" == r("<?def x?><?print xe('<')?><?end def?><?code x.render(xe=xmlescape)?>")
3064    assert "&lt;" == r("<?def xe?><?return xmlescape(s)?><?end def?><?def x?><?print xe(s='<')?><?end def?><?code x.render(xe=xe)?>")
3065    assert "&lt;" == r("<?def xe?><?return xmlescape(s)?><?end def?><?def x?><?print xe(s='<')?><?end def?><?code x.render()?>")
3066
3067
3068@pytest.mark.ul4
3069def test_parse(r):
3070    assert '42' == r('<?print data.Noner?>', data=dict(Noner=42))
3071
3072
3073@pytest.mark.ul4
3074def test_nested_exceptions(r):
3075    tmpl1 = ul4c.Template("<?print 2*x?>", "tmpl1")
3076    tmpl2 = ul4c.Template("<?code tmpl1.render(x=x)?>", "tmpl2")
3077    tmpl3 = ul4c.Template("<?code tmpl2.render(tmpl1=tmpl1, x=x)?>", "tmpl3")
3078
3079    with raises("unsupported operand type|not supported"):
3080        r("<?code tmpl3.render(tmpl1=tmpl1, tmpl2=tmpl2, x=x)?>", tmpl1=tmpl1, tmpl2=tmpl2, tmpl3=tmpl3, x=None)
3081
3082
3083@pytest.mark.ul4
3084def test_note(r):
3085    assert "foo" == r("f<?note This is?>o<?note a comment?>o")
3086
3087
3088@pytest.mark.ul4
3089def test_templateattributes(r):
3090    s1 = "<?print x?>"
3091    t1 = ul4c.Template(s1)
3092
3093    s2 = "<?printx 42?>"
3094    t2 = ul4c.Template(s2)
3095
3096    assert "<?" == r("<?print template.startdelim?>", template=t1)
3097    assert "?>" == r("<?print template.enddelim?>", template=t1)
3098    assert s1 == r("<?print template.source?>", template=t1)
3099    assert "1" == r("<?print len(template.content)?>", template=t1)
3100    assert "print" == r("<?print template.content[0].type?>", template=t1)
3101    assert s1 == r("<?print template.content[0].location.tag?>", template=t1)
3102    assert "x" == r("<?print template.content[0].location.code?>", template=t1)
3103    assert "var" == r("<?print template.content[0].obj.type?>", template=t1)
3104    assert "x" == r("<?print template.content[0].obj.name?>", template=t1)
3105    assert "printx" == r("<?print template.content[0].type?>", template=t2)
3106    assert "const" == r("<?print template.content[0].obj.type?>", template=t2)
3107    assert "42" == r("<?print template.content[0].obj.value?>", template=t2)
3108
3109
3110@pytest.mark.ul4
3111def test_templateattributes_localtemplate(r):
3112    # This checks that template attributes work on a closure
3113    source = "<?def lower?><?print t.lower()?><?end def?>"
3114
3115    assert source + "<?print lower.source?>" == r(source + "<?print lower.source?>")
3116    assert source == r(source + "<?print lower.source[lower.location.starttag:lower.endlocation.endtag]?>")
3117    assert "<?print t.lower()?>" == r(source + "<?print lower.source[lower.location.endtag:lower.endlocation.starttag]?>")
3118    assert "lower" == r(source + "<?print lower.name?>")
3119
3120
3121@pytest.mark.ul4
3122def test_nestedscopes(r):
3123    # Subtemplates can see the local variables from their parents
3124    source = """
3125    <?for i in range(3)?>
3126        <?def x?>
3127            <?print i?>!
3128        <?end def?>
3129        <?code x.render()?>
3130    <?end for?>
3131    """
3132    assert "0!1!2!" == r(source, keepws=False)
3133
3134    # Subtemplates see the state of the variable at the point of the ``<?def?>`` tag,
3135    # so the following code will use ``i = 1`` instead of ``i = 2`` even if the subtemplate is called after the variable has been changed.
3136    source = """
3137    <?code i = 1?>
3138    <?def x?>
3139        <?print i?>
3140    <?end def?>
3141    <?code i = 2?>
3142    <?code x.render()?>
3143    """
3144    assert "1" == r(source, keepws=False)
3145
3146
3147    # This shows the difference between local variables and variables from the parent.
3148    # ``x`` is passed to the subtemplate, so it will always the the current value instead of the one when it is defined
3149    # (Furthermore ``y += 1`` will load the variable from the parent but store it as a local variable)
3150    source = """
3151    <?def outer?>
3152        <?def inner?>
3153            <?code x += 1?>
3154            <?code y += 1?>
3155            <?print x?>!
3156            <?print y?>!
3157        <?end def?>
3158        <?code x += 1?>
3159        <?code y += 1?>
3160        <?code inner.render(x=x)?>
3161        <?print x?>!
3162        <?print y?>!
3163    <?end def?>
3164    <?code x += 1?>
3165    <?code y += 1?>
3166    <?code outer.render(x=x)?>
3167    <?print x?>!
3168    <?print y?>!
3169    """
3170
3171    assert "45!43!44!43!43!43!" == r(source, keepws=False, x=42, y=42)
3172
3173
3174def universaltemplate(keepws=True):
3175    return ul4c.Template("""
3176        text
3177        <?code x = 'gurk'?>
3178        <?code x = 42?>
3179        <?code x = 4.2?>
3180        <?code x = Undefined?>
3181        <?code x = ReallyUndefined?>
3182        <?code x = None?>
3183        <?code x = False?>
3184        <?code x = True?>
3185        <?code x = @(2009-01-04)?>
3186        <?code x = #0063a8?>
3187        <?code x = [42]?>
3188        <?code x = {"fortytwo": 42}?>
3189        <?code x = [x for x in range(10) if i % 2]?>
3190        <?code x = {x : x*x for x in range(10) if i % 2}?>
3191        <?code x = (x for x in range(10) if i % 2)?>
3192        <?code x = y?>
3193        <?code x += 42?>
3194        <?code x -= 42?>
3195        <?code x *= 42?>
3196        <?code x /= 42?>
3197        <?code x //= 42?>
3198        <?code x %= 42?>
3199        <?print x.gurk?>
3200        <?print x["gurk"]?>
3201        <?print x[1:2]?>
3202        <?print x[1:]?>
3203        <?print x[:2]?>
3204        <?print x[:]?>
3205        <?printx x?>
3206        <?for x in "12"?><?print x?><?break?><?continue?><?end for?>
3207        <?print not x?>
3208        <?print -x?>
3209        <?print x in y?>
3210        <?print x not in y?>
3211        <?print x==y?>
3212        <?print x!=y?>
3213        <?print x<y?>
3214        <?print x<=y?>
3215        <?print x>y?>
3216        <?print x>=y?>
3217        <?print x+y?>
3218        <?print x*y?>
3219        <?print x/y?>
3220        <?print x//y?>
3221        <?print x and y?>
3222        <?print x or y?>
3223        <?print x % y?>
3224        <?print now()?>
3225        <?print repr(1)?>
3226        <?print range(1, 2)?>
3227        <?print range(1, 2, 3)?>
3228        <?print rgb(1, 2, 3, 4)?>
3229        <?print repr(1, 2, x=17, y=23, *args, **kwargs)?>
3230        <?print x.r()?>
3231        <?print x.find(1)?>
3232        <?print x.find(1, 2)?>
3233        <?print x.find(1, 2, 3)?>
3234        <?print x.find(1, 2, x=17, y=23, *args, **kwargs)?>
3235        <?if x?>gurk<?elif y?>hurz<?else?>hinz<?end if?>
3236        <?code x.render(a=1, b=2)?>
3237        <?def x?>foo<?end def?>
3238        <?def x?><?return x?><?end def?>
3239        <?code x.render()?>
3240    """)
3241
3242
3243@pytest.mark.ul4
3244def test_strtemplate():
3245    t1 = universaltemplate(True)
3246    str(t1)
3247
3248    t2 = universaltemplate(False)
3249    str(t2)
3250
3251
3252@pytest.mark.ul4
3253def test_keepws():
3254    s = """
3255        <?for i in range(10)?>
3256            <?print i?>
3257            ;
3258        <?end for?>
3259    """
3260    t = ul4c.Template(s, keepws=True)
3261    output1 = t.renders()
3262    t.keepws = False
3263    output2 = t.renders()
3264    assert output1 != output2
3265    assert "".join(output1.split()) == output2
3266
3267
3268@pytest.mark.ul4
3269def test_keepws_nested(r):
3270    s1 = "<?def nested1?>1n\n<?code second.render()?><?end def?>1\n<?code nested1.render(second=second)?>"
3271    s2 = "<?def nested2?>2n\n<?end def?>2\n<?code nested2.render()?>"
3272
3273    assert "1\n1n\n22n" == r(s1, keepws=True, second=ul4c.Template(s2, keepws=False))
3274    assert "11n2\n2n\n" == r(s1, keepws=False, second=ul4c.Template(s2, keepws=True))
3275
3276
3277@pytest.mark.ul4
3278def test_function(c):
3279    assert 42 == c("<?return 42?>")
3280
3281
3282@pytest.mark.ul4
3283def test_function_value(c):
3284    assert 84 == c("<?return 2*x?>", x=42)
3285
3286
3287@pytest.mark.ul4
3288def test_function_multiple_returnvalues(c):
3289    assert 84 == c("<?return 2*x?><?return 3*x?>", x=42)
3290
3291
3292@pytest.mark.ul4
3293def test_function_name(c):
3294    assert "f" == c("<?def f?><?return f.name?><?end def?><?return f(f=f)?>")
3295
3296
3297@pytest.mark.ul4
3298def test_function_closure(c):
3299    assert 24 == c("<?code y=3?><?def inner?><?return 2*x*y?><?end def?><?return inner(x=4)?>")
3300    assert 24 == c("<?def outer?><?code y=3?><?def inner?><?return 2*x*y?><?end def?><?return inner?><?end def?><?return outer()(x=4)?>")
3301
3302
3303@pytest.mark.ul4
3304def test_jssource():
3305    t = universaltemplate()
3306    t.jssource()
3307
3308
3309@pytest.mark.ul4
3310def test_javasource():
3311    t = universaltemplate()
3312    t.javasource()
3313
3314
3315@pytest.mark.ul4
3316def test_attr_if(r):
3317    cond = ul4.attr_if(html.a("gu'\"rk"), cond="cond")
3318
3319    s = html.div(class_=cond).conv().string()
3320    assert '<div></div>' == r(s, cond=False)
3321    assert '''<div class="gu'&quot;rk"></div>''' == r(s, cond=True)
3322
3323    s = html.div(class_=(cond, "hurz")).conv().string()
3324    assert '<div class="hurz"></div>' == r(s, cond=False)
3325    assert '''<div class="gu'&quot;rkhurz"></div>''' == r(s, cond=True)
3326
3327    s = cond.conv().string()
3328    assert '' == r(s, cond=False)
3329    assert '''<a>gu'"rk</a>''' == r(s, cond=True)
3330
3331    s = html.ul(compact=ul4.attr_if(True, cond="cond")).conv().string()
3332    assert '<ul></ul>' == r(s, cond=False)
3333    assert '''<ul compact="compact"></ul>''' == r(s, cond=True)
Note: See TracBrowser for help on using the browser.