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.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.3.tar.gz (21.7 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.3-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: validating-0.0.3.tar.gz
  • Upload date:
  • Size: 21.7 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.3.tar.gz
Algorithm Hash digest
SHA256 db73d8d3c956a41ad2133991a133c80315f33cffc11d79b51505a170b4dda506
MD5 5d5c957d4f55f33cc9add3f81d5a436a
BLAKE2b-256 a346d5bae01b80048314842c923871e3855b0131fbc227e353dd52c4671faefb

See more details on using hashes here.

File details

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

File metadata

  • Download URL: validating-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 17.6 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 ccb58c7037e7d6c49583b61f8de4dd6b378f1c2523db4b73180c8e5c02f05dfc
MD5 9a26425ee7b27b57311980f2ca96fb18
BLAKE2b-256 1823e510ee79f2c0e880fd958d7007ecd36eca0d25683e213a9a299463dbcade

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