Добавление типа UUID к Церберу приводит к ошибке BAD_TYPE - PullRequest
0 голосов
/ 21 марта 2019

Я пытаюсь добавить пользовательские типы данных в Цербер . Класс UUID работает должным образом (это стандартный библиотечный класс), но я не могу проверить с помощью типа UUID с использованием Cerberus.

Во-вторых, я не смог зарегистрировать несколько типов в функции __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=() )]

1 Ответ

1 голос
/ 22 марта 2019

Не могли бы вы уточнить, для чего предназначен метод _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, а в своем примере вы реализуете другой с тем же именем.

...