Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-wrapt for openSUSE:Factory checked in at 2021-03-24 16:10:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-wrapt (Old) and /work/SRC/openSUSE:Factory/.python-wrapt.new.2401 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-wrapt" Wed Mar 24 16:10:28 2021 rev:12 rq:880495 version:1.12.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-wrapt/python-wrapt.changes 2020-12-05 20:35:39.122615579 +0100 +++ /work/SRC/openSUSE:Factory/.python-wrapt.new.2401/python-wrapt.changes 2021-03-24 16:10:29.923784524 +0100 @@ -1,0 +2,7 @@ +Sat Mar 20 16:50:08 UTC 2021 - Ben Greiner <[email protected]> + +- Fix python39 test suite failures + * wrapt-pr161-py39tests.patch + * gh#GrahamDumpleton/wrapt#161 + +------------------------------------------------------------------- New: ---- wrapt-pr161-py39tests.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-wrapt.spec ++++++ --- /var/tmp/diff_new_pack.2L2MdZ/_old 2021-03-24 16:10:30.527785157 +0100 +++ /var/tmp/diff_new_pack.2L2MdZ/_new 2021-03-24 16:10:30.531785162 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-wrapt # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # Copyright (c) 2015 LISA GmbH, Bingen, Germany. # # All modifications and additions to the file contributed by third parties @@ -28,6 +28,8 @@ Source: https://github.com/GrahamDumpleton/wrapt/archive/%{version}.tar.gz # PATCH-FIX-UPSTREAM gh#GrahamDumpleton/wrapt#168 -- fix pytest 6 dummy collection Patch0: https://github.com/GrahamDumpleton/wrapt/pull/168.patch#/fix-dummy-collector-pytest6.patch +# PATCH-FIX-UPSTREAM gh#GrahamDumpleton/wrapt#161 -- fix test for Python 3.9 +Patch1: https://github.com/GrahamDumpleton/wrapt/pull/161.patch#/wrapt-pr161-py39tests.patch BuildRequires: %{python_module devel} BuildRequires: %{python_module pytest} BuildRequires: %{python_module setuptools} @@ -60,8 +62,7 @@ * http://wrapt.readthedocs.org/ %prep -%setup -q -n wrapt-%{version} -%patch0 -p1 +%autosetup -p1 -n wrapt-%{version} %build export CFLAGS="%{optflags}" @@ -77,6 +78,7 @@ %files %{python_files} %license LICENSE %doc README.rst docs/changes.rst -%{python_sitearch}/* +%{python_sitearch}/wrapt +%{python_sitearch}/wrapt-%{version}*-info %changelog ++++++ wrapt-pr161-py39tests.patch ++++++ >From 33708e76578c173333d1879a4a21baddf8fcdb6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= <[email protected]> Date: Fri, 29 May 2020 16:06:07 +0200 Subject: [PATCH] Update for fixed outer @classmethod behavior in Python 3.9 Fixes #160 --- docs/decorators.rst | 18 ++++++------- tests/test_outer_classmethod.py | 45 +++++++++++++++++++++------------ tests/test_synchronized_lock.py | 22 ++++++++-------- 3 files changed, 49 insertions(+), 36 deletions(-) diff --git a/docs/decorators.rst b/docs/decorators.rst index b8200d6..94201de 100644 --- a/docs/decorators.rst +++ b/docs/decorators.rst @@ -641,15 +641,15 @@ When calling the wrapped function in the decorator wrapper function, the instance is already bound to ``wrapped`` and will be passed automatically as the first argument to the original wrapped function. -Note that due to a bug in Python ``classmethod.__get__()``, whereby it does -not apply the descriptor protocol to the function wrapped by ``@classmethod``, -the above only applies where the decorator wraps the ``@classmethod`` -decorator. If the decorator is placed inside of the ``@classmethod`` -decorator, then ``instance`` will be ``None`` and the decorator wrapper -function will see the call as being the same as a normal function. As a -result, always place any decorator outside of the ``@classmethod`` -decorator. Hopefully this issue in Python can be addressed in a future -Python version. +Note that due to a bug in Python prior to 3.9 ``classmethod.__get__()``, +whereby it does not apply the descriptor protocol to the function +wrapped by ``@classmethod``, the above only applies where the decorator +wraps the ``@classmethod`` decorator. If the decorator is placed inside +of the ``@classmethod`` decorator, then ``instance`` will be ``None`` +and the decorator wrapper function will see the call as being the same +as a normal function. As a result, always place any decorator outside of +the ``@classmethod`` decorator if you need to support earlier Python +versions. Decorating Static Methods ------------------------- diff --git a/tests/test_outer_classmethod.py b/tests/test_outer_classmethod.py index 6b4af4f..9c2fcb8 100644 --- a/tests/test_outer_classmethod.py +++ b/tests/test_outer_classmethod.py @@ -3,6 +3,7 @@ import unittest import inspect import imp +import sys import wrapt @@ -121,20 +122,26 @@ def test_instance_isinstance(self): class TestCallingOuterClassMethod(unittest.TestCase): def test_class_call_function(self): - # Test calling classmethod. 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. + # Test calling classmethod. In Python 3.9, the class will be + # passed as instance. In older versions of Python, 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. _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @wrapt.decorator def _decorator(wrapped, instance, args, kwargs): - self.assertEqual(instance, None) - self.assertEqual(args, (Class,)+_args) + if sys.hexversion >= 0x03090000: + self.assertEqual(instance, Class) + self.assertEqual(args, _args) + else: + self.assertEqual(instance, None) + self.assertEqual(args, (Class,)+_args) self.assertEqual(kwargs, _kwargs) self.assertEqual(wrapped.__module__, _function.__module__) self.assertEqual(wrapped.__name__, _function.__name__) @@ -155,20 +162,26 @@ def _function(cls, *args, **kwargs): self.assertEqual(result, (_args, _kwargs)) def test_instance_call_function(self): - # Test calling classmethod via class instance. 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. + # Test calling classmethod via class instance. In Python 3.9, + # the class will be passed as instance. In older versions + # of Python, 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. _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @wrapt.decorator def _decorator(wrapped, instance, args, kwargs): - self.assertEqual(instance, None) - self.assertEqual(args, (Class,)+_args) + if sys.hexversion >= 0x03090000: + self.assertEqual(instance, Class) + self.assertEqual(args, _args) + else: + self.assertEqual(instance, None) + self.assertEqual(args, (Class,)+_args) self.assertEqual(kwargs, _kwargs) self.assertEqual(wrapped.__module__, _function.__module__) self.assertEqual(wrapped.__name__, _function.__name__) diff --git a/tests/test_synchronized_lock.py b/tests/test_synchronized_lock.py index 6e7eb12..b8f60f3 100644 --- a/tests/test_synchronized_lock.py +++ b/tests/test_synchronized_lock.py @@ -1,5 +1,6 @@ from __future__ import print_function +import sys import unittest import wrapt @@ -157,34 +158,33 @@ def test_synchronized_inner_classmethod(self): self.assertEqual(_lock3, _lock2) def test_synchronized_outer_classmethod(self): - # XXX If all was good, this would be detected as a class + # Bug in Python < 3.9: + # If all was good, this would be detected as a class # method call, but 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. This screws things up. Would be nice if - # Python were fixed, but that isn't likely to happen. + # first argument. This screws things up. - #_lock0 = getattr(C4, '_synchronized_lock', None) - _lock0 = getattr(C4.function2, '_synchronized_lock', None) + lock_target = (C4 if sys.hexversion >= 0x03090000 + else C4.function2) + + _lock0 = getattr(lock_target, '_synchronized_lock', None) self.assertEqual(_lock0, None) c4.function2() - #_lock1 = getattr(C4, '_synchronized_lock', None) - _lock1 = getattr(C4.function2, '_synchronized_lock', None) + _lock1 = getattr(lock_target, '_synchronized_lock', None) self.assertNotEqual(_lock1, None) C4.function2() - #_lock2 = getattr(C4, '_synchronized_lock', None) - _lock2 = getattr(C4.function2, '_synchronized_lock', None) + _lock2 = getattr(lock_target, '_synchronized_lock', None) self.assertNotEqual(_lock2, None) self.assertEqual(_lock2, _lock1) C4.function2() - #_lock3 = getattr(C4, '_synchronized_lock', None) - _lock3 = getattr(C4.function2, '_synchronized_lock', None) + _lock3 = getattr(lock_target, '_synchronized_lock', None) self.assertNotEqual(_lock3, None) self.assertEqual(_lock3, _lock2)
