pytypehintweb 1.2.1__tar.gz → 1.2.2__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 (35) hide show
  1. pytypehintweb-1.2.2/PKG-INFO +82 -0
  2. pytypehintweb-1.2.2/README.md +47 -0
  3. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/pyproject.toml +1 -0
  4. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/__init__.py +1 -1
  5. pytypehintweb-1.2.2/src/pytypehintweb.egg-info/PKG-INFO +82 -0
  6. pytypehintweb-1.2.1/PKG-INFO +0 -193
  7. pytypehintweb-1.2.1/README.md +0 -159
  8. pytypehintweb-1.2.1/src/pytypehintweb.egg-info/PKG-INFO +0 -193
  9. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/LICENSE +0 -0
  10. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/setup.cfg +0 -0
  11. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/decode.py +0 -0
  12. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/demo/__init__.py +0 -0
  13. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/demo/__main__.py +0 -0
  14. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/demo/app.py +0 -0
  15. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/demo/examples.py +0 -0
  16. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/plan.py +0 -0
  17. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/py.typed +0 -0
  18. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/contract.js +0 -0
  19. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/defaults.js +0 -0
  20. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/fields.js +0 -0
  21. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/form.js +0 -0
  22. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/icons/select-arrow-dark.svg +0 -0
  23. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/icons/select-arrow-light.svg +0 -0
  24. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/icons/trash.svg +0 -0
  25. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/inputs.js +0 -0
  26. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/iso.js +0 -0
  27. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/normalize.js +0 -0
  28. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/slider.js +0 -0
  29. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/static/widgets.css +0 -0
  30. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb/types.py +0 -0
  31. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb.egg-info/SOURCES.txt +0 -0
  32. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb.egg-info/dependency_links.txt +0 -0
  33. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb.egg-info/entry_points.txt +0 -0
  34. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb.egg-info/requires.txt +0 -0
  35. {pytypehintweb-1.2.1 → pytypehintweb-1.2.2}/src/pytypehintweb.egg-info/top_level.txt +0 -0
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytypehintweb
3
+ Version: 1.2.2
4
+ Summary: Framework-free browser form layer for pytypehint
5
+ Author: Beltran Offerrall
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/offerrall/pytypehintweb
8
+ Project-URL: Documentation, https://offerrall.github.io/pytypehintweb/
9
+ Project-URL: Repository, https://github.com/offerrall/pytypehintweb
10
+ Project-URL: Issues, https://github.com/offerrall/pytypehintweb/issues
11
+ Keywords: forms,type-hints,dataclasses,schema,web,html
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: JavaScript
20
+ Classifier: Topic :: Software Development :: User Interfaces
21
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: pytypehint==1.0.0
27
+ Provides-Extra: demo
28
+ Requires-Dist: fastapi; extra == "demo"
29
+ Requires-Dist: uvicorn; extra == "demo"
30
+ Requires-Dist: python-multipart; extra == "demo"
31
+ Provides-Extra: test
32
+ Requires-Dist: pytest; extra == "test"
33
+ Requires-Dist: mypy; extra == "test"
34
+ Dynamic: license-file
35
+
36
+ # pytypehintweb
37
+
38
+ Python schemas in. Portable form plans and browser widgets out.
39
+
40
+ pytypehintweb turns a [pytypehint](https://offerrall.github.io/pytypehint/)
41
+ schema into a self-contained, JSON-serializable form plan, and renders that plan
42
+ in the browser with plain JavaScript widgets: no framework, no build step, no
43
+ npm. The browser side reads plans, not Python, so hand-written plans and plans
44
+ from another backend render the same way.
45
+
46
+ It is the rendering layer only. Routing, serving, submission and running the
47
+ function stay with the host application, or with
48
+ [func-to-web](https://offerrall.github.io/func-to-web/), which builds the whole
49
+ request cycle on top of it.
50
+
51
+ ```python
52
+ from typing import Annotated
53
+
54
+ from pytypehint import Label, Min
55
+ from pytypehintweb import plan_of
56
+
57
+
58
+ def create_user(
59
+ username: Annotated[str, Min(3), Label("Username")],
60
+ age: Annotated[int, Min(0), Label("Age")],
61
+ ) -> None:
62
+ pass
63
+
64
+
65
+ plan = plan_of(create_user) # a JSON-ready dict; compileForm(plan) renders it
66
+ ```
67
+
68
+ The full documentation is at https://offerrall.github.io/pytypehintweb/.
69
+
70
+ ## Documentation
71
+
72
+ - [Overview](docs/overview.md): what the library does, where it stops, its features and its stability promise.
73
+ - [Getting started](docs/getting-started.md): one complete form, from a Python function to the built result.
74
+ - [Plan contract](docs/plan.md): the plan format, every property, default and invariant.
75
+ - [Python API](docs/python.md): `plan_of()`, `decode()`, `WebConfig` and how each annotation maps to a node.
76
+ - [JavaScript API](docs/javascript.md): `compileForm()`, widgets, reading, accessibility, styling and themes.
77
+ - [Architecture](docs/architecture.md): the layers and which layer owns each rule.
78
+ - [Limitations](docs/limitations.md): what a plan cannot represent and why.
79
+
80
+ ### Maintaining
81
+
82
+ - [Testing](docs/testing.md): how to run the suites, what they guarantee, and CI and release.
@@ -0,0 +1,47 @@
1
+ # pytypehintweb
2
+
3
+ Python schemas in. Portable form plans and browser widgets out.
4
+
5
+ pytypehintweb turns a [pytypehint](https://offerrall.github.io/pytypehint/)
6
+ schema into a self-contained, JSON-serializable form plan, and renders that plan
7
+ in the browser with plain JavaScript widgets: no framework, no build step, no
8
+ npm. The browser side reads plans, not Python, so hand-written plans and plans
9
+ from another backend render the same way.
10
+
11
+ It is the rendering layer only. Routing, serving, submission and running the
12
+ function stay with the host application, or with
13
+ [func-to-web](https://offerrall.github.io/func-to-web/), which builds the whole
14
+ request cycle on top of it.
15
+
16
+ ```python
17
+ from typing import Annotated
18
+
19
+ from pytypehint import Label, Min
20
+ from pytypehintweb import plan_of
21
+
22
+
23
+ def create_user(
24
+ username: Annotated[str, Min(3), Label("Username")],
25
+ age: Annotated[int, Min(0), Label("Age")],
26
+ ) -> None:
27
+ pass
28
+
29
+
30
+ plan = plan_of(create_user) # a JSON-ready dict; compileForm(plan) renders it
31
+ ```
32
+
33
+ The full documentation is at https://offerrall.github.io/pytypehintweb/.
34
+
35
+ ## Documentation
36
+
37
+ - [Overview](docs/overview.md): what the library does, where it stops, its features and its stability promise.
38
+ - [Getting started](docs/getting-started.md): one complete form, from a Python function to the built result.
39
+ - [Plan contract](docs/plan.md): the plan format, every property, default and invariant.
40
+ - [Python API](docs/python.md): `plan_of()`, `decode()`, `WebConfig` and how each annotation maps to a node.
41
+ - [JavaScript API](docs/javascript.md): `compileForm()`, widgets, reading, accessibility, styling and themes.
42
+ - [Architecture](docs/architecture.md): the layers and which layer owns each rule.
43
+ - [Limitations](docs/limitations.md): what a plan cannot represent and why.
44
+
45
+ ### Maintaining
46
+
47
+ - [Testing](docs/testing.md): how to run the suites, what they guarantee, and CI and release.
@@ -29,6 +29,7 @@ classifiers = [
29
29
 
30
30
  [project.urls]
31
31
  Homepage = "https://github.com/offerrall/pytypehintweb"
32
+ Documentation = "https://offerrall.github.io/pytypehintweb/"
32
33
  Repository = "https://github.com/offerrall/pytypehintweb"
33
34
  Issues = "https://github.com/offerrall/pytypehintweb/issues"
34
35
 
@@ -6,7 +6,7 @@ from pytypehintweb.types import COLOR_PATTERN, EMAIL_PATTERN, Color, Email
6
6
 
7
7
  STATIC = Path(__file__).parent / "static"
8
8
 
9
- __version__ = "1.2.1"
9
+ __version__ = "1.2.2"
10
10
 
11
11
  __all__ = [
12
12
  "plan_of",
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytypehintweb
3
+ Version: 1.2.2
4
+ Summary: Framework-free browser form layer for pytypehint
5
+ Author: Beltran Offerrall
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/offerrall/pytypehintweb
8
+ Project-URL: Documentation, https://offerrall.github.io/pytypehintweb/
9
+ Project-URL: Repository, https://github.com/offerrall/pytypehintweb
10
+ Project-URL: Issues, https://github.com/offerrall/pytypehintweb/issues
11
+ Keywords: forms,type-hints,dataclasses,schema,web,html
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: JavaScript
20
+ Classifier: Topic :: Software Development :: User Interfaces
21
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: pytypehint==1.0.0
27
+ Provides-Extra: demo
28
+ Requires-Dist: fastapi; extra == "demo"
29
+ Requires-Dist: uvicorn; extra == "demo"
30
+ Requires-Dist: python-multipart; extra == "demo"
31
+ Provides-Extra: test
32
+ Requires-Dist: pytest; extra == "test"
33
+ Requires-Dist: mypy; extra == "test"
34
+ Dynamic: license-file
35
+
36
+ # pytypehintweb
37
+
38
+ Python schemas in. Portable form plans and browser widgets out.
39
+
40
+ pytypehintweb turns a [pytypehint](https://offerrall.github.io/pytypehint/)
41
+ schema into a self-contained, JSON-serializable form plan, and renders that plan
42
+ in the browser with plain JavaScript widgets: no framework, no build step, no
43
+ npm. The browser side reads plans, not Python, so hand-written plans and plans
44
+ from another backend render the same way.
45
+
46
+ It is the rendering layer only. Routing, serving, submission and running the
47
+ function stay with the host application, or with
48
+ [func-to-web](https://offerrall.github.io/func-to-web/), which builds the whole
49
+ request cycle on top of it.
50
+
51
+ ```python
52
+ from typing import Annotated
53
+
54
+ from pytypehint import Label, Min
55
+ from pytypehintweb import plan_of
56
+
57
+
58
+ def create_user(
59
+ username: Annotated[str, Min(3), Label("Username")],
60
+ age: Annotated[int, Min(0), Label("Age")],
61
+ ) -> None:
62
+ pass
63
+
64
+
65
+ plan = plan_of(create_user) # a JSON-ready dict; compileForm(plan) renders it
66
+ ```
67
+
68
+ The full documentation is at https://offerrall.github.io/pytypehintweb/.
69
+
70
+ ## Documentation
71
+
72
+ - [Overview](docs/overview.md): what the library does, where it stops, its features and its stability promise.
73
+ - [Getting started](docs/getting-started.md): one complete form, from a Python function to the built result.
74
+ - [Plan contract](docs/plan.md): the plan format, every property, default and invariant.
75
+ - [Python API](docs/python.md): `plan_of()`, `decode()`, `WebConfig` and how each annotation maps to a node.
76
+ - [JavaScript API](docs/javascript.md): `compileForm()`, widgets, reading, accessibility, styling and themes.
77
+ - [Architecture](docs/architecture.md): the layers and which layer owns each rule.
78
+ - [Limitations](docs/limitations.md): what a plan cannot represent and why.
79
+
80
+ ### Maintaining
81
+
82
+ - [Testing](docs/testing.md): how to run the suites, what they guarantee, and CI and release.
@@ -1,193 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: pytypehintweb
3
- Version: 1.2.1
4
- Summary: Framework-free browser form layer for pytypehint
5
- Author: Beltran Offerrall
6
- License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/offerrall/pytypehintweb
8
- Project-URL: Repository, https://github.com/offerrall/pytypehintweb
9
- Project-URL: Issues, https://github.com/offerrall/pytypehintweb/issues
10
- Keywords: forms,type-hints,dataclasses,schema,web,html
11
- Classifier: Development Status :: 5 - Production/Stable
12
- Classifier: Intended Audience :: Developers
13
- Classifier: Operating System :: OS Independent
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.11
16
- Classifier: Programming Language :: Python :: 3.12
17
- Classifier: Programming Language :: Python :: 3.13
18
- Classifier: Programming Language :: JavaScript
19
- Classifier: Topic :: Software Development :: User Interfaces
20
- Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
21
- Classifier: Typing :: Typed
22
- Requires-Python: >=3.11
23
- Description-Content-Type: text/markdown
24
- License-File: LICENSE
25
- Requires-Dist: pytypehint==1.0.0
26
- Provides-Extra: demo
27
- Requires-Dist: fastapi; extra == "demo"
28
- Requires-Dist: uvicorn; extra == "demo"
29
- Requires-Dist: python-multipart; extra == "demo"
30
- Provides-Extra: test
31
- Requires-Dist: pytest; extra == "test"
32
- Requires-Dist: mypy; extra == "test"
33
- Dynamic: license-file
34
-
35
- # pytypehintweb
36
-
37
- [![PyPI version](https://img.shields.io/pypi/v/pytypehintweb.svg)](https://pypi.org/project/pytypehintweb/)
38
- [![Python](https://img.shields.io/pypi/pyversions/pytypehintweb.svg)](https://pypi.org/project/pytypehintweb/)
39
- [![License](https://img.shields.io/pypi/l/pytypehintweb.svg)](LICENSE)
40
-
41
- Python schemas in. Portable form plans and browser widgets out.
42
-
43
- `pytypehintweb` is a framework-free browser form layer for
44
- [`pytypehint`](https://github.com/offerrall/pytypehint). It converts compiled
45
- Python type schemas into self-contained, JSON-serializable form plans and
46
- renders them with plain JavaScript widgets. The browser runtime also consumes
47
- hand-written plans or plans from another backend, so Python is not required at
48
- render time. Everything around the form — routing, static-file delivery,
49
- authentication, submission, function execution — belongs to the host
50
- application. (For the whole request/response cycle instead of the rendering
51
- layer, see [FuncToWeb](https://github.com/offerrall/FuncToWeb).)
52
-
53
- The public API — `plan_of()`, `decode()`, `WebConfig`, `STATIC` and the plan's
54
- own `v: 1` contract — is settled, and a breaking change to any of them belongs
55
- to a major release. Internals carry no such promise: 1.1.0 replaced most of
56
- `decode()` with a call into the core, and that kind of change is expected.
57
-
58
- ## Features
59
-
60
- - Self-contained, JSON-serializable plans from plain functions, dataclass types
61
- or compiled `Signature`/`Struct` schemas — and hand-written plans need no
62
- Python.
63
- - Framework-free browser runtime (plain HTML, CSS and JS modules), with widgets
64
- usable directly or from a plan; browser files ship inside the Python package
65
- under `pytypehintweb.STATIC`.
66
- - Optional stylesheet scoped to a `.pth-root` container, with a light/dark theme
67
- that follows the system or is forced with `data-pth-theme` — pure CSS, no
68
- theme JavaScript and no flash. Its icons are plain `.svg` files served beside
69
- it, so no `img-src data:` is needed.
70
- - `str`, `int`, `float`, `date`, `time`, `bool` and `enum` composing through lists,
71
- optional fields, unions and nested dataclasses, with constraints, static choices,
72
- integer sliders, and configurable validation messages and labels.
73
- - `file` fields (single, optional or `list[File]`, and inside dataclasses) that
74
- mint an upload reference the host redeems through its own channel, and that
75
- accept an existing reference as a plan default or through `setValue()`.
76
- - Centralized plan normalization and validation before any widget is built, and
77
- `plain` / `inline` / `wrapped` union transport.
78
- - Plan text is always rendered as text, never parsed as markup.
79
-
80
- ## Installation
81
-
82
- ```bash
83
- pip install pytypehintweb # library
84
- pip install "pytypehintweb[demo]" # + the local demo (pytypehintweb-demo)
85
- ```
86
-
87
- ```bash
88
- # Demo with all widgets, served by a local HTTP server on port 8000:
89
- pytypehintweb-demo
90
- ```
91
-
92
- There is no npm package: the browser modules live under `pytypehintweb.STATIC`
93
- and can be served by any static-file mount.
94
-
95
- ## Quick start
96
-
97
- ```python
98
- from typing import Annotated
99
-
100
- from pytypehint import Label, Min
101
- from pytypehintweb import plan_of
102
-
103
-
104
- def create_user(
105
- username: Annotated[str, Min(3), Label("Username")],
106
- age: Annotated[int, Min(0), Label("Age")],
107
- ) -> None:
108
- pass
109
-
110
-
111
- plan = plan_of(create_user)
112
- ```
113
-
114
- `plan_of()` returns ordinary Python dictionaries and lists — a single, fully
115
- expanded, self-contained document where every non-conditional property is present
116
- with an explicit value (`default` appears exactly when `hasDefault` is true),
117
- carrying a top-level `"v": 1`:
118
-
119
- ```json
120
- {
121
- "v": 1,
122
- "kind": "form",
123
- "name": "create_user",
124
- "description": null,
125
- "fields": [
126
- {
127
- "name": "username",
128
- "label": "Username",
129
- "description": null,
130
- "optional": false,
131
- "enabled": true,
132
- "hasDefault": false,
133
- "node": {
134
- "kind": "str",
135
- "options": {
136
- "minLength": 3,
137
- "maxLength": null,
138
- "pattern": null,
139
- "patternMessage": "Invalid format",
140
- "minMessage": "Must contain at least {value} characters",
141
- "maxMessage": "Must contain at most {value} characters",
142
- "placeholder": null,
143
- "password": false,
144
- "rows": null,
145
- "choices": null
146
- }
147
- }
148
- },
149
- {
150
- "name": "age",
151
- "label": "Age",
152
- "description": null,
153
- "optional": false,
154
- "enabled": true,
155
- "hasDefault": false,
156
- "node": {
157
- "kind": "int",
158
- "options": {
159
- "min": 0,
160
- "max": null,
161
- "multipleOf": null,
162
- "step": null,
163
- "slider": false,
164
- "showValue": false,
165
- "placeholder": null,
166
- "choices": null,
167
- "safeMessage": "Must be a safe integer",
168
- "invalidMessage": "Enter a valid integer",
169
- "minMessage": "Must be at least {value}",
170
- "maxMessage": "Must be at most {value}",
171
- "multipleOfMessage": "Must be a multiple of {value}",
172
- "increaseLabel": "Increase",
173
- "decreaseLabel": "Decrease"
174
- }
175
- }
176
- }
177
- ]
178
- }
179
- ```
180
-
181
- Transporting that document to the browser and compiling it with `compileForm()`
182
- is walked through end to end in [Getting started](docs/getting-started.md).
183
-
184
- ## Documentation
185
-
186
- - [Getting started](docs/getting-started.md) — the end-to-end tutorial.
187
- - [Plan contract](docs/plan.md) — the plan format, every property and invariant.
188
- - [Python API](docs/python.md) — `plan_of()`, `WebConfig`, annotation mappings.
189
- - [JavaScript API](docs/javascript.md) — `compileForm()`, widgets, reading,
190
- accessibility, styling and themes.
191
- - [Architecture](docs/architecture.md) — layers and which layer owns each rule.
192
- - [Testing](docs/testing.md) — how to run the suites and what they guarantee.
193
- - [Current limitations](docs/limitations.md).
@@ -1,159 +0,0 @@
1
- # pytypehintweb
2
-
3
- [![PyPI version](https://img.shields.io/pypi/v/pytypehintweb.svg)](https://pypi.org/project/pytypehintweb/)
4
- [![Python](https://img.shields.io/pypi/pyversions/pytypehintweb.svg)](https://pypi.org/project/pytypehintweb/)
5
- [![License](https://img.shields.io/pypi/l/pytypehintweb.svg)](LICENSE)
6
-
7
- Python schemas in. Portable form plans and browser widgets out.
8
-
9
- `pytypehintweb` is a framework-free browser form layer for
10
- [`pytypehint`](https://github.com/offerrall/pytypehint). It converts compiled
11
- Python type schemas into self-contained, JSON-serializable form plans and
12
- renders them with plain JavaScript widgets. The browser runtime also consumes
13
- hand-written plans or plans from another backend, so Python is not required at
14
- render time. Everything around the form — routing, static-file delivery,
15
- authentication, submission, function execution — belongs to the host
16
- application. (For the whole request/response cycle instead of the rendering
17
- layer, see [FuncToWeb](https://github.com/offerrall/FuncToWeb).)
18
-
19
- The public API — `plan_of()`, `decode()`, `WebConfig`, `STATIC` and the plan's
20
- own `v: 1` contract — is settled, and a breaking change to any of them belongs
21
- to a major release. Internals carry no such promise: 1.1.0 replaced most of
22
- `decode()` with a call into the core, and that kind of change is expected.
23
-
24
- ## Features
25
-
26
- - Self-contained, JSON-serializable plans from plain functions, dataclass types
27
- or compiled `Signature`/`Struct` schemas — and hand-written plans need no
28
- Python.
29
- - Framework-free browser runtime (plain HTML, CSS and JS modules), with widgets
30
- usable directly or from a plan; browser files ship inside the Python package
31
- under `pytypehintweb.STATIC`.
32
- - Optional stylesheet scoped to a `.pth-root` container, with a light/dark theme
33
- that follows the system or is forced with `data-pth-theme` — pure CSS, no
34
- theme JavaScript and no flash. Its icons are plain `.svg` files served beside
35
- it, so no `img-src data:` is needed.
36
- - `str`, `int`, `float`, `date`, `time`, `bool` and `enum` composing through lists,
37
- optional fields, unions and nested dataclasses, with constraints, static choices,
38
- integer sliders, and configurable validation messages and labels.
39
- - `file` fields (single, optional or `list[File]`, and inside dataclasses) that
40
- mint an upload reference the host redeems through its own channel, and that
41
- accept an existing reference as a plan default or through `setValue()`.
42
- - Centralized plan normalization and validation before any widget is built, and
43
- `plain` / `inline` / `wrapped` union transport.
44
- - Plan text is always rendered as text, never parsed as markup.
45
-
46
- ## Installation
47
-
48
- ```bash
49
- pip install pytypehintweb # library
50
- pip install "pytypehintweb[demo]" # + the local demo (pytypehintweb-demo)
51
- ```
52
-
53
- ```bash
54
- # Demo with all widgets, served by a local HTTP server on port 8000:
55
- pytypehintweb-demo
56
- ```
57
-
58
- There is no npm package: the browser modules live under `pytypehintweb.STATIC`
59
- and can be served by any static-file mount.
60
-
61
- ## Quick start
62
-
63
- ```python
64
- from typing import Annotated
65
-
66
- from pytypehint import Label, Min
67
- from pytypehintweb import plan_of
68
-
69
-
70
- def create_user(
71
- username: Annotated[str, Min(3), Label("Username")],
72
- age: Annotated[int, Min(0), Label("Age")],
73
- ) -> None:
74
- pass
75
-
76
-
77
- plan = plan_of(create_user)
78
- ```
79
-
80
- `plan_of()` returns ordinary Python dictionaries and lists — a single, fully
81
- expanded, self-contained document where every non-conditional property is present
82
- with an explicit value (`default` appears exactly when `hasDefault` is true),
83
- carrying a top-level `"v": 1`:
84
-
85
- ```json
86
- {
87
- "v": 1,
88
- "kind": "form",
89
- "name": "create_user",
90
- "description": null,
91
- "fields": [
92
- {
93
- "name": "username",
94
- "label": "Username",
95
- "description": null,
96
- "optional": false,
97
- "enabled": true,
98
- "hasDefault": false,
99
- "node": {
100
- "kind": "str",
101
- "options": {
102
- "minLength": 3,
103
- "maxLength": null,
104
- "pattern": null,
105
- "patternMessage": "Invalid format",
106
- "minMessage": "Must contain at least {value} characters",
107
- "maxMessage": "Must contain at most {value} characters",
108
- "placeholder": null,
109
- "password": false,
110
- "rows": null,
111
- "choices": null
112
- }
113
- }
114
- },
115
- {
116
- "name": "age",
117
- "label": "Age",
118
- "description": null,
119
- "optional": false,
120
- "enabled": true,
121
- "hasDefault": false,
122
- "node": {
123
- "kind": "int",
124
- "options": {
125
- "min": 0,
126
- "max": null,
127
- "multipleOf": null,
128
- "step": null,
129
- "slider": false,
130
- "showValue": false,
131
- "placeholder": null,
132
- "choices": null,
133
- "safeMessage": "Must be a safe integer",
134
- "invalidMessage": "Enter a valid integer",
135
- "minMessage": "Must be at least {value}",
136
- "maxMessage": "Must be at most {value}",
137
- "multipleOfMessage": "Must be a multiple of {value}",
138
- "increaseLabel": "Increase",
139
- "decreaseLabel": "Decrease"
140
- }
141
- }
142
- }
143
- ]
144
- }
145
- ```
146
-
147
- Transporting that document to the browser and compiling it with `compileForm()`
148
- is walked through end to end in [Getting started](docs/getting-started.md).
149
-
150
- ## Documentation
151
-
152
- - [Getting started](docs/getting-started.md) — the end-to-end tutorial.
153
- - [Plan contract](docs/plan.md) — the plan format, every property and invariant.
154
- - [Python API](docs/python.md) — `plan_of()`, `WebConfig`, annotation mappings.
155
- - [JavaScript API](docs/javascript.md) — `compileForm()`, widgets, reading,
156
- accessibility, styling and themes.
157
- - [Architecture](docs/architecture.md) — layers and which layer owns each rule.
158
- - [Testing](docs/testing.md) — how to run the suites and what they guarantee.
159
- - [Current limitations](docs/limitations.md).
@@ -1,193 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: pytypehintweb
3
- Version: 1.2.1
4
- Summary: Framework-free browser form layer for pytypehint
5
- Author: Beltran Offerrall
6
- License-Expression: MIT
7
- Project-URL: Homepage, https://github.com/offerrall/pytypehintweb
8
- Project-URL: Repository, https://github.com/offerrall/pytypehintweb
9
- Project-URL: Issues, https://github.com/offerrall/pytypehintweb/issues
10
- Keywords: forms,type-hints,dataclasses,schema,web,html
11
- Classifier: Development Status :: 5 - Production/Stable
12
- Classifier: Intended Audience :: Developers
13
- Classifier: Operating System :: OS Independent
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.11
16
- Classifier: Programming Language :: Python :: 3.12
17
- Classifier: Programming Language :: Python :: 3.13
18
- Classifier: Programming Language :: JavaScript
19
- Classifier: Topic :: Software Development :: User Interfaces
20
- Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
21
- Classifier: Typing :: Typed
22
- Requires-Python: >=3.11
23
- Description-Content-Type: text/markdown
24
- License-File: LICENSE
25
- Requires-Dist: pytypehint==1.0.0
26
- Provides-Extra: demo
27
- Requires-Dist: fastapi; extra == "demo"
28
- Requires-Dist: uvicorn; extra == "demo"
29
- Requires-Dist: python-multipart; extra == "demo"
30
- Provides-Extra: test
31
- Requires-Dist: pytest; extra == "test"
32
- Requires-Dist: mypy; extra == "test"
33
- Dynamic: license-file
34
-
35
- # pytypehintweb
36
-
37
- [![PyPI version](https://img.shields.io/pypi/v/pytypehintweb.svg)](https://pypi.org/project/pytypehintweb/)
38
- [![Python](https://img.shields.io/pypi/pyversions/pytypehintweb.svg)](https://pypi.org/project/pytypehintweb/)
39
- [![License](https://img.shields.io/pypi/l/pytypehintweb.svg)](LICENSE)
40
-
41
- Python schemas in. Portable form plans and browser widgets out.
42
-
43
- `pytypehintweb` is a framework-free browser form layer for
44
- [`pytypehint`](https://github.com/offerrall/pytypehint). It converts compiled
45
- Python type schemas into self-contained, JSON-serializable form plans and
46
- renders them with plain JavaScript widgets. The browser runtime also consumes
47
- hand-written plans or plans from another backend, so Python is not required at
48
- render time. Everything around the form — routing, static-file delivery,
49
- authentication, submission, function execution — belongs to the host
50
- application. (For the whole request/response cycle instead of the rendering
51
- layer, see [FuncToWeb](https://github.com/offerrall/FuncToWeb).)
52
-
53
- The public API — `plan_of()`, `decode()`, `WebConfig`, `STATIC` and the plan's
54
- own `v: 1` contract — is settled, and a breaking change to any of them belongs
55
- to a major release. Internals carry no such promise: 1.1.0 replaced most of
56
- `decode()` with a call into the core, and that kind of change is expected.
57
-
58
- ## Features
59
-
60
- - Self-contained, JSON-serializable plans from plain functions, dataclass types
61
- or compiled `Signature`/`Struct` schemas — and hand-written plans need no
62
- Python.
63
- - Framework-free browser runtime (plain HTML, CSS and JS modules), with widgets
64
- usable directly or from a plan; browser files ship inside the Python package
65
- under `pytypehintweb.STATIC`.
66
- - Optional stylesheet scoped to a `.pth-root` container, with a light/dark theme
67
- that follows the system or is forced with `data-pth-theme` — pure CSS, no
68
- theme JavaScript and no flash. Its icons are plain `.svg` files served beside
69
- it, so no `img-src data:` is needed.
70
- - `str`, `int`, `float`, `date`, `time`, `bool` and `enum` composing through lists,
71
- optional fields, unions and nested dataclasses, with constraints, static choices,
72
- integer sliders, and configurable validation messages and labels.
73
- - `file` fields (single, optional or `list[File]`, and inside dataclasses) that
74
- mint an upload reference the host redeems through its own channel, and that
75
- accept an existing reference as a plan default or through `setValue()`.
76
- - Centralized plan normalization and validation before any widget is built, and
77
- `plain` / `inline` / `wrapped` union transport.
78
- - Plan text is always rendered as text, never parsed as markup.
79
-
80
- ## Installation
81
-
82
- ```bash
83
- pip install pytypehintweb # library
84
- pip install "pytypehintweb[demo]" # + the local demo (pytypehintweb-demo)
85
- ```
86
-
87
- ```bash
88
- # Demo with all widgets, served by a local HTTP server on port 8000:
89
- pytypehintweb-demo
90
- ```
91
-
92
- There is no npm package: the browser modules live under `pytypehintweb.STATIC`
93
- and can be served by any static-file mount.
94
-
95
- ## Quick start
96
-
97
- ```python
98
- from typing import Annotated
99
-
100
- from pytypehint import Label, Min
101
- from pytypehintweb import plan_of
102
-
103
-
104
- def create_user(
105
- username: Annotated[str, Min(3), Label("Username")],
106
- age: Annotated[int, Min(0), Label("Age")],
107
- ) -> None:
108
- pass
109
-
110
-
111
- plan = plan_of(create_user)
112
- ```
113
-
114
- `plan_of()` returns ordinary Python dictionaries and lists — a single, fully
115
- expanded, self-contained document where every non-conditional property is present
116
- with an explicit value (`default` appears exactly when `hasDefault` is true),
117
- carrying a top-level `"v": 1`:
118
-
119
- ```json
120
- {
121
- "v": 1,
122
- "kind": "form",
123
- "name": "create_user",
124
- "description": null,
125
- "fields": [
126
- {
127
- "name": "username",
128
- "label": "Username",
129
- "description": null,
130
- "optional": false,
131
- "enabled": true,
132
- "hasDefault": false,
133
- "node": {
134
- "kind": "str",
135
- "options": {
136
- "minLength": 3,
137
- "maxLength": null,
138
- "pattern": null,
139
- "patternMessage": "Invalid format",
140
- "minMessage": "Must contain at least {value} characters",
141
- "maxMessage": "Must contain at most {value} characters",
142
- "placeholder": null,
143
- "password": false,
144
- "rows": null,
145
- "choices": null
146
- }
147
- }
148
- },
149
- {
150
- "name": "age",
151
- "label": "Age",
152
- "description": null,
153
- "optional": false,
154
- "enabled": true,
155
- "hasDefault": false,
156
- "node": {
157
- "kind": "int",
158
- "options": {
159
- "min": 0,
160
- "max": null,
161
- "multipleOf": null,
162
- "step": null,
163
- "slider": false,
164
- "showValue": false,
165
- "placeholder": null,
166
- "choices": null,
167
- "safeMessage": "Must be a safe integer",
168
- "invalidMessage": "Enter a valid integer",
169
- "minMessage": "Must be at least {value}",
170
- "maxMessage": "Must be at most {value}",
171
- "multipleOfMessage": "Must be a multiple of {value}",
172
- "increaseLabel": "Increase",
173
- "decreaseLabel": "Decrease"
174
- }
175
- }
176
- }
177
- ]
178
- }
179
- ```
180
-
181
- Transporting that document to the browser and compiling it with `compileForm()`
182
- is walked through end to end in [Getting started](docs/getting-started.md).
183
-
184
- ## Documentation
185
-
186
- - [Getting started](docs/getting-started.md) — the end-to-end tutorial.
187
- - [Plan contract](docs/plan.md) — the plan format, every property and invariant.
188
- - [Python API](docs/python.md) — `plan_of()`, `WebConfig`, annotation mappings.
189
- - [JavaScript API](docs/javascript.md) — `compileForm()`, widgets, reading,
190
- accessibility, styling and themes.
191
- - [Architecture](docs/architecture.md) — layers and which layer owns each rule.
192
- - [Testing](docs/testing.md) — how to run the suites and what they guarantee.
193
- - [Current limitations](docs/limitations.md).
File without changes
File without changes