2018-03-30 14:51:13 +00:00
|
|
|
import time
|
|
|
|
|
2018-08-06 19:01:59 +00:00
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
2018-08-20 17:02:12 +00:00
|
|
|
def test_init(selenium_standalone):
|
2018-08-24 15:43:59 +00:00
|
|
|
assert ('Python initialization complete'
|
|
|
|
in selenium_standalone.logs.splitlines())
|
2018-08-20 17:02:12 +00:00
|
|
|
assert len(selenium_standalone.driver.window_handles) == 1
|
2018-03-30 14:51:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_webbrowser(selenium):
|
|
|
|
selenium.run("import antigravity")
|
|
|
|
time.sleep(2)
|
|
|
|
assert len(selenium.driver.window_handles) == 2
|
|
|
|
|
|
|
|
|
|
|
|
def test_print(selenium):
|
|
|
|
selenium.run("print('This should be logged')")
|
2018-08-24 15:43:59 +00:00
|
|
|
assert 'This should be logged' in selenium.logs.splitlines()
|
2018-04-09 14:39:52 +00:00
|
|
|
|
|
|
|
|
2018-05-23 11:23:49 +00:00
|
|
|
def test_python2js(selenium):
|
|
|
|
assert selenium.run_js('return pyodide.runPython("None") === undefined')
|
|
|
|
assert selenium.run_js('return pyodide.runPython("True") === true')
|
|
|
|
assert selenium.run_js('return pyodide.runPython("False") === false')
|
|
|
|
assert selenium.run_js('return pyodide.runPython("42") === 42')
|
|
|
|
assert selenium.run_js('return pyodide.runPython("3.14") === 3.14')
|
2018-07-26 20:50:12 +00:00
|
|
|
# Need to test all three internal string representations in Python: UCS1,
|
|
|
|
# UCS2 and UCS4
|
|
|
|
assert selenium.run_js(
|
|
|
|
'return pyodide.runPython("\'ascii\'") === "ascii"')
|
|
|
|
assert selenium.run_js(
|
|
|
|
'return pyodide.runPython("\'ιωδιούχο\'") === "ιωδιούχο"')
|
2018-05-23 11:23:49 +00:00
|
|
|
assert selenium.run_js(
|
|
|
|
'return pyodide.runPython("\'碘化物\'") === "碘化物"')
|
|
|
|
assert selenium.run_js(
|
|
|
|
'let x = pyodide.runPython("b\'bytes\'");\n'
|
2018-06-05 10:16:32 +00:00
|
|
|
'return (x instanceof window.Uint8ClampedArray) && '
|
2018-05-23 11:23:49 +00:00
|
|
|
'(x.length === 5) && '
|
|
|
|
'(x[0] === 98)')
|
|
|
|
assert selenium.run_js(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
let x = pyodide.runPython("[1, 2, 3]");
|
|
|
|
return ((x instanceof window.Array) && (x.length === 3) &&
|
|
|
|
(x[0] == 1) && (x[1] == 2) && (x[2] == 3))
|
|
|
|
""")
|
2018-05-23 11:23:49 +00:00
|
|
|
assert selenium.run_js(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
let x = pyodide.runPython("{42: 64}");
|
|
|
|
return (typeof x === "object") && (x[42] === 64)
|
|
|
|
""")
|
2018-05-23 11:23:49 +00:00
|
|
|
assert selenium.run_js(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
let x = pyodide.runPython("open('/foo.txt', 'wb')")
|
|
|
|
return (x.tell() === 0)
|
|
|
|
""")
|
2018-05-23 11:23:49 +00:00
|
|
|
|
|
|
|
|
2018-10-02 17:53:56 +00:00
|
|
|
def test_python2js_long_ints(selenium):
|
|
|
|
assert selenium.run('2**30') == 2**30
|
|
|
|
assert selenium.run('2**31') == 2**31
|
|
|
|
assert selenium.run('2**30 - 1 + 2**30') == (2**30 - 1 + 2**30)
|
|
|
|
assert selenium.run('2**32 / 2**4') == (2**32 / 2**4)
|
2018-10-03 12:15:00 +00:00
|
|
|
assert selenium.run('-2**30') == -2**30
|
|
|
|
assert selenium.run('-2**31') == -2**31
|
2018-10-02 17:53:56 +00:00
|
|
|
|
|
|
|
|
2018-12-07 19:33:07 +00:00
|
|
|
def test_python2js_numpy_dtype(selenium_standalone):
|
|
|
|
selenium = selenium_standalone
|
|
|
|
|
|
|
|
selenium.load_package('numpy')
|
|
|
|
selenium.run("import numpy as np")
|
|
|
|
|
|
|
|
expected_result = [[[0, 1], [2, 3]],
|
|
|
|
[[4, 5], [6, 7]]]
|
|
|
|
|
2018-12-27 17:58:44 +00:00
|
|
|
def assert_equal():
|
|
|
|
# We have to do this an element at a time, since the Selenium driver
|
|
|
|
# for Firefox does not convert TypedArrays to Python correctly
|
|
|
|
for i in range(2):
|
|
|
|
for j in range(2):
|
|
|
|
for k in range(2):
|
|
|
|
assert selenium.run_js(
|
|
|
|
f"return pyodide.pyimport('x')[{i}][{j}][{k}]"
|
|
|
|
) == expected_result[i][j][k]
|
|
|
|
|
2018-12-07 19:33:07 +00:00
|
|
|
for order in ('C', 'F'):
|
|
|
|
for dtype in (
|
|
|
|
'int8',
|
|
|
|
'uint8',
|
|
|
|
'int16',
|
|
|
|
'uint16',
|
|
|
|
'int32',
|
|
|
|
'uint32',
|
|
|
|
'int64',
|
|
|
|
'uint64',
|
|
|
|
'float32',
|
|
|
|
'float64'
|
|
|
|
):
|
2018-12-27 17:58:44 +00:00
|
|
|
selenium.run(
|
2018-12-07 19:33:07 +00:00
|
|
|
f"""
|
|
|
|
x = np.arange(8, dtype=np.{dtype})
|
|
|
|
x = x.reshape((2, 2, 2))
|
|
|
|
x = x.copy({order!r})
|
|
|
|
"""
|
2018-12-27 17:58:44 +00:00
|
|
|
)
|
|
|
|
assert_equal()
|
|
|
|
classname = selenium.run_js(
|
|
|
|
"return pyodide.pyimport('x')[0][0].constructor.name"
|
|
|
|
)
|
|
|
|
if order == 'C' and dtype not in ('uint64', 'int64'):
|
2018-12-28 16:28:31 +00:00
|
|
|
# Here we expect a TypedArray subclass, such as Uint8Array, but
|
|
|
|
# not a plain-old Array
|
2018-12-27 17:58:44 +00:00
|
|
|
assert classname.endswith('Array')
|
|
|
|
assert classname != 'Array'
|
|
|
|
else:
|
|
|
|
assert classname == 'Array'
|
|
|
|
selenium.run(
|
2018-12-07 19:33:07 +00:00
|
|
|
"""
|
2018-12-27 17:58:44 +00:00
|
|
|
x = x.byteswap().newbyteorder()
|
2018-12-07 19:33:07 +00:00
|
|
|
"""
|
2018-12-27 17:58:44 +00:00
|
|
|
)
|
|
|
|
assert_equal()
|
|
|
|
classname = selenium.run_js(
|
|
|
|
"return pyodide.pyimport('x')[0][0].constructor.name"
|
|
|
|
)
|
|
|
|
if order == 'C' and dtype in ('int8', 'uint8'):
|
2018-12-28 16:28:31 +00:00
|
|
|
# Here we expect a TypedArray subclass, such as Uint8Array, but
|
|
|
|
# not a plain-old Array -- but only for single byte types where
|
|
|
|
# endianness doesn't matter
|
2018-12-27 17:58:44 +00:00
|
|
|
assert classname.endswith('Array')
|
|
|
|
assert classname != 'Array'
|
|
|
|
else:
|
|
|
|
assert classname == 'Array'
|
2018-12-07 19:33:07 +00:00
|
|
|
|
|
|
|
assert selenium.run("np.array([True, False])") == [True, False]
|
|
|
|
|
|
|
|
selenium.run(
|
|
|
|
"x = np.array([['string1', 'string2'], ['string3', 'string4']])"
|
|
|
|
)
|
|
|
|
assert selenium.run_js("return pyodide.pyimport('x').length") == 2
|
|
|
|
assert selenium.run_js("return pyodide.pyimport('x')[0][0]") == 'string1'
|
|
|
|
assert selenium.run_js("return pyodide.pyimport('x')[1][1]") == 'string4'
|
|
|
|
|
|
|
|
|
2018-05-23 11:23:49 +00:00
|
|
|
def test_pythonexc2js(selenium):
|
|
|
|
try:
|
|
|
|
selenium.run_js('return pyodide.runPython("5 / 0")')
|
2018-07-10 00:59:03 +00:00
|
|
|
except selenium.JavascriptException as e:
|
2018-11-05 23:42:00 +00:00
|
|
|
assert 'ZeroDivisionError' in str(e)
|
2018-06-24 16:29:46 +00:00
|
|
|
else:
|
|
|
|
assert False, 'Expected exception'
|
2018-05-23 11:23:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_js2python(selenium):
|
|
|
|
selenium.run_js(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
window.jsstring = "碘化物";
|
|
|
|
window.jsnumber0 = 42;
|
|
|
|
window.jsnumber1 = 42.5;
|
|
|
|
window.jsundefined = undefined;
|
|
|
|
window.jsnull = null;
|
|
|
|
window.jstrue = true;
|
|
|
|
window.jsfalse = false;
|
|
|
|
window.jspython = pyodide.pyimport("open");
|
|
|
|
window.jsbytes = new Uint8Array([1, 2, 3]);
|
|
|
|
window.jsfloats = new Float32Array([1, 2, 3]);
|
|
|
|
window.jsobject = new XMLHttpRequest();
|
|
|
|
"""
|
2018-05-23 11:23:49 +00:00
|
|
|
)
|
|
|
|
assert selenium.run(
|
|
|
|
'from js import jsstring\n'
|
|
|
|
'jsstring == "碘化物"')
|
|
|
|
assert selenium.run(
|
|
|
|
'from js import jsnumber0\n'
|
|
|
|
'jsnumber0 == 42')
|
|
|
|
assert selenium.run(
|
|
|
|
'from js import jsnumber1\n'
|
|
|
|
'jsnumber1 == 42.5')
|
|
|
|
assert selenium.run(
|
|
|
|
'from js import jsundefined\n'
|
|
|
|
'jsundefined is None')
|
|
|
|
assert selenium.run(
|
|
|
|
'from js import jstrue\n'
|
|
|
|
'jstrue is True')
|
|
|
|
assert selenium.run(
|
|
|
|
'from js import jsfalse\n'
|
|
|
|
'jsfalse is False')
|
|
|
|
assert selenium.run(
|
|
|
|
'from js import jspython\n'
|
|
|
|
'jspython is open')
|
|
|
|
assert selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
from js import jsbytes
|
|
|
|
((jsbytes.tolist() == [1, 2, 3])
|
|
|
|
and (jsbytes.tobytes() == b"\x01\x02\x03"))
|
|
|
|
""")
|
2018-06-27 14:57:53 +00:00
|
|
|
assert selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
from js import jsfloats
|
|
|
|
import struct
|
|
|
|
expected = struct.pack("fff", 1, 2, 3)
|
|
|
|
(jsfloats.tolist() == [1, 2, 3]) and (jsfloats.tobytes() == expected)
|
|
|
|
""")
|
2018-05-23 11:23:49 +00:00
|
|
|
assert selenium.run(
|
|
|
|
'from js import jsobject\n'
|
|
|
|
'str(jsobject) == "[object XMLHttpRequest]"')
|
|
|
|
|
|
|
|
|
2018-09-07 12:01:58 +00:00
|
|
|
@pytest.mark.parametrize('wasm_heap', (False, True))
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
'jstype, pytype',
|
|
|
|
(
|
|
|
|
('Int8Array', 'b'),
|
|
|
|
('Uint8Array', 'B'),
|
|
|
|
('Uint8ClampedArray', 'B'),
|
|
|
|
('Int16Array', 'h'),
|
|
|
|
('Uint16Array', 'H'),
|
|
|
|
('Int32Array', 'i'),
|
|
|
|
('Uint32Array', 'I'),
|
|
|
|
('Float32Array', 'f'),
|
|
|
|
('Float64Array', 'd')))
|
|
|
|
def test_typed_arrays(selenium, wasm_heap, jstype, pytype):
|
|
|
|
if not wasm_heap:
|
|
|
|
selenium.run_js(
|
|
|
|
f'window.array = new {jstype}([1, 2, 3, 4]);\n')
|
|
|
|
else:
|
|
|
|
selenium.run_js(
|
|
|
|
f"""
|
2018-09-19 14:42:49 +00:00
|
|
|
var buffer = pyodide._module._malloc(
|
2018-09-07 12:01:58 +00:00
|
|
|
4 * {jstype}.BYTES_PER_ELEMENT);
|
|
|
|
window.array = new {jstype}(
|
2018-09-19 14:42:49 +00:00
|
|
|
pyodide._module.HEAPU8.buffer, buffer, 4);
|
2018-09-07 12:01:58 +00:00
|
|
|
window.array[0] = 1;
|
|
|
|
window.array[1] = 2;
|
|
|
|
window.array[2] = 3;
|
|
|
|
window.array[3] = 4;
|
|
|
|
""")
|
|
|
|
assert selenium.run(
|
|
|
|
f"""
|
|
|
|
from js import array
|
|
|
|
import struct
|
|
|
|
expected = struct.pack("{pytype*4}", 1, 2, 3, 4)
|
|
|
|
print(array.format, array.tolist(), array.tobytes())
|
|
|
|
((array.format == "{pytype}")
|
|
|
|
and array.tolist() == [1, 2, 3, 4]
|
|
|
|
and array.tobytes() == expected
|
|
|
|
and array.obj._has_bytes() is {not wasm_heap})
|
|
|
|
""")
|
2018-06-29 20:18:29 +00:00
|
|
|
|
|
|
|
|
2018-04-26 15:43:48 +00:00
|
|
|
def test_import_js(selenium):
|
|
|
|
result = selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
from js import window
|
|
|
|
window.title = 'Foo'
|
|
|
|
window.title
|
|
|
|
""")
|
2018-04-26 15:43:48 +00:00
|
|
|
assert result == 'Foo'
|
|
|
|
|
|
|
|
|
2018-11-09 23:22:54 +00:00
|
|
|
def test_pyimport_multiple(selenium):
|
|
|
|
"""See #1151"""
|
|
|
|
selenium.run("v = 0.123")
|
|
|
|
selenium.run_js("pyodide.pyimport('v')")
|
|
|
|
selenium.run_js("pyodide.pyimport('v')")
|
|
|
|
|
|
|
|
|
2018-05-23 11:23:49 +00:00
|
|
|
def test_pyproxy(selenium):
|
2018-05-04 17:13:56 +00:00
|
|
|
selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
class Foo:
|
|
|
|
bar = 42
|
|
|
|
def get_value(self, value):
|
|
|
|
return value * 64
|
|
|
|
f = Foo()
|
|
|
|
"""
|
2018-05-09 18:59:55 +00:00
|
|
|
)
|
|
|
|
assert selenium.run_js("return pyodide.pyimport('f').get_value(2)") == 128
|
2018-05-04 17:13:56 +00:00
|
|
|
assert selenium.run_js("return pyodide.pyimport('f').bar") == 42
|
2018-06-15 16:30:22 +00:00
|
|
|
assert selenium.run_js("return ('bar' in pyodide.pyimport('f'))")
|
2018-05-04 17:13:56 +00:00
|
|
|
selenium.run_js("f = pyodide.pyimport('f'); f.baz = 32")
|
|
|
|
assert selenium.run("f.baz") == 32
|
|
|
|
assert set(selenium.run_js(
|
|
|
|
"return Object.getOwnPropertyNames(pyodide.pyimport('f'))")) == set(
|
2018-05-23 11:23:49 +00:00
|
|
|
['__class__', '__delattr__', '__dict__', '__dir__',
|
2018-05-04 17:13:56 +00:00
|
|
|
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
|
|
|
|
'__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',
|
|
|
|
'__lt__', '__module__', '__ne__', '__new__', '__reduce__',
|
|
|
|
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
|
|
|
|
'__str__', '__subclasshook__', '__weakref__', 'bar', 'baz',
|
2018-07-09 21:15:10 +00:00
|
|
|
'get_value', 'toString', 'prototype', 'arguments', 'caller'])
|
2018-06-15 16:30:22 +00:00
|
|
|
assert selenium.run("hasattr(f, 'baz')")
|
2018-05-04 17:13:56 +00:00
|
|
|
selenium.run_js("delete pyodide.pyimport('f').baz")
|
2018-06-15 16:30:22 +00:00
|
|
|
assert not selenium.run("hasattr(f, 'baz')")
|
|
|
|
assert selenium.run_js(
|
|
|
|
"return pyodide.pyimport('f').toString()").startswith('<Foo')
|
2018-05-04 17:13:56 +00:00
|
|
|
|
|
|
|
|
2018-06-24 16:29:46 +00:00
|
|
|
def test_pyproxy_destroy(selenium):
|
|
|
|
selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
class Foo:
|
|
|
|
bar = 42
|
|
|
|
def get_value(self, value):
|
|
|
|
return value * 64
|
|
|
|
f = Foo()
|
|
|
|
"""
|
2018-06-24 16:29:46 +00:00
|
|
|
)
|
|
|
|
try:
|
|
|
|
selenium.run_js(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
let f = pyodide.pyimport('f');
|
|
|
|
console.assert(f.get_value(1) === 64);
|
|
|
|
f.destroy();
|
|
|
|
f.get_value();
|
|
|
|
""")
|
2018-07-10 00:59:03 +00:00
|
|
|
except selenium.JavascriptException as e:
|
2018-06-25 13:09:16 +00:00
|
|
|
assert 'Object has already been destroyed' in str(e)
|
2018-06-24 16:29:46 +00:00
|
|
|
else:
|
|
|
|
assert False, 'Expected exception'
|
|
|
|
|
|
|
|
|
2018-05-23 11:23:49 +00:00
|
|
|
def test_jsproxy(selenium):
|
2018-05-10 14:37:46 +00:00
|
|
|
assert selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
from js import document
|
|
|
|
el = document.createElement('div')
|
|
|
|
document.body.appendChild(el)
|
|
|
|
document.body.children.length"""
|
2018-05-10 14:37:46 +00:00
|
|
|
) == 1
|
|
|
|
assert selenium.run(
|
|
|
|
"document.body.children[0].tagName") == 'DIV'
|
2018-05-23 11:23:49 +00:00
|
|
|
assert selenium.run(
|
|
|
|
"repr(document)") == '[object HTMLDocument]'
|
2018-06-05 00:37:40 +00:00
|
|
|
selenium.run_js(
|
|
|
|
"window.square = function (x) { return x*x; }")
|
|
|
|
assert selenium.run(
|
|
|
|
"from js import square\n"
|
|
|
|
"square(2)") == 4
|
|
|
|
assert selenium.run(
|
|
|
|
"from js import ImageData\n"
|
|
|
|
"ImageData.new(64, 64)")
|
2018-06-25 20:54:08 +00:00
|
|
|
assert selenium.run(
|
|
|
|
"from js import ImageData\n"
|
|
|
|
"ImageData.typeof") == 'function'
|
|
|
|
selenium.run_js(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
class Point {
|
|
|
|
constructor(x, y) {
|
|
|
|
this.x = x;
|
|
|
|
this.y = y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
window.TEST = new Point(42, 43);""")
|
2018-06-25 20:54:08 +00:00
|
|
|
assert selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
from js import TEST
|
|
|
|
del TEST.y
|
|
|
|
TEST.y""") is None
|
2018-06-25 20:54:08 +00:00
|
|
|
selenium.run_js(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
class Point {
|
|
|
|
constructor(x, y) {
|
|
|
|
this.x = x;
|
|
|
|
this.y = y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
window.TEST = new Point(42, 43);""")
|
2018-06-25 20:54:08 +00:00
|
|
|
assert selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
from js import TEST
|
|
|
|
del TEST['y']
|
|
|
|
TEST['y']""") is None
|
2018-06-25 20:54:08 +00:00
|
|
|
assert selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
from js import TEST
|
|
|
|
TEST == TEST
|
|
|
|
""")
|
2018-06-25 20:54:08 +00:00
|
|
|
assert selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
from js import TEST
|
|
|
|
TEST != 'foo'
|
|
|
|
""")
|
2018-06-25 20:54:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_jsproxy_iter(selenium):
|
|
|
|
selenium.run_js(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
function makeIterator(array) {
|
|
|
|
var nextIndex = 0;
|
|
|
|
return {
|
|
|
|
next: function() {
|
|
|
|
return nextIndex < array.length ?
|
|
|
|
{value: array[nextIndex++], done: false} :
|
|
|
|
{done: true};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
window.ITER = makeIterator([1, 2, 3]);""")
|
2018-06-25 20:54:08 +00:00
|
|
|
assert selenium.run(
|
|
|
|
"from js import ITER\n"
|
|
|
|
"list(ITER)") == [1, 2, 3]
|
2018-05-10 14:37:46 +00:00
|
|
|
|
2018-05-09 18:33:52 +00:00
|
|
|
|
2018-09-26 21:59:40 +00:00
|
|
|
def test_jsproxy_implicit_iter(selenium):
|
|
|
|
selenium.run_js(
|
|
|
|
"""
|
|
|
|
window.ITER = [1, 2, 3];""")
|
|
|
|
assert selenium.run(
|
2018-10-08 14:00:45 +00:00
|
|
|
"from js import ITER, Object\n"
|
|
|
|
"list(ITER)") == [1, 2, 3]
|
|
|
|
assert selenium.run(
|
|
|
|
"from js import ITER, Object\n"
|
2018-09-26 21:59:40 +00:00
|
|
|
"list(ITER.values())") == [1, 2, 3]
|
2018-10-08 14:00:45 +00:00
|
|
|
assert selenium.run(
|
|
|
|
"from js import ITER, Object\n"
|
|
|
|
"list(Object.values(ITER))") == [1, 2, 3]
|
2018-09-26 21:59:40 +00:00
|
|
|
|
|
|
|
|
2018-11-28 17:25:04 +00:00
|
|
|
def test_jsproxy_kwargs(selenium):
|
|
|
|
selenium.run_js(
|
|
|
|
"""
|
|
|
|
window.kwarg_function = ({ a = 1, b = 1 }) => {
|
|
|
|
return a / b;
|
|
|
|
};
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
assert selenium.run(
|
|
|
|
"""
|
|
|
|
from js import kwarg_function
|
|
|
|
kwarg_function(b = 2, a = 10)
|
|
|
|
"""
|
|
|
|
) == 5
|
|
|
|
|
|
|
|
|
2018-05-09 18:33:52 +00:00
|
|
|
def test_open_url(selenium):
|
|
|
|
assert selenium.run(
|
2018-09-07 12:01:58 +00:00
|
|
|
"""
|
|
|
|
import pyodide
|
2018-09-12 14:14:51 +00:00
|
|
|
pyodide.open_url('test/data.txt').read()
|
|
|
|
""") == 'HELLO\n'
|
|
|
|
|
|
|
|
|
|
|
|
def test_open_url_cgi(selenium):
|
|
|
|
assert selenium.run(
|
|
|
|
"""
|
|
|
|
import pyodide
|
|
|
|
pyodide.open_url('test/data.cgi').read()
|
2018-09-07 12:01:58 +00:00
|
|
|
""") == 'HELLO\n'
|
2018-05-09 18:33:52 +00:00
|
|
|
|
|
|
|
|
2018-07-26 20:50:12 +00:00
|
|
|
def test_load_package_after_convert_string(selenium):
|
|
|
|
"""
|
|
|
|
See #93.
|
|
|
|
"""
|
|
|
|
selenium.run(
|
|
|
|
"import sys\n"
|
|
|
|
"x = sys.version")
|
|
|
|
selenium.run_js(
|
|
|
|
"var x = pyodide.pyimport('x')\n"
|
|
|
|
"console.log(x)")
|
|
|
|
selenium.load_package('kiwisolver')
|
|
|
|
selenium.run(
|
|
|
|
"import kiwisolver")
|
2018-09-14 14:58:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_version_info(selenium):
|
|
|
|
from distutils.version import LooseVersion
|
|
|
|
|
|
|
|
version_py_str = selenium.run("""
|
|
|
|
import pyodide
|
|
|
|
|
|
|
|
pyodide.__version__
|
|
|
|
""")
|
|
|
|
version_py = LooseVersion(version_py_str)
|
|
|
|
assert version_py > LooseVersion('0.0.1')
|
|
|
|
|
|
|
|
version_js_str = selenium.run_js("return pyodide.version()")
|
|
|
|
version_js = LooseVersion(version_js_str)
|
|
|
|
assert version_py == version_js
|
2018-09-12 21:17:42 +00:00
|
|
|
|
|
|
|
|
2018-09-17 19:35:54 +00:00
|
|
|
def test_recursive_list(selenium_standalone):
|
|
|
|
selenium_standalone.run(
|
2018-09-12 21:17:42 +00:00
|
|
|
"""
|
|
|
|
x = []
|
|
|
|
x.append(x)
|
|
|
|
"""
|
|
|
|
)
|
2018-09-17 19:35:54 +00:00
|
|
|
selenium_standalone.run_js("x = pyodide.pyimport('x')")
|
2018-09-12 21:17:42 +00:00
|
|
|
|
|
|
|
|
2018-09-17 19:35:54 +00:00
|
|
|
def test_recursive_dict(selenium_standalone):
|
|
|
|
selenium_standalone.run(
|
2018-09-12 21:17:42 +00:00
|
|
|
"""
|
|
|
|
x = {}
|
|
|
|
x[0] = x
|
|
|
|
"""
|
|
|
|
)
|
2018-09-17 19:35:54 +00:00
|
|
|
selenium_standalone.run_js("x = pyodide.pyimport('x')")
|
2018-10-10 18:17:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_runpythonasync(selenium_standalone):
|
2018-12-27 17:58:44 +00:00
|
|
|
selenium_standalone.run_async(
|
2018-10-10 18:17:29 +00:00
|
|
|
"""
|
|
|
|
import numpy as np
|
2018-12-27 17:58:44 +00:00
|
|
|
x = np.zeros(5)
|
2018-10-10 18:17:29 +00:00
|
|
|
"""
|
|
|
|
)
|
2018-12-27 17:58:44 +00:00
|
|
|
for i in range(5):
|
|
|
|
assert selenium_standalone.run_js(
|
|
|
|
f"return pyodide.pyimport('x')[{i}] == 0"
|
|
|
|
)
|
2018-10-10 18:17:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_runpythonasync_different_package_name(selenium_standalone):
|
|
|
|
output = selenium_standalone.run_async(
|
|
|
|
"""
|
|
|
|
import dateutil
|
|
|
|
dateutil.__version__
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
assert isinstance(output, str)
|
|
|
|
|
|
|
|
|
|
|
|
def test_runpythonasync_no_imports(selenium_standalone):
|
|
|
|
output = selenium_standalone.run_async(
|
|
|
|
"""
|
|
|
|
42
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
assert output == 42
|
|
|
|
|
|
|
|
|
|
|
|
def test_runpythonasync_missing_import(selenium_standalone):
|
|
|
|
try:
|
|
|
|
selenium_standalone.run_async(
|
|
|
|
"""
|
|
|
|
import foo
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
except selenium_standalone.JavascriptException as e:
|
|
|
|
assert "ModuleNotFoundError" in str(e)
|
|
|
|
else:
|
|
|
|
assert False
|
|
|
|
|
|
|
|
|
|
|
|
def test_runpythonasync_exception(selenium_standalone):
|
|
|
|
try:
|
|
|
|
selenium_standalone.run_async(
|
|
|
|
"""
|
|
|
|
42 / 0
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
except selenium_standalone.JavascriptException as e:
|
|
|
|
assert "ZeroDivisionError" in str(e)
|
|
|
|
else:
|
|
|
|
assert False
|
|
|
|
|
|
|
|
|
|
|
|
def test_runpythonasync_exception_after_import(selenium_standalone):
|
|
|
|
try:
|
|
|
|
selenium_standalone.run_async(
|
|
|
|
"""
|
|
|
|
import numpy as np
|
|
|
|
x = np.empty(5)
|
|
|
|
42 / 0
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
except selenium_standalone.JavascriptException as e:
|
|
|
|
assert "ZeroDivisionError" in str(e)
|
|
|
|
else:
|
|
|
|
assert False
|
2018-12-19 19:22:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_py(selenium_standalone):
|
|
|
|
selenium_standalone.run(
|
|
|
|
"""
|
|
|
|
def func():
|
|
|
|
return 42
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
|
2018-12-19 21:28:39 +00:00
|
|
|
assert selenium_standalone.run_js('return pyodide.globals.func()') == 42
|
2019-01-23 21:59:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
def test_eval_nothing(selenium):
|
|
|
|
assert selenium.run('# comment') is None
|
|
|
|
assert selenium.run('') is None
|