From ba5545cbf1ee16a69e412d4941f0ac9c27375ecb Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Fri, 3 Mar 2023 18:19:43 +0900 Subject: [PATCH] Add private APIs to get Python version before bootstrapping Python (#3625) Use them in Module.preRun to initialize the filesystem. --- Makefile | 3 ++- src/core/pyversion.c | 21 +++++++++++++++++++++ src/core/pyversion.h | 13 +++++++++++++ src/js/module.ts | 11 +++++++---- src/tests/test_pyodide.py | 12 ++++++++++++ 5 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 src/core/pyversion.c create mode 100644 src/core/pyversion.h diff --git a/Makefile b/Makefile index 2f16c56e8..0f8f49046 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,8 @@ dist/libpyodide.a: \ src/core/pyproxy.o \ src/core/python2js_buffer.o \ src/core/python2js.o \ - src/core/pyodide_pre.o + src/core/pyodide_pre.o \ + src/core/pyversion.o emar rcs dist/libpyodide.a $(filter %.o,$^) diff --git a/src/core/pyversion.c b/src/core/pyversion.c new file mode 100644 index 000000000..afd34ca15 --- /dev/null +++ b/src/core/pyversion.c @@ -0,0 +1,21 @@ +#define PY_SSIZE_T_CLEAN +#include "Python.h" +#include + +EMSCRIPTEN_KEEPALIVE int +py_version_major() +{ + return PY_MAJOR_VERSION; +} + +EMSCRIPTEN_KEEPALIVE int +py_version_minor() +{ + return PY_MINOR_VERSION; +} + +EMSCRIPTEN_KEEPALIVE int +py_version_micro() +{ + return PY_MICRO_VERSION; +} diff --git a/src/core/pyversion.h b/src/core/pyversion.h new file mode 100644 index 000000000..e883c187f --- /dev/null +++ b/src/core/pyversion.h @@ -0,0 +1,13 @@ +#ifndef PYVERSION_H +#define PYVERSION_H + +int +py_version_major(); + +int +py_version_minor(); + +int +py_version_micro(); + +#endif /* PYVERSION_H */ diff --git a/src/js/module.ts b/src/js/module.ts index 04e3aaa67..9f826c756 100644 --- a/src/js/module.ts +++ b/src/js/module.ts @@ -130,19 +130,22 @@ function mountLocalDirectories(Module: Module, mounts: string[]) { * @param stdlibPromise A promise that resolves to the standard library. */ function installStdlib(Module: Module, stdlibURL: string) { - // TODO(ryanking13): Get python version from Python.h - const stdlibPromise: Promise = loadBinaryFile(stdlibURL); Module.preRun.push(() => { + /* @ts-ignore */ + const pymajor = Module._py_version_major(); + /* @ts-ignore */ + const pyminor = Module._py_version_minor(); + Module.FS.mkdirTree("/lib"); - Module.FS.mkdirTree("/lib/python3.11/site-packages"); + Module.FS.mkdirTree(`/lib/python${pymajor}.${pyminor}/site-packages`); Module.addRunDependency("install-stdlib"); stdlibPromise .then((stdlib: Uint8Array) => { - Module.FS.writeFile("/lib/python311.zip", stdlib); + Module.FS.writeFile(`/lib/python${pymajor}${pyminor}.zip`, stdlib); }) .catch((e) => { console.error("Error occurred while installing the standard library:"); diff --git a/src/tests/test_pyodide.py b/src/tests/test_pyodide.py index 4c5541bb9..860ac2b25 100644 --- a/src/tests/test_pyodide.py +++ b/src/tests/test_pyodide.py @@ -1782,3 +1782,15 @@ def test_python_error(selenium): ) assert msg.endswith("TypeError: oops\n") assert ty == "TypeError" + + +def test_python_version(selenium): + selenium.run_js( + """ + sys = pyodide.pyimport("sys"); + assert(() => sys.version_info.major === pyodide._module._py_version_major()); + assert(() => sys.version_info.minor === pyodide._module._py_version_minor()); + assert(() => sys.version_info.micro === pyodide._module._py_version_micro()); + sys.destroy(); + """ + )