def test_js_module_types(): code = create_js_module('baz.js', CODE, ['bb'], 'aa', 'hidden') assert 'define' not in code assert 'require' not in code assert 'bb' not in code assert 'aa' not in code assert 'return' not in code code = create_js_module('baz.js', CODE, ['bb'], 'aa', 'simple') assert 'define' not in code assert 'require' not in code assert 'bb' not in code assert 'return aa' in code code = create_js_module('baz.js', CODE, ['bb'], 'aa', 'amd') assert 'define' in code assert 'require' not in code assert 'bb' in code assert 'return aa' in code code = create_js_module('baz.js', CODE, ['bb'], 'aa', 'umd') assert 'define' in code assert 'require' in code assert 'bb' in code assert 'return aa' in code with raises(ValueError): # type not a str create_js_module('baz.js', CODE, ['bb'], 'aa', 3) with raises(ValueError): # invalid type create_js_module('baz.js', CODE, ['bb'], 'aa', 'not_known')
def test_js_module_names(): with raises(ValueError): # name not a str create_js_module(3, CODE, ['bb'], 'aa', 'simple') with raises(ValueError): # name empty str create_js_module('', CODE, ['bb'], 'aa', 'simple') code = create_js_module('foo.js', CODE, ['bb'], 'aa', 'simple') assert '.foo =' in code # using safe names
def test_js_module_exports(): with raises(ValueError): # exports not a str or list create_js_module('foo.js', CODE, ['bb'], 3, 'simple') with raises(ValueError): # exports element not a str create_js_module('foo.js', CODE, ['bb'], ['aa', 3], 'simple') code = create_js_module('foo.js', CODE, ['bb'], 'aa', 'simple') assert 'return aa' in code code = create_js_module('foo.js', CODE, ['bb'], ['aa', 'bb'], 'simple') assert 'return {aa: aa, bb: bb}' in code
def test_js_module_imports(): with raises(ValueError): # imports not a list create_js_module('foo.js', CODE, 'bb', 'aa', 'simple') with raises(ValueError): # imports element not a str create_js_module('foo.js', CODE, ['bb', 4], 'aa', 'simple') for type in ('amd', 'umd'): code = create_js_module('foo.js', CODE, ['bb as cc', 'dd'], 'aa', type) assert '"bb"' in code assert '"dd"' in code assert '"cc"' not in code assert 'cc, dd' in code
def test_overload_usage(self): # Can only use in a function with raises(JSError) as err_info: py2js("PSCRIPT_OVERLOAD=False\n3+4") assert 'PSCRIPT_OVERLOAD inside a function' in str(err_info.value) # Can only use with a bool def foo(): PSCRIPT_OVERLOAD = 0 return a + b with raises(JSError) as err_info: py2js(foo) assert 'PSCRIPT_OVERLOAD with a bool' in str(err_info.value)
def test_json_conversion(): from commonast import Node, Assign, Name, BinOp, Bytes, Num # Test json conversion roota = Assign([Name('foo')], BinOp('Add', Name('a'), Num(3))) rootb = Assign([Name('foo')], BinOp('Add', None, Num(3.2))) rootc = Assign([Name('foo')], BinOp('Add', Bytes(b'xx'), Num(4j))) for node1 in (roota, rootb, rootc): js = node1.tojson() node2 = Node.fromjson(js) # assert js.count('BinOp') == 1 assert js.count('Num') == 1 # assert node2.target_nodes[0].name == node1.target_nodes[0].name assert node2.value_node.op == node1.value_node.op assert node2.value_node.left_node == node1.value_node.left_node assert node2.value_node.right_node.value == node1.value_node.right_node.value # In fact, we can do node1 == node2 assert roota != rootb assert roota != rootc with raises(ValueError): roota == 5 assert str(roota) == roota.tojson() assert len(repr(roota)) < 80
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_python2_old_syntax(): # We do not support tuple function arg; it would complicate things with raises(RuntimeError): commonast.parse('def foo((a,)=c):pass') # Print statement becomes print function assert commonast.parse('print(foo)') == commonast.parse('print foo') # Exec statement becomes a d function assert commonast.parse('exec(foo)') == commonast.parse('exec foo') # Backticks becomes repr function assert commonast.parse('repr(foo)') == commonast.parse('`foo`')
def test_print(self): # Test code assert py2js('print()') == 'console.log("");' assert py2js('print(3)') == 'console.log(3);' assert py2js('foo.print()') == 'foo.print();' # Test single assert evalpy('print(3)') == '3' assert evalpy('print(3); print(3)') == '3\n3' assert evalpy('print(); print(3)') == '\n3' # Test \n assert evalpy('print("hello world")') == 'hello world' # Test multiple args assert evalpy('print(3, "hello")') == '3 hello' assert evalpy('print(3+1, "hello", 3+1)') == '4 hello 4' # Test sep and end assert evalpy('print(3, 4, 5)') == '3 4 5' assert evalpy('print(3, 4, 5, sep="")') == '345' assert evalpy('print(3, 4, 5, sep="\\n")') == '3\n4\n5' assert evalpy('print(3, 4, 5, sep="--")') == '3--4--5' assert evalpy('print(3, 4, 5, end="-")') == '3 4 5-' assert evalpy('print(3, 4, 5, end="\\n\\n-")') == '3 4 5\n\n-' raises(JSError, py2js, 'print(foo, file=x)') raises(JSError, py2js, 'print(foo, bar=x)')
def test_raw_js(): with raises(TypeError): RawJS() with raises(TypeError): RawJS(3) # Empty r1 = RawJS('') assert str(r1) == '' assert r1.get_code() == '' assert r1.get_code(4) == '' assert '0' in repr(r1) assert r1.__module__.endswith(__name__) # Short single line r2 = RawJS('require("foobar")') assert 'require(' in repr(r2) assert 'require(' in str(r2) assert r2.get_code().startswith('require') assert r2.get_code(4).startswith(' require') assert r2.get_code(2).startswith(' require') assert '\n' not in r2.get_code() # Long single line r2b = RawJS('require("foobar")'*10) assert 'require(' not in repr(r2b) assert '1' in repr(r2b) # Multiline, start at first line r3 = RawJS("""for ... { yyyy } """) assert 'lines' in repr(r3) assert 'for ...' in str(r3) assert str(r3).endswith('}\n') assert r3.get_code().count('\n') == 3 assert r3.get_code().startswith('for') assert r3.get_code(4).startswith(' for') assert '\n yyyy\n' in r3.get_code(0) assert '\n yyyy\n' in r3.get_code(4) # Multiline, exactly the same, but start at second line; same results r4 = RawJS(""" for ... { yyyy } """) assert 'lines' in repr(r4) assert 'for ...' in str(r4) assert str(r4).endswith('}\n') assert r4.get_code().count('\n') == 3 assert r4.get_code().startswith('for') assert r4.get_code(4).startswith(' for') assert '\n yyyy\n' in r4.get_code(0) assert '\n yyyy\n' in r4.get_code(4) # Multiline, now newline at the ned r5 = RawJS(""" for ... { yyyy }""") assert r5.get_code().count('\n') == 2 assert str(r5).endswith('}')
def test_py2js_on_wrong_vals(): raises(ValueError, py2js, []) raises(ValueError, py2js, {}) raises(ValueError, py2js, str) # cannot find source for str
def test_for(self): # Test all possible ranges line = nowhitespace(py2js('for i in range(9): pass', inline_stdlib=False)) assert line == 'vari;for(i=0;i<9;i+=1){}' line = nowhitespace(py2js('for i in range(2, 99): pass', inline_stdlib=False)) assert line == 'vari;for(i=2;i<99;i+=1){}' line = nowhitespace(py2js('for i in range(100, 0, -1): pass', inline_stdlib=False)) assert line == 'vari;for(i=100;i>0;i+=-1){}' # Test enumeration (code) assert ' in ' not in py2js('for i in [1, 2, 3]: pass') assert ' in ' not in py2js('for i in {1:2, 2:3}: pass') # Test declaration of iteration variable assert 'var aa' in py2js('for aa in x: pass') assert 'var aa' in py2js('aa=""\nfor aa in x: pass') assert 'var aa' in py2js('j=aa=""\nfor aa in x: pass') # Test output for range assert evalpy('for i in range(3):\n print(i)') == '0\n1\n2' assert evalpy('for i in range(1,6,2):\n print(i)') == '1\n3\n5' # Range with complex input assert evalpy('for i in range(sum([2, 3])): print(i)') == '0\n1\n2\n3\n4' # Test explicit for-array iteration code = py2js('a=[7,8]\nfor i in range(len(a)):\n print(a[i])') assert ' in ' not in code and evaljs(code) == '7\n8' # Test enumeration over arrays - should use actual for-loop code = py2js('for k in [7, 8]:\n print(k)') assert ' in ' not in code and evaljs(code) == '7\n8' # compile time tests raises(JSError, py2js, 'for i, j in range(10): pass') # Test enumeration over dicts # Python cannot see its a dict, and uses a for-loop code = py2js('d = {3:7, 4:8}\nfor k in d:\n print(k)') assert ' in ' not in code and evaljs(code) == '3\n4' code = py2js('d = {3:7, 4:8}\nfor k in d:\n print(d[k])') assert ' in ' not in code and evaljs(code) == '7\n8' # .keys() code = py2js('d = {3:7, 4:8}\nfor k in d.keys():\n print(d[k])') assert evaljs(code) == '7\n8' # and ' in ' in code # .values() code = py2js('d = {3:7, 4:8}\nfor v in d.values():\n print(v)') assert ' in ' in code and evaljs(code) == '7\n8' # .items() code = py2js('d = {3:7, 4:8}\nfor k,v in d.items():\n print(k)') assert ' in ' in code and evaljs(code) == '3\n4' code = py2js('d = {3:7, 4:8}\nfor k,v in d.items():\n print(v)') assert ' in ' in code and evaljs(code) == '7\n8' # compile time tests raises(JSError, py2js, 'for i, j in x.keys(): pass') raises(JSError, py2js, 'for i, j in x.values(): pass') raises(JSError, py2js, 'for i in x.items(): pass') raises(JSError, py2js, 'for i, j, k in x.items(): pass') # Test iterate over strings code = py2js('for c in "foo":\n print(c)') assert evaljs(code) == 'f\no\no' # Break and continue for9 = 'for i in range(9):\n ' assert evalpy(for9 + 'if i==4:break\n print(i)') == '0\n1\n2\n3' assert evalpy(for9 + 'if i<5:continue\n print(i)') == '5\n6\n7\n8' # 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' # Nested loops correct else code = py2js(self.method_for) assert evaljs('%s method_for()' % code) == 'ok\nok\nnull' # Tuple iterators assert evalpy('for i, j in [[1, 2], [3, 4]]: print(i+j)') == '3\n7' assert evalpy('for i, j, k in [[1, 2, 3], [3, 4, 5]]: print(i+j+k)') == '6\n12'
def test_js_module_code(): with raises(ValueError): # code not a str create_js_module('foo.js', 4, ['bb'], 'aa', 'simple')
def test_Node_creation(): Node = commonast.Node class MyNodeWithoutSlots(Node): pass class MyStubNode(Node): __slots__ = () class MyNode(Node): __slots__ = 'name', 'op', 'foo_node', 'foo_nodes', 'bar' stubnode = MyStubNode() stubnodes = [MyStubNode(), MyStubNode(), MyStubNode()] # Node is an abstract class raises(AssertionError, Node) # Nodes must have slots (and no __dict__ to preserve memory) raises(AssertionError, MyNodeWithoutSlots) # number of names must match raises( AssertionError, MyNode, ) raises(AssertionError, MyStubNode, 1) raises(AssertionError, MyNode, 'a', 'Add', stubnode, stubnodes, 1, 2) # These work node = MyNode('a', 'Add', stubnode, stubnodes, 1) node = MyNode('a', 'Add', None, stubnodes, 1) node = MyNode('a', 'Add', stubnode, [], 1) node = MyNode('a', 'Add', stubnode, stubnodes, 'bla') node = MyNode('a', 'Add', stubnode, stubnodes, [1, 2, 3]) node = MyNode('a', 'Mult', stubnode, stubnodes, 1) node = MyNode('blas asdasd as', 'Mult', stubnode, stubnodes, 1) # Name must be a string raises(AssertionError, MyNode, 1, 'Add', stubnode, stubnodes, 1) # op must be an existing operator raises(AssertionError, MyNode, 'a', 'crap', stubnode, stubnodes, 1) # names ending with _node must be a node, and _nodes must be a list of nodes raises(AssertionError, MyNode, 'a', 'Add', 1, stubnodes, 1) raises(AssertionError, MyNode, 'a', 'Add', 'x', stubnodes, 1) raises(AssertionError, MyNode, 'a', 'Add', stubnode, 'not a node', 1) raises(AssertionError, MyNode, 'a', 'Add', stubnode, [1, 2], 1) # bar can be anything, but not a Node or list of Nodes raises(AssertionError, MyNode, 'a', 'Add', stubnode, stubnodes, stubnode) raises(AssertionError, MyNode, 'a', 'Add', stubnode, stubnodes, stubnodes)