Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
-c https://repo.mamba.pm/emscripten-forge \
-c https://repo.mamba.pm/conda-forge \
--yes \
python pybind11 nlohmann_json pybind11_json numpy "pytest==7.1.1" bzip2 sqlite zlib libffi exceptiongroup
python pybind11 nlohmann_json pybind11_json numpy "pytest==7.1.1" bzip2 sqlite zlib zstd libffi exceptiongroup


mkdir build
Expand Down
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ set(PYJS_HEADERS
include/pyjs/export_py_object.hpp
include/pyjs/export_pyjs_module.hpp
include/pyjs/untar.hpp
include/pyjs/install_conda_file.hpp
include/pyjs/inflate.hpp
${CMAKE_CURRENT_BINARY_DIR}/pyjs_pre.js
${CMAKE_CURRENT_BINARY_DIR}/pyjs_post.js
Expand Down Expand Up @@ -110,6 +111,7 @@ add_library(pyjs STATIC
src/js_timestamp.cpp
src/inflate.cpp
src/untar.cpp
src/install_conda_file.cpp
${PYCPPSOURCES}
)

Expand Down Expand Up @@ -153,6 +155,7 @@ SET(PYTHON_UTIL_LIBS
${CMAKE_INSTALL_PREFIX}/lib/libz.a
${CMAKE_INSTALL_PREFIX}/lib/libsqlite3.a
${CMAKE_INSTALL_PREFIX}/lib/libffi.a
${CMAKE_INSTALL_PREFIX}/lib/libzstd.a
)


Expand Down
2 changes: 1 addition & 1 deletion build_mkdocs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ if [ ! -d "$WASM_ENV_PREFIX" ]; then
-c https://repo.mamba.pm/conda-forge \
--yes \
python pybind11 nlohmann_json pybind11_json numpy \
bzip2 sqlite zlib libffi exceptiongroup \
bzip2 sqlite zlib zstd libffi exceptiongroup \
"xeus<4" "xeus-lite<2" xeus-python "xeus-javascript>=0.3.2" xtl "ipython=8.22.2=py311had7285e_1" "traitlets>=5.14.2"

else
Expand Down
12 changes: 12 additions & 0 deletions include/pyjs/install_conda_file.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include <emscripten/bind.h>

namespace pyjs
{

em::val install_conda_file(const std::string& zstd_file_path,
const std::string& working_dir,
const std::string& path);

}
124 changes: 111 additions & 13 deletions include/pyjs/pre_js/load_pkg.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,69 @@ def _py_untar(tarball_path, target_dir):
}


Module["_unzip_from_python"] = function(tarball_path, target_dir) {
Module.exec(`
def _py_unzip(tarball_path, target_dir):
import json
from pathlib import Path
import zipfile

target = Path(target_dir)
target.mkdir(parents=True, exist_ok=True)
pkg_file = {"name": "", "path": ""}
with zipfile.ZipFile(tarball_path, mode="r") as archive:

for filename in archive.namelist():
if filename.startswith("pkg-"):
pkg_file["name"] = filename
pkg_file["path"] = str(target / filename)
archive.extract(filename, target_dir)
break
return json.dumps(pkg_file)

`)
let extracted_file = Module.eval(`_py_unzip("${tarball_path}", "${target_dir}")`)

return JSON.parse(extracted_file)
}

Module["_install_conda_file_from_python"] = function(tarball_path, target_dir) {
Module.exec(`
def _py_unbz2(tarball_path, target_dir):
import json
from pathlib import Path
import tarfile
import shutil
import os
import sys

target = Path(target_dir)
prefix = Path(sys.prefix)
try:
with tarfile.open(tarball_path) as tar:
tar.extractall(target_dir)

src = target / "site-packages"
dest = prefix / "lib/python3.11/site-packages"
shutil.copytree(src, dest, dirs_exist_ok=True)
for folder in ["etc", "share"]:
src = target / folder
dest = prefix / folder
if src.exists():
shutil.copytree(src, dest, dirs_exist_ok=True)
shutil.rmtree(target)
except Exception as e:
print("ERROR",e)
raise e

return json.dumps([])

`)
let extracted_file = Module.eval(`_py_unbz2("${tarball_path}", "${target_dir}")`)

return JSON.parse(extracted_file)
}




Expand Down Expand Up @@ -108,20 +171,55 @@ Module["bootstrap_from_empack_packed_environment"] = async function
pkg,
verbose
) {
const package_url = pkg?.url ?? `${package_tarballs_root_url}/${pkg.filename}`;
if (verbose) {
console.log(`!!fetching pkg ${pkg.name} from ${package_url}`)
}
let byte_array = await fetchByteArray(package_url)
const tarball_path = `/package_tarballs/${pkg.filename}`;
Module.FS.writeFile(tarball_path, byte_array);
if(verbose){
console.log(`!!extract ${tarball_path} (${byte_array.length} bytes)`)
const package_url =
pkg?.url ?? `${package_tarballs_root_url}/${pkg.filename}`;
if (verbose) {
console.log(`!!fetching pkg ${pkg.name} from ${package_url}`);
}
let byte_array = await fetchByteArray(package_url);
const tarball_path = `/package_tarballs/${pkg.filename}`;
Module.FS.writeFile(tarball_path, byte_array);
if (verbose) {
console.log(
`!!extract ${tarball_path} (${byte_array.length} bytes)`
);
}

if (verbose) {
console.log("await python_is_ready_promise");
}
await python_is_ready_promise;

if (package_url.toLowerCase().endsWith(".conda")) {
// Conda v2 packages
if (verbose) {
console.log(
`!!extract conda package ${package_url} (${byte_array.length} bytes)`
);
}
const dest = `/conda_packages/${pkg.name}`;
const pkg_file = Module["_unzip_from_python"](
tarball_path,
dest
);
return Module._install_conda_file(pkg_file.path, dest, prefix);
} else if (package_url.toLowerCase().endsWith(".tar.bz2")) {
// Conda v1 packages
if (verbose) {
console.log(
`!!extract conda package ${package_url} (${byte_array.length} bytes)`
);
}
const dest = `/conda_packages/${pkg.name}`;
return Module["_install_conda_file_from_python"](
tarball_path,
dest
);
} else {
// Pre-relocated packages
return Module["_untar_from_python"](tarball_path);
}
}
if(verbose){console.log("await python_is_ready_promise");}
await python_is_ready_promise;
return Module["_untar_from_python"](tarball_path);
}


async function bootstrap_python(prefix, package_tarballs_root_url, python_package, verbose) {
Expand Down
5 changes: 3 additions & 2 deletions include/pyjs/untar.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once

#include <emscripten/bind.h>
#include <emscripten/val.h>

namespace em = emscripten;
namespace pyjs{

em::val untar(const std::string &tar_path, const std::string &path);

void untar_impl(FILE *a, const char *path, em::val & shared_libraraies);
}
1 change: 1 addition & 0 deletions src/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace py = pybind11;
namespace em = emscripten;


namespace pyjs
{
std::pair<em::val,bool> implicit_py_to_js(py::object& py_ret)
Expand Down
2 changes: 2 additions & 0 deletions src/export_js_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <pyjs/export_py_object.hpp>
#include <pyjs/convert.hpp>
#include <pyjs/untar.hpp>
#include <pyjs/install_conda_file.hpp>

#include <pybind11/embed.h>
#include <emscripten/bind.h>
Expand Down Expand Up @@ -105,6 +106,7 @@ namespace pyjs


em::function("_untar", &untar);
em::function("_install_conda_file", &install_conda_file);
em::function("setenv", &set_env);

// py-object (proxy)
Expand Down
Loading
Loading