Skip to main content

Provides a lightweight `attr()` descriptor factory that adds runtime validation to dataclass fields.

Project description

validating

validating is a lightweight runtime validation library focused on making dataclass fields and function arguments safer and easier to validate.

It exposes three main entry points:

  • attr(...): declare validated fields (type checks, bounds, allow/deny lists, custom validators)
  • @dataclass(...): a compatible enhancement of dataclasses.dataclass with automatic validation integration
  • @validate: a decorator that validates function arguments using type annotations

Installation

pip install validating

Quick Start

from validating import attr, dataclass

@dataclass
class UserConfig:
    age: int = attr(lb=0)
    role: str = attr(allowlist=["admin", "user"])

cfg = UserConfig(age=18, role="admin")
cfg.age = 20          # ✅
cfg.role = "user"    # ✅
# cfg.age = -1        # ❌ ValueError
# cfg.role = "guest" # ❌ ValueError

Core API

attr(...)

Declares a descriptor-backed field that validates values on initialization and assignment.

Common parameters:

  • default: default value
  • default_factory: lazy default factory (mutually exclusive with default)
  • allowlist: whitelist of allowed values
  • denylist: blacklist of forbidden values
  • lb / ub: inclusive lower / upper bounds
  • slb / sub: exclusive lower / upper bounds
  • validator: custom validator function with signature Callable[[Any], bool]
  • init / repr / hash / compare / kw_only: forwarded dataclass field behavior controls

Error semantics:

  • Misconfiguration at class-definition time (for example, default type mismatch) raises ValidatorError
  • Invalid runtime values raise TypeError or ValueError

@dataclass(...)

validating.dataclass is a compatible enhanced wrapper around dataclasses.dataclass.

Enhancements:

  1. Automatic default promotion: x: int = 1 is promoted to attr(default=1)
  2. Method argument validation: when validate_methods=True (by default False), all public methods are wrapped with validate (including @staticmethod and @classmethod)
from validating import dataclass

@dataclass(validate_methods=True)
class Service:
    retries: int = 3

    def run(self, timeout: int) -> int:
        return timeout + self.retries

svc = Service()
svc.run(1)       # ✅
# svc.run("1")   # ❌ TypeError

@validate

Enables call-time argument validation based on type annotations.

from typing import Literal
from validating import validate

@validate
def configure(mode: Literal["dev", "prod"], workers: int):
    return mode, workers

configure("dev", 4)    # ✅
# configure("test", 4)  # ❌ TypeError

@validate also handles assert statements in validated functions:

  • assert <expr>, "custom message" keeps the original AssertionError with your message.
  • assert <expr> (without message) is converted to a ValueError when <expr> is a direct assertion on function arguments, with a message like expected <expr>, got <value> instead.
  • Assertions that are not direct checks on function arguments are left as regular AssertionError.
from validating import validate

@validate
def check_score(score: int) -> int:
    assert score >= 60
    return score

check_score(80)   # ✅
# check_score(59) # ❌ ValueError: expected score >= 60, got 59 instead

More Examples

1) default_factory

from validating import attr, dataclass

@dataclass
class Cache:
    items: list[int] = attr(default_factory=list)

2) Complex type hints

from typing import Literal
from validating import attr, dataclass

@dataclass
class AppConfig:
    mode: Literal["dev", "prod"] = attr()
    token: int | str = attr()
    mapping: dict[str, int] = attr()

3) Custom validator

from validating import attr, dataclass

@dataclass
class EvenNumber:
    value: int = attr(validator=lambda x: x % 2 == 0)

Notes

  • Dataclasses with slots=True are currently not supported.
  • This project focuses on runtime validation and does not replace static type checking.

See Also

License

This project falls under the BSD 3-Clause License.

History

v0.0.5

  • Added typing.dataclass_transform metadata to validating.dataclass (with attr and dataclasses.Field specifiers) to improve IDE/static-analysis support, including better Pylance hints.

v0.0.4

  • Updated error messages when validating typed dicts.

v0.0.3

  • Improved support for PEP 585 generics with quoted builtin annotations (for example list["int"]) to ensure consistent runtime type validation.

v0.0.2

  • Fixed runtime checking for TypedDict and several special typing hints to avoid invalid isinstance paths.
  • Added runtime validation support for typing.Unpack-style annotations.
  • Improved forward-reference handling under TYPE_CHECKING imports, including deferred annotation resolution and safer fallback behavior when references are temporarily unresolved.
  • Refined the @validate argument-checking path for better robustness and consistency across annotated call patterns.

v0.0.1

  • Initial release.

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

validating-0.0.5.tar.gz (22.2 kB view details)

Uploaded Source

Built Distribution

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

validating-0.0.5-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

Details for the file validating-0.0.5.tar.gz.

File metadata

  • Download URL: validating-0.0.5.tar.gz
  • Upload date:
  • Size: 22.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for validating-0.0.5.tar.gz
Algorithm Hash digest
SHA256 ef464baf48e5fdcab5473eaf2b4639ddefce2f608d0a9e87a2d62cd7442b70ea
MD5 e4bb1ae70fe9c64fba7cf6799e958455
BLAKE2b-256 56dadfcebd2df7ce4814352274b383d2b0628c1d2787004c7ce649a2ec8d10d4

See more details on using hashes here.

File details

Details for the file validating-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: validating-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 17.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for validating-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 00fa2d851d1f0ef5f363173769d05772b43f9ddac3c8eec79c0cd9e153e18e05
MD5 70580feaf63e877c4a80b2574c79fc14
BLAKE2b-256 3c21d08bcab03ee553b91f657235d74fd0dc1da0485cc103979f0ea39313ce8a

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