mirror of https://github.com/pyodide/pyodide.git
Deprecate pyodide.pyimport (#1367)
This commit is contained in:
parent
e408dede25
commit
f2d6137673
|
@ -51,6 +51,8 @@ substitutions:
|
|||
access, then the wrapper has `get`, `set`, `has`, and `delete` methods which do
|
||||
`obj[key]`, `obj[key] = val`, `key in obj` and `del obj[key]` respectively.
|
||||
[#1175](https://github.com/iodide-project/pyodide/pull/1175)
|
||||
- {{ API }} The `pyodide.pyimport` function is deprecated in favor of using
|
||||
`pyodide.globals.get('key')`. [#1367](https://github.com/iodide-project/pyodide/pull/1367)
|
||||
|
||||
### Fixed
|
||||
- {{ Fix }} getattr and dir on JsProxy now report consistent results and include all
|
||||
|
|
|
@ -125,19 +125,18 @@ Create and save a test `index.html` page with the following contents:
|
|||
## Accessing Python scope from Javascript
|
||||
|
||||
You can also access from Javascript all functions and variables defined in
|
||||
Python by using the {any}`pyodide.pyimport` api or the {any}`pyodide.globals`
|
||||
object.
|
||||
Python by using the {any}`pyodide.globals` object.
|
||||
|
||||
For example, if you run the code `x = numpy.ones([3,3])` in Python, you can
|
||||
access the variable ``x`` from Javascript in your browser's developer console
|
||||
as either `pyodide.globals.get("x")` or `pyodide.pyimport('x')`. The same goes
|
||||
as `pyodide.globals.get("x")`. The same goes
|
||||
for functions and imports. See {ref}`type-translations` for more details.
|
||||
|
||||
You can try it yourself in the browser console:
|
||||
```js
|
||||
pyodide.runPython(`import numpy`);
|
||||
pyodide.runPython(`x=numpy.ones((3, 4))`);
|
||||
pyodide.globals.get('x').toJs(); // or pyodide.pyimport('x').toJs();
|
||||
pyodide.globals.get('x').toJs();
|
||||
// >>> [ Float64Array(4), Float64Array(4), Float64Array(4) ]
|
||||
|
||||
// create the same 3x4 ndarray from js
|
||||
|
|
|
@ -16,7 +16,7 @@ converted using the explicit conversion methods `JsProxy.to_py` and
|
|||
Python to Javascript translations occur:
|
||||
|
||||
- when returning the final expression from a {any}`pyodide.runPython` call,
|
||||
- when using {any}`pyodide.pyimport`,
|
||||
- when using `pyodide.globals.get('key')`,
|
||||
- when passing arguments to a Javascript function called from Python,
|
||||
- when returning the results of a Python function called from Javascript,
|
||||
- when accessing an attribute of a `PyProxy`
|
||||
|
@ -195,7 +195,7 @@ object exist in Python either, then the Python garbage collector can eventually
|
|||
collect it.
|
||||
|
||||
```javascript
|
||||
let foo = pyodide.pyimport('foo');
|
||||
let foo = pyodide.globals.get('foo');
|
||||
foo();
|
||||
foo.destroy();
|
||||
foo(); // throws Error: Object has already been destroyed
|
||||
|
@ -220,7 +220,7 @@ pyodide.runPython(`
|
|||
import sys
|
||||
print(sys.getrefcount(d)) # prints 2
|
||||
`);
|
||||
let d = pyodide.pyimport("d");
|
||||
let d = pyodide.globals.get("d");
|
||||
// Leak three temporary bound "get" methods!
|
||||
let l = [d.get("a", 0), d.get("b", 0), d.get("c", 0)];
|
||||
d.destroy(); // Try to free dict
|
||||
|
@ -232,7 +232,7 @@ pyodide.runPython(`
|
|||
```
|
||||
Here is how we can do this without leaking:
|
||||
```pyodide
|
||||
let d = pyodide.pyimport("d");
|
||||
let d = pyodide.globals.get("d");
|
||||
let d_get = d.get; // this time avoid the leak
|
||||
let l = [d_get("a", 0), d_get("b", 0), d_get("c", 0)];
|
||||
d.destroy();
|
||||
|
@ -247,7 +247,7 @@ Another exciting inconsistency is that `d.set` is a __Javascript__ method not a
|
|||
PyProxy of a bound method, so using it has no effect on refcounts or memory
|
||||
reclamation and it cannot be destroyed.
|
||||
```pyodide
|
||||
let d = pyodide.pyimport("d");
|
||||
let d = pyodide.globals.get("d");
|
||||
let d_set = d.set;
|
||||
d_set("x", 7);
|
||||
pyodide.runPython(`
|
||||
|
@ -379,11 +379,11 @@ implementation for Javascript.
|
|||
## Importing Python objects into Javascript
|
||||
|
||||
A Python object in the `__main__` global scope can imported into Javascript
|
||||
using the {any}`pyodide.pyimport` function. Given the name of the Python object
|
||||
to import, `pyimport` returns the object translated to Javascript.
|
||||
using the `pyodide.globals.get` method. Given the name of the Python object
|
||||
to import, it returns the object translated to Javascript.
|
||||
|
||||
```js
|
||||
let sys = pyodide.pyimport('sys');
|
||||
let sys = pyodide.globals.get('sys');
|
||||
```
|
||||
|
||||
As always, if the result is a `PyProxy` and you care about not leaking the Python
|
||||
|
|
|
@ -2,12 +2,14 @@ def test_numpy(selenium):
|
|||
selenium.load_package("numpy")
|
||||
selenium.run("import numpy")
|
||||
selenium.run("x = numpy.ones((32, 64))")
|
||||
assert selenium.run_js("return pyodide.pyimport('x').toJs().length == 32")
|
||||
assert selenium.run_js("return pyodide.globals.get('x').toJs().length == 32")
|
||||
for i in range(32):
|
||||
assert selenium.run_js(f"return pyodide.pyimport('x').toJs()[{i}].length == 64")
|
||||
assert selenium.run_js(
|
||||
f"return pyodide.globals.get('x').toJs()[{i}].length == 64"
|
||||
)
|
||||
for j in range(64):
|
||||
assert selenium.run_js(
|
||||
f"return pyodide.pyimport('x').toJs()[{i}][{j}] == 1"
|
||||
f"return pyodide.globals.get('x').toJs()[{i}][{j}] == 1"
|
||||
)
|
||||
|
||||
|
||||
|
@ -51,7 +53,7 @@ def test_python2js_numpy_dtype(selenium_standalone):
|
|||
for k in range(2):
|
||||
assert (
|
||||
selenium.run_js(
|
||||
f"return pyodide.pyimport('x').toJs()[{i}][{j}][{k}]"
|
||||
f"return pyodide.globals.get('x').toJs()[{i}][{j}][{k}]"
|
||||
)
|
||||
== expected_result[i][j][k]
|
||||
)
|
||||
|
@ -78,7 +80,7 @@ def test_python2js_numpy_dtype(selenium_standalone):
|
|||
)
|
||||
assert_equal()
|
||||
classname = selenium.run_js(
|
||||
"return pyodide.pyimport('x').toJs()[0][0].constructor.name"
|
||||
"return pyodide.globals.get('x').toJs()[0][0].constructor.name"
|
||||
)
|
||||
if order == "C" and dtype not in ("uint64", "int64"):
|
||||
# Here we expect a TypedArray subclass, such as Uint8Array, but
|
||||
|
@ -94,7 +96,7 @@ def test_python2js_numpy_dtype(selenium_standalone):
|
|||
)
|
||||
assert_equal()
|
||||
classname = selenium.run_js(
|
||||
"return pyodide.pyimport('x').toJs()[0][0].constructor.name"
|
||||
"return pyodide.globals.get('x').toJs()[0][0].constructor.name"
|
||||
)
|
||||
if order == "C" and dtype in ("int8", "uint8"):
|
||||
# Here we expect a TypedArray subclass, such as Uint8Array, but
|
||||
|
@ -147,7 +149,7 @@ def test_python2js_numpy_scalar(selenium_standalone):
|
|||
assert (
|
||||
selenium.run_js(
|
||||
"""
|
||||
return pyodide.pyimport('x') == 1
|
||||
return pyodide.globals.get('x') == 1
|
||||
"""
|
||||
)
|
||||
is True
|
||||
|
@ -160,7 +162,7 @@ def test_python2js_numpy_scalar(selenium_standalone):
|
|||
assert (
|
||||
selenium.run_js(
|
||||
"""
|
||||
return pyodide.pyimport('x') == 1
|
||||
return pyodide.globals.get('x') == 1
|
||||
"""
|
||||
)
|
||||
is True
|
||||
|
@ -176,7 +178,7 @@ def test_runpythonasync_numpy(selenium_standalone):
|
|||
)
|
||||
for i in range(5):
|
||||
assert selenium_standalone.run_js(
|
||||
f"return pyodide.pyimport('x').toJs()[{i}] == 0"
|
||||
f"return pyodide.globals.get('x').toJs()[{i}] == 0"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -435,9 +435,8 @@ globalThis.languagePluginLoader = (async () => {
|
|||
*
|
||||
* An alias to the global Python namespace.
|
||||
*
|
||||
* An object whose attributes are members of the Python global namespace. This
|
||||
* is an alternative to :meth:`pyimport`. For example, to access the ``foo``
|
||||
* Python object from Javascript use
|
||||
* An object whose attributes are members of the Python global namespace.
|
||||
* For example, to access the ``foo`` Python object from Javascript use
|
||||
* ``pyodide.globals.get("foo")``
|
||||
*
|
||||
* @type {PyProxy}
|
||||
|
@ -543,12 +542,21 @@ globalThis.languagePluginLoader = (async () => {
|
|||
|
||||
/**
|
||||
* Access a Python object in the global namespace from Javascript.
|
||||
*
|
||||
* Note: this function is deprecated and will be removed in version 0.18.0.
|
||||
* Use pyodide.globals.get('key') instead.
|
||||
*
|
||||
* @param {string} name Python variable name
|
||||
* @returns If the Python object is an immutable type (string, number,
|
||||
* boolean), it is converted to Javascript and returned. For other types, a
|
||||
* ``PyProxy`` object is returned.
|
||||
*/
|
||||
Module.pyimport = name => Module.globals.get(name);
|
||||
Module.pyimport = name => {
|
||||
console.warn(
|
||||
"Access to the Python global namespace via pyodide.pyimport is deprecated and " +
|
||||
"will be removed in version 0.18.0. Use pyodide.globals.get('key') instead.");
|
||||
return Module.globals.get(name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs Python code, possibly asynchronously loading any known packages that
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<body>
|
||||
<script>
|
||||
languagePluginLoader.then(() => {
|
||||
let namespace = pyodide.pyimport("dict")();
|
||||
let namespace = pyodide.globals.get("dict")();
|
||||
pyodide.runPython(`
|
||||
import sys
|
||||
import js
|
||||
|
|
|
@ -12,7 +12,7 @@ def test_pyproxy(selenium):
|
|||
f = Foo()
|
||||
"""
|
||||
)
|
||||
selenium.run_js("window.f = pyodide.pyimport('f')")
|
||||
selenium.run_js("window.f = pyodide.globals.get('f')")
|
||||
assert selenium.run_js("return f.type") == "Foo"
|
||||
assert selenium.run_js("return f.get_value(2)") == 128
|
||||
assert selenium.run_js("return f.bar") == 42
|
||||
|
@ -53,9 +53,11 @@ def test_pyproxy(selenium):
|
|||
]
|
||||
)
|
||||
assert selenium.run("hasattr(f, 'baz')")
|
||||
selenium.run_js("delete pyodide.pyimport('f').baz")
|
||||
selenium.run_js("delete pyodide.globals.get('f').baz")
|
||||
assert not selenium.run("hasattr(f, 'baz')")
|
||||
assert selenium.run_js("return pyodide.pyimport('f').toString()").startswith("<Foo")
|
||||
assert selenium.run_js("return pyodide.globals.get('f').toString()").startswith(
|
||||
"<Foo"
|
||||
)
|
||||
|
||||
|
||||
def test_pyproxy_refcount(selenium):
|
||||
|
@ -124,7 +126,7 @@ def test_pyproxy_destroy(selenium):
|
|||
with pytest.raises(selenium.JavascriptException, match=msg):
|
||||
selenium.run_js(
|
||||
"""
|
||||
let f = pyodide.pyimport('f');
|
||||
let f = pyodide.globals.get('f');
|
||||
console.assert(f.get_value(1) === 64);
|
||||
f.destroy();
|
||||
f.get_value();
|
||||
|
|
|
@ -35,18 +35,18 @@ def test_import_js(selenium):
|
|||
assert "window" in result
|
||||
|
||||
|
||||
def test_pyimport_multiple(selenium):
|
||||
def test_globals_get_multiple(selenium):
|
||||
"""See #1151"""
|
||||
selenium.run("v = 0.123")
|
||||
selenium.run_js("pyodide.pyimport('v')")
|
||||
selenium.run_js("pyodide.pyimport('v')")
|
||||
selenium.run_js("pyodide.globals.get('v')")
|
||||
selenium.run_js("pyodide.globals.get('v')")
|
||||
|
||||
|
||||
def test_pyimport_same(selenium):
|
||||
def test_globals_get_same(selenium):
|
||||
"""See #382"""
|
||||
selenium.run("def func(): return 42")
|
||||
assert selenium.run_js(
|
||||
"return pyodide.pyimport('func') == pyodide.pyimport('func')"
|
||||
"return pyodide.globals.get('func') == pyodide.globals.get('func')"
|
||||
)
|
||||
|
||||
|
||||
|
@ -72,7 +72,7 @@ def test_load_package_after_convert_string(selenium):
|
|||
See #93.
|
||||
"""
|
||||
selenium.run("import sys\n" "x = sys.version")
|
||||
selenium.run_js("let x = pyodide.pyimport('x');\n" "console.log(x);")
|
||||
selenium.run_js("let x = pyodide.globals.get('x');\n" "console.log(x);")
|
||||
selenium.load_package("kiwisolver")
|
||||
selenium.run("import kiwisolver")
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ def test_js2python(selenium):
|
|||
window.jsfalse = false;
|
||||
window.jsarray0 = [];
|
||||
window.jsarray1 = [1, 2, 3];
|
||||
window.jspython = pyodide.pyimport("open");
|
||||
window.jspython = pyodide.globals.get("open");
|
||||
window.jsbytes = new Uint8Array([1, 2, 3]);
|
||||
window.jsfloats = new Float32Array([1, 2, 3]);
|
||||
window.jsobject = new XMLHttpRequest();
|
||||
|
@ -270,7 +270,7 @@ def test_recursive_list_to_js(selenium_standalone):
|
|||
x.append(x)
|
||||
"""
|
||||
)
|
||||
selenium_standalone.run_js("x = pyodide.pyimport('x').toJs();")
|
||||
selenium_standalone.run_js("x = pyodide.globals.get('x').toJs();")
|
||||
|
||||
|
||||
def test_recursive_dict_to_js(selenium_standalone):
|
||||
|
@ -280,7 +280,7 @@ def test_recursive_dict_to_js(selenium_standalone):
|
|||
x[0] = x
|
||||
"""
|
||||
)
|
||||
selenium_standalone.run_js("x = pyodide.pyimport('x').toJs();")
|
||||
selenium_standalone.run_js("x = pyodide.globals.get('x').toJs();")
|
||||
|
||||
|
||||
def test_list_js2py2js(selenium):
|
||||
|
@ -408,7 +408,7 @@ def test_python2js_with_depth(selenium):
|
|||
assert selenium.run_js(
|
||||
"""
|
||||
pyodide.runPython("a = [1, 2, 3]");
|
||||
let res = pyodide.pyimport("a").toJs();
|
||||
let res = pyodide.globals.get("a").toJs();
|
||||
return (Array.isArray(res)) && JSON.stringify(res) === "[1,2,3]";
|
||||
"""
|
||||
)
|
||||
|
@ -416,7 +416,7 @@ def test_python2js_with_depth(selenium):
|
|||
assert selenium.run_js(
|
||||
"""
|
||||
pyodide.runPython("a = (1, 2, 3)");
|
||||
let res = pyodide.pyimport("a").toJs();
|
||||
let res = pyodide.globals.get("a").toJs();
|
||||
return (Array.isArray(res)) && JSON.stringify(res) === "[1,2,3]";
|
||||
"""
|
||||
)
|
||||
|
@ -424,7 +424,7 @@ def test_python2js_with_depth(selenium):
|
|||
assert selenium.run_js(
|
||||
"""
|
||||
pyodide.runPython("a = [(1,2), (3,4), [5, 6], { 2 : 3, 4 : 9}]")
|
||||
let res = pyodide.pyimport("a").toJs();
|
||||
let res = pyodide.globals.get("a").toJs();
|
||||
return Array.isArray(res) && \
|
||||
JSON.stringify(res) === `[[1,2],[3,4],[5,6],{}]` && \
|
||||
JSON.stringify(Array.from(res[3].entries())) === "[[2,3],[4,9]]";
|
||||
|
@ -444,7 +444,7 @@ def test_python2js_with_depth(selenium):
|
|||
selenium.run_js(
|
||||
"""
|
||||
pyodide.runPython("a = [1,[2,[3,[4,[5,[6,[7]]]]]]]")
|
||||
let a = pyodide.pyimport("a");
|
||||
let a = pyodide.globals.get("a");
|
||||
for(let i=0; i < 7; i++){
|
||||
let x = a.toJs(i);
|
||||
for(let j=0; j < i; j++){
|
||||
|
@ -464,7 +464,7 @@ def test_python2js_with_depth(selenium):
|
|||
throw new Error(`Assertion failed: ${msg}`);
|
||||
}
|
||||
}
|
||||
let a = pyodide.pyimport("a");
|
||||
let a = pyodide.globals.get("a");
|
||||
for(let i=0; i < 7; i++){
|
||||
let x = a.toJs(i);
|
||||
for(let j=0; j < i; j++){
|
||||
|
@ -484,7 +484,7 @@ def test_python2js_with_depth(selenium):
|
|||
c = [b, b, b, b, b]
|
||||
`);
|
||||
let total_refs = pyodide._module.hiwire.num_keys();
|
||||
let res = pyodide.pyimport("c").toJs();
|
||||
let res = pyodide.globals.get("c").toJs();
|
||||
let new_total_refs = pyodide._module.hiwire.num_keys();
|
||||
assert(total_refs === new_total_refs);
|
||||
assert(res[0] === res[1]);
|
||||
|
@ -502,7 +502,7 @@ def test_python2js_with_depth(selenium):
|
|||
a.append(b)
|
||||
`);
|
||||
let total_refs = pyodide._module.hiwire.num_keys();
|
||||
let res = pyodide.pyimport("a").toJs();
|
||||
let res = pyodide.globals.get("a").toJs();
|
||||
let new_total_refs = pyodide._module.hiwire.num_keys();
|
||||
assert(total_refs === new_total_refs);
|
||||
assert(res[0][0] === "b");
|
||||
|
@ -690,3 +690,9 @@ def test_to_py(selenium):
|
|||
`);
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def test_pyimport_deprecation(selenium):
|
||||
selenium.run_js("pyodide.runPython('x = 1')")
|
||||
assert selenium.run_js("return pyodide.pyimport('x') === 1")
|
||||
assert "pyodide.pyimport is deprecated and will be removed" in selenium.logs
|
||||
|
|
Loading…
Reference in New Issue