Decorators¶
Validatedata provides two decorators for validating function arguments at call
time: @validate for explicit rules and @validate_types for annotation-
based validation.
@validate¶
Wraps a function and runs validation against its arguments before the body
executes. The rule argument follows the same format as validate_data().
Basic usage¶
from validatedata import validate
@validate(['str|min:3', 'email'])
def create_user(username, email):
return f'created {username}'
create_user('al', 'alice@example.com')
# returns {'errors': [['invalid string length'], []]}
create_user('alice', 'alice@example.com')
# returns 'created alice'
On failure the decorator returns {'errors': result.errors} by default
instead of calling the function.
Dict rules¶
Pass a dict rule to validate named arguments:
signup_rules = {'keys': {
'username': 'str|min:3|max:32',
'email': 'email',
'password': 'str|min:8|re:(?=.*[A-Z])(?=.*\d).+',
}}
@validate(signup_rules, raise_exceptions=True)
def signup(username, email, password):
return 'Account Created'
signup('alice_99', 'alice@example.com', 'Secure@123') # works
signup('alice_99', 'not-an-email', 'weak') # raises ValidationError
raise_exceptions¶
Set raise_exceptions=True to raise ValidationError instead of
returning the error dict:
from validatedata import validate, ValidationError
@validate(['email'], raise_exceptions=True)
def send_email(address):
...
try:
send_email('not-an-email')
except ValidationError as e:
print(e)
mutate¶
Set mutate=True to apply transforms before calling the function. The
function receives the transformed values:
@validate(['str|strip|lower'], mutate=True)
def find_user(username):
# username arrives already stripped and lowercased
return db.get(username)
find_user(' Alice ') # finds 'alice' in the database
Class methods¶
For regular instance methods, no extra configuration is needed — the decorator
detects self automatically:
class User:
@validate(['str|min:3', 'email'], raise_exceptions=True)
def signup(self, username, email):
return 'Account Created'
For @classmethod, pass is_class=True:
class User:
@classmethod
@validate(rule=['str', 'str'], is_class=True)
def format_name(cls, firstname, lastname):
return f'{firstname} {lastname}'
Async functions¶
The decorator works identically with async functions:
@validate(signup_rules, raise_exceptions=True)
async def signup(username, email, password):
await db.save(username, email, password)
return 'Account Created'
# call as normal — validation runs before the coroutine body
await signup('alice', 'alice@example.com', 'Secure@123')
@validate_types¶
Validates function arguments against their Python type annotations. No rule argument is needed — the decorator reads the annotations automatically.
Basic usage¶
from validatedata import validate_types
@validate_types
def add(a: int, b: int) -> int:
return a + b
add(1, 2) # 3
add(1, 'two') # raises ValidationError
The decorator can be used with or without brackets:
@validate_types # no brackets
def create_user(username: str, age: int):
...
@validate_types() # empty brackets — identical
def create_user(username: str, age: int):
...
@validate_types(raise_exceptions=False) # with options — brackets required
def create_user(username: str, age: int):
...
Note
raise_exceptions defaults to True for @validate_types, unlike
@validate and validate_data where it defaults to False.
Return annotations are ignored. Only parameter annotations are validated.
Async support¶
Works identically with async functions:
@validate_types
async def fetch_user(user_id: int) -> dict:
return await db.get(user_id)
Class methods¶
The self parameter is ignored automatically for instance methods. For
@classmethod, pass is_class=True:
class Calculator:
@validate_types(is_class=True)
@classmethod
def multiply(cls, a: int, b: int) -> int:
return a * b
Parameters (both decorators)¶
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
bool |
|
Raise |
|
bool |
|
Set |
|
bool |
|
Apply transforms before calling the function. Transformed values are passed as arguments |
|
bool |
|
Log background errors |
|
bool |
|
Return errors grouped by field. Set |
Return values¶
When validation passes, the original function is called and its return value is returned normally.
When validation fails and raise_exceptions=False (the default for
@validate), the decorator returns:
{'errors': result.errors}
When raise_exceptions=True, a ValidationError is raised instead.