fastlifeweb 0.28.8__py3-none-any.whl → 0.29.1__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 fastlifeweb might be problematic. Click here for more details.

CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.29.1 - Released on 2025-11-03
2
+ * Don't emit UserWarning while building pydantic form data at editing.
3
+
4
+ ## 0.29.0 - Released on 2025-11-03
5
+ * Change behavior on how UUID are rendered in pydantic form.
6
+ By default, they becomes hidden fields.
7
+ * Update the doc for xcomponent usage, depracating jinjax that
8
+ is not up to date and has changed is attribute syntax again.
9
+
1
10
  ## 0.28.8 - Released on 2025-10-22
2
11
  * Fix optional template engine bis.
3
12
 
@@ -27,6 +27,7 @@ from .sequence_builder import SequenceBuilder
27
27
  from .set_builder import SetBuilder
28
28
  from .simpletype_builder import SimpleTypeBuilder
29
29
  from .union_builder import UnionBuilder
30
+ from .uuid_builder import UuidBuilder
30
31
 
31
32
 
32
33
  class FatalError(JinjaXTemplate):
@@ -59,6 +60,7 @@ class WidgetFactory:
59
60
  EnumBuilder(self),
60
61
  EmailStrBuilder(self),
61
62
  SecretStrBuilder(self),
63
+ UuidBuilder(self),
62
64
  # we keep simple types, str, int at the end
63
65
  SimpleTypeBuilder(self),
64
66
  ]
@@ -0,0 +1,46 @@
1
+ """Handle simple types (str, int, float, ...)."""
2
+
3
+ from collections.abc import Mapping
4
+ from typing import Any
5
+ from uuid import UUID
6
+
7
+ from pydantic.fields import FieldInfo
8
+
9
+ from fastlife.adapters.jinjax.widget_factory.base import BaseWidgetBuilder
10
+ from fastlife.adapters.jinjax.widgets.base import Widget
11
+ from fastlife.adapters.jinjax.widgets.hidden import HiddenWidget
12
+ from fastlife.domain.model.types import Builtins
13
+
14
+
15
+ class UuidBuilder(BaseWidgetBuilder[UUID]):
16
+ """Builder for simple types."""
17
+
18
+ def accept(self, typ: type[Any], origin: type[Any] | None) -> bool:
19
+ """True for simple types: int, str, float, Decimal, UUID"""
20
+ return issubclass(typ, UUID)
21
+
22
+ def build(
23
+ self,
24
+ *,
25
+ field_name: str,
26
+ field_type: type[Any],
27
+ field: FieldInfo | None,
28
+ value: Builtins | None,
29
+ form_errors: Mapping[str, Any],
30
+ removable: bool,
31
+ ) -> Widget[UUID]:
32
+ """Build the widget."""
33
+ return HiddenWidget(
34
+ name=field_name,
35
+ title=field.title or "" if field else "",
36
+ hint=field.description if field else None,
37
+ aria_label=(
38
+ field.json_schema_extra.get("aria_label") # type:ignore
39
+ if field and field.json_schema_extra
40
+ else None
41
+ ),
42
+ removable=removable,
43
+ token=self.factory.token,
44
+ value=str(value) if value else "",
45
+ error=form_errors.get(field_name),
46
+ )
@@ -27,6 +27,7 @@ from .sequence_builder import SequenceBuilder
27
27
  from .set_builder import SetBuilder
28
28
  from .simpletype_builder import SimpleTypeBuilder
29
29
  from .union_builder import UnionBuilder
30
+ from .uuid_builder import UuidBuilder
30
31
 
31
32
 
32
33
  class OptionalFatalError(XTemplate):
@@ -67,6 +68,7 @@ class WidgetFactory:
67
68
  EnumBuilder(self),
68
69
  EmailStrBuilder(self),
69
70
  SecretStrBuilder(self),
71
+ UuidBuilder(self),
70
72
  # we keep simple types, str, int at the end
71
73
  SimpleTypeBuilder(self),
72
74
  ]
@@ -17,7 +17,7 @@ class SimpleTypeBuilder(BaseWidgetBuilder[Builtins]):
17
17
  """Builder for simple types."""
18
18
 
19
19
  def accept(self, typ: type[Any], origin: type[Any] | None) -> bool:
20
- """True for simple types: int, str, float, Decimal, UUID"""
20
+ """True for simple types: int, str, float, Decimal."""
21
21
  return issubclass(typ, Builtins)
22
22
 
23
23
  def build(
@@ -0,0 +1,47 @@
1
+ """Handle simple types (str, int, float, ...)."""
2
+
3
+ from collections.abc import Mapping
4
+ from typing import Any
5
+ from uuid import UUID
6
+
7
+ from pydantic.fields import FieldInfo
8
+
9
+ from fastlife.adapters.xcomponent.pydantic_form.widget_factory.base import (
10
+ BaseWidgetBuilder,
11
+ )
12
+ from fastlife.adapters.xcomponent.pydantic_form.widgets.base import Widget
13
+ from fastlife.adapters.xcomponent.pydantic_form.widgets.hidden import HiddenWidget
14
+
15
+
16
+ class UuidBuilder(BaseWidgetBuilder[UUID]):
17
+ """Builder for simple types."""
18
+
19
+ def accept(self, typ: type[Any], origin: type[Any] | None) -> bool:
20
+ """True for simple types: int, str, float, Decimal, UUID"""
21
+ return issubclass(typ, UUID)
22
+
23
+ def build(
24
+ self,
25
+ *,
26
+ field_name: str,
27
+ field_type: type[Any],
28
+ field: FieldInfo | None,
29
+ value: UUID | None,
30
+ form_errors: Mapping[str, Any],
31
+ removable: bool,
32
+ ) -> Widget[UUID]:
33
+ """Build the widget."""
34
+ return HiddenWidget(
35
+ name=field_name,
36
+ title=field.title or "" if field else "",
37
+ hint=field.description if field else None,
38
+ aria_label=(
39
+ field.json_schema_extra.get("aria_label") # type:ignore
40
+ if field and field.json_schema_extra
41
+ else None
42
+ ),
43
+ removable=removable,
44
+ token=self.factory.token,
45
+ value=str(value) if value else "",
46
+ error=form_errors.get(field_name),
47
+ )
@@ -51,7 +51,7 @@ class FormModel(Generic[T]):
51
51
 
52
52
  @property
53
53
  def form_data(self) -> Mapping[str, Any]:
54
- return {self.prefix: self.model.model_dump()}
54
+ return {self.prefix: self.model.model_dump(warnings="none")}
55
55
 
56
56
  @classmethod
57
57
  def from_payload(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastlifeweb
3
- Version: 0.28.8
3
+ Version: 0.29.1
4
4
  Summary: High-level web framework
5
5
  Author-Email: Guillaume Gauvrit <guillaume@gauvr.it>
6
6
  License: MIT
@@ -21,7 +21,7 @@ Requires-Dist: fastapi[standard]<0.116.0,>=0.115.4
21
21
  Requires-Dist: itsdangerous<3,>=2.1.2
22
22
  Requires-Dist: markupsafe<3,>=2.1.3
23
23
  Requires-Dist: multidict<7,>=6.0.5
24
- Requires-Dist: pydantic<3,>=2.5.3
24
+ Requires-Dist: pydantic<3,>=2.7.0
25
25
  Requires-Dist: pydantic-settings<3,>=2.0.3
26
26
  Requires-Dist: python-multipart<1,>=0.0.13
27
27
  Requires-Dist: venusian<4,>=3.0.0
@@ -60,18 +60,17 @@ An opinionated Python web framework (based on {term}`FastAPI`).
60
60
  Fastlife helps at building Web Application with session, security, html test client,
61
61
  and html form generated from pydantic schema using customizable widget.
62
62
 
63
- Templates are made using {term}`JinjaX` and an extensible [set of
64
- component](https://mardiros.github.io/fastlife/components/index.html) is available
65
- in order to build pages.
63
+ ### Hypermedia based
64
+
65
+ In Fastlife, templates are made using {term}`XComponent`.
66
+ It's a modern HTML template made to create template with components.
66
67
 
67
68
  Those components are currently stylized by {term}`Tailwind CSS`,
68
69
  using [pytailwindcss](https://github.com/timonweb/pytailwindcss).
69
70
 
70
- Moreover, you can also write API, in an opinionated way to enforce documentation
71
- consistency.
72
-
71
+ Even if it is not used by fastlife, it has been made to be used with {term}`HTMX`.
73
72
 
74
- ## First class configuration.
73
+ ### First class configuration.
75
74
 
76
75
  Fastlife is adding a "Configurator", like {term}`Pyramid` to get a better scallable codebase.
77
76
 
@@ -80,16 +79,27 @@ enabling easy management and overriding at different levels.
80
79
  This promotes modularity and clarity in application configuration, making it simpler
81
80
  to maintain and scale your project.
82
81
 
82
+ ### Auto generated HTML Form.
83
+
84
+ Fastlife generate HTML Form from pydantic models, default widgets depending on
85
+ the type of the model's field but customizable to get the expected results.
83
86
 
84
- ## Tests
87
+ It allows fast development of form to get early prototype to focus on what matter
88
+ the most.
89
+
90
+ ### Tests
85
91
 
86
92
  Fastlife comes with [a test client](https://mardiros.github.io/fastlife/develop/fastlife/fastlife.testing.testclient.html) that can interact with html inside unit tests.
87
93
 
94
+ ### API
95
+
96
+ It also comes with an opinionated API wrapper made to enforce documentation consistency.
97
+ Under the wood, it's a FastAPI application made for writing API.
88
98
 
89
99
  ## Try it
90
100
 
91
101
  The package is available on pypi with the name fastlifeweb.
92
102
 
93
103
  ```bash
94
- pip install fastlifeweb
104
+ pip install "fastlifeweb[xcomponent]"
95
105
  ```
@@ -1,4 +1,4 @@
1
- CHANGELOG.md,sha256=sFFz-ksoOzyVjvY5Yke5WPk_PCDyG45ncgmyhZ0If2A,9718
1
+ CHANGELOG.md,sha256=AM0DqAKkkEBSXBSlmKyQVogX8z8VUijBnJU72S_h_Uw,10092
2
2
  fastlife/__init__.py,sha256=XtGrcI5a3MPSl4vupeWT4ZijISiXtAhjcL6eRt9WpfE,2503
3
3
  fastlife/adapters/__init__.py,sha256=imPD1hImpgrYkvUJRhHA5kVyGAua7VbP2WGkhSWKJT8,93
4
4
  fastlife/adapters/fastapi/__init__.py,sha256=1goV1FGFP04TGyskJBLKZam4Gvt1yoAvLMNs4ekWSSQ,243
@@ -23,7 +23,7 @@ fastlife/adapters/jinjax/widget_factory/base.py,sha256=TLEpYdekR4AeHhIie_DICc_oS
23
23
  fastlife/adapters/jinjax/widget_factory/bool_builder.py,sha256=ElIDb6rlUiwuDAetC22TreoMa9HDgoZ2euVV1VurFFY,1291
24
24
  fastlife/adapters/jinjax/widget_factory/emailstr_builder.py,sha256=1niv0fB-KXV5wEjs5Q7PmKMs0RlmQ8CmGJ8YLw3cI7k,1566
25
25
  fastlife/adapters/jinjax/widget_factory/enum_builder.py,sha256=agx67oUeVy5_BKzY4WV0DxT67R43Vy74CoeHl9PBvK4,1527
26
- fastlife/adapters/jinjax/widget_factory/factory.py,sha256=zTa6zbpW5lAh_eHlhO6XBP2GbeDTHatymhMAJQ-alTI,5915
26
+ fastlife/adapters/jinjax/widget_factory/factory.py,sha256=3yK4_Cxwz4yoluspK5XMb6BX6ViEDkiB344EqCnjr-Q,5984
27
27
  fastlife/adapters/jinjax/widget_factory/literal_builder.py,sha256=mrtWbDMKNFtw5ufJK3DnkkttGGk16EnDQhejyOd57Ys,1758
28
28
  fastlife/adapters/jinjax/widget_factory/model_builder.py,sha256=WgIEUExtGO_s9AlNQlaTG_136ipe64MIJsNP0nlnsOc,2236
29
29
  fastlife/adapters/jinjax/widget_factory/secretstr_builder.py,sha256=-A7tEQTvzc1M9eNPvEZ_9EYX8zqel2XjLGNFH-V6iqk,1564
@@ -31,6 +31,7 @@ fastlife/adapters/jinjax/widget_factory/sequence_builder.py,sha256=j5KRfK5R8q_Qd
31
31
  fastlife/adapters/jinjax/widget_factory/set_builder.py,sha256=kwtVLATkoOFTcKBKHk7xZwQxRomPCic0sp4Bsd8YQfM,2742
32
32
  fastlife/adapters/jinjax/widget_factory/simpletype_builder.py,sha256=olP66B9AMY1X8fgEAxhMdozWN_w1TtcIAIW6uPJRSng,1570
33
33
  fastlife/adapters/jinjax/widget_factory/union_builder.py,sha256=qQOK3Y4I0Tg0XOzU_DwseaaKRmqQ7ORMfFyIHd6oysU,2841
34
+ fastlife/adapters/jinjax/widget_factory/uuid_builder.py,sha256=zq3LhABzJOIlHd8_pn4vwEpDbtxAM_o0L7xlHLfEiNc,1494
34
35
  fastlife/adapters/jinjax/widgets/__init__.py,sha256=HERnX9xiXUbTDz3XtlnHWABTBjhIq_kkBgWs5E6ZIMY,42
35
36
  fastlife/adapters/jinjax/widgets/base.py,sha256=M1Mu4ArU_YCxRrhisaMMzjKMNCw7npX5DRfdZyVKuks,4120
36
37
  fastlife/adapters/jinjax/widgets/boolean.py,sha256=gHErI8tp_6J3kuqjL4-i1dw-UuR65zDsOCcVKcg_s4E,624
@@ -60,14 +61,15 @@ fastlife/adapters/xcomponent/pydantic_form/widget_factory/base.py,sha256=iKqYXpK
60
61
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/bool_builder.py,sha256=nE8Q2kaYhLyTTPFn7Hi8vSTotGLdmKthM_ryzTiBiIY,1336
61
62
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/emailstr_builder.py,sha256=9RDlB-Lvmwp0h5XNW-dnb6rDPwx2MabrguQJ2Dtfveg,1611
62
63
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/enum_builder.py,sha256=wZRODjXX_LAEWbkA61XxtALctw1t94CjEDb52hJ4av0,1590
63
- fastlife/adapters/xcomponent/pydantic_form/widget_factory/factory.py,sha256=V8QBKnz_Bx-7L5B9V0nbYPXFrFXbD4VjeSKPOt-Hg2o,6138
64
+ fastlife/adapters/xcomponent/pydantic_form/widget_factory/factory.py,sha256=4Um7jR54e0KMb9blyHc1PE2aHMzCJzzB391Vo6LDVDg,6207
64
65
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/literal_builder.py,sha256=7_nv3vtnVxKYAuPp2CJVWQvvZLf_NJYZ4qS2l-oqJQg,1821
65
66
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/model_builder.py,sha256=AgT7dRzu5COns6iUBpDvz2Fq8Ob48fT0aNT-9ozQlkE,2299
66
67
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/secretstr_builder.py,sha256=TbeYqeHXlSQY2H5B6JsiOmdsT9202ICa4DEvQu_5btE,1627
67
68
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/sequence_builder.py,sha256=mpdol0o2RnNRUyIUvdkyWsX-EdnGAvxxTBuT6gpY4lw,2007
68
69
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/set_builder.py,sha256=4Zn9pK8vFmyVN2x6Ur5vG40L_gGFDvrwAc2KDv9RB7E,2818
69
- fastlife/adapters/xcomponent/pydantic_form/widget_factory/simpletype_builder.py,sha256=ADQH1YogP5NHkWPoqi7aTWICAVZ33m8Q1i_dx4w4nx8,1633
70
+ fastlife/adapters/xcomponent/pydantic_form/widget_factory/simpletype_builder.py,sha256=kt8uCCZrrAUxzc8rV_h_liOVrZQutQBsXVIA8HrI9rk,1628
70
71
  fastlife/adapters/xcomponent/pydantic_form/widget_factory/union_builder.py,sha256=bRxEF75S3In2vGnHxcONEjUGeVt_5c_6CP11WOfXP4Y,2904
72
+ fastlife/adapters/xcomponent/pydantic_form/widget_factory/uuid_builder.py,sha256=DgNZz5C5gYFfsulmAnsrEq0V0RhMRwiswHKPFwJCSW4,1504
71
73
  fastlife/adapters/xcomponent/pydantic_form/widgets/__init__.py,sha256=HERnX9xiXUbTDz3XtlnHWABTBjhIq_kkBgWs5E6ZIMY,42
72
74
  fastlife/adapters/xcomponent/pydantic_form/widgets/base.py,sha256=iHcZb_9-qTiVGUiRS9aYHrQPlqcws05LMTnQlE8qIBM,4128
73
75
  fastlife/adapters/xcomponent/pydantic_form/widgets/boolean.py,sha256=MVPehGxij8o1rul5cr4d4YIdtBu3tpT4Pj0jgcIFUws,586
@@ -1737,7 +1739,7 @@ fastlife/domain/__init__.py,sha256=3zDDos5InVX0el9OO0lgSDGzdUNYIhlA6w4uhBh2pF8,2
1737
1739
  fastlife/domain/model/__init__.py,sha256=aoBjaSpDscuFXvtknJHwiNyoJRUpE-v4X54h_wNuo2Y,27
1738
1740
  fastlife/domain/model/asgi.py,sha256=Cz45TZOtrh2pBVZr37aJ9jpnJH9BeNHrsvk9bq1nBc0,526
1739
1741
  fastlife/domain/model/csrf.py,sha256=BUiWK-S7rVciWHO1qTkM8e_KxzpF6gGC4MMJK1v6iDo,414
1740
- fastlife/domain/model/form.py,sha256=JP6uumlZBYhiPxzcdxOsfsFm5BRfvkDFvlUCD6Vy8dI,3275
1742
+ fastlife/domain/model/form.py,sha256=-rRjyoJrRFLjae9DSLXijEXl7byAZFFfr4N8kA8jP8g,3290
1741
1743
  fastlife/domain/model/request.py,sha256=hHtGsfVND3TSG7HQZI_I0n4Gp4KyaAtsjaZEc4lwrv0,3090
1742
1744
  fastlife/domain/model/response.py,sha256=Vsd2zYGGhH0D2DlfiKz1CX9OJZ_ZYoEv_-foMZpDFZo,1294
1743
1745
  fastlife/domain/model/security_policy.py,sha256=f9SLi54vvRU-KSPJ5K0unoqYpkxIyzuZjKf2Ylwf5Rg,4796
@@ -1772,8 +1774,8 @@ fastlife/testing/session.py,sha256=LEFFbiR67_x_g-ioudkY0C7PycHdbDfaIaoo_G7GXQ8,2
1772
1774
  fastlife/testing/testclient.py,sha256=gqgHQalhrLLZ8eveN2HeuoG9ne8CwxCm-Ll4b7jo9Xo,7249
1773
1775
  fastlife/views/__init__.py,sha256=zG8gveL8e2zBdYx6_9jtZfpQ6qJT-MFnBY3xXkLwHZI,22
1774
1776
  fastlife/views/pydantic_form.py,sha256=9lcS14jxddIpoN_n4VqWwU8CKhKZ8AtoD3c1Pdc-Oe4,1651
1775
- fastlifeweb-0.28.8.dist-info/METADATA,sha256=IB6OsbBqTSxYKNy00wcA0qZoFdZ_dM10VV8-wzcABCQ,3975
1776
- fastlifeweb-0.28.8.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
1777
- fastlifeweb-0.28.8.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
1778
- fastlifeweb-0.28.8.dist-info/licenses/LICENSE,sha256=JFWuiKYRXKKMEAsX0aZp3hBcju-HYflJ2rwJAGwbCJo,1080
1779
- fastlifeweb-0.28.8.dist-info/RECORD,,
1777
+ fastlifeweb-0.29.1.dist-info/METADATA,sha256=pQxD2_ivgY4Ihiq2iE6Cwq_5oFFJGGc-EOwtQ3D5NCY,4396
1778
+ fastlifeweb-0.29.1.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
1779
+ fastlifeweb-0.29.1.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
1780
+ fastlifeweb-0.29.1.dist-info/licenses/LICENSE,sha256=JFWuiKYRXKKMEAsX0aZp3hBcju-HYflJ2rwJAGwbCJo,1080
1781
+ fastlifeweb-0.29.1.dist-info/RECORD,,