Skip to main content

Talea

Talea

Data contracts, built for modern Python

Test Suite Package version Supported Python versions


Documentation: https://talea.tarsild.io 📚

Source Code: https://github.com/tarsil/talea

The official supported version is always the latest released.


Talea is a 2026+ Python data-contract library for applications that want strict Python semantics, explicit external boundaries, immutable records, and standards-aware schemas without a required runtime dependency graph.

It is built for Python 3.14 and newer. An annotation is resolved once into one canonical contract, then Talea compiles specialized pure-Python operations for construction, external Mapping input, JSON input, Python output, JSON output, and schema projection.

from typing import Annotated
from uuid import UUID

from talea import Alias, MinLength, Sensitive, Spec


class Credentials(Spec):
    token: Annotated[str, Sensitive(), MinLength(16)]


class UserCreate(Spec):
    user_id: Annotated[UUID, Alias("id")]
    display_name: Annotated[str, Alias("displayName"), MinLength(1)]
    credentials: Credentials


request = UserCreate.from_json(
    """{
      "id": "12345678-1234-5678-1234-567812345678",
      "displayName": "Ada Lovelace",
      "credentials": {"token": "correct-horse-battery-staple"}
    }"""
)

assert request.user_id == UUID("12345678-1234-5678-1234-567812345678")
assert request.display_name == "Ada Lovelace"
assert "correct-horse-battery-staple" not in repr(request)

The conversion above is deliberately attached to from_json(). Ordinary Python construction is strict:

UserCreate(
    user_id="12345678-1234-5678-1234-567812345678",  # ValidationError
    display_name="Ada Lovelace",
    credentials=Credentials(token="correct-horse-battery-staple"),
)

A UUID field accepts a Python UUID on the trusted path. JSON has no UUID value, so the JSON boundary owns its documented string representation. That separation is the core of Talea's mental model: conversion is explicit, and already-valid Python values do not pass through a general parsing pipeline.

Why Talea exists

Python applications often need more than a typed record. At an API, event, configuration, or third-party boundary they need to answer all of these questions consistently:

  • Which Python values are valid without conversion?
  • Which external representations are accepted from Mapping and JSON input?
  • Where does hostile input receive finite work and error budgets?
  • What locations and stable codes does invalid nested data produce?
  • Which names and representations appear in serialized output?
  • Can a framework project the same contract as Draft 2020-12 JSON Schema or an OpenAPI 3.1 Schema Object?
  • Can tooling inspect the contract without reconstructing annotations?

Talea answers them from one canonical schema graph, while retaining separate execution paths for operations that have different trust and performance requirements.

“2026+” describes that starting point. Talea began with Python 3.14+, PEP 695 generics, deferred annotations, recursive type graphs, current typing behavior, and modern JSON Schema as architectural assumptions. It did not need to carry compatibility requirements for historical Python releases or retrofit those assumptions into an older public contract. This is a design circumstance—not a claim that mature libraries are obsolete, a prediction of ecosystem replacement, or a guarantee of future superiority.

The boundary model

Operation Use it when What it does
User(...) application code already has Python values strict, keyword-only construction
Contract(T).validate(value) an arbitrary root is already Python-shaped strict validation without conversion
User.from_mapping(data) an external Python Mapping represents an object structural conversion with finite traversal policy
Contract(T).from_python(data) an external root may be a list, union, alias, or TypedDict structural conversion with finite traversal policy
from_json(data) text or bytes crosses a serialized boundary strict decoding, JSON representations, conversion, and resource policy
to_dict() / to_python() an application needs detached Python output schema-aware projection and current-state validation
to_json() an application needs JSON text schema-aware projection followed by encoding
json_schema() / openapi_schema() tooling needs a standards description projection from the same canonical graph

JSON and Mapping boundaries are not aliases for the constructor. For example, Decimal, UUID, temporal values, paths, IP values, bytes, enums, nested Specs, and tagged unions each retain an explicit Python contract and an explicit JSON representation.

What is implemented

Talea currently provides:

  • strict, keyword-only, immutable, slotted Spec records;
  • defaults and factories, inheritance, safe narrowing, custom transforms, field checks, whole-Spec checks, and serializers;
  • built-in numeric, length, and pattern constraints carried by Annotated;
  • aliases, titles, descriptions, examples, deprecation, read/write metadata, and sensitive-value handling;
  • Contract for primitives, containers, unions, TypedDict, type aliases, stdlib dataclasses, recursive graphs, tagged unions, and concrete generic specializations;
  • first-class Mapping and JSON input with structured nested errors;
  • finite transport-size, depth, traversal-node, and error-aggregation policy;
  • presence-aware partial Specs, derive_spec(), and apply_patch() for PATCH semantics where absent is not confused with None;
  • explicit input/output Spec views derived from ReadOnly and WriteOnly;
  • canonical discriminator-based union dispatch and OpenAPI discriminator maps;
  • Python and JSON serialization with explicit per-call codec boundaries and finite nested include/exclude selection;
  • JSON Schema Draft 2020-12 and OpenAPI 3.1-compatible Schema Objects;
  • public immutable introspection and runtime create_spec() declarations;
  • compile-once specialized pure-Python execution with permanent benchmark canaries for distinct workloads.

The documentation proves these features with executable account API, REST PATCH, event, financial, recursive AST, arbitrary Contract, error/security, schema/OpenAPI, dynamic declaration, and immutable replacement examples.

A complete service boundary

A framework-neutral request flow looks like this:

raw request bytes
    -> ResourcePolicy
    -> UserCreate.from_json(...)
    -> ValidationError or ResourceLimitError
    -> application/domain operation
    -> UserResponse
    -> to_json()

Talea does not choose routes, dependency injection, HTTP status codes, ORM behavior, or response envelopes. A FastAPI, Lilya, Django, Starlette, Flask, or other adapter can own those framework concerns while calling the explicit Talea boundary operations. The manual includes the entire executable flow, plus presence-aware PATCH and generated input/output OpenAPI fragments.

Installation

Talea requires Python 3.14+. Install the published release from PyPI:

python -m pip install talea

To install from a source checkout instead:

git clone https://github.com/tarsil/talea.git
cd talea
python -m pip install .

The core package declares dependencies = []. Development, test, benchmark, build, and documentation tools remain separate development dependencies.

Not a competition

Talea is not trying to replace Pydantic, msgspec, dataclasses, attrs, or manually written validation.

Pydantic has broad adoption, extensive integrations, a mature ecosystem, and coercive/parsing workflows many applications actively want. msgspec has an extremely fast native implementation, mature serialization, and a different set of representation and performance tradeoffs. Dataclasses and attrs remain excellent for internal records that do not need a full external-boundary contract. Direct Python is often clearest for three checks in one specialized function.

Talea is another design point: strict, dependency-light, Python-native, compile-once, explicit-boundary, introspectable, standards-aware, and security-conscious. Selection is a requirements decision, not a winner/loser ranking.

When Talea fits—and when it does not

Talea is worth evaluating when a project uses Python 3.14+, wants strict ordinary Python construction, needs Mapping or JSON boundaries, values an empty required dependency graph, and can benefit from structured errors, finite external-input policy, schemas, or framework introspection.

It is likely the wrong choice when:

  • the application depends heavily on Pydantic-specific integrations or wants broad coercion by default;
  • Python 3.13 or earlier must remain supported;
  • settings, ORM extraction, or a large plugin ecosystem must come from the same package;
  • msgspec already exactly matches a high-throughput native serialization workflow;
  • the only requirement is a small internal record, where a dataclass or attrs class is simpler;
  • specialized validation is shorter and clearer as manually written Python;
  • adopting a 0.x library with an evolving API and small ecosystem is unacceptable.

Documentation

For a local checkout, task docs_test executes all docs_src examples and checks navigation, links, API inventory, and documentation policy. task build builds the site; task build_with_checks verifies release artifacts.

Maturity and evidence

Talea deliberately remains in the 0.x release series. Compatibility, deprecation, support, and release governance are not yet frozen, and its ecosystem is necessarily much smaller than mature alternatives. This is an ongoing product stage, not a signal that a 1.0 freeze is imminent.

Repository gates include unit and integration tests, 100% line coverage, linting, formatting, static typing, package checks, executable documentation, standards-conformance tests, security/adversarial cases, and 19 permanent benchmark workloads. Performance comparisons require semantically equivalent operations; no claim is based on removing validation from one side.

See Contributing for exact commands, Maturity and support for current governance, and Security for the technical threat model and reporting status.

Talea is licensed under the MIT License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

talea-0.2.0.tar.gz (117.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

talea-0.2.0-py3-none-any.whl (151.4 kB view details)

Uploaded Python 3

File details

Details for the file talea-0.2.0.tar.gz.

File metadata

  • Download URL: talea-0.2.0.tar.gz
  • Upload date:
  • Size: 117.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.18.0 {"ci":true,"cpu":"x86_64","distro":{"id":"noble","libc":{"lib":"glibc","version":"2.39"},"name":"Ubuntu","version":"24.04"},"implementation":{"name":"CPython","version":"3.14.7"},"installer":{"name":"hatch","version":"1.18.0"},"openssl_version":"OpenSSL 3.0.13 30 Jan 2024","python":"3.14.7","system":{"name":"Linux","release":"6.17.0-1022-azure"}} HTTPX2/2.12.0

File hashes

Hashes for talea-0.2.0.tar.gz
Algorithm Hash digest
SHA256 74b074c5e1bebf86f400aa391e6034b4a23ed01d4a591e4f1cf1b75137726c60
MD5 d7e7cd9fc0e20ec0e77e625e1efa06f4
BLAKE2b-256 d29df3b66dd6ba62a75fcfe64bde52d1fe2260646f646d9e530a32ba88d4cb9d

See more details on using hashes here.

File details

Details for the file talea-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: talea-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 151.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.18.0 {"ci":true,"cpu":"x86_64","distro":{"id":"noble","libc":{"lib":"glibc","version":"2.39"},"name":"Ubuntu","version":"24.04"},"implementation":{"name":"CPython","version":"3.14.7"},"installer":{"name":"hatch","version":"1.18.0"},"openssl_version":"OpenSSL 3.0.13 30 Jan 2024","python":"3.14.7","system":{"name":"Linux","release":"6.17.0-1022-azure"}} HTTPX2/2.12.0

File hashes

Hashes for talea-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4b9d735967528c7cf3f6ff45d1577b5eb8ed6fa0fdc670c21e7d39d498b4b5be
MD5 ce6bd7b2c03cb488e15d2831e0db54c7
BLAKE2b-256 b690252900eca1b24b353ee4b375320791ea42b41915c7609c3b2b54542d0159

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.0

2 files

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page