Skip to content

Commit

Permalink
Merge pull request #76 from trungleduc/conda-format
Browse files Browse the repository at this point in the history
Support direct download for no-arch packages
  • Loading branch information
martinRenou authored Oct 22, 2024
2 parents b27943b + b7dcff8 commit 28d35bd
Show file tree
Hide file tree
Showing 10 changed files with 310 additions and 18 deletions.
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

0 comments on commit 28d35bd

Please sign in to comment.