From a4139eab245c2af2cfbbe4952f81d390d115bf41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Sat, 4 Jan 2020 23:58:53 +0100 Subject: [PATCH] Python 3.9 compatibility https://bugzilla.redhat.com/show_bug.cgi?id=1787746 https://github.com/micheles/decorator/issues/75 https://github.com/micheles/decorator/pull/76 --- python-decorator.spec | 9 ++- python39.patch | 170 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 python39.patch diff --git a/python-decorator.spec b/python-decorator.spec index 772bf64..25fb07f 100644 --- a/python-decorator.spec +++ b/python-decorator.spec @@ -14,6 +14,13 @@ Summary: Module to simplify usage of decorators License: BSD URL: https://github.com/micheles/decorator Source0: %pypi_source decorator + +# Python 3.9 compatibility +# https://bugzilla.redhat.com/show_bug.cgi?id=1787746 +# https://github.com/micheles/decorator/issues/75 +# https://github.com/micheles/decorator/pull/76 +Patch1: python39.patch + BuildArch: noarch BuildRequires: python2-setuptools @@ -54,7 +61,7 @@ etc. The core of this module is a decorator factory called decorator. # with python3 %prep -%autosetup -n %{pypi_name}-%{version} +%autosetup -p1 -n %{pypi_name}-%{version} %build %py2_build diff --git a/python39.patch b/python39.patch new file mode 100644 index 0000000..c1ced80 --- /dev/null +++ b/python39.patch @@ -0,0 +1,170 @@ +From 482f0833884fe490d50eb03a08eebfb19e9ed46d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= +Date: Sat, 4 Jan 2020 23:59:54 +0100 +Subject: [PATCH 1/2] Python 3.9 compatibility + +Thread.isAlive() is deprecated in 3.8 and removed in 3.9: + + $ python3.8 -c 'import threading; t = threading.Thread(); t.isAlive()' + :1: DeprecationWarning: isAlive() is deprecated, use is_alive() instead + + $ python3.9 -c 'import threading; t = threading.Thread(); t.isAlive()' + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'Thread' object has no attribute 'isAlive' + +Fixes https://github.com/micheles/decorator/issues/75 +--- + src/tests/documentation.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tests/documentation.py b/src/tests/documentation.py +index 2888ea1..bd3367c 100644 +--- a/src/tests/documentation.py ++++ b/src/tests/documentation.py +@@ -1531,7 +1531,7 @@ def set_result(): + f.thread = threading.Thread(None, set_result) + f.thread.start() + return msg +- elif f.thread.isAlive(): ++ elif f.thread.is_alive(): + return msg + else: # the thread is ended, return the stored result + del f.thread + +From 89907e760bdc32c3a6e5169015ded485b4d992fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= +Date: Sun, 5 Jan 2020 00:13:52 +0100 +Subject: [PATCH 2/2] On Python 3.9, we cannot longer avoid using + collections.abc + +Related to https://github.com/micheles/decorator/issues/75#issuecomment-570827328 +--- + docs/documentation.md | 35 +++++++++++++++++---------------- + src/tests/documentation.py | 40 ++++++++++++++++++++------------------ + 2 files changed, 39 insertions(+), 36 deletions(-) + +diff --git a/src/tests/documentation.py b/src/tests/documentation.py +index bd3367c..60a37a2 100644 +--- a/src/tests/documentation.py ++++ b/src/tests/documentation.py +@@ -9,6 +9,7 @@ + import collections.abc as c + except ImportError: + c = collections ++ collections.abc = collections + from decorator import (decorator, decorate, FunctionMaker, contextmanager, + dispatch_on, __version__) + +@@ -1008,15 +1009,16 @@ def coro_to_func(coro, *args, **kw): + $$WithLength + + This class defines a ``__len__`` method, and is therefore +-considered to be a subclass of the abstract base class ``collections.Sized``: ++considered to be a subclass of the abstract base class ++``collections.abc.Sized`` (``collections.Sized`` on Python 2): + + ```python +->>> issubclass(WithLength, collections.Sized) ++>>> issubclass(WithLength, collections.abc.Sized) + True + + ``` + +-However, ``collections.Sized`` is not in the MRO_ of ``WithLength``; it ++However, ``collections.abc.Sized`` is not in the MRO_ of ``WithLength``; it + is not a true ancestor. Any implementation of generic functions (even + with single dispatch) must go through some contorsion to take into + account the virtual ancestors. +@@ -1037,7 +1039,7 @@ def coro_to_func(coro, *args, **kw): + + ``` + +-...even if ``collections.Sized`` is not a true ancestor of ``WithLength``. ++...even if ``collections.abc.Sized`` is not a true ancestor of ``WithLength``. + + Of course, this is a contrived example--you could just use the + builtin ``len``--but you should get the idea. +@@ -1053,14 +1055,14 @@ def coro_to_func(coro, *args, **kw): + $$SomeSet + + Here, the author of ``SomeSet`` made a mistake by inheriting from +-``collections.Sized`` (instead of ``collections.Set``). ++``collections.abc.Sized`` (instead of ``collections.abc.Set``). + + This is not a problem. You can register *a posteriori* +-``collections.Set`` as a virtual ancestor of ``SomeSet``: ++``collections.abc.Set`` as a virtual ancestor of ``SomeSet``: + + ```python +->>> _ = collections.Set.register(SomeSet) +->>> issubclass(SomeSet, collections.Set) ++>>> _ = collections.abc.Set.register(SomeSet) ++>>> issubclass(SomeSet, collections.abc.Set) + True + + ``` +@@ -1080,10 +1082,10 @@ def coro_to_func(coro, *args, **kw): + ``` + + Sometimes it is not clear how to dispatch. For instance, consider a +-class ``C`` registered both as ``collections.Iterable`` and +-``collections.Sized``, and defines a generic function ``g`` with +-implementations for both ``collections.Iterable`` *and* +-``collections.Sized``: ++class ``C`` registered both as ``collections.abc.Iterable`` and ++``collections.abc.Sized``, and defines a generic function ``g`` with ++implementations for both ``collections.abc.Iterable`` *and* ++``collections.abc.Sized``: + + $$singledispatch_example1 + +@@ -1784,7 +1786,7 @@ def __len__(self): + return 0 + + +-class SomeSet(collections.Sized): ++class SomeSet(collections.abc.Sized): + # methods that make SomeSet set-like + # not shown ... + def __len__(self): +@@ -1796,12 +1798,12 @@ def get_length(obj): + raise NotImplementedError(type(obj)) + + +-@get_length.register(collections.Sized) ++@get_length.register(collections.abc.Sized) + def get_length_sized(obj): + return len(obj) + + +-@get_length.register(collections.Set) ++@get_length.register(collections.abc.Set) + def get_length_set(obj): + return 1 + +@@ -1810,8 +1812,8 @@ class C(object): + "Registered as Sized and Iterable" + + +-collections.Sized.register(C) +-collections.Iterable.register(C) ++collections.abc.Sized.register(C) ++collections.abc.Iterable.register(C) + + + def singledispatch_example1(): +@@ -1821,11 +1823,11 @@ def singledispatch_example1(): + def g(obj): + raise NotImplementedError(type(g)) + +- @g.register(collections.Sized) ++ @g.register(collections.abc.Sized) + def g_sized(object): + return "sized" + +- @g.register(collections.Iterable) ++ @g.register(collections.abc.Iterable) + def g_iterable(object): + return "iterable" +