root/livinglogic.python.xist/test/test_ul4.py @ 5312:9a98178e4483

Revision 5312:9a98178e4483, 119.6 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Merge UL4 templates and functions again.

Templates call be called as functions. All ouput will be ignored in this case.

Executing templates is now done by interpreting the AST directly (via the eval()
method), instead of generating Python source code from it first.

AST nodes can both produce output and return results via enhanced generators.

Constant folding has been removed.

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 function from the source ``__``, call it with the variables ``variables`` and return the result.
317    """
318    function = ul4c.Function(__, keepws=keepws)
319    f = sys._getframe(1)
320    print("Testing Python function ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
321    print(function)
322    print("with variables:")
323    print(repr(variables))
324    return function(**variables)
325
326
327def call_python_dumps(__, *, keepws=True, **variables):
328    """
329    Compile the function from the source ``__``, create a string dump from it,
330    recreate the function from the dump string, call it with the variables
331    ``variables`` and return the result.
332    """
333    function = ul4c.Function(__, keepws=keepws)
334    function = ul4c.Function.loads(function.dumps()) # Recreate the function from the binary dump
335    f = sys._getframe(1)
336    print("Testing Python function loaded from string ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
337    print(function)
338    print("with variables:")
339    print(repr(variables))
340    return function(**variables)
341
342
343def call_python_dump(__, *, keepws=True, **variables):
344    """
345    Compile the function from the source ``__``, dump it to a stream, recreate
346    the function from the dump, call it with the variables ``variables`` and
347    return the result.
348    """
349    function = ul4c.Function(__, keepws=keepws)
350    stream = io.StringIO()
351    function.dump(stream)
352    stream.seek(0)
353    f = sys._getframe(1)
354    function = ul4c.Function.load(stream) # Recreate the function from the stream
355    print("Testing Python function loaded from stream ({}, line {}):".format(f.f_code.co_filename, f.f_lineno))
356    print(function)
357    print("with variables:")
358    print(repr(variables))
359    return function(**variables)
360
361
362def call_js(__, *, keepws=True, **variables):
363    """
364    Compile the function from the source ``__``, and generate Javascript source
365    from it and call it with the variables ``variables``.
366
367    (this requires an installed ``d8`` shell from V8 (http://code.google.com/p/v8/))
368    """
369    function = ul4c.Function(__, keepws=keepws)
370    js = function.jssource()
371    js = "func = {};\ndata = {};\nprint(ul4on.dumps(func.call(data)));\n".format(js, ul4c._asjson(variables))
372    f = sys._getframe(1)
373    print("Testing Javascript function 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    # Test **
685    assert '1:2\n' == r('<?for (key, value) in {**{1:2}}.items()?><?print key?>:<?print value?>\n<?end for?>')
686    assert '1:4\n' == r('<?for (key, value) in {1:1, **{1:2}, 1:3, **{1:4}}.items()?><?print key?>:<?print value?>\n<?end for?>')
687    assert 'no' == r('<?if {}?>yes<?else?>no<?end if?>')
688    assert 'yes' == r('<?if {1:2}?>yes<?else?>no<?end if?>')
689
690    # Make sure that the loop variables doesn't leak into the surrounding scope
691    assert "undefined" == r("<?code d = {i: 2*i for i in range(4)}?><?print type(i)?>")
692
693
694@pytest.mark.ul4
695def test_dictcomp(r):
696    # JS only supports string keys
697    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?>")
698    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?>")
699    assert "6" == r("<?code d = {str(i):2*i for i in range(10)}?><?print d['3']?>")
700
701
702@pytest.mark.ul4
703def test_print(r):
704    assert "" == r("<?print None?>")
705    assert "<foo>" == r("<?print '<foo>'?>")
706
707
708@pytest.mark.ul4
709def test_printx(r):
710    assert "" == r("<?printx None?>")
711    assert "&lt;foo&gt;" == r("<?printx '<foo>'?>")
712
713
714@pytest.mark.ul4
715def test_code_storevar(r):
716    assert '42' == r('<?code x = 42?><?print x?>')
717    assert 'xyzzy' == r('<?code x = "xyzzy"?><?print x?>')
718    assert 'x,y' == r('<?code (x, y) = "xy"?><?print x?>,<?print y?>')
719    assert '42' == r('<?code (x,) = [42]?><?print x?>')
720    assert '17,23' == r('<?code (x,y) = [17, 23]?><?print x?>,<?print y?>')
721    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?>')
722
723
724@pytest.mark.ul4
725def test_code_addvar(r):
726    for x in (17, 17., False, True):
727        for y in (23, 23., False, True):
728            assert x + y == eval(r('<?code x = {}?><?code x += {}?><?print x?>'.format(x, y)))
729    assert 'xyzzy' == r('<?code x = "xyz"?><?code x += "zy"?><?print x?>')
730
731
732@pytest.mark.ul4
733def test_code_subvar(r):
734    for x in (17, 17., False, True):
735        for y in (23, 23., False, True):
736            assert x - y == eval(r('<?code x = {}?><?code x -= {}?><?print x?>'.format(x, y)))
737
738
739@pytest.mark.ul4
740def test_code_mulvar(r):
741    for x in (17, 17., False, True):
742        for y in (23, 23., False, True):
743            assert x * y == eval(r('<?code x = {}?><?code x *= {}?><?print x?>'.format(x, y)))
744    for x in (17, False, True):
745        y = "xyzzy"
746        assert x * y == r('<?code x = {}?><?code x *= {!r}?><?print x?>'.format(x, y))
747    assert 17*"xyzzy" == r('<?code x = "xyzzy"?><?code x *= 17?><?print x?>')
748
749
750@pytest.mark.ul4
751def test_code_floordivvar(r):
752    for x in (5, -5, 5.0, -5.0, 4, -4, 4.0, -4.0, False, True):
753        for y in (2, -2, 2.0, -2.0, True):
754            assert x // y == eval(r('<?code x = {}?><?code x //= {}?><?print x?>'.format(x, y)))
755
756
757@pytest.mark.ul4
758def test_code_truedivvar(r):
759    for x in (5, -5, 5.0, -5.0, 4, -4, 4.0, -4.0, False, True):
760        for y in (2, -2, 2.0, -2.0, True):
761            assert x / y == eval(r('<?code x = {}?><?code x /= {}?><?print x?>'.format(x, y)))
762
763
764@pytest.mark.ul4
765def test_code_modvar(r):
766    for x in (1729, 1729.0, -1729, -1729.0, False, True):
767        for y in (23, 23., -23, -23.0, True):
768            assert x % y == eval(r('<?code x = {}?><?code x %= {}?><?print x?>'.format(x, y)))
769
770
771@pytest.mark.ul4
772def test_code_delvar(r):
773    if r is not render_js:
774        with raises("(x|not found)"):
775            r('<?code x = 1729?><?code del x?><?print x?>')
776
777
778@pytest.mark.ul4
779def test_for_string(r):
780    assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data="")
781    assert '(g)(u)(r)(k)' == r('<?for c in data?>(<?print c?>)<?end for?>', data="gurk")
782
783
784@pytest.mark.ul4
785def test_for_list(r):
786    assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data="")
787    assert '(g)(u)(r)(k)' == r('<?for c in data?>(<?print c?>)<?end for?>', data=["g", "u", "r", "k"])
788
789
790@pytest.mark.ul4
791def test_for_dict(r):
792    assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data={})
793    assert '(a)(b)(c)' == r('<?for c in sorted(data)?>(<?print c?>)<?end for?>', data=dict(a=1, b=2, c=3))
794
795
796@pytest.mark.ul4
797def test_for_nested_loop(r):
798    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]])
799
800
801@pytest.mark.ul4
802def test_for_unpacking(r):
803    data = [
804        ("spam", "eggs", 17),
805        ("gurk", "hurz", 23),
806        ("hinz", "kunz", 42),
807    ]
808
809    assert '(spam)(gurk)(hinz)' == r('<?for (a,) in data?>(<?print a?>)<?end for?>', data=[item[:1] for item in data])
810    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])
811    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)
812
813
814@pytest.mark.ul4
815def test_for_nested_unpacking(r):
816    data = [
817        (("spam", "eggs"), (17,), None),
818        (("gurk", "hurz"), (23,), False),
819        (("hinz", "kunz"), (42,), True),
820    ]
821
822    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)
823
824
825@pytest.mark.ul4
826def test_break(r):
827    assert '1, 2, ' == r('<?for i in [1,2,3]?><?print i?>, <?if i==2?><?break?><?end if?><?end for?>')
828
829
830@pytest.mark.ul4
831def test_break_nested(r):
832    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?>')
833
834
835@pytest.mark.ul4
836def test_continue(r):
837    assert '1, 3, ' == r('<?for i in [1,2,3]?><?if i==2?><?continue?><?end if?><?print i?>, <?end for?>')
838
839
840@pytest.mark.ul4
841def test_continue_nested(r):
842    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?>')
843
844
845@pytest.mark.ul4
846def test_if(r):
847    assert '42' == r('<?if data?><?print data?><?end if?>', data=42)
848
849
850@pytest.mark.ul4
851def test_else(r):
852    assert '42' == r('<?if data?><?print data?><?else?>no<?end if?>', data=42)
853    assert 'no' == r('<?if data?><?print data?><?else?>no<?end if?>', data=0)
854
855
856@pytest.mark.ul4
857def test_block_errors(r):
858    with raises("block unclosed"):
859        r('<?for x in data?>')
860    with raises("for ended by endif|endif doesn't match any if"):
861        r('<?for x in data?><?end if?>')
862    with raises("not in any block"):
863        r('<?end?>')
864    with raises("not in any block"):
865        r('<?end for?>')
866    with raises("not in any block"):
867        r('<?end if?>')
868    with raises("else doesn't match any if"):
869        r('<?else?>')
870    with raises("block unclosed"):
871        r('<?if data?>')
872    with raises("block unclosed"):
873        r('<?if data?><?else?>')
874    with raises("duplicate else in if/elif/else chain|else already seen in if"):
875        r('<?if data?><?else?><?else?>')
876    with raises("elif can't follow else in if/elif/else chain|else already seen in if"):
877        r('<?if data?><?else?><?elif data?>')
878    with raises("elif can't follow else in if/elif/else chain|else already seen in if"):
879        r('<?if data?><?elif data?><?elif data?><?else?><?elif data?>')
880
881
882@pytest.mark.ul4
883def test_empty():
884    with raises("expression required"):
885        render_python('<?print?>')
886    with raises("expression required"):
887        render_python('<?if?>')
888    with raises("expression required"):
889        render_python('<<?if x?><?elif?><?end if?>')
890    with raises("loop expression required"):
891        render_python('<?for?>')
892    with raises("statement required"):
893        render_python('<?code?>')
894    with raises("expression required"):
895        render_python('<?render?>')
896
897
898@pytest.mark.ul4
899def test_add(r):
900    code = '<?print x + y?>'
901    values = (17, 23, 1., -1.)
902
903    for x in values:
904        for y in values:
905            assert x + y == eval(r(code, x=x, y=y)) # Using ``evaleq`` avoids problem with the nonexistant int/float distinction in JS
906    assert 'foobar' == r('<?code x="foo"?><?code y="bar"?><?print x+y?>')
907    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"))
908    assert "2012-10-18 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(1))
909    assert "2013-10-17 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(365))
910    assert "2012-10-17 12:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 12*60*60))
911    assert "2012-10-17 00:00:01" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 1))
912    if r is not render_php:
913        assert "2012-10-17 00:00:00.500000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 500000))
914        assert "2012-10-17 00:00:00.001000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 1000))
915    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
916    assert "1 day, 0:00:01" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 1))
917    assert "1 day, 0:00:00.000001" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 0, 1))
918    assert "2 months" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
919    assert "2000-02-01 00:00:00" == r(code, x=datetime.datetime(2000, 1, 1), y=misc.monthdelta(1))
920    assert "1999-11-30 00:00:00" == r(code, x=datetime.datetime(2000, 1, 31), y=misc.monthdelta(-2))
921    assert "2000-03-29 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(1))
922    assert "2001-02-28 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(12))
923    assert "2001-02-28 00:00:00" == r(code, x=misc.monthdelta(12), y=datetime.datetime(2000, 2, 29))
924
925
926@pytest.mark.ul4
927def test_sub(r):
928    code = '<?print x - y?>'
929    values = (17, 23, 1., -1.)
930
931    for x in values:
932        for y in values:
933            assert x - y == eval(r(code, x=x, y=y))
934
935    assert "2012-10-16 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(1))
936    assert "2011-10-17 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(366))
937    assert "2012-10-16 12:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 12*60*60))
938    assert "2012-10-16 23:59:59" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 1))
939    if r is not render_php:
940        assert "2012-10-16 23:59:59.500000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 500000))
941        assert "2012-10-16 23:59:59.999000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 1000))
942    assert "0:00:00" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
943    assert "1 day, 0:00:00" == r(code, x=datetime.timedelta(2), y=datetime.timedelta(1))
944    assert "23:59:59" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 1))
945    assert "23:59:59.999999" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 0, 1))
946    assert "-1 day, 23:59:59" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
947    assert "-1 day, 23:59:59.999999" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
948    assert "2000-01-01 00:00:00" == r(code, x=datetime.datetime(2000, 2, 1), y=misc.monthdelta(1))
949    assert "2000-02-29 00:00:00" == r(code, x=datetime.datetime(1999, 12, 31), y=misc.monthdelta(-2))
950    assert "2000-02-29 00:00:00" == r(code, x=datetime.datetime(2000, 3, 29), y=misc.monthdelta(1))
951    assert "1999-02-28 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(12))
952    assert "-1 month" == r(code, x=misc.monthdelta(2), y=misc.monthdelta(3))
953
954
955@pytest.mark.ul4
956def test_neg(r):
957    code = "<?print -x?>"
958
959    assert "0" == r(code, x=False)
960    assert "-1" == r(code, x=True)
961    assert "-17" == r(code, x=17)
962    assert "-42.5" == r(code, x=42.5)
963    assert "0:00:00" == r(code, x=datetime.timedelta())
964    assert "-1 day, 0:00:00" == r(code, x=datetime.timedelta(1))
965    assert "-1 day, 23:59:59" == r(code, x=datetime.timedelta(0, 1))
966    assert "-1 day, 23:59:59.999999" == r(code, x=datetime.timedelta(0, 0, 1))
967    assert "0 months" == r(code, x=misc.monthdelta())
968    assert "-1 month" == r(code, x=misc.monthdelta(1))
969    # This checks constant folding
970    assert "0" == r("<?print -False?>")
971    assert "-1" == r("<?print -True?>")
972    assert "-2" == r("<?print -2?>")
973    assert "-2.5" == r("<?print -2.5?>")
974
975@pytest.mark.ul4
976def test_mul(r):
977    code = '<?print x * y?>'
978    values = (17, 23, 1., -1.)
979
980    for x in values:
981        for y in values:
982            assert x * y == eval(r(code, x=x, y=y))
983    assert 17*"foo" == r('<?print 17*"foo"?>')
984    assert 17*"foo" == r('<?code x=17?><?code y="foo"?><?print x*y?>')
985    assert "foo"*17 == r('<?code x="foo"?><?code y=17?><?print x*y?>')
986    assert "foo"*17 == r('<?print "foo"*17?>')
987    assert "(foo)(bar)(foo)(bar)(foo)(bar)" == r('<?for i in 3*data?>(<?print i?>)<?end for?>', data=["foo", "bar"])
988    assert "0:00:00" == r(code, x=4, y=datetime.timedelta())
989    assert "4 days, 0:00:00" == r(code, x=4, y=datetime.timedelta(1))
990    assert "2 days, 0:00:00" == r(code, x=4, y=datetime.timedelta(0, 12*60*60))
991    assert "0:00:02" == r(code, x=4, y=datetime.timedelta(0, 0, 500000))
992    assert "12:00:00" == r(code, x=0.5, y=datetime.timedelta(1))
993    assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
994    assert "4 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=4)
995    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(0, 12*60*60), y=4)
996    assert "0:00:02" == r(code, x=datetime.timedelta(0, 0, 500000), y=4)
997    assert "12:00:00" == r(code, x=datetime.timedelta(1), y=0.5)
998    assert "4 months" == r(code, x=4, y=misc.monthdelta(1))
999    assert "4 months" == r(code, x=misc.monthdelta(1), y=4)
1000
1001
1002@pytest.mark.ul4
1003def test_truediv(r):
1004    code = "<?print x / y?>"
1005
1006    assert "0.5" == r('<?print 1/2?>')
1007    assert "0.5" == r('<?code x=1?><?code y=2?><?print x/y?>')
1008    assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
1009    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(8), y=4)
1010    assert "12:00:00" == r(code, x=datetime.timedelta(4), y=8)
1011    assert "0:00:00.500000" == r(code, x=datetime.timedelta(0, 4), y=8)
1012    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=0.5)
1013    assert "9:36:00" == r(code, x=datetime.timedelta(1), y=2.5)
1014    assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
1015    assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(8), y=4)
1016    assert "12:00:00" == r(code, x=datetime.timedelta(4), y=8)
1017    assert "0:00:00.500000" == r(code, x=datetime.timedelta(0, 4), y=8)
1018
1019
1020@pytest.mark.ul4
1021def test_floordiv(r):
1022    assert "0" == r('<?print 1//2?>')
1023    assert "0" == r('<?code x=1?><?code y=2?><?print x//y?>')
1024    assert "1 month" == r('<?print x//y?>', x=misc.monthdelta(3), y=2)
1025
1026
1027@pytest.mark.ul4
1028def test_mod(r):
1029    values = (17, 23, 17., 23.)
1030
1031    for x in values:
1032        for y in values:
1033            assert x % y == eval(r('<?print {} % {}?>'.format(x, y)))
1034            assert x % y == eval(r('<?print x % y?>', x=x, y=y))
1035
1036
1037@pytest.mark.ul4
1038def test_eq(r):
1039    code = '<?print x == y?>'
1040    numbervalues = (17, 23, 17., 23.)
1041
1042    for x in numbervalues:
1043        for y in numbervalues:
1044            assert str(x == y) == r('<?print {} == {}?>'.format(x, y))
1045            assert str(x == y) == r(code, x=x, y=y)
1046
1047    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
1048    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
1049    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
1050    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
1051    assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
1052    assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))
1053
1054
1055@pytest.mark.ul4
1056def test_ne(r):
1057    code = '<?print x != y?>'
1058    values = (17, 23, 17., 23.)
1059
1060    for x in values:
1061        for y in values:
1062            assert str(x != y) == r('<?print {} != {}?>'.format(x, y))
1063            assert str(x != y) == r(code, x=x, y=y)
1064
1065    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
1066    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
1067    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
1068    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
1069    assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
1070    assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))
1071
1072
1073@pytest.mark.ul4
1074def test_lt(r):
1075    code = '<?print x < y?>'
1076    values = (17, 23, 17., 23.)
1077
1078    for x in values:
1079        for y in values:
1080            assert str(x < y) == r('<?print {} < {}?>'.format(x, y))
1081            assert str(x < y) == r(code, x=x, y=y)
1082
1083    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
1084    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
1085    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
1086    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
1087    assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
1088    assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))
1089
1090
1091@pytest.mark.ul4
1092def test_le(r):
1093    code = '<?print x <= y?>'
1094    values = (17, 23, 17., 23.)
1095
1096    for x in values:
1097        for y in values:
1098            assert str(x <= y) == r('<?print {} <= {}?>'.format(x, y))
1099            assert str(x <= y) == r(code, x=x, y=y)
1100
1101    assert "True" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
1102    assert "False" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0))
1103    assert "False" == r(code, x=datetime.timedelta(0, 1), y=datetime.timedelta(0))
1104    assert "False" == r(code, x=datetime.timedelta(0, 0, 1), y=datetime.timedelta(0))
1105    assert "True" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
1106    assert "False" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(0))
1107
1108
1109@pytest.mark.ul4
1110def test_gt(r):
1111    code = '<?print x > y?>'
1112    values = (17, 23, 17., 23.)
1113
1114    for x in values:
1115        for y in values:
1116            assert str(x > y) == r('<?print {} > {}?>'.format(x, y))
1117            assert str(x > y) == r(code, x=x, y=y)
1118
1119    assert "False" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
1120    assert "True" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0))
1121    assert "True" == r(code, x=datetime.timedelta(0, 1), y=datetime.timedelta(0))
1122    assert "True" == r(code, x=datetime.timedelta(0, 0, 1), y=datetime.timedelta(0))
1123    assert "False" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
1124    assert "True" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(0))
1125
1126
1127@pytest.mark.ul4
1128def test_ge(r):
1129    code = '<?print x >= y?>'
1130    values = (17, 23, 17., 23.)
1131
1132    for x in values:
1133        for y in values:
1134            assert str(x >= y) == r('<?print {} >= {}?>'.format(x, y))
1135            assert str(x >= y) == r(code, x=x, y=y)
1136
1137    assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
1138    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
1139    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
1140    assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
1141    assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
1142    assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))
1143
1144
1145@pytest.mark.ul4
1146def test_contains(r):
1147    code = '<?print x in y?>'
1148
1149    assert "True" == r(code, x=2, y=[1, 2, 3])
1150    assert "False" == r(code, x=4, y=[1, 2, 3])
1151    assert "True" == r(code, x="ur", y="gurk")
1152    assert "False" == r(code, x="un", y="gurk")
1153    assert "True" == r(code, x="a", y={"a": 1, "b": 2})
1154    assert "False" == r(code, x="c", y={"a": 1, "b": 2})
1155    assert "True" == r(code, x=0xff, y=color.Color(0x00, 0x80, 0xff, 0x42))
1156    assert "False" == r(code, x=0x23, y=color.Color(0x00, 0x80, 0xff, 0x42))
1157
1158
1159@pytest.mark.ul4
1160def test_notcontains(r):
1161    code = '<?print x not in y?>'
1162
1163    assert "False" == r(code, x=2, y=[1, 2, 3])
1164    assert "True" == r(code, x=4, y=[1, 2, 3])
1165    assert "False" == r(code, x="ur", y="gurk")
1166    assert "True" == r(code, x="un", y="gurk")
1167    assert "False" == r(code, x="a", y={"a": 1, "b": 2})
1168    assert "True" == r(code, x="c", y={"a": 1, "b": 2})
1169    assert "False" == r(code, x=0xff, y=color.Color(0x00, 0x80, 0xff, 0x42))
1170    assert "True" == r(code, x=0x23, y=color.Color(0x00, 0x80, 0xff, 0x42))
1171
1172
1173@pytest.mark.ul4
1174def test_and(r):
1175    assert "False" == r('<?print x and y?>', x=False, y=False)
1176    assert "False" == r('<?print x and y?>', x=False, y=True)
1177    assert "0" == r('<?print x and y?>', x=0, y=True)
1178
1179
1180@pytest.mark.ul4
1181def test_or(r):
1182    assert "False" == r('<?print x or y?>', x=False, y=False)
1183    assert "True" == r('<?print x or y?>', x=False, y=True)
1184    assert "42" == r('<?print x or y?>', x=42, y=True)
1185
1186
1187@pytest.mark.ul4
1188def test_not(r):
1189    assert "True" == r('<?print not x?>', x=False)
1190    assert "False" == r('<?print not x?>', x=42)
1191
1192
1193@pytest.mark.ul4
1194def test_getitem(r):
1195    assert "u" == r("<?print 'gurk'[1]?>")
1196    assert "u" == r("<?print x[1]?>", x="gurk")
1197    assert "u" == r("<?print 'gurk'[-3]?>")
1198    assert "u" == r("<?print x[-3]?>", x="gurk")
1199    assert "" == r("<?print 'gurk'[4]?>")
1200    assert "" == r("<?print x[4]?>", x="gurk")
1201    assert "" == r("<?print 'gurk'[-5]?>")
1202    assert "" == r("<?print x[-5]?>", x="gurk")
1203
1204
1205@pytest.mark.ul4
1206def test_getslice12(r):
1207    assert "ur" == r("<?print 'gurk'[1:3]?>")
1208    assert "ur" == r("<?print x[1:3]?>", x="gurk")
1209    assert "ur" == r("<?print 'gurk'[-3:-1]?>")
1210    assert "ur" == r("<?print x[-3:-1]?>", x="gurk")
1211    assert "" == r("<?print 'gurk'[4:10]?>")
1212    assert "" == r("<?print x[4:10]?>", x="gurk")
1213    assert "" == r("<?print 'gurk'[-10:-5]?>")
1214    assert "" == r("<?print x[-10:-5]?>", x="gurk")
1215
1216
1217@pytest.mark.ul4
1218def test_getslice1(r):
1219    assert "urk" == r("<?print 'gurk'[1:]?>")
1220    assert "urk" == r("<?print x[1:]?>", x="gurk")
1221    assert "urk" == r("<?print 'gurk'[-3:]?>")
1222    assert "urk" == r("<?print x[-3:]?>", x="gurk")
1223    assert "" == r("<?print 'gurk'[4:]?>")
1224    assert "" == r("<?print x[4:]?>", x="gurk")
1225    assert "gurk" == r("<?print 'gurk'[-10:]?>")
1226    assert "gurk" == r("<?print x[-10:]?>", x="gurk")
1227
1228
1229@pytest.mark.ul4
1230def test_getslice2(r):
1231    assert "gur" == r("<?print 'gurk'[:3]?>")
1232    assert "gur" == r("<?print x[:3]?>", x="gurk")
1233    assert "gur" == r("<?print 'gurk'[:-1]?>")
1234    assert "gur" == r("<?print x[:-1]?>", x="gurk")
1235    assert "gurk" == r("<?print 'gurk'[:10]?>")
1236    assert "gurk" == r("<?print x[:10]?>", x="gurk")
1237    assert "" == r("<?print 'gurk'[:-5]?>")
1238    assert "" == r("<?print x[:-5]?>", x="gurk")
1239    assert "05" == r("<?print ('0' + str(x))[-2:]?>", x=5)
1240    assert "15" == r("<?print ('0' + str(x))[-2:]?>", x=15)
1241
1242
1243@pytest.mark.ul4
1244def test_getslice(r):
1245    assert "gurk" == r("<?print 'gurk'[:]?>")
1246    assert "gurk" == r("<?print x[:]?>", x="gurk")
1247    assert "[1, 2]" == r("<?print x[:]?>", x=[1, 2])
1248
1249
1250@pytest.mark.ul4
1251def test_nested(r):
1252    sc = "4"
1253    sv = "x"
1254    n = 4
1255    # when using 8 Java will output "An irrecoverable stack overflow has occurred"
1256    depth = 7
1257    for i in range(depth):
1258        sc = "({})+({})".format(sc, sc)
1259        sv = "({})+({})".format(sv, sv)
1260        n = n + n
1261
1262    assert str(n) == r('<?print {}?>'.format(sc))
1263    assert str(n) == r('<?code x=4?><?print {}?>'.format(sv))
1264
1265
1266@pytest.mark.ul4
1267def test_precedence(r):
1268    assert "14" == r('<?print 2+3*4?>')
1269    assert "20" == r('<?print (2+3)*4?>')
1270    assert "10" == r('<?print -2+-3*-4?>')
1271    assert "14" == r('<?print --2+--3*--4?>')
1272    assert "14" == r('<?print (-(-2))+(-((-3)*-(-4)))?>')
1273    assert "42" == r('<?print 2*data.value?>', data=dict(value=21))
1274    assert "42" == r('<?print data.value[0]?>', data=dict(value=[42]))
1275    assert "42" == r('<?print data[0].value?>', data=[dict(value=42)])
1276    assert "42" == r('<?print data[0][0][0]?>', data=[[[42]]])
1277    assert "42" == r('<?print data.value.value[0]?>', data=dict(value=dict(value=[42])))
1278    assert "42" == r('<?print data.value.value[0].value.value[0]?>', data=dict(value=dict(value=[dict(value=dict(value=[42]))])))
1279
1280@pytest.mark.ul4
1281def test_associativity(r):
1282    assert "9" == r('<?print 2+3+4?>')
1283    assert "-5" == r('<?print 2-3-4?>')
1284    assert "24" == r('<?print 2*3*4?>')
1285    if r is not render_js:
1286        assert "2.0" == r('<?print 24/6/2?>')
1287        assert "2" == r('<?print 24//6//2?>')
1288    else:
1289        assert 2.0 == eval(r('<?print 24/6/2?>'))
1290        assert 2 == eval(r('<?print 24//6//2?>'))
1291
1292@pytest.mark.ul4
1293def test_bracket(r):
1294    sc = "4"
1295    sv = "x"
1296    for i in range(10):
1297        sc = "({})".format(sc)
1298        sv = "({})".format(sv)
1299
1300    assert "4" == r('<?print {}?>'.format(sc))
1301    assert "4" == r('<?code x=4?><?print {}?>'.format(sv))
1302
1303
1304@pytest.mark.ul4
1305def test_callfunc_args(r):
1306    assert "@(2013-01-07)" == r("<?print repr(date(2013, 1, 7))?>")
1307    assert "@(2013-01-07)" == r("<?print repr(date(2013, 1, day=7))?>")
1308    assert "@(2013-01-07)" == r("<?print repr(date(2013, month=1, day=7))?>")
1309    assert "@(2013-01-07)" == r("<?print repr(date(year=2013, month=1, day=7))?>")
1310    assert "@(2013-01-07)" == r("<?print repr(date(2013, *[1, 7]))?>")
1311    assert "@(2013-01-07)" == r("<?print repr(date(*[2013, 1, 7]))?>")
1312    assert "@(2013-01-07)" == r("<?print repr(date(year=2013, **{'month': 1, 'day': 7}))?>")
1313    assert "@(2013-01-07)" == r("<?print repr(date(2013, *[1], **{'day': 7}))?>")
1314
1315
1316@pytest.mark.ul4
1317def test_function_now(r):
1318    now = str(datetime.datetime.now())
1319
1320    with raises(argumentmismatchmessage):
1321        r("<?print now(1)?>")
1322    with raises(argumentmismatchmessage):
1323        r("<?print now(1, 2)?>")
1324    with raises(argumentmismatchmessage):
1325        r("<?print now(foo=1)?>")
1326    assert now <= r("<?print now()?>")
1327
1328
1329@pytest.mark.ul4
1330def test_function_utcnow(r):
1331    utcnow = str(datetime.datetime.utcnow())
1332
1333    with raises(argumentmismatchmessage):
1334        r("<?print utcnow(1)?>")
1335    with raises(argumentmismatchmessage):
1336        r("<?print utcnow(1, 2)?>")
1337    with raises(argumentmismatchmessage):
1338        r("<?print utcnow(foo=1)?>")
1339    # JS and Java only have milliseconds precision, but this shouldn't lead to problems here, as rendering the template takes longer than a millisecond
1340    assert utcnow <= r("<?print utcnow()?>")
1341
1342
1343@pytest.mark.ul4
1344def test_function_date(r):
1345    assert "@(2012-10-06)" == r("<?print repr(date(2012, 10, 6))?>")
1346    assert "@(2012-10-06T12:00:00)" == r("<?print repr(date(2012, 10, 6, 12))?>")
1347    assert "@(2012-10-06T12:34:00)" == r("<?print repr(date(2012, 10, 6, 12, 34))?>")
1348    assert "@(2012-10-06T12:34:56)" == r("<?print repr(date(2012, 10, 6, 12, 34, 56))?>")
1349    if r is not render_php:
1350        assert "@(2012-10-06T12:34:56.987000)" == r("<?print repr(date(2012, 10, 6, 12, 34, 56, 987000))?>")
1351
1352    # Make sure that the parameters have the same name in all implementations
1353    assert "@(2012-10-06T12:34:56)" == r("<?print repr(date(year=2012, month=10, day=6, hour=12, minute=34, second=56, microsecond=0))?>")
1354
1355
1356@pytest.mark.ul4
1357def test_function_timedelta(r):
1358    with raises(argumentmismatchmessage):
1359        r("<?print timedelta(1, 2, 3, 4)?>")
1360    assert "1 day, 0:00:00" == r("<?print timedelta(1)?>")
1361    assert "-1 day, 0:00:00" == r("<?print timedelta(-1)?>")
1362    assert "2 days, 0:00:00" == r("<?print timedelta(2)?>")
1363    assert "0:00:01" == r("<?print timedelta(0, 0, 1000000)?>")
1364    assert "1 day, 0:00:00" == r("<?print timedelta(0, 0, 24*60*60*1000000)?>")
1365    assert "1 day, 0:00:00" == r("<?print timedelta(0, 24*60*60)?>")
1366    assert "12:00:00" == r("<?print timedelta(0.5)?>")
1367    assert "0:00:00.500000" == r("<?print timedelta(0, 0.5)?>")
1368    assert "0:00:00.500000" == r("<?print timedelta(0.5/(24*60*60))?>")
1369    assert "-1 day, 12:00:00" == r("<?print timedelta(-0.5)?>")
1370    assert "-1 day, 23:59:59.500000" == r("<?print timedelta(0, -0.5)?>")
1371    assert "0:00:01" == r("<?print timedelta(0, 1)?>")
1372    assert "0:01:00" == r("<?print timedelta(0, 60)?>")
1373    assert "1:00:00" == r("<?print timedelta(0, 60*60)?>")
1374    assert "1 day, 1:01:01.000001" == r("<?print timedelta(1, 60*60+60+1, 1)?>")
1375    assert "0:00:00.000001" == r("<?print timedelta(0, 0, 1)?>")
1376    assert "-1 day, 23:59:59" == r("<?print timedelta(0, -1)?>")
1377    assert "-1 day, 23:59:59.999999" == r("<?print timedelta(0, 0, -1)?>")
1378
1379    # Make sure that the parameters have the same name in all implementations
1380    assert "0:00:00.000001" == r("<?print timedelta(days=0, seconds=0, microseconds=1)?>")
1381
1382
1383@pytest.mark.ul4
1384def test_function_monthdelta(r):
1385    with raises(argumentmismatchmessage):
1386        r("<?print monthdelta(1, 2)?>")
1387    assert "0 months" == r("<?print monthdelta()?>")
1388    assert "2 months" == r("<?print monthdelta(2)?>")
1389    assert "1 month" == r("<?print monthdelta(1)?>")
1390    assert "-1 month" == r("<?print monthdelta(-1)?>")
1391
1392    # Make sure that the parameters have the same name in all implementations
1393    assert "1 month" == r("<?print monthdelta(months=1)?>")
1394
1395
1396@pytest.mark.ul4
1397def test_function_random(r):
1398    with raises(argumentmismatchmessage):
1399        r("<?print random(1)?>")
1400    with raises(argumentmismatchmessage):
1401        r("<?print random(1, 2)?>")
1402    with raises(argumentmismatchmessage):
1403        r("<?print random(foo=1)?>")
1404    assert "ok" == r("<?code r = random()?><?if r>=0 and r<1?>ok<?else?>fail<?end if?>")
1405
1406
1407@pytest.mark.ul4
1408def test_function_randrange(r):
1409    with raises(argumentmismatchmessage):
1410        r("<?print randrange()?>")
1411    with raises(argumentmismatchmessage):
1412        r("<?print randrange(foo=1)?>")
1413    assert "ok" == r("<?code r = randrange(4)?><?if r>=0 and r<4?>ok<?else?>fail<?end if?>")
1414    assert "ok" == r("<?code r = randrange(17, 23)?><?if r>=17 and r<23?>ok<?else?>fail<?end if?>")
1415    assert "ok" == r("<?code r = randrange(17, 23, 2)?><?if r>=17 and r<23 and r%2?>ok<?else?>fail<?end if?>")
1416
1417
1418@pytest.mark.ul4
1419def test_function_randchoice(r):
1420    with raises(argumentmismatchmessage):
1421        r("<?print randchoice()?>")
1422    assert "ok" == r("<?code r = randchoice('abc')?><?if r in 'abc'?>ok<?else?>fail<?end if?>")
1423    assert "ok" == r("<?code s = [17, 23, 42]?><?code r = randchoice(s)?><?if r in s?>ok<?else?>fail<?end if?>")
1424    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?>")
1425
1426    # Make sure that the parameters have the same name in all implementations
1427    assert "ok" == r("<?code s = [17, 23, 42]?><?code r = randchoice(sequence=s)?><?if r in s?>ok<?else?>fail<?end if?>")
1428
1429
1430@pytest.mark.ul4
1431def test_function_xmlescape(r):
1432    with raises(argumentmismatchmessage):
1433        r("<?print xmlescape()?>")
1434    with raises(argumentmismatchmessage):
1435        r("<?print xmlescape(1, 2)?>")
1436    assert "&lt;&lt;&gt;&gt;&amp;&#39;&quot;gurk" == r("<?print xmlescape(data)?>", data='<<>>&\'"gurk')
1437
1438    # Make sure that the parameters have the same name in all implementations
1439    assert "42" == r("<?print xmlescape(obj=data)?>", data=42)
1440
1441
1442@pytest.mark.ul4
1443def test_function_csv(r):
1444    with raises(argumentmismatchmessage):
1445        r("<?print csv()?>")
1446    with raises(argumentmismatchmessage):
1447        r("<?print csv(1, 2)?>")
1448    assert "" == r("<?print csv(data)?>", data=None)
1449    assert "False" == r("<?print csv(data)?>", data=False)
1450    assert "True" == r("<?print csv(data)?>", data=True)
1451    assert "42" == r("<?print csv(data)?>", data=42)
1452    # no check for float
1453    assert "abc" == r("<?print csv(data)?>", data="abc")
1454    assert '"a,b,c"' == r("<?print csv(data)?>", data="a,b,c")
1455    assert '"a""b""c"' == r("<?print csv(data)?>", data='a"b"c')
1456    assert '"a\nb\nc"' == r("<?print csv(data)?>", data="a\nb\nc")
1457
1458    # Make sure that the parameters have the same name in all implementations
1459    assert "42" == r("<?print csv(obj=data)?>", data=42)
1460
1461
1462@pytest.mark.ul4
1463def test_function_asjson(r):
1464    with raises(argumentmismatchmessage):
1465        r("<?print asjson()?>")
1466    with raises(argumentmismatchmessage):
1467        r("<?print asjson(1, 2)?>")
1468    assert "null" == r("<?print asjson(data)?>", data=None)
1469    assert "false" == r("<?print asjson(data)?>", data=False)
1470    assert "true" == r("<?print asjson(data)?>", data=True)
1471    assert "42" == r("<?print asjson(data)?>", data=42)
1472    # no check for float
1473    assert '"abc"' == r("<?print asjson(data)?>", data="abc")
1474    assert '[1, 2, 3]' == r("<?print asjson(data)?>", data=[1, 2, 3])
1475    assert '[1, 2, 3]' == r("<?print asjson(data)?>", data=PseudoList([1, 2, 3]))
1476    assert '{"one": 1}' == r("<?print asjson(data)?>", data={"one": 1})
1477    assert '{"one": 1}' == r("<?print asjson(data)?>", data=PseudoDict({"one": 1}))
1478
1479    # Make sure that the parameters have the same name in all implementations
1480    assert "42" == r("<?print asjson(obj=data)?>", data=42)
1481
1482
1483@pytest.mark.ul4
1484def test_function_fromjson(r):
1485    code = "<?print repr(fromjson(data))?>"
1486    with raises(argumentmismatchmessage):
1487        r("<?print fromjson()?>")
1488    with raises(argumentmismatchmessage):
1489        r("<?print fromjson(1, 2)?>")
1490    assert "None" == r(code, data="null")
1491    assert "False" == r(code, data="false")
1492    assert "True" == r(code, data="true")
1493    assert "42" == r(code, data="42")
1494    # no check for float
1495    assert r(code, data='"abc"') in ('"abc"', "'abc'")
1496    assert '[1, 2, 3]' == r(code, data="[1, 2, 3]")
1497    assert r(code, data='{"one": 1}') in ('{"one": 1}', "{'one': 1}")
1498
1499    # Make sure that the parameters have the same name in all implementations
1500    assert "42" == r("<?print fromjson(string=data)?>", data="42")
1501
1502
1503@pytest.mark.ul4
1504def test_function_ul4on(r):
1505    code = "<?print repr(fromul4on(asul4on(data)))?>"
1506
1507    with raises(argumentmismatchmessage):
1508        r("<?print asul4on()?>")
1509    with raises(argumentmismatchmessage):
1510        r("<?print asul4on(1, 2)?>")
1511    with raises(argumentmismatchmessage):
1512        r("<?print fromul4on()?>")
1513    with raises(argumentmismatchmessage):
1514        r("<?print fromul4on(1, 2)?>")
1515    assert "None" == r(code, data=None)
1516    assert "False" == r(code, data=False)
1517    assert "True" == r(code, data=True)
1518    assert "42" == r(code, data=42)
1519    # no check for float
1520    assert r(code, data="abc") in ('"abc"', "'abc'")
1521    assert '[1, 2, 3]' == r(code, data=[1, 2, 3])
1522    assert r(code, data={'one': 1}) in ('{"one": 1}', "{'one': 1}")
1523
1524    # Make sure that the parameters have the same name in all implementations
1525    assert "42" == r("<?print repr(fromul4on(string=asul4on(obj=data)))?>", data=42)
1526
1527
1528@pytest.mark.ul4
1529def test_function_str(r):
1530    code = "<?print str(data)?>"
1531
1532    with raises(argumentmismatchmessage):
1533        r("<?print str(1, 2)?>")
1534    assert "" == r("<?print str()?>")
1535    assert "" == r(code, data=None)
1536    assert "True" == r(code, data=True)
1537    assert "False" == r(code, data=False)
1538    assert "42" == r(code, data=42)
1539    assert "4.2" == r(code, data=4.2)
1540    assert "foo" == r(code, data="foo")
1541    assert "2011-02-09 00:00:00" == r(code, data=datetime.datetime(2011, 2, 9))
1542    assert "2011-02-09 12:34:56" == r(code, data=datetime.datetime(2011, 2, 9, 12, 34, 56))
1543    if r is not render_php:
1544        assert "2011-02-09 12:34:56.987000" == r(code, data=datetime.datetime(2011, 2, 9, 12, 34, 56, 987000))
1545    assert "0:00:00" == r(code, data=datetime.timedelta())
1546    assert "1 day, 0:00:00" == r(code, data=datetime.timedelta(1))
1547    assert "-1 day, 0:00:00" == r(code, data=datetime.timedelta(-1))
1548    assert "2 days, 0:00:00" == r(code, data=datetime.timedelta(2))
1549    assert "0:00:01" == r(code, data=datetime.timedelta(0, 1))
1550    assert "0:01:00" == r(code, data=datetime.timedelta(0, 60))
1551    assert "1:00:00" == r(code, data=datetime.timedelta(0, 60*60))
1552    assert "1 day, 1:01:01.000001" == r(code, data=datetime.timedelta(1, 60*60+60+1, 1))
1553    assert "0:00:00.000001" == r(code, data=datetime.timedelta(0, 0, 1))
1554    assert "-1 day, 23:59:59" == r(code, data=datetime.timedelta(0, -1))
1555    assert "-1 day, 23:59:59.999999" == r(code, data=datetime.timedelta(0, 0, -1))
1556
1557    # Make sure that the parameters have the same name in all implementations
1558    assert "42" == r("<?print str(obj=data)?>", data=42)
1559
1560
1561@pytest.mark.ul4
1562def test_function_bool(r):
1563    with raises(argumentmismatchmessage):
1564        r("<?print bool(1, 2)?>")
1565    assert "False" == r("<?print bool()?>")
1566    code = "<?print bool(data)?>"
1567    assert "True" == r(code, data=True)
1568    assert "False" == r(code, data=False)
1569    assert "False" == r(code, data=0)
1570    assert "True" == r(code, data=42)
1571    assert "False" == r(code, data=0.0)
1572    assert "True" == r(code, data=42.5)
1573    assert "False" == r(code, data="")
1574    assert "True" == r(code, data="gurk")
1575    assert "False" == r(code, data=[])
1576    assert "True" == r(code, data=["gurk"])
1577    assert "False" == r(code, data={})
1578    assert "True" == r(code, data={"gurk": "hurz"})
1579    assert "True" == r(code, data=datetime.datetime.now())
1580    assert "False" == r(code, data=datetime.timedelta())
1581    assert "True" == r(code, data=datetime.timedelta(1))
1582    assert "False" == r(code, data=misc.monthdelta())
1583    assert "True" == r(code, data=misc.monthdelta(1))
1584
1585    # Make sure that the parameters have the same name in all implementations
1586    assert "True" == r("<?print bool(obj=data)?>", data=42)
1587
1588
1589@pytest.mark.ul4
1590def test_function_int(r):
1591    with raises(argumentmismatchmessage):
1592        r("<?print int(1, 2, 3)?>")
1593    with raises("int\\(\\) argument must be a string or a number|int\\(null\\) not supported"):
1594        r("<?print int(data)?>", data=None)
1595    with raises("invalid literal for int|NumberFormatException"):
1596        r("<?print int(data)?>", data="foo")
1597    assert "0" == r("<?print int()?>")
1598    assert "1" == r("<?print int(data)?>", data=True)
1599    assert "0" == r("<?print int(data)?>", data=False)
1600    assert "42" == r("<?print int(data)?>", data=42)
1601    assert "4" == r("<?print int(data)?>", data=4.2)
1602    assert "42" == r("<?print int(data)?>", data="42")
1603    assert "66" == r("<?print int(data, 16)?>", data="42")
1604
1605    # Make sure that the parameters have the same name in all implementations
1606    assert "42" == r("<?print int(obj=data, base=None)?>", data=42)
1607
1608
1609@pytest.mark.ul4
1610def test_function_float(r):
1611    code = "<?print float(data)?>"
1612
1613    with raises(argumentmismatchmessage):
1614        r("<?print float(1, 2, 3)?>")
1615    with raises("float\\(\\) argument must be a string or a number|float\\(null\\) not supported"):
1616        r(code, data=None)
1617    assert "4.2" == r(code, data=4.2)
1618    if r is not render_js:
1619        assert "0.0" == r("<?print float()?>")
1620        assert "1.0" == r(code, data=True)
1621        assert "0.0" == r(code, data=False)
1622        assert "42.0" == r(code, data=42)
1623        assert "42.0" == r(code, data="42")
1624
1625        # Make sure that the parameters have the same name in all implementations
1626        assert "42.0" == r("<?print float(obj=data)?>", data=42)
1627    else:
1628        assert 0.0 == eval(r("<?print float()?>"))
1629        assert 1.0 == eval(r(code, data=True))
1630        assert 0.0 == eval(r(code, data=False))
1631        assert 42.0 == eval(r(code, data=42))
1632        assert 42.0 == eval(r(code, data="42"))
1633
1634        # Make sure that the parameters have the same name in all implementations
1635        assert 42.0 == eval(r("<?print float(obj=data)?>", data=42))
1636
1637
1638@pytest.mark.ul4
1639def test_function_len(r):
1640    code = "<?print len(data)?>"
1641
1642    with raises(argumentmismatchmessage):
1643        r("<?print len()?>")
1644    with raises(argumentmismatchmessage):
1645        r("<?print len(1, 2)?>")
1646    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1647        r(code, data=None)
1648    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1649        r(code, data=True)
1650    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1651        r(code, data=False)
1652    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1653        r(code, data=42)
1654    with raises("has no len\\(\\)|len\\(.*\\) not supported"):
1655        r(code, data=4.2)
1656    assert "42" == r(code, data=42*"?")
1657    assert "42" == r(code, data=42*[None])
1658    assert "42" == r(code, data=dict.fromkeys(range(42)))
1659
1660    # Make sure that the parameters have the same name in all implementations
1661    assert "42" == r("<?print len(sequence=data)?>", data=42*"?")
1662
1663
1664@pytest.mark.ul4
1665def test_function_any(r):
1666    with raises(argumentmismatchmessage):
1667        r("<?print any()?>")
1668    with raises(argumentmismatchmessage):
1669        r("<?print any(1, 2)?>")
1670    with raises("is not iterable|any\\(.*\\) not supported"):
1671        r("<?print any(data)?>", data=None)
1672    assert "False" == r("<?print any('')?>")
1673    assert "True" == r("<?print any('foo')?>")
1674    assert "True" == r("<?print any(i > 7 for i in range(10))?>")
1675    assert "False" == r("<?print any(i > 17 for i in range(10))?>")
1676
1677    # Make sure that the parameters have the same name in all implementations
1678    assert "False" == r("<?print any(iterable=(i > 17 for i in range(10)))?>")
1679
1680
1681@pytest.mark.ul4
1682def test_function_all(r):
1683    with raises(argumentmismatchmessage):
1684        r("<?print all()?>")
1685    with raises(argumentmismatchmessage):
1686        r("<?print all(1, 2)?>")
1687    with raises("is not iterable|all\\(.*\\) not supported"):
1688        r("<?print all(data)?>", data=None)
1689    assert "True" == r("<?print all('')?>")
1690    assert "True" == r("<?print all('foo')?>")
1691    assert "False" == r("<?print all(i < 7 for i in range(10))?>")
1692    assert "True" == r("<?print all(i < 17 for i in range(10))?>")
1693
1694    # Make sure that the parameters have the same name in all implementations
1695    assert "True" == r("<?print all(iterable=(i < 17 for i in range(10)))?>")
1696
1697
1698@pytest.mark.ul4
1699def test_function_enumerate(r):
1700    code1 = "<?for (i, value) in enumerate(data)?>(<?print value?>=<?print i?>)<?end for?>"
1701    code2 = "<?for (i, value) in enumerate(data, 42)?>(<?print value?>=<?print i?>)<?end for?>"
1702
1703    with raises(argumentmismatchmessage):
1704        r("<?print enumerate()?>")
1705    with raises(argumentmismatchmessage):
1706        r("<?print enumerate(1, 2, 3)?>")
1707    with raises("is not iterable|iter\\(.*\\) not supported"):
1708        r(code1, data=None)
1709    with raises("is not iterable|iter\\(.*\\) not supported"):
1710        r(code1, data=True)
1711    with raises("is not iterable|iter\\(.*\\) not supported"):
1712        r(code1, data=False)
1713    with raises("is not iterable|iter\\(.*\\) not supported"):
1714        r(code1, data=42)
1715    with raises("is not iterable|iter\\(.*\\) not supported"):
1716        r(code1, data=4.2)
1717    assert "(f=0)(o=1)(o=2)" == r(code1, data="foo")
1718    assert "(foo=0)(bar=1)" == r(code1, data=["foo", "bar"])
1719    assert "(foo=0)" == r(code1, data=dict(foo=True))
1720    assert "" == r(code1, data="")
1721    assert "(f=42)(o=43)(o=44)" == r(code2, data="foo")
1722
1723    # Make sure that the parameters have the same name in all implementations
1724    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")
1725
1726
1727@pytest.mark.ul4
1728def test_function_enumfl(r):
1729    code1 = "<?for (i, f, l, value) in enumfl(data)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>"
1730    code2 = "<?for (i, f, l, value) in enumfl(data, 42)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>"
1731
1732    with raises(argumentmismatchmessage):
1733        r("<?print enumfl()?>")
1734    with raises(argumentmismatchmessage):
1735        r("<?print enumfl(1, 2, 3)?>")
1736    with raises("is not iterable|iter\\(.*\\) not supported"):
1737        r(code1, data=None)
1738    with raises("is not iterable|iter\\(.*\\) not supported"):
1739        r(code1, data=True)
1740    with raises("is not iterable|iter\\(.*\\) not supported"):
1741        r(code1, data=False)
1742    with raises("is not iterable|iter\\(.*\\) not supported"):
1743        r(code1, data=42)
1744    with raises("is not iterable|iter\\(.*\\) not supported"):
1745        r(code1, data=4.2)
1746    assert "[(f=0)(o=1)(o=2)]" == r(code1, data="foo")
1747    assert "[(foo=0)(bar=1)]" == r(code1, data=["foo", "bar"])
1748    assert "[(foo=0)]" == r(code1, data=dict(foo=True))
1749    assert "" == r(code1, data="")
1750    assert "[(f=42)(o=43)(o=44)]" == r(code2, data="foo")
1751
1752    # Make sure that the parameters have the same name in all implementations
1753    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")
1754
1755
1756@pytest.mark.ul4
1757def test_function_isfirstlast(r):
1758    code = "<?for (f, l, value) in isfirstlast(data)?><?if f?>[<?end if?>(<?print value?>)<?if l?>]<?end if?><?end for?>"
1759
1760    with raises(argumentmismatchmessage):
1761        r("<?print isfirstlast()?>")
1762    with raises(argumentmismatchmessage):
1763        r("<?print isfirstlast(1, 2)?>")
1764    with raises("is not iterable|iter\\(.*\\) not supported"):
1765        r(code, data=None)
1766    with raises("is not iterable|iter\\(.*\\) not supported"):
1767        r(code, data=True)
1768    with raises("is not iterable|iter\\(.*\\) not supported"):
1769        r(code, data=False)
1770    with raises("is not iterable|iter\\(.*\\) not supported"):
1771        r(code, data=42)
1772    with raises("is not iterable|iter\\(.*\\) not supported"):
1773        r(code, data=4.2)
1774    assert "[(f)(o)(o)]" == r(code, data="foo")
1775    assert "[(foo)(bar)]" == r(code, data=["foo", "bar"])
1776    assert "[(foo)]" == r(code, data=dict(foo=True))
1777    assert "" == r(code, data="")
1778
1779    # Make sure that the parameters have the same name in all implementations
1780    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")
1781
1782
1783@pytest.mark.ul4
1784def test_function_isfirst(r):
1785    code = "<?for (f, value) in isfirst(data)?><?if f?>[<?end if?>(<?print value?>)<?end for?>"
1786
1787    with raises(argumentmismatchmessage):
1788        r("<?print isfirst()?>")
1789    with raises(argumentmismatchmessage):
1790        r("<?print isfirst(1, 2)?>")
1791    with raises("is not iterable|iter\\(.*\\) not supported"):
1792        r(code, data=None)
1793    with raises("is not iterable|iter\\(.*\\) not supported"):
1794        r(code, data=True)
1795    with raises("is not iterable|iter\\(.*\\) not supported"):
1796        r(code, data=False)
1797    with raises("is not iterable|iter\\(.*\\) not supported"):
1798        r(code, data=42)
1799    with raises("is not iterable|iter\\(.*\\) not supported"):
1800        r(code, data=4.2)
1801    assert "[(f)(o)(o)" == r(code, data="foo")
1802    assert "[(foo)(bar)" == r(code, data=["foo", "bar"])
1803    assert "[(foo)" == r(code, data=dict(foo=True))
1804    assert "" == r(code, data="")
1805
1806    # Make sure that the parameters have the same name in all implementations
1807    assert "[(f)(o)(o)" == r("<?for (f, value) in isfirst(iterable=data)?><?if f?>[<?end if?>(<?print value?>)<?end for?>", data="foo")
1808
1809
1810@pytest.mark.ul4
1811def test_function_islast(r):
1812    code = "<?for (l, value) in islast(data)?>(<?print value?>)<?if l?>]<?end if?><?end for?>"
1813
1814    with raises(argumentmismatchmessage):
1815        r("<?print islast()?>")
1816    with raises(argumentmismatchmessage):
1817        r("<?print islast(1, 2)?>")
1818    with raises("is not iterable|iter\\(.*\\) not supported"):
1819        r(code, data=None)
1820    with raises("is not iterable|iter\\(.*\\) not supported"):
1821        r(code, data=True)
1822    with raises("is not iterable|iter\\(.*\\) not supported"):
1823        r(code, data=False)
1824    with raises("is not iterable|iter\\(.*\\) not supported"):
1825        r(code, data=42)
1826    with raises("is not iterable|iter\\(.*\\) not supported"):
1827        r(code, data=4.2)
1828    assert "(f)(o)(o)]" == r(code, data="foo")
1829    assert "(foo)(bar)]" == r(code, data=["foo", "bar"])
1830    assert "(foo)]" == r(code, data=dict(foo=True))
1831    assert "" == r(code, data="")
1832
1833    # Make sure that the parameters have the same name in all implementations
1834    assert "(f)(o)(o)]" == r("<?for (l, value) in islast(iterable=data)?>(<?print value?>)<?if l?>]<?end if?><?end for?>", data="foo")
1835
1836
1837@pytest.mark.ul4
1838def test_function_isundefined(r):
1839    code = "<?print isundefined(data)?>"
1840
1841    with raises(argumentmismatchmessage):
1842        r("<?print isundefined()?>")
1843    with raises(argumentmismatchmessage):
1844        r("<?print isundefined(1, 2)?>")
1845    assert "True" == r(code)
1846    assert "False" == r(code, data=None)
1847    assert "False" == r(code, data=True)
1848    assert "False" == r(code, data=False)
1849    assert "False" == r(code, data=42)
1850    assert "False" == r(code, data=4.2)
1851    assert "False" == r(code, data="foo")
1852    assert "False" == r(code, data=datetime.datetime.now())
1853    assert "False" == r(code, data=datetime.timedelta(1))
1854    assert "False" == r(code, data=misc.monthdelta(1))
1855    assert "False" == r(code, data=())
1856    assert "False" == r(code, data=[])
1857    assert "False" == r(code, data={})
1858    assert "False" == r("<?print isundefined(repr)?>")
1859    assert "False" == r(code, data=ul4c.Template(""))
1860    assert "False" == r(code, data=color.red)
1861
1862    # Make sure that the parameters have the same name in all implementations
1863    assert "False" == r("<?print isundefined(obj=data)?>", data=None)
1864
1865
1866@pytest.mark.ul4
1867def test_function_isdefined(r):
1868    code = "<?print isdefined(data)?>"
1869
1870    with raises(argumentmismatchmessage):
1871        r("<?print isdefined()?>")
1872    with raises(argumentmismatchmessage):
1873        r("<?print isdefined(1, 2)?>")
1874    assert "False" == r(code)
1875    assert "True" == r(code, data=None)
1876    assert "True" == r(code, data=True)
1877    assert "True" == r(code, data=False)
1878    assert "True" == r(code, data=42)
1879    assert "True" == r(code, data=4.2)
1880    assert "True" == r(code, data="foo")
1881    assert "True" == r(code, data=datetime.datetime.now())
1882    assert "True" == r(code, data=datetime.timedelta(1))
1883    assert "True" == r(code, data=misc.monthdelta(1))
1884    assert "True" == r(code, data=())
1885    assert "True" == r(code, data=[])
1886    assert "True" == r(code, data={})
1887    assert "True" == r(code, data=ul4c.Template(""))
1888    assert "True" == r("<?print isdefined(repr)?>")
1889    assert "True" == r(code, data=color.red)
1890
1891    # Make sure that the parameters have the same name in all implementations
1892    assert "True" == r("<?print isdefined(obj=data)?>", data=None)
1893
1894
1895@pytest.mark.ul4
1896def test_function_isnone(r):
1897    code = "<?print isnone(data)?>"
1898
1899    with raises(argumentmismatchmessage):
1900        r("<?print isnone()?>")
1901    with raises(argumentmismatchmessage):
1902        r("<?print isnone(1, 2)?>")
1903    assert "False" == r(code)
1904    assert "True" == r(code, data=None)
1905    assert "False" == r(code, data=True)
1906    assert "False" == r(code, data=False)
1907    assert "False" == r(code, data=42)
1908    assert "False" == r(code, data=4.2)
1909    assert "False" == r(code, data="foo")
1910    assert "False" == r(code, data=datetime.datetime.now())
1911    assert "False" == r(code, data=datetime.timedelta(1))
1912    assert "False" == r(code, data=misc.monthdelta(1))
1913    assert "False" == r(code, data=())
1914    assert "False" == r(code, data=[])
1915    assert "False" == r(code, data={})
1916    assert "False" == r(code, data=ul4c.Template(""))
1917    assert "False" == r("<?print isnone(repr)?>")
1918    assert "False" == r(code, data=color.red)
1919
1920    # Make sure that the parameters have the same name in all implementations
1921    assert "True" == r("<?print isnone(obj=data)?>", data=None)
1922
1923
1924@pytest.mark.ul4
1925def test_function_isbool(r):
1926    code = "<?print isbool(data)?>"
1927
1928    with raises(argumentmismatchmessage):
1929        r("<?print isbool()?>")
1930    with raises(argumentmismatchmessage):
1931        r("<?print isbool(1, 2)?>")
1932    assert "False" == r(code)
1933    assert "False" == r(code, data=None)
1934    assert "True" == r(code, data=True)
1935    assert "True" == r(code, data=False)
1936    assert "False" == r(code, data=42)
1937    assert "False" == r(code, data=4.2)
1938    assert "False" == r(code, data="foo")
1939    assert "False" == r(code, data=datetime.datetime.now())
1940    assert "False" == r(code, data=datetime.timedelta(1))
1941    assert "False" == r(code, data=misc.monthdelta(1))
1942    assert "False" == r(code, data=())
1943    assert "False" == r(code, data=[])
1944    assert "False" == r(code, data={})
1945    assert "False" == r(code, data=ul4c.Template(""))
1946    assert "False" == r("<?print isbool(repr)?>")
1947    assert "False" == r(code, data=color.red)
1948
1949    # Make sure that the parameters have the same name in all implementations
1950    assert "False" == r("<?print isbool(obj=data)?>", data=None)
1951
1952
1953@pytest.mark.ul4
1954def test_function_isint(r):
1955    code = "<?print isint(data)?>"
1956
1957    with raises(argumentmismatchmessage):
1958        r("<?print isint()?>")
1959    with raises(argumentmismatchmessage):
1960        r("<?print isint(1, 2)?>")
1961    assert "False" == r(code)
1962    assert "False" == r(code, data=None)
1963    assert "False" == r(code, data=True)
1964    assert "False" == r(code, data=False)
1965    assert "True" == r(code, data=42)
1966    assert "False" == r(code, data=4.2)
1967    assert "False" == r(code, data="foo")
1968    assert "False" == r(code, data=datetime.datetime.now())
1969    assert "False" == r(code, data=datetime.timedelta(1))
1970    assert "False" == r(code, data=misc.monthdelta(1))
1971    assert "False" == r(code, data=())
1972    assert "False" == r(code, data=[])
1973    assert "False" == r(code, data={})
1974    assert "False" == r(code, data=ul4c.Template(""))
1975    assert "False" == r("<?print isint(repr)?>")
1976    assert "False" == r(code, data=color.red)
1977
1978    # Make sure that the parameters have the same name in all implementations
1979    assert "False" == r("<?print isint(obj=data)?>", data=None)
1980
1981
1982@pytest.mark.ul4
1983def test_function_isfloat(r):
1984    code = "<?print isfloat(data)?>"
1985
1986    with raises(argumentmismatchmessage):
1987        r("<?print isfloat()?>")
1988    with raises(argumentmismatchmessage):
1989        r("<?print isfloat(1, 2)?>")
1990    assert "False" == r(code)
1991    assert "False" == r(code, data=None)
1992    assert "False" == r(code, data=True)
1993    assert "False" == r(code, data=False)
1994    assert "False" == r(code, data=42)
1995    assert "True" == r(code, data=4.2)
1996    assert "False" == r(code, data="foo")
1997    assert "False" == r(code, data=datetime.datetime.now())
1998    assert "False" == r(code, data=datetime.timedelta(1))
1999    assert "False" == r(code, data=misc.monthdelta(1))
2000    assert "False" == r(code, data=())
2001    assert "False" == r(code, data=[])
2002    assert "False" == r(code, data={})
2003    assert "False" == r(code, data=ul4c.Template(""))
2004    assert "False" == r("<?print isfloat(repr)?>")
2005    assert "False" == r(code, data=color.red)
2006
2007    # Make sure that the parameters have the same name in all implementations
2008    assert "False" == r("<?print isfloat(obj=data)?>", data=None)
2009
2010
2011@pytest.mark.ul4
2012def test_function_isstr(r):
2013    code = "<?print isstr(data)?>"
2014
2015    with raises(argumentmismatchmessage):
2016        r("<?print isstr()?>")
2017    with raises(argumentmismatchmessage):
2018        r("<?print isstr(1, 2)?>")
2019    assert "False" == r(code)
2020    assert "False" == r(code, data=None)
2021    assert "False" == r(code, data=True)
2022    assert "False" == r(code, data=False)
2023    assert "False" == r(code, data=42)
2024    assert "False" == r(code, data=4.2)
2025    assert "True" == r(code, data="foo")
2026    assert "False" == r(code, data=datetime.datetime.now())
2027    assert "False" == r(code, data=datetime.timedelta(1))
2028    assert "False" == r(code, data=misc.monthdelta(1))
2029    assert "False" == r(code, data=())
2030    assert "False" == r(code, data=[])
2031    assert "False" == r(code, data={})
2032    assert "False" == r(code, data=ul4c.Template(""))
2033    assert "False" == r("<?print isstr(repr)?>")
2034    assert "False" == r(code, data=color.red)
2035
2036    # Make sure that the parameters have the same name in all implementations
2037    assert "False" == r("<?print isstr(obj=data)?>", data=None)
2038
2039
2040@pytest.mark.ul4
2041def test_function_isdate(r):
2042    code = "<?print isdate(data)?>"
2043
2044    with raises(argumentmismatchmessage):
2045        r("<?print isdate()?>")
2046    with raises(argumentmismatchmessage):
2047        r("<?print isdate(1, 2)?>")
2048    assert "False" == r(code)
2049    assert "False" == r(code, data=None)
2050    assert "False" == r(code, data=True)
2051    assert "False" == r(code, data=False)
2052    assert "False" == r(code, data=42)
2053    assert "False" == r(code, data=4.2)
2054    assert "False" == r(code, data="foo")
2055    assert "True" == r(code, data=datetime.datetime.now())
2056    assert "False" == r(code, data=datetime.timedelta(1))
2057    assert "False" == r(code, data=misc.monthdelta(1))
2058    assert "False" == r(code, data=())
2059    assert "False" == r(code, data=[])
2060    assert "False" == r(code, data={})
2061    assert "False" == r(code, data=ul4c.Template(""))
2062    assert "False" == r("<?print isdate(repr)?>")
2063    assert "False" == r(code, data=color.red)
2064
2065    # Make sure that the parameters have the same name in all implementations
2066    assert "False" == r("<?print isdate(obj=data)?>", data=None)
2067
2068
2069@pytest.mark.ul4
2070def test_function_islist(r):
2071    code = "<?print islist(data)?>"
2072
2073    with raises(argumentmismatchmessage):
2074        r("<?print islist()?>")
2075    with raises(argumentmismatchmessage):
2076        r("<?print islist(1, 2)?>")
2077    assert "False" == r(code)
2078    assert "False" == r(code, data=None)
2079    assert "False" == r(code, data=True)
2080    assert "False" == r(code, data=False)
2081    assert "False" == r(code, data=42)
2082    assert "False" == r(code, data=4.2)
2083    assert "False" == r(code, data="foo")
2084    assert "False" == r(code, data=datetime.datetime.now())
2085    assert "False" == r(code, data=datetime.timedelta(1))
2086    assert "False" == r(code, data=misc.monthdelta(1))
2087    assert "True" == r(code, data=())
2088    assert "True" == r(code, data=[])
2089    assert "True" == r(code, data=PseudoList([]))
2090    if r is not render_php:
2091        assert "False" == r(code, data={})
2092    assert "False" == r(code, data=ul4c.Template(""))
2093    assert "False" == r("<?print islist(repr)?>")
2094    assert "False" == r(code, data=color.red)
2095
2096    # Make sure that the parameters have the same name in all implementations
2097    assert "False" == r("<?print islist(obj=data)?>", data=None)
2098
2099
2100@pytest.mark.ul4
2101def test_function_isdict(r):
2102    code = "<?print isdict(data)?>"
2103
2104    with raises(argumentmismatchmessage):
2105        r("<?print isdict()?>")
2106    with raises(argumentmismatchmessage):
2107        r("<?print isdict(1, 2)?>")
2108    assert "False" == r(code)
2109    assert "False" == r(code, data=None)
2110    assert "False" == r(code, data=True)
2111    assert "False" == r(code, data=False)
2112    assert "False" == r(code, data=42)
2113    assert "False" == r(code, data=4.2)
2114    assert "False" == r(code, data="foo")
2115    assert "False" == r(code, data=datetime.datetime.now())
2116    assert "False" == r(code, data=datetime.timedelta(1))
2117    assert "False" == r(code, data=misc.monthdelta(1))
2118    if r is not render_php:
2119        assert "False" == r(code, data=())
2120        assert "False" == r(code, data=[])
2121    assert "True" == r(code, data={})
2122    assert "True" == r(code, data=PseudoDict({}))
2123    assert "False" == r(code, data=ul4c.Template(""))
2124    assert "False" == r("<?print isdict(repr)?>")
2125    assert "False" == r(code, data=color.red)
2126
2127    # Make sure that the parameters have the same name in all implementations
2128    assert "False" == r("<?print isdict(obj=data)?>", data=None)
2129
2130
2131@pytest.mark.ul4
2132def test_function_istemplate(r):
2133    code = "<?print istemplate(data)?>"
2134
2135    with raises(argumentmismatchmessage):
2136        r("<?print istemplate()?>")
2137    with raises(argumentmismatchmessage):
2138        r("<?print istemplate(1, 2)?>")
2139    assert "False" == r(code)
2140    assert "False" == r(code, data=None)
2141    assert "False" == r(code, data=True)
2142    assert "False" == r(code, data=False)
2143    assert "False" == r(code, data=42)
2144    assert "False" == r(code, data=4.2)
2145    assert "False" == r(code, data="foo")
2146    assert "False" == r(code, data=datetime.datetime.now())
2147    assert "False" == r(code, data=datetime.timedelta(1))
2148    assert "False" == r(code, data=misc.monthdelta(1))
2149    assert "False" == r(code, data=())
2150    assert "False" == r(code, data=[])
2151    assert "False" == r(code, data={})
2152    assert "True" == r(code, data=ul4c.Template(""))
2153    assert "False" == r("<?print istemplate(repr)?>")
2154    assert "False" == r(code, data=color.red)
2155
2156    # Make sure that the parameters have the same name in all implementations
2157    assert "False" == r("<?print istemplate(obj=data)?>", data=None)
2158
2159
2160@pytest.mark.ul4
2161def test_function_isfunction(r):
2162    code = "<?print isfunction(data)?>"
2163
2164    with raises(argumentmismatchmessage):
2165        r("<?print isfunction()?>")
2166    with raises(argumentmismatchmessage):
2167        r("<?print isfunction(1, 2)?>")
2168    assert "False" == r(code)
2169    assert "False" == r(code, data=None)
2170    assert "False" == r(code, data=True)
2171    assert "False" == r(code, data=False)
2172    assert "False" == r(code, data=42)
2173    assert "False" == r(code, data=4.2)
2174    assert "False" == r(code, data="foo")
2175    assert "False" == r(code, data=datetime.datetime.now())
2176    assert "False" == r(code, data=datetime.timedelta(1))
2177    assert "False" == r(code, data=misc.monthdelta(1))
2178    assert "False" == r(code, data=())
2179    assert "False" == r(code, data=[])
2180    assert "False" == r(code, data={})
2181    assert "True" == r(code, data=ul4c.Template(""))
2182    assert "True" == r("<?print isfunction(repr)?>")
2183    assert "True" == r("<?def f?><?return 42?><?end def?><?print isfunction(f)?>")
2184    assert "False" == r(code, data=color.red)
2185
2186    # Make sure that the parameters have the same name in all implementations
2187    assert "False" == r("<?print istemplate(obj=data)?>", data=None)
2188
2189
2190@pytest.mark.ul4
2191def test_function_iscolor(r):
2192    code = "<?print iscolor(data)?>"
2193
2194    with raises(argumentmismatchmessage):
2195        r("<?print iscolor()?>")
2196    with raises(argumentmismatchmessage):
2197        r("<?print iscolor(1, 2)?>")
2198    assert "False" == r(code)
2199    assert "False" == r(code, data=None)
2200    assert "False" == r(code, data=True)
2201    assert "False" == r(code, data=False)
2202    assert "False" == r(code, data=42)
2203    assert "False" == r(code, data=4.2)
2204    assert "False" == r(code, data="foo")
2205    assert "False" == r(code, data=datetime.datetime.now())
2206    assert "False" == r(code, data=datetime.timedelta(1))
2207    assert "False" == r(code, data=misc.monthdelta(1))
2208    assert "False" == r(code, data=())
2209    assert "False" == r(code, data=[])
2210    assert "False" == r(code, data={})
2211    assert "False" == r(code, data=ul4c.Template(""))
2212    assert "False" == r("<?print iscolor(repr)?>")
2213    assert "True" == r(code, data=color.red)
2214
2215    # Make sure that the parameters have the same name in all implementations
2216    assert "False" == r("<?print iscolor(obj=data)?>", data=None)
2217
2218
2219@pytest.mark.ul4
2220def test_function_istimedelta(r):
2221    code = "<?print istimedelta(data)?>"
2222
2223    with raises(argumentmismatchmessage):
2224        r("<?print istimedelta()?>")
2225    with raises(argumentmismatchmessage):
2226        r("<?print istimedelta(1, 2)?>")
2227    assert "False" == r(code)
2228    assert "False" == r(code, data=None)
2229    assert "False" == r(code, data=True)
2230    assert "False" == r(code, data=False)
2231    assert "False" == r(code, data=42)
2232    assert "False" == r(code, data=4.2)
2233    assert "False" == r(code, data="foo")
2234    assert "False" == r(code, data=datetime.datetime.now())
2235    assert "True" == r(code, data=datetime.timedelta(1))
2236    assert "False" == r(code, data=misc.monthdelta(1))
2237    assert "False" == r(code, data=())
2238    assert "False" == r(code, data=[])
2239    assert "False" == r(code, data={})
2240    assert "False" == r(code, data=ul4c.Template(""))
2241    assert "False" == r("<?print istimedelta(repr)?>")
2242    assert "False" == r(code, data=color.red)
2243
2244    # Make sure that the parameters have the same name in all implementations
2245    assert "False" == r("<?print istimedelta(obj=data)?>", data=None)
2246
2247
2248@pytest.mark.ul4
2249def test_function_ismonthdelta(r):
2250    code = "<?print ismonthdelta(data)?>"
2251
2252    with raises(argumentmismatchmessage):
2253        r("<?print ismonthdelta()?>")
2254    with raises(argumentmismatchmessage):
2255        r("<?print ismonthdelta(1, 2)?>")
2256    assert "False" == r(code)
2257    assert "False" == r(code, data=None)
2258    assert "False" == r(code, data=True)
2259    assert "False" == r(code, data=False)
2260    assert "False" == r(code, data=42)
2261    assert "False" == r(code, data=4.2)
2262    assert "False" == r(code, data="foo")
2263    assert "False" == r(code, data=datetime.datetime.now())
2264    assert "False" == r(code, data=datetime.timedelta(1))
2265    assert "True" == r(code, data=misc.monthdelta(1))
2266    assert "False" == r(code, data=())
2267    assert "False" == r(code, data=[])
2268    assert "False" == r(code, data={})
2269    assert "False" == r(code, data=ul4c.Template(""))
2270    assert "False" == r("<?print ismonthdelta(repr)?>")
2271    assert "False" == r(code, data=color.red)
2272
2273    # Make sure that the parameters have the same name in all implementations
2274    assert "False" == r("<?print ismonthdelta(obj=data)?>", data=None)
2275
2276
2277@pytest.mark.ul4
2278def test_function_repr(r):
2279    code = "<?print repr(data)?>"
2280
2281    with raises(argumentmismatchmessage):
2282        r("<?print repr()?>")
2283    with raises(argumentmismatchmessage):
2284        r("<?print repr(1, 2)?>")
2285    assert "None" == r(code, data=None)
2286    assert "True" == r(code, data=True)
2287    assert "False" == r(code, data=False)
2288    assert "42" == r(code, data=42)
2289    assert 42.5 == eval(r(code, data=42.5))
2290    assert r(code, data="foo") in ('"foo"', "'foo'")
2291    assert [1, 2, 3] == eval(r(code, data=[1, 2, 3]))
2292    if r is not render_js:
2293        assert [1, 2, 3] == eval(r(code, data=(1, 2, 3)))
2294    assert {"a": 1, "b": 2} == eval(r(code, data={"a": 1, "b": 2}))
2295    if r is not render_php:
2296        assert "@(2011-02-07T12:34:56.123000)" == r(code, data=datetime.datetime(2011, 2, 7, 12, 34, 56, 123000))
2297    assert "@(2011-02-07T12:34:56)" == r(code, data=datetime.datetime(2011, 2, 7, 12, 34, 56))
2298    assert "@(2011-02-07)" == r(code, data=datetime.datetime(2011, 2, 7))
2299    assert "@(2011-02-07)" == r(code, data=datetime.date(2011, 2, 7))
2300    assert "timedelta(1)" == r(code, data=datetime.timedelta(1))
2301    assert "timedelta(0, 1)" == r(code, data=datetime.timedelta(0, 1))
2302    assert "timedelta(0, 0, 1)" == r(code, data=datetime.timedelta(0, 0, 1))
2303    assert "timedelta(-1)" == r(code, data=datetime.timedelta(-1))
2304    assert "timedelta(-1, 86399)" == r(code, data=datetime.timedelta(0, -1))
2305    assert "timedelta(-1, 86399, 999999)" == r(code, data=datetime.timedelta(0, 0, -1))
2306    assert "timedelta(0, 43200)" == r(code, data=datetime.timedelta(0.5))
2307    assert "timedelta(0, 0, 500000)" == r(code, data=datetime.timedelta(0, 0.5))
2308    assert "timedelta(-1, 43200)" == r(code, data=datetime.timedelta(-0.5))
2309    assert "timedelta(-1, 86399, 500000)" == r(code, data=datetime.timedelta(0, -0.5))
2310
2311    # Make sure that the parameters have the same name in all implementations
2312    assert "None" == r("<?print repr(obj=data)?>", data=None)
2313
2314
2315@pytest.mark.ul4
2316def test_function_format_date(r):
2317    t = datetime.datetime(2011, 1, 25, 13, 34, 56, 987000)
2318    code2 = "<?print format(data, fmt)?>"
2319    code3 = "<?print format(data, fmt, lang)?>"
2320
2321    assert "2011" == r(code2, fmt="%Y", data=t)
2322    assert "01" == r(code2, fmt="%m", data=t)
2323    assert "25" == r(code2, fmt="%d", data=t)
2324    assert "13" == r(code2, fmt="%H", data=t)
2325    assert "34" == r(code2, fmt="%M", data=t)
2326    assert "56" == r(code2, fmt="%S", data=t)
2327    assert "987000" == r(code2, fmt="%f", data=t)
2328    assert "Tue" == r(code2, fmt="%a", data=t)
2329    assert "Tue" == r(code3, fmt="%a", data=t, lang=None)
2330    assert "Tue" == r(code3, fmt="%a", data=t, lang="en")
2331    assert "Di" == r(code3, fmt="%a", data=t, lang="de")
2332    assert "Di" == r(code3, fmt="%a", data=t, lang="de_DE")
2333    assert "Tuesday" == r(code2, fmt="%A", data=t)
2334    assert "Tuesday" == r(code3, fmt="%A", data=t, lang=None)
2335    assert "Tuesday" == r(code3, fmt="%A", data=t, lang="en")
2336    assert "Dienstag" == r(code3, fmt="%A", data=t, lang="de")
2337    assert "Dienstag" == r(code3, fmt="%A", data=t, lang="de_DE")
2338    assert "Jan" == r(code2, fmt="%b", data=t)
2339    assert "Jan" == r(code3, fmt="%b", data=t, lang=None)
2340    assert "Jan" == r(code3, fmt="%b", data=t, lang="en")
2341    assert "Jan" == r(code3, fmt="%b", data=t, lang="de")
2342    assert "Jan" == r(code3, fmt="%b", data=t, lang="de_DE")
2343    assert "January" == r(code2, fmt="%B", data=t)
2344    assert "January" == r(code3, fmt="%B", data=t, lang=None)
2345    assert "January" == r(code3, fmt="%B", data=t, lang="en")
2346    assert "Januar" == r(code3, fmt="%B", data=t, lang="de")
2347    assert "Januar" == r(code3, fmt="%B", data=t, lang="de_DE")
2348    assert "01" == r(code2, fmt="%I", data=t)
2349    assert "025" == r(code2, fmt="%j", data=t)
2350    assert "PM" == r(code2, fmt="%p", data=t)
2351    assert "04" == r(code2, fmt="%U", data=t)
2352    assert "2" == r(code2, fmt="%w", data=t)
2353    assert "04" == r(code2, fmt="%W", data=t)
2354    assert "11" == r(code2, fmt="%y", data=t)
2355    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 ")
2356    assert "01/25/2011" == r(code2, fmt="%x", data=t)
2357    assert "01/25/2011" == r(code3, fmt="%x", data=t, lang=None)
2358    assert "01/25/2011" == r(code3, fmt="%x", data=t, lang="en")
2359    assert "25.01.2011" == r(code3, fmt="%x", data=t, lang="de")
2360    assert "25.01.2011" == r(code3, fmt="%x", data=t, lang="de_DE")
2361    assert r(code2, fmt="%X", data=t) in ("13:34:56", "01:34:56 PM")
2362    assert r(code3, fmt="%X", data=t, lang=None) in ("13:34:56", "01:34:56 PM")
2363    assert r(code3, fmt="%X", data=t, lang="en") in ("13:34:56", "01:34:56 PM")
2364    assert "13:34:56" == r(code3, fmt="%X", data=t, lang="de")
2365    assert "13:34:56" == r(code3, fmt="%X", data=t, lang="de_DE")
2366    assert "%" == r(code2, fmt="%%", data=t)
2367
2368
2369@pytest.mark.ul4
2370def test_function_format_int(r):
2371    code2 = "<?print format(data, fmt)?>"
2372    code3 = "<?print format(data, fmt, lang)?>"
2373
2374    formatstrings = [
2375        "",
2376        "",
2377        "5",
2378        "05",
2379        "05",
2380        "+05",
2381        "+8b",
2382        "+#10b",
2383        "o",
2384        "+#x",
2385        "+#X",
2386        "<5",
2387        ">5",
2388        "?>5",
2389        "^5",
2390        "?= 5",
2391        "?= #11b",
2392    ]
2393
2394    for f in formatstrings:
2395        assert format(42, f) == r(code2, data=42, fmt=f)
2396        if "c" not in f:
2397            assert format(-42, f) == r(code2, data=-42, fmt=f)
2398    assert format(True, "05") == r(code2, data=True, fmt="05")
2399
2400
2401@pytest.mark.ul4
2402def test_function_format_kwargs(r):
2403    assert "42" == r("<?print format(obj=data, fmt=fmt, lang=lang)?>", fmt="", data=42, lang="de")
2404
2405
2406@pytest.mark.ul4
2407def test_function_chr(r):
2408    code = "<?print chr(data)?>"
2409
2410    with raises(argumentmismatchmessage):
2411        r("<?print chr()?>")
2412    with raises(argumentmismatchmessage):
2413        r("<?print chr(1, 2)?>")
2414    assert "\x00" == r(code, data=0)
2415    assert "a" == r(code, data=ord("a"))
2416    assert "\u20ac" == r(code, data=0x20ac)
2417
2418    # Make sure that the parameters have the same name in all implementations
2419    assert "\x00" == r("<?print chr(i=data)?>", data=0)
2420
2421
2422@pytest.mark.ul4
2423def test_function_ord(r):
2424    code = "<?print ord(data)?>"
2425
2426    with raises(argumentmismatchmessage):
2427        r("<?print ord()?>")
2428    with raises(argumentmismatchmessage):
2429        r("<?print ord(1, 2)?>")
2430    assert "0" == r(code, data="\x00")
2431    assert str(ord("a")) == r(code, data="a")
2432    assert str(0x20ac) == r(code, data="\u20ac")
2433
2434    # Make sure that the parameters have the same name in all implementations
2435    assert "0" == r("<?print ord(c=data)?>", data="\x00")
2436
2437
2438@pytest.mark.ul4
2439def test_function_hex(r):
2440    code = "<?print hex(data)?>"
2441
2442    with raises(argumentmismatchmessage):
2443        r("<?print hex()?>")
2444    with raises(argumentmismatchmessage):
2445        r("<?print hex(1, 2)?>")
2446    assert "0x0" == r(code, data=0)
2447    assert "0xff" == r(code, data=0xff)
2448    assert "0xffff" == r(code, data=0xffff)
2449    assert "-0xffff" == r(code, data=-0xffff)
2450
2451    # Make sure that the parameters have the same name in all implementations
2452    assert "0x0" == r("<?print hex(number=data)?>", data=0)
2453
2454
2455@pytest.mark.ul4
2456def test_function_oct(r):
2457    code = "<?print oct(data)?>"
2458
2459    with raises(argumentmismatchmessage):
2460        r("<?print oct()?>")
2461    with raises(argumentmismatchmessage):
2462        r("<?print oct(1, 2)?>")
2463    assert "0o0" == r(code, data=0)
2464    assert "0o77" == r(code, data=0o77)
2465    assert "0o7777" == r(code, data=0o7777)
2466    assert "-0o7777" == r(code, data=-0o7777)
2467
2468    # Make sure that the parameters have the same name in all implementations
2469    assert "0o0" == r("<?print oct(number=data)?>", data=0)
2470
2471
2472@pytest.mark.ul4
2473def test_function_bin(r):
2474    code = "<?print bin(data)?>"
2475
2476    with raises(argumentmismatchmessage):
2477        r("<?print bin()?>")
2478    with raises(argumentmismatchmessage):
2479        r("<?print bin(1, 2)?>")
2480    assert "0b0" == r(code, data=0b0)
2481    assert "0b11" == r(code, data=0b11)
2482    assert "-0b1111" == r(code, data=-0b1111)
2483
2484
2485@pytest.mark.ul4
2486def test_function_bin_kwargs(r):
2487    assert "0b0" == r("<?print bin(number=data)?>", data=0)
2488
2489
2490@pytest.mark.ul4
2491def test_function_abs(r):
2492    code = "<?print abs(data)?>"
2493
2494    with raises(argumentmismatchmessage):
2495        r("<?print abs()?>")
2496    with raises(argumentmismatchmessage):
2497        r("<?print abs(1, 2)?>")
2498    assert "0" == r(code, data=0)
2499    assert "42" == r(code, data=42)
2500    assert "42" == r(code, data=-42)
2501    assert "1 month" == r(code, data=misc.monthdelta(-1))
2502    assert "1 day, 0:00:01.000001" == r(code, data=datetime.timedelta(-1, -1, -1))
2503
2504    # Make sure that the parameters have the same name in all implementations
2505    assert "0" == r("<?print abs(number=data)?>", data=0)
2506
2507
2508@pytest.mark.ul4
2509def test_function_sorted(r):
2510    code = "<?for i in sorted(data)?><?print i?><?end for?>"
2511
2512    with raises(argumentmismatchmessage):
2513        r("<?print sorted()?>")
2514    assert "gkru" == r(code, data="gurk")
2515    assert "24679" == r(code, data="92746")
2516    assert "172342" == r(code, data=(42, 17, 23))
2517    assert "012" == r(code, data={0: "zero", 1: "one", 2: "two"})
2518
2519    # Make sure that the parameters have the same name in all implementations
2520    assert "123" == r("<?for i in sorted(iterable=data)?><?print i?><?end for?>", data="321")
2521
2522
2523@pytest.mark.ul4
2524def test_function_range(r):
2525    code1 = "<?for i in range(data)?><?print i?>;<?end for?>"
2526    code2 = "<?for i in range(data[0], data[1])?><?print i?>;<?end for?>"
2527    code3 = "<?for i in range(data[0], data[1], data[2])?><?print i?>;<?end for?>"
2528
2529    with raises(argumentmismatchmessage):
2530        r("<?print range()?>")
2531    with raises(argumentmismatchmessage):
2532        r("<?print range(1, 2, 3, 4)?>")
2533    assert "" == r(code1, data=-10)
2534    assert "" == r(code1, data=0)
2535    assert "0;" == r(code1, data=1)
2536    assert "0;1;2;3;4;" == r(code1, data=5)
2537    assert "" == r(code2, data=[0, -10])
2538    assert "" == r(code2, data=[0, 0])
2539    assert "0;1;2;3;4;" == r(code2, data=[0, 5])
2540    assert "-5;-4;-3;-2;-1;0;1;2;3;4;" == r(code2, data=[-5, 5])
2541    assert "" == r(code3, data=[0, -10, 1])
2542    assert "" == r(code3, data=[0, 0, 1])
2543    assert "0;2;4;6;8;" == r(code3, data=[0, 10, 2])
2544    assert "" == r(code3, data=[0, 10, -2])
2545    assert "10;8;6;4;2;" == r(code3, data=[10, 0, -2])
2546    assert "" == r(code3, data=[10, 0, 2])
2547
2548
2549@pytest.mark.ul4
2550def test_function_urlquote(r):
2551    assert "gurk" == r("<?print urlquote('gurk')?>")
2552    assert "%3C%3D%3E%2B%3F" == r("<?print urlquote('<=>+?')?>")
2553    assert "%7F%C3%BF%EF%BF%BF" == r("<?print urlquote('\u007f\u00ff\uffff')?>")
2554
2555    # Make sure that the parameters have the same name in all implementations
2556    assert "gurk" == r("<?print urlquote(string='gurk')?>")
2557
2558
2559@pytest.mark.ul4
2560def test_function_urlunquote(r):
2561    assert "gurk" == r("<?print urlunquote('gurk')?>")
2562    assert "<=>+?" == r("<?print urlunquote('%3C%3D%3E%2B%3F')?>")
2563    assert "\u007f\u00ff\uffff" == r("<?print urlunquote('%7F%C3%BF%EF%BF%BF')?>")
2564
2565    # Make sure that the parameters have the same name in all implementations
2566    assert "gurk" == r("<?print urlunquote(string='gurk')?>")
2567
2568
2569@pytest.mark.ul4
2570def test_function_zip(r):
2571    code0 = "<?for i in zip()?><?print i?>;<?end for?>"
2572    code1 = "<?for (ix, ) in zip(x)?><?print ix?>;<?end for?>"
2573    code2 = "<?for (ix, iy) in zip(x, y)?><?print ix?>-<?print iy?>;<?end for?>"
2574    code3 = "<?for (ix, iy, iz) in zip(x, y, z)?><?print ix?>-<?print iy?>+<?print iz?>;<?end for?>"
2575
2576    assert "" == r(code0)
2577    assert "1;2;" == r(code1, x=[1, 2])
2578    assert "" == r(code2, x=[], y=[])
2579    assert "1-3;2-4;" == r(code2, x=[1, 2], y=[3, 4])
2580    assert "1-4;2-5;" == r(code2, x=[1, 2, 3], y=[4, 5])
2581    assert "" == r(code3, x=[], y=[], z=[])
2582    assert "1-3+5;2-4+6;" == r(code3, x=[1, 2], y=[3, 4], z=[5, 6])
2583    assert "1-4+6;" == r(code3, x=[1, 2, 3], y=[4, 5], z=[6])
2584
2585
2586@pytest.mark.ul4
2587def test_function_type(r):
2588    code = "<?print type(x)?>"
2589
2590    with raises(argumentmismatchmessage):
2591        r("<?print type()?>")
2592    with raises(argumentmismatchmessage):
2593        r("<?print type(1, 2)?>")
2594    assert "undefined" == r(code)
2595    assert "none" == r(code, x=None)
2596    assert "bool" == r(code, x=False)
2597    assert "bool" == r(code, x=True)
2598    assert "int" == r(code, x=42)
2599    assert "float" == r(code, x=4.2)
2600    assert "str" == r(code, x="foo")
2601    assert "date" == r(code, x=datetime.datetime.now())
2602    assert "date" == r(code, x=datetime.date.today())
2603    assert "timedelta" == r(code, x=datetime.timedelta())
2604    assert "monthdelta" == r(code, x=misc.monthdelta())
2605    assert "list" == r(code, x=(1, 2))
2606    assert "list" == r(code, x=[1, 2])
2607    assert "list" == r(code, x=PseudoList([1, 2]))
2608    assert "dict" == r(code, x={1: 2})
2609    assert "dict" == r(code, x=PseudoDict({1: 2}))
2610    assert "template" == r(code, x=ul4c.Template(""))
2611    assert "template" == r("<?def t?><?end def?><?print type(t)?>")
2612    assert "function" == r("<?print type(repr)?>")
2613    assert "color" == r(code, x=color.red)
2614
2615    # Make sure that the parameters have the same name in all implementations
2616    assert "none" == r("<?print type(obj=x)?>", x=None)
2617
2618
2619@pytest.mark.ul4
2620def test_function_reversed(r):
2621    code = "<?for i in reversed(x)?>(<?print i?>)<?end for?>"
2622
2623    with raises(argumentmismatchmessage):
2624        r("<?print reversed()?>")
2625    with raises(argumentmismatchmessage):
2626        r("<?print reversed(1, 2)?>")
2627    assert "(3)(2)(1)" == r(code, x="123")
2628    assert "(3)(2)(1)" == r(code, x=[1, 2, 3])
2629    assert "(3)(2)(1)" == r(code, x=(1, 2, 3))
2630
2631    # Make sure that the parameters have the same name in all implementations
2632    assert "(3)(2)(1)" == r("<?for i in reversed(sequence=x)?>(<?print i?>)<?end for?>", x=(1, 2, 3))
2633
2634
2635@pytest.mark.ul4
2636def test_function_min(r):
2637    with raises(argumentmismatchmessage):
2638        r("<?print min()?>")
2639    with raises("empty sequence"):
2640        r("<?print min([])?>")
2641    assert "1" == r("<?print min('123')?>")
2642    assert "1" == r("<?print min(1, 2, 3)?>")
2643    assert "0" == r("<?print min(0, False, 1, True)?>")
2644    assert "False" == r("<?print min(False, 0, True, 1)?>")
2645    assert "False" == r("<?print min([False, 0, True, 1])?>")
2646
2647
2648@pytest.mark.ul4
2649def test_function_max(r):
2650    with raises(argumentmismatchmessage):
2651        r("<?print max()?>")
2652    with raises("empty sequence"):
2653        r("<?print max([])?>")
2654    assert "3" == r("<?print max('123')?>")
2655    assert "3" == r("<?print max(1, 2, 3)?>")
2656    assert "1" == r("<?print max(0, False, 1, True)?>")
2657    assert "True" == r("<?print max(False, 0, True, 1)?>")
2658    assert "True" == r("<?print max([False, 0, True, 1])?>")
2659
2660
2661@pytest.mark.ul4
2662def test_function_rgb(r):
2663    assert "#369" == r("<?print repr(rgb(0.2, 0.4, 0.6))?>")
2664    assert "#369c" == r("<?print repr(rgb(0.2, 0.4, 0.6, 0.8))?>")
2665
2666    # Make sure that the parameters have the same name in all implementations
2667    assert "#369c" == r("<?print repr(rgb(r=0.2, g=0.4, b=0.6, a=0.8))?>")
2668
2669
2670@pytest.mark.ul4
2671def test_function_hls(r):
2672    assert "#fff" == r("<?print repr(hls(0, 1, 0))?>")
2673    assert "#fff0" == r("<?print repr(hls(0, 1, 0, 0))?>")
2674
2675    # Make sure that the parameters have the same name in all implementations
2676    assert "#fff0" == r("<?print repr(hls(h=0, l=1, s=0, a=0))?>")
2677
2678
2679@pytest.mark.ul4
2680def test_function_hsv(r):
2681    assert "#fff" == r("<?print repr(hsv(0, 0, 1))?>")
2682    assert "#fff0" == r("<?print repr(hsv(0, 0, 1, 0))?>")
2683
2684    # Make sure that the parameters have the same name in all implementations
2685    assert "#fff0" == r("<?print repr(hsv(h=0, s=0, v=1, a=0))?>")
2686
2687
2688@pytest.mark.ul4
2689def test_method_upper(r):
2690    assert "GURK" == r("<?print 'gurk'.upper()?>")
2691
2692
2693@pytest.mark.ul4
2694def test_method_lower(r):
2695    assert "gurk" == r("<?print 'GURK'.lower()?>")
2696
2697
2698@pytest.mark.ul4
2699def test_method_capitalize(r):
2700    assert "Gurk" == r("<?print 'gURK'.capitalize()?>")
2701
2702
2703@pytest.mark.ul4
2704def test_method_startswith(r):
2705    assert "True" == r("<?print 'gurkhurz'.startswith('gurk')?>")
2706    assert "False" == r("<?print 'gurkhurz'.startswith('hurz')?>")
2707
2708    # Make sure that the parameters have the same name in all implementations
2709    assert "True" == r("<?print 'gurkhurz'.startswith(prefix='gurk')?>")
2710
2711
2712@pytest.mark.ul4
2713def test_method_endswith(r):
2714    assert "True" == r("<?print 'gurkhurz'.endswith('hurz')?>")
2715    assert "False" == r("<?print 'gurkhurz'.endswith('gurk')?>")
2716
2717    # Make sure that the parameters have the same name in all implementations
2718    assert "True" == r("<?print 'gurkhurz'.endswith(suffix='hurz')?>")
2719
2720
2721@pytest.mark.ul4
2722def test_method_strip(r):
2723    assert "gurk" == r(r"<?print obj.strip()?>", obj=' \t\r\ngurk \t\r\n')
2724    assert "gurk" == r(r"<?print obj.strip('xyz')?>", obj='xyzzygurkxyzzy')
2725
2726    # Make sure that the parameters have the same name in all implementations
2727    assert "gurk" == r(r"<?print obj.strip(chars='xyz')?>", obj='xyzzygurkxyzzy')
2728
2729
2730@pytest.mark.ul4
2731def test_method_lstrip(r):
2732    assert "gurk \t\r\n" == r("<?print obj.lstrip()?>", obj=" \t\r\ngurk \t\r\n")
2733    assert "gurkxyzzy" == r("<?print obj.lstrip(arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
2734
2735    # Make sure that the parameters have the same name in all implementations
2736    assert "gurkxyzzy" == r("<?print obj.lstrip(chars=arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
2737
2738
2739@pytest.mark.ul4
2740def test_method_rstrip(r):
2741    assert " \t\r\ngurk" == r("<?print obj.rstrip()?>", obj=" \t\r\ngurk \t\r\n")
2742    assert "xyzzygurk" == r("<?print obj.rstrip(arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
2743
2744    # Make sure that the parameters have the same name in all implementations
2745    assert "xyzzygurk" == r("<?print obj.rstrip(chars=arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
2746
2747
2748@pytest.mark.ul4
2749def test_method_split(r):
2750    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")
2751    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")
2752    assert "()(f)(o)(o)()" == r("<?for item in obj.split(arg)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2753    assert "()(f)(oxxoxx)" == r("<?for item in obj.split(arg, 2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2754
2755    # Make sure that the parameters have the same name in all implementations
2756    assert "()(f)(oxxoxx)" == r("<?for item in obj.split(sep=arg, count=2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2757
2758
2759@pytest.mark.ul4
2760def test_method_rsplit(r):
2761    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")
2762    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")
2763    assert "()(f)(o)(o)()" == r("<?for item in obj.rsplit(arg)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2764    assert "(xxfxxo)(o)()" == r("<?for item in obj.rsplit(arg, 2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2765
2766    # Make sure that the parameters have the same name in all implementations
2767    assert "(xxfxxo)(o)()" == r("<?for item in obj.rsplit(sep=arg, count=2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
2768
2769
2770@pytest.mark.ul4
2771def test_method_replace(r):
2772    assert 'goork' == r("<?print 'gurk'.replace('u', 'oo')?>")
2773    assert 'fuuuu' == r("<?print 'foo'.replace('o', 'uu', None)?>")
2774    assert 'fuuo' == r("<?print 'foo'.replace('o', 'uu', 1)?>")
2775
2776    # Make sure that the parameters have the same name in all implementations
2777    assert 'fuuo' == r("<?print 'foo'.replace(old='o', new='uu', count=1)?>")
2778
2779
2780@pytest.mark.ul4
2781def test_method_renders(r):
2782    t = ul4c.Template('(<?print data?>)')
2783    assert '(GURK)' == r("<?print t.renders(data='gurk').upper()?>", t=t)
2784    assert '(GURK)' == r("<?print t.renders(**{'data': 'gurk'}).upper()?>", t=t)
2785
2786    t = ul4c.Template('(gurk)')
2787    assert '(GURK)' == r("<?print t.renders().upper()?>", t=t)
2788
2789
2790@pytest.mark.ul4
2791def test_method_mimeformat(r):
2792    t = datetime.datetime(2010, 2, 22, 12, 34, 56)
2793
2794    assert 'Mon, 22 Feb 2010 12:34:56 GMT' == r(r"<?print data.mimeformat()?>", data=t)
2795
2796
2797@pytest.mark.ul4
2798def test_method_items(r):
2799    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))
2800
2801
2802@pytest.mark.ul4
2803def test_method_values(r):
2804    assert "17;23;42;" == r("<?for value in sorted(data.values())?><?print value?>;<?end for?>", data=dict(a=42, b=17, c=23))
2805
2806
2807@pytest.mark.ul4
2808def test_method_get(r):
2809    assert "42" == r("<?print {}.get('foo', 42)?>")
2810    assert "17" == r("<?print {'foo': 17}.get('foo', 42)?>")
2811    assert "" == r("<?print {}.get('foo')?>")
2812    assert "17" == r("<?print {'foo': 17}.get('foo')?>")
2813
2814    # Make sure that the parameters have the same name in all implementations
2815    assert "17" == r("<?print {'foo': 17}.get(key='foo', default=42)?>")
2816
2817
2818@pytest.mark.ul4
2819def test_method_r_g_b_a(r):
2820    assert '0x11' == r('<?code c = #123?><?print hex(c.r())?>')
2821    assert '0x22' == r('<?code c = #123?><?print hex(c.g())?>')
2822    assert '0x33' == r('<?code c = #123?><?print hex(c.b())?>')
2823    assert '0xff' == r('<?code c = #123?><?print hex(c.a())?>')
2824
2825
2826@pytest.mark.ul4
2827def test_method_hls(r):
2828    assert '0' == r('<?code c = #fff?><?print int(c.hls()[0])?>')
2829    assert '1' == r('<?code c = #fff?><?print int(c.hls()[1])?>')
2830    assert '0' == r('<?code c = #fff?><?print int(c.hls()[2])?>')
2831
2832
2833@pytest.mark.ul4
2834def test_method_hlsa(r):
2835    assert '0' == r('<?code c = #fff?><?print int(c.hlsa()[0])?>')
2836    assert '1' == r('<?code c = #fff?><?print int(c.hlsa()[1])?>')
2837    assert '0' == r('<?code c = #fff?><?print int(c.hlsa()[2])?>')
2838    assert '1' == r('<?code c = #fff?><?print int(c.hlsa()[3])?>')
2839
2840
2841@pytest.mark.ul4
2842def test_method_hsv(r):
2843    assert '0' == r('<?code c = #fff?><?print int(c.hsv()[0])?>')
2844    assert '0' == r('<?code c = #fff?><?print int(c.hsv()[1])?>')
2845    assert '1' == r('<?code c = #fff?><?print int(c.hsv()[2])?>')
2846
2847
2848@pytest.mark.ul4
2849def test_method_hsva(r):
2850    assert '0' == r('<?code c = #fff?><?print int(c.hsva()[0])?>')
2851    assert '0' == r('<?code c = #fff?><?print int(c.hsva()[1])?>')
2852    assert '1' == r('<?code c = #fff?><?print int(c.hsva()[2])?>')
2853    assert '1' == r('<?code c = #fff?><?print int(c.hsva()[3])?>')
2854
2855
2856@pytest.mark.ul4
2857def test_method_lum(r):
2858    assert 'True' == r('<?print #fff.lum() == 1?>')
2859
2860
2861@pytest.mark.ul4
2862def test_method_withlum(r):
2863    assert '#fff' == r('<?print #000.withlum(1)?>')
2864
2865    # Make sure that the parameters have the same name in all implementations
2866    assert '#fff' == r('<?print #000.withlum(lum=1)?>')
2867
2868
2869@pytest.mark.ul4
2870def test_method_witha(r):
2871    assert '#0063a82a' == r('<?print repr(#0063a8.witha(42))?>')
2872
2873    # Make sure that the parameters have the same name in all implementations
2874    assert '#0063a82a' == r('<?print repr(#0063a8.witha(a=42))?>')
2875
2876
2877@pytest.mark.ul4
2878def test_method_join(r):
2879    assert '1,2,3,4' == r('<?print ",".join("1234")?>')
2880    assert '1,2,3,4' == r('<?print ",".join(["1", "2", "3", "4"])?>')
2881
2882    # Make sure that the parameters have the same name in all implementations
2883    assert '1,2,3,4' == r('<?print ",".join(iterable="1234")?>')
2884
2885
2886@pytest.mark.ul4
2887def test_method_find(r):
2888    s = "gurkgurk"
2889    assert '-1' == r('<?print s.find("ks")?>', s=s)
2890    assert '2' == r('<?print s.find("rk")?>', s=s)
2891    assert '2' == r('<?print s.find("rk", 2)?>', s=s)
2892    assert '6' == r('<?print s.find("rk", -3)?>', s=s)
2893    assert '2' == r('<?print s.find("rk", 2, 4)?>', s=s)
2894    assert '6' == r('<?print s.find("rk", 4, 8)?>', s=s)
2895    assert '5' == r('<?print s.find("ur", -4, -1)?>', s=s)
2896    assert '-1' == r('<?print s.find("rk", 2, 3)?>', s=s)
2897    assert '-1' == r('<?print s.find("rk", 7)?>', s=s)
2898    l = list("gurkgurk")
2899    assert '-1' == r('<?print l.find("x")?>', l=l)
2900    assert '2' == r('<?print l.find("r")?>', l=l)
2901    assert '2' == r('<?print l.find("r", 2)?>', l=l)
2902    assert '6' == r('<?print l.find("r", -3)?>', l=l)
2903    assert '2' == r('<?print l.find("r", 2, 4)?>', l=l)
2904    assert '6' == r('<?print l.find("r", 4, 8)?>', l=l)
2905    assert '6' == r('<?print l.find("r", -3, -1)?>', l=l)
2906    assert '-1' == r('<?print l.find("r", 2, 2)?>', l=l)
2907    assert '-1' == r('<?print l.find("r", 7)?>', l=l)
2908    assert '1' == r('<?print l.find(None)?>', l=[0, None, 1, None, 2, None, 3, None])
2909
2910    # Make sure that the parameters have the same name in all implementations
2911    assert '2' == r('<?print s.find(sub="rk", start=2, end=4)?>', s=s)
2912
2913
2914@pytest.mark.ul4
2915def test_method_rfind(r):
2916    s = "gurkgurk"
2917    assert '-1' == r('<?print s.rfind("ks")?>', s=s)
2918    assert '6' == r('<?print s.rfind("rk")?>', s=s)
2919    assert '6' == r('<?print s.rfind("rk", 2)?>', s=s)
2920    assert '6' == r('<?print s.rfind("rk", -3)?>', s=s)
2921    assert '2' == r('<?print s.rfind("rk", 2, 4)?>', s=s)
2922    assert '6' == r('<?print s.rfind("rk", 4, 8)?>', s=s)
2923    assert '5' == r('<?print s.rfind("ur", -4, -1)?>', s=s)
2924    assert '-1' == r('<?print s.rfind("rk", 2, 3)?>', s=s)
2925    assert '-1' == r('<?print s.rfind("rk", 7)?>', s=s)
2926    l = list("gurkgurk")
2927    assert '-1' == r('<?print l.rfind("x")?>', l=l)
2928    assert '6' == r('<?print l.rfind("r")?>', l=l)
2929    assert '6' == r('<?print l.rfind("r", 2)?>', l=l)
2930    assert '2' == r('<?print l.rfind("r", 2, 4)?>', l=l)
2931    assert '6' == r('<?print l.rfind("r", 4, 8)?>', l=l)
2932    assert '6' == r('<?print l.rfind("r", -3, -1)?>', l=l)
2933    assert '-1' == r('<?print l.rfind("r", 2, 2)?>', l=l)
2934    assert '-1' == r('<?print l.rfind("r", 7)?>', l=l)
2935    assert '7' == r('<?print l.rfind(None)?>', l=[0, None, 1, None, 2, None, 3, None])
2936
2937    # Make sure that the parameters have the same name in all implementations
2938    assert '2' == r('<?print s.rfind(sub="rk", start=2, end=4)?>', s=s)
2939
2940
2941@pytest.mark.ul4
2942def test_method_day(r):
2943    assert '12' == r('<?print @(2010-05-12).day()?>')
2944    assert '12' == r('<?print d.day()?>', d=datetime.date(2010, 5, 12))
2945
2946
2947@pytest.mark.ul4
2948def test_method_month(r):
2949    assert '5' == r('<?print @(2010-05-12).month()?>')
2950    assert '5' == r('<?print d.month()?>', d=datetime.date(2010, 5, 12))
2951
2952
2953@pytest.mark.ul4
2954def test_method_year(r):
2955    assert '5' == r('<?print @(2010-05-12).month()?>')
2956    assert '5' == r('<?print d.month()?>', d=datetime.date(2010, 5, 12))
2957
2958
2959@pytest.mark.ul4
2960def test_method_hour(r):
2961    assert '16' == r('<?print @(2010-05-12T16:47:56).hour()?>')
2962    assert '16' == r('<?print d.hour()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
2963
2964
2965@pytest.mark.ul4
2966def test_method_minute(r):
2967    assert '47' == r('<?print @(2010-05-12T16:47:56).minute()?>')
2968    assert '47' == r('<?print d.minute()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
2969
2970
2971@pytest.mark.ul4
2972def test_method_second(r):
2973    assert '56' == r('<?print @(2010-05-12T16:47:56).second()?>')
2974    assert '56' == r('<?print d.second()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
2975
2976
2977@pytest.mark.ul4
2978def test_method_microsecond(r):
2979    if r is not render_php:
2980        assert '123000' == r('<?print @(2010-05-12T16:47:56.123000).microsecond()?>')
2981        assert '123000' == r('<?print d.microsecond()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56, 123000))
2982
2983
2984@pytest.mark.ul4
2985def test_method_weekday(r):
2986    assert '2' == r('<?print @(2010-05-12).weekday()?>')
2987    assert '2' == r('<?print d.weekday()?>', d=datetime.date(2010, 5, 12))
2988
2989
2990@pytest.mark.ul4
2991def test_method_week(r):
2992    assert '0' == r('<?print @(2012-01-01).week()?>')
2993    assert '0' == r('<?print @(2012-01-01).week(0)?>')
2994    assert '1' == r('<?print @(2012-01-01).week(6)?>')
2995    assert '1' == r('<?print @(2012-01-02).week()?>')
2996    assert '1' == r('<?print @(2012-01-02).week(0)?>')
2997    assert '1' == r('<?print @(2012-01-02).week(6)?>')
2998
2999    # Make sure that the parameters have the same name in all implementations
3000    assert '1' == r('<?print @(2012-01-02).week(firstweekday=0)?>')
3001
3002
3003@pytest.mark.ul4
3004def test_method_yearday(r):
3005    assert '1' == r('<?print @(2010-01-01).yearday()?>')
3006    assert '366' == r('<?print @(2008-12-31).yearday()?>')
3007    assert '365' == r('<?print @(2010-12-31).yearday()?>')
3008    assert '132' == r('<?print @(2010-05-12).yearday()?>')
3009    assert '132' == r('<?print @(2010-05-12T16:47:56).yearday()?>')
3010    assert '132' == r('<?print d.yearday()?>', d=datetime.date(2010, 5, 12))
3011    assert '132' == r('<?print d.yearday()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
3012
3013
3014@pytest.mark.ul4
3015def test_render(r):
3016    t = ul4c.Template('<?print prefix?><?print data?><?print suffix?>')
3017
3018    assert '(f)(o)(o)' == r('<?for c in data?><?render t.render(data=c, prefix="(", suffix=")")?><?end for?>', t=t, data='foo')
3019    assert '(f)(o)(o)' == r('<?for c in data?><?render t.render(data=c, **{"prefix": "(", "suffix": ")"})?><?end for?>', t=t, data='foo')
3020
3021
3022@pytest.mark.ul4
3023def test_def(r):
3024    assert 'foo' == r('<?def lower?><?print x.lower()?><?end def?><?print lower.renders(x="FOO")?>')
3025
3026
3027@pytest.mark.ul4
3028def test_pass_function(r):
3029    assert "&lt;" == r("<?def x?><?print xe('<')?><?end def?><?render x.render(xe=xmlescape)?>")
3030    assert "&lt;" == r("<?def xe?><?return xmlescape(s)?><?end def?><?def x?><?print xe(s='<')?><?end def?><?render x.render(xe=xe)?>")
3031    assert "&lt;" == r("<?def xe?><?return xmlescape(s)?><?end def?><?def x?><?print xe(s='<')?><?end def?><?render x.render()?>")
3032
3033
3034@pytest.mark.ul4
3035def test_parse(r):
3036    assert '42' == r('<?print data.Noner?>', data=dict(Noner=42))
3037
3038
3039@pytest.mark.ul4
3040def test_nested_exceptions(r):
3041    tmpl1 = ul4c.Template("<?print 2*x?>", "tmpl1")
3042    tmpl2 = ul4c.Template("<?render tmpl1.render(x=x)?>", "tmpl2")
3043    tmpl3 = ul4c.Template("<?render tmpl2.render(tmpl1=tmpl1, x=x)?>", "tmpl3")
3044
3045    with raises("unsupported operand type|not supported"):
3046        r("<?render tmpl3.render(tmpl1=tmpl1, tmpl2=tmpl2, x=x)?>", tmpl1=tmpl1, tmpl2=tmpl2, tmpl3=tmpl3, x=None)
3047
3048
3049@pytest.mark.ul4
3050def test_note(r):
3051    assert "foo" == r("f<?note This is?>o<?note a comment?>o")
3052
3053
3054@pytest.mark.ul4
3055def test_templateattributes(r):
3056    s1 = "<?print x?>"
3057    t1 = ul4c.Template(s1)
3058
3059    s2 = "<?printx 42?>"
3060    t2 = ul4c.Template(s2)
3061
3062    assert "<?" == r("<?print template.startdelim?>", template=t1)
3063    assert "?>" == r("<?print template.enddelim?>", template=t1)
3064    assert s1 == r("<?print template.source?>", template=t1)
3065    assert "1" == r("<?print len(template.content)?>", template=t1)
3066    assert "print" == r("<?print template.content[0].type?>", template=t1)
3067    assert s1 == r("<?print template.content[0].location.tag?>", template=t1)
3068    assert "x" == r("<?print template.content[0].location.code?>", template=t1)
3069    assert "var" == r("<?print template.content[0].obj.type?>", template=t1)
3070    assert "x" == r("<?print template.content[0].obj.name?>", template=t1)
3071    assert "printx" == r("<?print template.content[0].type?>", template=t2)
3072    assert "const" == r("<?print template.content[0].obj.type?>", template=t2)
3073    assert "42" == r("<?print template.content[0].obj.value?>", template=t2)
3074
3075
3076@pytest.mark.ul4
3077def test_templateattributes_localtemplate(r):
3078    # This checks that template attributes work on a closure
3079    source = "<?def lower?><?print t.lower()?><?end def?>"
3080
3081    assert source + "<?print lower.source?>" == r(source + "<?print lower.source?>")
3082    assert source == r(source + "<?print lower.source[lower.location.starttag:lower.endlocation.endtag]?>")
3083    assert "<?print t.lower()?>" == r(source + "<?print lower.source[lower.location.endtag:lower.endlocation.starttag]?>")
3084    assert "lower" == r(source + "<?print lower.name?>")
3085
3086
3087@pytest.mark.ul4
3088def test_nestedscopes(r):
3089    # Subtemplates can see the local variables from their parents
3090    source = """
3091    <?for i in range(3)?>
3092        <?def x?>
3093            <?print i?>!
3094        <?end def?>
3095        <?render x.render()?>
3096    <?end for?>
3097    """
3098    assert "0!1!2!" == r(source, keepws=False)
3099
3100    # Subtemplates see the state of the variable at the point of the ``<?def?>`` tag,
3101    # so the following code will use ``i = 1`` instead of ``i = 2`` even if the subtemplate is called after the variable has been changed.
3102    source = """
3103    <?code i = 1?>
3104    <?def x?>
3105        <?print i?>
3106    <?end def?>
3107    <?code i = 2?>
3108    <?render x.render()?>
3109    """
3110    assert "1" == r(source, keepws=False)
3111
3112
3113    # This shows the difference between local variables and variables from the parent.
3114    # ``x`` is passed to the subtemplate, so it will always the the current value instead of the one when it is defined
3115    # (Furthermore ``y += 1`` will load the variable from the parent but store it as a local variable)
3116    source = """
3117    <?def outer?>
3118        <?def inner?>
3119            <?code x += 1?>
3120            <?code y += 1?>
3121            <?print x?>!
3122            <?print y?>!
3123        <?end def?>
3124        <?code x += 1?>
3125        <?code y += 1?>
3126        <?render inner.render(x=x)?>
3127        <?print x?>!
3128        <?print y?>!
3129    <?end def?>
3130    <?code x += 1?>
3131    <?code y += 1?>
3132    <?render outer.render(x=x)?>
3133    <?print x?>!
3134    <?print y?>!
3135    """
3136
3137    assert "45!43!44!43!43!43!" == r(source, keepws=False, x=42, y=42)
3138
3139
3140def universaltemplate(keepws=True):
3141    return ul4c.Template("""
3142        text
3143        <?code x = 'gurk'?>
3144        <?code x = 42?>
3145        <?code x = 4.2?>
3146        <?code x = Undefined?>
3147        <?code x = ReallyUndefined?>
3148        <?code x = None?>
3149        <?code x = False?>
3150        <?code x = True?>
3151        <?code x = @(2009-01-04)?>
3152        <?code x = #0063a8?>
3153        <?code x = [42]?>
3154        <?code x = {"fortytwo": 42}?>
3155        <?code x = {**{"fortytwo": 42}}?>
3156        <?code x = [x for x in range(10) if i % 2]?>
3157        <?code x = {x : x*x for x in range(10) if i % 2}?>
3158        <?code x = (x for x in range(10) if i % 2)?>
3159        <?code x = y?>
3160        <?code x += 42?>
3161        <?code x -= 42?>
3162        <?code x *= 42?>
3163        <?code x /= 42?>
3164        <?code x //= 42?>
3165        <?code x %= 42?>
3166        <?print x.gurk?>
3167        <?print x["gurk"]?>
3168        <?print x[1:2]?>
3169        <?print x[1:]?>
3170        <?print x[:2]?>
3171        <?print x[:]?>
3172        <?printx x?>
3173        <?for x in "12"?><?print x?><?break?><?continue?><?end for?>
3174        <?print not x?>
3175        <?print -x?>
3176        <?print x in y?>
3177        <?print x not in y?>
3178        <?print x==y?>
3179        <?print x!=y?>
3180        <?print x<y?>
3181        <?print x<=y?>
3182        <?print x>y?>
3183        <?print x>=y?>
3184        <?print x+y?>
3185        <?print x*y?>
3186        <?print x/y?>
3187        <?print x//y?>
3188        <?print x and y?>
3189        <?print x or y?>
3190        <?print x % y?>
3191        <?print now()?>
3192        <?print repr(1)?>
3193        <?print range(1, 2)?>
3194        <?print range(1, 2, 3)?>
3195        <?print rgb(1, 2, 3, 4)?>
3196        <?print repr(1, 2, x=17, y=23, *args, **kwargs)?>
3197        <?print x.r()?>
3198        <?print x.find(1)?>
3199        <?print x.find(1, 2)?>
3200        <?print x.find(1, 2, 3)?>
3201        <?print x.find(1, 2, x=17, y=23, *args, **kwargs)?>
3202        <?if x?>gurk<?elif y?>hurz<?else?>hinz<?end if?>
3203        <?render x.render(a=1, b=2)?>
3204        <?def x?>foo<?end def?>
3205        <?def x?><?return x?><?end def?>
3206        <?render x.render()?>
3207    """)
3208
3209
3210@pytest.mark.ul4
3211def test_strtemplate():
3212    t1 = universaltemplate(True)
3213    str(t1)
3214
3215    t2 = universaltemplate(False)
3216    str(t2)
3217
3218
3219@pytest.mark.ul4
3220def test_keepws():
3221    s = """
3222        <?for i in range(10)?>
3223            <?print i?>
3224            ;
3225        <?end for?>
3226    """
3227    t = ul4c.Template(s, keepws=True)
3228    output1 = t.renders()
3229    t.keepws = False
3230    output2 = t.renders()
3231    assert output1 != output2
3232    assert "".join(output1.split()) == output2
3233
3234
3235@pytest.mark.ul4
3236def test_keepws_nested(r):
3237    s1 = "<?def nested1?>1n\n<?render second.render()?><?end def?>1\n<?render nested1.render(second=second)?>"
3238    s2 = "<?def nested2?>2n\n<?end def?>2\n<?render nested2.render()?>"
3239
3240    assert "1\n1n\n22n" == r(s1, keepws=True, second=ul4c.Template(s2, keepws=False))
3241    assert "11n2\n2n\n" == r(s1, keepws=False, second=ul4c.Template(s2, keepws=True))
3242
3243
3244@pytest.mark.ul4
3245def test_function(c):
3246    assert 42 == c("<?return 42?>")
3247
3248
3249@pytest.mark.ul4
3250def test_function_value(c):
3251    assert 84 == c("<?return 2*x?>", x=42)
3252
3253
3254@pytest.mark.ul4
3255def test_function_multiple_returnvalues(c):
3256    assert 84 == c("<?return 2*x?><?return 3*x?>", x=42)
3257
3258
3259@pytest.mark.ul4
3260def test_function_name(c):
3261    assert "f" == c("<?def f?><?return f.name?><?end def?><?return f(f=f)?>")
3262
3263
3264@pytest.mark.ul4
3265def test_function_closure(c):
3266    assert 24 == c("<?code y=3?><?def inner?><?return 2*x*y?><?end def?><?return inner(x=4)?>")
3267    assert 24 == c("<?def outer?><?code y=3?><?def inner?><?return 2*x*y?><?end def?><?return inner?><?end def?><?return outer()(x=4)?>")
3268
3269
3270@pytest.mark.ul4
3271def test_jssource():
3272    t = universaltemplate()
3273    t.jssource()
3274
3275
3276@pytest.mark.ul4
3277def test_javasource():
3278    t = universaltemplate()
3279    t.javasource()
3280
3281
3282@pytest.mark.ul4
3283def test_attr_if(r):
3284    cond = ul4.attr_if(html.a("gu'\"rk"), cond="cond")
3285
3286    s = html.div(class_=cond).conv().string()
3287    assert '<div></div>' == r(s, cond=False)
3288    assert '''<div class="gu'&quot;rk"></div>''' == r(s, cond=True)
3289
3290    s = html.div(class_=(cond, "hurz")).conv().string()
3291    assert '<div class="hurz"></div>' == r(s, cond=False)
3292    assert '''<div class="gu'&quot;rkhurz"></div>''' == r(s, cond=True)
3293
3294    s = cond.conv().string()
3295    assert '' == r(s, cond=False)
3296    assert '''<a>gu'"rk</a>''' == r(s, cond=True)
3297
3298    s = html.ul(compact=ul4.attr_if(True, cond="cond")).conv().string()
3299    assert '<ul></ul>' == r(s, cond=False)
3300    assert '''<ul compact="compact"></ul>''' == r(s, cond=True)
Note: See TracBrowser for help on using the browser.