Source: python-wrapt
Version: 1.15.0-2
Severity: normal
Tags: upstream patch
User: debian-pyt...@lists.debian.org
Usertags: python3.13
Forwarded: https://github.com/GrahamDumpleton/wrapt/issues/259

This package failed build from source when test-built against a version of
python3-defaults that incudes 3.13 as a supported version.

To reproduce this issue, build against python3-defaults (python3-all-dev etc.)
from Debian experimental.

What's new in Python 3.13:
https://docs.python.org/3.13/whatsnew/3.13.html

Log snippet:

tests/test_update_attributes.py::TestUpdateAttributes::test_update_annotations_modified_on_original
 PASSED [ 95%]
tests/test_update_attributes.py::TestUpdateAttributes::test_update_doc PASSED [ 
95%]
tests/test_update_attributes.py::TestUpdateAttributes::test_update_doc_modified_on_original
 PASSED [ 96%]
tests/test_update_attributes.py::TestUpdateAttributes::test_update_module 
PASSED [ 96%]
tests/test_update_attributes.py::TestUpdateAttributes::test_update_module_modified_on_original
 PASSED [ 96%]
tests/test_update_attributes.py::TestUpdateAttributes::test_update_name PASSED 
[ 96%]
tests/test_update_attributes.py::TestUpdateAttributes::test_update_name_modified_on_original
 PASSED [ 97%]
tests/test_update_attributes.py::TestUpdateAttributes::test_update_qualname 
PASSED [ 97%]
tests/test_update_attributes.py::TestUpdateAttributes::test_update_qualname_modified_on_original
 PASSED [ 97%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_call_expired 
PASSED [ 97%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_classmethod 
PASSED [ 97%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_decorator_method 
PASSED [ 98%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_function PASSED 
[ 98%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_instancemethod_delete_function
 PASSED [ 98%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_instancemethod_delete_function_and_instance
 PASSED [ 98%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_instancemethod_delete_instance
 PASSED [ 99%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_isinstance 
PASSED [ 99%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_no_callback 
PASSED [ 99%]
tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_staticmethod 
PASSED [ 99%]
tests/test_weak_function_proxy.py::TestArgumentUnpackingWeakFunctionProxy::test_self_keyword_argument
 PASSED [100%]

=================================== FAILURES ===================================
_____________ TestCallingOuterClassMethod.test_class_call_function _____________

self = <test_outer_classmethod.TestCallingOuterClassMethod 
testMethod=test_class_call_function>

    def test_class_call_function(self):
        # Test calling classmethod. Prior to Python 3.9, the instance
        # and class passed to the wrapper will both be None because our
        # decorator is surrounded by the classmethod decorator. The
        # classmethod decorator doesn't bind the method and treats it
        # like a normal function, explicitly passing the class as the
        # first argument with the actual arguments following that. This
        # was only finally fixed in Python 3.9. For more details see:
        # https://bugs.python.org/issue19072
    
        _args = (1, 2)
        _kwargs = {'one': 1, 'two': 2}
    
        @wrapt.decorator
        def _decorator(wrapped, instance, args, kwargs):
            if PYXY < (3, 9):
                self.assertEqual(instance, None)
                self.assertEqual(args, (Class,)+_args)
            else:
                self.assertEqual(instance, Class)
                self.assertEqual(args, _args)
    
            self.assertEqual(kwargs, _kwargs)
            self.assertEqual(wrapped.__module__, _function.__module__)
            self.assertEqual(wrapped.__name__, _function.__name__)
    
            return wrapped(*args, **kwargs)
    
        @_decorator
        def _function(*args, **kwargs):
            return args, kwargs
    
        class Class(object):
            @classmethod
            @_decorator
            def _function(cls, *args, **kwargs):
                return (args, kwargs)
    
>       result = Class._function(*_args, **_kwargs)

tests/test_outer_classmethod.py:160: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
src/wrapt/wrappers.py:598: in __call__
    return self._self_wrapper(self.__wrapped__, self._self_instance,
tests/test_outer_classmethod.py:141: in _decorator
    self.assertEqual(instance, Class)
E   AssertionError: None != <class 'test_outer_classmethod.TestCallin[54 
chars]ass'>
___________ TestCallingOuterClassMethod.test_instance_call_function ____________

self = <test_outer_classmethod.TestCallingOuterClassMethod 
testMethod=test_instance_call_function>

    def test_instance_call_function(self):
        # Test calling classmethod via class instance. Prior to Python
        # 3.9, the instance and class passed to the wrapper will both be
        # None because our decorator is surrounded by the classmethod
        # decorator. The classmethod decorator doesn't bind the method
        # and treats it like a normal function, explicitly passing the
        # class as the first argument with the actual arguments
        # following that. This was only finally fixed in Python 3.9. For
        # more details see: https://bugs.python.org/issue19072
    
        _args = (1, 2)
        _kwargs = {'one': 1, 'two': 2}
    
        @wrapt.decorator
        def _decorator(wrapped, instance, args, kwargs):
            if PYXY < (3, 9):
                self.assertEqual(instance, None)
                self.assertEqual(args, (Class,)+_args)
            else:
                self.assertEqual(instance, Class)
                self.assertEqual(args, _args)
    
            self.assertEqual(kwargs, _kwargs)
            self.assertEqual(wrapped.__module__, _function.__module__)
            self.assertEqual(wrapped.__name__, _function.__name__)
    
            return wrapped(*args, **kwargs)
    
        @_decorator
        def _function(*args, **kwargs):
            return args, kwargs
    
        class Class(object):
            @classmethod
            @_decorator
            def _function(cls, *args, **kwargs):
                return (args, kwargs)
    
>       result = Class()._function(*_args, **_kwargs)

tests/test_outer_classmethod.py:202: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
src/wrapt/wrappers.py:598: in __call__
    return self._self_wrapper(self.__wrapped__, self._self_instance,
tests/test_outer_classmethod.py:183: in _decorator
    self.assertEqual(instance, Class)
E   AssertionError: None != <class 'test_outer_classmethod.TestCallin[57 
chars]ass'>
_____________ TestSynchronized.test_synchronized_outer_classmethod _____________

self = <test_synchronized_lock.TestSynchronized 
testMethod=test_synchronized_outer_classmethod>

    def test_synchronized_outer_classmethod(self):
        # Prior to Python 3.9 this isn't detected as a class method
        # call, as the classmethod decorator doesn't bind the wrapped
        # function to the class before calling and just calls it direct,
        # explicitly passing the class as first argument. For more
        # details see: https://bugs.python.org/issue19072
    
        if PYXY < (3, 9):
            _lock0 = getattr(C4.function2, '_synchronized_lock', None)
        else:
            _lock0 = getattr(C4, '_synchronized_lock', None)
        self.assertEqual(_lock0, None)
    
        c4.function2()
    
        if PYXY < (3, 9):
            _lock1 = getattr(C4.function2, '_synchronized_lock', None)
        else:
            _lock1 = getattr(C4, '_synchronized_lock', None)
>       self.assertNotEqual(_lock1, None)
E       AssertionError: None == None

tests/test_synchronized_lock.py:181: AssertionError
----------------------------- Captured stdout call -----------------------------
function2
=============================== warnings summary ===============================
tests/conftest.py:21
  /<<PKGBUILDDIR>>/tests/conftest.py:21: PytestRemovedIn9Warning: The (path: 
py.path.local) argument is deprecated, please use (module_path: pathlib.Path)
  see 
https://docs.pytest.org/en/latest/deprecations.html#py-path-local-arguments-for-hooks-replaced-with-pathlib-path
    def pytest_pycollect_makemodule(path, parent):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED 
tests/test_outer_classmethod.py::TestCallingOuterClassMethod::test_class_call_function
FAILED 
tests/test_outer_classmethod.py::TestCallingOuterClassMethod::test_instance_call_function
FAILED 
tests/test_synchronized_lock.py::TestSynchronized::test_synchronized_outer_classmethod
============= 3 failed, 430 passed, 1 skipped, 1 warning in 0.66s ==============
make[1]: *** [debian/rules:26: override_dh_auto_test] Error 1
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
make: *** [debian/rules:9: build] Error 2
dpkg-buildpackage: error: debian/rules build subprocess returned exit status 2
--------------------------------------------------------------------------------
Build finished at 2024-09-11T15:48:22Z


If required, the full build log is available here (for the next 30 days):
https://debusine.debian.net/artifact/701553/

This bug has been filed at "normal" severity, as we haven't started the
transition to add 3.13 as a supported version, yet. This will be raised to RC
as soon as that happens, hopefully well before trixie.

Thanks,

Stefano

Reply via email to