flet-web 0.85.3.dev1__tar.gz → 0.86.0.dev1__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.
Files changed (24) hide show
  1. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/PKG-INFO +2 -2
  2. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/pyproject.toml +2 -2
  3. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/flet_app.py +53 -5
  4. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/patch_index.py +20 -0
  5. flet_web-0.86.0.dev1/src/flet_web/version.py +1 -0
  6. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web.egg-info/PKG-INFO +2 -2
  7. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web.egg-info/requires.txt +1 -1
  8. flet_web-0.85.3.dev1/src/flet_web/version.py +0 -1
  9. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/README.md +0 -0
  10. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/setup.cfg +0 -0
  11. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/__init__.py +0 -0
  12. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/__init__.py +0 -0
  13. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/app.py +0 -0
  14. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/flet_app_manager.py +0 -0
  15. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/flet_fastapi.py +0 -0
  16. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/flet_oauth.py +0 -0
  17. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/flet_static_files.py +0 -0
  18. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/flet_upload.py +0 -0
  19. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/oauth_state.py +0 -0
  20. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/fastapi/serve_fastapi_web_app.py +0 -0
  21. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web/uploads.py +0 -0
  22. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web.egg-info/SOURCES.txt +0 -0
  23. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/src/flet_web.egg-info/dependency_links.txt +0 -0
  24. {flet_web-0.85.3.dev1 → flet_web-0.86.0.dev1}/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.85.3.dev1
3
+ Version: 0.86.0.dev1
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.85.3.dev1
12
+ Requires-Dist: flet==0.86.0.dev1
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.85.3.dev1"
3
+ version = "0.86.0.dev1"
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.85.3.dev1",
10
+ "flet==0.86.0.dev1",
11
11
  "fastapi >=0.115.12",
12
12
  "uvicorn[standard] >=0.35.0"
13
13
  ]
@@ -96,6 +96,11 @@ class FletApp(Connection):
96
96
  self.__upload_endpoint_path = upload_endpoint_path
97
97
  self.__secret_key = secret_key
98
98
 
99
+ # DataChannel mux registry keyed by channel_id minted on the Dart
100
+ # side. Populated lazily on the first Control.get_data_channel(id)
101
+ # call. Frames for unknown ids are silently dropped.
102
+ self._data_channels: dict[int, Any] = {}
103
+
99
104
  app_id = self.__id
100
105
  weakref.finalize(
101
106
  self, lambda: logger.info(f"FletApp was garbage collected: {app_id}")
@@ -214,6 +219,11 @@ class FletApp(Connection):
214
219
  """
215
220
  Receive binary frames from WebSocket and dispatch decoded client messages.
216
221
 
222
+ Wire format: each WebSocket binary frame is one packet —
223
+ `[type:u8][payload]`. type=0x00 is a MsgPack-encoded Flet protocol
224
+ frame; type=0x01 is a raw DataChannel frame
225
+ (`[channel_id:u32 LE][bytes]`).
226
+
217
227
  On disconnect/error, terminates send loop via queue sentinel when a
218
228
  session is active.
219
229
  """
@@ -222,9 +232,23 @@ class FletApp(Connection):
222
232
  try:
223
233
  while True:
224
234
  data = await self.__websocket.receive_bytes()
225
- await self.__on_message(
226
- msgpack.unpackb(data, ext_hook=decode_ext_from_msgpack)
227
- )
235
+ if not data:
236
+ continue
237
+ ptype = data[0]
238
+ if ptype == 0x00:
239
+ await self.__on_message(
240
+ msgpack.unpackb(data[1:], ext_hook=decode_ext_from_msgpack)
241
+ )
242
+ elif ptype == 0x01:
243
+ if len(data) < 5:
244
+ logger.debug("Dropping malformed data-channel frame.")
245
+ continue
246
+ channel_id = int.from_bytes(data[1:5], "little", signed=False)
247
+ channel = self._data_channels.get(channel_id)
248
+ if channel is not None:
249
+ channel._deliver(data[5:])
250
+ else:
251
+ logger.debug("Dropping packet with unknown type 0x%02x", ptype)
228
252
  except Exception as e:
229
253
  if not isinstance(e, WebSocketDisconnect):
230
254
  logger.warning(f"Receive loop error: {e}", exc_info=True)
@@ -383,16 +407,40 @@ class FletApp(Connection):
383
407
  """
384
408
  Serialize and enqueue a server message for transport to the client.
385
409
 
410
+ Wire format: one packet per `send_bytes` call —
411
+ `[0x00][msgpack body]`. WebSocket preserves message boundaries so
412
+ no length prefix is needed.
413
+
386
414
  Args:
387
415
  message: Outbound protocol message.
388
416
  """
389
417
 
390
418
  transport_log.debug(f"send_message: {message}")
391
- m = msgpack.packb(
419
+ body = msgpack.packb(
392
420
  [message.action, message.body],
393
421
  default=configure_encode_object_for_msgpack(BaseControl),
394
422
  )
395
- self.__send_queue.put_nowait(m)
423
+ self.__send_queue.put_nowait(b"\x00" + body)
424
+
425
+ def send_data_channel_frame(self, channel_id: int, payload: bytes) -> None:
426
+ """Send a raw DataChannel frame `[0x01][channel_id:u32 LE][bytes]`
427
+ over the WebSocket. Called by `_ProtocolMuxedDataChannel.send`."""
428
+ header = b"\x01" + channel_id.to_bytes(4, "little", signed=False)
429
+ self.__send_queue.put_nowait(header + payload)
430
+
431
+ def data_channel_for(self, channel_id: int):
432
+ """Resolve or construct the muxed DataChannel for `channel_id`."""
433
+ from flet.data_channel import _ProtocolMuxedDataChannel
434
+
435
+ existing = self._data_channels.get(channel_id)
436
+ if existing is not None:
437
+ return existing
438
+ channel = _ProtocolMuxedDataChannel(channel_id, self)
439
+ self._data_channels[channel_id] = channel
440
+ return channel
441
+
442
+ def unregister_data_channel(self, channel_id: int) -> None:
443
+ self._data_channels.pop(channel_id, None)
396
444
 
397
445
  def get_upload_url(self, file_name: str, expires: int) -> str:
398
446
  """
@@ -15,6 +15,7 @@ def patch_index_html(
15
15
  pyodide: bool = False,
16
16
  pyodide_pre: bool = False,
17
17
  pyodide_script_path: str = "",
18
+ pyodide_version: Optional[str] = None,
18
19
  web_renderer: WebRenderer = WebRenderer.AUTO,
19
20
  route_url_strategy: RouteUrlStrategy = RouteUrlStrategy.PATH,
20
21
  no_cdn: bool = False,
@@ -61,6 +62,25 @@ def patch_index_html(
61
62
  app_config.append(f"flet.micropipIncludePre = {str(pyodide_pre).lower()};")
62
63
  app_config.append(f'flet.pythonModuleName = "{module_name}";')
63
64
 
65
+ # Pin the Pyodide runtime URL for this build. The web client used to fall
66
+ # back to a hardcoded CDN URL when not in no-cdn mode; with multi-version
67
+ # support that constant is gone, so we always inject the URL here.
68
+ #
69
+ # `.mjs` is the ES-module variant; python-worker.js (a module worker)
70
+ # loads it via dynamic `import()`. We can no longer use `.js` because
71
+ # Pyodide >= 0.29 throws "Classic web workers are not supported" inside
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.0)
74
+ # ship `pyodide.mjs`.
75
+ if pyodide_version:
76
+ if no_cdn:
77
+ pyodide_url = "pyodide/pyodide.mjs"
78
+ else:
79
+ pyodide_url = (
80
+ f"https://cdn.jsdelivr.net/pyodide/v{pyodide_version}/full/pyodide.mjs"
81
+ )
82
+ app_config.append(f'flet.pyodideUrl="{pyodide_url}";')
83
+
64
84
  app_config.append(f"flet.noCdn={str(no_cdn).lower()};")
65
85
  app_config.append(f'flet.webRenderer="{web_renderer.value}";')
66
86
  app_config.append(f'flet.routeUrlStrategy="{route_url_strategy.value}";')
@@ -0,0 +1 @@
1
+ version = "0.86.0.dev1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet-web
3
- Version: 0.85.3.dev1
3
+ Version: 0.86.0.dev1
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.85.3.dev1
12
+ Requires-Dist: flet==0.86.0.dev1
13
13
  Requires-Dist: fastapi>=0.115.12
14
14
  Requires-Dist: uvicorn[standard]>=0.35.0
15
15
 
@@ -1,3 +1,3 @@
1
- flet==0.85.3.dev1
1
+ flet==0.86.0.dev1
2
2
  fastapi>=0.115.12
3
3
  uvicorn[standard]>=0.35.0
@@ -1 +0,0 @@
1
- version = "0.85.3.dev1"
File without changes
File without changes