diff --git a/tests/.fmf/version b/.fmf/version similarity index 100% rename from tests/.fmf/version rename to .fmf/version diff --git a/.gitignore b/.gitignore index 1107137..67901af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /*.tar.* +/*-jit_stencils.h /*.src.rpm /results_python3* diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index f18a48e..b35197d 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -30,10 +30,10 @@ Co-authored-by: Lumír Balhar 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/Lib/site.py b/Lib/site.py -index 9da8b6724e..b53dd21d51 100644 +index aeb7c6cfc7..86f9ae9e76 100644 --- a/Lib/site.py +++ b/Lib/site.py -@@ -420,8 +420,15 @@ def getsitepackages(prefixes=None): +@@ -421,8 +421,15 @@ def getsitepackages(prefixes=None): return sitepackages def addsitepackages(known_paths, prefixes=None): @@ -51,7 +51,7 @@ index 9da8b6724e..b53dd21d51 100644 if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py -index 18e6b8d25e..42df12fad4 100644 +index faf8273bd0..d7667bbc77 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -106,6 +106,12 @@ @@ -130,10 +130,10 @@ index 18e6b8d25e..42df12fad4 100644 # On Windows we want to substitute 'lib' for schemes rather # than the native value (without modifying vars, in case it diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py -index cc11eade2e..b4f8aabaef 100644 +index 1fe4b6849f..e0cb3ec23a 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py -@@ -131,8 +131,19 @@ def test_get_path(self): +@@ -132,8 +132,19 @@ def test_get_path(self): for scheme in _INSTALL_SCHEMES: for name in _INSTALL_SCHEMES[scheme]: expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars) @@ -154,7 +154,7 @@ index cc11eade2e..b4f8aabaef 100644 os.path.normpath(expected), ) -@@ -387,7 +398,7 @@ def test_get_config_h_filename(self): +@@ -397,7 +408,7 @@ def test_get_config_h_filename(self): self.assertTrue(os.path.isfile(config_h), config_h) def test_get_scheme_names(self): @@ -163,7 +163,7 @@ index cc11eade2e..b4f8aabaef 100644 if HAS_USER_BASE: wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) -@@ -399,6 +410,8 @@ def test_symlink(self): # Issue 7880 +@@ -409,6 +420,8 @@ def test_symlink(self): # Issue 7880 cmd = "-c", "import sysconfig; print(sysconfig.get_platform())" self.assertEqual(py.call_real(*cmd), py.call_link(*cmd)) diff --git a/00454-invoke-regen-token-rst-with-rstfile-as-an-argument.patch b/00454-invoke-regen-token-rst-with-rstfile-as-an-argument.patch deleted file mode 100644 index 250072a..0000000 --- a/00454-invoke-regen-token-rst-with-rstfile-as-an-argument.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Karolina Surma -Date: Wed, 9 Apr 2025 10:47:48 +0200 -Subject: 00454: Invoke regen-token rst with rstfile as an argument - -Proposed upstream: https://github.com/python/cpython/pull/132304 ---- - Makefile.pre.in | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/Makefile.pre.in b/Makefile.pre.in -index e10c78d640..5dfde4efcb 100644 ---- a/Makefile.pre.in -+++ b/Makefile.pre.in -@@ -1960,7 +1960,8 @@ regen-token: - # using Tools/build/generate_token.py - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_token.py rst \ - $(srcdir)/Grammar/Tokens \ -- $(srcdir)/Doc/library/token-list.inc -+ $(srcdir)/Doc/library/token-list.inc \ -+ $(srcdir)/Doc/library/token.rst - # Regenerate Include/internal/pycore_token.h from Grammar/Tokens - # using Tools/build/generate_token.py - $(PYTHON_FOR_REGEN) $(srcdir)/Tools/build/generate_token.py h \ diff --git a/00456-find-the-correct-group-name-in-test_group_no_follow_symlinks.patch b/00456-find-the-correct-group-name-in-test_group_no_follow_symlinks.patch deleted file mode 100644 index 1577b85..0000000 --- a/00456-find-the-correct-group-name-in-test_group_no_follow_symlinks.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Karolina Surma -Date: Thu, 10 Apr 2025 13:46:25 +0200 -Subject: 00456: Find the correct group name in test_group_no_follow_symlinks - -Reported: https://github.com/python/cpython/issues/132356 -Fix proposed upstream: https://github.com/python/cpython/pull/132357 ---- - Lib/test/test_pathlib/test_pathlib.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py -index b1fcc5f6f0..3cfffc6311 100644 ---- a/Lib/test/test_pathlib/test_pathlib.py -+++ b/Lib/test/test_pathlib/test_pathlib.py -@@ -2065,7 +2065,7 @@ def test_group_no_follow_symlinks(self): - os.chown(link, -1, gid_2, follow_symlinks=False) - - expected_gid = link.stat(follow_symlinks=False).st_gid -- expected_name = self._get_pw_name_or_skip_test(expected_gid) -+ expected_name = self._get_gr_name_or_skip_test(expected_gid) - - self.assertEqual(expected_gid, gid_2) - self.assertEqual(expected_name, link.group(follow_symlinks=False)) diff --git a/00459-apply-intel-control-flow-technology-for-x86-64.patch b/00459-apply-intel-control-flow-technology-for-x86-64.patch deleted file mode 100644 index c6ed738..0000000 --- a/00459-apply-intel-control-flow-technology-for-x86-64.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Charalampos Stratakis -Date: Wed, 8 Jan 2025 04:58:22 +0100 -Subject: 00459: Apply Intel Control-flow Technology for x86-64 - -Required for mitigation against return-oriented programming (ROP) and Call or Jump Oriented Programming (COP/JOP) attacks - -Proposed upstream: https://github.com/python/cpython/pull/128606 - -See also: https://sourceware.org/annobin/annobin.html/Test-cf-protection.html ---- - Python/asm_trampoline.S | 22 ++++++++++++++++++++++ - Python/perf_jit_trampoline.c | 4 ++++ - 2 files changed, 26 insertions(+) - -diff --git a/Python/asm_trampoline.S b/Python/asm_trampoline.S -index 0a3265dfee..616752459b 100644 ---- a/Python/asm_trampoline.S -+++ b/Python/asm_trampoline.S -@@ -9,6 +9,9 @@ - # } - _Py_trampoline_func_start: - #ifdef __x86_64__ -+#if defined(__CET__) && (__CET__ & 1) -+ endbr64 -+#endif - sub $8, %rsp - call *%rcx - add $8, %rsp -@@ -34,3 +37,22 @@ _Py_trampoline_func_start: - .globl _Py_trampoline_func_end - _Py_trampoline_func_end: - .section .note.GNU-stack,"",@progbits -+# Note for indicating the assembly code supports CET -+#if defined(__x86_64__) && defined(__CET__) && (__CET__ & 1) -+ .section .note.gnu.property,"a" -+ .align 8 -+ .long 1f - 0f -+ .long 4f - 1f -+ .long 5 -+0: -+ .string "GNU" -+1: -+ .align 8 -+ .long 0xc0000002 -+ .long 3f - 2f -+2: -+ .long 0x3 -+3: -+ .align 8 -+4: -+#endif // __x86_64__ -diff --git a/Python/perf_jit_trampoline.c b/Python/perf_jit_trampoline.c -index 1211e0e9f1..da9f887769 100644 ---- a/Python/perf_jit_trampoline.c -+++ b/Python/perf_jit_trampoline.c -@@ -473,7 +473,11 @@ elf_init_ehframe(ELFObjectContext* ctx) - DWRF_U8(0); /* Augmentation data. */ - /* Registers saved in CFRAME. */ - #ifdef __x86_64__ -+# if defined(__CET__) && (__CET__ & 1) -+ DWRF_U8(DWRF_CFA_advance_loc | 8); -+# else - DWRF_U8(DWRF_CFA_advance_loc | 4); -+# endif - DWRF_U8(DWRF_CFA_def_cfa_offset); DWRF_UV(16); - DWRF_U8(DWRF_CFA_advance_loc | 6); - DWRF_U8(DWRF_CFA_def_cfa_offset); DWRF_UV(8); diff --git a/00460-gh-132415-update-vendored-setuptools-in-lib-test-wheeldata.patch b/00460-gh-132415-update-vendored-setuptools-in-lib-test-wheeldata.patch deleted file mode 100644 index 50de614..0000000 --- a/00460-gh-132415-update-vendored-setuptools-in-lib-test-wheeldata.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> -Date: Fri, 25 Apr 2025 00:46:20 +0100 -Subject: 00460: gh-132415: Update vendored setuptools in - ``Lib/test/wheeldata`` - -(cherry picked from commit c9f3f5b4ed52d7bed6073ffa39717ece47202558) -(actual changes in .whl files removed to make this patch smaller) - -gh-127906: Add missing sys import to test_cppext - -(cherry picked from commit 9cba14881b371b1e95d57877896169c4605f9b75) - -Co-Authored-By: Victor Stinner ---- - Lib/test/support/__init__.py | 14 +++++++------- - Lib/test/test_cext/__init__.py | 2 +- - Lib/test/test_cppext/__init__.py | 2 +- - Lib/test/test_cppext/setup.py | 1 + - Lib/test/test_peg_generator/test_c_parser.py | 2 +- - 5 files changed, 11 insertions(+), 10 deletions(-) - -diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py -index 6d670a575b..7f72c689e8 100644 ---- a/Lib/test/support/__init__.py -+++ b/Lib/test/support/__init__.py -@@ -2415,7 +2415,7 @@ def _findwheel(pkgname): - filenames = os.listdir(wheel_dir) - filenames = sorted(filenames, reverse=True) # approximate "newest" first - for filename in filenames: -- # filename is like 'setuptools-67.6.1-py3-none-any.whl' -+ # filename is like 'setuptools-{version}-py3-none-any.whl' - if not filename.endswith(".whl"): - continue - prefix = pkgname + '-' -@@ -2424,16 +2424,16 @@ def _findwheel(pkgname): - raise FileNotFoundError(f"No wheel for {pkgname} found in {wheel_dir}") - - --# Context manager that creates a virtual environment, install setuptools and wheel in it --# and returns the path to the venv directory and the path to the python executable -+# Context manager that creates a virtual environment, install setuptools in it, -+# and returns the paths to the venv directory and the python executable - @contextlib.contextmanager --def setup_venv_with_pip_setuptools_wheel(venv_dir): -- import shlex -+def setup_venv_with_pip_setuptools(venv_dir): - import subprocess - from .os_helper import temp_cwd - - def run_command(cmd): - if verbose: -+ import shlex - print() - print('Run:', ' '.join(map(shlex.quote, cmd))) - subprocess.run(cmd, check=True) -@@ -2457,10 +2457,10 @@ def run_command(cmd): - else: - python = os.path.join(venv, 'bin', python_exe) - -- cmd = [python, '-X', 'dev', -+ cmd = (python, '-X', 'dev', - '-m', 'pip', 'install', - _findwheel('setuptools'), -- _findwheel('wheel')] -+ ) - run_command(cmd) - - yield python -diff --git a/Lib/test/test_cext/__init__.py b/Lib/test/test_cext/__init__.py -index 402a2d04fa..46fde54149 100644 ---- a/Lib/test/test_cext/__init__.py -+++ b/Lib/test/test_cext/__init__.py -@@ -53,7 +53,7 @@ def test_build_limited_c11(self): - - def check_build(self, extension_name, std=None, limited=False): - venv_dir = 'env' -- with support.setup_venv_with_pip_setuptools_wheel(venv_dir) as python_exe: -+ with support.setup_venv_with_pip_setuptools(venv_dir) as python_exe: - self._check_build(extension_name, python_exe, - std=std, limited=limited) - -diff --git a/Lib/test/test_cppext/__init__.py b/Lib/test/test_cppext/__init__.py -index 13f9ea1c56..2b7adac4bc 100644 ---- a/Lib/test/test_cppext/__init__.py -+++ b/Lib/test/test_cppext/__init__.py -@@ -54,7 +54,7 @@ def test_build_limited(self): - - def check_build(self, extension_name, std=None, limited=False): - venv_dir = 'env' -- with support.setup_venv_with_pip_setuptools_wheel(venv_dir) as python_exe: -+ with support.setup_venv_with_pip_setuptools(venv_dir) as python_exe: - self._check_build(extension_name, python_exe, - std=std, limited=limited) - -diff --git a/Lib/test/test_cppext/setup.py b/Lib/test/test_cppext/setup.py -index b30c9e2746..ea1ed64bf7 100644 ---- a/Lib/test/test_cppext/setup.py -+++ b/Lib/test/test_cppext/setup.py -@@ -3,6 +3,7 @@ - import os - import platform - import shlex -+import sys - import sysconfig - from test import support - -diff --git a/Lib/test/test_peg_generator/test_c_parser.py b/Lib/test/test_peg_generator/test_c_parser.py -index 1411e55dd0..1095e7303c 100644 ---- a/Lib/test/test_peg_generator/test_c_parser.py -+++ b/Lib/test/test_peg_generator/test_c_parser.py -@@ -99,7 +99,7 @@ def setUpClass(cls): - cls.addClassCleanup(shutil.rmtree, cls.library_dir) - - with contextlib.ExitStack() as stack: -- python_exe = stack.enter_context(support.setup_venv_with_pip_setuptools_wheel("venv")) -+ python_exe = stack.enter_context(support.setup_venv_with_pip_setuptools("venv")) - sitepackages = subprocess.check_output( - [python_exe, "-c", "import sysconfig; print(sysconfig.get_path('platlib'))"], - text=True, diff --git a/00461-downstream-only-install-wheel-in-test-venvs-when-setuptools-71.patch b/00461-downstream-only-install-wheel-in-test-venvs-when-setuptools-71.patch deleted file mode 100644 index 0689c34..0000000 --- a/00461-downstream-only-install-wheel-in-test-venvs-when-setuptools-71.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= -Date: Fri, 25 Apr 2025 09:33:37 +0200 -Subject: 00461: Downstream only: Install wheel in test venvs when setuptools < - 71 - -This can be removed when Fedora 41 goes EOL (or updates setuptools). ---- - Lib/test/support/__init__.py | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py -index 7f72c689e8..e15f18c47e 100644 ---- a/Lib/test/support/__init__.py -+++ b/Lib/test/support/__init__.py -@@ -2457,9 +2457,16 @@ def run_command(cmd): - else: - python = os.path.join(venv, 'bin', python_exe) - -+ setuptools_whl = _findwheel('setuptools') -+ whl_filename = os.path.basename(setuptools_whl) -+ setuptools_major = int(whl_filename.split('-')[1].split('.')[0]) -+ if setuptools_major >= 71: # we need 70.1+, but that's OK -+ wheels = (setuptools_whl,) -+ else: -+ wheels = (setuptools_whl, _findwheel('wheel')) - cmd = (python, '-X', 'dev', - '-m', 'pip', 'install', -- _findwheel('setuptools'), -+ *wheels, - ) - run_command(cmd) - diff --git a/00466-downstream-only-lower-xml_combined_version-threshold-for-reparse-deferral.patch b/00466-downstream-only-lower-xml_combined_version-threshold-for-reparse-deferral.patch new file mode 100644 index 0000000..43e2056 --- /dev/null +++ b/00466-downstream-only-lower-xml_combined_version-threshold-for-reparse-deferral.patch @@ -0,0 +1,133 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= +Date: Wed, 12 Aug 2026 15:18:39 +0200 +Subject: 00466: Downstream only: Lower XML_COMBINED_VERSION threshold for + reparse deferral + +RHEL 9 expat 2.5.0 has XML_SetReparseDeferralEnabled backported +via the CVE-2023-52425 fix, but XML_COMBINED_VERSION remains 20500. +CPython's #if XML_COMBINED_VERSION >= 20600 guards compile the setter +as a no-op, so SetReparseDeferralEnabled silently does nothing and +GetReparseDeferralEnabled always returns False, even though the expat +library actually supports (and enables) reparse deferral. + +Lower the threshold from 20600 to 20500 so that CPython uses the +backported function. This makes the Python API actually work on RHEL 9 +and fixes test failures (test_reparse_deferral_disabled, +test_flush_reparse_deferral_disabled, test_simple_xml_chunk_*). + +The spec file BuildRequires expat-devel >= 2.5.0-2 to ensure the +backported function is available. +--- + Lib/test/test_pyexpat.py | 6 +++--- + Lib/test/test_sax.py | 4 ++-- + Lib/test/test_xml_etree.py | 4 ++-- + Modules/pyexpat.c | 6 +++--- + 4 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py +index fd3077063b..34f86e2dbd 100644 +--- a/Lib/test/test_pyexpat.py ++++ b/Lib/test/test_pyexpat.py +@@ -1005,7 +1005,7 @@ def test_error_path_no_crash(self): + class ReparseDeferralTest(unittest.TestCase): + def test_getter_setter_round_trip(self): + parser = expat.ParserCreate() +- enabled = (expat.version_info >= (2, 6, 0)) ++ enabled = (expat.version_info >= (2, 5, 0)) + + self.assertIs(parser.GetReparseDeferralEnabled(), enabled) + parser.SetReparseDeferralEnabled(False) +@@ -1014,7 +1014,7 @@ def test_getter_setter_round_trip(self): + self.assertIs(parser.GetReparseDeferralEnabled(), enabled) + + def test_reparse_deferral_enabled(self): +- if expat.version_info < (2, 6, 0): ++ if expat.version_info < (2, 5, 0): + self.skipTest(f'Expat {expat.version_info} does not ' + 'support reparse deferral') + +@@ -1045,7 +1045,7 @@ def start_element(name, _): + + parser = expat.ParserCreate() + parser.StartElementHandler = start_element +- if expat.version_info >= (2, 6, 0): ++ if expat.version_info >= (2, 5, 0): + parser.SetReparseDeferralEnabled(False) + self.assertFalse(parser.GetReparseDeferralEnabled()) + +diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py +index 5c10bcedc6..114f002b0b 100644 +--- a/Lib/test/test_sax.py ++++ b/Lib/test/test_sax.py +@@ -1216,7 +1216,7 @@ def test_expat_incremental_reset(self): + + self.assertEqual(result.getvalue(), start + b"text") + +- @unittest.skipIf(pyexpat.version_info < (2, 6, 0), ++ @unittest.skipIf(pyexpat.version_info < (2, 5, 0), + f'Expat {pyexpat.version_info} does not ' + 'support reparse deferral') + def test_flush_reparse_deferral_enabled(self): +@@ -1250,7 +1250,7 @@ def test_flush_reparse_deferral_disabled(self): + for chunk in (""): + parser.feed(chunk) + +- if pyexpat.version_info >= (2, 6, 0): ++ if pyexpat.version_info >= (2, 5, 0): + parser._parser.SetReparseDeferralEnabled(False) + self.assertEqual(result.getvalue(), start) # i.e. no elements started + +diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py +index 6da7c34dc4..d846ddf4e2 100644 +--- a/Lib/test/test_xml_etree.py ++++ b/Lib/test/test_xml_etree.py +@@ -1803,7 +1803,7 @@ def test_unknown_event(self): + with self.assertRaisesRegex(ValueError, "unknown event 'bogus'"): + ET.XMLPullParser(events=(x.decode() for x in (b'start', b'end', b'bogus'))) + +- @unittest.skipIf(pyexpat.version_info < (2, 6, 0), ++ @unittest.skipIf(pyexpat.version_info < (2, 5, 0), + f'Expat {pyexpat.version_info} does not ' + 'support reparse deferral') + def test_flush_reparse_deferral_enabled(self): +@@ -1833,7 +1833,7 @@ def test_flush_reparse_deferral_disabled(self): + for chunk in (""): + parser.feed(chunk) + +- if pyexpat.version_info >= (2, 6, 0): ++ if pyexpat.version_info >= (2, 5, 0): + if not ET is pyET: + self.skipTest(f'XMLParser.(Get|Set)ReparseDeferralEnabled ' + 'methods not available in C') +diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c +index f9fd7a7a5b..e88b7f16a8 100644 +--- a/Modules/pyexpat.c ++++ b/Modules/pyexpat.c +@@ -814,7 +814,7 @@ pyexpat_xmlparser_SetReparseDeferralEnabled_impl(xmlparseobject *self, + int enabled) + /*[clinic end generated code: output=5ec539e3b63c8c49 input=021eb9e0bafc32c5]*/ + { +-#if XML_COMBINED_VERSION >= 20600 ++#if XML_COMBINED_VERSION >= 20500 + XML_SetReparseDeferralEnabled(self->itself, enabled ? XML_TRUE : XML_FALSE); + self->reparse_deferral_enabled = (bool)enabled; + #endif +@@ -1478,7 +1478,7 @@ newxmlparseobject(pyexpat_state *state, const char *encoding, + self->ns_prefixes = 0; + self->handlers = NULL; + self->intern = Py_XNewRef(intern); +-#if XML_COMBINED_VERSION >= 20600 ++#if XML_COMBINED_VERSION >= 20500 + self->reparse_deferral_enabled = true; + #else + self->reparse_deferral_enabled = false; +@@ -2396,7 +2396,7 @@ pyexpat_exec(PyObject *mod) + #else + capi->SetHashSalt16Bytes = NULL; + #endif +-#if XML_COMBINED_VERSION >= 20600 ++#if XML_COMBINED_VERSION >= 20500 + capi->SetReparseDeferralEnabled = XML_SetReparseDeferralEnabled; + #else + capi->SetReparseDeferralEnabled = NULL; diff --git a/00475-cve-2025-15367.patch b/00475-cve-2025-15367.patch new file mode 100644 index 0000000..71c71c2 --- /dev/null +++ b/00475-cve-2025-15367.patch @@ -0,0 +1,59 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Tue, 20 Jan 2026 14:46:32 -0600 +Subject: 00475: CVE-2025-15367 + +Downstream only: Reject control characters in POP3 commands +--- + Lib/poplib.py | 2 ++ + Lib/test/test_poplib.py | 8 ++++++++ + .../2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst | 1 + + 3 files changed, 11 insertions(+) + create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst + +diff --git a/Lib/poplib.py b/Lib/poplib.py +index 4469bff44b..b97274c5c3 100644 +--- a/Lib/poplib.py ++++ b/Lib/poplib.py +@@ -122,6 +122,8 @@ def _putline(self, line): + def _putcmd(self, line): + if self._debugging: print('*cmd*', repr(line)) + line = bytes(line, self.encoding) ++ if re.search(b'[\x00-\x1F\x7F]', line): ++ raise ValueError('Control characters not allowed in commands') + self._putline(line) + + +diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py +index ef2da97f86..18ca7cb556 100644 +--- a/Lib/test/test_poplib.py ++++ b/Lib/test/test_poplib.py +@@ -17,6 +17,7 @@ + from test.support import threading_helper + from test.support import asynchat + from test.support import asyncore ++from test.support import control_characters_c0 + + + test_support.requires_working_socket(module=True) +@@ -395,6 +396,13 @@ def test_quit(self): + self.assertIsNone(self.client.sock) + self.assertIsNone(self.client.file) + ++ def test_control_characters(self): ++ for c0 in control_characters_c0(): ++ with self.assertRaises(ValueError): ++ self.client.user(f'user{c0}') ++ with self.assertRaises(ValueError): ++ self.client.pass_(f'{c0}pass') ++ + @requires_ssl + def test_stls_capa(self): + capa = self.client.capa() +diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst +new file mode 100644 +index 0000000000..3cde4df3e0 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst +@@ -0,0 +1 @@ ++Reject control characters in POP3 commands. diff --git a/00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-different-python-version.patch b/00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-different-python-version.patch new file mode 100644 index 0000000..1ba9248 --- /dev/null +++ b/00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-different-python-version.patch @@ -0,0 +1,156 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Petr Viktorin +Date: Fri, 6 Feb 2026 10:51:02 +0100 +Subject: 00477: Raise an error when importing stdlib modules compiled for a + different Python version + +This is a downstream workaround "implementing" +https://github.com/python/cpython/pull/137212 - +the mechanism for the check exists in Python 3.15+, where it needs to be +added to the standard library modules. +In Fedora, we need it also in previous Python versions, as we experience +segmentation fault when importing stdlib modules after update while +Python is running. + +_tkinter, _tracemalloc and readline are not calling PyModuleDef_Init, +which is modified with this patch, hence they need a +direct call to the check function. + +Co-Authored-By: Karolina Surma +--- + Include/moduleobject.h | 43 ++++++++++++++++++++++++++++++++++++++++++ + Makefile.pre.in | 3 +++ + Modules/_tkinter.c | 6 ++++++ + Modules/_tracemalloc.c | 6 ++++++ + Modules/readline.c | 6 ++++++ + Objects/moduleobject.c | 1 + + 6 files changed, 65 insertions(+) + +diff --git a/Include/moduleobject.h b/Include/moduleobject.h +index 2a17c891dd..64017c666c 100644 +--- a/Include/moduleobject.h ++++ b/Include/moduleobject.h +@@ -116,6 +116,49 @@ struct PyModuleDef { + freefunc m_free; + }; + ++#if defined(_PyHack_check_version_on_modinit) && defined(Py_BUILD_CORE) ++/* The mechanism for the check has been implemented on Python 3.15+: ++ * https://github.com/python/cpython/pull/137212. ++ * In Fedora, we need this in older Pythons too: ++ * if somebody attempts to import a module compiled for a different Python version, ++ * instead of segmentation fault a meaningful error is raised. ++ */ ++PyAPI_DATA(const unsigned long) Py_Version; ++ ++static inline int ++_PyHack_CheckInternalAPIVersion(const char *mod_name) ++{ ++ if (PY_VERSION_HEX != Py_Version) { ++ PyErr_Format( ++ PyExc_ImportError, ++ "internal Python C API version mismatch: " ++ "module %s compiled with %lu.%lu.%lu; " ++ "runtime version is %lu.%lu.%lu", ++ mod_name, ++ (const unsigned long)((PY_VERSION_HEX >> 24) & 0xFF), ++ (const unsigned long)((PY_VERSION_HEX >> 16) & 0xFF), ++ (const unsigned long)((PY_VERSION_HEX >> 8) & 0xFF), ++ (const unsigned long)((Py_Version >> 24) & 0xFF), ++ (const unsigned long)((Py_Version >> 16) & 0xFF), ++ (const unsigned long)((Py_Version >> 8) & 0xFF) ++ ); ++ return -1; ++ } ++ return 0; ++} ++ ++static inline PyObject * ++PyModuleDef_Init_with_check(PyModuleDef *def) ++{ ++ if (_PyHack_CheckInternalAPIVersion(def->m_name) < 0) { ++ return NULL; ++ } ++ return PyModuleDef_Init(def); ++} ++ ++#define PyModuleDef_Init PyModuleDef_Init_with_check ++#endif ++ + #ifdef __cplusplus + } + #endif +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 526d500fe0..506ec30408 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -3426,3 +3426,6 @@ MODULE__MULTIBYTECODEC_DEPS=$(srcdir)/Modules/cjkcodecs/multibytecodec.h + # Local Variables: + # mode: makefile + # End: ++ ++# Fedora-specific, downstream only ++PY_STDMODULE_CFLAGS += -D_PyHack_check_version_on_modinit=1 +diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c +index 22126b67d8..7ef5b5d5cd 100644 +--- a/Modules/_tkinter.c ++++ b/Modules/_tkinter.c +@@ -3611,6 +3611,12 @@ static struct PyModuleDef _tkintermodule = { + PyMODINIT_FUNC + PyInit__tkinter(void) + { ++ #ifdef _PyHack_check_version_on_modinit ++ if (_PyHack_CheckInternalAPIVersion("_tkinter") < 0) { ++ return NULL; ++ } ++ #endif ++ + PyObject *m, *uexe, *cexe; + + tcl_lock = PyThread_allocate_lock(); +diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c +index be71fc9fc9..67922098b2 100644 +--- a/Modules/_tracemalloc.c ++++ b/Modules/_tracemalloc.c +@@ -215,6 +215,12 @@ static struct PyModuleDef module_def = { + PyMODINIT_FUNC + PyInit__tracemalloc(void) + { ++ #ifdef _PyHack_check_version_on_modinit ++ if (_PyHack_CheckInternalAPIVersion("_tracemalloc") < 0) { ++ return NULL; ++ } ++ #endif ++ + PyObject *mod = PyModule_Create(&module_def); + if (mod == NULL) { + return NULL; +diff --git a/Modules/readline.c b/Modules/readline.c +index 7708f47d4d..7c0b70caa4 100644 +--- a/Modules/readline.c ++++ b/Modules/readline.c +@@ -1612,6 +1612,12 @@ static struct PyModuleDef readlinemodule = { + PyMODINIT_FUNC + PyInit_readline(void) + { ++ #ifdef _PyHack_check_version_on_modinit ++ if (_PyHack_CheckInternalAPIVersion("readline") < 0) { ++ return NULL; ++ } ++ #endif ++ + const char *backend = "readline"; + PyObject *m; + readlinestate *mod_state; +diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c +index b68584b5dd..cbf95dc92a 100644 +--- a/Objects/moduleobject.c ++++ b/Objects/moduleobject.c +@@ -50,6 +50,7 @@ _PyModule_IsExtension(PyObject *obj) + } + + ++#undef PyModuleDef_Init + PyObject* + PyModuleDef_Init(PyModuleDef* def) + { diff --git a/00486-gh-148646-add---enable-prebuilt-jit-stencils-configure-flag.patch b/00486-gh-148646-add---enable-prebuilt-jit-stencils-configure-flag.patch new file mode 100644 index 0000000..79101b5 --- /dev/null +++ b/00486-gh-148646-add---enable-prebuilt-jit-stencils-configure-flag.patch @@ -0,0 +1,146 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= +Date: Thu, 16 Apr 2026 14:39:41 +0200 +Subject: 00486: gh-148646: Add --enable-prebuilt-jit-stencils configure flag + +--- + ...-04-16-14-39-33.gh-issue-148646.iIIgWF.rst | 6 +++++ + Tools/jit/_targets.py | 3 ++- + Tools/jit/build.py | 6 +++++ + configure | 26 +++++++++++++++++++ + configure.ac | 13 ++++++++++ + 5 files changed, 53 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Build/2026-04-16-14-39-33.gh-issue-148646.iIIgWF.rst + +diff --git a/Misc/NEWS.d/next/Build/2026-04-16-14-39-33.gh-issue-148646.iIIgWF.rst b/Misc/NEWS.d/next/Build/2026-04-16-14-39-33.gh-issue-148646.iIIgWF.rst +new file mode 100644 +index 0000000000..52dbc347a0 +--- /dev/null ++++ b/Misc/NEWS.d/next/Build/2026-04-16-14-39-33.gh-issue-148646.iIIgWF.rst +@@ -0,0 +1,6 @@ ++Add a new ``--enable-prebuilt-jit-stencils`` configure flag that forces the ++build to use the existing provided JIT stencils even when the digest at the ++beginning of the file does not match expectations. That allows ++redistributors who prebuilt the JIT stencils on a system with a different ++autoconf version to still use them even when ``pyconfig.h`` is slightly ++different. +diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py +index f1085cc9bf..3d8af735e2 100644 +--- a/Tools/jit/_targets.py ++++ b/Tools/jit/_targets.py +@@ -205,6 +205,7 @@ def build( + *, + comment: str = "", + force: bool = False, ++ prebuilt: bool = False, + jit_stencils: pathlib.Path, + ) -> None: + """Build jit_stencils.h in the given directory.""" +@@ -218,7 +219,7 @@ def build( + if ( + not force + and jit_stencils.exists() +- and jit_stencils.read_text().startswith(digest) ++ and (prebuilt or jit_stencils.read_text().startswith(digest)) + ): + return + stencil_groups = ASYNCIO_RUNNER.run(self._build_stencils()) +diff --git a/Tools/jit/build.py b/Tools/jit/build.py +index a073300592..5580985974 100644 +--- a/Tools/jit/build.py ++++ b/Tools/jit/build.py +@@ -42,6 +42,11 @@ + parser.add_argument( + "--cflags", help="additional flags to pass to the compiler", default="" + ) ++ parser.add_argument( ++ "--prebuilt", ++ action="store_true", ++ help="accept prebuilt stencils even if the digest does not match", ++ ) + args = parser.parse_args() + for target in args.target: + target.debug = args.debug +@@ -52,6 +57,7 @@ + target.build( + comment=comment, + force=args.force, ++ prebuilt=args.prebuilt, + jit_stencils=args.output_dir / f"jit_stencils-{target.triple}.h", + ) + jit_stencils_h = args.output_dir / "jit_stencils.h" +diff --git a/configure b/configure +index 2cb22a7806..1b396c92b2 100755 +--- a/configure ++++ b/configure +@@ -1105,6 +1105,7 @@ with_strict_overflow + enable_safety + enable_slower_safety + enable_experimental_jit ++enable_prebuilt_jit_stencils + with_dsymutil + with_address_sanitizer + with_memory_sanitizer +@@ -1842,6 +1843,9 @@ Optional Features: + --enable-experimental-jit[=no|yes|yes-off|interpreter] + build the experimental just-in-time compiler + (default is no) ++ --enable-prebuilt-jit-stencils ++ accept prebuilt JIT stencils even if the digest does ++ not match (default is no) + --enable-loadable-sqlite-extensions + support loadable extensions in the sqlite3 module, + see Doc/library/sqlite3.rst (default is no) +@@ -11045,6 +11049,28 @@ fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tier2_flags $jit_flags" >&5 + printf "%s\n" "$tier2_flags $jit_flags" >&6; } + ++# Check for --enable-prebuilt-jit-stencils: ++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --enable-prebuilt-jit-stencils" >&5 ++printf %s "checking for --enable-prebuilt-jit-stencils... " >&6; } ++# Check whether --enable-prebuilt-jit-stencils was given. ++if test ${enable_prebuilt_jit_stencils+y} ++then : ++ enableval=$enable_prebuilt_jit_stencils; ++else case e in #( ++ e) enable_prebuilt_jit_stencils=no ;; ++esac ++fi ++ ++if test "x$enable_prebuilt_jit_stencils" = xno ++then : ++ ++else case e in #( ++ e) as_fn_append REGEN_JIT_COMMAND " --prebuilt" ;; ++esac ++fi ++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_prebuilt_jit_stencils" >&5 ++printf "%s\n" "$enable_prebuilt_jit_stencils" >&6; } ++ + if test "$disable_gil" = "yes" -a "$enable_experimental_jit" != "no"; then + # GH-133171: This configuration builds the JIT but never actually uses it, + # which is surprising (and strictly worse than not building it at all): +diff --git a/configure.ac b/configure.ac +index 967d34d47a..51160cafc2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2873,6 +2873,19 @@ AC_SUBST([REGEN_JIT_COMMAND]) + AC_SUBST([JIT_STENCILS_H]) + AC_MSG_RESULT([$tier2_flags $jit_flags]) + ++# Check for --enable-prebuilt-jit-stencils: ++AC_MSG_CHECKING([for --enable-prebuilt-jit-stencils]) ++AC_ARG_ENABLE([prebuilt-jit-stencils], ++ [AS_HELP_STRING([--enable-prebuilt-jit-stencils], ++ [accept prebuilt JIT stencils even if the digest does not match (default is no)])], ++ [], ++ [enable_prebuilt_jit_stencils=no]) ++AS_VAR_IF([enable_prebuilt_jit_stencils], ++ [no], ++ [], ++ [AS_VAR_APPEND([REGEN_JIT_COMMAND], [" --prebuilt"])]) ++AC_MSG_RESULT([$enable_prebuilt_jit_stencils]) ++ + if test "$disable_gil" = "yes" -a "$enable_experimental_jit" != "no"; then + # GH-133171: This configuration builds the JIT but never actually uses it, + # which is surprising (and strictly worse than not building it at all): diff --git a/download-jit-stencils-from-koji.sh b/download-jit-stencils-from-koji.sh new file mode 100644 index 0000000..296af97 --- /dev/null +++ b/download-jit-stencils-from-koji.sh @@ -0,0 +1,23 @@ +set -eu +export LANG=C.utf-8 + +taskid=$(echo "$1" | sed -E 's/.*=|^([0-9]+)/\1/') +filter='.*-debugsource-.*\.(x86_64|aarch64)\.rpm' + +download_stdout=$(koji download-task $taskid --filter "$filter" | tee /dev/stderr) +files=$(echo "$download_stdout" | grep -E '^Downloading ' | sed -E 's/.*\s+(\S+)/\1/' | sort) + +for file in $files; do + nvra=${file/.rpm} + snvra=${nvra/-debugsource} + version=$(echo $nvra | sed -E -e 's|.*-([^-]+)-[^-]+|\1|' -e 's|~||') + arch=$(echo $nvra | sed -E 's|.*\.([^.]+)|\1|') + rpm2cpio $file | cpio -idmv ./usr/src/debug/${snvra}/build/{debug,optimized}/jit_stencils-${arch}-redhat-linux-gnu.h + for build in debug optimized; do + mv -v ./usr/src/debug/${snvra}/build/${build}/jit_stencils-${arch}-redhat-linux-gnu.h Python-${version}-${arch}-${build}-jit_stencils.h > /dev/stderr + echo Python-${version}-${arch}-${build}-jit_stencils.h + done + rmdir ./usr/src/debug/${snvra}{/build{/{debug,optimized},},} || : + rm -v $file > /dev/stderr +done +rmdir ./usr{/src{/debug,},} || : diff --git a/plan.fmf b/plan.fmf new file mode 100644 index 0000000..bb45dcc --- /dev/null +++ b/plan.fmf @@ -0,0 +1,93 @@ +execute: + how: tmt + +provision: + hardware: + memory: '>= 3 GB' + +environment: + pybasever: '3.14' + +discover: + - name: tests_python + how: shell + url: https://src.fedoraproject.org/tests/python.git + tests: + - name: smoke + path: /smoke + test: "VERSION=${pybasever} CYTHON=true ./venv.sh" + - name: smoke_virtualenv + path: /smoke + test: "VERSION=${pybasever} METHOD=virtualenv CYTHON=true ./venv.sh" + - name: debugsmoke + path: /smoke + test: "PYTHON=python${pybasever}d TOX=false VERSION=${pybasever} CYTHON=true ./venv.sh" + - name: selftest + path: /selftest + test: "VERSION=${pybasever} X='-i test_check_probes' ./parallel.sh" + - name: debugtest + path: /selftest + # test_base_interpreter: https://github.com/python/cpython/issues/131372 + test: "VERSION=${pybasever} PYTHON=python${pybasever}d X='-i test_check_probes -i test_base_interpreter' ./parallel.sh" + - name: freethreadingtest + path: /selftest + test: "VERSION=${pybasever}t X='-i test_check_probes -i test_base_interpreter' ./parallel.sh" + - name: selftest_jit + path: /selftest + # test_attr_promotion_failure: https://github.com/python/cpython/issues/141833 + test: "VERSION=${pybasever} PYTHON_JIT=1 X='-i test_check_probes -i test_attr_promotion_failure' ./parallel.sh" + - name: jit_disabled_by_default + test: "python${pybasever} -c 'import sys; assert not sys._jit.is_enabled()'" + - name: jit_disabled_explicitly + test: "PYTHON_JIT=0 python${pybasever} -c 'import sys; assert not sys._jit.is_enabled()'" + - name: jit_enabled_explicitly + test: "PYTHON_JIT=1 python${pybasever} -c 'import sys; assert sys._jit.is_enabled()'" + - name: optimizedflags + path: /flags + test: "python${pybasever} ./assertflags.py -O3 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS" + - name: debugflags + path: /flags + test: "python${pybasever}d ./assertflags.py -O0 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS" + - name: freethreadingflags + path: /flags + test: "python${pybasever}t ./assertflags.py -O3 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS" + - name: freethreadingdebugflags + path: /flags + test: "python${pybasever}td ./assertflags.py -O0 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS" + - name: marshalparser + path: /marshalparser + test: "VERSION=${pybasever} SAMPLE=10 ./test_marshalparser_compatibility.sh" + - name: required_symbols + path: /required-symbols + test: "VERSION=${pybasever} ./check.sh" + +prepare: + - name: Install dependencies + how: install + package: + - gcc # for extension building in venv and selftest + - gcc-c++ # for test_cppext + - gdb # for test_gdb + - "python${pybasever}" # the test subject + - "python${pybasever}-debug" # for leak testing + - "python${pybasever}-devel" # for extension building in venv and selftest + - "python${pybasever}-tkinter" # for selftest + - "python${pybasever}-test" # for selftest + - "python${pybasever}-freethreading" # for -O... flag test + - "python${pybasever}-freethreading-debug" # for -O... flag test + - "python${pybasever}-freethreading-tkinter" # for freethreadingtest + - "python${pybasever}-freethreading-test" # for freethreadingtest + - tox # for venv tests + - virtualenv # for virtualenv tests + - glibc-all-langpacks # for locale tests + - marshalparser # for testing compatibility (magic numbers) with marshalparser + - binutils # for nm (symbol inspection) + - rpm # for debugging + - dnf # for upgrade and downgrade + - name: Update packages + how: shell + script: dnf upgrade -y + - name: rpm_qa + order: 100 + how: shell + script: rpm -qa | sort | tee $TMT_PLAN_DATA/rpmqa.txt diff --git a/python3.14.spec b/python3.14.spec index a10882d..2d68d27 100644 --- a/python3.14.spec +++ b/python3.14.spec @@ -1,3 +1,35 @@ +# ====================== +# Bootstrap conditionals +# ====================== + +# When bootstrapping python3, we need to build python3-packaging. +# but packaging BR python3-devel and that brings in python3-rpm-generators; +# python3-rpm-generators needs python3-packaging, so we cannot have it yet. +# +# We also use the previous build of Python in "make regen-all". +# +# Procedure: https://fedoraproject.org/wiki/SIGs/Python/UpgradingPython +# +# Bootstrap enabled: +# - disables regen-all with the same Python version +# - disables dependency on python3-rpm-generators if we build with main_python +# - disables rpmwheels, optimizations and tests by default +%bcond bootstrap 0 + +# Whether to use RPM build wheels from the python-{pip,setuptools,wheel}-wheel packages +# Uses upstream bundled prebuilt wheels otherwise +%bcond rpmwheels %{without bootstrap} + +# Expensive optimizations (mainly, profile-guided optimizations) +# We don't have to switch it off for bootstrap, but it speeds up the first build, +# so we opt to only run them during the "full" build +%bcond optimizations %{without bootstrap} + +# Run the test suite in %%check +# Technically, we can run the tests even during the bootstrap build, but since +# we build Python 2x, it's better to just run it once with the "full" build +%bcond tests %{without bootstrap} + # ================== # Top-level metadata # ================== @@ -13,11 +45,11 @@ URL: https://www.python.org/ # WARNING When rebasing to a new Python version, # remember to update the python3-docs package as well -%global general_version %{pybasever}.0 -%global prerel a7 +%global general_version %{pybasever}.7 +#global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -36,100 +68,26 @@ License: Python-2.0.1 # In ELN/RHEL/CentOS we want to allow building against alternative stacks, so the Provide is enabled. %bcond python_abi_provides_for_alt_pythons %{undefined fedora} -# When bootstrapping python3, we need to build python3-packaging. -# but packaging BR python3-devel and that brings in python3-rpm-generators; -# python3-rpm-generators needs python3-packaging, so we cannot have it yet. -# -# We also use the previous build of Python in "make regen-all". -# -# Procedure: https://fedoraproject.org/wiki/SIGs/Python/UpgradingPython -# -# IMPORTANT: When bootstrapping, it's very likely python-pip-wheel is -# not available. Turn off the rpmwheels bcond until -# python-pip is built with a wheel to get around the issue. -%bcond bootstrap 0 - -# Whether to use RPM build wheels from the python-{pip,setuptools,wheel}-wheel packages -# Uses upstream bundled prebuilt wheels otherwise -%bcond rpmwheels 1 -# If the rpmwheels condition is disabled, we use the bundled wheel packages -# from Python with the versions below. -# This needs to be manually updated when we update Python. -# Explore the sources tarball (you need the version before %%prep is executed): -# $ tar -tf Python-%%{upstream_version}.tar.xz | grep whl -%global pip_version 25.0.1 -%global setuptools_version 67.6.1 -%global wheel_version 0.43.0 -# All of those also include a list of indirect bundled libs: -# pip -# $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt) -%global pip_bundled_provides %{expand: -Provides: bundled(python3dist(cachecontrol)) = 0.14.1 -Provides: bundled(python3dist(certifi)) = 2024.8.30 -Provides: bundled(python3dist(distlib)) = 0.3.9 -Provides: bundled(python3dist(distro)) = 1.9 -Provides: bundled(python3dist(idna)) = 3.10 -Provides: bundled(python3dist(msgpack)) = 1.1 -Provides: bundled(python3dist(packaging)) = 24.2 -Provides: bundled(python3dist(platformdirs)) = 4.3.6 -Provides: bundled(python3dist(pygments)) = 2.18 -Provides: bundled(python3dist(pyproject-hooks)) = 1.2 -Provides: bundled(python3dist(requests)) = 2.32.3 -Provides: bundled(python3dist(resolvelib)) = 1.0.1 -Provides: bundled(python3dist(rich)) = 13.9.4 -Provides: bundled(python3dist(setuptools)) = 70.3 -Provides: bundled(python3dist(tomli)) = 2.2.1 -Provides: bundled(python3dist(truststore)) = 0.10 -Provides: bundled(python3dist(typing-extensions)) = 4.12.2 -Provides: bundled(python3dist(urllib3)) = 1.26.20 -} -# setuptools -# vendor.txt files not in .whl -# $ %%{_rpmconfigdir}/pythonbundles.py \ -# <(curl -L https://github.com/pypa/setuptools/raw/v%%{setuptools_version}/setuptools/_vendor/vendored.txt) \ -# <(curl -L https://github.com/pypa/setuptools/raw/v%%{setuptools_version}/pkg_resources/_vendor/vendored.txt) -%global setuptools_bundled_provides %{expand: -Provides: bundled(python3dist(importlib-metadata)) = 6 -Provides: bundled(python3dist(importlib-resources)) = 5.10.2 -Provides: bundled(python3dist(jaraco-text)) = 3.7 -Provides: bundled(python3dist(more-itertools)) = 8.8 -Provides: bundled(python3dist(ordered-set)) = 3.1.1 -Provides: bundled(python3dist(packaging)) = 23 -Provides: bundled(python3dist(platformdirs)) = 2.6.2 -Provides: bundled(python3dist(tomli)) = 2.0.1 -Provides: bundled(python3dist(typing-extensions)) = 4.0.1 -Provides: bundled(python3dist(typing-extensions)) = 4.4 -Provides: bundled(python3dist(zipp)) = 3.7 -} -# wheel -# $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/test/wheeldata/wheel-*.whl wheel/vendored/vendor.txt) -%global wheel_bundled_provides %{expand: -Provides: bundled(python3dist(packaging)) = 24 -} - -# Expensive optimizations (mainly, profile-guided optimizations) -%bcond optimizations 1 - -# Run the test suite in %%check -%bcond tests 1 - # Extra build for debugging the interpreter or C-API extensions # (the -debug subpackages) %bcond debug_build 1 -# Extra build without GIL, the freethreading PEP 703 provisional way +# Extra build without GIL, the freethreading PEP 703 way # (the -freethreading subpackage) %bcond freethreading_build 1 # PEP 744: JIT Compilation # Whether to build with the experimental JIT compiler -# We can only have this on Fedora 41+, where clang 19+ is available -# And only on certain architectures: https://peps.python.org/pep-0744/#support +# Only possible on certain architectures: https://peps.python.org/pep-0744/#support # The freethreading build (when enabled) does not support JIT yet -%bcond jit %[(0%{?fedora} >= 41 || 0%{?rhel} >= 10) && ("%{_arch}" == "x86_64" || "%{_arch}" == "aarch64")] +%bcond jit %["%{_arch}" == "x86_64" || "%{_arch}" == "aarch64"] +# Whether to build the JIT stencils (or else use the prebuilt ones) +# We can only do this on Fedora 41+, where clang 19 is available +# We don't do it in RHEL, see https://github.com/fedora-eln/eln/issues/207 +%bcond jit_build_stencils %[%{with jit} && 0%{?fedora} >= 41] %if %{with jit} # When built with JIT, it still needs to be enabled on runtime via PYTHON_JIT=1 -%global jit_flag --enable-experimental-jit=yes-off +%global jit_flag --enable-experimental-jit=yes-off %{!?with_jit_build_stencils:--enable-prebuilt-jit-stencils} %endif # Main interpreter loop optimization @@ -138,14 +96,69 @@ Provides: bundled(python3dist(packaging)) = 24 # ===================== # General global macros # ===================== + %if %{with main_python} %global pkgname python3 %global exename python3 +%global python3_pkgversion 3 %else %global pkgname python%{pybasever} %global exename python%{pybasever} +%global python3_pkgversion %{pybasever} %endif +# If the rpmwheels condition is disabled, we use the bundled wheel packages +# from Python with the versions below. +# This needs to be manually updated when we update Python. +# Explore the sources tarball (you need the version before %%prep is executed): +# $ tar -tf Python-%%{upstream_version}.tar.xz | grep whl +%global pip_version 26.2.1 +%global setuptools_version 79.0.1 +# All of those also include a list of indirect bundled libs: +# pip +# $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt) +%global pip_bundled_provides %{expand: +Provides: bundled(python3dist(cachecontrol)) = 0.14.4 +Provides: bundled(python3dist(certifi)) = 2026.6.17 +Provides: bundled(python3dist(distlib)) = 0.4.2 +Provides: bundled(python3dist(distro)) = 1.9 +Provides: bundled(python3dist(idna)) = 3.18 +Provides: bundled(python3dist(msgpack)) = 1.1.2 +Provides: bundled(python3dist(packaging)) = 26.2 +Provides: bundled(python3dist(platformdirs)) = 4.10 +Provides: bundled(python3dist(pygments)) = 2.20 +Provides: bundled(python3dist(pyproject-hooks)) = 1.2 +Provides: bundled(python3dist(requests)) = 2.34.2 +Provides: bundled(python3dist(resolvelib)) = 1.2.1 +Provides: bundled(python3dist(rich)) = 14.2 +Provides: bundled(python3dist(setuptools)) = 70.3 +Provides: bundled(python3dist(tomli)) = 2.4.1 +Provides: bundled(python3dist(tomli-w)) = 1.2 +Provides: bundled(python3dist(truststore)) = 0.10.4 +Provides: bundled(python3dist(urllib3)) = 2.7 +} +# setuptools +# vendor.txt not in .whl +# %%{_rpmconfigdir}/pythonbundles.py <(unzip -l Lib/test/wheeldata/setuptools-*.whl | grep -E '_vendor/.+dist-info/RECORD' | sed -E 's@^.*/([^-]+)-([^-]+)\.dist-info/.*$@\1==\2@') +%global setuptools_bundled_provides %{expand: +Provides: bundled(python3dist(autocommand)) = 2.2.2 +Provides: bundled(python3dist(backports-tarfile)) = 1.2 +Provides: bundled(python3dist(importlib-metadata)) = 8 +Provides: bundled(python3dist(inflect)) = 7.3.1 +Provides: bundled(python3dist(jaraco-collections)) = 5.1 +Provides: bundled(python3dist(jaraco-context)) = 5.3 +Provides: bundled(python3dist(jaraco-functools)) = 4.0.1 +Provides: bundled(python3dist(jaraco-text)) = 3.12.1 +Provides: bundled(python3dist(more-itertools)) = 10.3 +Provides: bundled(python3dist(packaging)) = 24.2 +Provides: bundled(python3dist(platformdirs)) = 4.2.2 +Provides: bundled(python3dist(tomli)) = 2.0.1 +Provides: bundled(python3dist(typeguard)) = 4.3 +Provides: bundled(python3dist(typing-extensions)) = 4.12.2 +Provides: bundled(python3dist(wheel)) = 0.45.1 +Provides: bundled(python3dist(zipp)) = 3.19.2 +} + # ABIFLAGS, LDVERSION and SOABI are in the upstream configure.ac # See PEP 3149 for some background: http://www.python.org/dev/peps/pep-3149/ %global ABIFLAGS_optimized %{nil} @@ -248,8 +261,7 @@ Obsoletes: python%{pybasever}%{?1:-%{1}}\ BuildRequires: autoconf BuildRequires: bluez-libs-devel BuildRequires: bzip2-devel -# See the runtime requirement in the -libs subpackage -BuildRequires: expat-devel >= 2.6 +BuildRequires: expat-devel >= 2.5.0-2 BuildRequires: findutils BuildRequires: gcc BuildRequires: gdbm-devel @@ -259,10 +271,10 @@ BuildRequires: gnupg2 BuildRequires: libX11-devel BuildRequires: libffi-devel BuildRequires: libuuid-devel +BuildRequires: libzstd-devel BuildRequires: make BuildRequires: mpdecimal-devel BuildRequires: ncurses-devel -BuildRequires: openssl-devel BuildRequires: pkgconfig BuildRequires: python-rpm-macros BuildRequires: readline-devel @@ -275,6 +287,10 @@ BuildRequires: xz-devel BuildRequires: zlib-devel BuildRequires: /usr/bin/dtrace +# Support for OpenSSL 4 only landed in Python 3.15 for now +# https://github.com/python/cpython/issues/146207 +BuildRequires: (openssl-devel < 1:4 or openssl3-devel) + %if %{with tests} BuildRequires: gcc-c++ BuildRequires: gdb @@ -282,7 +298,7 @@ BuildRequires: glibc-all-langpacks BuildRequires: tzdata %endif -%if %{with jit} +%if %{with jit_build_stencils} BuildRequires: clang(major) = 19 BuildRequires: llvm(major) = 19 %endif @@ -336,6 +352,27 @@ Source10: idle3.desktop # AppData file for idle3 Source11: idle3.appdata.xml +# Pre-generated JIT stencils (see PEP 774) +# As the PEP was deferred, we use stencils we built for ourselves. +# Only used on platforms without the required LLVM version. +# +# When updating Python: +# 1. scratch build Python on platform with required LLVM version (usually rawhide) +# 2. download the files from Koji: +# $ bash download-jit-stencils-from-koji.sh KOJI_TASK_URL|KOJI_TASK_ID +# 3. add the files to lookaside cache with fedpkg new-sources +Source30: download-jit-stencils-from-koji.sh +# This %%if-hack makes it easier to do step 1. from the above. +# Use `fedpkg sources --force` to get the conditionally defined sources from the lookaside cache. +%if (%{with jit} && %{without jit_build_stencils}) || %{exists:%{_sourcedir}/Python-%{upstream_version}-x86_64-optimized-jit_stencils.h} +Source31: Python-%{upstream_version}-aarch64-debug-jit_stencils.h +Source32: Python-%{upstream_version}-aarch64-optimized-jit_stencils.h +Source33: Python-%{upstream_version}-x86_64-debug-jit_stencils.h +Source34: Python-%{upstream_version}-x86_64-optimized-jit_stencils.h +%endif +%global jit_stencils_source %{_sourcedir}/Python-%{upstream_version}-%{_arch}-${ConfName}-jit_stencils.h +%global jit_stencils_filename jit_stencils-%{_arch}-redhat-linux-gnu.h + # (Patches taken from github.com/fedora-python/cpython) # 00251 # 5ac6e7781923cbb3e4606e3bca381a1167d322e5 @@ -355,42 +392,50 @@ Source11: idle3.appdata.xml # pypa/distutils integration: https://github.com/pypa/distutils/pull/70 Patch251: 00251-change-user-install-location.patch -# 00454 # 1d5d7e9ce724fbbd89645d637303d12731c2a622 -# Invoke regen-token rst with rstfile as an argument +# 00466 # 713a1368544eddd55088d67f88a23ce31722a4cb +# Downstream only: Lower XML_COMBINED_VERSION threshold for reparse deferral # -# Proposed upstream: https://github.com/python/cpython/pull/132304 -Patch454: 00454-invoke-regen-token-rst-with-rstfile-as-an-argument.patch +# RHEL 9 expat 2.5.0 has XML_SetReparseDeferralEnabled backported +# via the CVE-2023-52425 fix, but XML_COMBINED_VERSION remains 20500. +# CPython's #if XML_COMBINED_VERSION >= 20600 guards compile the setter +# as a no-op, so SetReparseDeferralEnabled silently does nothing and +# GetReparseDeferralEnabled always returns False, even though the expat +# library actually supports (and enables) reparse deferral. +# +# Lower the threshold from 20600 to 20500 so that CPython uses the +# backported function. This makes the Python API actually work on RHEL 9 +# and fixes test failures (test_reparse_deferral_disabled, +# test_flush_reparse_deferral_disabled, test_simple_xml_chunk_*). +# +# The spec file BuildRequires expat-devel >= 2.5.0-2 to ensure the +# backported function is available. +Patch466: 00466-downstream-only-lower-xml_combined_version-threshold-for-reparse-deferral.patch -# 00456 # 8f50cf7170e39c02d52cb5f99d647eeefad2f685 -# Find the correct group name in test_group_no_follow_symlinks +# 00475 # 91e12ebfb2a88b265f3764a0d852b6fa53b2386a +# CVE-2025-15367 # -# Reported: https://github.com/python/cpython/issues/132356 -# Fix proposed upstream: https://github.com/python/cpython/pull/132357 -Patch456: 00456-find-the-correct-group-name-in-test_group_no_follow_symlinks.patch +# Downstream only: Reject control characters in POP3 commands +Patch475: 00475-cve-2025-15367.patch -# 00459 # 9cf6fed17de184d2e17ace2b5063e782e7e186ba -# Apply Intel Control-flow Technology for x86-64 +# 00477 # f9f53e560d161531a0c3476c08ee26b89a628bde +# Raise an error when importing stdlib modules compiled for a different Python version # -# Required for mitigation against return-oriented programming (ROP) and Call or Jump Oriented Programming (COP/JOP) attacks +# This is a downstream workaround "implementing" +# https://github.com/python/cpython/pull/137212 - +# the mechanism for the check exists in Python 3.15+, where it needs to be +# added to the standard library modules. +# In Fedora, we need it also in previous Python versions, as we experience +# segmentation fault when importing stdlib modules after update while +# Python is running. # -# Proposed upstream: https://github.com/python/cpython/pull/128606 -# -# See also: https://sourceware.org/annobin/annobin.html/Test-cf-protection.html -Patch459: 00459-apply-intel-control-flow-technology-for-x86-64.patch +# _tkinter, _tracemalloc and readline are not calling PyModuleDef_Init, +# which is modified with this patch, hence they need a +# direct call to the check function. +Patch477: 00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-different-python-version.patch -# 00460 # f876c748b89770cfee4148c3dd3acbc3dd527eb6 -# gh-132415: Update vendored setuptools in ``Lib/test/wheeldata`` -# -# (actual changes in .whl files removed to make this patch smaller) -# -# gh-127906: Add missing sys import to test_cppext -Patch460: 00460-gh-132415-update-vendored-setuptools-in-lib-test-wheeldata.patch - -# 00461 # 920175020b21c0aff5edcc4c28d688b5061f591c -# Downstream only: Install wheel in test venvs when setuptools < 71 -# -# This can be removed when Fedora 41 goes EOL (or updates setuptools). -Patch461: 00461-downstream-only-install-wheel-in-test-venvs-when-setuptools-71.patch +# 00486 # 5ae0b81b3135319f8d75a886fb7a11fa40ac11f4 +# gh-148646: Add --enable-prebuilt-jit-stencils configure flag +Patch486: 00486-gh-148646-add---enable-prebuilt-jit-stencils-configure-flag.patch # (New patches go here ^^^) # @@ -512,8 +557,36 @@ This package contains /usr/bin/python - the "python" command that runs Python 3. %package -n %{pkgname}-libs Summary: Python runtime libraries -# Bundled mimalloc is MIT -%global libs_license Python-2.0.1 AND MIT +# Python is generally licensed as Python-2.0.1 but also includes incorporated software +# Combined manually from https://docs.python.org/3.14/license.html +# Hash of Doc/license.rst which is compared in %%prep, generated with: +# $ sha256sum Doc/license.rst | cut -f1 -d" " +%global license_file_hash cd6f471c0bfdb099efefc25ddff9b3df8bf62e10428987f1f05e6f2f9e35d563 +# Licenses of incorporated software: +# Mersenne Twister in _random C extension contains code under BSD-3-Clause +# socket.getaddrinfo() and socket.getnameinfo() are BSD-3-Clause +# test.support.asynchat and test.support.asyncore are MIT-CMU +# http.cookies is MIT-CMU +# trace is HPND-SMC +# uu is MIT-CMU +# xmlrpc.client is MIT-CMU +# test.test_epoll is MIT +# select kqueue interface is BSD-2-Clause +# SipHash algorithm in Python/pyhash.c is MIT +# strtod and dtoa are dtoa +# OpenSSL is not bundled +# expat is not bundled +# libffi is not bundled +# zlib is not bundled +# cfuhash used by tracemalloc is BSD-3-Clause +# libmpdec is not bundled +# C14N test suite in Lib/test/xmltestdata/c14n-20/ is BSD-3-Clause +# mimalloc is MIT +# parts of asyncio from uvloop are MIT +# Python/qsbr.c is adapted from code under BSD-2-Clause +# Zstandard bindings in Modules/_zstd and Lib/compression/zstd are BSD-3-Clause +# An extract of the `Unicode Character Database` converted to an internal format is Unicode-3.0 +%global libs_license Python-2.0.1 AND MIT AND BSD-3-Clause AND MIT-CMU AND HPND-SMC AND BSD-2-Clause AND dtoa AND Unicode-3.0 %if %{with rpmwheels} Requires: %{python_wheel_pkg_prefix}-pip-wheel >= 23.1.2 License: %{libs_license} @@ -521,7 +594,7 @@ License: %{libs_license} Provides: bundled(python3dist(pip)) = %{pip_version} %pip_bundled_provides # License combined from Python libs + pip -License: %{libs_license} AND Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND ISC AND LGPL-2.1-only AND MPL-2.0 AND (Apache-2.0 OR BSD-2-Clause) +License: %{libs_license} AND Apache-2.0 AND ISC AND LGPL-2.1-only AND MPL-2.0 AND (Apache-2.0 OR BSD-2-Clause) %endif %unversioned_obsoletes_of_python3_X_if_main libs @@ -546,12 +619,26 @@ Recommends: (%{pkgname}-tkinter%{?_isa} if tk%{?_isa}) Requires: tzdata # The requirement on libexpat is generated, but we need to version it. -# When built with expat >= 2.6, but installed with older expat, we get: +# When built with a specific expat version, but installed with an older one, +# we sometimes get: # ImportError: /usr/lib64/python3.X/lib-dynload/pyexpat.cpython-....so: -# undefined symbol: XML_SetReparseDeferralEnabled +# undefined symbol: XML_... +# The pyexpat module has build-time checks for expat version to only use the +# available symbols. However, there is no runtime protection, so when the module +# is later installed with an older expat, it may error due to undefined symbols. # This breaks many things, including python -m venv. +# We avoid this problem by requiring at least the same version of expat that +# was used during the build time. +# We also include release, in case pyxpat uses ABI that was backported +# (e.g. XML_SetReparseDeferralEnabled was added in c9s expat 2.5.0-2). # Other subpackages (like -debug) also need this, but they all depend on -libs. -Requires: expat >= 2.6 +# Since expat 2.7.4, the library has versioned symbols and this is no longer needed, +# as the generated requirement will be in the form of libexpat.so.1(LIBEXPAT_2.7.2) etc. +%global expat_version %(LANG=C rpm -q --qf '%%{version}-%%{release}' expat.%{_target_cpu} | sed 's/.*not installed/0/') +%if v"%{expat_version}" < v"2.7.4" +Requires: expat%{?_isa} >= %{expat_version} +%endif + %description -n %{pkgname}-libs This package contains runtime libraries for use by Python: @@ -653,8 +740,6 @@ Requires: (%{python_wheel_pkg_prefix}-wheel-wheel if %{python_wheel_pkg_prefix}- %else Provides: bundled(python3dist(setuptools)) = %{setuptools_version} %setuptools_bundled_provides -Provides: bundled(python3dist(wheel)) = %{wheel_version} -%wheel_bundled_provides # License manually combined from Python + setuptools + wheel License: Python-2.0.1 AND MIT AND Apache-2.0 AND (Apache-2.0 OR BSD-2-Clause) %endif @@ -707,56 +792,170 @@ The debug runtime additionally supports debug builds of C-API extensions %if %{with freethreading_build} # This deliberately does not use the %%{pkgname}- prefix, # we want to call this python3.X-threading even when built as a main Python. -# At least until the PEP 703 build remains provisional. +# This build of Python is not "the main freethreading Python", there's no such thing (yet?) %package -n python%{pybasever}-freethreading -Summary: Free Threading (PEP 703) version of the Python runtime +Summary: Free Threading (PEP 703) version of the Python interpreter -%if %{with rpmwheels} -Requires: %{python_wheel_pkg_prefix}-pip-wheel >= 23.1.2 -Requires: %{python_wheel_pkg_prefix}-setuptools-wheel -Requires: (%{python_wheel_pkg_prefix}-wheel-wheel if %{python_wheel_pkg_prefix}-setuptools-wheel < 71) -License: %{libs_license} -%else -Provides: bundled(python3dist(pip)) = %{pip_version} -%pip_bundled_provides -Provides: bundled(python3dist(setuptools)) = %{setuptools_version} -%setuptools_bundled_provides -Provides: bundled(python3dist(wheel)) = %{wheel_version} -%wheel_bundled_provides -# License combined from Python libs + pip + setuptools + wheel -License: %{libs_license} AND Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND ISC AND LGPL-2.1-only AND MPL-2.0 AND (Apache-2.0 OR BSD-2-Clause) -%endif +Requires: python%{pybasever}-freethreading-libs%{?_isa} = %{version}-%{release} -# This package doesn't depend on python3-libs, so we need to explicitly -# define the same Provides and Requires. -# See the comments in the definition of -libs subpackage for detailed explanations -Provides: bundled(mimalloc) = 2.12 -Requires: tzdata -Requires: expat >= 2.6 +Obsoletes: python%{pybasever}-freethreading < 3.14.0-2 %description -n python%{pybasever}-freethreading -The provisional Free Threading (PEP 703) build of Python. +The Free Threading (PEP 703) build of Python interpreter. -CPython’s global interpreter lock (“GIL”) prevents multiple threads from +CPython's global interpreter lock ("GIL") prevents multiple threads from executing Python code at the same time. The GIL is an obstacle to using multi-core CPUs from Python efficiently. This build of Python is built with the --disable-gil option. It lets the interpreter run Python code without the global interpreter lock and with the necessary changes needed to make the interpreter thread-safe. -%endif # with freethreading_build +The %{pkgname}-freethreading package provides the "python%{pybasever}t" executable. +The majority of its standard library is provided in the +python%{pybasever}-freethreading-libs package, which should be installed +automatically along with python%{pybasever}-freethreading. +The remaining parts of the Python standard library are broken out into the +python%{pybasever}-freethreading-tkinter and +python%{pybasever}-freethreading-test packages, +which may need to be installed separately. + + +%package -n python%{pybasever}-freethreading-libs +Summary: Free Threading Python runtime libraries +%if %{with rpmwheels} +Requires: %{python_wheel_pkg_prefix}-pip-wheel >= 23.1.2 +License: %{libs_license} +%else +Provides: bundled(python3dist(pip)) = %{pip_version} +%pip_bundled_provides +# License combined from Python libs + pip +License: %{libs_license} AND Apache-2.0 AND ISC AND LGPL-2.1-only AND MPL-2.0 AND (Apache-2.0 OR BSD-2-Clause) +%endif + +# See the comments in the definition of main -libs subpackage for detailed explanations +Provides: bundled(mimalloc) = 2.12 +Requires: tzdata +%if v"%{expat_version}" < v"2.7.4" +Requires: expat%{?_isa} >= %{expat_version} +%endif + +# There are files in the standard library that have python shebang. +# We've filtered the automatic requirement out so libs are installable without +# the main package. This however makes it pulled in by default. +Recommends: python%{pybasever}-freethreading%{?_isa} + +# tkinter is part of the standard library, +# but it is torn out to save an unwanted dependency on tk and X11. +# we recommend it when tk is already installed (for better UX) +Recommends: (python%{pybasever}-freethreading-tkinter%{?_isa} if tk%{?_isa}) + +Obsoletes: python%{pybasever}-freethreading < 3.14.0-2 + +%description -n python%{pybasever}-freethreading-libs +This package contains runtime libraries for use by Free Threading Python: +- the majority of the Python standard library +- a dynamically linked library for use by applications that embed Python as + a scripting language, and by the main "python%{pybasever}t" executable + + +%package -n python%{pybasever}-freethreading-devel +Summary: Libraries and header files needed for Free Threading Python development +# Bundled mimalloc header files are MIT +License: Python-2.0.1 AND MIT +Requires: python%{pybasever}-freethreading = %{version}-%{release} +Requires: python%{pybasever}-freethreading-libs%{?_isa} = %{version}-%{release} + +# tox users are likely to need the devel subpackage +Supplements: tox + +Obsoletes: python%{pybasever}-freethreading < 3.14.0-2 + +%description -n python%{pybasever}-freethreading-devel +This package contains the header files and configuration needed to compile +Python extension modules (typically written in C or C++) for the Free hreading +build, to embed Free Threading Python into other programs, and to make binary +distributions for Free Threading Python libraries. + + +%package -n python%{pybasever}-freethreading-idle +Summary: A basic graphical development environment for Free Threading Python +Requires: python%{pybasever}-freethreading = %{version}-%{release} +Requires: python%{pybasever}-freethreading-tkinter = %{version}-%{release} + +Obsoletes: python%{pybasever}-freethreading < 3.14.0-2 + +%description -n python%{pybasever}-freethreading-idle +IDLE is Python's Integrated Development and Learning Environment for +the Free Threading build. + +IDLE has the following features: Python shell window (interactive +interpreter) with colorizing of code input, output, and error messages; +multi-window text editor with multiple undo, Python colorizing, +smart indent, call tips, auto completion, and other features; +search within any window, replace within editor windows, and +search through multiple files (grep); debugger with persistent +breakpoints, stepping, and viewing of global and local namespaces; +configuration, browsers, and other dialogs. +Run with `python%{pybasever}t -m idlelib`. + + +%package -n python%{pybasever}-freethreading-tkinter +Summary: A GUI toolkit for Free Threading Python +Requires: python%{pybasever}-freethreading = %{version}-%{release} + +# The importable module "turtle" is here, so provide python3.x-freethreading-turtle. +%py_provides python%{pybasever}-freethreading-turtle + +Obsoletes: python%{pybasever}-freethreading < 3.14.0-2 + +%description -n python%{pybasever}-freethreading-tkinter +The Tkinter (Tk interface) library is a graphical user interface toolkit for +the Free Threading Python interpreter. + + +%package -n python%{pybasever}-freethreading-test +Summary: The self-test suite for the Free Threading Python package +Requires: python%{pybasever}-freethreading = %{version}-%{release} +Requires: python%{pybasever}-freethreading-libs%{?_isa} = %{version}-%{release} + +%if %{with rpmwheels} +Requires: %{python_wheel_pkg_prefix}-setuptools-wheel +Requires: (%{python_wheel_pkg_prefix}-wheel-wheel if %{python_wheel_pkg_prefix}-setuptools-wheel < 71) +%else +Provides: bundled(python3dist(setuptools)) = %{setuptools_version} +%setuptools_bundled_provides +# License manually combined from Python + setuptools + wheel +License: Python-2.0.1 AND MIT AND Apache-2.0 AND (Apache-2.0 OR BSD-2-Clause) +%endif + +Obsoletes: python%{pybasever}-freethreading < 3.14.0-2 + +%description -n python%{pybasever}-freethreading-test +The self-test suite for the Free Threading Python interpreter. + +This is only useful to test Free Threading Python itself. For testing general +Python code with the Free Threading build, you should use the unittest module +from python%{pybasever}-freethreading-libs, or a library such as pytest. +%endif # with freethreading_build %if %{with freethreading_build} && %{with debug_build} %package -n python%{pybasever}-freethreading-debug Summary: Free Threading (PEP 703) version of the Python runtime (debug build) License: %{libs_license} -# This uses the pure Python modules from the freethreading package +# The debug build is an all-in-one package version of the regular build, and +# shares the same .py/.pyc files and directories as the regular build. Hence +# we depend on all of the subpackages of the regular build: Requires: python%{pybasever}-freethreading%{?_isa} = %{version}-%{release} +Requires: python%{pybasever}-freethreading-libs%{?_isa} = %{version}-%{release} +Requires: python%{pybasever}-freethreading-devel%{?_isa} = %{version}-%{release} +Requires: python%{pybasever}-freethreading-test%{?_isa} = %{version}-%{release} +Requires: python%{pybasever}-freethreading-tkinter%{?_isa} = %{version}-%{release} +Requires: python%{pybasever}-freethreading-idle%{?_isa} = %{version}-%{release} %description -n python%{pybasever}-freethreading-debug -The provisional Free Threading (PEP 703) build of Python. Debug build. +The Free Threading (PEP 703) build of Python. Debug build. CPython’s global interpreter lock (“GIL”) prevents multiple threads from executing Python code at the same time. The GIL is an obstacle to using @@ -784,15 +983,22 @@ extension modules. # setuptools.whl does not contain the vendored.txt files if [ -f %{_rpmconfigdir}/pythonbundles.py ]; then %{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt) --compare-with '%pip_bundled_provides' - %{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/test/wheeldata/wheel-*.whl wheel/vendored/vendor.txt) --compare-with '%wheel_bundled_provides' + %{_rpmconfigdir}/pythonbundles.py <(unzip -l Lib/test/wheeldata/setuptools-*.whl | grep -E '_vendor/.+dist-info/RECORD' | sed -E 's@^.*/([^-]+)-([^-]+)\.dist-info/.*$@\1==\2@') --compare-with '%setuptools_bundled_provides' fi %if %{with rpmwheels} rm Lib/ensurepip/_bundled/pip-%{pip_version}-py3-none-any.whl rm Lib/test/wheeldata/setuptools-%{setuptools_version}-py3-none-any.whl -rm Lib/test/wheeldata/wheel-%{wheel_version}-py3-none-any.whl %endif +# check if there were any changes to Doc/license.rst +# if so, a review of %%libs_license and %%license_file_hash is needed +found_hash=$(sha256sum Doc/license.rst | cut -f1 -d" ") +if [ "$found_hash" != %{license_file_hash} ]; then + echo "File hash mismatch: review Doc/license.rst for changes" + exit 1 +fi + # Remove all exe files to ensure we are not shipping prebuilt binaries # note that those are only used to create Microsoft Windows installers # and that functionality is broken on Linux anyway @@ -807,8 +1013,8 @@ rm -r Modules/_decimal/libmpdec rm configure pyconfig.h.in # Patch out the version requirement on autoconf 2.72 -# This can be removed when Fedora 40 goes EOL (2025-05-28) -sed -i "s/AC_PREREQ(\[2\.72\])/AC_PREREQ([2.71])/" configure.ac +# We need it to allow the version available in RHEL 9 +sed -i "s/AC_PREREQ(\[2\.72\])/AC_PREREQ([2.69])/" configure.ac # ====================================================== # Configuring and building the code: @@ -878,9 +1084,6 @@ BuildPython() { # Since we changed directories, we need to tell %%configure where to look. %global _configure $topdir/configure - # A workaround for https://bugs.python.org/issue39761 - export DFLAGS=" " - %configure \ --with-platlibdir=%{_lib} \ --enable-ipv6 \ @@ -903,6 +1106,12 @@ BuildPython() { $ExtraConfigArgs \ %{nil} +%if %{with jit} && %{without jit_build_stencils} + if [[ ! "$ConfName" =~ ^freethreading ]]; then + cp -a %{jit_stencils_source} %{jit_stencils_filename} + fi +%endif + %global flags_override EXTRA_CFLAGS="$MoreCFlags" CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags" %if %{without bootstrap} @@ -976,12 +1185,6 @@ topdir=$(pwd) DirHoldingGdbPy=%{_usr}/lib/debug/%{_libdir} mkdir -p %{buildroot}$DirHoldingGdbPy -# When the actual %%{dynload_dir} exists (it does when python3.X is installed for regen-all) -# %%{buildroot}%%{dynload_dir} is not created by make install and the extension modules are missing -# Reported upstream as https://github.com/python/cpython/issues/98782 -# A workaround is to create the directory before running make install -mkdir -p %{buildroot}%{dynload_dir} - # Multilib support for pyconfig.h # 32- and 64-bit versions of pyconfig.h are different. For multilib support # (making it possible to install 32- and 64-bit versions simultaneously), @@ -1072,6 +1275,9 @@ InstallPython optimized \ # Install directories for additional packages install -d -m 0755 %{buildroot}%{pylibdir}/site-packages/__pycache__ +%if %{with freethreading_build} +install -d -m 0755 %{buildroot}%{pylibdir_freethreading}/site-packages/__pycache__ +%endif %if "%{_lib}" == "lib64" # The 64-bit version needs to create "site-packages" in /usr/lib/ (for # pure-Python modules) as well as in /usr/lib64/ (for packages with extension @@ -1217,6 +1423,11 @@ for file in %{buildroot}%{pylibdir}/pydoc_data/topics.py $(grep --include='*.py' rm ${directory}/{__pycache__/${module}.cpython-%{pyshortver}.opt-?.pyc,${module}.py} done +%if %{without rpmwheels} +# Inject SBOM into the installed wheels (if the macro is available) +%{?python_wheel_inject_sbom:%python_wheel_inject_sbom %{buildroot}%{pylibdir}/ensurepip/_bundled/*.whl} +%endif + # ====================================================== # Checks for packaging issues # ====================================================== @@ -1252,6 +1463,17 @@ for Module in %{buildroot}/%{dynload_dir}/*.so ; do esac done +# Assert the pre-generated JIT stencils are up to date +%if %{with jit_build_stencils} +for ConfName in %{?with_debug_build:debug} optimized; do + if [ -s %{jit_stencils_source} ]; then + # The -I option ignores the checksum line (calculated from files incl. pyconfig.h which may change with new autoconf) + diff -u -I '^// [0-9a-f]\{64\}$' %{jit_stencils_source} build/${ConfName}/%{jit_stencils_filename} + else + echo "%{jit_stencils_source} is empty, not checking if it is up to date" + fi +done +%endif # ====================================================== # Running the upstream test suite @@ -1272,18 +1494,9 @@ CheckPython() { # Run the upstream test suite # --timeout=2700: kill test running for longer than 45 minutes - # test_freeze_simple_script is skipped, because it fails without bundled libs. - # the freeze tool is only usable from the source checkout anyway, - # we don't ship it in the RPM package. # test_check_probes is failing since it was introduced in 3.12.0rc1, # the test is skipped until it is fixed in upstream. # see: https://github.com/python/cpython/issues/104280#issuecomment-1669249980 - # test_signal is skipped due to https://github.com/python/cpython/issues/118989 - # test.test_concurrent_futures.test_deadlock tends to time out on s390x and ppc64le in - # freethreading{,-debug} build, skipping it to shorten the build time - # see: https://github.com/python/cpython/issues/121719 - # test_external_inspection sometimes fails on freethreading-debug - # see: https://github.com/python/cpython/issues/130035 LD_LIBRARY_PATH=$ConfDir $ConfDir/python -m test.regrtest \ -wW --slowest %{_smp_mflags} \ %ifarch riscv64 @@ -1291,16 +1504,7 @@ CheckPython() { %else --timeout=2700 \ %endif - -i test_freeze_simple_script \ -i test_check_probes \ - -i test_external_inspection \ - %ifarch %{mips64} - -x test_ctypes \ - %endif - %ifarch s390x ppc64le - -x test_signal \ - -i test_deadlock \ - %endif echo FINISHED: CHECKING OF PYTHON FOR CONFIGURATION: $ConfName @@ -1362,6 +1566,7 @@ CheckPython freethreading %{1}/_pyrepl/\ %{1}/asyncio/\ %{1}/collections/\ +%{1}/compression/\ %{1}/concurrent/\ %{1}/ctypes/\ %{1}/curses/\ @@ -1377,6 +1582,7 @@ CheckPython freethreading %{1}/pydoc_data/\ %{1}/re/\ %{1}/sqlite3/\ +%{1}/string/\ %{1}/sysconfig/\ %{1}/tomllib/\ %{1}/unittest/\ @@ -1435,12 +1641,10 @@ CheckPython freethreading %{1}/_codecs_jp.%{2}.so\ %{1}/_codecs_kr.%{2}.so\ %{1}/_codecs_tw.%{2}.so\ -%{1}/_contextvars.%{2}.so\ %{1}/_csv.%{2}.so\ %{1}/_ctypes.%{2}.so\ %{1}/_curses.%{2}.so\ %{1}/_curses_panel.%{2}.so\ -%{1}/_datetime.%{2}.so\ %{1}/_dbm.%{2}.so\ %{1}/_gdbm.%{2}.so\ %{1}/_decimal.%{2}.so\ @@ -1462,6 +1666,7 @@ CheckPython freethreading %{1}/_posixsubprocess.%{2}.so\ %{1}/_queue.%{2}.so\ %{1}/_random.%{2}.so\ +%{1}/_remote_debugging.%{2}.so\ %{1}/_sha1.%{2}.so\ %{1}/_sha2.%{2}.so\ %{1}/_sha3.%{2}.so\ @@ -1472,6 +1677,7 @@ CheckPython freethreading %{1}/_struct.%{2}.so\ %{1}/_uuid.%{2}.so\ %{1}/_zoneinfo.%{2}.so\ +%{1}/_zstd.%{2}.so\ %{1}/array.%{2}.so\ %{1}/binascii.%{2}.so\ %{1}/cmath.%{2}.so\ @@ -1590,7 +1796,6 @@ CheckPython freethreading %{1}/_testcapi.%{2}.so\ %{1}/_testclinic.%{2}.so\ %{1}/_testclinic_limited.%{2}.so\ -%{1}/_testexternalinspection.%{2}.so\ %{1}/_testimportmultiple.%{2}.so\ %{1}/_testinternalcapi.%{2}.so\ %{1}/_testlimitedcapi.%{2}.so\ @@ -1644,6 +1849,13 @@ CheckPython freethreading %if %{with freethreading_build} %files -n python%{pybasever}-freethreading +%{_bindir}/python%{LDVERSION_freethreading} +%doc README.rst + + +%files -n python%{pybasever}-freethreading-libs +%doc README.rst + %dir %{pylibdir_freethreading} %dir %{dynload_dir_freethreading} @@ -1653,42 +1865,84 @@ CheckPython freethreading # Pure Python modules %pure_python_modules %{pylibdir_freethreading} -# Modules that we separate from python3-libs, but want to ship in -freethreading -%{pylibdir_freethreading}/__phello__/ -%{pylibdir_freethreading}/idlelib/ -%{pylibdir_freethreading}/test/ -%{pylibdir_freethreading}/tkinter/ -%{pylibdir_freethreading}/turtledemo/ - %{pylibdir_freethreading}/_sysconfig_vars_%{ABIFLAGS_freethreading}_linux_%{platform_triplet}.json # File defined by PEP 739 since Python 3.14: %{pylibdir_freethreading}/build-details.json +# This will be in the -freethreading-tkinter package +%exclude %{pylibdir_freethreading}/turtle.py +%exclude %{pylibdir_freethreading}/__pycache__/turtle*%{bytecode_suffixes} + # This will be in the -freethreading-debug package %if %{with debug_build} %exclude %{pylibdir_freethreading}/_sysconfigdata_%{ABIFLAGS_freethreading_debug}_linux_%{platform_triplet}.py %exclude %{pylibdir_freethreading}/__pycache__/_sysconfigdata_%{ABIFLAGS_freethreading_debug}_linux_%{platform_triplet}%{bytecode_suffixes} %endif -# Analog of the core subpackage's files: -%{_bindir}/python%{LDVERSION_freethreading} +# Extension modules +%extension_modules %{dynload_dir_freethreading} %{SOABI_freethreading} -# Analog to the -libs subpackage's files: +%dir %{pylibdir_freethreading}/site-packages/ +%dir %{pylibdir_freethreading}/site-packages/__pycache__/ + +%if "%{_lib}" == "lib64" +%attr(0755,root,root) %dir %{_prefix}/lib/python%{pybasever}%{ABIFLAGS_freethreading}/ +%attr(0755,root,root) %dir %{_prefix}/lib/python%{pybasever}%{ABIFLAGS_freethreading}/site-packages/ +%attr(0755,root,root) %dir %{_prefix}/lib/python%{pybasever}%{ABIFLAGS_freethreading}/site-packages/__pycache__/ +%endif + +# "Makefile" and the config-32/64.h file are needed by +# sysconfig.get_config_vars(), so we include them in the core +# package, along with their parent directories: +%dir %{pylibdir_freethreading}/config-%{LDVERSION_freethreading}-%{platform_triplet}/ +%{pylibdir_freethreading}/config-%{LDVERSION_freethreading}-%{platform_triplet}/Makefile +%dir %{_includedir}/python%{LDVERSION_freethreading}/ +%{_includedir}/python%{LDVERSION_freethreading}/%{_pyconfig_h} + +# Finally, libpython %{_libdir}/%{py_INSTSONAME_freethreading} -%extension_modules %{dynload_dir_freethreading} %{SOABI_freethreading} -%extension_modules_test %{dynload_dir_freethreading} %{SOABI_freethreading} -%{dynload_dir_freethreading}/_tkinter.%{SOABI_freethreading}.so -# Analog of the -devel subpackage's files: -%{pylibdir_freethreading}/config-%{LDVERSION_freethreading}-%{platform_triplet}/ -%{_includedir}/python%{LDVERSION_freethreading}/ +%files -n python%{pybasever}-freethreading-devel +%{pylibdir_freethreading}/config-%{LDVERSION_freethreading}-%{platform_triplet}/* +%exclude %{pylibdir_freethreading}/config-%{LDVERSION_freethreading}-%{platform_triplet}/Makefile +%exclude %{_includedir}/python%{LDVERSION_freethreading}/%{_pyconfig_h} +%{_includedir}/python%{LDVERSION_freethreading}/*.h +%{_includedir}/python%{LDVERSION_freethreading}/internal/ +%{_includedir}/python%{LDVERSION_freethreading}/cpython/ + %{_bindir}/python%{LDVERSION_freethreading}-config %{_bindir}/python%{LDVERSION_freethreading}-*-config %{_libdir}/libpython%{LDVERSION_freethreading}.so %{_libdir}/pkgconfig/python-%{LDVERSION_freethreading}.pc %{_libdir}/pkgconfig/python-%{LDVERSION_freethreading}-embed.pc + +%files -n python%{pybasever}-freethreading-idle +%{pylibdir_freethreading}/idlelib/ + + +%files -n python%{pybasever}-freethreading-tkinter +%{pylibdir_freethreading}/tkinter/ +%{dynload_dir_freethreading}/_tkinter.%{SOABI_freethreading}.so +%{pylibdir_freethreading}/turtle.py +%{pylibdir_freethreading}/__pycache__/turtle*%{bytecode_suffixes} +%dir %{pylibdir_freethreading}/turtledemo/ +%{pylibdir_freethreading}/turtledemo/*.py +%{pylibdir_freethreading}/turtledemo/*.cfg +%dir %{pylibdir_freethreading}/turtledemo/__pycache__/ +%{pylibdir_freethreading}/turtledemo/__pycache__/*%{bytecode_suffixes} + + +%files -n python%{pybasever}-freethreading-test +%{pylibdir_freethreading}/test/ + +# Pure Python modules +%{pylibdir_freethreading}/__phello__/ + +# Extension modules +%extension_modules_test %{dynload_dir_freethreading} %{SOABI_freethreading} + %endif # with freethreading_build %if %{with freethreading_build} && %{with debug_build} @@ -1740,6 +1994,99 @@ CheckPython freethreading # ====================================================== %changelog +* Tue Aug 18 2026 Miro Hrončok - 3.14.7-2 +- On RHEL 9, also supports reparse deferral in expat + +* Mon Aug 10 2026 Karolina Surma - 3.14.7-1 +- Update to Python 3.14.7 + +* Thu Jul 16 2026 Fedora Release Engineering - 3.14.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild + +* Thu Jun 11 2026 Karolina Surma - 3.14.6-1 +- Update to Python 3.14.6 + +* Wed Jun 03 2026 Python Maint - 3.14.5-2 +- Rebuilt as non-main Python on Fedora 45+ + +* Mon May 11 2026 Miro Hrončok - 3.14.5-1 +- Update to 3.14.5 + +* Tue May 05 2026 Miro Hrončok - 3.14.5~rc1-1 +- Update to 3.14.5rc1 + +* Thu Apr 16 2026 Charalampos Stratakis - 3.14.4-2 +- Security fixes for CVE-2026-1502, CVE-2026-4786, CVE-2026-5713, CVE-2026-6100 +Resolves: rhbz#2457944, rhbz#2458224, rhbz#2458488, rhbz#2458016 + +* Wed Apr 08 2026 Karolina Surma - 3.14.4-1 +- Update to Python 3.14.4 + +* Thu Mar 26 2026 Lumír Balhar - 3.14.3-2 +- Security fix for CVE-2026-4519 (rhbz#2449730) + +* Wed Feb 04 2026 Karolina Surma - 3.14.3-1 +- Update to Python 3.14.3 +- Fix CVE-2025-15366, CVE-2025-15367 + +* Sat Jan 17 2026 Fedora Release Engineering - 3.14.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild + +* Tue Jan 06 2026 Karolina Surma - 3.14.2-2 +- Require at least the same expat version as used during the build time + +* Fri Dec 05 2025 Miro Hrončok - 3.14.2-1 +- Update to Python 3.14.2 + +* Wed Dec 03 2025 Karolina Surma - 3.14.1-1 +- Update to Python 3.14.1 + +* Fri Oct 17 2025 Karolina Surma - 3.14.0-2 +- Split -freethreading package into analogs of the main Python + +* Tue Oct 07 2025 Karolina Surma - 3.14.0-1 +- Update to Python 3.14.0 + +* Thu Sep 18 2025 Karolina Surma - 3.14.0~rc3-1 +- Update to Python 3.14.0rc3 +- The .pyc magic number was bumped again + +* Thu Aug 14 2025 Miro Hrončok - 3.14.0~rc2-1 +- Update to Python 3.14.0rc2 +- The .pyc magic number was bumped + +* Fri Jul 25 2025 Fedora Release Engineering - 3.14.0~rc1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + +* Tue Jul 22 2025 Miro Hrončok - 3.14.0~rc1-1 +- Update to Python 3.14.0rc1 + +* Tue Jul 08 2025 Miro Hrončok - 3.14.0~b4-1 +- Update to Python 3.14.0b4 + +* Wed Jun 25 2025 Karolina Surma - 3.14.0~b3-3 +- Conditionally skip tests not working with the older expat version + +* Wed Jun 18 2025 Charalampos Stratakis - 3.14.0~b3-2 +- Enable PAC and BTI hardware protections for aarch64 + +* Tue Jun 17 2025 Miro Hrončok - 3.14.0~b3-1 +- Update to Python 3.14.0b3 +- The .pyc magic number was bumped +- python3.14-freethreading is no longer provisional + +* Mon Jun 02 2025 Python Maint - 3.14.0~b2-3 +- Rebuilt for Python 3.14 + +* Mon Jun 02 2025 Python Maint - 3.14.0~b2-2 +- Bootstrap for Python 3.14 + +* Mon May 26 2025 Miro Hrončok - 3.14.0~b2-1 +- Update to Python 3.14.0b2 + +* Wed May 07 2025 Karolina Surma - 3.14.0~b1-1 +- Update to Python 3.14.0b1 + * Mon May 05 2025 Miro Hrončok - 3.14.0~a7-3 - Drop requirement on python-wheel-wheel with setuptools >= 71 diff --git a/rpminspect.yaml b/rpminspect.yaml index 83dfb5e..8cc18cb 100644 --- a/rpminspect.yaml +++ b/rpminspect.yaml @@ -1,22 +1,22 @@ # exclude test XML data (not always valid) from XML validity check: xml: ignore: - - /usr/lib*/python*/test/xmltestdata/* - - /usr/lib*/python*/test/xmltestdata/*/* + - '/usr/lib*/python*/test/xmltestdata/*' + - '/usr/lib*/python*/test/xmltestdata/*/*' # exclude _socket from ipv4 only functions check, it has both ipv4 and ipv6 only badfuncs: allowed: - /usr/lib*/python*/lib-dynload/_socket.*: + '/usr/lib*/python*/lib-dynload/_socket.*': - inet_aton - inet_ntoa # exclude the debug build from annocheck entirely annocheck: ignore: - - /usr/bin/python*d - - /usr/lib*/libpython*d.so.1.0 - - /usr/lib*/python*/lib-dynload/*.cpython-*d-*-*-*.so + - '/usr/bin/python*d' + - '/usr/lib*/libpython*d.so.1.0' + - '/usr/lib*/python*/lib-dynload/*.cpython-*d-*-*-*.so' # don't report changed content of compiled files # that is expected with every toolchain update and not reproducible yet diff --git a/rpmlint.toml b/rpmlint.toml index 0864a1c..7ed20ba 100644 --- a/rpmlint.toml +++ b/rpmlint.toml @@ -6,7 +6,7 @@ Filters = [ # TESTS: - '(zero-length|pem-certificate|uncompressed-zip) /usr/lib(64)?/python3\.\d+t?/test', + '(zero-length|pem-certificate|uncompressed-zip|file-not-in-%lang) /usr/lib(64)?/python3\.\d+t?/test', # OTHER DELIBERATES: @@ -21,6 +21,9 @@ Filters = [ 'unversioned Obsoletes: Obsoletes: python3\.\d+$', 'self-obsoletion python3\.\d+(-\S+)? obsoletes python3\.\d+(-\S+)?', + # freethreading subpackages obsolete python3.X-freethreading, but don't provide it + '^python3(\.\d+)?-freethreading(-\w+)?\.[^:]+: (E|W): obsolete-not-provided python3(\.\d+)?-freethreading$', + # intentionally hardcoded 'hardcoded-library-path in %{_prefix}/lib/(debug/%{_libdir}|python%{pybasever})', @@ -37,6 +40,9 @@ Filters = [ # if this regex needs to be relaxed in the future, make sure it **does not** match pyc files in __pycache__ 'python-bytecode-without-source /usr/lib(64)?/python3\.\d+t?/(encodings|pydoc_data)/[^/]+.pyc', + # https://docs.fedoraproject.org/en-US/packaging-guidelines/RPM_Source_Dir/#_exceptions + 'use-of-RPM_SOURCE_DIR', + # DUPLICATE FILES # test data are often duplicated '(E|W): files-duplicate /usr/lib(64)?/python3\.\d+t?/(test|__phello__)/', @@ -55,7 +61,10 @@ Filters = [ 'no-manual-page-for-binary python3\.\d+t?dm?$', # missing documentation from subpackages - '^python3(\.\d+)?-(freethreading(-debug)?|debug|tkinter|test|idle)\.[^:]+: (E|W): no-documentation', + '^python3(\.\d+)?-(freethreading(-\w+)?|debug|tkinter|test|idle)\.[^:]+: (E|W): no-documentation', + + # idle subpackages have no binaries + '^python3(\.\d+)?-(freethreading-)?idle\.[^:]+: (E|W): no-binary', # platform python is obsoleted, but not provided 'obsolete-not-provided platform-python', @@ -101,6 +110,6 @@ Filters = [ '\bpython3(\.\d+)?\.(src|spec): (E|W): specfile-error\s+$', # SPELLING ERRORS - 'spelling-error .* en_US (bytecode|pyc|filename|tkinter|namespaces|pytest|unittest|gil) ', + 'spelling-error .*\b(bytecode|pyc|filename|tkinter|namespaces|pytest|unittest|gil|CPython)\b', ] diff --git a/sources b/sources index e82978e..48e32a1 100644 --- a/sources +++ b/sources @@ -1 +1,5 @@ -SHA512 (Python-3.14.0a7.tar.xz) = f7e50c201cb1bbc4779d898e65408147637de7b9d9d85a2e6ad4f8dda758ec150dfb95ee1f12c686a3f46c29a986a75b45323bcbab87b81b319d91236989f6b0 +SHA512 (Python-3.14.7.tar.xz) = 3d4e2e2f983b320dec47005c408d7178d3656a6de0c4430ce21514797174b972f461200898b25d3dfac2a455019ef87e45d0fb2bb6ec2ca887124d10037a2a07 +SHA512 (Python-3.14.7-aarch64-debug-jit_stencils.h) = 85bf4cdf5996ede2932aa1b5ffb0c3befe7fb395efdadaeedc05969bbf8f4db1fe825666276239183ec24caa58f2307983876b29efa86ac54bd5802c85ab1d3c +SHA512 (Python-3.14.7-aarch64-optimized-jit_stencils.h) = e7245f166126184655275dd5a90a4251e73ed042fc0d9b46624f55faa698a676a6714f8d2577aecd0a03fb54a6fda3d23b1391a1872b66c130b79b817699ab82 +SHA512 (Python-3.14.7-x86_64-debug-jit_stencils.h) = e34b31bcc3959b3fbd9cac07df69eababfab2ff42101a0dc14af34c67775c73ef48dcac658ac0c1f58c8c2957bd88a553a748f849e566d4cf66c0a5d9722f14d +SHA512 (Python-3.14.7-x86_64-optimized-jit_stencils.h) = d17bf0d61136580dfe589dbcac2d51bbb3fa75f467e008ad2000a7f778427f32aef3f88efb46a1c01c4aa4af8878d51d4f4e0b1d18976906ea332bfe6c11e1fe diff --git a/tests/provision.fmf b/tests/provision.fmf deleted file mode 100644 index 1a4f0f0..0000000 --- a/tests/provision.fmf +++ /dev/null @@ -1,4 +0,0 @@ ---- -standard-inventory-qcow2: - qemu: - m: 3G # Amount of VM memory diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index b1255ce..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,68 +0,0 @@ ---- -- hosts: localhost - tags: - - classic - tasks: - - dnf: - name: "*" - state: latest - -- hosts: localhost - roles: - - role: standard-test-basic - tags: - - classic - repositories: - - repo: "https://src.fedoraproject.org/tests/python.git" - dest: "python" - pybasever: "3.14" - tests: - - rpm_qa: - run: rpm -qa - - smoke: - dir: python/smoke - run: "VERSION={{ pybasever }} CYTHON=false ./venv.sh" - - smoke_virtualenv: - dir: python/smoke - run: "VERSION={{ pybasever }} METHOD=virtualenv CYTHON=false ./venv.sh" - - debugsmoke: - dir: python/smoke - run: "PYTHON=python{{ pybasever }}d TOX=false VERSION={{ pybasever }} CYTHON=false ./venv.sh" - - selftest: - dir: python/selftest - run: "VERSION={{ pybasever }} X='-i test_check_probes -i test_sysconfigdata_json' ./parallel.sh" - - debugtest: - dir: python/selftest - # test_base_interpreter: https://github.com/python/cpython/issues/131372 - run: "VERSION={{ pybasever }} PYTHON=python{{ pybasever }}d X='-i test_check_probes -i test_sysconfigdata_json -i test_base_interpreter' ./parallel.sh" - - optimizedflags: - dir: python/flags - run: "python{{ pybasever }} ./assertflags.py -O3 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS" - - debugflags: - dir: python/flags - run: "python{{ pybasever }}d ./assertflags.py -O0 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS" - - freethreadingflags: - dir: python/flags - run: "python{{ pybasever }}t ./assertflags.py -O3 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS" - - freethreadingdebugflags: - dir: python/flags - run: "python{{ pybasever }}td ./assertflags.py -O0 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS" - - marshalparser: - dir: python/marshalparser - run: "VERSION={{ pybasever }} SAMPLE=10 test_marshalparser_compatibility.sh" - required_packages: - - gcc # for extension building in venv and selftest - - gcc-c++ # for test_cppext - - gdb # for test_gdb - - "python{{ pybasever }}" # the test subject - - "python{{ pybasever }}-debug" # for leak testing - - "python{{ pybasever }}-devel" # for extension building in venv and selftest - - "python{{ pybasever }}-tkinter" # for selftest - - "python{{ pybasever }}-test" # for selftest - - "python{{ pybasever }}-freethreading" # for -O... flag test - - "python{{ pybasever }}-freethreading-debug" # for -O... flag test - - tox # for venv tests - - virtualenv # for virtualenv tests - - glibc-all-langpacks # for locale tests - - marshalparser # for testing compatibility (magic numbers) with marshalparser - - rpm # for debugging