Python 2/3 兼容的 DataClass 库,支持完整的数据校验功能和自定义错误消息
Project description
Schemas DataClass
A lightweight, Python 2/3 compatible data validation library that brings powerful schema validation to Python classes with a clean decorator-based API. Schemas DataClass combines the simplicity of Python dataclasses with robust validation capabilities, making it ideal for data processing, API validation, and configuration management.
🚀 Why Choose Schemas DataClass?
- Seamless Python 2/3 Compatibility: Works flawlessly across Python 2.7+ and 3.4+
- Type-Safe Data Validation: Comprehensive validation for strings, numbers, lists, and nested objects
- Clean, Pythonic API: Use standard class syntax with decorator-based validation
- Customizable Error Messages: Internationalization-ready with template formatting
- Zero Dependencies: Pure Python implementation using only standard libraries
- Efficient Performance: Lightweight design with minimal overhead
- Recursive Validation Protection: Safely handles nested and circular references
📦 Installation
From PyPI (Recommended)
pip install schemas-dataclass
From Source
git clone https://github.com/b40yd/schema_dataclass.git
cd dataclass
python setup.py install
For Development
git clone https://github.com/b40yd/schema_dataclass.git
cd dataclass
pip install -e .
pip install -r requirements-dev.txt
🚀 Quick Start
Basic Usage
from schema_dataclass import StringField, NumberField, dataclass, ValidationError
@dataclass
class User(object):
name = StringField(min_length=2, max_length=50)
age = NumberField(minvalue=0, maxvalue=120)
email = StringField(
regex=r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
)
# Create a user
user = User(name="Alice", age=25, email="alice@example.com")
print(user.to_dict()) # {'name': 'Alice', 'age': 25, 'email': 'alice@example.com'}
Custom Error Messages
@dataclass
class User(object):
name = StringField(
min_length=2,
error_messages={
'required': 'Name is required',
'min_length': 'Name must be at least {min_length} characters long'
}
)
try:
user = User(name="A") # Too short
except ValidationError as e:
print(e.message) # Output: Name must be at least 2 characters long
📚 Documentation Index
- Installation and Usage - Getting started guide
- Core Features - Key capabilities and design principles
- Complete Examples - Practical usage scenarios
- API Reference - Detailed API documentation
- Validation Features - Comprehensive validation capabilities
- Testing - How to run tests
- Compatibility - Supported Python versions
- Performance - Efficiency characteristics
- Contributing - How to contribute to the project
- License - Licensing information
- Changelog - Version history and updates
Installation and Usage
Basic Usage Guide
from schema_dataclass import StringField, NumberField, ListField, dataclass
@dataclass
class User(object):
name = StringField(min_length=2, max_length=50)
age = NumberField(minvalue=0, maxvalue=120)
email = StringField(
regex=r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
)
tags = ListField(item_type=str, required=False)
# Create and use
user = User(
name="Alice",
age=25,
email="alice@example.com",
tags=["developer", "python"]
)
print(user.name) # Alice
print(user['age']) # 25
print(user.get('email')) # alice@example.com
print(user.to_dict()) # Convert to dictionary
Core Features
🔧 Field Types Support
-
StringField: String validation
- Length constraints (
min_length,max_length) - Regular expression validation (
regex) - Enumeration validation (
choices) - Custom error messages with template formatting
- Length constraints (
-
NumberField: Numeric validation (int, float, long)
- Range validation (
minvalue,maxvalue) - Enumeration validation (
choices) - Type validation with automatic coercion
- Custom error messages with template formatting
- Range validation (
-
ListField: List validation
- Length constraints (
min_length,max_length) - Item type validation (
item_type) - Supports nested types including strings, numbers, and dataclass models
- Custom error messages with template formatting
- Length constraints (
🌍 Custom Error Messages
- Multi-language Ready: Supports internationalization with locale-aware messages
- Template Formatting: Use
{parameter}style formatting for dynamic messages - Complete Coverage: Customize error messages for all validation types
- Backward Compatible: Optional feature that doesn't affect existing code
# Custom error messages example
@dataclass
class User(object):
name = StringField(
min_length=3,
max_length=20,
error_messages={
'required': 'Username is required',
'min_length': 'Username must be at least {min_length} characters long',
'max_length': 'Username cannot exceed {max_length} characters'
}
)
🎯 Decorator Syntax
@dataclass
class User(object):
name = StringField(min_length=1, max_length=100)
age = NumberField(minvalue=0, maxvalue=150)
🔍 Custom Validation Decorator
@dataclass
class Product(object):
name = StringField()
price = NumberField()
@validate("name")
def validate_name_custom(self, name):
if not name.isalnum():
raise ValidationError("Name must be alphanumeric")
@validate("price")
def validate_price_custom(self, price):
if price <= 0:
raise ValidationError("Price must be positive")
🔧 Custom Get Methods
@dataclass
class BlogPost(object):
title = StringField()
status = StringField(default='draft')
def get_title(self):
"""Custom method to get formatted title"""
title = self.__dict__.get('title', '')
status = self.__dict__.get('status', 'draft')
return "[{0}] {1}".format(status.upper(), title)
🌐 Nested DataClass Support
@dataclass
class Address(object):
street = StringField()
city = StringField()
zip_code = StringField()
@dataclass
class User(object):
name = StringField()
address = Address # Class reference (auto-instantiated)
addresses = ListField(item_type=Address) # List of nested objects
Complete Examples
📁 Example Files
The project provides rich examples in the examples/ directory:
- Basic Usage Example - Field types, basic dataclass functionality
- Custom Error Messages Example - Multi-language messages, template formatting
- Advanced Features Example - Custom validation, nested dataclasses, conditional validation
- Real World Examples - User management, e-commerce products, blog systems
🚀 Running Examples
# Basic usage example
python examples/basic_usage.py
# Custom error messages example
python examples/custom_error_messages.py
# Advanced features example
python examples/advanced_features.py
# Real world examples
python examples/real_world_examples.py
💡 Quick Example
User Management System
from schema_dataclass import StringField, NumberField, ListField, dataclass, validate
@dataclass
class User(object):
username = StringField(
min_length=3,
max_length=20,
regex=r'^[a-zA-Z][a-zA-Z0-9_]*$',
error_messages={
'required': 'Username is required',
'min_length': 'Username must be at least {min_length} characters long',
'regex': 'Username must start with a letter and contain only letters, numbers, and underscores'
}
)
email = StringField(
regex=r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
error_messages={
'required': 'Email address is required',
'regex': 'Please enter a valid email address'
}
)
age = NumberField(
minvalue=13,
maxvalue=120,
error_messages={
'minvalue': 'Age cannot be less than {minvalue}',
'maxvalue': 'Age cannot be greater than {maxvalue}'
}
)
tags = ListField(
item_type=str,
required=False,
max_length=10,
error_messages={
'max_length': 'Cannot have more than {max_length} tags'
}
)
@validate("username")
def validate_username_not_reserved(self, username):
"""Check if username is a reserved word"""
reserved = ['admin', 'root', 'system']
if username.lower() in reserved:
raise ValidationError(f"Username '{username}' is a reserved word")
# Usage example
user = User(
username="alice_dev",
email="alice@example.com",
age=28,
tags=["developer", "python"]
)
print("User: {}".format(user.username))
print("Email: {}".format(user.email))
print("Age: {}".format(user.age))
print("Tags: {}".format(user.tags))
API Reference
Important Change Notice: Starting from version 2.0, all fields are optional by default (
required=False). For required fields, explicitly setrequired=True.
Field Types
StringField
StringField(
default=None, # Default value
alias=None, # Field alias
required=False, # Whether the field is required (default: False)
min_length=None, # Minimum length
max_length=None, # Maximum length
regex=None, # Regular expression pattern
choices=None, # Enumeration options
error_messages=None # Custom error messages
)
NumberField
NumberField(
default=None, # Default value
alias=None, # Field alias
required=False, # Whether the field is required (default: False)
minvalue=None, # Minimum value
maxvalue=None, # Maximum value
choices=None, # Enumeration options
error_messages=None # Custom error messages
)
ListField
ListField(
default=None, # Default value
alias=None, # Field alias
required=False, # Whether the field is required (default: False)
min_length=None, # Minimum length
max_length=None, # Maximum length
item_type=None, # Type of list items
error_messages=None # Custom error messages
)
Decorators
@dataclass
@dataclass
class MyClass(object):
field1 = StringField()
field2 = NumberField()
@validate
@dataclass
class MyClass(object):
field1 = StringField()
@validate("field1")
def validate_field1(self, value):
# Custom validation logic
if not condition:
raise ValidationError("Custom validation failed")
Error Message Keys
Common Error Message Keys
required: Required field is emptyinvalid_type: Type mismatch
StringField Error Message Keys
min_length: Length below minimummax_length: Length above maximumregex: Regular expression mismatchchoices: Value not in enumeration options
NumberField Error Message Keys
minvalue: Value below minimummaxvalue: Value above maximumchoices: Value not in enumeration options
ListField Error Message Keys
min_length: List length below minimummax_length: List length above maximuminvalid_list_item: List item type mismatch
Validation Features
String Validation
- Length validation:
min_length,max_length - Regular expression validation:
regex - Enumeration validation:
choices - Custom error messages for all validation types
Number Validation
- Range validation:
minvalue,maxvalue - Enumeration validation:
choices - Type validation: automatic support for int, float, long (Python 2)
- Custom error messages for all validation types
List Validation
- Length validation:
min_length,max_length - Item type validation:
item_type - Supports nesting: strings, numbers, dataclass models
- Custom error messages for list item type errors
DataClass Field Support
- Support dataclass as field types
- Automatic instantiation and validation
- Re-creation of objects on reassignment
- Support nested
to_dict()conversion - Validation on reassignment
Custom Validation
- Use
@validate("field_name")decorator - Executed after basic validation
- Support multiple custom validation functions
Custom Error Messages Features
- Multi-language Support: Full support for Chinese, English, and other languages
- Template Formatting: Support
{parameter}style parameter replacement - Complete Coverage: Support custom error messages for all validation types
- Backward Compatibility: Doesn't affect existing code, optional usage
- Robustness: Graceful degradation when formatting fails, returns original template
- Zero Performance Impact: Same performance as original version when not using custom messages
Supported Error Message Types
- Common:
required,invalid_type - StringField:
min_length,max_length,regex,choices - NumberField:
minvalue,maxvalue,choices - ListField:
min_length,max_length,invalid_list_item
Testing
Running Tests
# Run all tests
pytest
# Run specific test file
pytest tests/test_fields.py
# Run tests with coverage
pytest --cov=schema_dataclass
# Run tests with specific markers
pytest -m "unit"
pytest -m "integration"
pytest -m "error_messages"
Test Structure
tests/
├── conftest.py # pytest configuration and fixtures
├── test_fields.py # Field type tests
├── test_custom_error_messages.py # Custom error messages tests
├── test_dataclass.py # dataclass functionality tests
└── test_integration.py # Integration tests
Test Coverage
- 25+ test cases covering all functionality
- 100% test pass rate
- Backward compatibility verification
- Multi-language error message tests
- Complex scenario boundary testing
Compatibility
- Python 2.7+: Fully supported
- Python 3.4+: Fully supported
- PyPy: Supported
- Jython: Theoretically supported (untested)
Performance
- Zero Dependencies: Uses only Python standard library
- Lightweight: Core code under 1000 lines
- High Performance: Fast validation with low memory usage
- Extensible: Easy to add new field types and validation rules
Contributing
Contributions are welcome! Please follow these steps:
- Fork the project
- Create a feature branch (
git checkout -b feature/amazing-feature) - Add test cases
- Ensure all tests pass (
pytest) - Update relevant documentation
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Create a Pull Request
Development Environment Setup
git clone https://github.com/b40yd/schema_dataclass.git
cd dataclass
pip install -e .
pip install -r requirements-dev.txt
Code Guidelines
- Follow PEP 8 coding style
- Add appropriate docstrings
- Add test cases for new features
- Maintain Python 2/3 compatibility
License
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.
Changelog
Check CHANGELOG.md for detailed version history and updates.
Note: This library is fully compatible with Python 2.7 and Python 3.x. Custom error messages are an optional feature that doesn't affect the usage of existing code.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file schema_dataclass-0.0.3.tar.gz.
File metadata
- Download URL: schema_dataclass-0.0.3.tar.gz
- Upload date:
- Size: 55.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a3098dcfa289200aeb9947bb0355f321a9fbbab71cc7c87c507a26c247488da
|
|
| MD5 |
d6708319094e3f69ce1a8ba536db0786
|
|
| BLAKE2b-256 |
aac5f682bb8841a10db20a38b6768731a85e7caa12b79b6325c8e3b82e14caa2
|
File details
Details for the file schema_dataclass-0.0.3-py3-none-any.whl.
File metadata
- Download URL: schema_dataclass-0.0.3-py3-none-any.whl
- Upload date:
- Size: 26.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad3a47889a6191de611c46b57026faa57061538ee86c232040d4c1aa70269065
|
|
| MD5 |
9aba3f54d660cb36a6f1944d17600ce2
|
|
| BLAKE2b-256 |
57f24e7e8a1f023d2554bb26eefcfc08f0ac7872582d6a0db3999a71f8456efb
|