Draco Pyodide JavaScript Package
Usage
Apart from the Pyodide artifacts' location, the usage of draco-pyodide
is identical to that of
pyodide
.
You can find tagged releases of the Draco Pyodide artifacts on our GitHub releases page and commit-specific builds as GitHub Action artifacts attached to build workflows.
Node.js
Download the Draco Pyodide artifacts from GitHub releases
(pyodide-*.tar.gz
) and extract its contents into a local directory (./draco-pyodide-artifacts
in the example below)
The version of the release needs to match exactly the version of this package.
You can automate this using the following commands:
DRACO_PYODIDE_VERSION=2.0.0 # Replace with the package version of your choice
ARTIFACT_DIR=draco-pyodide-artifacts # Replace with the directory of your choice
TAR_NAME=pyodide-$DRACO_PYODIDE_VERSION.tar.gz
wget https://github.com/cmudig/draco2/releases/download/v$DRACO_PYODIDE_VERSION/$TAR_NAME
mkdir $ARTIFACT_DIR
tar -xzf $TAR_NAME --directory $ARTIFACT_DIR
rm $TAR_NAME
Then you can load Draco Pyodide in Node.js as follows:
// hello_draco.js
const { loadPyodide } = require("draco-pyodide");
async function hello_draco() {
let pyodide = await loadPyodide({
/* Draco Pyodide artifacts folder */
indexURL: "./draco-pyodide-artifacts",
});
// Load our package
await pyodide.loadPackage("draco");
// Import the loaded `draco` package and access some attributes
return pyodide.runPython(`
import draco
from draco.asp_utils import parse_blocks
d = draco.Draco()
# The final line of the code block is returned as the result
f"Running draco version: {draco.__version__}", parse_blocks(d.hard), parse_blocks(d.soft)
`);
}
hello_draco().then((result) => {
// Destructure the returned list of Python objects
const [version, hard, soft] = result;
// Extract the constraint names from the Python `dict` objects
const hardConstraintNames = Array.from(hard.keys()).slice(1);
const softConstraintNames = Array.from(soft.keys()).slice(1);
console.log(version);
console.log(`=== Hard constraints ===\n${hardConstraintNames.join("\n")}`);
console.log(`=== Soft constraints ===\n${softConstraintNames.join("\n")}`);
});
Client-side JavaScript
When using Draco Pyodide in the browser, you can load the draco-pyodide
package from jsdelivr
. You can decide
whether you want to host the Draco Pyodide artifacts downloaded from
GitHub releases (pyodide-*.tar.gz
) yourself or use the version hosted on
our GitHub Pages (indexURL: "https://dig.cmu.edu/draco2/jupyterlite/static/pyodide"
).
main
, but we only release a new version of this package when we do an actual tagged release.
<!doctype html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/draco-pyodide@latest/pyodide.js"></script>
</head>
<body
style="
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #1a1c40;
"
>
<script type="text/javascript">
async function main() {
let pyodide = await loadPyodide({
/* Draco Pyodide artifacts folder */
indexURL: "https://dig.cmu.edu/draco2/jupyterlite/static/pyodide",
});
// Load our package
await pyodide.loadPackage("draco");
// Import the loaded `draco` package and access some attributes
const [version, hard, soft] = await pyodide.runPython(`
import draco
d = draco.Draco()
# The final line of the code block is returned as the result
f"Running draco version: {draco.__version__}", d.hard, d.soft
`);
// Print the result of `f"Running draco version: {draco.__version__}"`
console.log(version);
console.log(`Hard constraints:\n${hard}`);
console.log(`Soft constraints:\n${soft}`);
}
main();
</script>
<h1 style="color: #ffffff">Check the console for outputs</h1>
</body>
</html>
Further Examples
You can find a variety of examples in the draco-web-examples repository, featuring more advanced usages of Draco in web applications.
Details
The JavaScript code in this package is responsible for the following tasks:
- Defines the public JavaScript API
- Package loading code to allow loading of other Python packages.
- Can load micropip to bootstrap loading of pure Python wheels
- Loads the CPython interpreter and the core/pyodide emscripten application which embeds the interpreter.
- Injects the
js/pyodide
JavaScript API intosys.modules
. This is the final runtime dependency forcore/pyodide
&py/pyodide
, so after this step the interpreter is fully up and running.