Skip to content

Commit

Permalink
feat: modularization
Browse files Browse the repository at this point in the history
  • Loading branch information
CNSeniorious000 committed Aug 23, 2024
1 parent 669e6fe commit 9b42bbd
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 65 deletions.
51 changes: 51 additions & 0 deletions reasonify-headless/api/fs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import sys
from functools import cache
from os import chdir
from pathlib import Path

from bridge import with_toast
from js import window
from pyodide.ffi import create_once_callable, create_proxy
from utils.fs import NativeFS, mount


@cache
def _install_slugify():
@with_toast("installing slugify")
@create_once_callable
async def install_slugify():
from reasonify.tools.install import pip_install

await pip_install("python-slugify")

return install_slugify()


mounted: dict[str, NativeFS] = {}


@create_proxy
async def mount_native_fs():
install_promise = _install_slugify()

handle = await window.showDirectoryPicker()
while await handle.requestPermission({"mode": "readwrite"}) != "granted":
pass

await install_promise

from slugify import slugify

name = slugify(handle.name)

fs = await mount(path := str(root / name), handle)

mounted[path] = fs

return name


root = Path("/workspace/mnt")
root.mkdir(parents=True, exist_ok=True)
chdir(root)
sys.path.append(str(root))
5 changes: 5 additions & 0 deletions reasonify-headless/bridge.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from typing import Callable

from pyodide.webloop import PyodideFuture

def with_toast[**Params, Return](message: str) -> Callable[[Callable[Params, Return]], Callable[Params, PyodideFuture[Return]]]: ...
58 changes: 1 addition & 57 deletions reasonify-headless/load.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
import sys
from functools import cache
from os import chdir
from pathlib import Path
from typing import TYPE_CHECKING, Awaitable, Callable

from js import FileSystemDirectoryHandle, window
from micropip import install
from pyodide.ffi import create_once_callable, create_proxy
from pyodide.webloop import PyodideFuture
from typing import TYPE_CHECKING

if TYPE_CHECKING:
sources: dict[str, str] = {}

def with_toast[**Params, Return](message: str) -> Callable[[Callable[Params, Return]], Callable[Params, PyodideFuture[Return]]]: ...


for path, source in sources.items():
file = Path("/home/pyodide", path)
Expand All @@ -26,50 +17,3 @@ def with_toast[**Params, Return](message: str) -> Callable[[Callable[Params, Ret
for module in tuple(sys.modules): # for HMR
if module.startswith("reasonify"):
sys.modules.pop(module).__dict__.clear()

if TYPE_CHECKING:

class NativeFS:
syncfs: Callable[[], Awaitable[None]]

def mount(target: str, handle: FileSystemDirectoryHandle) -> Awaitable[NativeFS]: ...

else:
from pyodide_js import mountNativeFS as mount


@cache
def install_slugify():
@with_toast("installing slugify")
@create_once_callable
async def install_slugify():
await install("python-slugify")

return install_slugify()


@create_proxy
async def mount_native_fs():
handle = await window.showDirectoryPicker()
while await handle.requestPermission({"mode": "readwrite"}) != "granted":
pass

await install_slugify()
from slugify import slugify

name = slugify(handle.name)

fs = await mount(path := str(root / name), handle)

mounted[path] = fs

return name


root = Path("/workspace/mnt")

root.mkdir(parents=True, exist_ok=True)

chdir(root)

mounted: dict[str, "NativeFS"] = {}
19 changes: 19 additions & 0 deletions reasonify-headless/utils/fs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from typing import TYPE_CHECKING, Awaitable, Callable

from js import FileSystemDirectoryHandle

if TYPE_CHECKING:

class NativeFS:
syncfs: Callable[[], Awaitable[None]]

def mount(target: str, handle: FileSystemDirectoryHandle) -> Awaitable[NativeFS]: ...
def unmount(target: str) -> None: ...

else:
from pyodide_js import mountNativeFS as mount
from pyodide_js.FS import unmount

NativeFS = object

__all__ = ["mount", "unmount", "NativeFS"]
2 changes: 2 additions & 0 deletions src/lib/components/Chat.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import type { PythonError } from "pyodide/ffi";
import { type Chain, initChain } from "../py";
import { clearApiCache } from "../py/api";
import Highlight from "./Highlight.svelte";
import Markdown from "./Markdown.svelte";
import { dev } from "$app/environment";
Expand All @@ -23,6 +24,7 @@
refreshing = true;
try {
$reasonifyReady = false;
clearApiCache();
chain = await initChain();
} finally {
refreshing = false;
Expand Down
17 changes: 17 additions & 0 deletions src/lib/py/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { py } from "./load";

const cache = new Map<string, any>();

export function getApi<T>(slug: string): T {
if (cache.has(slug)) {
return cache.get(slug) as T;
} else {
const api = py.pyimport(slug) as T;
cache.set(slug, api);
return api;
}
}

export function clearApiCache() {
cache.clear();
}
6 changes: 2 additions & 4 deletions src/lib/py/fs.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import getGlobals from "./globals";
import { getApi } from "./api";
import { withToast } from "$lib/utils/toast";

const getMount = getGlobals<() => Promise<string>>("mount_native_fs");

export async function mount(): Promise<string> {
const mount = await getMount();
const mount = getApi<() => Promise<string>>("api.fs.mount_native_fs");
return withToast("selecting a directory to mount", (name) => (`mounted ${name}`))(mount)();
}
12 changes: 8 additions & 4 deletions src/lib/py/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ import { dev } from "$app/environment";
import * as env from "$env/static/public";
import { cacheSingleton } from "$lib/utils/cache";
import { withToast } from "$lib/utils/toast";
import { version } from "pyodide";
import { type PyodideInterface, version } from "pyodide";

const indexURL = ("PUBLIC_PYODIDE_INDEX_URL" in env) ? (env.PUBLIC_PYODIDE_INDEX_URL as string).replace("{}", version) : `https://cdn.jsdelivr.net/pyodide/v${version}/full/`;

export const getPy = cacheSingleton(async () => {
const { loadPyodide } = await import("pyodide");
const py = await loadPyodide({ indexURL, packages: ["micropip", "typing-extensions"], args: dev ? [] : ["-O"] });
const pyodide = await loadPyodide({ indexURL, packages: ["micropip", "typing-extensions"], args: dev ? [] : ["-O"] });
pyodide.registerJsModule("bridge", { with_toast: withToast });
pyodideReady.set(true);
py.globals.set("with_toast", withToast);
return py;
py = pyodide;
return pyodide;
});

// eslint-disable-next-line import/no-mutable-exports
export let py: PyodideInterface;

0 comments on commit 9b42bbd

Please sign in to comment.