fastlifeweb 0.28.7__py3-none-any.whl → 0.29.0__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.
- CHANGELOG.md +9 -0
- fastlife/adapters/jinjax/widget_factory/factory.py +2 -0
- fastlife/adapters/jinjax/widget_factory/uuid_builder.py +46 -0
- fastlife/adapters/xcomponent/pydantic_form/widget_factory/factory.py +2 -0
- fastlife/adapters/xcomponent/pydantic_form/widget_factory/simpletype_builder.py +1 -1
- fastlife/adapters/xcomponent/pydantic_form/widget_factory/uuid_builder.py +47 -0
- fastlife/config/configurator.py +1 -1
- {fastlifeweb-0.28.7.dist-info → fastlifeweb-0.29.0.dist-info}/METADATA +20 -10
- {fastlifeweb-0.28.7.dist-info → fastlifeweb-0.29.0.dist-info}/RECORD +12 -10
- {fastlifeweb-0.28.7.dist-info → fastlifeweb-0.29.0.dist-info}/WHEEL +0 -0
- {fastlifeweb-0.28.7.dist-info → fastlifeweb-0.29.0.dist-info}/entry_points.txt +0 -0
- {fastlifeweb-0.28.7.dist-info → fastlifeweb-0.29.0.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 0.29.0 - Released on 2025-11-03
|
|
2
|
+
* Change behavior on how UUID are rendered in pydantic form.
|
|
3
|
+
By default, they becomes hidden fields.
|
|
4
|
+
* Update the doc for xcomponent usage, depracating jinjax that
|
|
5
|
+
is not up to date and has changed is attribute syntax again.
|
|
6
|
+
|
|
7
|
+
## 0.28.8 - Released on 2025-10-22
|
|
8
|
+
* Fix optional template engine bis.
|
|
9
|
+
|
|
1
10
|
## 0.28.7 - Released on 2025-10-19
|
|
2
11
|
* Fix optional template engine.
|
|
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
|
|
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
|
+
)
|
fastlife/config/configurator.py
CHANGED
|
@@ -184,7 +184,7 @@ class GenericConfigurator(Generic[TRegistry]):
|
|
|
184
184
|
f"fastlife.adapters.{optional_adapter}",
|
|
185
185
|
ignore="fastlife.adapters.jinjax.jinjax_ext.jinjax_doc",
|
|
186
186
|
)
|
|
187
|
-
except ConfigurationError:
|
|
187
|
+
except (ModuleNotFoundError, ConfigurationError):
|
|
188
188
|
pass
|
|
189
189
|
|
|
190
190
|
app = FastAPI(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fastlifeweb
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.29.0
|
|
4
4
|
Summary: High-level web framework
|
|
5
5
|
Author-Email: Guillaume Gauvrit <guillaume@gauvr.it>
|
|
6
6
|
License: MIT
|
|
@@ -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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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=
|
|
1
|
+
CHANGELOG.md,sha256=M0AcLWEwr1k1ALXxY3msvsPCXEv_mozQzbBUgzGKt3E,9984
|
|
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=
|
|
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=
|
|
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=
|
|
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
|
|
@@ -1728,7 +1730,7 @@ fastlife/components/pydantic_form/FatalError.jinja,sha256=ADtQvmo-e-NmDcFM1E6wZV
|
|
|
1728
1730
|
fastlife/components/pydantic_form/Hint.jinja,sha256=8leBpfMGDmalc_KAjr2paTojr_rwq-luS6m_1BGj7Tw,202
|
|
1729
1731
|
fastlife/components/pydantic_form/Widget.jinja,sha256=PgguUpvhG6CY9AW6H8qQMjKqjlybjDCAaFFAOHzrzVQ,418
|
|
1730
1732
|
fastlife/config/__init__.py,sha256=5qpuaVYqi-AS0GgsfggM6rFsSwXgrqrLBo9jH6dVroc,407
|
|
1731
|
-
fastlife/config/configurator.py,sha256=
|
|
1733
|
+
fastlife/config/configurator.py,sha256=kUq_aUO8ybBvxh-fviT3mUTQqINQf7-hDHDlUXDDKHU,25027
|
|
1732
1734
|
fastlife/config/exceptions.py,sha256=9MdBnbfy-Aw-KaIFzju0Kh8Snk41-v9LqK2w48Tdy1s,1169
|
|
1733
1735
|
fastlife/config/openapiextra.py,sha256=rYoerrn9sni2XwnO3gIWqaz7M0aDZPhVLjzqhDxue0o,514
|
|
1734
1736
|
fastlife/config/resources.py,sha256=stKCuZQGgiDW9xTrTNxKMb_JzkgkM1Ubum1b7OK4Lm4,8780
|
|
@@ -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.
|
|
1776
|
-
fastlifeweb-0.
|
|
1777
|
-
fastlifeweb-0.
|
|
1778
|
-
fastlifeweb-0.
|
|
1779
|
-
fastlifeweb-0.
|
|
1777
|
+
fastlifeweb-0.29.0.dist-info/METADATA,sha256=g1tNKg7zLrzhgcWeIvu9keZxoM8aT7MK2YhvyT_wETE,4396
|
|
1778
|
+
fastlifeweb-0.29.0.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
|
|
1779
|
+
fastlifeweb-0.29.0.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
|
1780
|
+
fastlifeweb-0.29.0.dist-info/licenses/LICENSE,sha256=JFWuiKYRXKKMEAsX0aZp3hBcju-HYflJ2rwJAGwbCJo,1080
|
|
1781
|
+
fastlifeweb-0.29.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|