From bff314d73f4120100dfa7f1234a5a7fc355231ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 1 Mar 2023 12:33:35 +0100 Subject: [PATCH] Python 3.12.0a5 fixes --- 15de63e460.patch | 116 +++++++++++++++++++++++++++++++++++++++++++++ 21e64ec206.patch | 25 ++++++++++ 3397705da0.patch | 34 ++++++++++++++ Cython.spec | 17 ++++++- d883ccdec1.patch | 119 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 15de63e460.patch create mode 100644 21e64ec206.patch create mode 100644 3397705da0.patch create mode 100644 d883ccdec1.patch diff --git a/15de63e460.patch b/15de63e460.patch new file mode 100644 index 0000000..6bac79d --- /dev/null +++ b/15de63e460.patch @@ -0,0 +1,116 @@ +From 15de63e460e8a634aeb6bede0ba40ffa759f8c08 Mon Sep 17 00:00:00 2001 +From: da-woods +Date: Sun, 17 Jul 2022 10:51:11 +0100 +Subject: [PATCH] Account for possible extension type struct padding when + calculating the itemsize for the "size changed" check (GH-4894) + +--- + Cython/Compiler/ModuleNode.py | 6 +++--- + Cython/Utility/ImportExport.c | 40 ++++++++++++++++++++++++++++++++--- + 2 files changed, 40 insertions(+), 6 deletions(-) + +diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py +index 56845330df..e81b63d0a6 100644 +--- a/Cython/Compiler/ModuleNode.py ++++ b/Cython/Compiler/ModuleNode.py +@@ -3078,12 +3078,12 @@ def generate_type_import_call(self, type, code, import_generator, error_code=Non + if not condition: + code.putln("") # start in new line + code.putln("#if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000") +- code.putln('sizeof(%s),' % objstruct) ++ code.putln('sizeof(%s), __PYX_GET_STRUCT_ALIGNMENT(%s),' % (objstruct, objstruct)) + code.putln("#else") +- code.putln('sizeof(%s),' % sizeof_objstruct) ++ code.putln('sizeof(%s), __PYX_GET_STRUCT_ALIGNMENT(%s),' % (sizeof_objstruct, sizeof_objstruct)) + code.putln("#endif") + else: +- code.put('sizeof(%s), ' % objstruct) ++ code.putln('sizeof(%s), __PYX_GET_STRUCT_ALIGNMENT(%s),' % (objstruct, objstruct)) + + # check_size + if type.check_size and type.check_size in ('error', 'warn', 'ignore'): +diff --git a/Cython/Utility/ImportExport.c b/Cython/Utility/ImportExport.c +index 1689c11381..e1458fc8ff 100644 +--- a/Cython/Utility/ImportExport.c ++++ b/Cython/Utility/ImportExport.c +@@ -301,13 +301,24 @@ static int __Pyx_SetPackagePathFromImportLib(PyObject *module_name) { + #ifndef __PYX_HAVE_RT_ImportType_proto + #define __PYX_HAVE_RT_ImportType_proto + ++#if __STDC_VERSION__ >= 201112L ++#include ++#endif ++ ++#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L ++#define __PYX_GET_STRUCT_ALIGNMENT(s) alignof(s) ++#else ++// best guess at what the alignment could be since we can't measure it ++#define __PYX_GET_STRUCT_ALIGNMENT(s) sizeof(void*) ++#endif ++ + enum __Pyx_ImportType_CheckSize { + __Pyx_ImportType_CheckSize_Error = 0, + __Pyx_ImportType_CheckSize_Warn = 1, + __Pyx_ImportType_CheckSize_Ignore = 2 + }; + +-static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); /*proto*/ ++static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize check_size); /*proto*/ + + #endif + +@@ -316,13 +327,15 @@ static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, + #ifndef __PYX_HAVE_RT_ImportType + #define __PYX_HAVE_RT_ImportType + static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, +- size_t size, enum __Pyx_ImportType_CheckSize check_size) ++ size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize check_size) + { + PyObject *result = 0; + char warning[200]; + Py_ssize_t basicsize; ++ Py_ssize_t itemsize; + #ifdef Py_LIMITED_API + PyObject *py_basicsize; ++ PyObject *py_itemsize; + #endif + + result = PyObject_GetAttrString(module, class_name); +@@ -336,6 +349,7 @@ static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, + } + #ifndef Py_LIMITED_API + basicsize = ((PyTypeObject *)result)->tp_basicsize; ++ itemsize = ((PyTypeObject *)result)->tp_itemsize; + #else + py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); + if (!py_basicsize) +@@ -345,8 +359,28 @@ static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, + py_basicsize = 0; + if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) + goto bad; ++ py_itemsize = PyObject_GetAttrString(result, "__itemsize__"); ++ if (!py_itemsize) ++ goto bad; ++ itemsize = PyLong_AsSsize_t(py_itemsize); ++ Py_DECREF(py_itemsize); ++ py_itemsize = 0; ++ if (itemsize == (Py_ssize_t)-1 && PyErr_Occurred()) ++ goto bad; + #endif +- if ((size_t)basicsize < size) { ++ if (itemsize) { ++ // If itemsize is smaller than the alignment the struct can end up with some extra ++ // padding at the end. In this case we need to work out the maximum size that ++ // the padding could be when calculating the range of valid struct sizes. ++ if (size % alignment) { ++ // if this is true we've probably calculated the alignment wrongly ++ // (most likely because alignof isn't available) ++ alignment = size % alignment; ++ } ++ if (itemsize < (Py_ssize_t)alignment) ++ itemsize = (Py_ssize_t)alignment; ++ } ++ if ((size_t)(basicsize + itemsize) < size) { + PyErr_Format(PyExc_ValueError, + "%.200s.%.200s size changed, may indicate binary incompatibility. " + "Expected %zd from C header, got %zd from PyObject", diff --git a/21e64ec206.patch b/21e64ec206.patch new file mode 100644 index 0000000..ac6213c --- /dev/null +++ b/21e64ec206.patch @@ -0,0 +1,25 @@ +From 21e64ec20619d9ac530030a8e0c259912af10407 Mon Sep 17 00:00:00 2001 +From: Matti Picus +Date: Tue, 29 Nov 2022 08:55:55 +0200 +Subject: [PATCH] Disable "py_unicode_strings" test in Py3.12, which removed + the support for it. + +Picked from https://github.com/cython/cython/commit/9d38bf8d620fd09166a5469c76b54f66d7fbd828 +--- + runtests.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/runtests.py b/runtests.py +index 91a0dd2570..cc79a53250 100755 +--- a/runtests.py ++++ b/runtests.py +@@ -429,6 +429,9 @@ def get_openmp_compiler_flags(language): + 'run.pep526_variable_annotations', # typing module + 'run.test_exceptions', # copied from Py3.7+ + ]), ++ (3,11,999): (operator.gt, lambda x: x in ['run.py_unicode_strings', ++ ]), ++ + } + + INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ] diff --git a/3397705da0.patch b/3397705da0.patch new file mode 100644 index 0000000..bf3b68d --- /dev/null +++ b/3397705da0.patch @@ -0,0 +1,34 @@ +From 3397705da036bb2df4a5b8b4bf08dbad7bdb409f Mon Sep 17 00:00:00 2001 +From: Stefan Behnel +Date: Tue, 7 Mar 2023 08:43:06 +0100 +Subject: [PATCH] Stop using PyLong internals and dict versioning in Py3.12 for + 0.29.x (handled differently in master). + +--- + Cython/Utility/ModuleSetupCode.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c +index 33aac2c4a7..e8fe62be00 100644 +--- a/Cython/Utility/ModuleSetupCode.c ++++ b/Cython/Utility/ModuleSetupCode.c +@@ -208,7 +208,8 @@ + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) +- #define CYTHON_USE_PYLONG_INTERNALS 1 ++ // PyLong internals changed in Py3.12. ++ #define CYTHON_USE_PYLONG_INTERNALS (PY_VERSION_HEX < 0x030C00A5) + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 +@@ -252,7 +253,8 @@ + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS +- #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) ++ // The dict version field is now deprecated in Py3.12. ++ #define CYTHON_USE_DICT_VERSIONS ((PY_VERSION_HEX >= 0x030600B1) && (PY_VERSION_HEX < 0x030C00A5)) + #endif + #if PY_VERSION_HEX >= 0x030B00A4 + #undef CYTHON_USE_EXC_INFO_STACK diff --git a/Cython.spec b/Cython.spec index 7af3349..9fd0204 100644 --- a/Cython.spec +++ b/Cython.spec @@ -6,7 +6,7 @@ Name: Cython Version: 0.29.33 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Language for writing Python extension modules License: Apache-2.0 @@ -18,6 +18,17 @@ Source: https://github.com/cython/cython/archive/%{version}/Cython-%{ver # Fixes https://bugzilla.redhat.com/2155090 Patch: emacs-docstring-wrap.patch +# Python 3.12 backports and fixes: +# Stop using PyLong internals and dict versioning in Py3.12 for 0.29.x +Patch: https://github.com/cython/cython/commit/3397705da0.patch +# Allow Py3.12 AttributeError suggestions in doctest output +Patch: https://github.com/cython/cython/commit/d883ccdec1.patch +# Disable "py_unicode_strings" test in Py3.12, which removed the support for it +Patch: https://github.com/cython/cython/commit/21e64ec206.patch +# Account for possible extension type struct padding when calculating the itemsize for the "size changed" check +Patch: https://github.com/cython/cython/commit/15de63e460.patch + + BuildRequires: python3-devel BuildRequires: python3-setuptools @@ -133,6 +144,10 @@ cp -p cython-mode-init.el cython-mode-init.elc %{buildroot}%{_emacs_sitestartdir %changelog +* Wed Mar 01 2023 Miro Hrončok - 0.29.33-2 +- Make Cython work with Python 3.12.0a5 +- Fixes: rhbz#2172822 + * Fri Feb 17 2023 Miro Hrončok - 0.29.33-1 - Update to 0.29.33 - Fix test failures with NumPy 1.24 diff --git a/d883ccdec1.patch b/d883ccdec1.patch new file mode 100644 index 0000000..2a47a3b --- /dev/null +++ b/d883ccdec1.patch @@ -0,0 +1,119 @@ +From d883ccdec11dabc41e43e98ff4e12da5649e6316 Mon Sep 17 00:00:00 2001 +From: Stefan Behnel +Date: Tue, 7 Mar 2023 09:02:53 +0100 +Subject: [PATCH] Allow Py3.12 AttributeError suggestions in doctest output. + +--- + tests/run/special_methods_T561.pyx | 12 +++---- + tests/run/special_methods_T561_py3.pyx | 43 ++++++++++++-------------- + 2 files changed, 26 insertions(+), 29 deletions(-) + +diff --git a/tests/run/special_methods_T561.pyx b/tests/run/special_methods_T561.pyx +index e5d1ec5bce..1c5f7ceb10 100644 +--- a/tests/run/special_methods_T561.pyx ++++ b/tests/run/special_methods_T561.pyx +@@ -49,10 +49,10 @@ __doc__ = u""" + >>> g01 = object.__getattribute__(GetAttr(), '__getattribute__') + >>> g01('attr') + GetAttr getattr 'attr' +- >>> g10 = object.__getattribute__(GetAttribute(), '__getattr__') ++ >>> g10 = object.__getattribute__(GetAttribute(), '__getattr__') # doctest: +ELLIPSIS + Traceback (most recent call last): + ... +- AttributeError: 'special_methods_T561.GetAttribute' object has no attribute '__getattr__' ++ AttributeError: 'special_methods_T561.GetAttribute' object has no attribute '__getattr__'... + >>> g11 = object.__getattribute__(GetAttribute(), '__getattribute__') + >>> g11('attr') + GetAttribute getattribute 'attr' +@@ -62,15 +62,15 @@ __doc__ = u""" + >>> sa_setattr('foo', 'bar') + SetAttr setattr 'foo' 'bar' + >>> sa_delattr = SetAttr().__delattr__ +- >>> sa_delattr('foo') ++ >>> sa_delattr('foo') # doctest: +ELLIPSIS + Traceback (most recent call last): + ... +- AttributeError: 'special_methods_T561.SetAttr' object has no attribute 'foo' ++ AttributeError: 'special_methods_T561.SetAttr' object has no attribute 'foo'... + >>> da_setattr = DelAttr().__setattr__ +- >>> da_setattr('foo', 'bar') ++ >>> da_setattr('foo', 'bar') # doctest: +ELLIPSIS + Traceback (most recent call last): + ... +- AttributeError: 'special_methods_T561.DelAttr' object has no attribute 'foo' ++ AttributeError: 'special_methods_T561.DelAttr' object has no attribute 'foo'... + >>> da_delattr = DelAttr().__delattr__ + >>> da_delattr('foo') + DelAttr delattr 'foo' +diff --git a/tests/run/special_methods_T561_py3.pyx b/tests/run/special_methods_T561_py3.pyx +index 9320022549..b766591d86 100644 +--- a/tests/run/special_methods_T561_py3.pyx ++++ b/tests/run/special_methods_T561_py3.pyx +@@ -7,47 +7,44 @@ + __doc__ = u""" + >>> vs0 = VerySpecial(0) + VS __init__ 0 ++ + >>> # Python 3 does not use __cmp__, so any provided __cmp__ method is + >>> # discarded under Python 3. +- >>> vs0_cmp = vs0.__cmp__ ++ >>> vs0_cmp = vs0.__cmp__ # doctest: +ELLIPSIS + Traceback (most recent call last): +- ... +- AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__cmp__' ++ AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__cmp__'... ++ + >>> # Python 3 does not use __div__ or __idiv__, so these methods are + >>> # discarded under Python 3. +- >>> vs0_div = vs0.__div__ ++ >>> vs0_div = vs0.__div__ # doctest: +ELLIPSIS + Traceback (most recent call last): +- ... +- AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__div__' +- >>> vs0_rdiv = vs0.__rdiv__ ++ AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__div__'... ++ >>> vs0_rdiv = vs0.__rdiv__ # doctest: +ELLIPSIS + Traceback (most recent call last): +- ... +- AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__rdiv__' +- >>> vs0_idiv = vs0.__idiv__ ++ AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__rdiv__'... ++ >>> vs0_idiv = vs0.__idiv__ # doctest: +ELLIPSIS + Traceback (most recent call last): +- ... +- AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__idiv__' ++ AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__idiv__'... ++ + >>> # Python 3 does not use __oct__ or __hex__, so these methods are + >>> # discarded under Python 3. +- >>> vs0_oct = vs0.__oct__ ++ >>> vs0_oct = vs0.__oct__ # doctest: +ELLIPSIS + Traceback (most recent call last): +- ... +- AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__oct__' +- >>> vs0_hex = vs0.__hex__ ++ AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__oct__'... ++ >>> vs0_hex = vs0.__hex__ # doctest: +ELLIPSIS + Traceback (most recent call last): +- ... +- AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__hex__' ++ AttributeError: 'special_methods_T561_py3.VerySpecial' object has no attribute '__hex__'... ++ + >>> # Python 3 does not use __long__; if you define __long__ but not + >>> # __int__, the __long__ definition will be used for __int__. +- >>> Ll = Long().__long__ ++ >>> Ll = Long().__long__ # doctest: +ELLIPSIS + Traceback (most recent call last): +- ... +- AttributeError: 'special_methods_T561_py3.Long' object has no attribute '__long__' ++ AttributeError: 'special_methods_T561_py3.Long' object has no attribute '__long__'... + >>> Li = Long().__int__ + >>> Li() + Long __long__ +- >>> # As of Python 3, defining __nonzero__ gives you a __bool__ method +- >>> # instead. ++ ++ >>> # As of Python 3, defining __nonzero__ gives you a __bool__ method instead. + >>> vs0_bool = vs0.__bool__ + >>> vs0_bool() + VS __nonzero__ 0