Skip to content

Commit b71b680

Browse files
committed
Document Pyodide compatibility pattern (env marker + defensive re-export)
1 parent ec801df commit b71b680

3 files changed

Lines changed: 61 additions & 2 deletions

File tree

TEMPLATE.md

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,42 @@ repo, removes the template banner from `README.md`, and finally deletes
4242
PathSim core example; replace it with notebooks that demonstrate your
4343
blocks. Every `*.ipynb` here is executed and rendered by the docs build.
4444

45-
## 4. Register with the docs build
45+
## 4. Stay compatible with the web runtime
46+
47+
PathView ships a browser build that runs Python through Pyodide. Pure-Python
48+
toolboxes load there out of the box, but dependencies that ship native code
49+
(`pybamm`, `jsbsim`, `casadi`, anything that needs a compiled wheel) fail to
50+
install in the browser.
51+
52+
Default `pip install pathsim-<name>` on Linux/macOS/Windows should still
53+
install everything — no extras required. To get there:
54+
55+
1. **Mark heavy dependencies in `pyproject.toml`** with a PEP 508 environment
56+
marker so micropip (Pyodide) silently skips them:
57+
58+
```toml
59+
dependencies = [
60+
"pathsim>=0.22",
61+
"numpy>=1.15",
62+
"pybamm>=25.12; sys_platform != 'emscripten'",
63+
]
64+
```
65+
66+
2. **Guard the re-export in `src/pathsim_<name>/__init__.py`** so the rest of
67+
the toolbox stays importable when the heavy dep is missing:
68+
69+
```python
70+
try:
71+
from .cells import CellElectrical
72+
__all__ += ["CellElectrical"]
73+
except ImportError:
74+
pass
75+
```
76+
77+
In PathView's web Toolbox Manager, introspection then finds only the blocks
78+
whose submodules imported successfully; the desktop install sees everything.
79+
80+
## 5. Register with the docs build
4681

4782
The documentation site (`docs.pathsim.org`) is built by the
4883
[`pathsim/docs`](https://github.com/pathsim/docs) repository. It clones every
@@ -70,7 +105,7 @@ The repo-side docs contract is just: an importable package under `src/` and
70105
`*.ipynb` files under `docs/source/examples/`. No Sphinx — the docs build owns
71106
all rendering.
72107

73-
## 5. Releasing
108+
## 6. Releasing
74109

75110
`.github/workflows/publish.yml` publishes to PyPI via trusted publishing when
76111
a GitHub Release is published. Versions come from git tags via `setuptools-scm`,

pyproject.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ classifiers = [
2727
dependencies = [
2828
"pathsim>=0.22",
2929
"numpy>=1.15",
30+
# If your toolbox needs a dependency that ships native code (e.g.
31+
# pybamm, jsbsim, casadi, …) it will fail to install in Pyodide. Tag
32+
# it with a PEP 508 environment marker so a normal pip install on
33+
# Linux/macOS/Windows still pulls it eagerly, but micropip in the
34+
# browser silently skips it. Example:
35+
#
36+
# "pybamm>=25.12; sys_platform != 'emscripten'",
37+
#
38+
# Pair this with a defensive `try/except ImportError` re-export in
39+
# `src/pathsim_<name>/__init__.py` so the rest of the toolbox stays
40+
# importable when the heavy dependency is absent.
3041
]
3142

3243
[project.optional-dependencies]

src/pathsim_toolbox/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@
1111
except ImportError:
1212
__version__ = "unknown"
1313

14+
# Pure-Python blocks — eager.
1415
from .example_block import FirstOrderLag
1516

1617
__all__ = ["__version__", "FirstOrderLag"]
18+
19+
# If you add blocks that depend on a native package (e.g. pybamm, jsbsim,
20+
# casadi, …) put them in their own submodule and re-export them defensively
21+
# here so the toolbox still imports when the heavy dependency is missing
22+
# (e.g. in Pyodide). Pair this with a PEP 508 environment marker in
23+
# pyproject.toml — see the comment there for an example.
24+
#
25+
# try:
26+
# from .native_block import HeavyBlock
27+
# __all__ += ["HeavyBlock"]
28+
# except ImportError:
29+
# pass

0 commit comments

Comments
 (0)