root/livinglogic.python.xist/test/test_ul4.py @ 5321:fbc274119efb

Revision 5321:fbc274119efb, 119.7 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Add UL4 methods days(), seconds(), microseconds() and months() for timedelta/monthdelta objects.

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