14
0
forked from pool/python-wrapt

Accepting request 927607 from devel:languages:python

- update to 1.13.2:
  * Note that the next signficant release of `wrapt` will drop support for
    Python 2.7 and Python 3.5.
  * Fix Python version constraint so PyPi classifier for ``pip`` requires
    Python 2.7 or Python 3.5+.
  * When a reference to a class method was taken out of a class, and then
    wrapped in a function wrapper, and called, the class type was not being
    passed as the instance argument, but as the first argument in args,
    with the instance being ``None``. The class type should have been passed
    as the instance argument.
  * If supplying an adapter function for a signature changing decorator
    using input in the form of a function argument specification, name lookup
    exceptions would occur where the adaptor function had annotations which
    referenced non builtin Python types. Although the issues have been
    addressed where using input data in the format usually returned by
    ``inspect.getfullargspec()`` to pass the function argument specification,
    you can still have problems when supplying a function signature as
    string. In the latter case only Python builtin types can be referenced
    in annotations.
  * When a decorator was applied on top of a data/non-data descriptor in a
    class definition, the call to the special method ``__set_name__()`` to
    notify the descriptor of the variable name was not being propogated. Note
    that this issue has been addressed in the ``FunctionWrapper`` used by
    ``@wrapt.decorator`` but has not been applied to the generic
    ``ObjectProxy`` class. If using ``ObjectProxy`` directly to construct a
    custom wrapper which is applied to a descriptor, you will need to
    propogate the ``__set_name__()`` call yourself if required.
  * The ``issubclass()`` builtin method would give incorrect results when used
    with a class which had a decorator applied to it. Note that this has only
    been able to be fixed for Python 3.7+. Also, due to what is arguably a

OBS-URL: https://build.opensuse.org/request/show/927607
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-wrapt?expand=0&rev=13
This commit is contained in:
2021-10-29 20:32:57 +00:00
committed by Git OBS Bridge
6 changed files with 43 additions and 236 deletions

View File

@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:19f2043e05b76ce9b68971b387bfd8eed50c2ee1c9c0bd230edc422fec753917
size 126750

3
1.13.2.tar.gz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5013450a6609838fdbfeb357a135c52b75fbe8b42d79f581e1d4508c1f27801b
size 130624

View File

@@ -1,49 +0,0 @@
From abb18d6f52a0fd22de209f5d02f4d5c66656a26a Mon Sep 17 00:00:00 2001
From: Ben Greiner <code@bnavigator.de>
Date: Fri, 4 Dec 2020 01:24:34 +0100
Subject: [PATCH] fix dummycollector for pytest >= 6
---
tests/conftest.py | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/tests/conftest.py b/tests/conftest.py
index e37790f..9e9e35b 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -2,18 +2,30 @@
import pytest
+try:
+ from pytest import File as FileCollector
+except ImportError:
+ from pytest.collect import File as FileCollector
+
version = tuple(sys.version_info[:2])
-class DummyCollector(pytest.collect.File):
+class DummyCollector(FileCollector):
def collect(self):
return []
+def construct_dummy(path, parent):
+ if hasattr(DummyCollector, "from_parent"):
+ item = DummyCollector.from_parent(parent, fspath=path)
+ return item
+ else:
+ return DummyCollector(path, parent=parent)
+
def pytest_pycollect_makemodule(path, parent):
if '_py33' in path.basename and version < (3, 3):
- return DummyCollector(path, parent=parent)
+ return construct_dummy(path, parent)
if '_py37' in path.basename and version < (3, 7):
- return DummyCollector(path, parent=parent)
+ return construct_dummy(path, parent)
if '_py3' in path.basename and version < (3, 0):
- return DummyCollector(path, parent=parent)
+ return construct_dummy(path, parent)
if '_py2' in path.basename and version >= (3, 0):
- return DummyCollector(path, parent=parent)
+ return construct_dummy(path, parent)

View File

@@ -1,3 +1,42 @@
-------------------------------------------------------------------
Tue Oct 26 21:13:04 UTC 2021 - Dirk Müller <dmueller@suse.com>
- update to 1.13.2:
* Note that the next signficant release of `wrapt` will drop support for
Python 2.7 and Python 3.5.
* Fix Python version constraint so PyPi classifier for ``pip`` requires
Python 2.7 or Python 3.5+.
* When a reference to a class method was taken out of a class, and then
wrapped in a function wrapper, and called, the class type was not being
passed as the instance argument, but as the first argument in args,
with the instance being ``None``. The class type should have been passed
as the instance argument.
* If supplying an adapter function for a signature changing decorator
using input in the form of a function argument specification, name lookup
exceptions would occur where the adaptor function had annotations which
referenced non builtin Python types. Although the issues have been
addressed where using input data in the format usually returned by
``inspect.getfullargspec()`` to pass the function argument specification,
you can still have problems when supplying a function signature as
string. In the latter case only Python builtin types can be referenced
in annotations.
* When a decorator was applied on top of a data/non-data descriptor in a
class definition, the call to the special method ``__set_name__()`` to
notify the descriptor of the variable name was not being propogated. Note
that this issue has been addressed in the ``FunctionWrapper`` used by
``@wrapt.decorator`` but has not been applied to the generic
``ObjectProxy`` class. If using ``ObjectProxy`` directly to construct a
custom wrapper which is applied to a descriptor, you will need to
propogate the ``__set_name__()`` call yourself if required.
* The ``issubclass()`` builtin method would give incorrect results when used
with a class which had a decorator applied to it. Note that this has only
been able to be fixed for Python 3.7+. Also, due to what is arguably a
bug (https://bugs.python.org/issue44847) in the Python standard library,
you will still have problems when the class heirarchy uses a base class
which has the ``abc.ABCMeta`` metaclass. In this later case an exception
will be raised of ``TypeError: issubclass() arg 1 must be a class``.
- drop fix-dummy-collector-pytest6.patch, wrapt-pr161-py39tests.patch (upstream)
-------------------------------------------------------------------
Sat Mar 20 16:50:08 UTC 2021 - Ben Greiner <code@bnavigator.de>

View File

@@ -19,17 +19,13 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-wrapt
Version: 1.12.1
Version: 1.13.2
Release: 0
Summary: A Python module for decorators, wrappers and monkey patching
License: BSD-2-Clause
Group: Development/Languages/Python
URL: https://github.com/GrahamDumpleton/wrapt
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}

View File

@@ -1,179 +0,0 @@
From 33708e76578c173333d1879a4a21baddf8fcdb6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= <mgorny@gentoo.org>
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)