Skip to main content

Lightweight validation library for (micro)Python

Project description

uzod

A lightweight validation library inspired by zod for (micro)python that provides runtime type checking and validation with a clean, chainable API.

PyPI - Version GitHub Actions Workflow Status PyPI - Downloads

Features

🦾 Ergonomic API - Fluent, chainable interface

🛡️ Type-safe - Comes with complete type stubs for IDE support

🪶 Lightweight - Zero dependencies, single file (~220 lines)

🤸🏻 Flexible - Built-in validators + custom refinements

🧩 Composable - Build complex schemas from simple primitives

Installation

Install from PyPI:

pip install uzod

Or just copy uzod.py into your project - it's standalone!

Quick Start

from uzod import z, ValidationError

# Define a schema
user_schema = z.object({
    "name": z.string(min=2, max=50),
    "email": z.string().refine(lambda s: "@" in s, "invalid email"),
    "age": z.integer(min=0, max=120).optional,
})

# Validate data
try:
    user = user_schema.parse({
        "name": "Alice",
        "email": "alice@example.com",
        "age": 30
    })
    print(user)  # {'name': 'Alice', 'email': 'alice@example.com', 'age': 30}
except ValidationError as error:
    print(f"Validation failed: {error}")

API Reference

String

z.string()                   # Any string
z.string(min=3)              # At least 3 characters
z.string(max=100)            # At most 100 characters
z.string(min=3, max=100)     # Between 3-100 characters

Integer

z.integer()                 # Any integer
z.integer(min=0)            # Non-negative
z.integer(min=1, max=10)    # Between 1-10

Float

z.float()                   # Any float
z.float(min=0.0)            # Non-negative
z.float(min=0.0, max=1.0)   # Between 0.0-1.0

Boolean

z.boolean()                 # true or false

Literal

z.literal("admin", "user")  # Must be "admin" or "user"
z.literal(1, 2, 3)          # Must be 1, 2, or 3

Array

z.array(z.string())                  # Array of strings
z.array(z.integer(), min=1, max=10)  # 1-10 integers
z.array(z.object({...}))             # Array of objects

Object

z.object({
    "name": z.string(),
    "age": z.integer()
})

# Strict mode - reject unknown keys (can also be used with chainable method)
z.object({"name": z.string()}, strict=True)

Union

z.union(z.string(), z.integer())     # String OR integer
z.union(z.literal("yes", "no"), z.boolean())

Modifiers

Optional

# Field can be omitted (returns None)
z.object({
    "name": z.string(),
    "nickname": z.string().optional
})

# parse({"name": "Alice"}) -> {"name": "Alice", "nickname": None}

Nullable

# Field can be None
z.object({
    "name": z.string().nullable
})

# parse({"name": None}) -> {"name": None}

Default

# Provide default value when field is missing or None
z.object({
    "role": z.string().default("user")
})

# parse({}) -> {"role": "user"}

Refine (Custom Validation)

# Add custom validation logic
z.string().refine(lambda s: s.isalnum(), "must be alphanumeric")
z.integer().refine(lambda n: n % 2 == 0, "must be even")

Error Messages

uzod provides helpful error messages:

>>> z.string(min=5).parse("hi")
ValidationError: too short, at least 5 chars

>>> z.integer().parse("123")
ValidationError: expected int, got str

>>> z.object({"name": z.string()}).parse({"name": 123})
ValidationError: name: expected str, got int

>>> z.object({"a": z.string()}, strict=True).parse({"a": "x", "b": "y"})
ValidationError: unexpected keys: b

Testing

Run the test suite with:

python -m unittest discover tests

Contributing

Contributions are welcome! This is a small, focused library - let's keep it that way.

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

uzod-1.1.0.tar.gz (12.1 kB view details)

Uploaded Source

Built Distribution

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

uzod-1.1.0-py3-none-any.whl (10.0 kB view details)

Uploaded Python 3

File details

Details for the file uzod-1.1.0.tar.gz.

File metadata

  • Download URL: uzod-1.1.0.tar.gz
  • Upload date:
  • Size: 12.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for uzod-1.1.0.tar.gz
Algorithm Hash digest
SHA256 1b381762252a21af87904a8d70f8def8214c05f6a62297ed6f16452a4b822400
MD5 a3bcba8269ac90f8ea9409018a73b5f0
BLAKE2b-256 913ff7953dc3fa42c9f58edef404ea9f6113fe0fe90c829bb43d2d3ade79a3df

See more details on using hashes here.

Provenance

The following attestation bundles were made for uzod-1.1.0.tar.gz:

Publisher: publish-to-pypi.yml on markusand/uzod

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

File details

Details for the file uzod-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: uzod-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for uzod-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5e856b187f5d95bdd886b8e01dccf4b58e1bbcb2b5f5f69d3eaa3deda52a41b8
MD5 5399558400473765825bcf0d24f29ef9
BLAKE2b-256 b635d28fd6393f8bf45cbda3289888c82e216cfffb053a36feb369b80714b227

See more details on using hashes here.

Provenance

The following attestation bundles were made for uzod-1.1.0-py3-none-any.whl:

Publisher: publish-to-pypi.yml on markusand/uzod

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