0

我有一个变量声明如下

my_var = typing.List[typing.Tuple[int, int]]

我想写一个验证器如下

schema_validator = "my_var": {
    "type": "list",
    "empty": False,
    "items": [
        {"type": "tuple"},
        {"items": [
            {"type": "int"}, {"type": "int"}
        ]}
    ]
}

在 Cerberus 文档中,它没有为tuples.

如何做到这一点?

4

2 回答 2

1

虽然这不是最干净的解决方案,但它肯定会做你想做的事。

from cerberus import Validator, TypeDefinition

class MyValidator(Validator):
    def __init__(self, *args, **kwargs):
        # Add the tuple type
        tuple_type = TypeDefinition("tuple", (tuple,), ())
        Validator.types_mapping["tuple"] = tuple_type
        # Call the Validator constructor
        super(MyValidator, self).__init__(*args, **kwargs)

    def _validate_is_int_two_tuple(self, is_int_two_tuple, field, value):
        ''' Test that the value is a 2-tuple of ints

        The rule's arguments are validated against this schema:
        {'type': 'boolean'}
        '''
        if is_int_two_tuple:
            # Check the type
            if type(value) != tuple:
                self._error(field, "Must be of type 'tuple'")
            # Check the length
            if len(value) != 2:
                self._error(field, "Tuple must have two elements")
            # Check the element types
            if type(value[0]) != int or type(value[1]) != int:
                self._error(field, "Both tuple values must be of type 'int'")

data = {"mylist": [(1,1), (2,2), (3,3)]}

schema = {
    "mylist": {
        "type": "list",
        "schema": {
            "type": "tuple",
            "is_int_two_tuple": True
        }
    }
}

v = MyValidator(schema)
print("Validated: {}".format(v.validate(data)))
print("Validation errors: {}".format(v.errors))
print("Normalized result: {}".format(v.normalized(data)))

因此,正如 bro-grammer 指出的那样,自定义数据类型将使您验证类型,仅此而已。从您提供的模式来看,您似乎还想验证其他特征,例如元组的长度和元组中元素的类型。这样做需要的不仅仅是一个简单TypeDefinition的元组。

扩展 Validator 以包含此特定用例的规则并不理想,但它会做你想做的事。更全面的解决方案是创建一个TupleValidator具有验证元组长度、元素类型、顺序等规则的子类。

于 2018-08-25T17:52:30.103 回答
1

给定您的 typevar typing.List[typing.Tuple[int, int]],您期望一个任意长度的二值元组列表,其中每个值都是一个整数。

class MyValidator(Validator):
    # add a type definition to a validator subclass
    types_mapping = Validator.types_mapping.copy()
    types_mapping['tuple'] = TypeDefinition((tuple,), ())


schema = {
    'type': 'list',
    'empty': False,
    'schema': {  # the number of items is undefined
        'type': 'tuple',
        'items': 2 * ({'type': 'int'},)
    }
}

validator = MyValidator(schema)

了解项目架构规则的区别很重要。

请注意,默认list类型实际上映射到更抽象的Sequence 类型,您可能希望为此添加另一个更严格的类型。

于 2018-08-26T19:31:10.450 回答