def test_all(self): assert evalpy('all([1, 2, 3])') == 'true' assert evalpy('all([0, 2, 3])') == 'false' assert evalpy('all([])') == 'true' assert evalpy('all([3, [], 3])') == 'false' assert evalpy('all([3, [1], 3])') == 'true'
def test_getattr(self): code = 'a = {"foo":1, "bar":2};\n' assert evalpy(code + 'getattr(a, "foo")') == '1' assert evalpy(code + 'getattr(a, "bar")') == '2' exc_att = 'except AttributeError: print("err")' assert evalpy(code + 'try:\n getattr(a, "fooo")\n' + exc_att) == 'err' assert evalpy(code + 'getattr(a, "fooo", 3)') == '3'
def test_zip(self): assert evalpy('for i, x in zip([1, 2, 3], [10, 20, 30]): print(i*x)' ) == '10\n40\n90' res = '111\n222\n333' assert evalpy( 'for a, b, c in zip([1, 2, 3], [10, 20, 30], [100, 200, 300]): print(a+b+c)' ) == res
def test_assignments(self): assert py2js('foo = 3') == 'var foo;\nfoo = 3;' # with var assert py2js('foo.bar = 3') == 'foo.bar = 3;' # without var assert py2js('foo[i] = 3') == 'foo[i] = 3;' # without var code = py2js('foo = 3; bar = 4') # define both assert code.count('var') == 1 code = py2js('foo = 3; foo = 4') # only define first time assert code.count('var') == 1 code = py2js('foo = bar = 3') # multiple assignment assert 'foo = bar = 3' in code assert 'var bar, foo' in code # alphabetic order # self -> this assert py2js('self') == 'this;' assert py2js('self.foo') == 'this.foo;' # Indexing assert evalpy('a=[0,0]\na[0]=2\na[1]=3\na', False) == '[2,3]' # Tuple unpacking evalpy('x=[1,2,3]\na, b, c = x\nb', False) == '2' evalpy('a,b,c = [1,2,3]\nc,b,a = a,b,c\n[a,b,c]', False) == '[3,2,1]' # For unpacking, test that variables are declared, but not when attr or index assert py2js('xx, yy = 3, 4').count('xx') == 2 assert py2js('xx[0], yy[0] = 3, 4').count('xx') == 1 assert py2js('xx.a, yy.a = 3, 4').count('xx') == 1 # Class variables don't get a var code = py2js('class Foo:\n bar=3\n bar = bar + 1') assert code.count('bar') == 3 assert code.count('Foo.prototype.bar') == 3
def test_index(self): # We know that the implementation is basded on find; no need to test all assert evalpy('"abcdefgh".index("a")') == '0' assert evalpy('"abcdefgh".index("h")') == '7' assert evalpy('"abcdefgh".index("")') == '0' assert 'ValueError' in evalpy( 'try:\n "abcdefgh".index("z")\nexcept Exception as e:\n e')
def test_function_call_varargs(self): code = "def foo(x, *xx): return x + sum(xx)\nd = {'foo':foo}\nfive=[2, 3]\n" assert evalpy(code + 'foo(1, 2, 3)') == '6' assert evalpy(code + 'd.foo(1, 2, 3)') == '6' # assert evalpy(code + 'foo(1, *five)') == '6' assert evalpy(code + 'd.foo(1, *five)') == '6'
def test_pop(self): code = 'a=[1,2,3,4,5];\n' assert evalpy(code + 'a.pop(2); a') == '[ 1, 2, 4, 5 ]' assert evalpy(code + 'a.pop(0); a') == '[ 2, 3, 4, 5 ]' assert evalpy(code + 'a.pop(); a') == '[ 1, 2, 3, 4 ]' assert evalpy(code + 'a.pop(-1); a') == '[ 1, 2, 3, 4 ]' assert 'IndexError' in evalpy( code + 'try:\n a.pop(9);\nexcept Exception as e:\n e')
def test_import(self): with raises(JSError): py2js('import time') # But we do support special time funcs import time assert abs(float(evalpy('time()')) - time.time()) < 0.5 evalpy('t0=perf_counter(); t1=perf_counter(); (t1-t0)').startswith('0.0')
def test_raw_js_overloading(self): # more RawJS tests in test_parser3.py s1 = 'a=3; b=4; c=1; a + b - c' s2 = 'a=3; b=4; c=1; RawJS("a + b") - c' assert evalpy(s1) == '6' assert evalpy(s2) == '6' assert 'pyfunc' in py2js(s1) assert 'pyfunc' not in py2js(s2)
def test_string_formatting4(self): x = 'a = 3; b = 4; ' # Setting positions in format string assert evalpy(x + "'hi {1:g} {1:+g} {0}'.format(a, b)") == 'hi 4 +4 3' # Using a predefined template string for .format() assert evalpy(x + "t = 'hi {} {}'; t.format(a, b)") == 'hi 3 4'
def test_assert(self): assert 'throw' in py2js('assert True') evalpy('assert true; 7') == '7' evalpy('assert true, "msg"; 7') == '7' catcher = 'try { %s } catch(err) { console.log(err); }' assert evaljs(catcher % py2js('assert false')).count('AssertionError') assert evaljs(catcher % py2js('assert false, "foo"')).count('foo')
def test_indexing_and_slicing(self): c = 'a = [1, 2, 3, 4, 5]\n' # Indexing assert evalpy(c + 'a[2]') == '3' assert evalpy(c + 'a[-2]') == '4' # Slicing assert evalpy(c + 'a[:]') == '[ 1, 2, 3, 4, 5 ]' assert evalpy(c + 'a[1:-1]') == '[ 2, 3, 4 ]'
def test_filter(self): assert list(filter(lambda x: x > 0, [-1, -2, 1, 2])) == [1, 2] code = 'f1 = lambda x: x>0\n' assert evalpy( code + 'for x in filter(f1, [-1, -2, 0, 1, 2]): print(x)') == '1\n2' assert evalpy(code + 'for x in filter(None, [-1, -2, 0, 1, 2]): print(x)' ) == '-1\n-2\n1\n2'
def test_remove(self): code = 'a=[1,2,3,4,3,5];\n' assert evalpy(code + 'a.remove(2); a') == '[ 1, 3, 4, 3, 5 ]' assert evalpy(code + 'a.remove(3); a') == '[ 1, 2, 4, 3, 5 ]' assert 'ValueError' in evalpy( code + 'try:\n a.remove(9);\nexcept Exception as e:\n e') assert nowhitespace( evalpy('x = {"a":[2, 3]}; x.a.remove(2); x.a')) == '[3]' assert evalpy('a=[1,(2,3),4]; a.remove((2,3)); a') == '[ 1, 4 ]'
def test_ops(self): # Test code assert py2js('2+3') == '2 + 3;' # Binary assert py2js('2/3') == '2 / 3;' assert py2js('not 2') == '!2;' # Unary assert py2js('-(2+3)') == '-(2 + 3);' assert py2js('True and False') == 'true && false;' # Boolean # No parentices around names, numbers and strings assert py2js('foo - bar') == "foo - bar;" assert py2js('_foo3 - _bar4') == "_foo3 - _bar4;" assert py2js('3 - 4') == "3 - 4;" assert py2js('"abc" - "def"') == '"abc" - "def";' assert py2js("'abc' - 'def'") == '"abc" - "def";' assert py2js("'\"abc\" - \"def\"'") == '"\\"abc\\" - \\"def\\"";' # But they should be if it gets more complex assert py2js('foo - bar > 4') == "(foo - bar) > 4;" # Test outcome assert evalpy('2+3') == '5' # Binary assert evalpy('6/3') == '2' assert evalpy('4//3') == '1' assert evalpy('2**8') == '256' assert evalpy('not True') == 'false' # Unary assert evalpy('- 3') == '-3' assert evalpy('True and False') == 'false' # Boolean assert evalpy('True or False') == 'true' # Bug assert evalpy('(9-3-3)/3') == '1'
def test_recursion(self=None): code = 'def f(i): i *= 2; return i if i > 10 else f(i)\n\n' assert evalpy(code + 'f(1)') == '16' clscode = 'class G:\n def __init__(self): self.i = 1\n\n' code = clscode + ' def f(self): self.i *= 2; return self.i if self.i > 10 else self.f()\n\n' assert evalpy(code + 'g = G(); g.f()') == '16' code = clscode + ' def f(self):\n def h(): self.i *= 2; return self.i if self.i > 10 else h()\n\n' assert evalpy(code + ' return h()\n\ng = G(); g.f()') == '16'
def test_count(self): assert evalpy('"foo".count("o")') == '2' assert evalpy('"foo".count("f")') == '1' assert evalpy('"foo".count("x")') == '0' assert evalpy('"foo".count("")') == '3' assert evalpy('"a--a--a".count("a")') == '3' assert evalpy('"a--a--a".count("a", 0)') == '3' assert evalpy('"a--a--a".count("a", 0, 99)') == '3' assert evalpy('"a--a--a".count("a", 1)') == '2' assert evalpy('"a--a--a".count("a", 0, 4)') == '2' assert evalpy('"a--a--a".count("a", 1, 4)') == '1'
def test_funcion_call(self): jscode = 'var foo = function (x, y) {return x+y;};' assert evaljs(jscode + py2js('foo(2,2)')) == '4' assert evaljs(jscode + py2js('foo("so ", True)')) == 'so true' assert evaljs(jscode + py2js('a=[1,2]; foo(*a)')) == '3' assert evaljs(jscode + py2js('a=[1,2]; foo(7, *a)')) == '8' # Test super (is tested for real in test_parser3.py assert evalpy('d={"_base_class": console};d._base_class.log(4)') == '4' assert evalpy('d={"_base_class": console};d._base_class.log()') == '' jscode = 'var foo = function () {return this.val};' jscode += 'var d = {"foo": foo, "val": 7};\n' assert evaljs(jscode + py2js('d["foo"]()')) == '7' assert evaljs(jscode + py2js('d["foo"](*[3, 4])')) == '7'
def test_while(self): # Test code output line = nowhitespace(py2js('while(True): pass')) assert line == 'while(true){}' line = nowhitespace(py2js('while(not ok): pass')) assert 'while' in line # Test break and continue for9 = 'i=-1\nwhile(i<8):\n i+=1\n ' assert evalpy(for9 + 'if i==4:break\n print(i)\n0') == '0\n1\n2\n3\n0' assert evalpy(for9 + 'if i<6:continue\n print(i)\n0') == '6\n7\n8\n0' # Test else assert evalpy(for9 + 'if i==3:break\nelse: print(99)\n0') == '0' assert evalpy(for9 + 'if i==30:break\nelse: print(99)\n0') == '99\n0'
def test_rfind(self): assert evalpy('"abcdefgh".rfind("a")') == '0' assert evalpy('"abcdefgh".rfind("h")') == '7' assert evalpy('"abcdefgh".rfind("z")') == '-1' assert evalpy('"abcdefgh".rfind("")') == '8' assert evalpy('"abcdefgh".rfind("cd")') == '2' assert evalpy('"abcdefgh".rfind("def")') == '3' assert evalpy('"ab ab ab".rfind("ab", 0, -2)') == '3' assert evalpy('"ab ab ab".rfind("ab", 0, 3)') == '0' assert evalpy('"ab ".rfind("ab", 3)') == '-1'
def test_isidentifier(self): assert evalpy('"".isidentifier()') == 'false' assert evalpy('"012".isidentifier()') == 'false' assert evalpy('"abc".isidentifier()') == 'true' assert evalpy('"0a1b2c".isidentifier()') == 'false' assert evalpy('"a0a1b2c".isidentifier()') == 'true' assert evalpy('"0a_".isidentifier()') == 'false' assert evalpy('"_a".isidentifier()') == 'true' assert evalpy('"_0".isidentifier()') == 'true'
def xx_test_list_comprehension_speed(self): # https://developers.google.com/speed/articles/optimizing-javascript # ~ 0.029 when comprehension transpile to closures # ~ 0.023 when comprehensions transpile to inner function s, plus smaller chance on closures # ~ 0.017 when comprehensions transpile to inner function s, plus no chance on closures code = 't0 = perf_counter()\nfor i in range(100000): a = [j for j in range(10)]\n\nperf_counter()-t0' t1 = evalpy(code) print(t1)
def test_replace(self): assert evalpy("'abcABC'.replace('a', 'x')") == "xbcABC" assert evalpy("'abcABC'.replace('C', 'x')") == "abcABx" assert evalpy("'abcABC'.replace('cA', 'x')") == "abxBC" assert evalpy("'abababab'.replace('a', 'x', 0)") == "abababab" assert evalpy("'abababab'.replace('a', 'x', 1)") == "xbababab" assert evalpy("'abababab'.replace('a', 'x', 3)") == "xbxbxbab" assert evalpy("'abababab'.replace('a', 'x', 99)") == "xbxbxbxb" assert evalpy("'abababab'.replace('b', 'x', 2)") == "axaxabab"
def test_istitle(self): assert evalpy('"".istitle()') == 'false' assert evalpy('" ".istitle()') == 'false' assert evalpy('"AbC".istitle()') == 'false' assert evalpy('"Foo bar".istitle()') == 'false' assert evalpy('"AbC 01_".istitle()') == 'false' assert evalpy('"Foo".istitle()') == 'true' assert evalpy('"Foo Bar".istitle()') == 'true' assert evalpy('"Foo 01_".istitle()') == 'true'
def test_bool(self): assert evalpy('bool(5)') == 'true' assert evalpy('bool("xx")') == 'true' assert evalpy('bool(0)') == 'false' assert evalpy('bool("")') == 'false' # assert evalpy('bool([1])') == 'true' assert evalpy('bool({1:2})') == 'true' assert evalpy('bool([])') == 'false' assert evalpy('bool({})') == 'false'
def test_index(self): assert evalpy('[1,2,3,4,5,3].index(2)') == '1' assert evalpy('[1,2,3,4,5,3].index(3)') == '2' assert 'ValueError' in evalpy( 'try:\n [1,2,3,4,5,3].index(9);\nexcept Exception as e:\n e') assert evalpy('[1,2,3,4,5,3].index(3, 4)') == '5' assert evalpy('[1,2,3,4,5,3].index(3, -2)') == '5' assert evalpy('[1,2,3,4,5,3].index(3, 0, -2)') == '2' assert evalpy('a=[1,(2,3),4, (2,3), 5]; a.index((2,3))') == '1' assert evalpy('a=[1,(2,3),4, (2,3), 5]; a.index((2,3),2)') == '3'
def test_function_call_keyword_only_args_and_kwargs(self): code = "def foo(*, a=3, b=4, **x): return repr([a, b]) + repr(x);\nd = {'foo':foo}\n" assert evalpy(code + 'foo(1)') == '[3,4]{}' assert evalpy(code + 'foo(a=1, b=2)') == '[1,2]{}' assert evalpy(code + 'foo(a=1, b=2, c=5)') == '[1,2]{"c":5}' # assert evalpy(code + 'd.foo(1)') == '[3,4]{}' assert evalpy(code + 'd.foo(a=1, b=2, c=5)') == '[1,2]{"c":5}' # All the args code = "def foo(a, b=2, *, c=3, **x): return repr([a, b, c]) + repr(x);\n" assert evalpy(code + 'foo(1)') == '[1,2,3]{}' assert evalpy(code + 'foo(1, b=8)') == '[1,2,3]{"b":8}' # this one might be surprising assert evalpy(code + 'foo(1, c=8)') == '[1,2,8]{}' assert evalpy(code + 'foo(1, d=8)') == '[1,2,3]{"d":8}'
def test_string_formatting1(self): # string formatting that we already had assert evalpy('"%s" % "bar"') == 'bar' assert evalpy('"-%s-" % "bar"') == '-bar-' assert evalpy('"foo %s foo" % "bar"') == 'foo bar foo' assert evalpy('"x %i" % 6') == 'x 6' assert evalpy('"x %g" % 6') == 'x 6' assert evalpy('"%s: %f" % ("value", 6)') == 'value: 6.000000' assert evalpy('"%r: %r" % ("value", 6)') == '"value": 6'
def test_function_call_default_args(self): code = "def foo(a=2, b=3, c=4): return a+b+c;\nd = {'foo':foo}\n" assert evalpy(code + 'foo(1, 2, 3)') == '6' assert evalpy(code + 'd.foo(1, 2, 3)') == '6' # assert evalpy(code + 'foo(1, 2)') == '7' assert evalpy(code + 'd.foo(1, 2)') == '7' # assert evalpy(code + 'foo(1)') == '8' assert evalpy(code + 'd.foo(1)') == '8' # assert evalpy(code + 'foo()') == '9' assert evalpy(code + 'd.foo()') == '9'
def test_partition(self): assert evalpy('"".partition("-")') == "[ '', '', '' ]" assert evalpy('"abc".partition("-")') == "[ 'abc', '', '' ]" assert evalpy('"-".partition("-")') == "[ '', '-', '' ]" assert evalpy('"abc-".partition("-")') == "[ 'abc', '-', '' ]" assert evalpy('"-def".partition("-")') == "[ '', '-', 'def' ]" assert evalpy('"abc-def".partition("-")') == "[ 'abc', '-', 'def' ]" assert 'ValueError' in evalpy( 'try:\n "aa".partition("")\nexcept Exception as e:\n e')