Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pytest.raises 3.5.0 breaks for exception classes that look iterable (e.g. spyne.error.RequestNotAllowed) #3372

Closed
backbord opened this issue Apr 6, 2018 · 5 comments
Labels
type: bug problem that needs to be addressed type: regression indicates a problem that was introduced in a release which was working previously

Comments

@backbord
Copy link

backbord commented Apr 6, 2018

Hi,

I recently update to pytest 3.5.0 and use it to test applications that use spyne.

Unfortunately, my tests that have code like

import pytest
from spyne.errors import RequestNotAllowed, InvalidCredentialsError

import mymodule

def test_a():
    with pytest.raises(RequestNotAllowed):
        mymodule.func_that_raises_request_not_allowed()

def test_b():
    with pytest.raises(InvalidCredentialsError):
        mymodule.func_that_raises_invalid_credentials_error()

now break in the lines starting on with pytest.raises and give a traceback similar to this one:

___ test_detect_replay_nonce[example_forecast.xml.gz] ___

    def test_a():
>       with pytest.raises(RequestNotAllowed):

tests/test_client.py:130: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/foobar/lib/python3.6/site-packages/_pytest/python_api.py:587: in raises
    for exc in filterfalse(isclass, always_iterable(expected_exception)):
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <class 'spyne.error.RequestNotAllowed'>, item = 0

    def __getitem__(self, item):
>       return self.customize(**item)
E       TypeError: customize() argument after ** must be a mapping, not int

/foobar/lib/python3.6/site-packages/spyne/model/_base.py:179: TypeError

The issue didn't come up in previous versions of pytest so I dug a bit and found that

  • pytest.raises changed in version 3.5.0 to use always_iterable,
  • the exception classes used by spyne both have a __len__ and a __getitem__ function,
  • python thinks that the exception class is iterable,
    and that this is the cause of these unexpected problems.

I don't know whether exception classes that look iterable are generally disallowed or if this is something that should be supported/fixed in pytest.
I didn't find this behavior change to be mentioned in the changelog but I may have not looked thoroughly enough.

Perhaps you can advise?

Thanks!
Tim


Here is some IPython output from my digging:

Python 3.6.5
Type 'copyright', 'credits' or 'license' for more information
IPython 6.3.0 -- An enhanced Interactive Python. Type '?' for help.
Warning: disable autoreload in ipython_config.py to improve performance.

In [1]: from spyne.error import InvalidCredentialsError

In [2]: hasattr(InvalidCredentialsError, '__getitem__')
Out[2]: True

In [3]: hasattr(InvalidCredentialsError, '__len__')
Out[3]: True

In [4]: from more_itertools.more import always_iterable

In [5]: next(always_iterable(InvalidCredentialsError))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-24d61822a93e> in <module>()
----> 1 next(always_iterable(InvalidCredentialsError))

/foobar/lib/python3.6/site-packages/spyne/model/_base.py in __getitem__(self, item)
    177 class ModelBaseMeta(type(object)):
    178     def __getitem__(self, item):
--> 179         return self.customize(**item)
    180
    181     def customize(self, **kwargs):

TypeError: customize() argument after ** must be a mapping, not int

always_iterable attempts to create an iterable by executing

try:
    return iter(obj)
except TypeError:
    return iter((obj,))
In [6]: next(iter(InvalidCredentialsError))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-5759e2f7cde0> in <module>()
----> 1 next(iter(InvalidCredentialsError))

/foobar/lib/python3.6/site-packages/spyne/model/_base.py in __getitem__(self, item)
    177 class ModelBaseMeta(type(object)):
    178     def __getitem__(self, item):
--> 179         return self.customize(**item)
    180
    181     def customize(self, **kwargs):

TypeError: customize() argument after ** must be a mapping, not int

I'm using

  • python 3.6.5
  • pytest 3.5.0
  • spyne 2.12.14

It works in pytest 3.4.2 where always_iterable isn't used in functionraises of _pytest/python_api.py.

@pytestbot
Copy link
Contributor

GitMate.io thinks possibly related issues are #1965 (Pytest 3.0.2 memory leak with pytest.raises), #2573 (3.2.0: exceptions / internal errors related to markers), #2118 (pytest triggering deprecation warnings in 3.0.5), #1882 (pytest 3.0 on Anaconda), and #1005 (Error in Python 3.5.0).

@RonnyPfannschmidt
Copy link
Member

at first glance - wow they just implemented a fundamentally broken sequence as part of an exception api for convenience - the code change in queston is a internal clenaup

@RonnyPfannschmidt
Copy link
Member

@nicoddemus i believe a reasonable fix is to set the base_type parameter to Exception in our call,

alltho it may be necessary to use (Exception, six.string_types)

@nicoddemus
Copy link
Member

at first glance - wow they just implemented a fundamentally broken sequence as part of an exception api for convenience

😱

@nicoddemus i believe a reasonable fix is to set the base_type parameter to Exception in our call,

If that works then it sounds good!

@backbord are you interested in opening a PR?

@nicoddemus nicoddemus added type: bug problem that needs to be addressed type: regression indicates a problem that was introduced in a release which was working previously labels Apr 6, 2018
nicoddemus added a commit that referenced this issue Apr 7, 2018
@nicoddemus
Copy link
Member

Fixed by #3373

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug problem that needs to be addressed type: regression indicates a problem that was introduced in a release which was working previously
Projects
None yet
Development

No branches or pull requests

4 participants