Skip to main content

Validify

Python library for automated and manual runtime data type validation. It focuses on utilizing type hints and handling subscribed generics (e.g., list[str]). Use it manually with isvalid or add decorators to methods, functions, and classes for automatic validation.

While Python natively supports basic type validation, it does not manage complex types like list[dict[str, tuple[str, str, bool]]]. Validify simplifies this by allowing easy integration of type validation through a single decorator. Add it to your method or class, and let Validify ensure your type hints are enforced at runtime.

Contents

 1 Features
 2 Installation
 3 Supported Data Types
 4 Usage
  4.1 Manual validation
  4.2 Decorator for Functions
  4.3 Decorator for Classes
  4.4 Notes
 5 Developers Guide
  5.1 Contributing
  5.2 Architecture
  5.3 Known Issues
 6 License & Contact

1 Features

  • Uniform way to describe and manipulate both base and generic data types via Descriptor class.
  • Manual validation of data via isvalid function.
  • Function signature inspection and input validation via func.validate decorator.
  • Class-level attribute validation based on type annotations via cls.validate decorator.
  • Class methods signature inspection and input validation via cls.validate decorator.

2 Installation

pip install pyvalidify

3 Supported Data Types

  • Text Type: str
  • Numeric Types: int, float, complex
  • Sequence Types: list, tuple, range
  • Mapping Type: dict
  • Set Types: set, frozenset
  • Boolean Type: bool
  • Binary Types: bytes, bytearray, memoryview
  • None Type: NoneType/None
  • Generics - e.g. list[str]
  • Unions - e.g. str | int
  • Generics with unions (limited support) - e.g. list | tuple[str | bytes, bool]

4 Usage

4.1 Manual validation

from validify import isvalid

simple_var = 2

isvalid(simple_var, int) # true
isvalid(simple_var, str) # false

complicated_var = [
    {
        "name": "John",
        "email": "johnny1975@hotmail.com"
    },
    {
        "name": "Dan",
        "email": None
    }
]

isvalid(complicated_var, list[dict[str, str]]) # false
isvalid(complicated_var, list[dict[str, str | None]]) # true

4.2 Decorator for Functions

from validify import func

@func.validate
def func(a: list[int], b: list[int], *args: str, c: bool, **kwargs: bool) -> None: ...

func([1, 2, 3], [4, 5, 6], "foo", "bar", c=True, d=False) # OK
func((1, 2, 3), (4, 5, 6), "foo", "bar", c=True, d=False) # TypeError

4.3 Decorator for Classes

from dataclasses import dataclass
from validify import cls

@dataclass
@cls.validify
class MyClass:
    name: str
    address: list[str]

MyClass("John", ["SY23 2JS", "3102 Bridge Street"]) # OK
MyClass("John", "SY23 2JS, 3102 Bridge Street") # TypeError

@cls.validify
class MyOtherClass:
    basket: list[tuple[str, int, float]]
    customer_name: str | None

    def __init__(self, **items: tuple[int, float]) -> None: ...

    def add_item(self, name: str, qty: int, price: float) -> None: ...

    @classmethod
    def from_item_list(cls, items: list[tuple[str, int, float]]) -> "MyOtherClass": ...

    @staticmethod
    def calcualte_total(item_prices: list[float]) -> float: ...

    @property
    def customer_name(self) -> str | None: ...

    @customer_name.setter
    def customer_name(self, val) -> None: ...

inst = MyOtherClass(chocolate=(1.5, 4.99)) # TypeError
inst.add_item("beans", "2", "2.59") # TypeError
inst = inst.from_item_list([["carrot", 5, 1.43], ["reduced fat pesto", 1, 2.99]]) # TypeError
total = MyOtherClass.calculate_total([("carrot", 5, 1.43), ("reduced fat pesto", 1, 2.99)]) # TypeError
inst.customer_name = ["Bart", "Simpson"] # TypeError

4.4 Notes

  • func.validate does not work on lambdas and abstract methods (I guess the latter is no surprise).
  • classmethod decorator must precede func.validate

5 Developers Guide

5.1 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository.
  2. Create a new branch for your feature or bugfix.
  3. Commit your changes.
  4. Push the branch to your fork.
  5. Create a pull request.

5.2 Architecture

The library can be described as service based, however, it roughly follows layered, DDD-like pattern. The below names of each layer are mearely contextual - I made them up to remember what is what, don't judge. The rules of interactions of these layers are simple: a layer can only import from beneath itself.

"service" layer #2:

  • decorators.py - two classes cls and func with static methods

"service" layer #1:

  • validator.py - contains two functions: describe_type() - like Python's native type() and is_valid() - like Python's native isinstance()

"model" layer:

  • descriptor.py - definition of the Descriptor class, a framework for working with datatypes.

"core" layer:

  • type_hints.py - describes supported types and defines functions for validating them.

5.3 Known Issues

  • When describing a datatype in terms of combinations or their equivalence (see type_description.TypeDescription.combinations() or type_description.TypeDescription.__hash__()), unions are not being propagated outward within nested datatype. For example, consider a type list[tuple[int | str]]. It represents a list of tuples, where tuple can hold only one element each. Valid values would be [(1,), (1,)], [("1",), ("1",)] or [(1,), ("1",)]. Respectively, they can be represented as types list[tuple[int]], list[tuple[str]] or list[tuple[int] | tuple[str]]. The last expression is equivalent to the initial one - describes a list of mixed items. Unfortunately neither combinations() nor __hash__() method describe the the relationship. The issue is to be fixed.

6 License

Validify is licensed under the MIT License. See the LICENSE file for more information.

Release files for pyvalidify 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyvalidify 1.0.1
File Size Uploaded
pyvalidify-1.0.1.tar.gz 15.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyvalidify 1.0.1
File Interpreter ABI Platform
pyvalidify-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 30.0 kB

Release files / pyvalidify-1.0.1.tar.gz

Download URL pyvalidify-1.0.1.tar.gz
Size 15.3 kB
Tags Source
SHA-256 checksum
How to use checksums
473c21b2335618fe561c1a04ecf9e552163d010eaf6b43bfe2c4cb92b6d9aed4
BLAKE2b-256 checksum
How to use checksums
ac8a8c0de32f0f1779368cefe54cdae51fd9afbbdf9f656486cf729dff31e328
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.8.3 CPython/3.12.1 Linux/6.5.0-1025-azure

Release files / pyvalidify-1.0.1-py3-none-any.whl

Download URL pyvalidify-1.0.1-py3-none-any.whl
Size 14.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b2515af280a156bb9e5f71a4e9d793748b483868de0bd231ad4d58c64196eb81
BLAKE2b-256 checksum
How to use checksums
83f625d7f7a3f5db9cce83a44594e939b6bde8ec9d1ee50ddef86172966518ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.8.3 CPython/3.12.1 Linux/6.5.0-1025-azure

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page