#934 [CLI] TypeError: __init__() got an unexpected keyword argument 'strict' with marshmallow-3.0.0
Closed: Fixed 4 years ago by praiskup. Opened 4 years ago by szpak.

After upgrade to 1.81 (#925) I observe the following error in the Travis build log:

Traceback (most recent call last):
  File "/home/travis/virtualenv/python3.6.3/bin/copr-cli", line 7, in <module>
    from copr_cli.main import main
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/copr_cli/main.py", line 30, in <module>
    from copr import CoprClient
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/copr/__init__.py", line 3, in <module>
    from .client_v2.client import CoprClient as ClientV2
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/copr/client_v2/client.py", line 18, in <module>
    from .resources import Root
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/copr/client_v2/resources.py", line 15, in <module>
    from .entities import Link, ProjectEntity, ProjectChrootEntity, BuildEntity, MockChrootEntity, BuildTaskEntity
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/copr/client_v2/entities.py", line 44, in <module>
    class ProjectEntity(Entity):
  File "/home/travis/virtualenv/python3.6.3/lib/python3.6/site-packages/copr/client_v2/entities.py", line 45, in ProjectEntity
    _schema = ProjectSchema(strict=True)
TypeError: __init__() got an unexpected keyword argument 'strict'

I could suspect that there was some related change in 1.81, but the first build after upgrade passed that point. Looking at the pip logs I determined that there was one dependency upgrade - marshmallow-2.20.1 to 3.0.0 which brings: https://marshmallow.readthedocs.io/en/stable/upgrading.html#schemas-are-always-strict .

I could force marshmallow to be in 2.20.1 for a time being, but maybe copr(-cli) could be compatible with both version (I'm not a Python developer and I don't know about its cost)?


Thanks for the report.

I could force marshmallow to be in 2.20.1 for a time being, but maybe copr(-cli) could be
compatible with both version (I'm not a Python developer and I don't know about its cost)?

Yes it should be compatible, sooner or later we'll have to do the work. Of course help is welcome since this doesn't have huge priority.

Metadata Update from @praiskup:
- Issue tagged with: RFE

4 years ago

Metadata Update from @praiskup:
- Issue untagged with: RFE
- Issue tagged with: bug

4 years ago

We have this issue now in Mageia when building python-copr. Marshmallow version is 3.0.3.

After removing all 'strict=True' references build fails due to test errors:

+ /usr/bin/python3 -m pytest copr/test
============================= test session starts ==============================
platform linux -- Python 3.8.0b4, pytest-5.1.0, py-1.8.0, pluggy-0.12.0
rootdir: /home/wally/mageia/py3.8/python-copr/BUILD/python-copr-1.96
plugins: cov-2.7.1
collected 32 items

copr/test/test_client.py .....                                           [ 15%]
copr/test/test_resources.py .                                            [ 18%]
copr/test/client_v2/test_client.py ....                                  [ 31%]
copr/test/client_v2/test_entities.py EEE                                 [ 40%]
copr/test/client_v2/test_handlers.py FFFEEE                              [ 59%]
copr/test/client_v2/test_net_client.py ..                                [ 65%]
copr/test/client_v3/test_builds.py .                                     [ 68%]
copr/test/client_v3/test_general.py .                                    [ 71%]
copr/test/client_v3/test_helpers.py .F..F.                               [ 90%]
copr/test/client_v3/test_requests.py ...                                 [100%]

==================================== ERRORS ====================================
________________ ERROR at setup of TestEntities.test_from_dict _________________

self = <test_entities.TestEntities object at 0x7fd9fa048a60>
method = <bound method TestEntities.test_from_dict of <test_entities.TestEntities object at 0x7fd9fa048a60>>

    def setup_method(self, method):
>       self.entity = FooEntity.from_dict({"foo": "baz", "bar": 123, "non_existing_attribute": None})

copr/test/client_v2/test_entities.py:23: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/entities.py:40: in from_dict
    parsed = cls._schema.load(raw_dict)
/usr/lib/python3.8/site-packages/marshmallow/schema.py:683: in load
    return self._do_load(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <FooSchema(many=False)>
data = {'bar': 123, 'foo': 'baz', 'non_existing_attribute': None}

    def _do_load(
        self, data, *, many=None, partial=None, unknown=None, postprocess=True
    ):
        """Deserialize `data`, returning the deserialized result.

        :param data: The data to deserialize.
        :param bool many: Whether to deserialize `data` as a collection. If `None`, the
            value for `self.many` is used.
        :param bool|tuple partial: Whether to validate required fields. If its
            value is an iterable, only fields listed in that iterable will be
            ignored will be allowed missing. If `True`, all fields will be allowed missing.
            If `None`, the value for `self.partial` is used.
        :param unknown: Whether to exclude, include, or raise an error for unknown
            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.
            If `None`, the value for `self.unknown` is used.
        :param bool postprocess: Whether to run post_load methods..
        :return: A dict of deserialized data
        :rtype: dict
        """
        error_store = ErrorStore()
        errors = {}
        many = self.many if many is None else bool(many)
        unknown = unknown or self.unknown
        if partial is None:
            partial = self.partial
        # Run preprocessors
        if self._has_processors(PRE_LOAD):
            try:
                processed_data = self._invoke_load_processors(
                    PRE_LOAD, data, many=many, original_data=data, partial=partial
                )
            except ValidationError as err:
                errors = err.normalized_messages()
                result = None
        else:
            processed_data = data
        if not errors:
            # Deserialize data
            result = self._deserialize(
                processed_data,
                error_store=error_store,
                many=many,
                partial=partial,
                unknown=unknown,
            )
            # Run field-level validation
            self._invoke_field_validators(
                error_store=error_store, data=result, many=many
            )
            # Run schema-level validation
            if self._has_processors(VALIDATES_SCHEMA):
                field_errors = bool(error_store.errors)
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=True,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=False,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
            errors = error_store.errors
            # Run post processors
            if not errors and postprocess and self._has_processors(POST_LOAD):
                try:
                    result = self._invoke_load_processors(
                        POST_LOAD,
                        result,
                        many=many,
                        original_data=data,
                        partial=partial,
                    )
                except ValidationError as err:
                    errors = err.normalized_messages()
        if errors:
            exc = ValidationError(errors, data=data, valid_data=result)
            self.handle_error(exc, data, many=many, partial=partial)
>           raise exc
E           marshmallow.exceptions.ValidationError: {'non_existing_attribute': ['Unknown field.']}

/usr/lib/python3.8/site-packages/marshmallow/schema.py:842: ValidationError
_________________ ERROR at setup of TestEntities.test_to_dict __________________

self = <test_entities.TestEntities object at 0x7fd9fa07e340>
method = <bound method TestEntities.test_to_dict of <test_entities.TestEntities object at 0x7fd9fa07e340>>

    def setup_method(self, method):
>       self.entity = FooEntity.from_dict({"foo": "baz", "bar": 123, "non_existing_attribute": None})

copr/test/client_v2/test_entities.py:23: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/entities.py:40: in from_dict
    parsed = cls._schema.load(raw_dict)
/usr/lib/python3.8/site-packages/marshmallow/schema.py:683: in load
    return self._do_load(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <FooSchema(many=False)>
data = {'bar': 123, 'foo': 'baz', 'non_existing_attribute': None}

    def _do_load(
        self, data, *, many=None, partial=None, unknown=None, postprocess=True
    ):
        """Deserialize `data`, returning the deserialized result.

        :param data: The data to deserialize.
        :param bool many: Whether to deserialize `data` as a collection. If `None`, the
            value for `self.many` is used.
        :param bool|tuple partial: Whether to validate required fields. If its
            value is an iterable, only fields listed in that iterable will be
            ignored will be allowed missing. If `True`, all fields will be allowed missing.
            If `None`, the value for `self.partial` is used.
        :param unknown: Whether to exclude, include, or raise an error for unknown
            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.
            If `None`, the value for `self.unknown` is used.
        :param bool postprocess: Whether to run post_load methods..
        :return: A dict of deserialized data
        :rtype: dict
        """
        error_store = ErrorStore()
        errors = {}
        many = self.many if many is None else bool(many)
        unknown = unknown or self.unknown
        if partial is None:
            partial = self.partial
        # Run preprocessors
        if self._has_processors(PRE_LOAD):
            try:
                processed_data = self._invoke_load_processors(
                    PRE_LOAD, data, many=many, original_data=data, partial=partial
                )
            except ValidationError as err:
                errors = err.normalized_messages()
                result = None
        else:
            processed_data = data
        if not errors:
            # Deserialize data
            result = self._deserialize(
                processed_data,
                error_store=error_store,
                many=many,
                partial=partial,
                unknown=unknown,
            )
            # Run field-level validation
            self._invoke_field_validators(
                error_store=error_store, data=result, many=many
            )
            # Run schema-level validation
            if self._has_processors(VALIDATES_SCHEMA):
                field_errors = bool(error_store.errors)
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=True,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=False,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
            errors = error_store.errors
            # Run post processors
            if not errors and postprocess and self._has_processors(POST_LOAD):
                try:
                    result = self._invoke_load_processors(
                        POST_LOAD,
                        result,
                        many=many,
                        original_data=data,
                        partial=partial,
                    )
                except ValidationError as err:
                    errors = err.normalized_messages()
        if errors:
            exc = ValidationError(errors, data=data, valid_data=result)
            self.handle_error(exc, data, many=many, partial=partial)
>           raise exc
E           marshmallow.exceptions.ValidationError: {'non_existing_attribute': ['Unknown field.']}

/usr/lib/python3.8/site-packages/marshmallow/schema.py:842: ValidationError
_________________ ERROR at setup of TestEntities.test_to_json __________________

self = <test_entities.TestEntities object at 0x7fd9f9e919a0>
method = <bound method TestEntities.test_to_json of <test_entities.TestEntities object at 0x7fd9f9e919a0>>

    def setup_method(self, method):
>       self.entity = FooEntity.from_dict({"foo": "baz", "bar": 123, "non_existing_attribute": None})

copr/test/client_v2/test_entities.py:23: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/entities.py:40: in from_dict
    parsed = cls._schema.load(raw_dict)
/usr/lib/python3.8/site-packages/marshmallow/schema.py:683: in load
    return self._do_load(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <FooSchema(many=False)>
data = {'bar': 123, 'foo': 'baz', 'non_existing_attribute': None}

    def _do_load(
        self, data, *, many=None, partial=None, unknown=None, postprocess=True
    ):
        """Deserialize `data`, returning the deserialized result.

        :param data: The data to deserialize.
        :param bool many: Whether to deserialize `data` as a collection. If `None`, the
            value for `self.many` is used.
        :param bool|tuple partial: Whether to validate required fields. If its
            value is an iterable, only fields listed in that iterable will be
            ignored will be allowed missing. If `True`, all fields will be allowed missing.
            If `None`, the value for `self.partial` is used.
        :param unknown: Whether to exclude, include, or raise an error for unknown
            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.
            If `None`, the value for `self.unknown` is used.
        :param bool postprocess: Whether to run post_load methods..
        :return: A dict of deserialized data
        :rtype: dict
        """
        error_store = ErrorStore()
        errors = {}
        many = self.many if many is None else bool(many)
        unknown = unknown or self.unknown
        if partial is None:
            partial = self.partial
        # Run preprocessors
        if self._has_processors(PRE_LOAD):
            try:
                processed_data = self._invoke_load_processors(
                    PRE_LOAD, data, many=many, original_data=data, partial=partial
                )
            except ValidationError as err:
                errors = err.normalized_messages()
                result = None
        else:
            processed_data = data
        if not errors:
            # Deserialize data
            result = self._deserialize(
                processed_data,
                error_store=error_store,
                many=many,
                partial=partial,
                unknown=unknown,
            )
            # Run field-level validation
            self._invoke_field_validators(
                error_store=error_store, data=result, many=many
            )
            # Run schema-level validation
            if self._has_processors(VALIDATES_SCHEMA):
                field_errors = bool(error_store.errors)
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=True,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=False,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
            errors = error_store.errors
            # Run post processors
            if not errors and postprocess and self._has_processors(POST_LOAD):
                try:
                    result = self._invoke_load_processors(
                        POST_LOAD,
                        result,
                        many=many,
                        original_data=data,
                        partial=partial,
                    )
                except ValidationError as err:
                    errors = err.normalized_messages()
        if errors:
            exc = ValidationError(errors, data=data, valid_data=result)
            self.handle_error(exc, data, many=many, partial=partial)
>           raise exc
E           marshmallow.exceptions.ValidationError: {'non_existing_attribute': ['Unknown field.']}

/usr/lib/python3.8/site-packages/marshmallow/schema.py:842: ValidationError
______________ ERROR at setup of TestProjectHandle.test_get_self _______________

self = <test_handlers.TestProjectHandle object at 0x7fd9f9e71790>
project_handle = <copr.client_v2.handlers.ProjectHandle object at 0x7fd9f9e71a90>

    @pytest.fixture
    def one_project(self, project_handle):
        response = self.make_response(self.project_1)
        self.nc.request.return_value = response
>       one = project_handle.get_one(self.project_1_id)

copr/test/client_v2/test_handlers.py:188: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/handlers.py:314: in get_one
    return Project.from_response(
copr/client_v2/resources.py:320: in from_response
    entity = ProjectEntity.from_dict(data_dict["project"])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'copr.client_v2.entities.ProjectEntity'>
raw_dict = {'build_enable_net': True, 'contact': None, 'description': 'A simple KDE respin', 'disable_createrepo': False, ...}

    @classmethod
    def from_dict(cls, raw_dict):
        parsed = cls._schema.load(raw_dict)
>       return cls(**parsed.data)
E       AttributeError: 'dict' object has no attribute 'data'

copr/client_v2/entities.py:41: AttributeError
_______________ ERROR at setup of TestProjectHandle.test_update ________________

self = <test_handlers.TestProjectHandle object at 0x7fd9f9e263d0>
project_handle = <copr.client_v2.handlers.ProjectHandle object at 0x7fd9f9e26430>

    @pytest.fixture
    def one_project(self, project_handle):
        response = self.make_response(self.project_1)
        self.nc.request.return_value = response
>       one = project_handle.get_one(self.project_1_id)

copr/test/client_v2/test_handlers.py:188: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/handlers.py:314: in get_one
    return Project.from_response(
copr/client_v2/resources.py:320: in from_response
    entity = ProjectEntity.from_dict(data_dict["project"])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'copr.client_v2.entities.ProjectEntity'>
raw_dict = {'build_enable_net': True, 'contact': None, 'description': 'A simple KDE respin', 'disable_createrepo': False, ...}

    @classmethod
    def from_dict(cls, raw_dict):
        parsed = cls._schema.load(raw_dict)
>       return cls(**parsed.data)
E       AttributeError: 'dict' object has no attribute 'data'

copr/client_v2/entities.py:41: AttributeError
_______________ ERROR at setup of TestProjectHandle.test_delete ________________

self = <test_handlers.TestProjectHandle object at 0x7fd9f9e0d100>
project_handle = <copr.client_v2.handlers.ProjectHandle object at 0x7fd9f9e0d490>

    @pytest.fixture
    def one_project(self, project_handle):
        response = self.make_response(self.project_1)
        self.nc.request.return_value = response
>       one = project_handle.get_one(self.project_1_id)

copr/test/client_v2/test_handlers.py:188: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/handlers.py:314: in get_one
    return Project.from_response(
copr/client_v2/resources.py:320: in from_response
    entity = ProjectEntity.from_dict(data_dict["project"])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'copr.client_v2.entities.ProjectEntity'>
raw_dict = {'build_enable_net': True, 'contact': None, 'description': 'A simple KDE respin', 'disable_createrepo': False, ...}

    @classmethod
    def from_dict(cls, raw_dict):
        parsed = cls._schema.load(raw_dict)
>       return cls(**parsed.data)
E       AttributeError: 'dict' object has no attribute 'data'

copr/client_v2/entities.py:41: AttributeError
=================================== FAILURES ===================================
________________________ TestProjectHandle.test_get_one ________________________

self = <test_handlers.TestProjectHandle object at 0x7fd9fa04dbe0>
project_handle = <copr.client_v2.handlers.ProjectHandle object at 0x7fd9fa04d7c0>

    def test_get_one(self, project_handle):
        response = self.make_response(self.project_1)
        self.nc.request.return_value = response
>       project = project_handle.get_one(
            self.project_1_id,
            #    show_builds=True, show_chroots=True
        )

copr/test/client_v2/test_handlers.py:147: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/handlers.py:314: in get_one
    return Project.from_response(
copr/client_v2/resources.py:320: in from_response
    entity = ProjectEntity.from_dict(data_dict["project"])
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'copr.client_v2.entities.ProjectEntity'>
raw_dict = {'build_enable_net': True, 'contact': None, 'description': 'A simple KDE respin', 'disable_createrepo': False, ...}

    @classmethod
    def from_dict(cls, raw_dict):
        parsed = cls._schema.load(raw_dict)
>       return cls(**parsed.data)
E       AttributeError: 'dict' object has no attribute 'data'

copr/client_v2/entities.py:41: AttributeError
_______________________ TestProjectHandle.test_get_list ________________________

self = <test_handlers.TestProjectHandle object at 0x7fd9f9fd8340>
project_handle = <copr.client_v2.handlers.ProjectHandle object at 0x7fd9f9fd8310>

    def test_get_list(self, project_handle):
        response = self.make_response(self.project_list_1)
        self.nc.request.return_value = response
>       plist = project_handle.get_list()

copr/test/client_v2/test_handlers.py:158: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/handlers.py:298: in get_list
    return ProjectList.from_response(self, response, options)
copr/client_v2/resources.py:539: in from_response
    individuals = [
copr/client_v2/resources.py:540: in <listcomp>
    Project.from_response(
copr/client_v2/resources.py:320: in from_response
    entity = ProjectEntity.from_dict(data_dict["project"])
copr/client_v2/entities.py:40: in from_dict
    parsed = cls._schema.load(raw_dict)
/usr/lib/python3.8/site-packages/marshmallow/schema.py:683: in load
    return self._do_load(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <ProjectSchema(many=False)>
data = {'build_enable_net': False, 'contact': None, 'description': 'Lightweight buildsystem -', 'disable_createrepo': False, ...}

    def _do_load(
        self, data, *, many=None, partial=None, unknown=None, postprocess=True
    ):
        """Deserialize `data`, returning the deserialized result.

        :param data: The data to deserialize.
        :param bool many: Whether to deserialize `data` as a collection. If `None`, the
            value for `self.many` is used.
        :param bool|tuple partial: Whether to validate required fields. If its
            value is an iterable, only fields listed in that iterable will be
            ignored will be allowed missing. If `True`, all fields will be allowed missing.
            If `None`, the value for `self.partial` is used.
        :param unknown: Whether to exclude, include, or raise an error for unknown
            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.
            If `None`, the value for `self.unknown` is used.
        :param bool postprocess: Whether to run post_load methods..
        :return: A dict of deserialized data
        :rtype: dict
        """
        error_store = ErrorStore()
        errors = {}
        many = self.many if many is None else bool(many)
        unknown = unknown or self.unknown
        if partial is None:
            partial = self.partial
        # Run preprocessors
        if self._has_processors(PRE_LOAD):
            try:
                processed_data = self._invoke_load_processors(
                    PRE_LOAD, data, many=many, original_data=data, partial=partial
                )
            except ValidationError as err:
                errors = err.normalized_messages()
                result = None
        else:
            processed_data = data
        if not errors:
            # Deserialize data
            result = self._deserialize(
                processed_data,
                error_store=error_store,
                many=many,
                partial=partial,
                unknown=unknown,
            )
            # Run field-level validation
            self._invoke_field_validators(
                error_store=error_store, data=result, many=many
            )
            # Run schema-level validation
            if self._has_processors(VALIDATES_SCHEMA):
                field_errors = bool(error_store.errors)
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=True,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=False,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
            errors = error_store.errors
            # Run post processors
            if not errors and postprocess and self._has_processors(POST_LOAD):
                try:
                    result = self._invoke_load_processors(
                        POST_LOAD,
                        result,
                        many=many,
                        original_data=data,
                        partial=partial,
                    )
                except ValidationError as err:
                    errors = err.normalized_messages()
        if errors:
            exc = ValidationError(errors, data=data, valid_data=result)
            self.handle_error(exc, data, many=many, partial=partial)
>           raise exc
E           marshmallow.exceptions.ValidationError: {'is_a_group_project': ['Unknown field.']}

/usr/lib/python3.8/site-packages/marshmallow/schema.py:842: ValidationError
_________________ TestProjectHandle.test_get_list_pass_options _________________

self = <test_handlers.TestProjectHandle object at 0x7fd9f9ed3820>
project_handle = <copr.client_v2.handlers.ProjectHandle object at 0x7fd9f9ed3700>

    def test_get_list_pass_options(self, project_handle):
        response = self.make_response(self.project_list_1)
        self.nc.request.return_value = response

        query_params = {
            "search_query": "Foo bar",
            "owner": "John Smith",
            "name": "void",
            "offset": 12,
            "limit": 5
        }
>       project_handle.get_list(**query_params)

copr/test/client_v2/test_handlers.py:175: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
copr/client_v2/handlers.py:298: in get_list
    return ProjectList.from_response(self, response, options)
copr/client_v2/resources.py:539: in from_response
    individuals = [
copr/client_v2/resources.py:540: in <listcomp>
    Project.from_response(
copr/client_v2/resources.py:320: in from_response
    entity = ProjectEntity.from_dict(data_dict["project"])
copr/client_v2/entities.py:40: in from_dict
    parsed = cls._schema.load(raw_dict)
/usr/lib/python3.8/site-packages/marshmallow/schema.py:683: in load
    return self._do_load(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <ProjectSchema(many=False)>
data = {'build_enable_net': False, 'contact': None, 'description': 'Lightweight buildsystem -', 'disable_createrepo': False, ...}

    def _do_load(
        self, data, *, many=None, partial=None, unknown=None, postprocess=True
    ):
        """Deserialize `data`, returning the deserialized result.

        :param data: The data to deserialize.
        :param bool many: Whether to deserialize `data` as a collection. If `None`, the
            value for `self.many` is used.
        :param bool|tuple partial: Whether to validate required fields. If its
            value is an iterable, only fields listed in that iterable will be
            ignored will be allowed missing. If `True`, all fields will be allowed missing.
            If `None`, the value for `self.partial` is used.
        :param unknown: Whether to exclude, include, or raise an error for unknown
            fields in the data. Use `EXCLUDE`, `INCLUDE` or `RAISE`.
            If `None`, the value for `self.unknown` is used.
        :param bool postprocess: Whether to run post_load methods..
        :return: A dict of deserialized data
        :rtype: dict
        """
        error_store = ErrorStore()
        errors = {}
        many = self.many if many is None else bool(many)
        unknown = unknown or self.unknown
        if partial is None:
            partial = self.partial
        # Run preprocessors
        if self._has_processors(PRE_LOAD):
            try:
                processed_data = self._invoke_load_processors(
                    PRE_LOAD, data, many=many, original_data=data, partial=partial
                )
            except ValidationError as err:
                errors = err.normalized_messages()
                result = None
        else:
            processed_data = data
        if not errors:
            # Deserialize data
            result = self._deserialize(
                processed_data,
                error_store=error_store,
                many=many,
                partial=partial,
                unknown=unknown,
            )
            # Run field-level validation
            self._invoke_field_validators(
                error_store=error_store, data=result, many=many
            )
            # Run schema-level validation
            if self._has_processors(VALIDATES_SCHEMA):
                field_errors = bool(error_store.errors)
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=True,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
                self._invoke_schema_validators(
                    error_store=error_store,
                    pass_many=False,
                    data=result,
                    original_data=data,
                    many=many,
                    partial=partial,
                    field_errors=field_errors,
                )
            errors = error_store.errors
            # Run post processors
            if not errors and postprocess and self._has_processors(POST_LOAD):
                try:
                    result = self._invoke_load_processors(
                        POST_LOAD,
                        result,
                        many=many,
                        original_data=data,
                        partial=partial,
                    )
                except ValidationError as err:
                    errors = err.normalized_messages()
        if errors:
            exc = ValidationError(errors, data=data, valid_data=result)
            self.handle_error(exc, data, many=many, partial=partial)
>           raise exc
E           marshmallow.exceptions.ValidationError: {'is_a_group_project': ['Unknown field.']}

/usr/lib/python3.8/site-packages/marshmallow/schema.py:842: ValidationError
______________________________ TestWait.test_wait ______________________________

self = <test_helpers.TestWait object at 0x7fd9f9fe80a0>
mock_get = <MagicMock name='get' id='140574178837072'>

    @mock.patch("copr.v3.proxies.build.BuildProxy.get")
    def test_wait(self, mock_get):
        build = MunchMock(id=1, state="importing")

        mock_get.return_value = MunchMock(id=1, state="succeeded")
        assert wait(build)

        mock_get.return_value = MunchMock(id=1, state="unknown")
        with pytest.raises(CoprException) as ex:
            wait(build)
>       assert "Unknown status" in str(ex)
E       AssertionError: assert 'Unknown status' in '<ExceptionInfo CoprException tblen=2>'
E        +  where '<ExceptionInfo CoprException tblen=2>' = str(<ExceptionInfo CoprException tblen=2>)

copr/test/client_v3/test_helpers.py:32: AssertionError
__________________________ TestWait.test_wait_timeout __________________________

self = <test_helpers.TestWait object at 0x7fd9f9e80550>
mock_get = <MagicMock name='get' id='140574177208928'>
mock_time = <MagicMock name='time' id='140574177204352'>

    @mock.patch("time.time")
    @mock.patch("copr.v3.proxies.build.BuildProxy.get")
    def test_wait_timeout(self, mock_get, mock_time):
        build = MunchMock(id=1, state="importing")

        mock_get.return_value = MunchMock(id=1, state="running")
        mock_time.return_value = 0
        with pytest.raises(CoprException) as ex:
            wait(build, interval=0, timeout=-10)
>       assert "Timeouted" in str(ex)
E       AssertionError: assert 'Timeouted' in '<ExceptionInfo CoprException tblen=2>'
E        +  where '<ExceptionInfo CoprException tblen=2>' = str(<ExceptionInfo CoprException tblen=2>)

copr/test/client_v3/test_helpers.py:55: AssertionError
==================== 5 failed, 21 passed, 6 error in 0.61s =====================

New python-marsmallow is now Rawhide (F32), so we have broken cli and backend, this is high priority now.

Backend CI failure:

==================================== ERRORS ====================================
____________________ ERROR collecting tests/test_action.py _____________________
tests/test_action.py:15: in <module>
    from backend.actions import Action, ActionType, ActionResult
backend/actions.py:13: in <module>
    from copr.exceptions import CoprRequestException
/usr/lib/python3.8/site-packages/copr/__init__.py:3: in <module>
    from .client_v2.client import CoprClient as ClientV2
/usr/lib/python3.8/site-packages/copr/client_v2/client.py:18: in <module>
    from .resources import Root
/usr/lib/python3.8/site-packages/copr/client_v2/resources.py:15: in <module>
    from .entities import Link, ProjectEntity, ProjectChrootEntity, BuildEntity, MockChrootEntity, BuildTaskEntity
/usr/lib/python3.8/site-packages/copr/client_v2/entities.py:44: in <module>
    class ProjectEntity(Entity):
/usr/lib/python3.8/site-packages/copr/client_v2/entities.py:45: in ProjectEntity
    _schema = ProjectSchema(strict=True)
E   TypeError: __init__() got an unexpected keyword argument 'strict'
=============================== warnings summary ===============================
/usr/lib/python3.8/site-packages/netaddr/strategy/__init__.py:189

Metadata Update from @praiskup:
- Issue assigned to dturecek

4 years ago

Login to comment on this ticket.

Metadata
Related Pull Requests
  • #1028 Merged 4 years ago