Skip to main content

Python 2/3 兼容的 DataClass 库,支持完整的数据校验功能和自定义错误消息

Project description

Schemas DataClass

Python Version License CI Coverage

一个专为 Python 2/3 兼容设计的 DataClass 库,支持完整的数据校验功能、装饰器语法和自定义错误消息。

🚀 快速开始

安装

pip install schemas-dataclass

基础使用

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,}$'
    )

# 创建用户
user = User(name="Alice", age=25, email="alice@example.com")
print(user.to_dict())  # {'name': 'Alice', 'age': 25, 'email': 'alice@example.com'}

自定义错误消息

@dataclass
class User(object):
    name = StringField(
        min_length=2,
        error_messages={
            'required': '姓名是必填项',
            'min_length': '姓名至少需要 {min_length} 个字符'
        }
    )

try:
    user = User(name="A")  # 太短
except ValidationError as e:
    print(e.message)  # 输出: 姓名至少需要 2 个字符

📚 文档索引

安装和使用

安装方式

从 PyPI 安装(推荐)

pip install schemas-dataclass

从源码安装

git clone https://github.com/schemas/dataclass.git
cd dataclass
python setup.py install

开发环境安装

git clone https://github.com/schemas/dataclass.git
cd dataclass
pip install -e .
pip install -r requirements-dev.txt

基础使用指南

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)

# 创建和使用
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())   # 转换为字典

核心特性

🔧 字段类型支持

  • StringField: 字符串字段

    • 长度验证 (min_length, max_length)
    • 正则表达式验证 (regex)
    • 枚举验证 (choices)
    • 自定义错误消息支持
  • NumberField: 数字字段(支持int、float、long)

    • 范围验证 (minvalue, maxvalue)
    • 枚举验证 (choices)
    • 自定义错误消息支持
  • ListField: 数组字段

    • 长度验证 (min_length, max_length)
    • 支持嵌套类型验证 (item_type)
    • 支持字符串、数字、dataclass模型嵌套
    • 自定义错误消息支持

🌍 自定义错误消息

  • 多语言支持: 支持中文、英文等多语言错误消息
  • 模板格式化: 支持 {参数名} 格式的参数替换
  • 完整覆盖: 支持所有验证类型的自定义错误消息
  • 向后兼容: 不影响现有代码,可选使用
# 自定义错误消息示例
@dataclass
class User(object):
    name = StringField(
        min_length=3,
        max_length=20,
        error_messages={
            'required': '用户名是必填项',
            'min_length': '用户名至少需要 {min_length} 个字符',
            'max_length': '用户名不能超过 {max_length} 个字符'
        }
    )

🎯 装饰器语法

@dataclass
class User(object):
    name = StringField(min_length=1, max_length=100)
    age = NumberField(minvalue=0, maxvalue=150)

🔍 自定义验证装饰器

@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")

🔧 自定义get方法

@dataclass
class BlogPost(object):
    title = StringField()
    status = StringField(default='draft')
    
    def get_title(self):
        """自定义获取标题的方法"""
        title = self.__dict__.get('title', '')
        status = self.__dict__.get('status', 'draft')
        return "[{0}] {1}".format(status.upper(), title)

完整示例

📁 示例文件

项目提供了丰富的示例文件,位于 examples/ 目录:

🚀 运行示例

# 基础使用示例
python examples/basic_usage.py

# 自定义错误消息示例
python examples/custom_error_messages.py

# 高级功能示例
python examples/advanced_features.py

# 实际应用示例
python examples/real_world_examples.py

💡 快速示例

用户管理系统

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': '用户名是必填项',
            'min_length': '用户名至少需要 {min_length} 个字符',
            'regex': '用户名必须以字母开头,只能包含字母、数字和下划线'
        }
    )
    
    email = StringField(
        regex=r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
        error_messages={
            'required': '邮箱地址是必填项',
            'regex': '请输入有效的邮箱地址'
        }
    )
    
    age = NumberField(
        minvalue=13,
        maxvalue=120,
        error_messages={
            'minvalue': '年龄不能小于 {minvalue} 岁',
            'maxvalue': '年龄不能大于 {maxvalue} 岁'
        }
    )
    
    tags = ListField(
        item_type=str,
        required=False,
        max_length=10,
        error_messages={
            'max_length': '标签数量不能超过 {max_length} 个'
        }
    )
    
    @validate("username")
    def validate_username_not_reserved(self, username):
        """检查用户名是否为保留词"""
        reserved = ['admin', 'root', 'system']
        if username.lower() in reserved:
            raise ValidationError(f"用户名 '{username}' 是系统保留词")

# 使用示例
user = User(
    username="alice_dev",
    email="alice@example.com",
    age=28,
    tags=["developer", "python"]
)

print("用户: {}".format(user.username))
print("邮箱: {}".format(user.email))
print("年龄: {}".format(user.age))
print("标签: {}".format(user.tags))

API 参考

重要变更说明: 从版本 2.0 开始,所有字段默认为可选 (required=False)。如需必填字段,请显式设置 required=True

字段类型

StringField

StringField(
    default=None,           # 默认值
    alias=None,            # 字段别名
    required=False,        # 是否必填 (默认为 False)
    min_length=None,       # 最小长度
    max_length=None,       # 最大长度
    regex=None,            # 正则表达式
    choices=None,          # 枚举选项
    error_messages=None    # 自定义错误消息
)

NumberField

NumberField(
    default=None,           # 默认值
    alias=None,            # 字段别名
    required=False,        # 是否必填 (默认为 False)
    minvalue=None,         # 最小值
    maxvalue=None,         # 最大值
    choices=None,          # 枚举选项
    error_messages=None    # 自定义错误消息
)

ListField

ListField(
    default=None,           # 默认值
    alias=None,            # 字段别名
    required=False,        # 是否必填 (默认为 False)
    min_length=None,       # 最小长度
    max_length=None,       # 最大长度
    item_type=None,        # 列表项类型
    error_messages=None    # 自定义错误消息
)

装饰器

@dataclass

@dataclass
class MyClass(object):
    field1 = StringField()
    field2 = NumberField()

@validate

@dataclass
class MyClass(object):
    field1 = StringField()

    @validate("field1")
    def validate_field1(self, value):
        # 自定义验证逻辑
        if not condition:
            raise ValidationError("Custom validation failed")

错误消息键

通用错误消息键

  • required: 必填字段为空
  • invalid_type: 类型不匹配

StringField 错误消息键

  • min_length: 长度小于最小值
  • max_length: 长度大于最大值
  • regex: 正则表达式匹配失败
  • choices: 值不在枚举选项中

NumberField 错误消息键

  • minvalue: 数值小于最小值
  • maxvalue: 数值大于最大值
  • choices: 值不在枚举选项中

ListField 错误消息键

  • min_length: 列表长度小于最小值
  • max_length: 列表长度大于最大值
  • invalid_list_item: 列表项类型不匹配

测试

运行测试

# 运行所有测试
pytest

# 运行特定测试文件
pytest tests/test_fields.py

# 运行带覆盖率的测试
pytest --cov=schema_dataclass

# 运行特定标记的测试
pytest -m "unit"
pytest -m "integration"
pytest -m "error_messages"

测试结构

tests/
├── conftest.py                    # pytest 配置和 fixtures
├── test_fields.py                 # 字段类型测试
├── test_custom_error_messages.py  # 自定义错误消息测试
├── test_dataclass.py             # dataclass 功能测试
└── test_integration.py           # 集成测试

测试覆盖

  • 25+ 个测试用例,覆盖所有功能点
  • 100% 测试通过率
  • 向后兼容性验证
  • 多语言错误消息测试
  • 复杂场景边界测试

验证特性

字符串验证

  • 长度验证:min_length, max_length
  • 正则表达式验证:regex
  • 枚举验证:choices
  • 自定义错误消息:支持所有验证类型

数字验证

  • 范围验证:minvalue, maxvalue
  • 枚举验证:choices
  • 类型验证:自动支持int、float、long(Python 2)
  • 自定义错误消息:支持所有验证类型

数组验证

  • 长度验证:min_length, max_length
  • 项类型验证:item_type
  • 支持嵌套:字符串、数字、dataclass模型
  • 自定义错误消息:支持列表项类型错误

DataClass字段支持

  • 支持dataclass作为字段类型
  • 自动实例化和验证
  • 重新赋值时重新创建对象
  • 支持嵌套的to_dict()转换

自定义验证

  • 使用@validate("field_name")装饰器
  • 在基础验证之后执行
  • 支持多个自定义验证函数

自定义错误消息特性

  • 多语言支持:完全支持中文、英文等多语言错误消息
  • 模板格式化:支持 {参数名} 格式的参数替换,如 {min_length}, {maxvalue}
  • 完整覆盖:支持所有验证类型的自定义错误消息
  • 向后兼容:不影响现有代码,可选使用
  • 健壮性:格式化失败时优雅降级,返回原始模板
  • 零性能影响:不使用自定义消息时性能与原版本完全相同

支持的错误消息类型

  • 通用: required, invalid_type
  • StringField: min_length, max_length, regex, choices
  • NumberField: minvalue, maxvalue, choices
  • ListField: min_length, max_length, invalid_list_item

兼容性

  • Python 2.7+: 完全支持
  • Python 3.4+: 完全支持
  • PyPy: 支持
  • Jython: 理论支持(未测试)

性能

  • 零依赖: 仅使用 Python 标准库
  • 轻量级: 核心代码不到 1000 行
  • 高性能: 验证速度快,内存占用低
  • 可扩展: 易于添加新的字段类型和验证规则

贡献指南

欢迎贡献代码!请遵循以下步骤:

  1. Fork 项目
  2. 创建功能分支 (git checkout -b feature/amazing-feature)
  3. 添加测试用例
  4. 确保所有测试通过 (pytest)
  5. 更新相关文档
  6. 提交更改 (git commit -m 'Add amazing feature')
  7. 推送到分支 (git push origin feature/amazing-feature)
  8. 创建 Pull Request

开发环境设置

git clone https://github.com/schemas/dataclass.git
cd dataclass
pip install -e .
pip install -r requirements-dev.txt

代码规范

  • 遵循 PEP 8 代码风格
  • 添加适当的文档字符串
  • 为新功能添加测试用例
  • 保持 Python 2/3 兼容性

许可证

本项目采用 GNU General Public License v3.0 许可证。详见 LICENSE 文件。

更新日志

查看 CHANGELOG.md 了解详细的版本更新记录。


注意: 本库完全兼容 Python 2.7 和 Python 3.x,自定义错误消息功能为可选特性,不影响现有代码的使用。

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

schema_dataclass-0.0.1.tar.gz (47.8 kB view details)

Uploaded Source

Built Distribution

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

schema_dataclass-0.0.1-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file schema_dataclass-0.0.1.tar.gz.

File metadata

  • Download URL: schema_dataclass-0.0.1.tar.gz
  • Upload date:
  • Size: 47.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for schema_dataclass-0.0.1.tar.gz
Algorithm Hash digest
SHA256 3415f75686c4e4662927c682fe18bf82cc5a90e200eac427e9af2d8e2ea0c26c
MD5 8c34eeda4d41ce900f861c980cd14fff
BLAKE2b-256 e1e76baf1cdf74435fdad5943244f3e653e6e4a60237871793b09d4902f0e927

See more details on using hashes here.

File details

Details for the file schema_dataclass-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for schema_dataclass-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ea1a55f1239c77c285036d6da48e173e852895f0efd5244c5c0f9ad3ecb44432
MD5 ee8c17617daa11346588b061ab56b1e3
BLAKE2b-256 9e87271b20d5098baa4f290c3cbc27ff004dcf39fc4a05795712819efb4f7a65

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