root/livinglogic.python.xist/test/test_ul4.py @ 5363:b1fc48086f15

Revision 5363:b1fc48086f15, 119.1 KB (checked in by Walter Doerwald <walter@…>, 7 years ago)

Fix test for the printx function.

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