talea 0.1.0__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 (76) hide show
  1. talea-0.1.0/.gitignore +32 -0
  2. talea-0.1.0/LICENSE +21 -0
  3. talea-0.1.0/PKG-INFO +317 -0
  4. talea-0.1.0/README.md +275 -0
  5. talea-0.1.0/pyproject.toml +183 -0
  6. talea-0.1.0/talea/__init__.py +51 -0
  7. talea-0.1.0/talea/codegen.py +25 -0
  8. talea-0.1.0/talea/constraints.py +179 -0
  9. talea-0.1.0/talea/contract/__init__.py +5 -0
  10. talea-0.1.0/talea/contract/api.py +247 -0
  11. talea-0.1.0/talea/contract/artifacts.py +67 -0
  12. talea-0.1.0/talea/declaration/__init__.py +12 -0
  13. talea-0.1.0/talea/declaration/metadata.py +26 -0
  14. talea-0.1.0/talea/declaration/models.py +291 -0
  15. talea-0.1.0/talea/declaration/policies.py +256 -0
  16. talea-0.1.0/talea/errors/__init__.py +6 -0
  17. talea-0.1.0/talea/errors/codes.py +37 -0
  18. talea-0.1.0/talea/errors/models.py +619 -0
  19. talea-0.1.0/talea/errors/safety.py +100 -0
  20. talea-0.1.0/talea/input/__init__.py +3 -0
  21. talea-0.1.0/talea/input/artifacts.py +151 -0
  22. talea-0.1.0/talea/input/compilation.py +427 -0
  23. talea-0.1.0/talea/input/current.py +209 -0
  24. talea-0.1.0/talea/input/emission.py +911 -0
  25. talea-0.1.0/talea/input/json.py +144 -0
  26. talea-0.1.0/talea/input/references.py +100 -0
  27. talea-0.1.0/talea/input/value.py +57 -0
  28. talea-0.1.0/talea/introspection.py +349 -0
  29. talea-0.1.0/talea/json/__init__.py +3 -0
  30. talea-0.1.0/talea/json/representations.py +108 -0
  31. talea-0.1.0/talea/json_schema/__init__.py +5 -0
  32. talea-0.1.0/talea/json_schema/api.py +47 -0
  33. talea-0.1.0/talea/json_schema/errors.py +13 -0
  34. talea-0.1.0/talea/json_schema/projection.py +563 -0
  35. talea-0.1.0/talea/metadata/__init__.py +298 -0
  36. talea-0.1.0/talea/py.typed +1 -0
  37. talea-0.1.0/talea/resources/__init__.py +6 -0
  38. talea-0.1.0/talea/resources/errors.py +29 -0
  39. talea-0.1.0/talea/resources/policy.py +65 -0
  40. talea-0.1.0/talea/resources/state.py +98 -0
  41. talea-0.1.0/talea/schema/__init__.py +63 -0
  42. talea-0.1.0/talea/schema/nodes.py +329 -0
  43. talea-0.1.0/talea/schema/references.py +100 -0
  44. talea-0.1.0/talea/schema/resolution.py +636 -0
  45. talea-0.1.0/talea/serialization/__init__.py +6 -0
  46. talea-0.1.0/talea/serialization/api.py +183 -0
  47. talea-0.1.0/talea/serialization/artifacts.py +156 -0
  48. talea-0.1.0/talea/serialization/compilation.py +163 -0
  49. talea-0.1.0/talea/serialization/declaration.py +77 -0
  50. talea-0.1.0/talea/serialization/emission.py +641 -0
  51. talea-0.1.0/talea/serialization/errors.py +53 -0
  52. talea-0.1.0/talea/serialization/hooks.py +43 -0
  53. talea-0.1.0/talea/serialization/json.py +49 -0
  54. talea-0.1.0/talea/serialization/references.py +79 -0
  55. talea-0.1.0/talea/spec/__init__.py +7 -0
  56. talea-0.1.0/talea/spec/construction.py +213 -0
  57. talea-0.1.0/talea/spec/declaration.py +483 -0
  58. talea-0.1.0/talea/spec/derivation.py +187 -0
  59. talea-0.1.0/talea/spec/dynamic.py +211 -0
  60. talea-0.1.0/talea/spec/fields.py +57 -0
  61. talea-0.1.0/talea/spec/generics.py +227 -0
  62. talea-0.1.0/talea/spec/hooks.py +127 -0
  63. talea-0.1.0/talea/spec/lifecycle.py +334 -0
  64. talea-0.1.0/talea/spec/metaclass.py +458 -0
  65. talea-0.1.0/talea/spec/presence.py +186 -0
  66. talea-0.1.0/talea/spec/replacement.py +160 -0
  67. talea-0.1.0/talea/spec/specialization.py +57 -0
  68. talea-0.1.0/talea/tagged/__init__.py +24 -0
  69. talea-0.1.0/talea/tagged/dispatch.py +19 -0
  70. talea-0.1.0/talea/tagged/validation.py +186 -0
  71. talea-0.1.0/talea/validation/__init__.py +6 -0
  72. talea-0.1.0/talea/validation/compilation.py +95 -0
  73. talea-0.1.0/talea/validation/emission.py +916 -0
  74. talea-0.1.0/talea/validation/errors.py +5 -0
  75. talea-0.1.0/talea/validation/failure_contracts.py +166 -0
  76. talea-0.1.0/talea/validation/references.py +73 -0
talea-0.1.0/.gitignore ADDED
@@ -0,0 +1,32 @@
1
+ # folders
2
+ *.egg-info/
3
+ .hypothesis/
4
+ .idea/
5
+ .mypy_cache/
6
+ .pytest_cache/
7
+ .scannerwork/
8
+ .tox/
9
+ .venv/
10
+ .vscode/
11
+ __pycache__/
12
+ virtualenv/
13
+ build/
14
+ dist/
15
+ docs/generated/
16
+ node_modules/
17
+ results/
18
+ site/
19
+ site_lang/
20
+ target/
21
+
22
+ # files
23
+ **/*.so
24
+ **/*.sqlite
25
+ *.iml
26
+ **/*_test*
27
+ .DS_Store
28
+ .coverage
29
+ .coverage.*
30
+ .python-version
31
+ coverage.*
32
+ example.sqlite
talea-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Tiago Silva.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
talea-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,317 @@
1
+ Metadata-Version: 2.5
2
+ Name: talea
3
+ Version: 0.1.0
4
+ Summary: Modern Python data contracts with strict validation, serialization, and JSON Schema
5
+ Project-URL: Homepage, https://github.com/tarsil/talea
6
+ Project-URL: Documentation, https://talea.tarsild.io
7
+ Project-URL: Changelog, https://talea.tarsild.io/release-notes/
8
+ Project-URL: Funding, https://github.com/sponsors/tarsil
9
+ Project-URL: Issues, https://github.com/tarsil/talea/issues
10
+ Project-URL: Source, https://github.com/tarsil/talea
11
+ Author-email: Tiago Silva <tiago.arasilva@gmail.com>
12
+ License-Expression: MIT
13
+ License-File: LICENSE
14
+ Keywords: data-contracts,data-validation,deserialization,json,json-schema,openapi,pure-python,runtime-validation,schema,serialization,strict-validation,structured-data,type-validation,typing,validation,zero-dependencies
15
+ Classifier: Development Status :: 3 - Alpha
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Software Development
24
+ Classifier: Topic :: Software Development :: Libraries
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Classifier: Typing :: Typed
27
+ Requires-Python: >=3.14
28
+ Provides-Extra: benchmarking
29
+ Requires-Dist: msgspec<1.0.0,>=0.20.0; extra == 'benchmarking'
30
+ Requires-Dist: pydantic<3.0.0,>=2.12.0; extra == 'benchmarking'
31
+ Provides-Extra: testing
32
+ Requires-Dist: autoflake<3.0.0,>=2.0.2; extra == 'testing'
33
+ Requires-Dist: black<25.0,==24.1.1; extra == 'testing'
34
+ Requires-Dist: hypothesis<7.0,>=6.0; extra == 'testing'
35
+ Requires-Dist: isort<6.0.0,>=5.12.0; extra == 'testing'
36
+ Requires-Dist: jsonschema<5.0.0,>=4.26.0; extra == 'testing'
37
+ Requires-Dist: openapi-spec-validator<1.0.0,>=0.9.0; extra == 'testing'
38
+ Requires-Dist: pytest-cov<5.0.0,>=4.0.0; extra == 'testing'
39
+ Requires-Dist: pytest<9.0.0,>=7.2.2; extra == 'testing'
40
+ Requires-Dist: zensical<0.1.0,>=0.0.23; extra == 'testing'
41
+ Description-Content-Type: text/markdown
42
+
43
+ # Talea
44
+
45
+ <p align="center">
46
+ <a href="https://talea.tarsild.io"><img src="https://res.cloudinary.com/dymmond/image/upload/v1787765742/Talea/logo_gn9nx6.png" alt='Talea'></a>
47
+ </p>
48
+
49
+ <p align="center">
50
+ <em>Data contracts, built for modern Python</em>
51
+ </p>
52
+
53
+ <p align="center">
54
+ <a href="https://github.com/tarsil/talea/actions/workflows/test-suite.yml/badge.svg?event=push&branch=main" target="_blank">
55
+ <img src="https://github.com/tarsil/talea/actions/workflows/test-suite.yml/badge.svg?event=push&branch=main" alt="Test Suite">
56
+ </a>
57
+
58
+ <a href="https://pypi.org/project/talea" target="_blank">
59
+ <img src="https://img.shields.io/pypi/v/talea?color=%2334D058&label=pypi%20package" alt="Package version">
60
+ </a>
61
+
62
+ <a href="https://pypi.org/project/talea" target="_blank">
63
+ <img src="https://img.shields.io/pypi/pyversions/talea.svg?color=%2334D058" alt="Supported Python versions">
64
+ </a>
65
+ </p>
66
+
67
+ ---
68
+
69
+ **Documentation**: [https://talea.tarsild.io](https://talea.tarsild.io) 📚
70
+
71
+ **Source Code**: [https://github.com/tarsil/talea](https://github.com/tarsil/talea)
72
+
73
+ **The official supported version is always the latest released**.
74
+
75
+ ---
76
+
77
+ Talea is a **2026+ Python data-contract library** for applications that want
78
+ strict Python semantics, explicit external boundaries, immutable records, and
79
+ standards-aware schemas without a required runtime dependency graph.
80
+
81
+ It is built for Python 3.14 and newer. An annotation is resolved once into one
82
+ canonical contract, then Talea compiles specialized pure-Python operations for
83
+ construction, external Mapping input, JSON input, Python output, JSON output,
84
+ and schema projection.
85
+
86
+ ```python
87
+ from typing import Annotated
88
+ from uuid import UUID
89
+
90
+ from talea import Alias, MinLength, Sensitive, Spec
91
+
92
+
93
+ class Credentials(Spec):
94
+ token: Annotated[str, Sensitive(), MinLength(16)]
95
+
96
+
97
+ class UserCreate(Spec):
98
+ user_id: Annotated[UUID, Alias("id")]
99
+ display_name: Annotated[str, Alias("displayName"), MinLength(1)]
100
+ credentials: Credentials
101
+
102
+
103
+ request = UserCreate.from_json(
104
+ """{
105
+ "id": "12345678-1234-5678-1234-567812345678",
106
+ "displayName": "Ada Lovelace",
107
+ "credentials": {"token": "correct-horse-battery-staple"}
108
+ }"""
109
+ )
110
+
111
+ assert request.user_id == UUID("12345678-1234-5678-1234-567812345678")
112
+ assert request.display_name == "Ada Lovelace"
113
+ assert "correct-horse-battery-staple" not in repr(request)
114
+ ```
115
+
116
+ The conversion above is deliberately attached to `from_json()`. Ordinary
117
+ Python construction is strict:
118
+
119
+ ```python
120
+ UserCreate(
121
+ user_id="12345678-1234-5678-1234-567812345678", # ValidationError
122
+ display_name="Ada Lovelace",
123
+ credentials=Credentials(token="correct-horse-battery-staple"),
124
+ )
125
+ ```
126
+
127
+ A UUID field accepts a Python `UUID` on the trusted path. JSON has no UUID
128
+ value, so the JSON boundary owns its documented string representation. That
129
+ separation is the core of Talea's mental model: conversion is explicit, and
130
+ already-valid Python values do not pass through a general parsing pipeline.
131
+
132
+ ## Why Talea exists
133
+
134
+ Python applications often need more than a typed record. At an API, event,
135
+ configuration, or third-party boundary they need to answer all of these
136
+ questions consistently:
137
+
138
+ - Which Python values are valid without conversion?
139
+ - Which external representations are accepted from Mapping and JSON input?
140
+ - Where does hostile input receive finite work and error budgets?
141
+ - What locations and stable codes does invalid nested data produce?
142
+ - Which names and representations appear in serialized output?
143
+ - Can a framework project the same contract as Draft 2020-12 JSON Schema or
144
+ an OpenAPI 3.1 Schema Object?
145
+ - Can tooling inspect the contract without reconstructing annotations?
146
+
147
+ Talea answers them from one canonical schema graph, while retaining separate
148
+ execution paths for operations that have different trust and performance
149
+ requirements.
150
+
151
+ “2026+” describes that starting point. Talea began with Python 3.14+, PEP 695
152
+ generics, deferred annotations, recursive type graphs, current typing behavior,
153
+ and modern JSON Schema as architectural assumptions. It did not need to carry
154
+ compatibility requirements for historical Python releases or retrofit those
155
+ assumptions into an older public contract. This is a design circumstance—not a
156
+ claim that mature libraries are obsolete, a prediction of ecosystem
157
+ replacement, or a guarantee of future superiority.
158
+
159
+ ## The boundary model
160
+
161
+ | Operation | Use it when | What it does |
162
+ | --- | --- | --- |
163
+ | `User(...)` | application code already has Python values | strict, keyword-only construction |
164
+ | `Contract(T).validate(value)` | an arbitrary root is already Python-shaped | strict validation without conversion |
165
+ | `User.from_mapping(data)` | an external Python Mapping represents an object | structural conversion with finite traversal policy |
166
+ | `Contract(T).from_python(data)` | an external root may be a list, union, alias, or TypedDict | structural conversion with finite traversal policy |
167
+ | `from_json(data)` | text or bytes crosses a serialized boundary | strict decoding, JSON representations, conversion, and resource policy |
168
+ | `to_dict()` / `to_python()` | an application needs detached Python output | schema-aware projection and current-state validation |
169
+ | `to_json()` | an application needs JSON text | schema-aware projection followed by encoding |
170
+ | `json_schema()` / `openapi_schema()` | tooling needs a standards description | projection from the same canonical graph |
171
+
172
+ JSON and Mapping boundaries are not aliases for the constructor. For example,
173
+ `Decimal`, UUID, temporal values, paths, IP values, bytes, enums, nested Specs,
174
+ and tagged unions each retain an explicit Python contract and an explicit JSON
175
+ representation.
176
+
177
+ ## What is implemented
178
+
179
+ Talea currently provides:
180
+
181
+ - strict, keyword-only, immutable, slotted `Spec` records;
182
+ - defaults and factories, inheritance, safe narrowing, custom transforms,
183
+ field checks, whole-Spec checks, and serializers;
184
+ - built-in numeric, length, and pattern constraints carried by `Annotated`;
185
+ - aliases, titles, descriptions, examples, deprecation, read/write metadata,
186
+ and sensitive-value handling;
187
+ - `Contract` for primitives, containers, unions, `TypedDict`, type aliases,
188
+ recursive graphs, tagged unions, and concrete generic specializations;
189
+ - first-class Mapping and JSON input with structured nested errors;
190
+ - finite transport-size, depth, traversal-node, and error-aggregation policy;
191
+ - presence-aware partial Specs, `derive_spec()`, and `apply_patch()` for PATCH
192
+ semantics where absent is not confused with `None`;
193
+ - canonical discriminator-based union dispatch and OpenAPI discriminator maps;
194
+ - Python and JSON serialization with explicit per-call codec boundaries;
195
+ - JSON Schema Draft 2020-12 and OpenAPI 3.1-compatible Schema Objects;
196
+ - public immutable introspection and runtime `create_spec()` declarations;
197
+ - compile-once specialized pure-Python execution with permanent benchmark
198
+ canaries for distinct workloads.
199
+
200
+ The documentation proves these features with executable account API, REST
201
+ PATCH, event, financial, recursive AST, arbitrary Contract, error/security,
202
+ schema/OpenAPI, dynamic declaration, and immutable replacement examples.
203
+
204
+ ## A complete service boundary
205
+
206
+ A framework-neutral request flow looks like this:
207
+
208
+ ```text
209
+ raw request bytes
210
+ -> ResourcePolicy
211
+ -> UserCreate.from_json(...)
212
+ -> ValidationError or ResourceLimitError
213
+ -> application/domain operation
214
+ -> UserResponse
215
+ -> to_json()
216
+ ```
217
+
218
+ Talea does not choose routes, dependency injection, HTTP status codes, ORM
219
+ behavior, or response envelopes. A FastAPI, Lilya, Django, Starlette, Flask, or
220
+ other adapter can own those framework concerns while calling the explicit
221
+ Talea boundary operations. The manual includes the entire executable flow,
222
+ plus presence-aware PATCH and generated input/output OpenAPI fragments.
223
+
224
+ ## Installation
225
+
226
+ Talea requires Python 3.14+. Install the published release from PyPI:
227
+
228
+ ```console
229
+ python -m pip install talea
230
+ ```
231
+
232
+ To install from a source checkout instead:
233
+
234
+ ```console
235
+ git clone https://github.com/tarsil/talea.git
236
+ cd talea
237
+ python -m pip install .
238
+ ```
239
+
240
+ The core package declares `dependencies = []`. Development, test, benchmark,
241
+ build, and documentation tools remain separate development dependencies.
242
+
243
+ ## Not a competition
244
+
245
+ Talea is not trying to replace Pydantic, msgspec, dataclasses, attrs, or
246
+ manually written validation.
247
+
248
+ Pydantic has broad adoption, extensive integrations, a mature ecosystem, and
249
+ coercive/parsing workflows many applications actively want. msgspec has an
250
+ extremely fast native implementation, mature serialization, and a different
251
+ set of representation and performance tradeoffs. Dataclasses and attrs remain
252
+ excellent for internal records that do not need a full external-boundary
253
+ contract. Direct Python is often clearest for three checks in one specialized
254
+ function.
255
+
256
+ Talea is another design point: strict, dependency-light, Python-native,
257
+ compile-once, explicit-boundary, introspectable, standards-aware, and
258
+ security-conscious. Selection is a requirements decision, not a winner/loser
259
+ ranking.
260
+
261
+ ## When Talea fits—and when it does not
262
+
263
+ Talea is worth evaluating when a project uses Python 3.14+, wants strict
264
+ ordinary Python construction, needs Mapping or JSON boundaries, values an
265
+ empty required dependency graph, and can benefit from structured errors,
266
+ finite external-input policy, schemas, or framework introspection.
267
+
268
+ It is likely the wrong choice when:
269
+
270
+ - the application depends heavily on Pydantic-specific integrations or wants
271
+ broad coercion by default;
272
+ - Python 3.13 or earlier must remain supported;
273
+ - settings, ORM extraction, or a large plugin ecosystem must come from the
274
+ same package;
275
+ - msgspec already exactly matches a high-throughput native serialization
276
+ workflow;
277
+ - the only requirement is a small internal record, where a dataclass or attrs
278
+ class is simpler;
279
+ - specialized validation is shorter and clearer as manually written Python;
280
+ - adopting a pre-1.0 library with a small ecosystem is unacceptable.
281
+
282
+ ## Documentation
283
+
284
+ - [Documentation home](https://talea.tarsild.io)
285
+ - [Why Talea?](https://talea.tarsild.io/getting-started/why-talea/)
286
+ - [Five-minute quickstart](https://talea.tarsild.io/getting-started/quickstart/)
287
+ - [Progressive tutorial](https://talea.tarsild.io/getting-started/tutorial/)
288
+ - [Production service boundary](https://talea.tarsild.io/getting-started/production-service/)
289
+ - [Concepts and mental model](https://talea.tarsild.io/concepts/)
290
+ - [How-to recipes](https://talea.tarsild.io/guides/recipes/)
291
+ - [Complete API reference](https://talea.tarsild.io/reference/api/)
292
+ - [Security and resource model](https://talea.tarsild.io/resource-security/)
293
+ - [Performance method and evidence](https://talea.tarsild.io/engineering/performance/)
294
+ - [Known limitations](https://talea.tarsild.io/engineering/limitations/)
295
+
296
+ For a local checkout, `task docs_test` executes all `docs_src` examples and
297
+ checks navigation, links, API inventory, and documentation policy. `task build`
298
+ builds the site; `task build_with_checks` verifies release artifacts.
299
+
300
+ ## Maturity and evidence
301
+
302
+ Talea is pre-1.0. Compatibility, deprecation, support, and release governance
303
+ are not yet frozen, and its ecosystem is necessarily much smaller than mature
304
+ alternatives. The project does not call that tradeoff complete or invisible.
305
+
306
+ Repository gates include unit and integration tests, 100% line coverage,
307
+ linting, formatting, static typing, package checks, executable documentation,
308
+ standards-conformance tests, security/adversarial cases, and 18 permanent
309
+ benchmark workloads. Performance comparisons require semantically equivalent
310
+ operations; no claim is based on removing validation from one side.
311
+
312
+ See [Contributing](https://talea.tarsild.io/contributing/) for exact commands,
313
+ [Maturity and support](https://talea.tarsild.io/release-ledger/) for current
314
+ governance, and [Security](https://talea.tarsild.io/engineering/security/) for
315
+ the technical threat model and reporting status.
316
+
317
+ Talea is licensed under the MIT License.
talea-0.1.0/README.md ADDED
@@ -0,0 +1,275 @@
1
+ # Talea
2
+
3
+ <p align="center">
4
+ <a href="https://talea.tarsild.io"><img src="https://res.cloudinary.com/dymmond/image/upload/v1787765742/Talea/logo_gn9nx6.png" alt='Talea'></a>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <em>Data contracts, built for modern Python</em>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://github.com/tarsil/talea/actions/workflows/test-suite.yml/badge.svg?event=push&branch=main" target="_blank">
13
+ <img src="https://github.com/tarsil/talea/actions/workflows/test-suite.yml/badge.svg?event=push&branch=main" alt="Test Suite">
14
+ </a>
15
+
16
+ <a href="https://pypi.org/project/talea" target="_blank">
17
+ <img src="https://img.shields.io/pypi/v/talea?color=%2334D058&label=pypi%20package" alt="Package version">
18
+ </a>
19
+
20
+ <a href="https://pypi.org/project/talea" target="_blank">
21
+ <img src="https://img.shields.io/pypi/pyversions/talea.svg?color=%2334D058" alt="Supported Python versions">
22
+ </a>
23
+ </p>
24
+
25
+ ---
26
+
27
+ **Documentation**: [https://talea.tarsild.io](https://talea.tarsild.io) 📚
28
+
29
+ **Source Code**: [https://github.com/tarsil/talea](https://github.com/tarsil/talea)
30
+
31
+ **The official supported version is always the latest released**.
32
+
33
+ ---
34
+
35
+ Talea is a **2026+ Python data-contract library** for applications that want
36
+ strict Python semantics, explicit external boundaries, immutable records, and
37
+ standards-aware schemas without a required runtime dependency graph.
38
+
39
+ It is built for Python 3.14 and newer. An annotation is resolved once into one
40
+ canonical contract, then Talea compiles specialized pure-Python operations for
41
+ construction, external Mapping input, JSON input, Python output, JSON output,
42
+ and schema projection.
43
+
44
+ ```python
45
+ from typing import Annotated
46
+ from uuid import UUID
47
+
48
+ from talea import Alias, MinLength, Sensitive, Spec
49
+
50
+
51
+ class Credentials(Spec):
52
+ token: Annotated[str, Sensitive(), MinLength(16)]
53
+
54
+
55
+ class UserCreate(Spec):
56
+ user_id: Annotated[UUID, Alias("id")]
57
+ display_name: Annotated[str, Alias("displayName"), MinLength(1)]
58
+ credentials: Credentials
59
+
60
+
61
+ request = UserCreate.from_json(
62
+ """{
63
+ "id": "12345678-1234-5678-1234-567812345678",
64
+ "displayName": "Ada Lovelace",
65
+ "credentials": {"token": "correct-horse-battery-staple"}
66
+ }"""
67
+ )
68
+
69
+ assert request.user_id == UUID("12345678-1234-5678-1234-567812345678")
70
+ assert request.display_name == "Ada Lovelace"
71
+ assert "correct-horse-battery-staple" not in repr(request)
72
+ ```
73
+
74
+ The conversion above is deliberately attached to `from_json()`. Ordinary
75
+ Python construction is strict:
76
+
77
+ ```python
78
+ UserCreate(
79
+ user_id="12345678-1234-5678-1234-567812345678", # ValidationError
80
+ display_name="Ada Lovelace",
81
+ credentials=Credentials(token="correct-horse-battery-staple"),
82
+ )
83
+ ```
84
+
85
+ A UUID field accepts a Python `UUID` on the trusted path. JSON has no UUID
86
+ value, so the JSON boundary owns its documented string representation. That
87
+ separation is the core of Talea's mental model: conversion is explicit, and
88
+ already-valid Python values do not pass through a general parsing pipeline.
89
+
90
+ ## Why Talea exists
91
+
92
+ Python applications often need more than a typed record. At an API, event,
93
+ configuration, or third-party boundary they need to answer all of these
94
+ questions consistently:
95
+
96
+ - Which Python values are valid without conversion?
97
+ - Which external representations are accepted from Mapping and JSON input?
98
+ - Where does hostile input receive finite work and error budgets?
99
+ - What locations and stable codes does invalid nested data produce?
100
+ - Which names and representations appear in serialized output?
101
+ - Can a framework project the same contract as Draft 2020-12 JSON Schema or
102
+ an OpenAPI 3.1 Schema Object?
103
+ - Can tooling inspect the contract without reconstructing annotations?
104
+
105
+ Talea answers them from one canonical schema graph, while retaining separate
106
+ execution paths for operations that have different trust and performance
107
+ requirements.
108
+
109
+ “2026+” describes that starting point. Talea began with Python 3.14+, PEP 695
110
+ generics, deferred annotations, recursive type graphs, current typing behavior,
111
+ and modern JSON Schema as architectural assumptions. It did not need to carry
112
+ compatibility requirements for historical Python releases or retrofit those
113
+ assumptions into an older public contract. This is a design circumstance—not a
114
+ claim that mature libraries are obsolete, a prediction of ecosystem
115
+ replacement, or a guarantee of future superiority.
116
+
117
+ ## The boundary model
118
+
119
+ | Operation | Use it when | What it does |
120
+ | --- | --- | --- |
121
+ | `User(...)` | application code already has Python values | strict, keyword-only construction |
122
+ | `Contract(T).validate(value)` | an arbitrary root is already Python-shaped | strict validation without conversion |
123
+ | `User.from_mapping(data)` | an external Python Mapping represents an object | structural conversion with finite traversal policy |
124
+ | `Contract(T).from_python(data)` | an external root may be a list, union, alias, or TypedDict | structural conversion with finite traversal policy |
125
+ | `from_json(data)` | text or bytes crosses a serialized boundary | strict decoding, JSON representations, conversion, and resource policy |
126
+ | `to_dict()` / `to_python()` | an application needs detached Python output | schema-aware projection and current-state validation |
127
+ | `to_json()` | an application needs JSON text | schema-aware projection followed by encoding |
128
+ | `json_schema()` / `openapi_schema()` | tooling needs a standards description | projection from the same canonical graph |
129
+
130
+ JSON and Mapping boundaries are not aliases for the constructor. For example,
131
+ `Decimal`, UUID, temporal values, paths, IP values, bytes, enums, nested Specs,
132
+ and tagged unions each retain an explicit Python contract and an explicit JSON
133
+ representation.
134
+
135
+ ## What is implemented
136
+
137
+ Talea currently provides:
138
+
139
+ - strict, keyword-only, immutable, slotted `Spec` records;
140
+ - defaults and factories, inheritance, safe narrowing, custom transforms,
141
+ field checks, whole-Spec checks, and serializers;
142
+ - built-in numeric, length, and pattern constraints carried by `Annotated`;
143
+ - aliases, titles, descriptions, examples, deprecation, read/write metadata,
144
+ and sensitive-value handling;
145
+ - `Contract` for primitives, containers, unions, `TypedDict`, type aliases,
146
+ recursive graphs, tagged unions, and concrete generic specializations;
147
+ - first-class Mapping and JSON input with structured nested errors;
148
+ - finite transport-size, depth, traversal-node, and error-aggregation policy;
149
+ - presence-aware partial Specs, `derive_spec()`, and `apply_patch()` for PATCH
150
+ semantics where absent is not confused with `None`;
151
+ - canonical discriminator-based union dispatch and OpenAPI discriminator maps;
152
+ - Python and JSON serialization with explicit per-call codec boundaries;
153
+ - JSON Schema Draft 2020-12 and OpenAPI 3.1-compatible Schema Objects;
154
+ - public immutable introspection and runtime `create_spec()` declarations;
155
+ - compile-once specialized pure-Python execution with permanent benchmark
156
+ canaries for distinct workloads.
157
+
158
+ The documentation proves these features with executable account API, REST
159
+ PATCH, event, financial, recursive AST, arbitrary Contract, error/security,
160
+ schema/OpenAPI, dynamic declaration, and immutable replacement examples.
161
+
162
+ ## A complete service boundary
163
+
164
+ A framework-neutral request flow looks like this:
165
+
166
+ ```text
167
+ raw request bytes
168
+ -> ResourcePolicy
169
+ -> UserCreate.from_json(...)
170
+ -> ValidationError or ResourceLimitError
171
+ -> application/domain operation
172
+ -> UserResponse
173
+ -> to_json()
174
+ ```
175
+
176
+ Talea does not choose routes, dependency injection, HTTP status codes, ORM
177
+ behavior, or response envelopes. A FastAPI, Lilya, Django, Starlette, Flask, or
178
+ other adapter can own those framework concerns while calling the explicit
179
+ Talea boundary operations. The manual includes the entire executable flow,
180
+ plus presence-aware PATCH and generated input/output OpenAPI fragments.
181
+
182
+ ## Installation
183
+
184
+ Talea requires Python 3.14+. Install the published release from PyPI:
185
+
186
+ ```console
187
+ python -m pip install talea
188
+ ```
189
+
190
+ To install from a source checkout instead:
191
+
192
+ ```console
193
+ git clone https://github.com/tarsil/talea.git
194
+ cd talea
195
+ python -m pip install .
196
+ ```
197
+
198
+ The core package declares `dependencies = []`. Development, test, benchmark,
199
+ build, and documentation tools remain separate development dependencies.
200
+
201
+ ## Not a competition
202
+
203
+ Talea is not trying to replace Pydantic, msgspec, dataclasses, attrs, or
204
+ manually written validation.
205
+
206
+ Pydantic has broad adoption, extensive integrations, a mature ecosystem, and
207
+ coercive/parsing workflows many applications actively want. msgspec has an
208
+ extremely fast native implementation, mature serialization, and a different
209
+ set of representation and performance tradeoffs. Dataclasses and attrs remain
210
+ excellent for internal records that do not need a full external-boundary
211
+ contract. Direct Python is often clearest for three checks in one specialized
212
+ function.
213
+
214
+ Talea is another design point: strict, dependency-light, Python-native,
215
+ compile-once, explicit-boundary, introspectable, standards-aware, and
216
+ security-conscious. Selection is a requirements decision, not a winner/loser
217
+ ranking.
218
+
219
+ ## When Talea fits—and when it does not
220
+
221
+ Talea is worth evaluating when a project uses Python 3.14+, wants strict
222
+ ordinary Python construction, needs Mapping or JSON boundaries, values an
223
+ empty required dependency graph, and can benefit from structured errors,
224
+ finite external-input policy, schemas, or framework introspection.
225
+
226
+ It is likely the wrong choice when:
227
+
228
+ - the application depends heavily on Pydantic-specific integrations or wants
229
+ broad coercion by default;
230
+ - Python 3.13 or earlier must remain supported;
231
+ - settings, ORM extraction, or a large plugin ecosystem must come from the
232
+ same package;
233
+ - msgspec already exactly matches a high-throughput native serialization
234
+ workflow;
235
+ - the only requirement is a small internal record, where a dataclass or attrs
236
+ class is simpler;
237
+ - specialized validation is shorter and clearer as manually written Python;
238
+ - adopting a pre-1.0 library with a small ecosystem is unacceptable.
239
+
240
+ ## Documentation
241
+
242
+ - [Documentation home](https://talea.tarsild.io)
243
+ - [Why Talea?](https://talea.tarsild.io/getting-started/why-talea/)
244
+ - [Five-minute quickstart](https://talea.tarsild.io/getting-started/quickstart/)
245
+ - [Progressive tutorial](https://talea.tarsild.io/getting-started/tutorial/)
246
+ - [Production service boundary](https://talea.tarsild.io/getting-started/production-service/)
247
+ - [Concepts and mental model](https://talea.tarsild.io/concepts/)
248
+ - [How-to recipes](https://talea.tarsild.io/guides/recipes/)
249
+ - [Complete API reference](https://talea.tarsild.io/reference/api/)
250
+ - [Security and resource model](https://talea.tarsild.io/resource-security/)
251
+ - [Performance method and evidence](https://talea.tarsild.io/engineering/performance/)
252
+ - [Known limitations](https://talea.tarsild.io/engineering/limitations/)
253
+
254
+ For a local checkout, `task docs_test` executes all `docs_src` examples and
255
+ checks navigation, links, API inventory, and documentation policy. `task build`
256
+ builds the site; `task build_with_checks` verifies release artifacts.
257
+
258
+ ## Maturity and evidence
259
+
260
+ Talea is pre-1.0. Compatibility, deprecation, support, and release governance
261
+ are not yet frozen, and its ecosystem is necessarily much smaller than mature
262
+ alternatives. The project does not call that tradeoff complete or invisible.
263
+
264
+ Repository gates include unit and integration tests, 100% line coverage,
265
+ linting, formatting, static typing, package checks, executable documentation,
266
+ standards-conformance tests, security/adversarial cases, and 18 permanent
267
+ benchmark workloads. Performance comparisons require semantically equivalent
268
+ operations; no claim is based on removing validation from one side.
269
+
270
+ See [Contributing](https://talea.tarsild.io/contributing/) for exact commands,
271
+ [Maturity and support](https://talea.tarsild.io/release-ledger/) for current
272
+ governance, and [Security](https://talea.tarsild.io/engineering/security/) for
273
+ the technical threat model and reporting status.
274
+
275
+ Talea is licensed under the MIT License.