GrahamDumpleton / wrapt

A Python module for decorators, wrappers and monkey patching.
BSD 2-Clause "Simplified" License
2.05k stars 231 forks source link

Python 3.13 tests are failing #270

Open FFY00 opened 3 weeks ago

FFY00 commented 3 weeks ago

When I run the test suite on 3.13, I see the following failures.

$ tox -e py313
...
============================================================================================================================================== FAILURES ===============================================================================================================================================
_______________________________________________________________________________________________________________________________ TestWeakFunctionProxy.test_classmethod ________________________________________________________________________________________________________________________________

self = <test_weak_function_proxy.TestWeakFunctionProxy testMethod=test_classmethod>

    def test_classmethod(self):
        class Class(object):
            @classmethod
            def function(cls, a, b):
                self.assertEqual(cls, Class)
                return a, b

        result = []

        def callback(proxy):
            result.append(id(proxy))

        proxy = wrapt.WeakFunctionProxy(Class.function, callback)

        self.assertEqual(proxy(1, 2), (1, 2))

        Class = None
        gc.collect()

>       self.assertEqual(len(result), 1)
E       AssertionError: 0 != 1

tests/test_weak_function_proxy.py:151: AssertionError
_______________________________________________________________________________________________________________________________ TestWeakFunctionProxy.test_staticmethod _______________________________________________________________________________________________________________________________

self = <test_weak_function_proxy.TestWeakFunctionProxy testMethod=test_staticmethod>

    def test_staticmethod(self):
        class Class(object):
            @staticmethod
            def function(a, b):
                return a, b

        result = []

        def callback(proxy):
            result.append(id(proxy))

        proxy = wrapt.WeakFunctionProxy(Class.function, callback)

        self.assertEqual(proxy(1, 2), (1, 2))

        Class = None
        gc.collect()

>       self.assertEqual(len(result), 1)
E       AssertionError: 0 != 1

tests/test_weak_function_proxy.py:172: AssertionError
========================================================================================================================================== warnings summary ===========================================================================================================================================
tests/conftest.py:21
  /home/anubis/git/wrapt/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_weak_function_proxy.py::TestWeakFunctionProxy::test_classmethod - AssertionError: 0 != 1
FAILED tests/test_weak_function_proxy.py::TestWeakFunctionProxy::test_staticmethod - AssertionError: 0 != 1
============================================================================================================================== 2 failed, 436 passed, 1 warning in 3.25s ===============================================================================================================================
py313: exit 1 (4.07 seconds) /home/anubis/git/wrapt> python -m coverage run --rcfile /home/anubis/git/wrapt/setup.cfg -m pytest -v /home/anubis/git/wrapt/tests pid=2526876
.pkg: _exit> python /usr/lib/python3.12/site-packages/pyproject_api/_backend.py True setuptools.build_meta __legacy__
  py313: FAIL code 1 (11.16=setup[7.09]+cmd[4.07] seconds)
  evaluation failed :( (11.24 seconds)

Full log: https://gist.github.com/FFY00/280242204b24e7ff43905cfe9e901e06 (it was too big to include here)

This seems to be due to some changed on 3.13 causing Class.function to not be destructed on gc.collect() — I don't see the failures when only running the test suite partially. We should probably explore a better way to cause Class.function to be destructed in the test suite, as relying on the GC can be a bit unpredictable.

I don't see the same failures on 3.14 or older versions, so it seems isolated to 3.13.

GrahamDumpleton commented 6 days ago

Any further thoughts on how to deal with this? I have running of no GIL tests set up under GitHub actions now so can try and sort it out.

GrahamDumpleton commented 6 days ago

I managed to get both these tests to pass by clearing the function in the class, rather than just the class.

        Class.function = None
        Class = None
        gc.collect()
henryiii commented 4 days ago

Once it's sorted out, wheels for 3.13 would be nice. :)

GrahamDumpleton commented 4 days ago

Use wrapt==1.17.0.dev4 from PyPi for now to test. I need feedback that is all good before doing a final release.