Packaging¶
Packaging and distribution¶
This document covers how simweave should be distributed, and how
EdgeWeave consumes it.
The short answer¶
Publish simweave as a standalone package on PyPI. EdgeWeave imports
it as an ordinary third-party dependency. The Electron installer
bundles a Python runtime that has simweave pre-installed so end users
get a zero-setup experience; power users who only want the engine
pip install simweave on their own.
This is the right call for three reasons:
- EdgeWeave is an optional front-end, not the delivery vehicle. The library has real value without the GUI — for notebooks, for CI-embedded Monte Carlo sweeps, for headless batch runs on a cluster.
- Code generated by EdgeWeave has to import
simweave. If the library only ships inside the Electron bundle, generated scripts don't run anywhere else. A PyPI release makes generated code portable. - Two distribution channels means two release cadences. EdgeWeave can update its UI independently of the engine, and the engine can fix a Monte Carlo bug without you rebuilding the Electron app.
Recommended channel layout¶
+----------------------+
| GitHub repo |
| simweave (src/) |
+----------------------+
|
+------------+------------+
| |
v v
+-----------+ +------------+
| PyPI | | EdgeWeave |
| simweave | <- depends- | Electron |
| (wheel) | | bundle |
+-----------+ +------------+
| |
v v
pip install simweave ships a Python venv
(CLI / notebook with simweave prebundled
/ script user) (GUI user)
Why not bundle inside EdgeWeave only?¶
- Generated Python won't run on a fresh machine without EdgeWeave.
- Users who want the engine in a Jupyter notebook, a Django app, or a FastAPI service are forced to install an entire Electron app. Many won't.
- You lose the PyPI release graph (versions, yanks, dependency
resolvers' understanding of
simweave>=0.3). - CI environments can't install from an Electron bundle.
Why not vendor-copy inside EdgeWeave?¶
The EdgeWeave repo could in principle contain a copy of simweave and
install it as a local dependency. That drifts. Either:
- Treat EdgeWeave's copy as read-only (pull from PyPI at build time — then you might as well just declare a dependency), or
- Allow EdgeWeave to patch locally, in which case EdgeWeave- generated code no longer works against stock PyPI simweave.
Both end badly.
Name on PyPI¶
The package name in pyproject.toml is currently simweave. Check
availability on PyPI before tagging a release — the name is short
and may be taken. Options if it is:
simweave-core— clear suffix, good for a package you'll later splitpysimweave— traditional Python prefix- A brandable name specific to your project (e.g.,
tempo-sim,atomclock-sim). This is the moment to pick, because renaming post-publication is painful.
If renaming, change:
[project].nameinpyproject.toml- The folder
src/simweave/— rename to match - Imports throughout —
simweave→<newname>is a simplesed - CI workflow references
- README / PACKAGING / demos
Or keep the package name simweave on PyPI and the importable module
simweave — even if it collides you can typically reclaim a dormant
name via PyPI's name reuse policy.
First release checklist¶
Before tagging v0.1.0:
- PyPI name reserved (register a dummy
0.0.0a0upload if needed) -
LICENSEfile present (MIT is declared inpyproject.tomlbut should also be a top-level file) -
CHANGELOG.mdseeded with the initial release notes -
README.mdrenders correctly on PyPI (no relative links that won't resolve off-repo; use absolute GitHub URLs for badges) -
pyproject.tomlincludes[project.urls]pointing at the repo, docs, and issue tracker -
python -m build && twine check dist/*passes locally -
pip install -e .[dev] && pytestis green - Trusted publishing configured on PyPI (preferred over uploading API tokens to GitHub secrets)
# Add this to pyproject.toml before release
[project.urls]
Homepage = "https://github.com/<you>/sim_engine"
Repository = "https://github.com/<you>/sim_engine"
Issues = "https://github.com/<you>/sim_engine/issues"
Documentation = "https://github.com/<you>/sim_engine#readme"
Release workflow¶
The repo ships a two-stage release flow at .github/workflows/release.yml:
- Pre-release tags (any tag with a letter or dash — e.g.
v0.1.0rc1,v0.1.0-alpha) upload to TestPyPI only. - Stable semver tags (e.g.
v0.1.0) upload to PyPI.
Cutting a release:
# 1. bump version in pyproject.toml
# 2. update CHANGELOG.md
# 3. commit and tag
git commit -am "release: 0.1.0"
git tag v0.1.0
git push --follow-tags
GitHub Actions picks up the tag, builds a wheel + sdist, runs
twine check, and publishes via PyPI trusted publishing (OIDC — no
secrets to manage).
Pull the release back down on your Electron build machine with
pip install simweave==0.1.0 and you have a reproducible EdgeWeave
build.
EdgeWeave integration¶
Depending on simweave from EdgeWeave¶
Inside EdgeWeave's Python side (edgeweave/pyproject.toml or
requirements.txt):
The Electron packager has to embed the Python runtime and all dependencies. The typical pattern is:
- Build a
.venvat package time withpip install -r requirements.txt. - Use
pyinstaller,briefcase, orpython-build-standaloneto produce a redistributable Python.python-build-standaloneis the lightest if you just need a headless embedded interpreter. - Ship
app.asar+ the.venv/alongside — the Electron main process spawnspythonpointing at that interpreter.
Code generation contract¶
EdgeWeave's generated Python should import from the public API surface, not internal modules:
# Good
from simweave import Queue, Service, Warehouse, a_star
# Bad
from simweave.discrete._internal import _WorkChannel
The top-level simweave/__init__.py re-exports every stable name;
anything not re-exported is not part of the API contract.
Versioning contract¶
- Bug fixes → patch (
0.1.0→0.1.1) - New features that are additive → minor (
0.1.0→0.2.0) - Breaking changes → major (
0.x→1.0.0)
EdgeWeave should pin to a minor range (simweave>=0.1,<0.2) pre-1.0
and to a major range (simweave>=1,<2) once we hit 1.0. That way we
can fix bugs without breaking existing EdgeWeave builds, and users
upgrading EdgeWeave get compatible engine upgrades automatically.
Distribution sanity-check¶
After each release, install the published wheel into a fresh venv and run the demos:
python -m venv /tmp/simweave-check
source /tmp/simweave-check/bin/activate
pip install simweave==0.1.0
python - <<'PY'
from simweave import Queue, Service, SimEnvironment, Entity
q = Queue(maxlen=5)
print("simweave installed OK:", q)
PY
This is fast enough to be worth automating as a post-publish step in the release workflow.
Wheels: pure-Python today, binary tomorrow¶
simweave is pure Python today — no compiled extensions — so the wheel
is py3-none-any.whl and works everywhere Python 3.10+ runs. That's
the ideal state.
When we eventually add Cython or Numba-compiled inner loops, the story changes:
- Numba: stays pure-Python at distribution time; JIT happens on the user's machine at first call. Preferred.
- Cython: requires platform-specific wheels (manylinux, macosx_x86,
macosx_arm64, win_amd64). Use
cibuildwheelin CI; prebuilt binary wheels for each platform become a chore but buy 2–5× over Numba on the hot path. Only worth it for genuinely hot code.
If we take the Cython path, add a [build-system] section pulling in
cython and numpy as build requires, and add a cibuildwheel job to
the release workflow.