Skip to content

Commit 30b54a6

Browse files
committed
Pyodide bootstrap: zip/tar.gz app package + pyproject.toml deps
1 parent f225182 commit 30b54a6

3 files changed

Lines changed: 79 additions & 9 deletions

File tree

client/web/python-worker.js

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ self.initPyodide = async function () {
2424
if "app_package_url" in py_args:
2525
app_package_url = py_args["app_package_url"]
2626
27-
if app_package_url is None:
28-
app_package_url = "assets/app/app.zip"
29-
3027
if "python_module_name" in py_args:
3128
python_module_name = py_args["python_module_name"]
3229
@@ -45,7 +42,22 @@ self.initPyodide = async function () {
4542
if "script" not in py_args:
4643
print("Downloading app archive")
4744
response = await pyfetch(app_package_url)
48-
await response.unpack_archive()
45+
# Pick format from the URL's path extension. Pyodide's
46+
# filename-based sniff trips over query strings like
47+
# ?v=42. We only support zip and tar.gz (matching what
48+
# our server and "flet publish" emit).
49+
from urllib.parse import urlparse
50+
_archive_path = urlparse(app_package_url).path.lower()
51+
if _archive_path.endswith(".zip"):
52+
_archive_format = "zip"
53+
elif _archive_path.endswith((".tar.gz", ".tgz")):
54+
_archive_format = "gztar"
55+
else:
56+
raise ValueError(
57+
f"Unsupported app package URL: {app_package_url} "
58+
"(expected .zip or .tar.gz)"
59+
)
60+
await response.unpack_archive(format=_archive_format)
4961
else:
5062
print("Saving script to a file")
5163
with open(f"{python_module_name}.py", "w") as f:
@@ -77,6 +89,29 @@ self.initPyodide = async function () {
7789
print("Loading requirements.txt:", deps)
7890
await micropip.install(deps, pre=micropip_include_pre)
7991
92+
if os.path.exists("pyproject.toml"):
93+
import tomllib
94+
with open("pyproject.toml", "rb") as f:
95+
pyproject = tomllib.load(f)
96+
project_deps = list(
97+
pyproject.get("project", {}).get("dependencies", []) or []
98+
)
99+
web_deps = list(
100+
pyproject.get("tool", {})
101+
.get("flet", {})
102+
.get("web", {})
103+
.get("dependencies", [])
104+
or []
105+
)
106+
# [tool.flet.web].dependencies overrides [project].dependencies
107+
# by package name — install in order so the web-specific specs
108+
# win through micropip's last-writer-wins dedupe.
109+
pyproject_deps = project_deps + web_deps
110+
if pyproject_deps:
111+
micropip = await ensure_micropip()
112+
print("Loading pyproject.toml deps:", pyproject_deps)
113+
await micropip.install(pyproject_deps, pre=micropip_include_pre)
114+
80115
if "dependencies" in py_args:
81116
micropip = await ensure_micropip()
82117
await micropip.install(py_args["dependencies"], pre=micropip_include_pre)

packages/flet/lib/src/utils/platform_utils_web.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ extension FletJSExtension on FletJS {
5353
external String get canvasKitBaseUrl;
5454
external String get pyodideUrl;
5555
external String get webRenderer;
56-
external bool get appPackageUrl;
56+
external String? get appPackageUrl;
5757
}
5858

5959
@JS('flet')

sdk/python/templates/build/{{cookiecutter.out_dir}}/web/python-worker.js

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ self.initPyodide = async function () {
2424
if "app_package_url" in py_args:
2525
app_package_url = py_args["app_package_url"]
2626
27-
if app_package_url is None:
28-
app_package_url = "assets/app/app.zip"
29-
3027
if "python_module_name" in py_args:
3128
python_module_name = py_args["python_module_name"]
3229
@@ -45,7 +42,22 @@ self.initPyodide = async function () {
4542
if "script" not in py_args:
4643
print("Downloading app archive")
4744
response = await pyfetch(app_package_url)
48-
await response.unpack_archive()
45+
# Pick format from the URL's path extension. Pyodide's
46+
# filename-based sniff trips over query strings like
47+
# ?v=42. We only support zip and tar.gz (matching what
48+
# our server and "flet publish" emit).
49+
from urllib.parse import urlparse
50+
_archive_path = urlparse(app_package_url).path.lower()
51+
if _archive_path.endswith(".zip"):
52+
_archive_format = "zip"
53+
elif _archive_path.endswith((".tar.gz", ".tgz")):
54+
_archive_format = "gztar"
55+
else:
56+
raise ValueError(
57+
f"Unsupported app package URL: {app_package_url} "
58+
"(expected .zip or .tar.gz)"
59+
)
60+
await response.unpack_archive(format=_archive_format)
4961
else:
5062
print("Saving script to a file")
5163
with open(f"{python_module_name}.py", "w") as f:
@@ -77,6 +89,29 @@ self.initPyodide = async function () {
7789
print("Loading requirements.txt:", deps)
7890
await micropip.install(deps, pre=micropip_include_pre)
7991
92+
if os.path.exists("pyproject.toml"):
93+
import tomllib
94+
with open("pyproject.toml", "rb") as f:
95+
pyproject = tomllib.load(f)
96+
project_deps = list(
97+
pyproject.get("project", {}).get("dependencies", []) or []
98+
)
99+
web_deps = list(
100+
pyproject.get("tool", {})
101+
.get("flet", {})
102+
.get("web", {})
103+
.get("dependencies", [])
104+
or []
105+
)
106+
# [tool.flet.web].dependencies overrides [project].dependencies
107+
# by package name — install in order so the web-specific specs
108+
# win through micropip's last-writer-wins dedupe.
109+
pyproject_deps = project_deps + web_deps
110+
if pyproject_deps:
111+
micropip = await ensure_micropip()
112+
print("Loading pyproject.toml deps:", pyproject_deps)
113+
await micropip.install(pyproject_deps, pre=micropip_include_pre)
114+
80115
if "dependencies" in py_args:
81116
micropip = await ensure_micropip()
82117
await micropip.install(py_args["dependencies"], pre=micropip_include_pre)

0 commit comments

Comments
 (0)