You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/pages/reference/imports.md
+14-14Lines changed: 14 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@ title: "Imports"
3
3
description: "Importing modules in Edge Python: syntax, resolution, and the two module flavors."
4
4
---
5
5
6
-
Supports `import`, `from <spec> import <names>`, `from <spec> import *`. Resolution is compile-time, the VM never learns what a module is; bytecode flattens every import into the sequence that materialises the exports.
6
+
Supports `import`, `from <spec> import <names>`, `from <spec> import *`. Resolution is compile-time: the VM never learns what a module is; bytecode flattens every import into the sequence that materialises the exports.
7
7
8
8
## The two flavors
9
9
@@ -56,15 +56,15 @@ The names above (`json`, `utils`, `math`) are illustrative. `json` is an [offici
56
56
2. For each spec, asks the host `Resolver` to materialise as `Resolved::Native { bindings, canonical }` or `Resolved::Code { src, canonical }`.
57
57
3. Natives become direct-dispatch entries; code modules parse to a fresh `SSAChunk`. Both register under the canonical spec so first-class references and `import_module()` lookups resolve uniformly. See [Syntax, Imports](/implementation/syntax).
58
58
59
-
Modules are singletons across the compilation unit: same canonical spec -> one `SSAChunk`, top level runs once, one `HeapObj::Module` shared by every importer. Two files importing `./util.py` see the same module,`mod is mod_alias` is true; module-attr mutations are observed by every consumer. Inside the module's top level, `__name__` is bound to the canonical spec so `if __name__ == "__main__":` skips when imported.
59
+
Modules are singletons across the compilation unit: same canonical spec -> one `SSAChunk`, top level runs once, one `HeapObj::Module` shared by every importer. Two files importing `./util.py` see the same module —`mod is mod_alias` is true; module-attr mutations are observed by every consumer. Inside the module's top level, `__name__` is bound to the canonical spec so `if __name__ == "__main__":` skips when imported.
60
60
61
61
Helpers and constants stay private: they live in the module's slot frame, reached via attribute access on the `HeapObj::Module` Val, not through the parent chunk's name table. `a.f` calling `helper` resolves through `a`'s attrs, not the importer's globals.
62
62
63
63
The runtime never fetches. The host (browser, WASI, embedded Rust) brings the bytes; the compiler accepts them through `Resolver`.
64
64
65
65
## packages.json
66
66
67
-
Bare-name imports resolve through an import map in `packages.json` (next to the entry script). The manifest is always `packages.json`, no `edge.json` or other variants.
67
+
Bare-name imports resolve through an import map in `packages.json` (next to the entry script). The manifest is always `packages.json` — no `edge.json` or other variants.
68
68
69
69
```json
70
70
{
@@ -81,14 +81,14 @@ Schema:
81
81
- Top-level value is a JSON object. Empty `{}` is valid.
82
82
-`imports` (optional): alias -> spec string.
83
83
-`extends` (optional): directory whose `packages.json` is consulted when an alias isn't found locally.
84
-
-`host` (optional): name -> JS module URL. Read by the browser runtime's `<edge-python>` element to load [host libraries](/reference/packages#host-libraries) on the main thread (DOM, network, storage,...). The compiler itself ignores it (it's one of the silently-ignored keys below); the runtime consumes it. See the [runtime README](https://github.com/dylan-sutton-chavez/edge-python/tree/main/runtime).
84
+
-`host` (optional): name -> JS module URL. Read by the browser runtime's `<edge-python>` element to load [host libraries](/reference/packages#host-libraries) on the main thread (DOM, network, storage…). The compiler itself ignores it (it's one of the silently-ignored keys below); the runtime consumes it. See the [runtime README](https://github.com/dylan-sutton-chavez/edge-python/tree/main/runtime).
`from utils import x` resolves to `./lib/utils.py` relative to the entry script; `from math import add` loads `.wasm` per the [wire format](/reference/wasm-abi).
90
90
91
-
`packages.json` is optional, scripts can use string-form paths directly without project config, and the browser runtime resolves the [official packages](/reference/packages#defaults) by bare name without it.
91
+
`packages.json` is optional — scripts can use string-form paths directly without project config, and the browser runtime resolves the [official packages](/reference/packages#defaults) by bare name without it.
92
92
93
93
### Walk-up resolution
94
94
@@ -97,17 +97,17 @@ Bare-name imports resolve against the nearest `packages.json` walking up from th
97
97
```
98
98
my_app/
99
99
├── packages.json <- root manifest
100
-
├── main.py bare imports here resolve via root manifest
100
+
├── main.py # bare imports here resolve via root manifest
101
101
├── lib/
102
102
│ ├── packages.json <- sub-package manifest
103
-
│ └── helper.py bare imports here resolve via lib/ first
103
+
│ └── helper.py # bare imports here resolve via lib/ first
104
104
└── ...
105
105
```
106
106
107
107
-**Bare-name imports** (`from utils import x`) walk up looking for `packages.json`. First one decides. Capped at 32 hops; over: `packages.json walk-up exceeded <cap> hops resolving '<name>'`.
108
-
-**Hermetic by default**: if the nearest manifest doesn't declare the alias, compilation fails (`alias '<name>' not declared in '<manifest>'`). No silent fall-through, prevents a deep transitive dep from borrowing parent aliases.
108
+
-**Hermetic by default**: if the nearest manifest doesn't declare the alias, compilation fails (`alias '<name>' not declared in '<manifest>'`). No silent fall-through — prevents a deep transitive dep from borrowing parent aliases.
109
109
-**`extends` opts in to inheritance**: `"extends": ".."` re-runs the search from the extended directory when the alias isn't local. Cycles detected at compile time (`circular extends chain in packages.json`).
The compiler asks the host for raw bytes (`Resolver::fetch_bytes`), computes SHA-256, refuses to compile on mismatch, diagnostic surfaces both digests:
172
+
The compiler asks the host for raw bytes (`Resolver::fetch_bytes`), computes SHA-256, refuses to compile on mismatch; the diagnostic surfaces both digests:
173
173
174
174
```text
175
175
error: integrity check failed for 'https://example.com/utils.py'
Verification lives in the compiler, not the host, every host inherits it uniformly. Hosts without `fetch_bytes` surface a clean "not supported" error rather than silently bypassing.
180
+
Verification lives in the compiler, not the host: every host inherits it uniformly. Hosts without `fetch_bytes` surface a clean "not supported" error rather than silently bypassing.
181
181
182
182
Only `sha256` supported. Other prefixes (`md5-...`, `sha384-...`) fail with `unrecognized integrity fragment`. The hex body must be exactly 64 chars.
183
183
184
184
## Lockfile and content-addressed cache
185
185
186
-
The browser worker auto-generates a lockfile and a content-addressed cache (both in IndexedDB) as a side-effect of running scripts that import URLs, repeat runs go to zero network round-trips and upstream drift is detected on demand.
186
+
The browser worker auto-generates a lockfile and a content-addressed cache (both in IndexedDB) as a side-effect of running scripts that import URLs; repeat runs go to zero network round-trips, and upstream drift is detected on demand.
187
187
188
188
| File | Who writes it | Purpose |
189
189
|---|---|---|
@@ -209,7 +209,7 @@ integrity drift for 'https://cdn.foo/kit/index.py'
209
209
210
210
Same primitive as inline `#sha256-...` integrity, applied automatically to every imported URL. Explicit hashes in source are still honoured and fail at compile time before any code runs.
211
211
212
-
Non-browser hosts make their own caching choices,`Resolver` sees only `(spec -> Resolved)` and `(spec -> bytes)`.
212
+
Non-browser hosts make their own caching choices:`Resolver` sees only `(spec -> Resolved)` and `(spec -> bytes)`.
0 commit comments