From 761b6320ba6a795630c4d44df9f253fd0cd0c562 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 25 Jun 2022 21:20:22 -0700 Subject: [PATCH] Move eval functions to pyodide.code submodule (#2787) This raises a deprecation warning the first time such a function is used. Work towards #2689. --- docs/project/changelog.md | 2 +- docs/usage/faq.md | 10 +-- .../pyodide_test_runner/browser.py | 6 +- .../tests/test_decorator.py | 4 +- src/js/api.ts | 14 +-- src/js/pyodide.ts | 1 + src/py/pyodide/__init__.py | 49 +++++++---- src/py/pyodide/code.py | 35 ++++++++ src/tests/test_asyncio.py | 12 +-- src/tests/test_browser_apis.py | 10 +-- src/tests/test_console.py | 3 +- src/tests/test_jsproxy.py | 16 ++-- src/tests/test_pyodide.py | 31 +++++-- src/tests/test_typeconversions.py | 86 ++++++++++--------- 14 files changed, 181 insertions(+), 98 deletions(-) create mode 100644 src/py/pyodide/code.py diff --git a/docs/project/changelog.md b/docs/project/changelog.md index ee6ab287d..c5deee635 100644 --- a/docs/project/changelog.md +++ b/docs/project/changelog.md @@ -59,7 +59,7 @@ substitutions: `ArrayBuffer` as first argument, rather than only a `Uint8Array`. {pr}`2451` -- {{ Feature }} Added `pyodide.run_js` API. +- {{ Feature }} Added `pyodide.code.run_js` API. {pr}`2426` - {{ Fix }} BigInt's between 2^{32\*n - 1} and 2^{32\*n} no longer get diff --git a/docs/usage/faq.md b/docs/usage/faq.md index 8436a5cc3..0f117332d 100644 --- a/docs/usage/faq.md +++ b/docs/usage/faq.md @@ -347,13 +347,13 @@ simple: ```javascript function runPython(code) { - pyodide.pyodide_py.eval_code(code, pyodide.globals); + pyodide.pyodide_py.code.eval_code(code, pyodide.globals); } ``` ```javascript async function runPythonAsync(code) { - return await pyodide.pyodide_py.eval_code_async(code, pyodide.globals); + return await pyodide.pyodide_py.code.eval_code_async(code, pyodide.globals); } ``` @@ -361,10 +361,10 @@ To make your own version of {any}`runPython ` you could do: ```pyodide const my_eval_code = pyodide.runPython(` - import pyodide + from pyodide.code import eval_code def my_eval_code(code, ns): extra_info = None - result = pyodide.eval_code(code, ns) + result = eval_code(code, ns) return ns["extra_info"], result my_eval_code `) @@ -377,5 +377,5 @@ function myRunPython(code){ Then `myRunPython("2+7")` returns `[None, 9]` and `myRunPython("extra_info='hello' ; 2 + 2")` returns `['hello', 4]`. If you want to change which packages {any}`pyodide.loadPackagesFromImports` loads, you can -monkey patch {any}`pyodide.find_imports` which takes `code` as an argument +monkey patch {any}`pyodide.code.find_imports` which takes `code` as an argument and returns a list of packages imported. diff --git a/pyodide-test-runner/pyodide_test_runner/browser.py b/pyodide-test-runner/pyodide_test_runner/browser.py index 9ec247e78..30f499b1a 100644 --- a/pyodide-test-runner/pyodide_test_runner/browser.py +++ b/pyodide-test-runner/pyodide_test_runner/browser.py @@ -180,11 +180,11 @@ class BrowserWrapper: self.run_js( """ pyodide.globals.get; - pyodide.pyodide_py.eval_code; - pyodide.pyodide_py.eval_code_async; + pyodide._api.pyodide_code.eval_code; + pyodide._api.pyodide_code.eval_code_async; + pyodide._api.pyodide_code.find_imports; pyodide.pyodide_py.register_js_module; pyodide.pyodide_py.unregister_js_module; - pyodide.pyodide_py.find_imports; pyodide._api.importlib.invalidate_caches; pyodide._api.package_loader.unpack_buffer; pyodide._api.package_loader.get_dynlibs; diff --git a/pyodide-test-runner/pyodide_test_runner/tests/test_decorator.py b/pyodide-test-runner/pyodide_test_runner/tests/test_decorator.py index 77b263a10..40a15e60a 100644 --- a/pyodide-test-runner/pyodide_test_runner/tests/test_decorator.py +++ b/pyodide-test-runner/pyodide_test_runner/tests/test_decorator.py @@ -238,7 +238,7 @@ def test_run_in_pyodide_alias(request): def test_pickle_jsexception(selenium): import pickle - from pyodide import run_js + from pyodide.code import run_js pickle.dumps(run_js("new Error('hi');")) @@ -250,7 +250,7 @@ def test_raises_jsexception(selenium): @run_in_pyodide def raise_jsexception(selenium): - from pyodide import run_js + from pyodide.code import run_js run_js("throw new Error('hi');") diff --git a/src/js/api.ts b/src/js/api.ts index 129771f01..e7ebfe049 100644 --- a/src/js/api.ts +++ b/src/js/api.ts @@ -51,7 +51,7 @@ API.runPythonInternal = function (code: string): any { let runPythonPositionalGlobalsDeprecationWarned = false; /** - * Runs a string of Python code from JavaScript, using :any:`pyodide.eval_code` + * Runs a string of Python code from JavaScript, using :any:`pyodide.code.eval_code` * to evaluate the code. If the last statement in the Python code is an * expression (and the code doesn't end with a semicolon), the value of the * expression is returned. @@ -68,7 +68,7 @@ let runPythonPositionalGlobalsDeprecationWarned = false; * @param options.globals An optional Python dictionary to use as the globals. * Defaults to :any:`pyodide.globals`. * @returns The result of the Python code translated to JavaScript. See the - * documentation for :any:`pyodide.eval_code` for more info. + * documentation for :any:`pyodide.code.eval_code` for more info. */ export function runPython( code: string, @@ -86,14 +86,14 @@ export function runPython( if (!options.globals) { options.globals = API.globals; } - return API.pyodide_py.eval_code(code, options.globals); + return API.pyodide_code.eval_code(code, options.globals); } API.runPython = runPython; /** * Inspect a Python code chunk and use :js:func:`pyodide.loadPackage` to install * any known packages that the code chunk imports. Uses the Python API - * :func:`pyodide.find\_imports` to inspect the code. + * :func:`pyodide.code.find\_imports` to inspect the code. * * For example, given the following code as input * @@ -116,7 +116,7 @@ export async function loadPackagesFromImports( messageCallback?: (msg: string) => void, errorCallback?: (err: string) => void ) { - let pyimports = API.pyodide_py.find_imports(code); + let pyimports = API.pyodide_code.find_imports(code); let imports; try { imports = pyimports.toJs(); @@ -141,7 +141,7 @@ export async function loadPackagesFromImports( /** * Run a Python code string with top level await using - * :any:`pyodide.eval_code_async` to evaluate the code. Returns a promise which + * :any:`pyodide.code.eval_code_async` to evaluate the code. Returns a promise which * resolves when execution completes. If the last statement in the Python code * is an expression (and the code doesn't end with a semicolon), the returned * promise will resolve to the value of this expression. @@ -196,7 +196,7 @@ export async function runPythonAsync( if (!options.globals) { options.globals = API.globals; } - return await API.pyodide_py.eval_code_async(code, options.globals); + return await API.pyodide_code.eval_code_async(code, options.globals); } API.runPythonAsync = runPythonAsync; diff --git a/src/js/pyodide.ts b/src/js/pyodide.ts index e6d5bf4d8..aa3aa108e 100644 --- a/src/js/pyodide.ts +++ b/src/js/pyodide.ts @@ -128,6 +128,7 @@ function finalizeBootstrap(API: any, config: ConfigType) { // pyodide_py code (Otherwise it's very hard to keep track of which things // aren't set up yet.) API.pyodide_py = import_module("pyodide"); + API.pyodide_code = import_module("pyodide.code"); API.package_loader = import_module("pyodide._package_loader"); API.version = API.pyodide_py.__version__; diff --git a/src/py/pyodide/__init__.py b/src/py/pyodide/__init__.py index 3a9a9acba..489c9e894 100644 --- a/src/py/pyodide/__init__.py +++ b/src/py/pyodide/__init__.py @@ -11,13 +11,6 @@ # pytest mocks for js or pyodide_js, so make sure to test "if IN_BROWSER" before # importing from these. -from _pyodide._base import ( - CodeRunner, - eval_code, - eval_code_async, - find_imports, - should_quiet, -) from _pyodide._importhook import register_js_module, unregister_js_module from . import _state # noqa: F401 @@ -39,9 +32,22 @@ from ._core import ( destroy_proxies, to_js, ) -from ._run_js import run_js +from .code import CodeRunner # noqa: F401 +from .code import eval_code # noqa: F401 +from .code import eval_code_async # noqa: F401 +from .code import find_imports # noqa: F401 +from .code import should_quiet # noqa: F401 from .http import open_url +DEPRECATED_LIST = { + "CodeRunner": "code", + "eval_code": "code", + "eval_code_async": "code", + "find_imports": "code", + "should_quiet": "code", +} + + if IN_BROWSER: import asyncio @@ -49,31 +55,26 @@ if IN_BROWSER: asyncio.set_event_loop_policy(WebLoopPolicy()) +from warnings import warn __version__ = "0.21.0.dev0" + __all__ = [ - "CodeRunner", "ConversionError", "JsException", "JsProxy", "add_event_listener", "clear_interval", "clear_timeout", - "console", "create_once_callable", "create_proxy", "destroy_proxies", - "eval_code", - "eval_code_async", - "find_imports", "open_url", "register_js_module", "remove_event_listener", - "run_js", "set_interval", "set_timeout", - "should_quiet", "to_js", "unregister_js_module", ] @@ -81,3 +82,21 @@ __all__ = [ def __dir__() -> list[str]: return __all__ + + +for name in DEPRECATED_LIST: + globals()[f"_deprecated_{name}"] = globals()[name] + del globals()[name] + + +def __getattr__(name): + if name in DEPRECATED_LIST: + warn( + f"pyodide.{name} has been moved to pyodide.{DEPRECATED_LIST[name]}.{name} " + "Accessing it through the pyodide module is deprecated.", + FutureWarning, + ) + # Put the name back so we won't warn next time this name is accessed + globals()[name] = globals()[f"_deprecated_{name}"] + return globals()[name] + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/py/pyodide/code.py b/src/py/pyodide/code.py new file mode 100644 index 000000000..a259a7024 --- /dev/null +++ b/src/py/pyodide/code.py @@ -0,0 +1,35 @@ +from typing import Any + +from _pyodide._base import ( + CodeRunner, + eval_code, + eval_code_async, + find_imports, + should_quiet, +) + + +def run_js(code: str, /) -> Any: + """ + A wrapper for the JavaScript 'eval' function. + + Runs 'code' as a Javascript code string and returns the result. Unlike + JavaScript's 'eval', if 'code' is not a string we raise a TypeError. + """ + from js import eval as eval_ + + if not isinstance(code, str): + raise TypeError( + f"argument should have type 'string' not type '{type(code).__name__}'" + ) + return eval_(code) + + +__all__ = [ + "CodeRunner", + "eval_code", + "eval_code_async", + "find_imports", + "should_quiet", + "run_js", +] diff --git a/src/tests/test_asyncio.py b/src/tests/test_asyncio.py index b1c558043..956514857 100644 --- a/src/tests/test_asyncio.py +++ b/src/tests/test_asyncio.py @@ -3,7 +3,7 @@ import time import pytest -from pyodide import eval_code_async +from pyodide.code import eval_code_async def test_await_jsproxy(selenium): @@ -352,7 +352,7 @@ def test_await_pyproxy_eval_async(selenium): assert ( selenium.run_js( """ - let c = pyodide.pyodide_py.eval_code_async("1+1"); + let c = pyodide._api.pyodide_code.eval_code_async("1+1"); let result = await c; c.destroy(); return result; @@ -365,7 +365,7 @@ def test_await_pyproxy_eval_async(selenium): selenium.run_js( """ let finally_occurred = false; - let c = pyodide.pyodide_py.eval_code_async("1+1"); + let c = pyodide._api.pyodide_code.eval_code_async("1+1"); let result = await c.finally(() => { finally_occurred = true; }); c.destroy(); return [result, finally_occurred]; @@ -379,7 +379,7 @@ def test_await_pyproxy_eval_async(selenium): """ let finally_occurred = false; let err_occurred = false; - let c = pyodide.pyodide_py.eval_code_async("raise ValueError('hi')"); + let c = pyodide._api.pyodide_code.eval_code_async("raise ValueError('hi')"); try { let result = await c.finally(() => { finally_occurred = true; }); } catch(e){ @@ -394,7 +394,7 @@ def test_await_pyproxy_eval_async(selenium): assert selenium.run_js( """ - let c = pyodide.pyodide_py.eval_code_async("raise ValueError('hi')"); + let c = pyodide._api.pyodide_code.eval_code_async("raise ValueError('hi')"); try { return await c.catch(e => e.constructor.name === "PythonError"); } finally { @@ -405,7 +405,7 @@ def test_await_pyproxy_eval_async(selenium): assert selenium.run_js( """ - let c = pyodide.pyodide_py.eval_code_async(` + let c = pyodide._api.pyodide_code.eval_code_async(` from js import fetch await (await fetch('repodata.json')).json() `); diff --git a/src/tests/test_browser_apis.py b/src/tests/test_browser_apis.py index cf35bc98d..ad1f16eb6 100644 --- a/src/tests/test_browser_apis.py +++ b/src/tests/test_browser_apis.py @@ -173,7 +173,7 @@ async def test_start_multiple_intervals_and_clear_one(selenium): @run_in_pyodide async def test_trigger_event_listener(selenium): - from pyodide import run_js + from pyodide.code import run_js x = run_js( """ @@ -226,7 +226,7 @@ x; @run_in_pyodide async def test_remove_event_listener(selenium): - from pyodide import run_js + from pyodide.code import run_js x = run_js( """ @@ -277,7 +277,7 @@ x; @run_in_pyodide async def test_trigger_some_of_multiple_event_listeners(selenium): - from pyodide import run_js + from pyodide.code import run_js x = run_js( """ @@ -347,7 +347,7 @@ x; @run_in_pyodide async def test_remove_event_listener_twice(selenium): - from pyodide import run_js + from pyodide.code import run_js x = run_js( """ @@ -404,7 +404,7 @@ x; @run_in_pyodide async def test_nonexistant_remove_event_listener(selenium): - from pyodide import run_js + from pyodide.code import run_js x = run_js( """ diff --git a/src/tests/test_console.py b/src/tests/test_console.py index 0b497980d..4fcc03bf9 100644 --- a/src/tests/test_console.py +++ b/src/tests/test_console.py @@ -5,7 +5,8 @@ import time import pytest from pyodide_test_runner import run_in_pyodide -from pyodide import CodeRunner, console # noqa: E402 +from pyodide import console +from pyodide.code import CodeRunner # noqa: E402 from pyodide.console import Console, _CommandCompiler, _Compile # noqa: E402 diff --git a/src/tests/test_jsproxy.py b/src/tests/test_jsproxy.py index 35dc448bf..4e9ffd74b 100644 --- a/src/tests/test_jsproxy.py +++ b/src/tests/test_jsproxy.py @@ -146,7 +146,7 @@ def test_jsproxy_class(selenium): def test_jsproxy_map(selenium): import pytest - from pyodide import run_js + from pyodide.code import run_js TEST = run_js('new Map([["x", 42], ["y", 43]])') assert "y" in TEST @@ -671,7 +671,7 @@ def test_register_jsmodule_docs_example(selenium_standalone): @run_in_pyodide def test_object_entries_keys_values(selenium): - from pyodide import run_js + from pyodide.code import run_js x = run_js("({ a : 2, b : 3, c : 4 })") assert x.object_entries().to_py() == [["a", 2], ["b", 3], ["c", 4]] @@ -861,7 +861,7 @@ def test_mixins_errors_2(selenium): def test_mixins_errors_3(selenium): from unittest import TestCase - from pyodide import run_js + from pyodide.code import run_js raises = TestCase().assertRaises @@ -897,7 +897,7 @@ def test_mixins_errors_3(selenium): def test_mixins_errors_4(selenium): from unittest import TestCase - from pyodide import run_js + from pyodide.code import run_js raises = TestCase().assertRaises @@ -1049,7 +1049,7 @@ def test_buffer_assign_back(selenium): @run_in_pyodide def test_buffer_conversions(selenium): - from pyodide import run_js + from pyodide.code import run_js s, jsbytes = run_js( """ @@ -1067,7 +1067,7 @@ def test_buffer_conversions(selenium): @run_in_pyodide def test_tostring_encoding(selenium): - from pyodide import run_js + from pyodide.code import run_js bytes = run_js( """ @@ -1083,7 +1083,7 @@ def test_tostring_encoding(selenium): def test_tostring_error(selenium): from unittest import TestCase - from pyodide import run_js + from pyodide.code import run_js raises = TestCase().assertRaises @@ -1100,7 +1100,7 @@ def test_tostring_error(selenium): @run_in_pyodide def test_duck_buffer_method_presence(selenium): - from pyodide import run_js + from pyodide.code import run_js bytes = run_js( "new Uint8Array([207, 240, 232, 226, 229, 242, 44, 32, 236, 232, 240, 33])" diff --git a/src/tests/test_pyodide.py b/src/tests/test_pyodide.py index 623e54a62..dca6b64de 100644 --- a/src/tests/test_pyodide.py +++ b/src/tests/test_pyodide.py @@ -5,7 +5,7 @@ from typing import Any, Sequence import pytest from pyodide_test_runner import run_in_pyodide -from pyodide import CodeRunner, eval_code, find_imports, should_quiet # noqa: E402 +from pyodide.code import CodeRunner, eval_code, find_imports, should_quiet # noqa: E402 def _strip_assertions_stderr(messages: Sequence[str]) -> list[str]: @@ -298,11 +298,11 @@ def test_monkeypatch_eval_code(selenium): selenium.run( """ import pyodide - old_eval_code = pyodide.eval_code + old_eval_code = pyodide.code.eval_code x = 3 def eval_code(code, ns): return [ns["x"], old_eval_code(code, ns)] - pyodide.eval_code = eval_code + pyodide.code.eval_code = eval_code """ ) assert selenium.run("x = 99; 5") == [3, 5] @@ -310,7 +310,7 @@ def test_monkeypatch_eval_code(selenium): finally: selenium.run( """ - pyodide.eval_code = old_eval_code + pyodide.code.eval_code = old_eval_code """ ) @@ -1158,7 +1158,7 @@ def test_sys_path0(selenium): def test_run_js(selenium): from unittest import TestCase - from pyodide import run_js + from pyodide.code import run_js raises = TestCase().assertRaises @@ -1171,3 +1171,24 @@ def test_run_js(selenium): from js import x assert x == 77 + + +@run_in_pyodide(packages=["pytest"]) +def test_moved_deprecation_warnings(selenium_standalone): + import pytest + + import pyodide + + with pytest.warns() as record: + deprecated_funcs = [ + "CodeRunner", + "eval_code", + "eval_code_async", + "find_imports", + "should_quiet", + ] + for func in deprecated_funcs: + getattr(pyodide, func) + assert len(record) == 5 + for func in deprecated_funcs: + getattr(pyodide, func) diff --git a/src/tests/test_typeconversions.py b/src/tests/test_typeconversions.py index c6ac0803d..bc52422f3 100644 --- a/src/tests/test_typeconversions.py +++ b/src/tests/test_typeconversions.py @@ -18,7 +18,7 @@ from pyodide_test_runner.hypothesis import ( def test_string_conversion(selenium_module_scope, s): @run_in_pyodide def main(selenium, sbytes): - from pyodide import run_js + from pyodide.code import run_js run_js("self.encoder = new TextEncoder()") run_js("self.decoder = new TextDecoder('utf8', {ignoreBOM: true})") @@ -44,7 +44,7 @@ def test_string_conversion(selenium_module_scope, s): @std_hypothesis_settings @run_in_pyodide def test_string_conversion2(selenium, s): - from pyodide import run_js + from pyodide.code import run_js run_js("self.encoder = new TextEncoder()") run_js("self.decoder = new TextDecoder('utf8', {ignoreBOM: true})") @@ -66,7 +66,7 @@ def test_string_conversion2(selenium, s): @run_in_pyodide def test_large_string_conversion(selenium): - from pyodide import run_js + from pyodide.code import run_js longstr = run_js('"ab".repeat(200_000)') res = longstr.count("ab") @@ -115,7 +115,7 @@ def test_number_conversions(selenium_module_scope, n): @run_in_pyodide def test_nan_conversions(selenium): - from pyodide import run_js + from pyodide.code import run_js jsnan = run_js("NaN") from math import isnan @@ -179,7 +179,7 @@ def test_big_int_conversions2(selenium_module_scope, n): def main(selenium, s): import json - from pyodide import run_js + from pyodide.code import run_js x_py = json.loads(s) x_js, check = run_js( @@ -211,7 +211,7 @@ def test_big_int_conversions3(selenium_module_scope, n, exp): def main(selenium, s): import json - from pyodide import run_js + from pyodide.code import run_js x_py = json.loads(s) run_js( @@ -251,7 +251,7 @@ def test_big_int_conversions3(selenium_module_scope, n, exp): def test_hyp_py2js2py(selenium, obj): import __main__ - from pyodide import run_js + from pyodide.code import run_js __main__.obj = obj @@ -278,7 +278,7 @@ def test_hyp_py2js2py(selenium, obj): def test_hyp_py2js2py_2(selenium, obj): import __main__ - from pyodide import run_js + from pyodide.code import run_js __main__.o = obj try: @@ -292,7 +292,7 @@ def test_hyp_py2js2py_2(selenium, obj): def test_big_integer_py2js2py(selenium, a): import __main__ - from pyodide import run_js + from pyodide.code import run_js __main__.a = a try: @@ -311,7 +311,7 @@ def test_big_integer_py2js2py(selenium, a): def test_hyp_tojs_no_crash(selenium, obj): import __main__ - from pyodide import run_js + from pyodide.code import run_js __main__.x = obj try: @@ -345,7 +345,7 @@ def test_hyp_tojs_no_crash(selenium, obj): ) @run_in_pyodide def test_python2js1(selenium, py, js): - from pyodide import run_js + from pyodide.code import run_js assert run_js( f""" @@ -356,7 +356,7 @@ def test_python2js1(selenium, py, js): @run_in_pyodide def test_python2js2(selenium): - from pyodide import run_js + from pyodide.code import run_js assert ( list( @@ -375,7 +375,7 @@ def test_python2js2(selenium): @run_in_pyodide def test_python2js3(selenium): - from pyodide import run_js + from pyodide.code import run_js l = [7, 9, 13] result = run_js( @@ -391,7 +391,7 @@ def test_python2js3(selenium): @run_in_pyodide def test_python2js4(selenium): - from pyodide import run_js + from pyodide.code import run_js assert ( list( @@ -411,7 +411,7 @@ def test_python2js4(selenium): @run_in_pyodide def test_python2js5(selenium): - from pyodide import run_js + from pyodide.code import run_js assert run_js("(x) => x.tell()")(open("/foo.txt", "wb")) == 0 @@ -467,7 +467,7 @@ def test_python2js_track_proxies(selenium): @run_in_pyodide def test_wrong_way_track_proxies(selenium): - from pyodide import run_js + from pyodide.code import run_js checkDestroyed = run_js( """ @@ -535,7 +535,8 @@ def test_wrong_way_conversions1(selenium): @run_in_pyodide def test_wrong_way_conversions2(selenium): - from pyodide import run_js, to_js + from pyodide import to_js + from pyodide.code import run_js [astr, bstr] = run_js( """ @@ -550,7 +551,8 @@ def test_wrong_way_conversions2(selenium): @run_in_pyodide def test_wrong_way_conversions3(selenium): - from pyodide import run_js, to_js + from pyodide import to_js + from pyodide.code import run_js class Test: pass @@ -577,7 +579,8 @@ def test_wrong_way_conversions4(selenium): def test_dict_converter1(selenium): import json - from pyodide import run_js, to_js + from pyodide import to_js + from pyodide.code import run_js arrayFrom = run_js("Array.from") d = {x: x + 2 for x in range(5)} @@ -598,7 +601,7 @@ def test_dict_converter1(selenium): def test_dict_converter2(selenium): import json - from pyodide import run_js + from pyodide.code import run_js d = {x: x + 2 for x in range(5)} constructor, serialized = run_js( @@ -619,7 +622,8 @@ def test_dict_converter3(selenium): import json from js import Object - from pyodide import run_js, to_js + from pyodide import to_js + from pyodide.code import run_js d = {x: x + 2 for x in range(5)} @@ -638,7 +642,7 @@ def test_dict_converter3(selenium): def test_dict_converter4(selenium): import json - from pyodide import run_js + from pyodide.code import run_js d = {x: x + 2 for x in range(5)} @@ -665,7 +669,7 @@ def test_python2js_long_ints(selenium, formula): @run_in_pyodide def test_python2js_long_ints2(selenium): - from pyodide import run_js + from pyodide.code import run_js assert run_js( """ @@ -753,7 +757,7 @@ def test_js2python(selenium): ) @run_in_pyodide def test_js2python_bool(selenium, jsval, is_truthy): - from pyodide import run_js + from pyodide.code import run_js assert bool(run_js(jsval)) is is_truthy @@ -774,7 +778,7 @@ def test_js2python_bool(selenium, jsval, is_truthy): ) @run_in_pyodide def test_typed_arrays(selenium, jstype, pytype): - from pyodide import run_js + from pyodide.code import run_js array = run_js(f"new {jstype}([1, 2, 3, 4]);").to_py() print(array.format, array.tolist(), array.tobytes()) @@ -787,7 +791,7 @@ def test_typed_arrays(selenium, jstype, pytype): @run_in_pyodide def test_array_buffer(selenium): - from pyodide import run_js + from pyodide.code import run_js array = run_js("new ArrayBuffer(100);").to_py() assert len(array.tobytes()) == 100 @@ -869,7 +873,7 @@ def test_dict_py2js2py(selenium): def test_jsproxy_attribute_error(selenium): import pytest - from pyodide import run_js + from pyodide.code import run_js point = run_js( """ @@ -909,7 +913,7 @@ def test_javascript_error(selenium): @run_in_pyodide def test_javascript_error_back_to_js(selenium): - from pyodide import run_js + from pyodide.code import run_js err = run_js('self.err = new Error("This is a js error"); err') assert type(err).__name__ == "JsException" @@ -979,7 +983,7 @@ def test_python2js_with_depth(selenium): def test_tojs1(selenium, ty): import json - from pyodide import run_js + from pyodide.code import run_js l = [1, 2, 3] x = ty(l) @@ -992,7 +996,7 @@ def test_tojs1(selenium, ty): def test_tojs2(selenium): import json - from pyodide import run_js + from pyodide.code import run_js o = [(1, 2), (3, 4), [5, 6], {2: 3, 4: 9}] @@ -1129,7 +1133,7 @@ def test_tojs9(selenium): @run_in_pyodide def test_to_py1(selenium): - from pyodide import run_js + from pyodide.code import run_js a = run_js( """ @@ -1149,7 +1153,7 @@ def test_to_py1(selenium): @run_in_pyodide def test_to_py2(selenium): - from pyodide import run_js + from pyodide.code import run_js a = run_js( """ @@ -1169,7 +1173,7 @@ def test_to_py2(selenium): @run_in_pyodide def test_to_py3(selenium): - from pyodide import run_js + from pyodide.code import run_js a = run_js( """ @@ -1200,7 +1204,8 @@ def test_to_py3(selenium): def test_to_py4(selenium, obj, msg): import pytest - from pyodide import ConversionError, JsException, run_js + from pyodide import ConversionError, JsException + from pyodide.code import run_js a = run_js(f"new {obj}") @@ -1210,7 +1215,7 @@ def test_to_py4(selenium, obj, msg): @run_in_pyodide def test_to_py_default_converter(selenium): - from pyodide import run_js + from pyodide.code import run_js [r1, r2] = run_js( """ @@ -1254,7 +1259,7 @@ def test_to_py_default_converter(selenium): def test_to_py_default_converter2(selenium): from typing import Any - from pyodide import run_js + from pyodide.code import run_js [p1, p2] = run_js( """ @@ -1332,7 +1337,8 @@ def test_to_js_default_converter2(selenium): import pytest from js import JSON, Array - from pyodide import JsException, run_js, to_js + from pyodide import JsException, to_js + from pyodide.code import run_js class Pair: def __init__(self, first, second): @@ -1435,7 +1441,7 @@ def test_buffer_format_string(selenium): def test_object_with_null_constructor(selenium): from unittest import TestCase - from pyodide import run_js + from pyodide.code import run_js o = run_js("Object.create(null)") with TestCase().assertRaises(TypeError): @@ -1458,7 +1464,7 @@ def test_dict_converter_cache(selenium): def test_very_large_length(selenium, n): from unittest import TestCase - from pyodide import run_js + from pyodide.code import run_js raises = TestCase().assertRaises( OverflowError, msg=f"length {n} of object is larger than INT_MAX (2147483647)" @@ -1484,7 +1490,7 @@ def test_very_large_length(selenium, n): def test_negative_length(selenium, n): from unittest import TestCase - from pyodide import run_js + from pyodide.code import run_js raises = TestCase().assertRaises( ValueError, msg=f"length {n} of object is negative"