flet-web 0.86.5__tar.gz → 1.0.0.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/PKG-INFO +2 -2
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/pyproject.toml +2 -2
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/app.py +6 -1
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/flet_app.py +11 -11
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/flet_static_files.py +34 -8
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/patch_index.py +8 -1
- flet_web-1.0.0.dev0/src/flet_web/version.py +1 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web.egg-info/PKG-INFO +2 -2
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web.egg-info/SOURCES.txt +2 -1
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web.egg-info/requires.txt +1 -1
- flet_web-1.0.0.dev0/tests/test_loading_logo.py +43 -0
- flet_web-0.86.5/src/flet_web/version.py +0 -1
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/README.md +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/setup.cfg +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/__init__.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/__init__.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/flet_app_manager.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/flet_fastapi.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/flet_oauth.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/flet_upload.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/oauth_state.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/fastapi/serve_fastapi_web_app.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web/uploads.py +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web.egg-info/dependency_links.txt +0 -0
- {flet_web-0.86.5 → flet_web-1.0.0.dev0}/src/flet_web.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flet-web
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0.dev0
|
|
4
4
|
Summary: Flet web client in Flutter.
|
|
5
5
|
Author-email: "Appveyor Systems Inc." <hello@flet.dev>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -9,7 +9,7 @@ Project-URL: Repository, https://github.com/flet-dev/flet
|
|
|
9
9
|
Project-URL: Documentation, https://flet.dev/docs
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: flet==0.
|
|
12
|
+
Requires-Dist: flet==1.0.0.dev0
|
|
13
13
|
Requires-Dist: fastapi>=0.115.12
|
|
14
14
|
Requires-Dist: uvicorn[standard]>=0.35.0
|
|
15
15
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "flet-web"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "1.0.0.dev0"
|
|
4
4
|
description = "Flet web client in Flutter."
|
|
5
5
|
authors = [{ name = "Appveyor Systems Inc.", email = "hello@flet.dev" }]
|
|
6
6
|
license = "Apache-2.0"
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
requires-python = ">=3.10"
|
|
9
9
|
dependencies = [
|
|
10
|
-
"flet==0.
|
|
10
|
+
"flet==1.0.0.dev0",
|
|
11
11
|
"fastapi >=0.115.12",
|
|
12
12
|
"uvicorn[standard] >=0.35.0"
|
|
13
13
|
]
|
|
@@ -46,7 +46,8 @@ def app(
|
|
|
46
46
|
instance :class:`~flet.Page`.
|
|
47
47
|
before_main: Called after `Page` was created, but before calling `main`.
|
|
48
48
|
proxy_path: URL prefix when the app is mounted under a proxy.
|
|
49
|
-
assets_dir:
|
|
49
|
+
assets_dir: path to app's assets directory. A relative path is resolved
|
|
50
|
+
against the current working directory.
|
|
50
51
|
app_name: PWA application name.
|
|
51
52
|
app_short_name: PWA application short name.
|
|
52
53
|
app_description: PWA application description.
|
|
@@ -64,6 +65,10 @@ def app(
|
|
|
64
65
|
redirecting to OAuth callback URL.
|
|
65
66
|
"""
|
|
66
67
|
|
|
68
|
+
env_assets_dir = os.getenv("FLET_ASSETS_DIR")
|
|
69
|
+
if env_assets_dir:
|
|
70
|
+
assets_dir = env_assets_dir
|
|
71
|
+
|
|
67
72
|
env_upload_dir = os.getenv("FLET_UPLOAD_DIR")
|
|
68
73
|
if env_upload_dir:
|
|
69
74
|
upload_dir = env_upload_dir
|
|
@@ -18,10 +18,10 @@ from flet.controls.context import _context_page, context
|
|
|
18
18
|
from flet.controls.exceptions import FletPageDisconnectedException
|
|
19
19
|
from flet.messaging.connection import Connection
|
|
20
20
|
from flet.messaging.protocol import (
|
|
21
|
-
ClientAction,
|
|
22
|
-
ClientMessage,
|
|
23
21
|
ControlEventBody,
|
|
24
22
|
InvokeMethodResponseBody,
|
|
23
|
+
Message,
|
|
24
|
+
MessageAction,
|
|
25
25
|
RegisterClientRequestBody,
|
|
26
26
|
RegisterClientResponseBody,
|
|
27
27
|
UpdateControlPropsBody,
|
|
@@ -259,7 +259,7 @@ class FletApp(Connection):
|
|
|
259
259
|
async def __on_message(self, data: Any):
|
|
260
260
|
"""
|
|
261
261
|
Handle one decoded client message and dispatch
|
|
262
|
-
by `
|
|
262
|
+
by `MessageAction`.
|
|
263
263
|
|
|
264
264
|
Args:
|
|
265
265
|
data: Decoded message payload from msgpack transport.
|
|
@@ -268,11 +268,11 @@ class FletApp(Connection):
|
|
|
268
268
|
RuntimeError: If message action is unknown.
|
|
269
269
|
"""
|
|
270
270
|
|
|
271
|
-
action =
|
|
271
|
+
action = MessageAction(data[0])
|
|
272
272
|
body = data[1]
|
|
273
273
|
transport_log.debug(f"_on_message: {action} {body}")
|
|
274
274
|
task = None
|
|
275
|
-
if action ==
|
|
275
|
+
if action == MessageAction.REGISTER_CLIENT:
|
|
276
276
|
req = RegisterClientRequestBody(**body)
|
|
277
277
|
|
|
278
278
|
new_session = False
|
|
@@ -335,8 +335,8 @@ class FletApp(Connection):
|
|
|
335
335
|
|
|
336
336
|
# register response
|
|
337
337
|
self.send_message(
|
|
338
|
-
|
|
339
|
-
|
|
338
|
+
Message(
|
|
339
|
+
MessageAction.REGISTER_CLIENT,
|
|
340
340
|
RegisterClientResponseBody(
|
|
341
341
|
session_id=self.__session.id,
|
|
342
342
|
page_patch=self.__session.get_page_patch()
|
|
@@ -379,17 +379,17 @@ class FletApp(Connection):
|
|
|
379
379
|
}
|
|
380
380
|
)
|
|
381
381
|
|
|
382
|
-
elif action ==
|
|
382
|
+
elif action == MessageAction.CONTROL_EVENT:
|
|
383
383
|
req = ControlEventBody(**body)
|
|
384
384
|
task = asyncio.create_task(
|
|
385
385
|
self.__session.dispatch_event(req.target, req.name, req.data)
|
|
386
386
|
)
|
|
387
387
|
|
|
388
|
-
elif action ==
|
|
388
|
+
elif action == MessageAction.UPDATE_CONTROL_PROPS:
|
|
389
389
|
req = UpdateControlPropsBody(**body)
|
|
390
390
|
self.__session.apply_patch(req.id, req.props)
|
|
391
391
|
|
|
392
|
-
elif action ==
|
|
392
|
+
elif action == MessageAction.INVOKE_METHOD:
|
|
393
393
|
req = InvokeMethodResponseBody(**body)
|
|
394
394
|
self.__session.handle_invoke_method_results(
|
|
395
395
|
req.control_id, req.call_id, req.result, req.error
|
|
@@ -403,7 +403,7 @@ class FletApp(Connection):
|
|
|
403
403
|
self.__running_tasks.add(task)
|
|
404
404
|
task.add_done_callback(self.__running_tasks.discard)
|
|
405
405
|
|
|
406
|
-
def send_message(self, message:
|
|
406
|
+
def send_message(self, message: Message):
|
|
407
407
|
"""
|
|
408
408
|
Serialize and enqueue a server message for transport to the client.
|
|
409
409
|
|
|
@@ -28,12 +28,44 @@ mimetypes.add_type("text/javascript", ".mjs")
|
|
|
28
28
|
mimetypes.add_type("application/wasm", ".wasm")
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
def resolve_assets_dir(assets_dir: Optional[str]) -> Optional[str]:
|
|
32
|
+
"""
|
|
33
|
+
Resolve an app's assets directory to an existing absolute path.
|
|
34
|
+
|
|
35
|
+
A relative path is resolved against the current working directory, which
|
|
36
|
+
matches `ft.run(export_asgi_app=True)` - the other way a Flet app is served
|
|
37
|
+
from a server process started externally (e.g. by `uvicorn`).
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
assets_dir: Path to the app's assets directory, absolute or relative.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
The resolved absolute path, or `None` if `assets_dir` was not set or
|
|
44
|
+
does not exist.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
if not assets_dir:
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
path = Path(assets_dir)
|
|
51
|
+
if not path.is_absolute():
|
|
52
|
+
path = Path.cwd().joinpath(path)
|
|
53
|
+
resolved = str(path.resolve())
|
|
54
|
+
|
|
55
|
+
if not os.path.exists(resolved):
|
|
56
|
+
logger.warning(f"assets_dir does not exist: {resolved}")
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
return resolved
|
|
60
|
+
|
|
61
|
+
|
|
31
62
|
class FletStaticFiles(StaticFiles):
|
|
32
63
|
"""
|
|
33
64
|
Serve Flet app static files.
|
|
34
65
|
|
|
35
66
|
Args:
|
|
36
|
-
assets_dir:
|
|
67
|
+
assets_dir: Path to app's assets directory. A relative path is resolved
|
|
68
|
+
against the current working directory.
|
|
37
69
|
app_name: PWA application name.
|
|
38
70
|
app_short_name: PWA application short name.
|
|
39
71
|
app_description: PWA application description.
|
|
@@ -151,13 +183,7 @@ class FletStaticFiles(StaticFiles):
|
|
|
151
183
|
raise RuntimeError(f"Web root path not found: {web_dir}")
|
|
152
184
|
|
|
153
185
|
# user-defined assets
|
|
154
|
-
|
|
155
|
-
if not Path(self.__assets_dir).is_absolute():
|
|
156
|
-
logger.warning("assets_dir must be absolute path.")
|
|
157
|
-
self.__assets_dir = None
|
|
158
|
-
elif not os.path.exists(self.__assets_dir):
|
|
159
|
-
logger.info(f"assets_dir does not exist: {self.__assets_dir}")
|
|
160
|
-
self.__assets_dir = None
|
|
186
|
+
self.__assets_dir = resolve_assets_dir(self.__assets_dir)
|
|
161
187
|
|
|
162
188
|
logger.info(f"Assets dir: {self.__assets_dir}")
|
|
163
189
|
|
|
@@ -70,7 +70,7 @@ def patch_index_html(
|
|
|
70
70
|
# loads it via dynamic `import()`. We can no longer use `.js` because
|
|
71
71
|
# Pyodide >= 0.29 throws "Classic web workers are not supported" inside
|
|
72
72
|
# any worker that has `importScripts` available — only classic workers
|
|
73
|
-
# have it. All supported Pyodide versions (0.27.7 / 0.29.4 / 314.0.
|
|
73
|
+
# have it. All supported Pyodide versions (0.27.7 / 0.29.4 / 314.0.6)
|
|
74
74
|
# ship `pyodide.mjs`.
|
|
75
75
|
if pyodide_version:
|
|
76
76
|
if no_cdn:
|
|
@@ -81,6 +81,13 @@ def patch_index_html(
|
|
|
81
81
|
)
|
|
82
82
|
app_config.append(f'flet.pyodideUrl="{pyodide_url}";')
|
|
83
83
|
|
|
84
|
+
# Only pinned when bundling: left unset, `flutter_bootstrap.js` lets
|
|
85
|
+
# Flutter resolve CanvasKit from gstatic and the Noto fallback fonts from
|
|
86
|
+
# Google Fonts, and `flet build`/`flet publish` skip shipping local copies.
|
|
87
|
+
if no_cdn:
|
|
88
|
+
app_config.append(f'flet.canvasKitBaseUrl="{base_url}canvaskit/";')
|
|
89
|
+
app_config.append('flet.fontFallbackBaseUrl="assets/fonts/";')
|
|
90
|
+
|
|
84
91
|
app_config.append(f"flet.noCdn={str(no_cdn).lower()};")
|
|
85
92
|
app_config.append(f'flet.webRenderer="{web_renderer.value}";')
|
|
86
93
|
app_config.append(f'flet.routeUrlStrategy="{route_url_strategy.value}";')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "1.0.0.dev0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flet-web
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0.dev0
|
|
4
4
|
Summary: Flet web client in Flutter.
|
|
5
5
|
Author-email: "Appveyor Systems Inc." <hello@flet.dev>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -9,7 +9,7 @@ Project-URL: Repository, https://github.com/flet-dev/flet
|
|
|
9
9
|
Project-URL: Documentation, https://flet.dev/docs
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: flet==0.
|
|
12
|
+
Requires-Dist: flet==1.0.0.dev0
|
|
13
13
|
Requires-Dist: fastapi>=0.115.12
|
|
14
14
|
Requires-Dist: uvicorn[standard]>=0.35.0
|
|
15
15
|
|
|
@@ -18,4 +18,5 @@ src/flet_web/fastapi/flet_oauth.py
|
|
|
18
18
|
src/flet_web/fastapi/flet_static_files.py
|
|
19
19
|
src/flet_web/fastapi/flet_upload.py
|
|
20
20
|
src/flet_web/fastapi/oauth_state.py
|
|
21
|
-
src/flet_web/fastapi/serve_fastapi_web_app.py
|
|
21
|
+
src/flet_web/fastapi/serve_fastapi_web_app.py
|
|
22
|
+
tests/test_loading_logo.py
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import shutil
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from fastapi import FastAPI
|
|
7
|
+
from fastapi.testclient import TestClient
|
|
8
|
+
|
|
9
|
+
static_files = importlib.import_module("flet_web.fastapi.flet_static_files")
|
|
10
|
+
CLIENT_WEB = Path(__file__).resolve().parents[5] / "client" / "web"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.parametrize("custom_logo", [False, True])
|
|
14
|
+
def test_dynamic_loading_logo_respects_assets_override(
|
|
15
|
+
tmp_path, monkeypatch, custom_logo
|
|
16
|
+
):
|
|
17
|
+
web = tmp_path / "web"
|
|
18
|
+
shutil.copytree(CLIENT_WEB, web)
|
|
19
|
+
# Flutter substitutes this token before packaging the dynamic client.
|
|
20
|
+
index = web / "index.html"
|
|
21
|
+
index.write_text(index.read_text().replace("$FLUTTER_BASE_HREF", "/"))
|
|
22
|
+
monkeypatch.setattr(static_files, "get_package_web_dir", lambda: str(web))
|
|
23
|
+
assets = tmp_path / "assets"
|
|
24
|
+
assets.mkdir()
|
|
25
|
+
relative = Path("icons/loading-animation.png")
|
|
26
|
+
expected = (CLIENT_WEB / relative).read_bytes()
|
|
27
|
+
if custom_logo:
|
|
28
|
+
# Serving must preserve the user's bytes instead of regenerating the logo.
|
|
29
|
+
expected = b"custom loading logo"
|
|
30
|
+
(assets / "icons").mkdir()
|
|
31
|
+
(assets / relative).write_bytes(expected)
|
|
32
|
+
|
|
33
|
+
app = FastAPI()
|
|
34
|
+
app.mount("/demo", static_files.FletStaticFiles(assets_dir=str(assets)))
|
|
35
|
+
with TestClient(app) as client:
|
|
36
|
+
page = client.get("/demo/nested/route")
|
|
37
|
+
assert page.status_code == 200
|
|
38
|
+
assert '<base href="/demo/">' in page.text
|
|
39
|
+
assert 'src="icons/loading-animation.png"' in page.text
|
|
40
|
+
assert "@keyframes" not in page.text
|
|
41
|
+
logo = client.get("/demo/icons/loading-animation.png")
|
|
42
|
+
assert logo.status_code == 200
|
|
43
|
+
assert logo.content == expected
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version = "0.86.5"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|