Skip to main content

valguard: A lightweight framework for defining and validating values in data pipelines.

Project description

valguard

Constraint-aware value types for semantic validation in Python pipelines

valguard is a lightweight framework for defining and validating values in data pipelines. It separates values from constraints. This allows a source to publish the constraint against which it will validate each value. An implies function can determine whether values satisfying an upstream constraint are guaranteed to satisfy a downstream constraint.

License PyPI Python Docs


Key Features

  • Declarative value types
  • Validators for clean pipeline integration
  • Type-safe abstractions compatible with Python 3.12+

Usage

Values

A Value stores a particular kind of value. It is immutable. Different methods are provided for accessing the value depending on its type: this provides a concise way to validate type and access the value simultaneously. If x is not an integer then x.as_int will raise an exception.

To avoid raising an exception, use isinstance() to test the type beforehand.

A subclass of NumericValue will have the method .to_float.

>>> from valguard import FloatValue, IntValue, NumericValue, BoolValue
>>> fv = FloatValue(1.0)    # Must use 1.0 and not 1
>>> iv = IntValue(1)
>>> bv = BoolValue(True)
>>> isinstance(bv,NumericValue)
False
>>> isinstance(iv,NumericValue)
True
>>> bv.as_float
Traceback (most recent call last):
    ...
valguard.exceptions.TypeMismatchError: Incompatible accessor
>>> iv.as_float
Traceback (most recent call last):
    ...
valguard.exceptions.TypeMismatchError: Incompatible accessor
>>> iv.to_float
1.0
>>> iv.as_int
1
>>> fv.as_float
1.0
>>> fv.to_float
1.0

Constraints

Constraints can be placed on both type and value.

>>> from valguard import IntValue, BoolValue, IntervalConstraint, NumericConstraint, IntConstraint
>>> iv = IntValue(23)
>>> bv = BoolValue(False)
>>> interval_a = IntervalConstraint(0,100)
>>> interval_b = IntervalConstraint(10,20)
>>> interval_a.validate(iv)
IntValue(23)
>>> interval_b.validate(iv)
Traceback (most recent call last):
    ...
valguard.exceptions.ValidationError: Invalid value: 23.0 lies outside [10.0, 20.0]
>>> interval_a.validate(bv)
Traceback (most recent call last):
    ...
valguard.exceptions.ValidationError: Invalid value: expected a numeric, got BoolValue(False)
>>> IntConstraint().validate(iv)
IntValue(23)
>>> IntConstraint().validate(iv).as_int
23
>>> NumericConstraint().validate(iv).to_float
23.0
>>> NumericConstraint().validate(bv).to_float
Traceback (most recent call last):
    ...
valguard.exceptions.ValidationError: Invalid value: expected a numeric, got BoolValue(False)

The implies function

The implies function determines whether one constraint implies another constraint. Constraint A implies constraint B if every value that satisfies A will also satisfy B.

>>> from valguard import BoundedIntConstraint, NumericConstraint, FloatConstraint, implies
>>> interval_A = BoundedIntConstraint(0,100)
>>> interval_B = BoundedIntConstraint(20,80)
>>> implies(interval_A, interval_B)
False
>>> implies(interval_B, interval_A)
True
>>> implies(interval_A, FloatConstraint)
False
>>> implies(interval_A, NumericConstraint)
True
>>> implies(NumericConstraint, interval_A)
False

Constraints that are parametrised (such as IntervalConstraint and LiteralStrConstraint) can be used in two ways: as an instance with specific parameters, or as a class. When used as a class, implies behaves differently depending on whether the class appears as the first or second argument to implies. As the first argument, implies(class, B) is True if all instances of class would imply B. As the second argument, implies(A, class) is True if at least one instance of class would be implied by A. For non-parametrised classes, there is no difference whether a class or an instance is used.

Constrained Value Dictionary

A ConstrainedValueDict behaves like a dictionary but its values are validated against a constraint at the time of insertion.

It is intentional that no type casting is performed, not even from int to IntValue.

>>> from valguard import IntValue, IntConstraint, ConstrainedValueDict
>>> d = ConstrainedValueDict(IntConstraint())                             
>>> d["one"] = IntValue(1)
>>> d["one"]
IntValue(1)
>>> d["two"] = 2
Traceback (most recent call last):
    ...
valguard.exceptions.ValidationError: Invalid value: expected an integer, got 2

Installation

pip install valguard

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

valguard-1.0.1.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

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

valguard-1.0.1-py3-none-any.whl (14.4 kB view details)

Uploaded Python 3

File details

Details for the file valguard-1.0.1.tar.gz.

File metadata

  • Download URL: valguard-1.0.1.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.13.5 Windows/11

File hashes

Hashes for valguard-1.0.1.tar.gz
Algorithm Hash digest
SHA256 8a35797b99ccbbc28266d9fcd1868e31edc535a18b9f20ca767029f4d76bf975
MD5 f23206d3068323875bfcaf09c4b83dd0
BLAKE2b-256 dc918158c69c592003446a729f6f8b7df5941e882b587c8418f62a371d183659

See more details on using hashes here.

File details

Details for the file valguard-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: valguard-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 14.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.13.5 Windows/11

File hashes

Hashes for valguard-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1406a2017ebc9b8984b56629e6ae278936c58a4eeeaeb640eca88561c07e0fe2
MD5 9c12a39c4130cc8b702f31bd2edf8c7a
BLAKE2b-256 d38e39ab08e72d05d3abafcba87541491001b706c66d9a01ed727ca12270a7e4

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