Skip to content

Commit 7f24102

Browse files
authored
✨ Allow setting micropip index_urls to Mahoraga (#18)
* ✨ Pyodide compat * 📝 Pyodide configurations
1 parent 39295d9 commit 7f24102

6 files changed

Lines changed: 120 additions & 211 deletions

File tree

docs/advanced/stlite.md

Lines changed: 0 additions & 207 deletions
This file was deleted.

docs/stylesheets/extra.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
:root>* {
66
--md-accent-fg-color--transparent: #d6e8bb1a;
77
--md-accent-fg-color: #d6e8bb;
8+
--md-code-hl-color: #6b8e7b;
9+
--md-code-hl-color--light: #6b8e7b1a;
810
--md-code-hl-constant-color: #6b8e7b;
911
--md-code-hl-function-color: var(--md-code-fg-color);
1012
--md-code-hl-keyword-color: #6b8e7b;

docs/tutorial.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,112 @@ not like to share between Pixi and rattler-build.
157157
...
158158
```
159159

160+
### Pyodide
161+
!!! note
162+
163+
Mirror configuration requires Pyodide version 0.28.0 or later.
164+
[Pyodide][10] Python distribution, wheels and JavaScript/WebAssembly runtime are
165+
all available in Mahoraga. To enable them, add the following line to your
166+
`mahoraga.toml`:
167+
``` toml title="mahoraga.toml" hl_lines="3"
168+
[cors]
169+
allow-origins = [
170+
"*",
171+
]
172+
```
173+
The frontend configuration depends on the library you directly use:
174+
=== "Pyodide"
175+
176+
``` html hl_lines="6 13-22 24"
177+
<!doctype html>
178+
<html>
179+
<head>
180+
<meta charset="UTF-8">
181+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
182+
<script type="text/javascript" src="http://127.0.0.1:3450/pyodide/v0.28.0/full/pyodide.js"></script>
183+
</head>
184+
<body>
185+
<script type="text/javascript">
186+
async function main() {
187+
let pyodide = await loadPyodide();
188+
await pyodide.loadPackage("micropip");
189+
// Prefer Pyodide-maintained wheels over PyPI ones
190+
// If this is not desired, remove the following lines
191+
pyodide.runPython(`
192+
import micropip
193+
class _Transaction(micropip.transaction.Transaction):
194+
def __post_init__(self):
195+
super().__post_init__()
196+
self.search_pyodide_lock_first = True
197+
micropip.package_manager.Transaction = _Transaction
198+
`);
199+
const micropip = pyodide.pyimport("micropip");
200+
micropip.set_index_urls("http://127.0.0.1:3450/pypi/simple/{package_name}/?micropip=1");
201+
await micropip.install(["your_package"]);
202+
pyodide.runPython(`# Your Python code here`);
203+
}
204+
main();
205+
</script>
206+
</body>
207+
</html>
208+
```
209+
210+
=== "PyScript"
211+
212+
``` html hl_lines="6 7 11 12"
213+
<!doctype html>
214+
<html>
215+
<head>
216+
<meta charset="UTF-8">
217+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
218+
<script type="module" src="http://127.0.0.1:3450/npm/@pyscript/core@0/dist/core.js"></script>
219+
<link rel="stylesheet" href="http://127.0.0.1:3450/npm/@pyscript/core@0/dist/core.css">
220+
</head>
221+
<body>
222+
<script type="py" config='{
223+
"index_urls": ["http://127.0.0.1:3450/pypi/simple/{package_name}/?micropip=1"],
224+
"interpreter": "http://127.0.0.1:3450/pyodide/v0.28.0/full/pyodide.mjs",
225+
"packages": ["your_package"]
226+
}'># Your Python code here</script>
227+
</body>
228+
</html>
229+
```
230+
231+
=== "Stlite"
232+
233+
``` html hl_lines="6 11 14 16-19"
234+
<!doctype html>
235+
<html>
236+
<head>
237+
<meta charset="UTF-8">
238+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
239+
<link rel="stylesheet" href="http://127.0.0.1:3450/npm/@stlite/browser@0/build/stlite.css">
240+
</head>
241+
<body>
242+
<div id="root"></div>
243+
<script type="module">
244+
import { mount } from "http://127.0.0.1:3450/npm/@stlite/browser@0/build/stlite.js";
245+
mount(
246+
{
247+
pyodideUrl: "http://127.0.0.1:3450/pyodide/v{{ pyodide_py_version }}/full/pyodide.js",
248+
requirements: [
249+
// Stlite doesn't expose the `index_urls` option,
250+
// hence the absolute wheel urls here
251+
"http://127.0.0.1:3450/pypi/packages/py3/b/blinker/blinker-{{ blinker_version }}-py3-none-any.whl",
252+
"http://127.0.0.1:3450/pypi/packages/py3/t/tenacity/tenacity-{{ tenacity_version }}-py3-none-any.whl",
253+
],
254+
entrypoint: "your_app.py",
255+
files: {
256+
"your_app.py": `# Your Python code here`,
257+
},
258+
},
259+
document.getElementById("root"),
260+
);
261+
</script>
262+
</body>
263+
</html>
264+
```
265+
160266
### pymanager
161267
The next generation of the official Python installer for Windows,
162268
[pymanager][4], can be downloaded from Mahoraga:
@@ -186,3 +292,4 @@ The next generation of the official Python installer for Windows,
186292
[7]: #server-configuration
187293
[8]: https://rattler.build/latest/
188294
[9]: #pixi
295+
[10]: https://pyodide.org/en/stable/

mkdocs.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ nav:
99
- tutorial.md
1010
- Advanced:
1111
- advanced/pyapp.md
12-
- advanced/stlite.md
1312

1413
exclude_docs: |
1514
__pycache__

src/mahoraga/_jsdelivr/_npm.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
router = fastapi.APIRouter(route_class=_core.APIRoute)
3535

3636

37+
@router.get("/@bokeh/{package}/{path:path}")
38+
@router.get("/@holoviz/{package}/{path:path}")
39+
@router.get("/@pyscript/{package}/{path:path}")
3740
@router.get("/@stlite/{package}/{path:path}")
3841
async def get_scoped_npm_file(
3942
package: Annotated[str, fastapi.Path(pattern=r"^[^@]+@[^@]+$")],
@@ -63,8 +66,8 @@ async def get_npm_file(
6366
},
6467
)
6568
prefix = request.url.path.removeprefix("/npm")
66-
if prefix.startswith("/@stlite"):
67-
scope = "stlite"
69+
if prefix.startswith("/@"):
70+
scope, _ = prefix[2:].split("/", 1)
6871
elif package.startswith(("pyodide@", "swagger-ui-dist@")):
6972
scope = None
7073
else:

src/mahoraga/_pypi/_simple.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,14 @@ async def get_pypi_project(
3636
description="See [PEP 691](https://peps.python.org/pep-0691/)",
3737
),
3838
] = None,
39+
*,
40+
micropip: Annotated[bool, fastapi.Query()] = False,
3941
) -> fastapi.Response:
4042
ctx = _core.context.get()
41-
media_type = _decide_content_type(accept)
43+
if micropip:
44+
media_type = "application/vnd.pypi.simple.v1+html"
45+
else:
46+
media_type = _decide_content_type(accept)
4247
if media_type == "application/vnd.pypi.simple.v1+json":
4348
urls = [
4449
posixpath.join(str(url), "simple", project) + "/"

0 commit comments

Comments
 (0)