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

Ecosystem

pytypehint is the policy-free schema core. Separate wrappers consume the same compiled structures for specific environments:

  • pytypehintweb compiles schemas into a strict, expanded JSON plan and provides a framework-free browser runtime for rendering forms and transporting their values back to Python.
  • FuncToWeb exposes typed Python functions through generated web interfaces while leaving invocation, presentation and application policy outside the core.

These packages build on pytypehint; they are not required to define, compile, validate or construct models with the core library.

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.
  • IsPathFile marks a str that names an existing file, and validates its extension, existence, regular-file status and size. The value stays exactly str; pathlib.Path is used only inside the validation, to inspect the file. The guarantee refers to the moment of validation. Defaults and Choices are certified under the same contract when the schema compiles.
  • 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; IsPathFile(extensions=(), min_size=None, max_size=None) — sizes in bytes;
  • notation: Label, Description, Placeholder, Step, Slider, IsPassword, Rows, Extra, OptionalToggle;
  • MISSING.

A file input is a str, not a new type:

FilePath = Annotated[
    str,
    IsPathFile(
        extensions=(".pdf",),
        max_size=10 * 1024 * 1024,
    ),
]

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.7.tar.gz (135.8 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.7-py3-none-any.whl (25.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pytypehint-0.0.7.tar.gz
  • Upload date:
  • Size: 135.8 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.7.tar.gz
Algorithm Hash digest
SHA256 94651c6fbf601d22d3f6d6869683aaaddef2fe6b950056c9b5a78538c930b44b
MD5 272a143aeab788884ad38127e2b44967
BLAKE2b-256 e4fc5aba904a5fd0dd2f757fb964e9cf61e2a8e3674b8db0923fe7641025dfd1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytypehint-0.0.7.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.7-py3-none-any.whl.

File metadata

  • Download URL: pytypehint-0.0.7-py3-none-any.whl
  • Upload date:
  • Size: 25.5 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.7-py3-none-any.whl
Algorithm Hash digest
SHA256 05b4145d24b180533a7af3ce4bfdac7d97054f41a9ce0718c2f3388a3b8cb202
MD5 84ca857cc5acec0d24ad43efcf5b218f
BLAKE2b-256 a7a4ca0b2505bddc4ac43c1fd1f36b06d2aa1fa6ba643fd922575e604302c20b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytypehint-0.0.7-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

This release

0.0.7 This release

2 files

0.0.6

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