-1

我正在尝试将自定义数据类型添加到Cerberus。UUID 类按预期工作(它是一个标准库类),但我无法使用 Cerberus 验证 UUID 类型。

其次,我无法在一个__init__函数中注册多种类型,但这可能应该是它自己的问题。

这是我应该注册给定类型的自定义验证器。

import cerberus

class UUID:
    name = "UUID"

    def __init__(self, potential_uuid: str):
        self.uuid = uuid.UUID(potential_uuid)

    def __str__(self):
        return str(self.uuid)

class Validator(cerberus.Validator):
    def _register_types(self) -> cerberus.Validator.types_mapping:
        types_mapping = Validator.types_mapping.copy()
        for schema_type in datatypes.ALL_TYPES:
            cerberus_type = cerberus.TypeDefinition(
                schema_type.name,
                (schema_type,),
                ())
            types_mapping[schema_type.name] = cerberus_type
        return types_mapping

    cerberus_type = cerberus.TypeDefinition(
        "UUID",
        (datatypes.UUID,),
        ())
    types_mapping = cerberus.Validator.types_mapping.copy()
    types_mapping["UUID"] = cerberus_type

    #def __init__(self, *args, **kwargs ):
    #    types_mapping = self._register_types()
    #    super().__init__(*args, **kwargs)

这是我对此代码的单元测试。

@pytest.mark.unit
def test_valid_uuid():
    test_input = "35d6d5a0-6f37-4794-a493-2712eda41c1a"
    actual = UUID(test_input)
    assert str(actual) == "35d6d5a0-6f37-4794-a493-2712eda41c1a"

@pytest.mark.unit
def test_invalid_uuid():
    test_input = "Not a Valid UUID"
    with pytest.raises(ValueError):
        actual = UUID(test_input) 

@pytest.mark.unit
def test_uuid_type_registration():
    test_schema = {"test_name": {"type": "UUID"}}
    validator = Validator(test_schema)
    test_record = {"test_name": "35d6d5a0-6f37-4794-a493-2712eda41c1a"}
    result = validator.validate(test_record)
    print(validator._errors)
    assert result == True

如果我们只是给 UUID 类一个有效的 UUID,它会成功,但如果我们尝试通过 Cerberus 验证它,我们会收到BAD_TYPE验证错误。

pytest tests/test_datatypes/test_datatypes.py
============================================================================================================================= test session starts ==============================================================================================================================
platform linux -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/vdev, inifile: setup.cfg
plugins: cov-2.6.1, benchmark-3.2.2
collected 4 items

tests/test_datatypes/test_datatypes.py ...F                                                                                                                                                                                                                              [100%]

=================================================================================================================================== FAILURES ===================================================================================================================================
_________________________________________________________________________________________________________________________ test_uuid_type_registration __________________________________________________________________________________________________________________________

    @pytest.mark.unit
    def test_uuid_type_registration():
        test_schema = {"test_name": {"type": "UUID"}}
        validator = Validator(test_schema)
        test_record = {"test_name": "35d6d5a0-6f37-4794-a493-2712eda41c1a"}
        result = validator.validate(test_record)
        print(validator._errors)
>       assert result == True
E       assert False == True

tests/test_datatypes/test_datatypes.py:30: AssertionError
----------------------------------------------------------------------------------------------------------------------------- Captured stdout call -----------------------------------------------------------------------------------------------------------------------------
[ValidationError @ 0x7fa477e10278 ( document_path=('test_name',),schema_path=('test_name', 'type'),code=0x24,constraint="UUID",value="35d6d5a0-6f37-4794-a493-2712eda41c1a",info=() )]
=============================================================================================================================== warnings summary ===============================================================================================================================
/usr/local/lib/python3.7/site-packages/cerberus/validator.py:14
/usr/local/lib/python3.7/site-packages/cerberus/validator.py:14
/usr/local/lib/python3.7/site-packages/cerberus/validator.py:14
/usr/local/lib/python3.7/site-packages/cerberus/validator.py:14
  /usr/local/lib/python3.7/site-packages/cerberus/validator.py:14: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
    from collections import Hashable, Iterable, Mapping, Sequence

/usr/local/lib/python3.7/site-packages/cerberus/errors.py:6
  /usr/local/lib/python3.7/site-packages/cerberus/errors.py:6: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
    from collections import defaultdict, namedtuple, MutableMapping

/usr/local/lib/python3.7/site-packages/cerberus/schema.py:3
  /usr/local/lib/python3.7/site-packages/cerberus/schema.py:3: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
    from collections import (Callable, Hashable, Iterable, Mapping,

-- Docs: https://docs.pytest.org/en/latest/warnings.html
================================================================================================================ 1 failed, 3 passed, 6 warnings in 0.33 seconds ===============================================================================================================

编辑 1

简化的示例代码

import cerberus
import uuid


class Validator(cerberus.Validator):
    types_mapping = {
        **cerberus.Validator.types_mapping,
        'UUID': cerberus.TypeDefinition('UUID', (uuid.UUID,), ())
    }

同样的失败

    @pytest.mark.unit
    def test_uuid_type_registration():
        test_schema = {"test_name": {"type": "UUID"}}
        validator = es_client.Validator(test_schema)
        test_record = {"test_name": "35d6d5a0-6f37-4794-a493-2712eda41c1a"}
        result = validator.validate(test_record)
        print(validator._errors)
>       assert result == True
E       assert False == True

tests/test_datatypes/test_datatypes.py:30: AssertionError
------------------------------------------------------------ Captured stdout call -------------------------------------------------------------
[ValidationError @ 0x7fd9cdeed0b8 ( document_path=('test_name',),schema_path=('test_name', 'type'),code=0x24,constraint="UUID",value="35d6d5a0-6f37-4794-a493-2712eda41c1a",info=() )]
4

1 回答 1

1

您能否澄清该_register_types方法的用途以及何时调用它?

这行得通,也许它可以帮助您找到错误:

def test_issue_475():
    class UUID:
        def __init__(self, data):
            self.data = data

    class MyValidator(Validator):
        types_mapping = {
            **Validator.types_mapping,
            'UUID': TypeDefinition('UUID', (UUID,), ())
        }

    assert_success(
        {'field': UUID(0)},
        {'field': {'type': 'UUID'}},
        validator=MyValidator()
    )

请注意,UUID当您在示例中实现另一个具有相同名称的类时,您提到了 sdtlib 的类。

于 2019-03-22T10:17:47.937 回答