flet 0.70.0.dev6326__py3-none-any.whl → 0.70.0.dev6348__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.

flet/controls/border.py CHANGED
@@ -86,34 +86,37 @@ class BorderSide:
86
86
  """
87
87
  The style of this side of the border.
88
88
 
89
- To omit a side, set `style` to `BorderStyle.NONE`.
90
- This skips painting the border, but the border still has a `width`.
89
+ Tip:
90
+ To omit a side, set `style` to [`BorderStyle.NONE`][flet.]. This skips
91
+ painting the border, but the border still has a `width`.
91
92
  """
92
93
 
93
94
  def __post_init__(self):
94
- assert self.width >= 0.0, (
95
- f"width must be greater than or equal to 0.0, got {self.width}"
96
- )
95
+ if self.width < 0.0:
96
+ raise ValueError(
97
+ f"width must be greater than or equal to 0.0, got {self.width}"
98
+ )
97
99
 
98
100
  # Properties
99
101
 
100
102
  @property
101
103
  def stroke_inset(self):
102
104
  """
103
- The amount of the stroke width that lies inside of the `BorderSide`.
105
+ The amount of the stroke width that lies inside this `BorderSide`.
104
106
 
105
- For example, this will return the `width` for a `stroke_align` of -1, half
106
- the `width` for a `stroke_align` of 0, and 0 for a `stroke_align` of 1.
107
+ For example, this will return the `width` for a `stroke_align` of `-`1, half
108
+ the `width` for a `stroke_align` of `0`, and `0` for a `stroke_align` of `1`.
107
109
  """
108
110
  return self.width * (1 - (1 + self.stroke_align) / 2)
109
111
 
110
112
  @property
111
113
  def stroke_outset(self):
112
114
  """
113
- The amount of the stroke width that lies outside of the [BorderSide].
115
+ The amount of the stroke width that lies outside this `BorderSide`.
114
116
 
115
- For example, this will return 0 for a `stroke_align` of -1, half the
116
- `width` for a `stroke_align` of 0, and the `width` for a `stroke_align` of 1.
117
+ For example, this will return `0` for a `stroke_align` of `-1`, half the
118
+ `width` for a `stroke_align` of `0`, and the `width` for a
119
+ `stroke_align` of `1`.
117
120
  """
118
121
  return self.width * (1 + self.stroke_align) / 2
119
122
 
@@ -163,12 +166,6 @@ class Border:
163
166
 
164
167
  Each side of the border is an instance of
165
168
  [`BorderSide`][flet.].
166
-
167
- Example:
168
- ```python
169
- container_1.border = ft.Border.all(10, ft.Colors.PINK_600)
170
- container_1.border = ft.Border.only(bottom=ft.BorderSide(1, "black"))
171
- ```
172
169
  """
173
170
 
174
171
  top: BorderSide = field(default_factory=lambda: BorderSide.none())
@@ -29,6 +29,34 @@ class Canvas(LayoutControl):
29
29
  """
30
30
  Canvas is a control for drawing arbitrary graphics using a set of primitives or
31
31
  "shapes" such as line, arc, path and text.
32
+
33
+ ```python
34
+ cv.Canvas(
35
+ width=160,
36
+ height=160,
37
+ shapes=[
38
+ cv.Rect(
39
+ 0,
40
+ 0,
41
+ 160,
42
+ 160,
43
+ paint=ft.Paint(
44
+ color=ft.Colors.BLUE_100,
45
+ style=ft.PaintingStyle.FILL,
46
+ ),
47
+ ),
48
+ cv.Circle(
49
+ 80,
50
+ 80,
51
+ 50,
52
+ paint=ft.Paint(
53
+ color=ft.Colors.BLUE_400,
54
+ style=ft.PaintingStyle.FILL,
55
+ ),
56
+ ),
57
+ ],
58
+ )
59
+ ```
32
60
  """
33
61
 
34
62
  shapes: list[Shape] = field(default_factory=list)
@@ -15,6 +15,21 @@ class CupertinoActionSheet(LayoutControl):
15
15
 
16
16
  Action sheets are generally used to give the user a choice between
17
17
  two or more choices for the current context.
18
+
19
+ ```python
20
+ sheet = ft.CupertinoActionSheet(
21
+ title=ft.Text("Choose an option"),
22
+ message=ft.Text("Select what you would like to do"),
23
+ actions=[
24
+ ft.CupertinoActionSheetAction(content=ft.Text("Save")),
25
+ ft.CupertinoActionSheetAction(
26
+ content=ft.Text("Delete"), destructive=True
27
+ ),
28
+ ],
29
+ cancel=ft.CupertinoActionSheetAction(content=ft.Text("Cancel")),
30
+ )
31
+ page.show_dialog(ft.CupertinoBottomSheet(sheet))
32
+ ```
18
33
  """
19
34
 
20
35
  title: Optional[StrOrControl] = None
@@ -11,6 +11,13 @@ __all__ = ["CupertinoActivityIndicator"]
11
11
  class CupertinoActivityIndicator(LayoutControl):
12
12
  """
13
13
  An iOS-style activity indicator that spins clockwise.
14
+
15
+ ```python
16
+ ft.CupertinoActivityIndicator(
17
+ radius=30,
18
+ color=ft.CupertinoColors.DARK_BACKGROUND_GRAY,
19
+ )
20
+ ```
14
21
  """
15
22
 
16
23
  radius: Number = 10
@@ -18,6 +18,20 @@ __all__ = ["BottomAppBar"]
18
18
  class BottomAppBar(LayoutControl):
19
19
  """
20
20
  A material design bottom app bar.
21
+
22
+ ```python
23
+ ft.BottomAppBar(
24
+ bgcolor=ft.Colors.SURFACE_CONTAINER_LOW,
25
+ content=ft.Row(
26
+ controls=[
27
+ ft.IconButton(ft.Icons.MENU),
28
+ ft.IconButton(ft.Icons.SEARCH),
29
+ ft.IconButton(ft.Icons.SETTINGS),
30
+ ],
31
+ alignment=ft.MainAxisAlignment.SPACE_AROUND,
32
+ ),
33
+ )
34
+ ```
21
35
  """
22
36
 
23
37
  content: Optional[Control] = None
@@ -18,6 +18,21 @@ class BottomSheet(DialogControl):
18
18
 
19
19
  A bottom sheet is an alternative to a menu or dialog and prevents the user
20
20
  from interacting with the rest of the app.
21
+
22
+ ```python
23
+ sheet = ft.BottomSheet(
24
+ content=ft.Column(
25
+ width=150,
26
+ alignment=ft.MainAxisAlignment.CENTER,
27
+ horizontal_alignment=ft.CrossAxisAlignment.CENTER,
28
+ controls=[
29
+ ft.Text("Choose an option"),
30
+ ft.TextButton("Dismiss"),
31
+ ],
32
+ )
33
+ )
34
+ page.show_dialog(sheet)
35
+ ```
21
36
  """
22
37
 
23
38
  content: Control
@@ -3,6 +3,7 @@ import logging
3
3
  import os
4
4
  import platform
5
5
  import tempfile
6
+ from collections.abc import Iterable
6
7
  from io import BytesIO
7
8
  from pathlib import Path
8
9
  from typing import Any, Optional
@@ -381,3 +382,71 @@ class FletTestApp:
381
382
  arr2 = np.array(img2)
382
383
  similarity, _ = ssim(arr1, arr2, channel_axis=-1, full=True)
383
384
  return similarity * 100
385
+
386
+ def create_gif(
387
+ self,
388
+ image_names: Iterable[str],
389
+ output_name: str,
390
+ *,
391
+ duration: int = 1000,
392
+ loop: int = 0,
393
+ ) -> Path:
394
+ """Create an animated GIF from a sequence of image files.
395
+
396
+ Args:
397
+ image_names: Iterable of file name stems (without ``.png``) in the
398
+ order they should appear in the animation.
399
+ output_name: Base name for the resulting animation. The ``.gif``
400
+ extension is added automatically and the file is stored in the
401
+ same directory as the provided frames.
402
+ duration: Frame duration in milliseconds. Defaults to ``300``.
403
+ loop: Number of times the GIF should repeat (``0`` means infinite).
404
+
405
+ Returns:
406
+ Path to the generated GIF file.
407
+
408
+ Raises:
409
+ ValueError: If ``image_names`` is empty.
410
+ FileNotFoundError: If any referenced image file does not exist.
411
+ """
412
+
413
+ if not self.__test_path:
414
+ raise ValueError("test_path must be set to create GIF animations")
415
+ if not self.test_platform:
416
+ raise ValueError("test_platform must be set to create GIF animations")
417
+
418
+ names = list(image_names)
419
+ if not names:
420
+ raise ValueError("image_names must contain at least one entry")
421
+
422
+ stem = output_name
423
+ golden_dir = (
424
+ Path(self.__test_path).parent
425
+ / "golden"
426
+ / self.test_platform
427
+ / Path(self.__test_path).stem.removeprefix("test_")
428
+ )
429
+ output = golden_dir / f"{stem}.gif"
430
+ output.parent.mkdir(parents=True, exist_ok=True)
431
+
432
+ frames: list[Image.Image] = []
433
+ try:
434
+ for name in names:
435
+ path = golden_dir / f"{name}.png"
436
+ if not path.exists():
437
+ raise FileNotFoundError(path)
438
+ frames.append(Image.open(path))
439
+
440
+ first, *rest = frames
441
+ first.save(
442
+ output,
443
+ save_all=True,
444
+ append_images=rest,
445
+ duration=duration,
446
+ loop=loop,
447
+ )
448
+ finally:
449
+ for frame in frames:
450
+ frame.close()
451
+
452
+ return output
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.dev6326"
13
+ version = "0.70.0.dev6348"
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.dev6326
3
+ Version: 0.70.0.dev6348
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
@@ -1,7 +1,7 @@
1
1
  flet/__init__.py,sha256=rj0DuM9ZNrzkM-TpQ35iIspYLzsrxOCwkVxOHRX6oiU,26152
2
2
  flet/app.py,sha256=HSws0Zm4ZO0-Hp2P9h7xirCVnRkKCVXhuekyAXT_9Fo,11883
3
3
  flet/cli.py,sha256=IUM25fY_sqMtl0hlQGhlMQaBb1oNyO0VZeeBgRodhuA,204
4
- flet/version.py,sha256=sWUWPbQY9PByaOtgEaglY6Zw3B-YcubEBnx4-GmQaWo,2512
4
+ flet/version.py,sha256=62NHkDMCuuXOPOn4bH5uVv_TOt88P483IlIpVb7LeZA,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
@@ -37,7 +37,7 @@ flet/controls/animation.py,sha256=C3Sxqte4S225m3UvlQOm-DGxd1WJaqfdLpA6e10B_BM,37
37
37
  flet/controls/base_control.py,sha256=Pn9b6ez81iFuWZw_rRsEHQw7CEkZVL8XHChORXgenPc,10545
38
38
  flet/controls/base_page.py,sha256=SuuoK-XHqsTmOQZXYz84DxOibE9_43sKZulalSjIxYI,17927
39
39
  flet/controls/blur.py,sha256=taMH4qtILyAFn1qNsgBGRV3z0GSH6V7VKPV3ZSBhOL4,602
40
- flet/controls/border.py,sha256=O-Pt3pydzR8lZYDi83caDOhhfWurPMJHANeRyFZDIKg,8931
40
+ flet/controls/border.py,sha256=bZS9piQD_smyHeO6r30KejYvJIThwiqcZPpAUL34Tb0,8819
41
41
  flet/controls/border_radius.py,sha256=ePfpA_uNhR6bfBSmYxy2cO0mZ3FU1r63qX_5RuHWwDM,6605
42
42
  flet/controls/box.py,sha256=f9T25pJYOk-VzmzapgYHKprucTuIPMMJRphIBinrZQ4,12606
43
43
  flet/controls/buttons.py,sha256=0mLPx4fBjQNGn-ejMuNu1wHb38_0BGU0JOggmqbUs1E,9943
@@ -107,7 +107,7 @@ flet/controls/core/window.py,sha256=7SbbEoprqCoO_xz9-tHppOMYj0m9nJwDi3tRlnuVSoo,
107
107
  flet/controls/core/window_drag_area.py,sha256=fH0fczp-LUN9n3XgL85tEsQzVH1F_OoWjYwq6gSIS1E,1834
108
108
  flet/controls/core/canvas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  flet/controls/core/canvas/arc.py,sha256=pgZ6e2yhzx2cAbb3zBnlhwtuJR_YEyVTjo_11GAra_Q,1772
110
- flet/controls/core/canvas/canvas.py,sha256=eOIO5k2qhkdb3bKXoM9-9MnX30ZGBEZIpF5SO-0M838,2898
110
+ flet/controls/core/canvas/canvas.py,sha256=51zE20T3kJYU9sDTOmTL6CMyeIq-tizuxDX7RJ_0aIg,3515
111
111
  flet/controls/core/canvas/circle.py,sha256=_hGiYhvz_cWwSyrD9A7IISck7HJ4TbmZ3cbfqBA4JOs,653
112
112
  flet/controls/core/canvas/color.py,sha256=MtmBewnuOaQ97E70qCNYU94ZmeRbLtQGko2caTUjZno,610
113
113
  flet/controls/core/canvas/fill.py,sha256=aW3R-C2TUQAXL9unO3gBQSMvZlS0jeeUmAlGhDPasBs,517
@@ -121,9 +121,9 @@ flet/controls/core/canvas/shadow.py,sha256=GuUwsGD9pO55lqRtVtuoRdESYNeruzkXrOyGx
121
121
  flet/controls/core/canvas/shape.py,sha256=Usq8DgS1jbi_uKva0SROima_8koDHmS3BO9VWznfX_E,484
122
122
  flet/controls/core/canvas/text.py,sha256=KJU7XepvY_klGYaecWRXlQZc86P0ZtMsxLAC591J1EA,2008
123
123
  flet/controls/cupertino/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
- flet/controls/cupertino/cupertino_action_sheet.py,sha256=TByUTXXk60O0Nf6zjzLJtB-_ntHnt9mmTKrlpAQuR_w,1865
124
+ flet/controls/cupertino/cupertino_action_sheet.py,sha256=If2qa70TNUk6EPrt86Al5O_ZOU9m0q06fUd7SpJ0DeI,2376
125
125
  flet/controls/cupertino/cupertino_action_sheet_action.py,sha256=NtLhsoHKtCtrgr0fGo0tsE5_ttNrt9ls9ULI7isWqX4,1378
126
- flet/controls/cupertino/cupertino_activity_indicator.py,sha256=vSLNarHRb0Oc5lVexuqnod7GcL5R6uEplSTNVXb2nc0,1014
126
+ flet/controls/cupertino/cupertino_activity_indicator.py,sha256=FgAgNcneStqtWNogIwqaXBgn_NEV_UabMoEd5J8m5PI,1152
127
127
  flet/controls/cupertino/cupertino_alert_dialog.py,sha256=kcACIyiv7gWN3KX27aqPfMS9BUVTPt0CPW8k2L9hC2o,2284
128
128
  flet/controls/cupertino/cupertino_app_bar.py,sha256=CxhgW5Z_tohnyn7WkGxes9aN_KBDjovzcn_mEuhRqms,5176
129
129
  flet/controls/cupertino/cupertino_bottom_sheet.py,sha256=o8154fJuBtJUSJtqJFrjE6tEBv1ylNtgDW8qn6vwSxs,938
@@ -153,8 +153,8 @@ flet/controls/material/app_bar.py,sha256=Ol2UNCcUGi8HLmIdaxGQtIr-CM5HSD2iKIPg6Za
153
153
  flet/controls/material/auto_complete.py,sha256=MVesy4fUvLvY0pw_BDQXpRB5o9ac1Ci7icTdG4nC5oM,1856
154
154
  flet/controls/material/badge.py,sha256=gWkDrqoZMIrjEreWeTaANlnzJn394Gj4vQZikuVAEIk,3365
155
155
  flet/controls/material/banner.py,sha256=gFj9oNpPMNiAMnFNWkZiUdgGcE6T72VVVw73BeIRMvU,4512
156
- flet/controls/material/bottom_app_bar.py,sha256=Rrx4LhiFxKkTAhyblvcuNenLuxNxc93tmlUULgKeVqo,2083
157
- flet/controls/material/bottom_sheet.py,sha256=fQE725QwN0mxknh_CdkWIAPC5DHV1tzW_mCT-CzX9ZY,2791
156
+ flet/controls/material/bottom_app_bar.py,sha256=_nnAUEP7_z3seEaDQ29qO5qEn8xbBEUxL-I68i9lk5c,2456
157
+ flet/controls/material/bottom_sheet.py,sha256=TRa6RgPiz3PLnmVHnJHXp3CW2pkZbx_RQ4ngnsuxjzc,3175
158
158
  flet/controls/material/button.py,sha256=8_CLLvjPO9ZXsaGkJhO1a3cVbG2Abe-40cEQcT9BPpY,4189
159
159
  flet/controls/material/card.py,sha256=kR87buDfX_mSTOlj4HRicq2hDfIRPyigIdLlxa5Q7Fw,2872
160
160
  flet/controls/material/checkbox.py,sha256=FUa77no8mpDI7p7wIQebiyu7ul69aMMDkychkoTxo2I,5851
@@ -227,7 +227,7 @@ flet/pubsub/pubsub_hub.py,sha256=1loRKhFYq23E89EYPaK4RMCbFdOW2qVeTQk8JqnbNp8,651
227
227
  flet/security/__init__.py,sha256=LcBftVee6pXMB2MiDsc0PPUXnTlR2CT53VAPiPadaHI,2189
228
228
  flet/testing/__init__.py,sha256=Yb9e6h11b2hV7O3TuqsJ7zwFAgNcbB7tY7Gp2ssxtN4,176
229
229
  flet/testing/finder.py,sha256=Rqv4qwjMcVx4ZYAJgZgGT2GVH5OR4ZgoQeKj5ZsFsRc,346
230
- flet/testing/flet_test_app.py,sha256=DNgSp1lRzJ5Wess7WdPrjScMB3RPx9jSeT9cTeiNBnM,14037
230
+ flet/testing/flet_test_app.py,sha256=T9SZMl1swPqhyu-BXhymVckxX0WuFbOO1AjbBJ3bE-U,16342
231
231
  flet/testing/tester.py,sha256=_DSRFQQoGISve5JR2nq3AdSbUf18E6FfG3ytRD5tAfo,4946
232
232
  flet/utils/__init__.py,sha256=LVgyCBf1VNqGXkdtf1JCP20Rx2oaPITF4nAGw2zquVI,1739
233
233
  flet/utils/browser.py,sha256=Z2PomJjClBXRRiPvGP7WRzbguvXQ8W2HQAzd_A5cmvE,157
@@ -246,8 +246,8 @@ flet/utils/platform_utils.py,sha256=U4cqV3EPi5QNYjbhfZmtk41-KMtI_P7KvVdnZzMOgJA,
246
246
  flet/utils/slugify.py,sha256=e-lsoDc2_dk5jQnySaHCU83AA4O6mguEgCEdk2smW2Y,466
247
247
  flet/utils/strings.py,sha256=R63_i7PdSAStCDPJ-O_WHBt3H02JQ14GSbnjLIpPTUc,178
248
248
  flet/utils/vector.py,sha256=pYZzjldBWCZbSeSkZ8VmujwcZC7VBWk1NLBPA-2th3U,3207
249
- flet-0.70.0.dev6326.dist-info/METADATA,sha256=hqlcYv0ZbExcuDKzYQGHdrYWdWI8N-gWoO-OQWBmJEY,6109
250
- flet-0.70.0.dev6326.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
251
- flet-0.70.0.dev6326.dist-info/entry_points.txt,sha256=mbBhHNUnLHiDqR36WeJrfLJU0Y0y087-M4wagQmaQ_Y,39
252
- flet-0.70.0.dev6326.dist-info/top_level.txt,sha256=HbLrSnWJX2jZOEZAI14cGzW8Q5BbOGTtE-7knD5FDh0,5
253
- flet-0.70.0.dev6326.dist-info/RECORD,,
249
+ flet-0.70.0.dev6348.dist-info/METADATA,sha256=pU5esLo0SL-Pc8IQhfQ7E7pFo5jDRJHbRzjAwpQwbEw,6109
250
+ flet-0.70.0.dev6348.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
251
+ flet-0.70.0.dev6348.dist-info/entry_points.txt,sha256=mbBhHNUnLHiDqR36WeJrfLJU0Y0y087-M4wagQmaQ_Y,39
252
+ flet-0.70.0.dev6348.dist-info/top_level.txt,sha256=HbLrSnWJX2jZOEZAI14cGzW8Q5BbOGTtE-7knD5FDh0,5
253
+ flet-0.70.0.dev6348.dist-info/RECORD,,