diff --git a/.gitignore b/.gitignore index 9befacc..36ea050 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/cffi-1.13.2.tar.gz +cffi-1.16.0.tar.gz diff --git a/.python-cffi.metadata b/.python-cffi.metadata deleted file mode 100644 index 3634e63..0000000 --- a/.python-cffi.metadata +++ /dev/null @@ -1 +0,0 @@ -ad94c1b64570ec3016a945d4b226d527de81f9b9 SOURCES/cffi-1.13.2.tar.gz diff --git a/364621f848.patch b/364621f848.patch new file mode 100644 index 0000000..7f95352 --- /dev/null +++ b/364621f848.patch @@ -0,0 +1,266 @@ +From 364621f8489d85c29b26fa5e754aaf2a5f8279fe Mon Sep 17 00:00:00 2001 +From: Matt Davis +Date: Mon, 16 Oct 2023 17:53:28 -0700 +Subject: [PATCH] update unraisable tests to use sys.unraisablehook + +* assert shape of calls to unraisablehook and sanity check traceback contents instead of (varying) stderr output from default unraisablehook impl +--- + src/c/test_c.py | 217 +++++++++++++++--------------------------------- + 1 file changed, 69 insertions(+), 148 deletions(-) + +diff --git a/src/c/test_c.py b/src/c/test_c.py +index 1cdab10f..10cc35cf 100644 +--- a/src/c/test_c.py ++++ b/src/c/test_c.py +@@ -1,5 +1,12 @@ ++from __future__ import annotations ++ ++import contextlib ++import traceback ++import unittest.mock ++ + import pytest + import sys ++import typing as t + + is_musl = False + if sys.platform == 'linux': +@@ -1337,27 +1344,37 @@ def cb(n): + e = pytest.raises(TypeError, f) + assert str(e.value) == "'int(*)(int)' expects 1 arguments, got 0" + ++@contextlib.contextmanager ++def _assert_unraisable(error_type: type[Exception] | None, message: str = '', traceback_tokens: list[str] | None = None): ++ """Assert that a given sys.unraisablehook interaction occurred (or did not occur, if error_type is None) while this context was active""" ++ raised_errors: list[Exception] = [] ++ raised_traceback: str = '' ++ ++ # sys.unraisablehook is called more than once for chained exceptions; accumulate the errors and tracebacks for inspection ++ def _capture_unraisable_hook(ur_args): ++ nonlocal raised_traceback ++ raised_errors.append(ur_args.exc_value) ++ ++ # NB: need to use the old etype/value/tb form until 3.10 is the minimum ++ raised_traceback += (ur_args.err_msg or '' + '\n') + ''.join(traceback.format_exception(None, ur_args.exc_value, ur_args.exc_traceback)) ++ ++ ++ with pytest.MonkeyPatch.context() as mp: ++ mp.setattr(sys, 'unraisablehook', _capture_unraisable_hook) ++ yield ++ ++ if error_type is None: ++ assert not raised_errors ++ assert not raised_traceback ++ return ++ ++ assert any(type(raised_error) is error_type for raised_error in raised_errors) ++ assert any(message in str(raised_error) for raised_error in raised_errors) ++ for t in traceback_tokens or []: ++ assert t in raised_traceback ++ ++ + def test_callback_exception(): +- try: +- import cStringIO +- except ImportError: +- import io as cStringIO # Python 3 +- import linecache +- def matches(istr, ipattern, ipattern38, ipattern311=None): +- if sys.version_info >= (3, 8): +- ipattern = ipattern38 +- if sys.version_info >= (3, 11): +- ipattern = ipattern311 or ipattern38 +- str, pattern = istr, ipattern +- while '$' in pattern: +- i = pattern.index('$') +- assert str[:i] == pattern[:i] +- j = str.find(pattern[i+1], i) +- assert i + 1 <= j <= str.find('\n', i) +- str = str[j:] +- pattern = pattern[i+1:] +- assert str == pattern +- return True + def check_value(x): + if x == 10000: + raise ValueError(42) +@@ -1366,148 +1383,52 @@ def Zcb1(x): + return x * 3 + BShort = new_primitive_type("short") + BFunc = new_function_type((BShort,), BShort, False) ++ + f = callback(BFunc, Zcb1, -42) +- # + seen = [] + oops_result = None + def oops(*args): + seen.append(args) + return oops_result + ff = callback(BFunc, Zcb1, -42, oops) +- # +- orig_stderr = sys.stderr +- orig_getline = linecache.getline +- try: +- linecache.getline = lambda *args: 'LINE' # hack: speed up PyPy tests +- sys.stderr = cStringIO.StringIO() +- if hasattr(sys, '__unraisablehook__'): # work around pytest +- sys.unraisablehook = sys.__unraisablehook__ # on recent CPythons ++ with _assert_unraisable(None): + assert f(100) == 300 +- assert sys.stderr.getvalue() == '' ++ with _assert_unraisable(ValueError, '42', ['in Zcb1', 'in check_value']): + assert f(10000) == -42 +- assert matches(sys.stderr.getvalue(), """\ +-From cffi callback : +-Traceback (most recent call last): +- File "$", line $, in Zcb1 +- $ +- File "$", line $, in check_value +- $ +-ValueError: 42 +-""", """\ +-Exception ignored from cffi callback : +-Traceback (most recent call last): +- File "$", line $, in Zcb1 +- $ +- File "$", line $, in check_value +- $ +-ValueError: 42 +-""") +- sys.stderr = cStringIO.StringIO() +- bigvalue = 20000 ++ ++ bigvalue = 20000 ++ with _assert_unraisable(OverflowError, "integer 60000 does not fit 'short'", ['callback', 'Zcb1']): + assert f(bigvalue) == -42 +- assert matches(sys.stderr.getvalue(), """\ +-From cffi callback : +-Trying to convert the result back to C: +-OverflowError: integer 60000 does not fit 'short' +-""", """\ +-Exception ignored from cffi callback , trying to convert the result back to C: +-Traceback (most recent call last): +- File "$", line $, in test_callback_exception +- $ +-OverflowError: integer 60000 does not fit 'short' +-""") +- sys.stderr = cStringIO.StringIO() +- bigvalue = 20000 +- assert len(seen) == 0 ++ assert len(seen) == 0 ++ ++ with _assert_unraisable(None): + assert ff(bigvalue) == -42 +- assert sys.stderr.getvalue() == "" +- assert len(seen) == 1 +- exc, val, tb = seen[0] +- assert exc is OverflowError +- assert str(val) == "integer 60000 does not fit 'short'" +- # +- sys.stderr = cStringIO.StringIO() +- bigvalue = 20000 +- del seen[:] +- oops_result = 81 ++ assert len(seen) == 1 ++ exc, val, tb = seen[0] ++ assert exc is OverflowError ++ assert str(val) == "integer 60000 does not fit 'short'" ++ ++ del seen[:] ++ oops_result = 81 ++ with _assert_unraisable(None): + assert ff(bigvalue) == 81 +- oops_result = None +- assert sys.stderr.getvalue() == "" +- assert len(seen) == 1 +- exc, val, tb = seen[0] +- assert exc is OverflowError +- assert str(val) == "integer 60000 does not fit 'short'" +- # +- sys.stderr = cStringIO.StringIO() +- bigvalue = 20000 +- del seen[:] +- oops_result = "xy" # not None and not an int! ++ ++ assert len(seen) == 1 ++ exc, val, tb = seen[0] ++ assert exc is OverflowError ++ assert str(val) == "integer 60000 does not fit 'short'" ++ ++ del seen[:] ++ oops_result = "xy" # not None and not an int! ++ ++ with _assert_unraisable(TypeError, "an integer is required", ["integer 60000 does not fit 'short'"]): + assert ff(bigvalue) == -42 +- oops_result = None +- assert matches(sys.stderr.getvalue(), """\ +-From cffi callback : +-Trying to convert the result back to C: +-OverflowError: integer 60000 does not fit 'short' +- +-During the call to 'onerror', another exception occurred: +- +-TypeError: $integer$ +-""", """\ +-Exception ignored from cffi callback , trying to convert the result back to C: +-Traceback (most recent call last): +- File "$", line $, in test_callback_exception +- $ +-OverflowError: integer 60000 does not fit 'short' +-Exception ignored during handling of the above exception by 'onerror': +-Traceback (most recent call last): +- File "$", line $, in test_callback_exception +- $ +-TypeError: $integer$ +-""") +- # +- sys.stderr = cStringIO.StringIO() +- seen = "not a list" # this makes the oops() function crash ++ ++ seen = "not a list" # this makes the oops() function crash ++ oops_result = None ++ with _assert_unraisable(AttributeError, "'str' object has no attribute 'append", ['Zcb1', 'ff', 'oops']): + assert ff(bigvalue) == -42 +- # the $ after the AttributeError message are for the suggestions that +- # will be added in Python 3.10 +- assert matches(sys.stderr.getvalue(), """\ +-From cffi callback : +-Trying to convert the result back to C: +-OverflowError: integer 60000 does not fit 'short' +- +-During the call to 'onerror', another exception occurred: +- +-Traceback (most recent call last): +- File "$", line $, in oops +- $ +-AttributeError: 'str' object has no attribute 'append$ +-""", """\ +-Exception ignored from cffi callback , trying to convert the result back to C: +-Traceback (most recent call last): +- File "$", line $, in test_callback_exception +- $ +-OverflowError: integer 60000 does not fit 'short' +-Exception ignored during handling of the above exception by 'onerror': +-Traceback (most recent call last): +- File "$", line $, in oops +- $ +-AttributeError: 'str' object has no attribute 'append$ +-""", """\ +-Exception ignored from cffi callback , trying to convert the result back to C: +-Traceback (most recent call last): +- File "$", line $, in test_callback_exception +- $ +-OverflowError: integer 60000 does not fit 'short' +-Exception ignored during handling of the above exception by 'onerror': +-Traceback (most recent call last): +- File "$", line $, in oops +- $ +- $ +-AttributeError: 'str' object has no attribute 'append$ +-""") +- finally: +- sys.stderr = orig_stderr +- linecache.getline = orig_getline ++ + + def test_callback_return_type(): + for rettype in ["signed char", "short", "int", "long", "long long", diff --git a/49127c6929.patch b/49127c6929.patch new file mode 100644 index 0000000..90767c3 --- /dev/null +++ b/49127c6929.patch @@ -0,0 +1,30 @@ +From 49127c6929bfc7186fbfd3819dd5e058ad888de4 Mon Sep 17 00:00:00 2001 +From: Victor Stinner +Date: Thu, 16 Nov 2023 17:26:12 +0100 +Subject: [PATCH] Use PyErr_FormatUnraisable() on Python 3.13 (#34) + +Use the new public PyErr_FormatUnraisable() on Python 3.13. + +The private _PyErr_WriteUnraisableMsg() function was removed in +Python 3.13: +https://github.com/python/cpython/pull/111643 +--- + src/c/_cffi_backend.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c +index 76ed8f09..5e284e00 100644 +--- a/src/c/_cffi_backend.c ++++ b/src/c/_cffi_backend.c +@@ -6118,7 +6118,11 @@ static void _my_PyErr_WriteUnraisable(PyObject *t, PyObject *v, PyObject *tb, + + PyErr_Restore(t, v, tb); + if (s != NULL) { ++#if PY_VERSION_HEX >= 0x030D0000 ++ PyErr_FormatUnraisable("Exception ignored %S", s); ++#else + _PyErr_WriteUnraisableMsg(PyText_AS_UTF8(s), NULL); ++#endif + Py_DECREF(s); + } + else diff --git a/SPECS/python-cffi.spec b/python-cffi.spec similarity index 58% rename from SPECS/python-cffi.spec rename to python-cffi.spec index c373fbf..091fac1 100644 --- a/SPECS/python-cffi.spec +++ b/python-cffi.spec @@ -1,91 +1,206 @@ -%bcond_with docs +## START: Set by rpmautospec +## (rpmautospec version 0.6.5) +## RPMAUTOSPEC: autorelease, autochangelog +%define autorelease(e:s:pb:n) %{?-p:0.}%{lua: + release_number = 7; + base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}")); + print(release_number + base_release_number - 1); +}%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}} +## END: Set by rpmautospec Name: python-cffi -Version: 1.13.2 -Release: 3%{?dist} +Version: 1.16.0 +Release: %autorelease Summary: Foreign Function Interface for Python to call C code -License: MIT -URL: https://cffi.readthedocs.org/ -Source0: %{pypi_source cffi} +# cffi is MIT +# cffi/_imp_emulation.py has bits copied from CPython (PSF-2.0) +License: MIT AND PSF-2.0 +URL: https://github.com/python-cffi/cffi +Source: %{url}/archive/v%{version}/cffi-%{version}.tar.gz -# Exclude i686 arch. Due to a modularity issue it's being added to the -# x86_64 compose of CRB, but we don't want to ship it at all. -# See: https://projects.engineering.redhat.com/browse/RCM-72605 -ExcludeArch: i686 +# Use PyErr_FormatUnraisable() on Python 3.13+ +# The private _PyErr_WriteUnraisableMsg() function was removed. +# Merged upstream. +Patch: https://github.com/python-cffi/cffi/commit/49127c6929.patch +# Update unraisable tests to use sys.unraisablehook (for Python 3.13+ compatibility) +# From https://github.com/python-cffi/cffi/pull/24 -- proposed upstream. +Patch: https://github.com/python-cffi/cffi/commit/364621f848.patch + +BuildRequires: python3-devel +BuildRequires: python3-pytest +BuildRequires: make BuildRequires: libffi-devel BuildRequires: gcc # For tests: BuildRequires: gcc-c++ -%?python_enable_dependency_generator - %description Foreign Function Interface for Python, providing a convenient and reliable way of calling existing C code from Python. The interface is based on LuaJIT’s FFI. -%package -n python%{python3_pkgversion}-cffi -Summary: Foreign Function Interface for Python 3 to call C code -%if %{with docs} -BuildRequires: python%{python3_pkgversion}-sphinx -%endif -BuildRequires: python%{python3_pkgversion}-pytest -BuildRequires: python%{python3_pkgversion}-devel -BuildRequires: python%{python3_pkgversion}-setuptools -BuildRequires: python%{python3_pkgversion}-pycparser -BuildRequires: python%{python3_pkgversion}-rpm-macros -%{?python_provide:%python_provide python%{python3_pkgversion}-cffi} -%description -n python%{python3_pkgversion}-cffi +%package -n python3-cffi +Summary: %{summary} + +%description -n python3-cffi Foreign Function Interface for Python, providing a convenient and reliable way of calling existing C code from Python. The interface is based on LuaJIT’s FFI. + %package doc Summary: Documentation for CFFI BuildArch: noarch +BuildRequires: python3-sphinx %description doc Documentation for CFFI, the Foreign Function Interface for Python. + %prep %autosetup -p1 -n cffi-%{version} -%build -%py3_build -%if %{with docs} +%generate_buildrequires +%pyproject_buildrequires + + +%build +%pyproject_wheel + cd doc -make SPHINXBUILD=sphinx-build-3 html +make html rm build/html/.buildinfo -%endif + %install -%py3_install +%pyproject_install +%pyproject_save_files _cffi_backend cffi + %check -PYTHONPATH=%{buildroot}%{python3_sitearch} %{__python3} -m pytest c/ testing/ +%pytest -%files -n python%{python3_pkgversion}-cffi -%doc PKG-INFO -%license LICENSE -%{python3_sitearch}/cffi/ -%{python3_sitearch}/_cffi_backend.*.so -%{python3_sitearch}/cffi-%{version}-py%{python3_version}.egg-info/ -%if %{with docs} +%files -n python3-cffi -f %{pyproject_files} +%doc README.md + %files doc +%license LICENSE %doc doc/build/html -%endif + %changelog -* Fri Dec 13 2019 Tomas Orsava - 1.13.2-3 -- Exclude unsupported i686 arch +## START: Generated by rpmautospec +* Tue Oct 29 2024 Troy Dawson - 1.16.0-7 +- Bump release for October 2024 mass rebuild: -* Wed Nov 20 2019 Lumír Balhar - 1.13.2-2 -- Adjusted for Python 3.8 module in RHEL 8 +* Fri Jun 28 2024 Sudhir Menon - 1.16.0-6 +- Added gating.yaml and tests for python-cffi + +* Mon Jun 24 2024 Troy Dawson - 1.16.0-5 +- Bump release for June 2024 mass rebuild + +* Fri Jan 26 2024 Fedora Release Engineering - 1.16.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Mon Jan 22 2024 Fedora Release Engineering - 1.16.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Mon Nov 20 2023 Miro Hrončok - 1.16.0-2 +- Python 3.13.0a1+ compatibility + +* Mon Oct 02 2023 Miro Hrončok - 1.16.0-1 +- Update to 1.16.0 +- Fixes: rhbz#2240695 + +* Fri Jul 21 2023 Fedora Release Engineering - 1.15.1-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Wed Jun 14 2023 Python Maint - 1.15.1-5 +- Rebuilt for Python 3.12 + +* Fri Jan 20 2023 Fedora Release Engineering - 1.15.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Mon Nov 14 2022 Miro Hrončok - 1.15.1-3 +- Fix build with pytest 7.2 +- Fixes: rhbz#2142063 + +* Fri Jul 22 2022 Fedora Release Engineering - 1.15.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Fri Jul 15 2022 Miro Hrončok - 1.15.1-1 +- Adjust tests for a last minute Python 3.11 change in the traceback format + +* Mon Jul 11 2022 Lumír Balhar - 1.15.1-0 +- Update to 1.15.1 +Resolves: rhbz#2102824 + +* Mon Jun 13 2022 Python Maint - 1.15.0-6 +- Rebuilt for Python 3.11 + +* Wed Mar 30 2022 Miro Hrončok - 1.15.0-5 +- Fix alignment issue on ppc64le +- Fixes: rhbz#2046865 + +* Wed Feb 02 2022 Tomáš Hrnčiar - 1.15.0-4 +- Backport patch to fix compatibility with Python 3.11 +- Fixes: rhbz#2040165 + +* Fri Jan 21 2022 Fedora Release Engineering - 1.15.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Sat Jan 08 2022 Miro Hrončok - 1.15.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Changes/LIBFFI34 + +* Tue Dec 21 2021 Lumír Balhar - 1.15.0-1 +- Update to 1.15.0 +Resolves: rhbz#2013760 + +* Thu Oct 07 2021 Tomáš Hrnčiar - 1.15.0~rc2-1 +- Update to 1.15.0rc2 +Resolves: rhbz#2007006 + +* Fri Jul 23 2021 Fedora Release Engineering - 1.14.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Fri Jul 09 2021 Lumír Balhar - 1.14.6-1 +- Update to 1.14.6 +Resolves: rhbz#1980622 + +* Wed Jun 02 2021 Python Maint - 1.14.5-2 +- Rebuilt for Python 3.10 + +* Fri Feb 12 2021 Lumír Balhar - 1.14.5-1 +- Update to 1.14.5 +Resolves: rhbz#1927933 + +* Wed Jan 27 2021 Fedora Release Engineering - 1.14.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Thu Nov 19 2020 Joel Capitao - 1.14.3-1 +- Update to 1.14.3 + +* Tue Sep 08 2020 Lumír Balhar - 1.14.2-1 +- Update to 1.14.2 (#1869032) + +* Fri Aug 14 2020 Miro Hrončok - 1.14.1-1 +- Update to 1.14.1 +- Fixes: rhbz#1860698 +- Fixes: rhbz#1865276 + +* Sat May 23 2020 Miro Hrončok - 1.14.0-2 +- Rebuilt for Python 3.9 + +* Mon Feb 10 2020 Lumír Balhar - 1.14.0 +- Update to 1.14.0 (#1800646) + +* Thu Jan 30 2020 Fedora Release Engineering - 1.13.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild * Mon Nov 18 2019 Lumír Balhar - 1.13.2-1 - Update to 1.13.2 (#1768219) @@ -273,3 +388,5 @@ PYTHONPATH=%{buildroot}%{python3_sitearch} %{__python3} -m pytest c/ testing/ * Sun Jul 21 2013 Eric Smith 0.6-1 - initial version + +## END: Generated by rpmautospec diff --git a/sources b/sources new file mode 100644 index 0000000..44dac8e --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (cffi-1.16.0.tar.gz) = 2115f4d2431f36b18494182d2abb378a750c970dfdf083cfc287b004e52830efe703f07f71a17c89060b47eaa3b52e7b2390017d1980eb39695bdaf31bac3bb5