Compare commits

..

No commits in common. "rawhide" and "f40" have entirely different histories.

20 changed files with 558 additions and 1188 deletions

1
.gitignore vendored
View file

@ -1,4 +1,3 @@
/*.tar.*
/*-jit_stencils.h
/*.src.rpm
/results_python3*

View file

@ -30,10 +30,10 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
3 files changed, 72 insertions(+), 4 deletions(-)
diff --git a/Lib/site.py b/Lib/site.py
index aeb7c6cfc7..86f9ae9e76 100644
index 9da8b6724e..b53dd21d51 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -421,8 +421,15 @@ def getsitepackages(prefixes=None):
@@ -420,8 +420,15 @@ def getsitepackages(prefixes=None):
return sitepackages
def addsitepackages(known_paths, prefixes=None):
@ -51,7 +51,7 @@ index aeb7c6cfc7..86f9ae9e76 100644
if os.path.isdir(sitedir):
addsitedir(sitedir, known_paths)
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index faf8273bd0..d7667bbc77 100644
index 18e6b8d25e..42df12fad4 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -106,6 +106,12 @@
@ -130,10 +130,10 @@ index faf8273bd0..d7667bbc77 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 1fe4b6849f..e0cb3ec23a 100644
index cc11eade2e..b4f8aabaef 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -132,8 +132,19 @@ def test_get_path(self):
@@ -131,8 +131,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 1fe4b6849f..e0cb3ec23a 100644
os.path.normpath(expected),
)
@@ -397,7 +408,7 @@ def test_get_config_h_filename(self):
@@ -387,7 +398,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 1fe4b6849f..e0cb3ec23a 100644
if HAS_USER_BASE:
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
@@ -409,6 +420,8 @@ def test_symlink(self): # Issue 7880
@@ -399,6 +410,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))

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Karolina Surma <ksurma@redhat.com>
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 \

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Karolina Surma <ksurma@redhat.com>
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))

View file

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
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);

View file

@ -0,0 +1,120 @@
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 <vstinner@python.org>
---
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,

View file

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
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)

View file

@ -1,133 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
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"<doc>text</doc>")
- @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 ("<doc", ">"):
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 ("<doc", ">"):
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;

View file

@ -1,59 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Seth Michael Larson <seth@python.org>
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.

View file

@ -1,156 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <encukou@gmail.com>
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 <ksurma@redhat.com>
---
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)
{

View file

@ -1,146 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
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):

View file

@ -1,23 +0,0 @@
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,},} || :

View file

@ -1,93 +0,0 @@
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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -6,7 +6,7 @@ Filters = [
# TESTS:
'(zero-length|pem-certificate|uncompressed-zip|file-not-in-%lang) /usr/lib(64)?/python3\.\d+t?/test',
'(zero-length|pem-certificate|uncompressed-zip) /usr/lib(64)?/python3\.\d+t?/test',
# OTHER DELIBERATES:
@ -21,9 +21,6 @@ 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})',
@ -40,9 +37,6 @@ 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__)/',
@ -61,10 +55,7 @@ Filters = [
'no-manual-page-for-binary python3\.\d+t?dm?$',
# missing documentation from subpackages
'^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',
'^python3(\.\d+)?-(freethreading(-debug)?|debug|tkinter|test|idle)\.[^:]+: (E|W): no-documentation',
# platform python is obsoleted, but not provided
'obsolete-not-provided platform-python',
@ -110,6 +101,6 @@ Filters = [
'\bpython3(\.\d+)?\.(src|spec): (E|W): specfile-error\s+$',
# SPELLING ERRORS
'spelling-error .*\b(bytecode|pyc|filename|tkinter|namespaces|pytest|unittest|gil|CPython)\b',
'spelling-error .* en_US (bytecode|pyc|filename|tkinter|namespaces|pytest|unittest|gil) ',
]

View file

@ -1,5 +1 @@
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
SHA512 (Python-3.14.0a7.tar.xz) = f7e50c201cb1bbc4779d898e65408147637de7b9d9d85a2e6ad4f8dda758ec150dfb95ee1f12c686a3f46c29a986a75b45323bcbab87b81b319d91236989f6b0

4
tests/provision.fmf Normal file
View file

@ -0,0 +1,4 @@
---
standard-inventory-qcow2:
qemu:
m: 3G # Amount of VM memory

68
tests/tests.yml Normal file
View file

@ -0,0 +1,68 @@
---
- 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