Skip to main content

pytypehint

PyPI

pytypehint compiles standard Python type hints into strict, inspectable schemas.

Your code remains ordinary Python:

  • No custom models, decorators, mutation, registration, or runtime hooks.
  • Your dataclasses remain untouched and work without pytypehint.
  • The library only observes them from the outside and compiles a separate schema.

The dataclass is the single source of truth:

  • types come from type hints;
  • constraints and presentation come from Annotated;
  • defaults are validated and rematerialized fresh;
  • plain input is validated and converted into dataclass instances.

Wrappers inspect the same schema to render controls, coerce external input, generate interfaces, or execute functions. The core never imposes those policies.

Standard Python in. Raw, strict structure out.

Stdlib only. Python 3.11+. py.typed included.

pip install pytypehint
from dataclasses import dataclass, field
from typing import Annotated
from pytypehint import Label, Max, Min, signature_of, struct_of

@dataclass(frozen=True)
class Page:
    number: Annotated[int, Min(1)] = 1
    size: Annotated[int, Min(1), Max(100), Label("Page size")] = 20

@dataclass
class Search:
    query: str
    page: Page = Page()
    tags: list[str] = field(default_factory=list)

value = struct_of(Search).build({"query": "python", "page": {"size": 50}})
# Search(query='python', page=Page(number=1, size=50), tags=[])

try:
    struct_of(Search).build({"query": "python", "page": {"size": 500}})
except ValueError as error:
    assert str(error) == "page: size: too large: 500, maximum 100"

def search(query: str, page: Page = Page()): ...
kwargs = signature_of(search).build({"query": "python"})
search(**kwargs)  # execution belongs to the caller

Guarantees

  • Exact types: type(value) is T; the core never coerces.
  • Data enters as dictionaries and lists; dataclass instances leave through build.
  • A union routes by the exact runtime type of the value. Where two options share that type — list[str] | list[int], A | B — the caller names one; the core never guesses from the contents, from the option order, or by trying them.
  • Defaults are certified at compilation and rematerialized per missing key. Immutable scalar values and enum members may be reused; lists and dataclass instances are reconstructed. A default_factory runs during certification and again whenever its missing value is served.
  • Invalid atom combinations and contradictions the core can determine exactly fail while compiling the schema. The core does not attempt a general satisfiability proof across unrelated constraints.
  • Errors retain the complete field and list-index path, as the message text and as data: SchemaTypeError and SchemaValueError carry path and leaf, and subclass TypeError and ValueError.
  • Notation atoms are stored and cross-checked but never affect validation; presentation belongs to the wrapper.
  • Struct, Field and Signature compare by identity; compile once and share.
  • build validates supplied input values once and then constructs directly. Missing defaults are materialized and validated at their own depth.
  • resolve validates the supplied tree and fills defaults for missing fields at the level being resolved. A supplied nested dataclass dictionary remains a dictionary and is not recursively expanded with that dataclass's defaults; build fills those defaults while constructing the nested instance.
  • Signature.build returns constructed keyword arguments and never invokes the function.

Vocabulary

Hint Shape Input
int Int exact int
float Float exact float
str Str exact str
bool Bool exact bool
date Date exact datetime.date
time Time exact naive datetime.time
Enum subclass EnumShape exact member type
None NoneShape None
list[X] List list; nesting and union items supported
dataclass Struct dictionary; build constructs it
A | B tuple of shapes exact scalar type or routed dataclass dictionary
list[str] | list[int] tuple of shapes {"$type": "list[str]", "$value": [...]}
Literal[...] Int or Str with Choices homogeneous int or str literals

Python allows list[str | int] and list[str] | list[int], and they mean different things. The core keeps both, and asks for a discriminator only where the value cannot supply one:

mixed: list[str | int]          # {"mixed": ["a", 1, "b", 2]}
either: list[str] | list[int]   # {"either": {"$type": "list[str]", "$value": ["a", "b"]}}

Every element of mixed routes by its own exact type. either chooses one option for the whole list, and both options arrive as a list, so the caller names the one it meant. See build.md.

Public API

Everything public is exported from pytypehint:

  • struct_of, signature_of;
  • Struct, Field, Signature;
  • errors: SchemaTypeError, SchemaValueError;
  • Shape, Int, Float, Str, Bool, Date, Time, List, NoneShape, EnumShape;
  • limits: Min, Max, Choices, MultipleOf, Pattern, IsPathFile;
  • notation: Label, Description, Placeholder, Step, Slider, IsPassword, Rows, Extra, OptionalToggle;
  • MISSING.

Extra(key, value) takes a key containing a namespace separator ("package.name"; a dot is required) and any string value, including an empty string. A shape merges every Extra on its hint by key; the rightmost/outermost value wins for a repeated key. Internally the pairs are sorted and immutable. The extras property returns a fresh dict[str, str] on every access, so callers may modify that snapshot without changing the shape. The core stores these entries but never interprets them.

Start with the design principles, then read build, resolve, defaults, vocabulary, atoms, restrictions, and comparison.

Download files

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

Source Distribution

pytypehint-0.0.6.tar.gz (127.2 kB view details)

Uploaded Source

Built Distribution

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

pytypehint-0.0.6-py3-none-any.whl (24.6 kB view details)

Uploaded Python 3

File details

Details for the file pytypehint-0.0.6.tar.gz.

File metadata

  • Download URL: pytypehint-0.0.6.tar.gz
  • Upload date:
  • Size: 127.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pytypehint-0.0.6.tar.gz
Algorithm Hash digest
SHA256 4d3dbf10c883822a678e469c30c33b60ddce4debae8d8482cd7ad0857673127b
MD5 34434245f26dfc6b74097a073c8a3675
BLAKE2b-256 741edcb44db6adebea189f69a5c83cb7709dd803fef95da3b2d2d28f92e1ffb0

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytypehint-0.0.6.tar.gz:

Publisher: publish.yml on offerrall/pytypehint

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytypehint-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: pytypehint-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 24.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pytypehint-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 1fe6c5be16ae2401c2d7546bba887d78932c5d1910f4605ded61fccd97792587
MD5 5a5569693ca6f690de8428ca0df794bc
BLAKE2b-256 6ad8d85c1e4bc31281fb1dcce443c959a940c2a3ab0854f0fcd5f2efe71bccc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytypehint-0.0.6-py3-none-any.whl:

Publisher: publish.yml on offerrall/pytypehint

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.0.0

2 files

0.0.7

2 files

This release

0.0.6 This release

2 files

0.0.3

2 files

0.0.1

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