Skip to main content

Universal Data Validator

A comprehensive data validation library for Python that works across API, database, and form contexts.

Features

  • Rich Validator Types: String, int, float, bool, email, URL, list, dict
  • Schema-Based Validation: Define complex data structures
  • Custom Validators: Add your own validation logic
  • Nested Validation: Validate nested objects and lists
  • Clear Error Messages: Detailed error reporting with field paths
  • Zero Dependencies: No external dependencies required
  • Production Ready: Comprehensive test coverage

Installation

pip install universal-validator

Quick Start

from universal_validator import Schema, validators

schema = Schema({
    'email': validators.email(),
    'age': validators.int(min_value=0, max_value=120),
    'username': validators.string(min_length=3, max_length=20),
    'tags': validators.list(validators.string())
})

result = schema.validate(data)
if not result.valid:
    for error in result.errors:
        print(f"{error.field}: {error.message}")

Usage Examples

String Validation

from universal_validator import validators

# Basic string
validator = validators.string()

# String with length constraints
validator = validators.string(min_length=3, max_length=20)

# String with pattern
validator = validators.string(pattern=r'^\d{3}-\d{4}$')

# String with choices
validator = validators.string(choices=['red', 'green', 'blue'])

# Optional string
validator = validators.string(required=False)

# Nullable string
validator = validators.string(nullable=True)

Integer and Float Validation

# Integer with range
age_validator = validators.int(min_value=0, max_value=120)

# Float with range
price_validator = validators.float(min_value=0.0, max_value=9999.99)

# Optional integer
count_validator = validators.int(required=False)

Boolean Validation

# Boolean
terms_validator = validators.bool()

# Optional boolean
newsletter_validator = validators.bool(required=False)

Email and URL Validation

# Email validation
email_validator = validators.email()

# URL validation
url_validator = validators.url()

List Validation

# Simple list
tags_validator = validators.list()

# List with item validation
numbers_validator = validators.list(validators.int())

# List with length constraints
items_validator = validators.list(
    validators.string(),
    min_length=1,
    max_length=10
)

Dictionary Validation

# Dictionary with schema
address_validator = validators.dict({
    'street': validators.string(),
    'city': validators.string(),
    'zip': validators.string(pattern=r'^\d{5}$')
})

# Nested dictionary
user_validator = validators.dict({
    'name': validators.string(),
    'email': validators.email(),
    'address': validators.dict({
        'street': validators.string(),
        'city': validators.string()
    })
})

Schema Validation

from universal_validator import Schema, validators

# Define schema
user_schema = Schema({
    'username': validators.string(min_length=3, max_length=20),
    'email': validators.email(),
    'age': validators.int(min_value=13, required=False),
    'bio': validators.string(max_length=500, required=False),
    'tags': validators.list(validators.string()),
    'settings': validators.dict({
        'theme': validators.string(choices=['light', 'dark']),
        'notifications': validators.bool()
    })
})

# Validate data
data = {
    'username': 'john_doe',
    'email': 'john@example.com',
    'age': 25,
    'tags': ['python', 'javascript'],
    'settings': {
        'theme': 'dark',
        'notifications': True
    }
}

result = user_schema.validate(data)

if result.valid:
    print("✅ Data is valid!")
else:
    print("❌ Validation errors:")
    for error in result.errors:
        print(f"  {error.field}: {error.message}")

Custom Validators

from universal_validator import validators

def is_even(value):
    """Custom validator to check if number is even."""
    if value % 2 != 0:
        return "Value must be even"
    return None

# Add custom validator
validator = validators.int().custom(is_even)

result = validator.validate(4, 'number')
print(result.valid)  # True

result = validator.validate(3, 'number')
print(result.valid)  # False
print(result.errors[0].message)  # "Value must be even"

Multiple Custom Validators

def is_positive(value):
    return "Must be positive" if value <= 0 else None

def is_even(value):
    return "Must be even" if value % 2 != 0 else None

validator = validators.int().custom(is_positive).custom(is_even)

result = validator.validate(4, 'field')
print(result.valid)  # True

result = validator.validate(-2, 'field')
print(result.valid)  # False

Real-World Examples

User Registration

from universal_validator import Schema, validators

registration_schema = Schema({
    'username': validators.string(min_length=3, max_length=20),
    'email': validators.email(),
    'password': validators.string(min_length=8),
    'confirm_password': validators.string(min_length=8),
    'age': validators.int(min_value=13, required=False),
    'terms_accepted': validators.bool()
})

data = {
    'username': 'john_doe',
    'email': 'john@example.com',
    'password': 'secure_password_123',
    'confirm_password': 'secure_password_123',
    'age': 25,
    'terms_accepted': True
}

result = registration_schema.validate(data)

API Request Validation

api_request_schema = Schema({
    'method': validators.string(choices=['GET', 'POST', 'PUT', 'DELETE']),
    'url': validators.url(),
    'headers': validators.dict(required=False),
    'body': validators.dict(required=False),
    'timeout': validators.float(min_value=0, required=False)
})

request_data = {
    'method': 'POST',
    'url': 'https://api.example.com/users',
    'headers': {'Content-Type': 'application/json'},
    'body': {'name': 'John'},
    'timeout': 30.0
}

result = api_request_schema.validate(request_data)

Configuration Validation

config_schema = Schema({
    'database': validators.dict({
        'host': validators.string(),
        'port': validators.int(min_value=1, max_value=65535),
        'username': validators.string(),
        'password': validators.string(),
        'ssl': validators.bool()
    }),
    'cache': validators.dict({
        'enabled': validators.bool(),
        'ttl': validators.int(min_value=0),
        'max_size': validators.int(min_value=1)
    }),
    'features': validators.list(validators.string())
})

config = {
    'database': {
        'host': 'localhost',
        'port': 5432,
        'username': 'admin',
        'password': 'secret',
        'ssl': True
    },
    'cache': {
        'enabled': True,
        'ttl': 3600,
        'max_size': 1000
    },
    'features': ['feature1', 'feature2']
}

result = config_schema.validate(config)

Error Handling

from universal_validator import Schema, validators, ValidationError

schema = Schema({
    'email': validators.email()
})

# Option 1: Check result
result = schema.validate({'email': 'invalid'})
if not result.valid:
    for error in result.errors:
        print(f"{error.field}: {error.message}")

# Option 2: Raise exception
try:
    schema.validate_or_raise({'email': 'invalid'})
except ValidationError as e:
    print(f"Validation failed: {e}")

API Reference

Validators

  • validators.string(min_length, max_length, pattern, choices, required, nullable) - String validator
  • validators.int(min_value, max_value, required, nullable) - Integer validator
  • validators.float(min_value, max_value, required, nullable) - Float validator
  • validators.bool(required, nullable) - Boolean validator
  • validators.email(required, nullable) - Email validator
  • validators.url(required, nullable) - URL validator
  • validators.list(item_validator, min_length, max_length, required, nullable) - List validator
  • validators.dict(schema, required, nullable) - Dictionary validator

Schema

  • Schema(schema_dict) - Create a schema
  • schema.validate(data) - Validate data and return ValidationResult
  • schema.validate_or_raise(data) - Validate data and raise ValidationError if invalid

ValidationResult

  • result.valid - Boolean indicating if validation passed
  • result.errors - List of ValidationError objects

ValidationError

  • error.field - Field name that failed validation
  • error.message - Error message
  • error.value - Value that failed validation

Testing

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest test_universal_validator.py -v

# Run with coverage
pytest test_universal_validator.py --cov=universal_validator --cov-report=html

Comparison with Other Libraries

Feature universal-validator pydantic marshmallow cerberus
Schema-based
Custom validators
Zero dependencies
Nested validation
Clear errors
Simple API
Type hints

License

MIT License

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Changelog

1.0.0 (2024-01-15)

  • Initial release
  • Support for string, int, float, bool, email, URL, list, dict validators
  • Schema-based validation
  • Custom validators
  • Nested validation
  • Comprehensive test coverage

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

universal_validator-1.0.0.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

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

universal_validator-1.0.0-py3-none-any.whl (7.6 kB view details)

Uploaded Python 3

File details

Details for the file universal_validator-1.0.0.tar.gz.

File metadata

  • Download URL: universal_validator-1.0.0.tar.gz
  • Upload date:
  • Size: 9.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.5

File hashes

Hashes for universal_validator-1.0.0.tar.gz
Algorithm Hash digest
SHA256 78d3872438a4dcf51f9724b70e190ad870fac20e373f8608d3c80deb52e4228c
MD5 1d733e58488f0bf3c33bdfab2ff7a03d
BLAKE2b-256 bc5000f926ad5948e812a8d8f684996da348643969b7de00b0daca17895bcf67

See more details on using hashes here.

File details

Details for the file universal_validator-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for universal_validator-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c0d1939f95f0937232a23f46cbe5e38cd1be31787f792d9f5d2353524530628f
MD5 de18d754743b38e9b9ec2eaa012526a9
BLAKE2b-256 8f64b8e89baa031962a5129cf51bd52f8b599a3828cd7af6f139b11345f0049f

See more details on using hashes here.

Release history Release notifications | RSS feed

2.0.0

2 files

This release

1.0.0 This release

2 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