Python 3.8 compatibility

https://bugzilla.redhat.com/show_bug.cgi?id=1693617
This commit is contained in:
Miro Hrončok 2019-03-28 12:06:27 +01:00
parent 824bcda4e7
commit 524344e564
2 changed files with 140 additions and 1 deletions

136
cffi-python38.patch Normal file
View File

@ -0,0 +1,136 @@
# HG changeset patch
# User Armin Rigo <arigo@tunes.org>
# Date 1552719624 -3600
# Node ID 272b53198be984719f29748f998504d1e0634e21
# Parent ff25b4e68195de3034253a1b35e096f8b616aa73
py3.8 fixes
diff --git a/cffi/_embedding.h b/cffi/_embedding.h
--- a/cffi/_embedding.h
+++ b/cffi/_embedding.h
@@ -169,8 +169,10 @@
global_dict = PyDict_New();
if (global_dict == NULL)
goto error;
- if (PyDict_SetItemString(global_dict, "__builtins__",
- PyThreadState_GET()->interp->builtins) < 0)
+ PyObject *builtins = PyEval_GetBuiltins();
+ if (builtins == NULL)
+ goto error;
+ if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0)
goto error;
x = PyEval_EvalCode(
#if PY_MAJOR_VERSION < 3
@@ -263,23 +265,33 @@
So we use a global variable as a simple spin lock. This global
variable must be from 'libpythonX.Y.so', not from this
cffi-based extension module, because it must be shared from
- different cffi-based extension modules. We choose
+ different cffi-based extension modules.
+
+ In Python < 3.8, we choose
_PyParser_TokenNames[0] as a completely arbitrary pointer value
that is never written to. The default is to point to the
string "ENDMARKER". We change it temporarily to point to the
next character in that string. (Yes, I know it's REALLY
obscure.)
+
+ In Python >= 3.8, this string array is no longer writable, so
+ instead we pick PyCapsuleType.tp_version_tag. We can't change
+ Python < 3.8 because someone might use a mixture of cffi
+ embedded modules, some of which were compiled before this file
+ changed.
*/
#ifdef WITH_THREAD
+# if PY_VERSION_HEX < 0x03080000
char *volatile *lock = (char *volatile *)_PyParser_TokenNames;
- char *old_value;
+ char *old_value, *locked_value;
while (1) { /* spin loop */
old_value = *lock;
+ locked_value = old_value + 1;
if (old_value[0] == 'E') {
assert(old_value[1] == 'N');
- if (cffi_compare_and_swap(lock, old_value, old_value + 1))
+ if (cffi_compare_and_swap(lock, old_value, locked_value))
break;
}
else {
@@ -290,6 +302,27 @@
this is only run at start-up anyway. */
}
}
+# else
+ int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag;
+ int old_value, locked_value;
+ assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG));
+
+ while (1) { /* spin loop */
+ old_value = *lock;
+ locked_value = -42;
+ if (old_value == 0) {
+ if (cffi_compare_and_swap(lock, old_value, locked_value))
+ break;
+ }
+ else {
+ assert(old_value == locked_value);
+ /* should ideally do a spin loop instruction here, but
+ hard to do it portably and doesn't really matter I
+ think: PyEval_InitThreads() should be very fast, and
+ this is only run at start-up anyway. */
+ }
+ }
+# endif
#endif
/* call Py_InitializeEx() */
@@ -306,7 +339,7 @@
#ifdef WITH_THREAD
/* release the lock */
- while (!cffi_compare_and_swap(lock, old_value + 1, old_value))
+ while (!cffi_compare_and_swap(lock, locked_value, old_value))
;
#endif
diff --git a/testing/cffi0/test_verify.py b/testing/cffi0/test_verify.py
--- a/testing/cffi0/test_verify.py
+++ b/testing/cffi0/test_verify.py
@@ -20,7 +20,8 @@
extra_compile_args.append('-Qunused-arguments')
else:
# assume a standard gcc
- extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
+ extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion',
+ '-Wno-unused-parameter']
class FFI(FFI):
def verify(self, *args, **kwds):
diff --git a/testing/cffi1/test_verify1.py b/testing/cffi1/test_verify1.py
--- a/testing/cffi1/test_verify1.py
+++ b/testing/cffi1/test_verify1.py
@@ -22,7 +22,8 @@
extra_compile_args.append('-Qunused-arguments')
else:
# assume a standard gcc
- extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
+ extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion',
+ '-Wno-unused-parameter']
class FFI(FFI):
error = _cffi_backend.FFI.error
diff --git a/testing/embedding/test_basic.py b/testing/embedding/test_basic.py
--- a/testing/embedding/test_basic.py
+++ b/testing/embedding/test_basic.py
@@ -172,7 +172,8 @@
result = popen.stdout.read()
err = popen.wait()
if err:
- raise OSError("%r failed with exit code %r" % (name, err))
+ raise OSError("%r failed with exit code %r" % (
+ os.path.join(path, executable_name), err))
return result

View File

@ -6,6 +6,9 @@ License: MIT
URL: https://cffi.readthedocs.org/
Source0: %{pypi_source cffi}
# https://bugzilla.redhat.com/show_bug.cgi?id=1693617
Patch0: cffi-python38.patch
BuildRequires: libffi-devel
BuildRequires: gcc
@ -58,7 +61,7 @@ BuildArch: noarch
Documentation for CFFI, the Foreign Function Interface for Python.
%prep
%autosetup -n cffi-%{version}
%autosetup -p1 -n cffi-%{version}
%build
%py2_build