flet 0.70.0.dev5776__py3-none-any.whl → 0.70.0.dev5835__py3-none-any.whl

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.

Potentially problematic release.


This version of flet might be problematic. Click here for more details.

Files changed (44) hide show
  1. flet/__init__.py +32 -4
  2. flet/components/__init__.py +0 -0
  3. flet/components/component.py +346 -0
  4. flet/components/component_decorator.py +24 -0
  5. flet/components/component_owned.py +22 -0
  6. flet/components/hooks/__init__.py +0 -0
  7. flet/components/hooks/hook.py +12 -0
  8. flet/components/hooks/use_callback.py +28 -0
  9. flet/components/hooks/use_context.py +91 -0
  10. flet/components/hooks/use_effect.py +104 -0
  11. flet/components/hooks/use_memo.py +52 -0
  12. flet/components/hooks/use_state.py +58 -0
  13. flet/components/memo.py +34 -0
  14. flet/components/observable.py +269 -0
  15. flet/components/public_utils.py +10 -0
  16. flet/components/utils.py +85 -0
  17. flet/controls/base_control.py +34 -10
  18. flet/controls/base_page.py +44 -40
  19. flet/controls/context.py +22 -1
  20. flet/controls/control_event.py +19 -2
  21. flet/controls/core/column.py +5 -0
  22. flet/controls/core/drag_target.py +17 -8
  23. flet/controls/core/row.py +5 -0
  24. flet/controls/core/view.py +6 -6
  25. flet/controls/id_counter.py +24 -0
  26. flet/controls/material/divider.py +6 -0
  27. flet/controls/material/textfield.py +10 -1
  28. flet/controls/material/vertical_divider.py +6 -0
  29. flet/controls/object_patch.py +434 -197
  30. flet/controls/page.py +203 -84
  31. flet/controls/services/haptic_feedback.py +0 -3
  32. flet/controls/services/shake_detector.py +0 -3
  33. flet/messaging/flet_socket_server.py +13 -6
  34. flet/messaging/session.py +103 -10
  35. flet/{controls/session_storage.py → messaging/session_store.py} +2 -2
  36. flet/version.py +1 -1
  37. {flet-0.70.0.dev5776.dist-info → flet-0.70.0.dev5835.dist-info}/METADATA +5 -5
  38. {flet-0.70.0.dev5776.dist-info → flet-0.70.0.dev5835.dist-info}/RECORD +41 -28
  39. flet/controls/cache.py +0 -87
  40. flet/controls/control_id.py +0 -22
  41. flet/controls/core/state_view.py +0 -60
  42. {flet-0.70.0.dev5776.dist-info → flet-0.70.0.dev5835.dist-info}/WHEEL +0 -0
  43. {flet-0.70.0.dev5776.dist-info → flet-0.70.0.dev5835.dist-info}/entry_points.txt +0 -0
  44. {flet-0.70.0.dev5776.dist-info → flet-0.70.0.dev5835.dist-info}/top_level.txt +0 -0
flet/messaging/session.py CHANGED
@@ -5,6 +5,7 @@ import weakref
5
5
  from datetime import datetime, timedelta, timezone
6
6
  from typing import Any, Optional
7
7
 
8
+ from flet.components.hooks.use_effect import EffectHook
8
9
  from flet.controls.base_control import BaseControl
9
10
  from flet.controls.context import _context_page, context
10
11
  from flet.controls.object_patch import ObjectPatch
@@ -17,11 +18,13 @@ from flet.messaging.protocol import (
17
18
  PatchControlBody,
18
19
  SessionCrashedBody,
19
20
  )
21
+ from flet.messaging.session_store import SessionStore
20
22
  from flet.pubsub.pubsub_client import PubSubClient
21
23
  from flet.utils.object_model import patch_dataclass
22
24
  from flet.utils.strings import random_string
23
25
 
24
26
  logger = logging.getLogger("flet")
27
+ patch_logger = logging.getLogger("flet_object_patch")
25
28
 
26
29
  __all__ = ["Session"]
27
30
 
@@ -37,9 +40,14 @@ class Session:
37
40
  )
38
41
  self.__page = Page(self)
39
42
  self.__index[self.__page._i] = self.__page
43
+ self.__store: SessionStore = SessionStore()
40
44
  self.__pubsub_client = PubSubClient(conn.pubsubhub, self.__id)
41
45
  self.__method_calls: dict[str, asyncio.Event] = {}
42
46
  self.__method_call_results: dict[asyncio.Event, tuple[Any, Optional[str]]] = {}
47
+ self.__updates_ready: asyncio.Event = asyncio.Event()
48
+ self.__pending_updates: set[BaseControl] = set()
49
+ self.__pending_effects: list[tuple[weakref.ref[EffectHook], bool]] = []
50
+ self.__closed = False
43
51
 
44
52
  session_id = self.__id
45
53
  weakref.finalize(
@@ -70,6 +78,10 @@ class Session:
70
78
  def pubsub_client(self) -> PubSubClient:
71
79
  return self.__pubsub_client
72
80
 
81
+ @property
82
+ def store(self) -> SessionStore:
83
+ return self.__store
84
+
73
85
  async def connect(self, conn: Connection) -> None:
74
86
  logger.debug(f"Connect session: {self.id}")
75
87
  _context_page.set(self.__page)
@@ -92,18 +104,30 @@ class Session:
92
104
 
93
105
  def close(self):
94
106
  logger.debug(f"Closing expired session: {self.id}")
107
+ self.__closed = True
95
108
  self.__pubsub_client.unsubscribe_all()
96
109
  self.__cancel_method_calls()
97
110
  asyncio.create_task(self.dispatch_event(self.__page._i, "close", None))
98
111
 
99
- def patch_control(self, control: BaseControl):
112
+ def patch_control(
113
+ self,
114
+ control: BaseControl,
115
+ prev_control: Optional[BaseControl] = None,
116
+ parent: Any = None,
117
+ path: Optional[list[Any]] = None,
118
+ frozen: bool = False,
119
+ ):
100
120
  patch, added_controls, removed_controls = self.__get_update_control_patch(
101
- control=control, prev_control=control
121
+ control=control,
122
+ prev_control=prev_control or control,
123
+ parent=parent,
124
+ path=path,
125
+ frozen=frozen,
102
126
  )
103
127
 
104
- # print(f"\n\nremoved_controls: ({len(removed_controls)})")
105
- # for c in removed_controls:
106
- # print(f"\n\nremoved_control: {c._c}({c._i} - {id(c)})")
128
+ patch_logger.debug(f"\npatch removed_controls ({len(removed_controls)}):")
129
+ for c in removed_controls:
130
+ patch_logger.debug(" %s", c)
107
131
 
108
132
  for removed_control in removed_controls:
109
133
  if not any(added._i == removed_control._i for added in added_controls):
@@ -113,13 +137,14 @@ class Session:
113
137
  if len(patch) > 1:
114
138
  self.__send_message(
115
139
  ClientMessage(
116
- ClientAction.PATCH_CONTROL, PatchControlBody(control._i, patch)
140
+ ClientAction.PATCH_CONTROL,
141
+ PatchControlBody(parent._i if parent else control._i, patch),
117
142
  )
118
143
  )
119
144
 
120
- # print(f"\n\nadded_controls: ({len(added_controls)})")
121
- # for ac in added_controls:
122
- # print(f"\n\nadded_control: {ac._c}({ac._i} - {id(ac)})")
145
+ patch_logger.debug(f"\npatch added_controls: ({len(added_controls)})")
146
+ for ac in added_controls:
147
+ patch_logger.debug(" %s", ac)
123
148
 
124
149
  for added_control in added_controls:
125
150
  self.__index[added_control._i] = added_control
@@ -258,15 +283,83 @@ class Session:
258
283
  self.__send_buffer.append(message)
259
284
 
260
285
  def __get_update_control_patch(
261
- self, control: BaseControl, prev_control: Optional[BaseControl]
286
+ self,
287
+ control: BaseControl,
288
+ prev_control: Optional[BaseControl],
289
+ parent: Any = None,
290
+ path: Optional[list[Any]] = None,
291
+ frozen: bool = False,
262
292
  ):
293
+ # start_time = datetime.now()
294
+
263
295
  # calculate patch
264
296
  patch, added_controls, removed_controls = ObjectPatch.from_diff(
265
297
  prev_control,
266
298
  control,
267
299
  control_cls=BaseControl,
300
+ parent=parent,
301
+ path=path,
302
+ frozen=frozen,
268
303
  )
269
304
 
305
+ # end_time = datetime.now()
306
+ # elapsed_time = end_time - start_time
307
+ # print(
308
+ # "Time spent calculating patch: "
309
+ # f"{elapsed_time.total_seconds() * 1000:.3f} ms"
310
+ # )
311
+
270
312
  # print("\n\npatch:", patch)
271
313
 
272
314
  return patch.to_message(), added_controls, removed_controls
315
+
316
+ def schedule_update(self, control: BaseControl):
317
+ logger.debug("Schedule_update(%s)", control)
318
+ self.__pending_updates.add(control)
319
+ self.__updates_ready.set()
320
+
321
+ def schedule_effect(self, hook: EffectHook, is_cleanup: bool):
322
+ logger.debug("Schedule_effect(%s, %s)", hook, is_cleanup)
323
+ self.__pending_effects.append((weakref.ref(hook), is_cleanup))
324
+ self.__updates_ready.set()
325
+
326
+ def start_updates_scheduler(self):
327
+ logger.debug(f"Starting updates scheduler: {self.id}")
328
+ asyncio.create_task(self.__updates_scheduler())
329
+
330
+ async def __updates_scheduler(self):
331
+ while not self.__closed:
332
+ await self.__updates_ready.wait()
333
+ self.__updates_ready.clear()
334
+
335
+ # Process pending updates
336
+ for control in self.__pending_updates:
337
+ control.update()
338
+
339
+ self.__pending_updates.clear()
340
+
341
+ # Process pending effects
342
+ for effect in self.__pending_effects:
343
+ try:
344
+ hook = effect[0]()
345
+ is_cleanup = effect[1]
346
+ # print(f"**** Running effect: {hook} {is_cleanup}")
347
+ if hook and hook.setup and not is_cleanup:
348
+ hook.cancel()
349
+ if asyncio.iscoroutinefunction(hook.setup):
350
+ hook._setup_task = asyncio.create_task(hook.setup())
351
+ else:
352
+ res = hook.setup()
353
+ if callable(res):
354
+ hook.cleanup = res
355
+ elif hook and hook.cleanup and is_cleanup:
356
+ hook.cancel()
357
+ if asyncio.iscoroutinefunction(hook.cleanup):
358
+ hook._cleanup_task = asyncio.create_task(hook.cleanup())
359
+ else:
360
+ hook.cleanup()
361
+ except Exception as ex:
362
+ tb = traceback.format_exc()
363
+ self.error(f"Exception in effect: {ex}\n{tb}")
364
+
365
+ self.__pending_effects.clear()
@@ -1,9 +1,9 @@
1
1
  from typing import Any
2
2
 
3
- __all__ = ["SessionStorage"]
3
+ __all__ = ["SessionStore"]
4
4
 
5
5
 
6
- class SessionStorage:
6
+ class SessionStore:
7
7
  def __init__(self):
8
8
  self.__store: dict[str, Any] = {}
9
9
 
flet/version.py CHANGED
@@ -10,7 +10,7 @@ from flet.utils import is_mobile, is_windows, which
10
10
  DEFAULT_VERSION = "0.1.0"
11
11
 
12
12
  # will be replaced by CI
13
- version = "0.70.0.dev5776"
13
+ version = "0.70.0.dev5835"
14
14
 
15
15
 
16
16
  def update_version():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flet
3
- Version: 0.70.0.dev5776
3
+ Version: 0.70.0.dev5835
4
4
  Summary: Flet for Python - easily build interactive multi-platform apps in Python
5
5
  Author-email: "Appveyor Systems Inc." <hello@flet.dev>
6
6
  License-Expression: Apache-2.0
@@ -9,10 +9,10 @@ Project-URL: Repository, https://github.com/flet-dev/flet
9
9
  Project-URL: Documentation, https://docs.flet.dev/
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
- Requires-Dist: flet-cli==0.70.0.dev5776; extra == "cli"
13
- Requires-Dist: flet-desktop==0.70.0.dev5776; extra == "desktop" and (platform_system == "Darwin" or platform_system == "Windows")
14
- Requires-Dist: flet-desktop-light==0.70.0.dev5776; platform_system == "Linux" and (extra == "all" or extra == "desktop")
15
- Requires-Dist: flet-web==0.70.0.dev5776; extra == "web"
12
+ Requires-Dist: flet-cli==0.70.0.dev5835; extra == "cli"
13
+ Requires-Dist: flet-desktop==0.70.0.dev5835; extra == "desktop" and (platform_system == "Darwin" or platform_system == "Windows")
14
+ Requires-Dist: flet-desktop-light==0.70.0.dev5835; platform_system == "Linux" and (extra == "all" or extra == "desktop")
15
+ Requires-Dist: flet-web==0.70.0.dev5835; extra == "web"
16
16
  Requires-Dist: oauthlib>=3.2.2; platform_system != "Pyodide"
17
17
  Requires-Dist: httpx>=0.28.1; platform_system != "Pyodide"
18
18
  Requires-Dist: repath>=0.9.0
@@ -1,7 +1,7 @@
1
- flet/__init__.py,sha256=-yozy6OjbujMIRehArvHUY6-ej7F6yzeiShM2F6LPhQ,24805
1
+ flet/__init__.py,sha256=Lv9YmVVMQHTiO5E089OW9ES1CnGyoJadzi4IFk0bhmI,25642
2
2
  flet/app.py,sha256=HSws0Zm4ZO0-Hp2P9h7xirCVnRkKCVXhuekyAXT_9Fo,11883
3
3
  flet/cli.py,sha256=IUM25fY_sqMtl0hlQGhlMQaBb1oNyO0VZeeBgRodhuA,204
4
- flet/version.py,sha256=VhvpQCV4Az1S_uzr4sKfAGi_d78P7gx0dIMS_TabZzg,2512
4
+ flet/version.py,sha256=eHFiuFHZ31WYF3bMGm1eqUJexiv7Yl9gY-obkEgdxJU,2512
5
5
  flet/auth/__init__.py,sha256=eDqmi0Ki8Resd198S7XxgYa2R14wnNqIXnYhBLPl8fQ,289
6
6
  flet/auth/authorization.py,sha256=hP_36RiRPtSwmK_Yp6MMzAjQdDxbBiEcZ2yFNqyNiRs,357
7
7
  flet/auth/authorization_service.py,sha256=6N2LvisSt7KI_VgfyCH0OaJ6jTcmXCkAldN1yYlakzQ,6410
@@ -15,23 +15,36 @@ flet/auth/providers/azure_oauth_provider.py,sha256=EF8-Nl_HR5LeP3wztV5IVwrEzGXYk
15
15
  flet/auth/providers/github_oauth_provider.py,sha256=iiJEUGlQysYQlvIURgUqNZuL4izaaB-_PC-PSj-Pjmk,2643
16
16
  flet/auth/providers/google_oauth_provider.py,sha256=RGPQfbal53C6okaniDeegt1GH8TvyAvja6G-SNme8RU,799
17
17
  flet/canvas/__init__.py,sha256=_02Qjscc6DU4c4FYVSjv2S35ld6WFte_Be8NBABRN8Q,957
18
+ flet/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ flet/components/component.py,sha256=-bkB0A3Q9OpiQ0xuxeK15wajYnJl8hjnsc5_zKTFfHE,11671
20
+ flet/components/component_decorator.py,sha256=14ocjVSXPVl-SduJUtEQ1JivhpIoWnDDG4ioD0TCn0I,639
21
+ flet/components/component_owned.py,sha256=eC2NNNFWmZADBivLHjScfrmEj-s7xygHlABo7CiGtFA,563
22
+ flet/components/memo.py,sha256=tpztAInP4LkGOCFSJLyRuKp2t6EKM2AnX7SQmXiUZH8,620
23
+ flet/components/observable.py,sha256=XnO3ZOA7tttILoyKvKaSaozrKrYEqt3Duz0YxxwCKDo,6888
24
+ flet/components/public_utils.py,sha256=9orF-ZoxspZtTmjMUp9KmXL4-jpQG6TAOVSrGTEbVyo,180
25
+ flet/components/utils.py,sha256=6Uzs2cXg2VAWKr82vghSGTL3JglbHzADxkqc_7vns8o,2079
26
+ flet/components/hooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ flet/components/hooks/hook.py,sha256=otO5mz15MutMsRujuqLMefZvepm777FyIkGA4PTqI-8,207
28
+ flet/components/hooks/use_callback.py,sha256=TUTIfwBeZ5Xsbt7wI8OVbzfMKBGyPq27z3Jj9U5-k7s,791
29
+ flet/components/hooks/use_context.py,sha256=38_MYBIOzHE-X45psuyHV6cTjbcrQVXVRzcCz_bMwv8,2516
30
+ flet/components/hooks/use_effect.py,sha256=dZik3viWSfkOi5uTzc-kWV00P2_DIWcV2OzA8OexAN4,3225
31
+ flet/components/hooks/use_memo.py,sha256=4IbT89yQXicMgzqp9a6hJ6egit_6GX8sVkn4DczVeyQ,1693
32
+ flet/components/hooks/use_state.py,sha256=ZAhtIRnm2CKDK2-cIWmkWWEV-Gz2eOx7f9ZhsE1b06M,1680
18
33
  flet/controls/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
34
  flet/controls/adaptive_control.py,sha256=Pw0E7z0IlNSe05cQTi5BLElLF3OnlVLzwfvtOQpsRr8,1594
20
35
  flet/controls/alignment.py,sha256=re4jnpuqNPPWs55bf8RB_c9llqcuGhZcCjdNutx2N5M,3257
21
36
  flet/controls/animation.py,sha256=C3Sxqte4S225m3UvlQOm-DGxd1WJaqfdLpA6e10B_BM,3763
22
- flet/controls/base_control.py,sha256=BjjhaSZR02zdiMJatwwC7773IlIu7GtcIsLhS5j9SBc,10050
23
- flet/controls/base_page.py,sha256=EDIVmKjSuLntotY1-XrhNRmm1r3i-dg3pLKv-B27qVw,17749
37
+ flet/controls/base_control.py,sha256=1Yea_zW1O9dpjyrgdt8Cr-jUJyujlscKedkdK08lRHA,10713
38
+ flet/controls/base_page.py,sha256=SuuoK-XHqsTmOQZXYz84DxOibE9_43sKZulalSjIxYI,17927
24
39
  flet/controls/blur.py,sha256=taMH4qtILyAFn1qNsgBGRV3z0GSH6V7VKPV3ZSBhOL4,602
25
40
  flet/controls/border.py,sha256=X0NGRfjAx1YN3VcdOvOdH0BOH27LgeIrtjxiDKzrx0g,8931
26
41
  flet/controls/border_radius.py,sha256=ePfpA_uNhR6bfBSmYxy2cO0mZ3FU1r63qX_5RuHWwDM,6605
27
42
  flet/controls/box.py,sha256=f9T25pJYOk-VzmzapgYHKprucTuIPMMJRphIBinrZQ4,12606
28
43
  flet/controls/buttons.py,sha256=0mLPx4fBjQNGn-ejMuNu1wHb38_0BGU0JOggmqbUs1E,9943
29
- flet/controls/cache.py,sha256=0SJVqUtouvypBV_SEzJ-HLT-QBG5HtpWXCsJGH_zNSw,2872
30
44
  flet/controls/colors.py,sha256=J5A9ZQ25xqyKkM7X1SjX3uRlBP9PCsUJoHhCdM-YNOw,15345
31
- flet/controls/context.py,sha256=2U_YLmtv__7A7Q0wYOeX1BBqZnkXDlB_f5MihGlS82c,3692
45
+ flet/controls/context.py,sha256=xmmkrF2r4jD9ILe9lIrwtmkhvXv6awYpnwjHeqM5jFk,4239
32
46
  flet/controls/control.py,sha256=7uZKB9NOtj3zM-5uGq_x2GjsuDaXuSuVzuEKLJ1ysJU,4473
33
- flet/controls/control_event.py,sha256=uALISWT6mRS3r-owF7ENDMsQfL60PoWCDjx5C3xckWE,2565
34
- flet/controls/control_id.py,sha256=6GrwGlpnQhTkh1QnBIGutFDKfQwLuvoC5XIHnD4zDcU,671
47
+ flet/controls/control_event.py,sha256=wuI62LF8K42U6Ba2LK5R5YyhBtmxyTHBgZN4XfRKGRk,3107
35
48
  flet/controls/control_state.py,sha256=7Pi_WirBkE5dmUN0QnQLjSaW17Nj_escRlUvNxlrNR8,433
36
49
  flet/controls/dialog_control.py,sha256=4a1poIK4al6DAsdiV56jE-Q4E-eKrvP12DqYw5HFvYM,507
37
50
  flet/controls/duration.py,sha256=Fwb26eyHKrU_lqvmGuTLw4m-28leLHOlgHxtqRIQsnA,7398
@@ -41,18 +54,18 @@ flet/controls/exceptions.py,sha256=DV7sWQamNFSGlU6w1IBi59U03qsDBLPUzIVRnuVPrhc,8
41
54
  flet/controls/geometry.py,sha256=1M_rLlKlPdZF2s4wOBNCUGpGK8-vC5HJc8VHUhxomCQ,5000
42
55
  flet/controls/gradients.py,sha256=oUYQTL0wI4FYbhOzd2b-KkbCUsijBgGpH9gSRIMYQdk,5804
43
56
  flet/controls/icon_data.py,sha256=dtlNXm8_8yd_PRp_ogBuTDPz3-IXCXP47FA9C6SGoSk,2357
57
+ flet/controls/id_counter.py,sha256=YhZT-dB_yYYqPEBJ8IoTA98NU_EPFnx6T7FWbA9ENB4,627
44
58
  flet/controls/keys.py,sha256=YpcAeINKelX3WgSOMF8_T7wMzcFmAXNg-ssPej_NZWY,614
45
59
  flet/controls/layout_control.py,sha256=17JFILKY6_G73VgoyGofF41E3hykUl4ipQh6EKCig3Y,7279
46
60
  flet/controls/margin.py,sha256=ni5FwkchO1LPKPTKV0Cimvh2YzABi-t5DhOqTS25eIQ,2305
47
61
  flet/controls/multi_view.py,sha256=7RbM1nt8t75qgTKyfemsV06XQ04Mer0Op409Nu9q9Vs,304
48
- flet/controls/object_patch.py,sha256=VgGK0mZ4CVEs-Z_atGjdJ6tjo-xAYZYT52Deekzx6Y4,33957
62
+ flet/controls/object_patch.py,sha256=0OE8TswTyYH_l1yEqJPIf-Z6kLnOCCQCYiV-gNUvuSA,44111
49
63
  flet/controls/padding.py,sha256=AdxAZ5dbg1-Bo8aKeJ7AptUdyjaX7VWBIJto5mBT9Pk,2485
50
- flet/controls/page.py,sha256=U6KjD8-hisR_cit40wkL1tPoJ0V76xdM4eTxiGBgvSI,22717
64
+ flet/controls/page.py,sha256=_1FGO52-hWj7Z99Q9mEynQwWLqnmdxJZKcp6L4tPnJ4,26383
51
65
  flet/controls/painting.py,sha256=GCEycacejiCAdA4eZBQlTgxmE2ccXyad4Gy7VsjIwn0,12108
52
66
  flet/controls/query_string.py,sha256=NDrf1P0cxSWuJd4Rqz1qYld_JKDJpHY7mKcP52-70DI,3575
53
67
  flet/controls/ref.py,sha256=Lde_Nlly6NEtJX_LYv_DxIDkao6w4Buo7Nus4XUPQDA,580
54
68
  flet/controls/scrollable_control.py,sha256=Mu0oGA3fxweurlJQq1TuaUw2NMA8xy3DC27zJndQBZc,4571
55
- flet/controls/session_storage.py,sha256=UzDpebR1ddDW9seghplws9zgirlvQjRgAnskVDcrbas,561
56
69
  flet/controls/template_route.py,sha256=qP5KvFY5gazw-G9Q9bcoADlWAh-MJ_9wsIyIxjElkaE,662
57
70
  flet/controls/text_style.py,sha256=WC8uPdfps5PyZ64cdPBnWhC2HULK39Uah5V368JdVoI,9386
58
71
  flet/controls/theme.py,sha256=jed561Y3ENTgp1aHB6z5djzJdZdmazaDjfMy1acpWuI,97055
@@ -61,9 +74,9 @@ flet/controls/types.py,sha256=f4rUZ36Ul5FID2ZTgamPXAT7wZTfJl4Lbam9dpANtvI,25574
61
74
  flet/controls/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
75
  flet/controls/core/animated_switcher.py,sha256=qkPoKcmN3_fMN39VEnJw1dlV_7W46DT2O8LF0t13m2I,1873
63
76
  flet/controls/core/autofill_group.py,sha256=3py4hGl8ez9prZ6e4dpT2zazk7aBPqs40M64p5awWHk,3687
64
- flet/controls/core/column.py,sha256=cQPnroGU-FVUG-tSuWadsqqHla8lOMIOdhFO6K7p9D0,2035
77
+ flet/controls/core/column.py,sha256=g04SvwdP0iqJP-1w3STJl2eCEciwN4dt6eLKZ_xzV2U,2157
65
78
  flet/controls/core/dismissible.py,sha256=ywMKNAVpYx6vkSSWIKEO8gyrkSbUqj66emrVHWGsmOk,5542
66
- flet/controls/core/drag_target.py,sha256=NrUUu8AN-iXH9bwfjYp_2tVcm9x7D4Urnnli3empv-c,2552
79
+ flet/controls/core/drag_target.py,sha256=-u_5vUH_CJy-DbOmW8A1M2kl6pSyFS3W7_JMiG2Ga7c,2810
67
80
  flet/controls/core/draggable.py,sha256=jTwiflMgocFKA6NGYtSpzQplpck_76uX_F3Ta0JmJM8,3846
68
81
  flet/controls/core/flet_app.py,sha256=5WvbgRiktRxAMRKiZ667o1Yt7ozfuSM811yTE6D2rfA,1116
69
82
  flet/controls/core/gesture_detector.py,sha256=dcSzIiIjD7QOPVGcKDdW2MxvCdtla8M_yHvqxn4N1kg,8911
@@ -79,17 +92,16 @@ flet/controls/core/pagelet.py,sha256=PBpw49SBniprw_3CuxlsjzuJPvxjzJaWesXza020plE
79
92
  flet/controls/core/placeholder.py,sha256=XqqP1QmjlboezVKIrwZHA4FCcl06cptqxvYQs7kVkB8,992
80
93
  flet/controls/core/reorderable_draggable.py,sha256=Mdu9mHvfNs0m9VTFQ0wfYPnvB592t53XT-NyvoZs5Fs,1016
81
94
  flet/controls/core/responsive_row.py,sha256=Ij02f54UuB2qPUfJ3Y6l-W06nZQcZnEuY3ef3mn44EI,2382
82
- flet/controls/core/row.py,sha256=cIajHnIPzeWG7RoV1_aIqw975qDJ7rRrxuSle-c3GS8,2046
95
+ flet/controls/core/row.py,sha256=u_mWESVQv9Q9zV19Rzag0eMA5TCugh7mRNZFGvTwPeA,2167
83
96
  flet/controls/core/safe_area.py,sha256=oDCmD9aWHSfYa-d_Nagw32bfnwuDNX6yiTCqDyFLxus,2230
84
97
  flet/controls/core/screenshot.py,sha256=6X3f6rYaX7PHkvWM7gpFlyhA2xzt-M15ax-Nfd45n1g,1110
85
98
  flet/controls/core/semantics.py,sha256=tiRTyFMYYNIcj8kuiopZMPGxeo_n4L7eCchHcywColI,7413
86
99
  flet/controls/core/shader_mask.py,sha256=z4sr8RP2PnP-ooh0c5KNiUDLsHmj1S-R7ATm53j5CJo,1034
87
100
  flet/controls/core/stack.py,sha256=JqCIXFcDxd4C7dhJik0qwOu7IoHRmkj7BpvF6LhM03k,1954
88
- flet/controls/core/state_view.py,sha256=BLDp0PkPsI6TGs2akAJqXyxq64XqJJaisTgUKxT3CxY,1842
89
101
  flet/controls/core/text.py,sha256=Z2gqu5IIOvUQYV7RpoqAmoEueiHozxL0xN0hlnyMseQ,8811
90
102
  flet/controls/core/text_span.py,sha256=KpW6jER8HYRj-kHQPuAaSOa816B-nQc02le9i9M22Pc,2939
91
103
  flet/controls/core/transparent_pointer.py,sha256=BGDFuDWyDUIYOmwaEgMMks6OWS_lVjZObAw2M-3r2bQ,963
92
- flet/controls/core/view.py,sha256=wlUirfLnm3uY4ElyadWoLABC_txDgLBzCzJUMcLlU1A,4991
104
+ flet/controls/core/view.py,sha256=WuXwdjKtMwhzy1foPJa5kPsrwnpti_b85g8w_ldhOeQ,5031
93
105
  flet/controls/core/window.py,sha256=7SbbEoprqCoO_xz9-tHppOMYj0m9nJwDi3tRlnuVSoo,7157
94
106
  flet/controls/core/window_drag_area.py,sha256=cgq3bH4vkXZl3HcYRceSiqS4-pbibRSuuhgNzOG5m2I,1834
95
107
  flet/controls/core/canvas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -151,7 +163,7 @@ flet/controls/material/container.py,sha256=quw_KEu7N5tbEFK7EuX39OQ4Idd0i4qa4Nu6H
151
163
  flet/controls/material/datatable.py,sha256=fw2qtz5BAPxwfW3s8xm9hTrpNx9tNDkOkLhCe8RGf5E,17535
152
164
  flet/controls/material/date_picker.py,sha256=JCuU3-BcwFkb8KHQdcRQm0Scfdur7FGiMXElUX4WSxU,5336
153
165
  flet/controls/material/date_range_picker.py,sha256=7KJKE78bQYLJRdsTKgNu9JZbmyu3xh8xQUbrgwN5HwY,5350
154
- flet/controls/material/divider.py,sha256=LCfJ9inCmj8JaacOc0bs0d6kjxi_CueT1EkV8FAjQK8,2748
166
+ flet/controls/material/divider.py,sha256=e3EUc8TqeDpiUwJjjtaewM3ghxQDXSy8huwWpz_R6Yo,2908
155
167
  flet/controls/material/dropdown.py,sha256=hkDIO1GTLBNbX7QW45Um0RfnCxKFbUl0Qwq71fdBiPU,9863
156
168
  flet/controls/material/dropdownm2.py,sha256=JGie5s9jReAbhGWQkkoBMY1S8iBgdEvqqhhL7JMIoJg,5452
157
169
  flet/controls/material/elevated_button.py,sha256=AjrLkxn1ViwGE7ms8aNlNTgaR1-qIFhN8aU254Hx9Vc,274
@@ -186,27 +198,28 @@ flet/controls/material/submenu_button.py,sha256=4iQvOPTNRjNwXx3in8FWqBFKW6Mt22aw
186
198
  flet/controls/material/switch.py,sha256=sykhqKToMADriYkp2dmGCUZCqum-2Ht6MMCJ3o2UHU4,6892
187
199
  flet/controls/material/tabs.py,sha256=aWdLCgNyGPTzhTmEq28syYjvGAMXwPaJ7GLWF0de3PA,18642
188
200
  flet/controls/material/text_button.py,sha256=Mkvz4LIl0yH1-e0ekOjPD6z8CZ5ZUIyE00zcb7sLKns,2578
189
- flet/controls/material/textfield.py,sha256=YWQzJzeGPwfNT0TOeP-DzNdq_pAGHUq3_6scPuoYsRo,11387
201
+ flet/controls/material/textfield.py,sha256=tFxtWIk7JCXeq7oL_2Ltmbw5bqmY4125PIBd07Qur3Y,11668
190
202
  flet/controls/material/time_picker.py,sha256=_gUTaQi4N-mo1Oj_yJEsti8ToM0WhwhofbCjP5v2gzA,3070
191
203
  flet/controls/material/tooltip.py,sha256=PTqJiiE95z4WCTlvCx7i3vA-gGwphUT7w_2oXMiiVtY,5636
192
- flet/controls/material/vertical_divider.py,sha256=1xBj4bDLmTmhIcU5apbEbgLD778akbZehLwKgTCu-t8,2627
204
+ flet/controls/material/vertical_divider.py,sha256=5-yjdV-sDXotSZFg_ApP_rtzBHlai4WkyeCOEoJhK34,2787
193
205
  flet/controls/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
194
206
  flet/controls/services/browser_context_menu.py,sha256=iLb160q7wPicdiVPXLZLzzQ4MCGxl2e-mOV4y4d2xQg,721
195
207
  flet/controls/services/clipboard.py,sha256=Linpoz32r5i-K5vpafFwNKaWwByZ6cVFhJZ0p87M_UE,987
196
208
  flet/controls/services/file_picker.py,sha256=Gsh1A4XBD3nIS9MDsLDirDwTMwO9nBZGHeC-F2furXI,7662
197
- flet/controls/services/haptic_feedback.py,sha256=rQ3Miw0jKlmoKHTOJKt-7vklqKxR1m2dngH7Oylyx6w,1266
209
+ flet/controls/services/haptic_feedback.py,sha256=JZMveq3loC3CWt3LPp87iWl6IeAzyUOnRejKzX9nLmo,1164
198
210
  flet/controls/services/semantics_service.py,sha256=eF_EcVqOMsgUyyZYhKTNLP-PcFTX0a8NQsQkAU-jxyk,1662
199
211
  flet/controls/services/service.py,sha256=1k3PGJxkJOub5Eb9SIjrRo2-Ik_xrmERQD0TfxjHYC0,378
200
- flet/controls/services/shake_detector.py,sha256=wrjoEfYcN7607QHCtW6FRdEdcj2yxyzSK-E1vBx5t_k,997
212
+ flet/controls/services/shake_detector.py,sha256=A9o5Z89lBUL7j6OhhMWv3Qna2O_ke1h3R1AFwKgmMwk,895
201
213
  flet/controls/services/shared_preferences.py,sha256=xCwAxSf52PL56KfObLLG8DGQvSZRLtQmKXP3nB0kdDY,949
202
214
  flet/controls/services/storage_paths.py,sha256=q6ykCW33IeMhvMQKAWaXZ8HKzsfdUpHGWAC52SM2NAQ,7800
203
215
  flet/controls/services/url_launcher.py,sha256=YfvNGaivvwJ2vrSkxwgQ2R1l3A5wbgY6AxX8n2Fe02U,2735
204
216
  flet/fastapi/__init__.py,sha256=crLmmKE-B-O-cm5MTlXFreYCUnqkw6mK4eIPUUMvSCM,45
205
217
  flet/messaging/connection.py,sha256=yd7NlEAwAMxhCEhh6mLN-cihYfeJdUlHhx5SycRVct4,1646
206
- flet/messaging/flet_socket_server.py,sha256=2y71YejYqAJGXhuoEaanGTHiCtnyXdu_62abur5gX-g,9053
218
+ flet/messaging/flet_socket_server.py,sha256=bFeC-hlKFhBoVHBYy6o_LzWiuFaUmT-vMT81t5lGEUM,9146
207
219
  flet/messaging/protocol.py,sha256=LTdTUHD2RQfP55rL6InG2w0FfTJPWoKo_SGcand3YpA,3856
208
220
  flet/messaging/pyodide_connection.py,sha256=-bNGKh0nYNtgdJ_nhBGJTF1TNX3vHqgxygetv2ZQwUs,4313
209
- flet/messaging/session.py,sha256=yv-pAlakXjFhhqy6VgCIOXtXZp1tUBBogrzdL-Saiaw,8879
221
+ flet/messaging/session.py,sha256=RQkYkZDIKW-l9ShUvbYKPD6ZXgfD4yVz2WERgUnp_OA,12310
222
+ flet/messaging/session_store.py,sha256=80yy3fjEGJs_60UxS_o2tXl2QCenFb9IVDaJCK8wckY,557
210
223
  flet/pubsub/__init__.py,sha256=qWcHYUa7oQEKysceGCeYG2AgIe0IO18NRXiP47jb_6o,126
211
224
  flet/pubsub/pubsub_client.py,sha256=Wamm3T_md2ObOu5odN5-bPuMgt9Si8YvbYhSC2TtAIA,1245
212
225
  flet/pubsub/pubsub_hub.py,sha256=1loRKhFYq23E89EYPaK4RMCbFdOW2qVeTQk8JqnbNp8,6514
@@ -232,8 +245,8 @@ flet/utils/platform_utils.py,sha256=U4cqV3EPi5QNYjbhfZmtk41-KMtI_P7KvVdnZzMOgJA,
232
245
  flet/utils/slugify.py,sha256=e-lsoDc2_dk5jQnySaHCU83AA4O6mguEgCEdk2smW2Y,466
233
246
  flet/utils/strings.py,sha256=R63_i7PdSAStCDPJ-O_WHBt3H02JQ14GSbnjLIpPTUc,178
234
247
  flet/utils/vector.py,sha256=pYZzjldBWCZbSeSkZ8VmujwcZC7VBWk1NLBPA-2th3U,3207
235
- flet-0.70.0.dev5776.dist-info/METADATA,sha256=LTjKJFeIzE0rqNYPHLViBCRDyLEjpRyXpVzlopurNEM,6220
236
- flet-0.70.0.dev5776.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
237
- flet-0.70.0.dev5776.dist-info/entry_points.txt,sha256=mbBhHNUnLHiDqR36WeJrfLJU0Y0y087-M4wagQmaQ_Y,39
238
- flet-0.70.0.dev5776.dist-info/top_level.txt,sha256=HbLrSnWJX2jZOEZAI14cGzW8Q5BbOGTtE-7knD5FDh0,5
239
- flet-0.70.0.dev5776.dist-info/RECORD,,
248
+ flet-0.70.0.dev5835.dist-info/METADATA,sha256=GUvIKok6bJMD_anTcdBLA4S3G4gRtTN7Cwvsy6GUtoo,6220
249
+ flet-0.70.0.dev5835.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
250
+ flet-0.70.0.dev5835.dist-info/entry_points.txt,sha256=mbBhHNUnLHiDqR36WeJrfLJU0Y0y087-M4wagQmaQ_Y,39
251
+ flet-0.70.0.dev5835.dist-info/top_level.txt,sha256=HbLrSnWJX2jZOEZAI14cGzW8Q5BbOGTtE-7knD5FDh0,5
252
+ flet-0.70.0.dev5835.dist-info/RECORD,,
flet/controls/cache.py DELETED
@@ -1,87 +0,0 @@
1
- import functools
2
- import hashlib
3
- import weakref
4
- from typing import Callable, Optional, ParamSpec, TypeVar, Union, overload
5
-
6
- P = ParamSpec("P")
7
- R = TypeVar("R")
8
-
9
-
10
- def _hash_args(*args, **kwargs):
11
- try:
12
- # Convert args/kwargs to a string and hash it
13
- sig = repr((args, kwargs))
14
- return hashlib.sha256(sig.encode()).hexdigest()
15
- except Exception:
16
- # fallback to id-based hash if unhashable
17
- return str(id(args)) + str(id(kwargs))
18
-
19
-
20
- def _freeze_controls(control):
21
- if isinstance(control, list):
22
- return [_freeze_controls(c) for c in control]
23
- elif isinstance(control, dict):
24
- return {k: _freeze_controls(v) for k, v in control.items()}
25
- elif hasattr(control, "__dict__"): # assume it's a control
26
- object.__setattr__(control, "_frozen", True)
27
- return control
28
-
29
-
30
- @overload
31
- def cache(
32
- _fn: None = ..., *, freeze: bool = False
33
- ) -> Callable[[Callable[P, R]], Callable[P, R]]: ...
34
- @overload
35
- def cache(_fn: Callable[P, R], *, freeze: bool = False) -> Callable[P, R]: ...
36
-
37
-
38
- def cache(
39
- _fn: Optional[Callable[P, R]] = None, *, freeze: bool = False
40
- ) -> Union[Callable[[Callable[P, R]], Callable[P, R]], Callable[P, R]]:
41
- """
42
- A decorator to cache the results of a function based on its arguments.
43
- Used with Flet controls to optimize comparisons in declarative apps.
44
-
45
- Args:
46
- _fn: The function to be decorated.
47
- If None, the decorator is used with arguments.
48
- freeze: If `True`, freezes the returned controls
49
- by setting a `_frozen` attribute.
50
-
51
- Returns:
52
- A decorated function that caches its results.
53
- """
54
-
55
- def decorator(fn: Callable[P, R]) -> Callable[P, R]:
56
- # Use a weak reference dictionary to store cached results
57
- cache_store = weakref.WeakValueDictionary()
58
-
59
- @functools.wraps(fn)
60
- def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
61
- # Generate a unique hash key based on the function arguments
62
- key = _hash_args(*args, **kwargs)
63
-
64
- # Return cached result if it exists
65
- if key in cache_store:
66
- return cache_store[key]
67
-
68
- # Call the original function and cache the result
69
- result = fn(*args, **kwargs)
70
- if result is not None:
71
- if freeze:
72
- # Freeze the controls if the freeze flag is set
73
- _freeze_controls(result)
74
- cache_store[key] = result
75
- elif key in cache_store:
76
- # Remove the cache entry if the result is None
77
- del cache_store[key]
78
- return result
79
-
80
- return wrapper
81
-
82
- # If _fn is None, return the decorator itself for use with arguments
83
- if _fn is None:
84
- return decorator
85
- else:
86
- # Apply the decorator directly if _fn is provided
87
- return decorator(_fn)
@@ -1,22 +0,0 @@
1
- import itertools
2
- import threading
3
-
4
- from flet.utils.locks import NopeLock
5
- from flet.utils.platform_utils import is_pyodide
6
-
7
-
8
- class ControlId:
9
- """
10
- Generates unique, auto-incrementing integers safely across
11
- multiple threads and asyncio tasks using itertools.count.
12
- """
13
-
14
- _counter_iterator = itertools.count(3) # Creates an iterator starting at 3
15
- _lock = threading.Lock() if not is_pyodide() else NopeLock()
16
-
17
- @classmethod
18
- def next(cls) -> int:
19
- """Returns the next unique integer identifier."""
20
- with cls._lock:
21
- # next() on the iterator is atomic *relative to the lock*
22
- return next(cls._counter_iterator)
@@ -1,60 +0,0 @@
1
- import weakref
2
- from dataclasses import InitVar
3
- from typing import Any, Callable, ClassVar, Generic, Optional, TypeVar
4
-
5
- from flet.controls.base_control import control
6
- from flet.controls.control import Control
7
- from flet.controls.ref import Ref
8
-
9
- __all__ = ["StateView"]
10
-
11
- T = TypeVar("T")
12
-
13
-
14
- @control("StateView", post_init_args=4)
15
- class StateView(Control, Generic[T]):
16
- """
17
- Builds control tree on every update based on data.
18
- """
19
-
20
- state: InitVar[T]
21
- builder: InitVar[Callable[[T], Control]]
22
- state_key: InitVar[Optional[Callable[[T], Any]]] = None
23
- content: Optional[Control] = None
24
-
25
- # Cache: (control_id, state_id) -> control
26
- _builder_cache: ClassVar[weakref.WeakValueDictionary[tuple[int, Any], Control]] = (
27
- weakref.WeakValueDictionary()
28
- )
29
-
30
- def __post_init__(
31
- self,
32
- ref: Optional[Ref[Any]],
33
- state: T,
34
- builder: Callable[[T], Control],
35
- state_key: Optional[Callable[[T], Any]] = None,
36
- ):
37
- Control.__post_init__(self, ref)
38
- self._state: T = state
39
- self._builder = builder
40
- self._state_key = state_key
41
-
42
- def before_update(self):
43
- # print(f"StateView({self._i}).before_update")
44
- frozen = getattr(self, "_frozen", None)
45
- if frozen:
46
- del self._frozen
47
-
48
- cache_key = (self._i, self._state_key(self._state)) if self._state_key else None
49
-
50
- if cache_key is not None and cache_key in self._builder_cache:
51
- self.content = self._builder_cache[cache_key]
52
- else:
53
- self.content = self._builder(self._state)
54
- if cache_key is not None and self.content:
55
- self._builder_cache[cache_key] = self.content
56
-
57
- if self.content:
58
- object.__setattr__(self.content, "_frozen", True)
59
- if frozen:
60
- self._frozen = frozen