Skip to content

Commit 7c5a44f

Browse files
fix(ci): Skip wasm build for pure-Python test stdpkg.
1 parent 83839e9 commit 7c5a44f

4 files changed

Lines changed: 49 additions & 9 deletions

File tree

.github/workflows/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ check -> wasm -> runtime -> demo
1414
| `_demo.yml` | Hashes `compiler_lib.wasm` into `version.json` (cache-busting) and deploys `demo/` to Cloudflare Pages |
1515
| `cli.yml` | Standalone (not part of the pipeline above): builds and tests `cli/`; on `main` pushes also publishes the release binary + `cli/setup/` scripts (`install.sh`, `uninstall.sh`) to GitHub Pages |
1616
| `host.yml` | Standalone: deno-lints and tests each host capability (`dom`, `network`, `storage`, `time`) in headless Chromium; on `main` pushes also deploys their ESM sources to Cloudflare Pages (`edge-python-host`) |
17-
| `std.yml` | Standalone: clippy + build + optimize + test each stdpkg wasm (`json`, `re`, `math`); on `main` pushes also deploys the per-package `.wasm` to Cloudflare Pages (`edge-python-std`) |
17+
| `std.yml` | Standalone: clippy + build + optimize + test each stdpkg (`json`, `re`, `math` as wasm; `test` is pure Edge Python, so its steps skip the wasm build and only run the corpus); on `main` pushes also deploys the per-package `.wasm` to Cloudflare Pages (`edge-python-std`) |
1818

1919
## Cloudflare Pages
2020

.github/workflows/std.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@ jobs:
4747

4848
# Lint only the cdylib; --all-targets clashes with its panic handler.
4949
- name: Clippy src/
50+
if: matrix.package != 'test'
5051
working-directory: std/${{ matrix.package }}
5152
run: cargo clippy --release --target wasm32-unknown-unknown -- -D warnings
5253

53-
# Build, optimize, and test each package's wasm; uploads the artifact for the deploy step.
54+
# Build, optimize, and test each package; uploads the wasm artifact for the deploy step.
5455
wasm:
5556
name: WASM (${{ matrix.package }})
5657
needs: lint
@@ -100,12 +101,15 @@ jobs:
100101

101102
# apt ships an old binaryen, so fetch the upstream release.
102103
- name: Install wasm-opt
104+
if: matrix.package != 'test'
103105
run: |
104106
curl -sSL "https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VERSION}/binaryen-version_${BINARYEN_VERSION}-x86_64-linux.tar.gz" \
105107
| tar -xz --strip-components=2 -C /usr/local/bin "binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt"
106108
wasm-opt --version
107109
110+
# `test` is pure Edge Python (src/entry.py): no crate to compile, so skip the wasm build/optimize/upload and let the corpus run below.
108111
- name: Build
112+
if: matrix.package != 'test'
109113
working-directory: std/${{ matrix.package }}
110114
run: |
111115
RUSTFLAGS="-Z location-detail=none -Z fmt-debug=none -Z unstable-options -C panic=immediate-abort" \
@@ -115,10 +119,12 @@ jobs:
115119
-Z build-std=std,panic_abort
116120
117121
- name: Size (unoptimized)
122+
if: matrix.package != 'test'
118123
run: ls -lh "$WASM"
119124

120125
# Two passes: -Oz with traps-never-happen, then reflatten for a fresh CFG.
121126
- name: Optimize
127+
if: matrix.package != 'test'
122128
run: |
123129
wasm-opt -Oz --converge \
124130
--generate-global-effects \
@@ -138,16 +144,18 @@ jobs:
138144
rm /tmp/wasm_stage1.wasm
139145
140146
- name: Size (optimized)
147+
if: matrix.package != 'test'
141148
run: ls -lh "$WASM"
142149

143-
# STDPKG narrows Deno's test discovery to this package's corpus.
150+
# STDPKG narrows Deno's test discovery to this package's corpus. The driver routes .py packages to src/entry.py, native ones to the built wasm.
144151
- name: Test
145152
working-directory: std
146153
env:
147154
STDPKG: ${{ matrix.package }}
148155
run: deno test --allow-all tests/
149156

150157
- uses: actions/upload-artifact@v6
158+
if: matrix.package != 'test'
151159
with:
152160
name: wasm-${{ matrix.package }}
153161
path: ${{ env.WASM }}

docs/reference/packages.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,33 @@ print(factorial(5)) # 120
6363

6464
Integers are bounded by the VM's `i128`, so `factorial`, `comb`, `perm`, and `lcm` raise `ValueError` past that range, and there is no `complex` / `cmath`. Pre-built `.wasm` is served from `https://std.edgepython.com/math.wasm`. Full API: [`std/math/README.md`](https://github.com/dylan-sutton-chavez/edge-python/tree/main/std/math).
6565

66+
### `test`
67+
68+
A tiny unit-test harness written in pure Edge Python, not a Rust `.wasm` module: fixtures, test registration, exception assertions, and a runner that reports pass/fail and sets the exit code. It leans only on language built-ins (`assert`, `issubclass`, `SystemExit`), so it needs no host capability and runs wherever the VM runs.
69+
70+
```python
71+
from test import fixture, test, raises, run
72+
73+
@fixture
74+
def user():
75+
return {"name": "Ana"}
76+
77+
@test("user has a name", "user")
78+
def test_name(user):
79+
assert user["name"] == "Ana"
80+
81+
@test("division by zero raises")
82+
def test_div():
83+
with raises(ZeroDivisionError):
84+
1 / 0
85+
86+
run() # prints PASS/FAIL lines and a summary, then raises SystemExit(0 if all passed, else 1)
87+
```
88+
89+
`@fixture` registers a `def` under its name and injects it by keyword into the tests that ask for it; `@test(description, *uses)` registers a test plus the fixtures it pulls; `raises(ExcType)` is a context manager asserting the block raises `ExcType` (a subclass, or any type in a tuple); `run()` executes every registered test, prints `PASS` / `FAIL` / `ERROR` and a summary, then raises `SystemExit(1 if any failed, else 0)` so a host can read the result as a process exit code.
90+
91+
Unlike the other standard packages, `test` ships as **pure Edge Python source** (`src/entry.py`), not a compiled `.wasm`, so there is no `cargo` build and nothing served from `std.edgepython.com`; the browser runtime resolves it by default and imports the `.py` directly (see [Defaults](#defaults)). Full API: [`std/test/README.md`](https://github.com/dylan-sutton-chavez/edge-python/tree/main/std/test).
92+
6693
## Host libraries
6794

6895
Plain-JS capabilities that run on the browser's main thread, registered declaratively via the `host` field of [`packages.json`](/reference/imports#packages-json) (with the `<edge-python>` element), programmatically via `createWorker({ hostModules })`, or resolved by default with no config at all (see [Defaults](#defaults)). No `.wasm`, no Rust, no build step. Each call defers to the main thread over `postMessage` (around 0.1 to 0.4 ms); Python sees a synchronous call. The ESM loads lazily, the first time a run imports it.
@@ -143,7 +170,7 @@ One manifest drives both directions: `imports` for worker-side `.py` / `.wasm` m
143170

144171
### Defaults
145172

146-
The browser runtime ships a built-in base manifest, so the official packages resolve by bare name with **no `packages.json` at all**: the std `.wasm` packages (`json`, `re`, `math`) and the host libraries (`dom`, `network`, `storage`, `time`). Three rules:
173+
The browser runtime ships a built-in base manifest, so the official packages resolve by bare name with **no `packages.json` at all**: the std packages (`json`, `re`, `math`, and the pure-Python `test`) and the host libraries (`dom`, `network`, `storage`, `time`). Three rules:
147174

148175
- **Lazy.** A default is fetched only when a run actually imports it. Unused defaults never hit the network.
149176
- **Overridable.** Your `packages.json` (or `imports` / `hostModules`) wins for the same name, so you can pin a specific version or URL.

std/README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# Edge Python Standard Packages
22

3-
Official `.wasm` standard-library packages for [Edge Python](https://edgepython.com). Each capability is a Rust crate compiled to `wasm32-unknown-unknown` against the [wasm-pdk](https://github.com/dylan-sutton-chavez/edge-python/tree/main/wasm-pdk) ABI. Hosts load the resulting `.wasm` over the standard plugin contract, no custom embedder, no Rust on the consumer side.
3+
Official standard-library packages for [Edge Python](https://edgepython.com). Most are a Rust crate compiled to `wasm32-unknown-unknown` against the [wasm-pdk](https://github.com/dylan-sutton-chavez/edge-python/tree/main/wasm-pdk) ABI; hosts load the resulting `.wasm` over the standard plugin contract, no custom embedder, no Rust on the consumer side. A package can also ship as pure Edge Python source (`src/entry.py`), imported as a code module with no `cargo` build (e.g. `test`).
44

55
## Layout
66

77
```
88
tests/, agnostic Deno + Playwright runner driving the <edge-python> tag
9-
<name>/, one folder per stdpkg crate, with src/, README.md, and <name>.json corpus
9+
<name>/, one folder per stdpkg, with src/, README.md, and <name>.json corpus
1010
```
1111

12-
The folder name IS the package name IS the wasm artifact name (e.g. `json/` -> `json/target/wasm32-unknown-unknown/release/json.wasm`). Each package's `<name>.json` sits alongside `Cargo.toml`; cases in it are automatically prefixed with `from <name> import *\n` before dispatch, so the corpus only contains the code being tested.
12+
The folder name IS the package name. A native package builds to `<name>/target/wasm32-unknown-unknown/release/<name>.wasm`; a pure-Python package has `src/entry.py` and no build artifact. Each package's `<name>.json` corpus sits in its folder; cases in it are automatically prefixed with `from <name> import *\n` before dispatch, so the corpus only contains the code being tested.
1313

1414
## Packages
1515

@@ -18,13 +18,14 @@ The folder name IS the package name IS the wasm artifact name (e.g. `json/` -> `
1818
| `json` | JSON serialization/deserialization, see [`json/README.md`](json/README.md) |
1919
| `re` | Regular expressions, a subset with capture, backreferences, lookaround, and a ReDoS step budget, see [`re/README.md`](re/README.md) |
2020
| `math` | CPython-style math over libm, integer ops, and a packed-f64 batch fast path, see [`math/README.md`](math/README.md) |
21+
| `test` | Tiny unit-test harness in pure Edge Python (fixtures, `raises`, runner with exit code), see [`test/README.md`](test/README.md) |
2122

2223
## Build + test
2324

24-
Each package builds independently; the agnostic runner asserts against the produced `.wasm`. From the repo root:
25+
Native packages build independently; the agnostic runner asserts against the produced `.wasm`, or against `src/entry.py` for a pure-Python package. From the repo root:
2526

2627
```bash
27-
# Build every package's .wasm artifact.
28+
# Build a native package's .wasm artifact (skip for pure-Python packages like test).
2829
( cd json && cargo build --release --target wasm32-unknown-unknown )
2930

3031
# One command, drives all corpora through the shared runner.
@@ -35,11 +36,15 @@ The runner discovers packages by walking the repo root for `<name>/<name>.json`
3536

3637
## Adding a new stdpkg
3738

39+
For a native (wasm) package:
40+
3841
1. Create `<name>/` at the repo root with `Cargo.toml` (`name = "<name>"`, `crate-type = ["cdylib"]`, `wasm-pdk` dep) and a `src/lib.rs` exporting via `#[plugin_fn]`.
3942
2. Drop `<name>/<name>.json` with the corpus (Edge Python source + expected `output` / `error` per case).
4043
3. Run `cargo build --release --target wasm32-unknown-unknown` inside the package folder.
4144
4. Run `deno test --allow-all tests/` from the repo root.
4245

46+
For a pure-Python package, skip the crate: add `<name>/src/entry.py` plus `<name>/<name>.json`, then run `deno test --allow-all tests/`. The runner routes `.py` packages to their source and skips the wasm build.
47+
4348
No edits to `tests/`.
4449

4550
## License

0 commit comments

Comments
 (0)