2
Show HN: Validatedata 0.3.0 – lightweight inline data validation for Python
Validatedata is a Python library for validating dicts, lists, function arguments, and API payloads inline. No model classes, no boilerplate — just rules alongside the data. pip install validatedata
Three ways to use it 1. Standalone function — validate a dict pythonfrom validatedata import validate_data
result = validate_data( data={'username': 'alice', 'email': 'alice@example.com', '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', 'alice@example.com', '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.