From e1dc46892b08b03480ae46c83b3529ed9eaec306 Mon Sep 17 00:00:00 2001 From: Thorsten Beier Date: Wed, 14 Feb 2024 14:19:34 +0100 Subject: [PATCH] bytes converter, better pyodide polyfill (#55) * added bytes converter * improved pyodide polyfill by using correct error messages --- CMakeLists.txt | 1 + include/pyjs/convert.hpp | 1 + include/pyjs/pycpp/convert_py_to_js.py | 6 ++++++ include/pyjs/pycpp/core.py | 21 ++------------------- include/pyjs/pycpp/pyodide_polyfill.py | 26 ++++++++++++++++++++++++++ src/convert.cpp | 10 ++++++++++ src/export_js_proxy.cpp | 1 + src/export_pyjs_module.cpp | 3 ++- src/js_timestamp.cpp | 2 +- 9 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 include/pyjs/pycpp/pyodide_polyfill.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 30cdb14..198f1c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ set(PYCPPSCRIPTS error_handling.py extend_js_val.py webloop.py + pyodide_polyfill.py ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pycpp_includes) diff --git a/include/pyjs/convert.hpp b/include/pyjs/convert.hpp index 422bc53..998b50a 100644 --- a/include/pyjs/convert.hpp +++ b/include/pyjs/convert.hpp @@ -56,5 +56,6 @@ namespace pyjs em::val py_1d_buffer_to_typed_array(py::buffer buffer, bool view); + em::val bytes_to_js(char* data); } diff --git a/include/pyjs/pycpp/convert_py_to_js.py b/include/pyjs/pycpp/convert_py_to_js.py index 564120e..644e2d5 100644 --- a/include/pyjs/pycpp/convert_py_to_js.py +++ b/include/pyjs/pycpp/convert_py_to_js.py @@ -60,5 +60,11 @@ def to_js(value, cache=None, depth=0, max_depth=None): return js_undefined() elif isinstance(value, (int, float, str, bool)): return JsValue(value) + + # # bytestring + elif isinstance(value, bytes): + return internal.bytes_to_typed_array(value).buffer + + else: raise RuntimeError(f"no registerd converted for {value} of type {type(value)}") diff --git a/include/pyjs/pycpp/core.py b/include/pyjs/pycpp/core.py index 21c4eda..8385644 100644 --- a/include/pyjs/pycpp/core.py +++ b/include/pyjs/pycpp/core.py @@ -6,6 +6,7 @@ import ast + def install_submodules(): def _js_mod__getattr__(name: str) -> Any: ret = internal.global_property(name) @@ -25,29 +26,11 @@ def _module_mod__getattr__(name: str) -> Any: _module = sys.modules["pyjs._module"] = types.ModuleType("_module") _module.__getattr__ = _module_mod__getattr__ - # Expose a small pyodide polyfill - def _pyodide__getattr__(name: str) -> Any: - if name == "to_js": - from pyjs import to_js - return to_js - - raise AttributeError( - "This is not the real Pyodide. We are providing a small Pyodide polyfill for conveniance." - "If you are missing an important Pyodide feature, please open an issue in https://github.com/emscripten-forge/pyjs/issues" - ) - - pyodide = sys.modules["pyodide"] = types.ModuleType("pyodide") - pyodide.ffi = sys.modules["pyodide.ffi"] = types.ModuleType("ffi") - pyodide.ffi.JsException = RuntimeError - pyodide.ffi.JsArray = object - pyodide.ffi.JsProxy = object - pyodide.__getattr__ = _pyodide__getattr__ - pyodide.ffi.__getattr__ = _pyodide__getattr__ - install_submodules() del install_submodules + js = sys.modules["pyjs.js"] _module = sys.modules["pyjs._module"] diff --git a/include/pyjs/pycpp/pyodide_polyfill.py b/include/pyjs/pycpp/pyodide_polyfill.py new file mode 100644 index 0000000..7c78e46 --- /dev/null +++ b/include/pyjs/pycpp/pyodide_polyfill.py @@ -0,0 +1,26 @@ + + +def install_pyodide_polyfill(): + # Expose a small pyodide polyfill + def _pyodide__getattr__(name: str) -> Any: + if name == "to_js": + from pyjs import to_js + return to_js + + raise AttributeError( + "This is not the real Pyodide. We are providing a small Pyodide polyfill for conveniance." + "If you are missing an important Pyodide feature, please open an issue in https://github.com/emscripten-forge/pyjs/issues" + ) + + pyodide = sys.modules["pyodide"] = types.ModuleType("pyodide") + pyodide.ffi = sys.modules["pyodide.ffi"] = types.ModuleType("ffi") + pyodide.ffi.JsException = JsException + pyodide.ffi.JsArray = object + pyodide.ffi.JsProxy = object + pyodide.__getattr__ = _pyodide__getattr__ + pyodide.ffi.__getattr__ = _pyodide__getattr__ + + + +install_pyodide_polyfill() +del install_pyodide_polyfill \ No newline at end of file diff --git a/src/convert.cpp b/src/convert.cpp index 147b543..dc1c8eb 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -197,6 +197,14 @@ namespace pyjs } + em::val bytes_to_js(char * binary_string) + { + // get the length of the string + std::size_t length = std::strlen(binary_string); + em::val mem_view = em::val(em::typed_memory_view(length, binary_string)); + em::val mem_copy = em::val::global("Uint8Array").new_(mem_view); + return mem_copy; + } template em::val py_1d_buffer_to_typed_array_t(const std::size_t size, @@ -215,6 +223,8 @@ namespace pyjs } + + em::val py_1d_buffer_to_typed_array(py::buffer buffer, bool view) { /* Request a buffer descriptor from Python */ diff --git a/src/export_js_proxy.cpp b/src/export_js_proxy.cpp index b6ddcc4..899dc51 100644 --- a/src/export_js_proxy.cpp +++ b/src/export_js_proxy.cpp @@ -326,6 +326,7 @@ namespace pyjs m_internal.def("py_1d_buffer_to_typed_array", &py_1d_buffer_to_typed_array); + m_internal.def("bytes_to_typed_array", &bytes_to_js); } diff --git a/src/export_pyjs_module.cpp b/src/export_pyjs_module.cpp index 3537faf..b6bb6f0 100644 --- a/src/export_pyjs_module.cpp +++ b/src/export_pyjs_module.cpp @@ -21,7 +21,7 @@ void pyjs_error_handling_pseudo_init(py::module_&); void pyjs_convert_pseudo_init(py::module_&); void pyjs_convert_py_to_js_pseudo_init(py::module_&); void pyjs_webloop_pseudo_init(py::module_&); - +void pyjs_pyodide_polyfill_pseudo_init(py::module_&); namespace pyjs { @@ -36,6 +36,7 @@ namespace pyjs pyjs_convert_pseudo_init(pyjs_module); pyjs_convert_py_to_js_pseudo_init(pyjs_module); pyjs_webloop_pseudo_init(pyjs_module); + pyjs_pyodide_polyfill_pseudo_init(pyjs_module); } catch (py::error_already_set& e) { diff --git a/src/js_timestamp.cpp b/src/js_timestamp.cpp index 469e896..696b188 100644 --- a/src/js_timestamp.cpp +++ b/src/js_timestamp.cpp @@ -1 +1 @@ -#define PYJS_JS_UTC_TIMESTAMP "2024-02-05 11:33:27.581566" \ No newline at end of file +#define PYJS_JS_UTC_TIMESTAMP "2024-02-14 09:09:18.446638" \ No newline at end of file