Skip to main content

Lightweight, zero-dependency Python library for validating dictionaries with optional coercion and custom rules

Project description

Pyvalidly

Pyvalidly is a lightweight, zero-dependency Python library for validating dictionaries with simple rules, custom functions, and optional coercion.

Inspired by Pydantic's power but built for simplicity, speed, and flexibility — especially useful when you want to avoid creating full-blown classes.


Features

  • Simple schema-based dictionary validation
  • Type validation – int, str, float, list, dict, custom classes.
  • Coercion – Automatically convert types when possible.
  • Default values – Fill missing fields with defaults.
  • Conditional validation – Skip validation based on another field.
  • Custom validation functions – Pass any callable returning True/False.
  • Helper functions – is_email, is_url, min_value, max_value, min_length, max_length.
  • Custom error messages – Per-field validation errors.
  • Old-style and new-style schemas – Flexible for migration.

Installation

pip install pyvalidly

Basic Usage

Old-style Schema

from pyvalidly import validate, is_email

schema = {
    "name": str, #(str,),
    "age": (int, lambda x: x > 18),
    "email": (str, is_email)
}

data = {
    "name": "John",
    "age": 25,
    "email": "john@example.com"
}

validated = validate(data, schema)
print(validated)
# {'name': 'John', 'age': 25, 'email': 'john@example.com'}


New-style Schema

from pyvalidly import validate, is_email, min_value

schema = {
    "name": {"type": str, "required": True},
    "age": {"type": int, "coerce": True, "rules": [min_value(18)]},
    "email": {"type": str, "rules": [is_email]}
}

data = {
    "name": "John",
    "age": "42",
    "email": "john@example.com"
}

validated = validate(data,schema)
print(validated)
# {'name': 'John', 'age': 42, 'email': 'john@example.com'}

Advanced Features

1. Type Coercion

from pyvalidly import validate, is_email, min_value

schema = {
    "age": {"type": int, "coerce": True}
}
data = {"age": "30"}

print(validate(data,schema))
# {'age': 30}

2. Default Values

from pyvalidly import validate, is_email, min_value

schema = {
    "name": {"type": str, "default": "Anonymous"}
}
data = {}

print(validate(data,schema))
# {'name': 'Anonymous'}

3. Conditional Validation

from pyvalidly import validate, is_email, min_value

schema = {
    "is_member": {"type": bool, "required": True},
    "membership_id": {
        "type": str,
        "required": True,
        "condition": lambda data: data.get("is_member") is True
    }
}

data = {"is_member": False}
print(validate(data, schema))
# {'is_member': False}

4. Custom Error Messages

from pyvalidly import validate, is_email, min_value
schema = {
    "age": {
        "type": int,
        "rules": [lambda x: x >= 18],
        "error": "Must be at least 18 years old"
    }
}
data = {"age": 10}

from pyvalidly.exceptions import ValidationError
try:
    print(validate(data, schema))
except ValidationError as e:
    print(e)
# Must be at least 18 years old

5. Built-in Helpers

from pyvalidly import is_email, is_url, min_value, max_value, min_length, max_length

print(is_email("test@example.com")) # True
print(is_url("http://example.com")) # True
print(min_value(10)(15)) # True
print(max_length(5)("hello")) # True

Schema Styles

  • Old-style tuple rules : Each field maps to a tuple of rules: (type, func, func, ...)

  • New-style dict rules : { "type": str, "required": True, "default": "X", "rules": [func], "coerce": True, "condition": func }

Project Structure

pyvalidly/
├── core.py
├── exceptions.py
├── validators.py
├── __init__.py
└── tests/
    └── test_core.py

License

MIT License

Contribute

Pull requests, suggestions, and stars are welcome! If this helped you, consider supporting the project.

Contact

Made with love by Deepak singh — https://github.com/dark00infinity

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

pyvalidly-1.0.1.tar.gz (10.4 kB view details)

Uploaded Source

Built Distribution

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

pyvalidly-1.0.1-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file pyvalidly-1.0.1.tar.gz.

File metadata

  • Download URL: pyvalidly-1.0.1.tar.gz
  • Upload date:
  • Size: 10.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for pyvalidly-1.0.1.tar.gz
Algorithm Hash digest
SHA256 c8e4e5c5e6e771cbfb5be8d8d5ddf8b8dc7e1dd644ea8b906c7f326f7e00d565
MD5 60cdd1d434fc1539636819f1f0c96df9
BLAKE2b-256 307c4fcc2d5a8ff82c41c128e4a4b8987d840dc9c828608c17f1a00fe7bae869

See more details on using hashes here.

File details

Details for the file pyvalidly-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: pyvalidly-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 9.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for pyvalidly-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7baa9b6285bd8e9510e368ef2d7f9eae406b7e0718beb77a9b531a7fd494012a
MD5 4ddbfaf6e90913433c66c949ec271150
BLAKE2b-256 88147f9399453c1f4f7d1842fbbc6b10a836ed06ffa1b01b82f336608c1f1800

See more details on using hashes here.

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