Skip to main content

Decorator for validating function arguments and result.

Project description

valdec

PyPI Build Status Coverage Status Total alerts Language grade: Python PyPI - Python Version

Decorator for validating arguments and/or result of functions and methods of a class against annotations.

Can be used in synchronous or asynchronous version.

Validation is supported using pydantic.BaseModel and validated_dc.ValidatedDC.

You can easily add support for any other validator. To do this, you need to write your own validator-function and specify it in the settings for decorator (how to do this - see the examples below).

Note: if the result of the function has no annotation, the result is expected to be None.

Installation

pip install valdec

Quick example

Default

Based on the validator pydantic.BaseModel:

pip install pydantic
from typing import List, Optional

from pydantic import BaseModel, StrictInt, StrictStr
from valdec.decorators import validate
# from valdec.decorators import async_validate  # Use for async functions


@validate  # all arguments with annotations and return
def func(i: StrictInt, s: StrictStr) -> StrictInt:
    return i

assert func(1, "s") == 1


@validate("i", exclude=True)  # exclude "i" (only "s" and return)
def func(i: StrictInt, s: StrictStr) -> StrictInt:
    return int(i)

assert func("1", "s") == 1


# For example, an Api got a json-string and decoded it:
data_for_group = [
    {"name": "Peter", "profile": {"age": 22, "city": "Samara"}},
    {"name": "Elena", "profile": {"age": 20, "city": "Kazan"}},
]

class Profile(BaseModel):
    age: StrictInt
    city: StrictStr

class Student(BaseModel):
    name: StrictStr
    profile: Profile

@validate("s", "group")  # only "s" and "group"
def func(i: StrictInt, s: StrictStr, group: Optional[List[Student]] = None):

    assert i == "i not int"  # because "i" is not validated
    assert isinstance(s, str)
    for student in group:
        # `student` is now an instance of `Student`
        # (This conversion can be disabled!)
        assert isinstance(student, Student)
        assert isinstance(student.name, str)
        assert isinstance(student.profile.age, int)

    return group

result = func("i not int", "string",  data_for_group)
# The result can be any, because it is not validated.., now this is a list:
assert isinstance(result, list)

validated_dc_validator

It is possible to enable validation with validated_dc.ValidatedDC. To do this, change the reference to the validator-function in the decorator settings:

pip install validated-dc
from dataclasses import dataclass
from typing import List, Optional

from valdec.data_classes import Settings
from valdec.decorators import validate as _validate
from valdec.validator_validated_dc import validator 
from validated_dc import ValidatedDC

custom_settings = Settings(
    validator=validator,     # function for validation
    is_replace_args=True,    # default
    is_replace_result=True,  # default
    extra={}                 # default
)
def validate(*args, **kwargs):  # define new decorator
    kwargs["settings"] = custom_settings
    return _validate(*args, **kwargs)


# The new decorator can now be used:

@validate  # all arguments with annotations and return
def func(i: int, s: str) -> int:
    return i

assert func(1, "s") == 1


@validate("s")  # only "s"
def func(i: int, s: str) -> int:
    return i

assert func("not int", "s") == "not int"


@validate("s", "return")  # only "s" and return
def func(i: int, s: str) -> int:
    return int(i)

assert func("1", "s") == 1


@validate("i", exclude=True)  # exclude "i" (only "s" and return)
def func(i: int, s: str) -> int:
    return int(i)

assert func("1", "s") == 1


data_for_group = [
    {"name": "Peter", "profile": {"age": 22, "city": "Samara"}},
    {"name": "Elena", "profile": {"age": 20, "city": "Kazan"}},
]

@dataclass
class Profile(ValidatedDC):
    age: int
    city: str

@dataclass
class Student(ValidatedDC):
    name: str
    profile: Profile

@validate("s", "group")  # only "s" and "group"
def func(i: int, s: str, group: Optional[List[Student]] = None):

    assert i == "i not int"  # because "i" is not validated
    assert isinstance(s, str)
    for student in group:
        # `student` is now an instance of `Student`
        # (This behavior can be changed by is_replace_args=False in the
        # Settings instance)
        assert isinstance(student, Student)
        assert isinstance(student.name, str)
        assert isinstance(student.profile.age, int)

    return group

result = func("i not int", "string",  data_for_group)
# The result can be any, because it is not validated.., now this is a list:
assert isinstance(result, list)

Errors

ValidationArgumentsError is raised on an arguments validation error, and a ValidationReturnError on a result validation error:

from typing import Optional

from pydantic import StrictInt, StrictStr
from valdec.decorators import validate
from valdec.errors import ValidationArgumentsError, ValidationReturnError


class Foo:

    @validate  # all arguments with annotations and return
    def bar_1(self, i: StrictInt, s: Optional[StrictStr] = None):
        pass

    @validate("return")  # only "return"
    def bar_2(self, i: StrictInt, s: Optional[StrictStr] = None):
        return i


foo = Foo()

foo.bar_1(1, "2")  # ok

try:
    foo.bar_1(1, 2)
except ValidationArgumentsError as error:
    print(type(error), error, "\n")


foo.bar_2(None, 1)  # ok

try:
    foo.bar_2(1, 2)
except ValidationReturnError as error:
    print(type(error), error)

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

valdec-1.1.0.tar.gz (10.9 kB view details)

Uploaded Source

Built Distribution

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

valdec-1.1.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: valdec-1.1.0.tar.gz
  • Upload date:
  • Size: 10.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.6.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.55.1 CPython/3.8.5

File hashes

Hashes for valdec-1.1.0.tar.gz
Algorithm Hash digest
SHA256 bc8570e62a148ff81e5061916b7cc22af64d1524dad8c78873edc092e4a114a1
MD5 7ed8ba6b8df2931606bd97bf4b368bf2
BLAKE2b-256 6776ee4414475d712c781d76fad49accece76fd77dc57385502b6864f3f68e6a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: valdec-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.6.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.55.1 CPython/3.8.5

File hashes

Hashes for valdec-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d252ec0d0a841a26d897915cd06d98f962acdba2acb6d8ccc0b9b90ab008f566
MD5 5416917c56a8f7ae046632b6339566ae
BLAKE2b-256 4f4bffc694d25a2079bc2f7765f5b94a95f72c772ae5d9e1ae025cfc8205bfc0

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