Validatedata – lightweight inline data validation for Python
Inline validation without schema classes, but Pydantic already owns this space.

Pydantic alternative for scripts and CLIs, but overlaps with existing inline validation approaches.
Python developers building scripts, lightweight APIs, and CLI tools who want validation without Pydantic boilerplate.
Pydantic · Cerberus · Voluptuous
Three ways to use it 1. Standalone function — validate a dict pythonfrom validatedata import validate_data
result = validate_data( data={'username': 'alice', 'email': '[email protected]', 'age': 25}, rule={'keys': { 'username': 'str|min:3|max:32', 'email': 'email', 'age': 'int|min:18', }} )
result.ok # True result.errors # []
# on failure: # [['username: invalid string length'], ['age: number out of range']] 2. Decorator — validate function arguments pythonfrom validatedata import validate
@validate(['str|min:3|max:32', 'email', 'str|min:8|msg:password too weak']) def signup(username, email, password): return 'Account Created'
signup('alice', '[email protected]', 'Secure@123') # works signup('alice', 'not-an-email', 'weak') # returns {'errors': [...]} 3. Type annotation decorator pythonfrom validatedata import validate_types
@validate_types def create_user(username: str, age: int): return f'{username} ({age})'
create_user('alice', 30) # works create_user('alice', 'thirty') # raises ValidationError All three support async functions transparently.
Shorthand rule syntax Rules can be written as compact pipe-separated strings. Transforms, validators, and custom messages chain in one line: python'str|min:3|max:32' 'email|nullable' 'int|between:0,100' 'str|strip|lower|in:admin,editor,viewer|msg:invalid role' 'str|min:8|re:(?=.[A-Z])(?=.\d).+|msg:password must contain uppercase and a number' 'color|format:hex|nullable' 'url|starts_with:https|msg:must be a secure URL' Named transforms (strip, lstrip, rstrip, lower, upper, title) run before validation. msg: is always last.
Transforms and mutation Apply transforms before validation and get cleaned values back: pythonresult = validate_data( data=[' Alice ', ' bob '], rule=['str|strip|lower', 'str|strip|lower'], mutate=True )
result.ok # True result.data # ['alice', 'bob']
Conditional validation Validate a field only when a sibling field meets a condition: pythonrule = {'keys': { 'role': {'type': 'str'}, 'permissions': { 'type': 'str', 'depends_on': {'field': 'role', 'value': 'admin'}, 'options': ('full', 'read', 'none') } }}
# permissions only validated when role == 'admin'
Custom error messages Any rule key accepts a {rule}-message override: python{ 'type': 'int', 'range': (18, 'any'), 'range-message': 'you must be at least 18', 'type-message': 'age must be a number', } Shorthand: 'int|min:18|msg:you must be at least 18'
Supported types Basic: str, int, float, bool, email, url, ip, uuid, slug, semver, phone, color, date, even, odd, prime Extended: dict, list, tuple, set, regex, object Phone validation supports E.164 built-in. National, international, and region-specific formats available via pip install phonenumbers. Color validation supports hex, rgb, hsl, and named CSS colors.
Supported rules range, length, contains, excludes, options, expression, startswith, endswith, unique, nullable, strict, transform, depends_on, fields, items
Return value validate_data returns a SimpleNamespace:
result.ok — True if all validation passed result.errors — list of error groups, one per field result.data — transformed values, only present when mutate=True
MIT licensed. Python 3.7+. No required dependencies. Repo: https://github.com/Edward-K1/validatedata PyPI: https://pypi.org/project/validatedata/ Feedback, bug reports, and use-case stories welcome.
Inline validation without schema classes, but Pydantic already owns this space.
Rule-based function dispatching beats functools.singledispatch for complex validation logic.
Pydantic alternative for when defining full model classes feels like overkill.
Implicit parallelism from function signatures beats manual asyncio.gather spaghetti.
Map any Python function to 1000 VMs in <1 second, automatic env sync.
NumPy's full API in JavaScript with zero dependencies, 93% coverage validated against Python.