Skip to main content

Runtime type validation for Python

Project description

TypeWall

Runtime type validation for Python with a small, schema-first API.

from typewall import w

User = w.object({
    "name": w.str(),
    "age": w.int().optional(),
    "tags": w.list(w.str()).default([]),
})

user = User.parse({"name": "Ada"})
assert user == {"name": "Ada", "tags": []}

Use safe_parse() when validation failures should be returned instead of raised:

result = User.safe_parse({"name": 42})

if not result.ok:
    print(result.to_dict())

TypeWall supports strict string, integer, float, boolean, object, and list schemas; required, optional, and defaulted fields; constraints, composition, transforms, type-derived schemas, and structured validation errors. It does not coerce values. Schema export, environment parsing, CLI tools, and framework integrations are intentionally deferred to later phases.

MVP Public API

  • Builders: w, tw, and SchemaBuilder
  • Schemas: Schema, StringSchema, IntegerSchema, FloatSchema, BooleanSchema, ObjectSchema, and ListSchema
  • Parsing: Schema.parse() and Schema.safe_parse()
  • Field configuration: Schema.optional() and Schema.default()
  • Results and errors: ParseResult, ValidationIssue, and ValidationError

MVP object schemas reject unknown keys, omit absent optional fields, defensively copy defaults, and aggregate independently reachable issues in deterministic order. The error dictionary uses $ for root failures and dot-delimited paths for nested fields and list indexes.

Constraints

Account = w.object({
    "name": w.str().min(2).max(80),
    "email": w.str().email(),
    "homepage": w.str().url().optional(),
    "age": w.int().min(18),
})

String constraints include length, email, URL, UUID, and regex validation. Integer and float schemas support inclusive ranges plus positive and negative checks. Constraint declarations are available as immutable schema.rules; each rule exposes stable metadata for the later schema-export phase.

Composition

Identifier = w.union((w.int(), w.str().uuid()))
Coordinates = w.tuple((w.float(), w.float()))
Labels = w.dict(w.str(), w.int())
Role = w.enum(["admin", "user"])

TypeWall also provides literals, intersections, nullable schemas, w.any(), and w.none(). Union failures retain per-branch issues, and transformed dictionary keys cannot silently overwrite an existing parsed key.

Custom Processing

NormalizedName = (
    w.str()
    .refine(str.strip, "Name must not be empty", code="empty_name")
    .transform(str.strip)
)

Refinements run after built-in validation. Transforms run only after every validation and refinement succeeds. These callbacks are runtime behavior and cannot be exported accurately as JSON Schema without explicit metadata in a future integration phase.

Python Types

from dataclasses import dataclass
from typing import TypedDict

from typewall import schema_from_type


class UserInput(TypedDict):
    name: str
    age: int


@dataclass
class User:
    name: str
    age: int = 18


InputSchema = schema_from_type(UserInput)
UserSchema = schema_from_type(User)

schema_from_type() supports primitives, Any, None, lists, dictionaries, fixed tuples, unions, optionals, literals, TypedDict declarations, dataclasses, and supported recursive declarations. Unsupported annotations fail during schema construction with the annotation path.

Typing Contract

MyPy and Pyright verify the same conservative output-type contract. Primitive, collection, literal, tuple, union, nullable, transformed, and dataclass-derived schemas preserve their parsed output types. Manually declared w.object() schemas currently return dict[str, Any]; exact dictionary-shape inference is deferred.

Export Metadata

Constraint rules expose serializable metadata. Composition schemas expose their declared literals, enum values, item schemas, members, or wrapped schema. Custom refinements and transforms contain arbitrary Python callbacks and must be treated as non-representable by schema exporters unless a later API supplies explicit metadata.

Development

TypeWall uses uv and supports CPython 3.9 through 3.14.

UV_CACHE_DIR=.uv-cache uv sync --python 3.14
UV_CACHE_DIR=.uv-cache uv run pytest
UV_CACHE_DIR=.uv-cache uv run ruff check .
UV_CACHE_DIR=.uv-cache uv run mypy
UV_CACHE_DIR=.uv-cache uv run pyright
UV_CACHE_DIR=.uv-cache uv run python tests/typing/check_negative.py

Project details


Download files

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

Source Distribution

typewall-0.1.0.tar.gz (13.0 kB view details)

Uploaded Source

Built Distribution

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

typewall-0.1.0-py3-none-any.whl (16.8 kB view details)

Uploaded Python 3

File details

Details for the file typewall-0.1.0.tar.gz.

File metadata

  • Download URL: typewall-0.1.0.tar.gz
  • Upload date:
  • Size: 13.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for typewall-0.1.0.tar.gz
Algorithm Hash digest
SHA256 15d571e90456ba2ef948be977ef57f1f09cf2cc2d06f6864e11a33ac719b4055
MD5 5235bfc3c3c832d292c73f419c67c0e4
BLAKE2b-256 15cb2ff7a7bfb1736b2445533ec973a0bc36e850528af9776c4510d06d59c572

See more details on using hashes here.

Provenance

The following attestation bundles were made for typewall-0.1.0.tar.gz:

Publisher: pypi-release.yml on MyGenX/TypeWall

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

File details

Details for the file typewall-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: typewall-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for typewall-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0c07ec2712b8b2f75ab8633eddd5480e30e7c1d4cc027dbf27bd38b5bb8c367f
MD5 2e0fada14fb93110f9d0d97ab6e2a1a1
BLAKE2b-256 c6150d16e1a7381cec6316356a5a7f3b16600bc11ddca402481de5ae2c29fa1e

See more details on using hashes here.

Provenance

The following attestation bundles were made for typewall-0.1.0-py3-none-any.whl:

Publisher: pypi-release.yml on MyGenX/TypeWall

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page