将UUID类型添加到Cerberus会导致BAD_TYPE错误

问题描述 投票:-1回答: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 ===============================================================================================================

EDIT 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=() )]
python-3.x cerberus
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()
    )

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

© www.soinside.com 2019 - 2024. All rights reserved.