tantale / deprecated

Python @deprecated decorator to deprecate old python classes, functions or methods.
MIT License
301 stars 32 forks source link

Test regression in 1.2.8 with PyPy3 #20

Closed mgorny closed 4 years ago

mgorny commented 4 years ago

Expected Behavior

Tests should pass, as they did in 1.2.7.

To run tests, I've added ,pypy3 to PyTest conditions in tox.ini.

Actual Behavior

The following tests fails with PyPy3:

==================================================================== FAILURES =====================================================================
___________________________________________________ test_classic_deprecated_class__warns[None] ____________________________________________________

classic_deprecated_class = <class 'tests.test_deprecated.classic_deprecated_class.<locals>.Foo2'>

    def test_classic_deprecated_class__warns(classic_deprecated_class):
        with warnings.catch_warnings(record=True) as warns:
            warnings.simplefilter("always")
            classic_deprecated_class()
        assert len(warns) == 1
        warn = warns[0]
        assert issubclass(warn.category, DeprecationWarning)
        assert "deprecated class" in str(warn.message)
>       assert warn.filename == __file__, 'Incorrect warning stackLevel'
E       AssertionError: Incorrect warning stackLevel
E       assert '/tmp/depreca...est/python.py' == '/tmp/depreca...deprecated.py'
E         - /tmp/deprecated-1.2.8/tests/test_deprecated.py
E         + /tmp/deprecated-1.2.8/.tox/pypy3/site-packages/_pytest/python.py

tests/test_deprecated.py:150: AssertionError
_________________________________________ test_classic_deprecated_class__warns[classic_deprecated_class1] _________________________________________

classic_deprecated_class = <class 'tests.test_deprecated.classic_deprecated_class.<locals>.Foo2'>

    def test_classic_deprecated_class__warns(classic_deprecated_class):
        with warnings.catch_warnings(record=True) as warns:
            warnings.simplefilter("always")
            classic_deprecated_class()
        assert len(warns) == 1
        warn = warns[0]
        assert issubclass(warn.category, DeprecationWarning)
        assert "deprecated class" in str(warn.message)
>       assert warn.filename == __file__, 'Incorrect warning stackLevel'
E       AssertionError: Incorrect warning stackLevel
E       assert '/tmp/depreca...est/python.py' == '/tmp/depreca...deprecated.py'
E         - /tmp/deprecated-1.2.8/tests/test_deprecated.py
E         + /tmp/deprecated-1.2.8/.tox/pypy3/site-packages/_pytest/python.py

tests/test_deprecated.py:150: AssertionError
_________________________________________ test_classic_deprecated_class__warns[classic_deprecated_class2] _________________________________________

classic_deprecated_class = <class 'tests.test_deprecated.classic_deprecated_class.<locals>.Foo2'>

    def test_classic_deprecated_class__warns(classic_deprecated_class):
        with warnings.catch_warnings(record=True) as warns:
            warnings.simplefilter("always")
            classic_deprecated_class()
        assert len(warns) == 1
        warn = warns[0]
        assert issubclass(warn.category, DeprecationWarning)
        assert "deprecated class" in str(warn.message)
>       assert warn.filename == __file__, 'Incorrect warning stackLevel'
E       AssertionError: Incorrect warning stackLevel
E       assert '/tmp/depreca...est/python.py' == '/tmp/depreca...deprecated.py'
E         - /tmp/deprecated-1.2.8/tests/test_deprecated.py
E         + /tmp/deprecated-1.2.8/.tox/pypy3/site-packages/_pytest/python.py

tests/test_deprecated.py:150: AssertionError
_________________________________________ test_classic_deprecated_class__warns[classic_deprecated_class3] _________________________________________

classic_deprecated_class = <class 'tests.test_deprecated.classic_deprecated_class.<locals>.Foo2'>

    def test_classic_deprecated_class__warns(classic_deprecated_class):
        with warnings.catch_warnings(record=True) as warns:
            warnings.simplefilter("always")
            classic_deprecated_class()
        assert len(warns) == 1
        warn = warns[0]
        assert issubclass(warn.category, DeprecationWarning)
        assert "deprecated class" in str(warn.message)
>       assert warn.filename == __file__, 'Incorrect warning stackLevel'
E       AssertionError: Incorrect warning stackLevel
E       assert '/tmp/depreca...est/python.py' == '/tmp/depreca...deprecated.py'
E         - /tmp/deprecated-1.2.8/tests/test_deprecated.py
E         + /tmp/deprecated-1.2.8/.tox/pypy3/site-packages/_pytest/python.py

tests/test_deprecated.py:150: AssertionError
_________________________________________ test_classic_deprecated_class__warns[classic_deprecated_class4] _________________________________________

classic_deprecated_class = <class 'tests.test_deprecated.classic_deprecated_class.<locals>.Foo2'>

    def test_classic_deprecated_class__warns(classic_deprecated_class):
        with warnings.catch_warnings(record=True) as warns:
            warnings.simplefilter("always")
            classic_deprecated_class()
        assert len(warns) == 1
        warn = warns[0]
        assert issubclass(warn.category, DeprecationWarning)
        assert "deprecated class" in str(warn.message)
>       assert warn.filename == __file__, 'Incorrect warning stackLevel'
E       AssertionError: Incorrect warning stackLevel
E       assert '/tmp/depreca...est/python.py' == '/tmp/depreca...deprecated.py'
E         - /tmp/deprecated-1.2.8/tests/test_deprecated.py
E         + /tmp/deprecated-1.2.8/.tox/pypy3/site-packages/_pytest/python.py

tests/test_deprecated.py:150: AssertionError
_________________________________________ test_classic_deprecated_class__warns[classic_deprecated_class5] _________________________________________

classic_deprecated_class = <class 'tests.test_deprecated.classic_deprecated_class.<locals>.Foo2'>

    def test_classic_deprecated_class__warns(classic_deprecated_class):
        with warnings.catch_warnings(record=True) as warns:
            warnings.simplefilter("always")
            classic_deprecated_class()
        assert len(warns) == 1
        warn = warns[0]
        assert issubclass(warn.category, DeprecationWarning)
        assert "deprecated class" in str(warn.message)
>       assert warn.filename == __file__, 'Incorrect warning stackLevel'
E       AssertionError: Incorrect warning stackLevel
E       assert '/tmp/depreca...est/python.py' == '/tmp/depreca...deprecated.py'
E         - /tmp/deprecated-1.2.8/tests/test_deprecated.py
E         + /tmp/deprecated-1.2.8/.tox/pypy3/site-packages/_pytest/python.py

tests/test_deprecated.py:150: AssertionError
_________________________________________ test_classic_deprecated_class__warns[classic_deprecated_class6] _________________________________________

classic_deprecated_class = <class 'tests.test_deprecated.classic_deprecated_class.<locals>.Foo2'>

    def test_classic_deprecated_class__warns(classic_deprecated_class):
        with warnings.catch_warnings(record=True) as warns:
            warnings.simplefilter("always")
            classic_deprecated_class()
        assert len(warns) == 1
        warn = warns[0]
        assert issubclass(warn.category, DeprecationWarning)
        assert "deprecated class" in str(warn.message)
>       assert warn.filename == __file__, 'Incorrect warning stackLevel'
E       AssertionError: Incorrect warning stackLevel
E       assert '/tmp/depreca...est/python.py' == '/tmp/depreca...deprecated.py'
E         - /tmp/deprecated-1.2.8/tests/test_deprecated.py
E         + /tmp/deprecated-1.2.8/.tox/pypy3/site-packages/_pytest/python.py

tests/test_deprecated.py:150: AssertionError
================================================================ warnings summary =================================================================
tests/test_deprecated_class.py::test_simple_class_deprecation_with_args
  /tmp/deprecated-1.2.8/.tox/pypy3/site-packages/_pytest/python.py:184: DeprecationWarning: Call to deprecated class MyClass. (kwargs class)
    result = testfunction(**testargs)

-- Docs: https://docs.pytest.org/en/latest/warnings.html

----------- coverage: platform linux, python 3.6.9-final-0 -----------
Name                     Stmts   Miss  Cover   Missing
------------------------------------------------------
deprecated/__init__.py       3      0   100%
deprecated/classic.py       71      3    96%   22, 130, 280
deprecated/sphinx.py        36      2    94%   124, 150
------------------------------------------------------
TOTAL                      110      5    95%

============================================================= short test summary info =============================================================
FAILED tests/test_deprecated.py::test_classic_deprecated_class__warns[None] - AssertionError: Incorrect warning stackLevel
FAILED tests/test_deprecated.py::test_classic_deprecated_class__warns[classic_deprecated_class1] - AssertionError: Incorrect warning stackLevel
FAILED tests/test_deprecated.py::test_classic_deprecated_class__warns[classic_deprecated_class2] - AssertionError: Incorrect warning stackLevel
FAILED tests/test_deprecated.py::test_classic_deprecated_class__warns[classic_deprecated_class3] - AssertionError: Incorrect warning stackLevel
FAILED tests/test_deprecated.py::test_classic_deprecated_class__warns[classic_deprecated_class4] - AssertionError: Incorrect warning stackLevel
FAILED tests/test_deprecated.py::test_classic_deprecated_class__warns[classic_deprecated_class5] - AssertionError: Incorrect warning stackLevel
FAILED tests/test_deprecated.py::test_classic_deprecated_class__warns[classic_deprecated_class6] - AssertionError: Incorrect warning stackLevel
==================================================== 7 failed, 148 passed, 1 warning in 20.18s ====================================================

I don't know if this isn't a problem with pytest itself and/or pypy3. However,

Environment

tantale commented 4 years ago

When printing a warning, the message should gives the user the right filename. The filename comes from the current execution stack.

For (still) unknown reason the stacklevel (the position of the caller in the stack) should be 3 if we decorate a function but 2 if it is a class.