Compare commits

..

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

11 changed files with 243 additions and 800 deletions

View file

@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
Date: Mon, 15 Feb 2021 12:19:27 +0100
Subject: 00251: Change user install location
Subject: [PATCH] 00251: Change user install location
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -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 041dca113a..ca6320df2f 100644
index 0a0dc47b17..bb42e1cf5a 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -415,8 +415,15 @@ def getsitepackages(prefixes=None):
@@ -414,8 +414,15 @@ def getsitepackages(prefixes=None):
return sitepackages
def addsitepackages(known_paths, prefixes=None):
@ -51,7 +51,7 @@ index 041dca113a..ca6320df2f 100644
if os.path.isdir(sitedir):
addsitedir(sitedir, known_paths)
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index 43edebce34..40e85568ea 100644
index 80aef34471..4e4ea6aeea 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -106,6 +106,12 @@
@ -87,7 +87,7 @@ index 43edebce34..40e85568ea 100644
_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
'scripts', 'data')
@@ -266,11 +285,40 @@ def _extend_dict(target_dict, other_dict):
@@ -261,11 +280,40 @@ def _extend_dict(target_dict, other_dict):
target_dict[key] = value
@ -120,7 +120,7 @@ index 43edebce34..40e85568ea 100644
+ # we only change the defaults here, so explicit --prefix will take precedence
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
+ if (scheme == 'posix_prefix' and
+ sys.prefix == '/usr' and
+ _PREFIX == '/usr' and
+ 'RPM_BUILD_ROOT' not in os.environ):
+ _extend_dict(vars, _config_vars_local())
+ else:
@ -130,10 +130,10 @@ index 43edebce34..40e85568ea 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 ce17206a3c..fd95071099 100644
index 1ade49281b..e21ca34733 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -130,8 +130,19 @@ def test_get_path(self):
@@ -121,8 +121,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 ce17206a3c..fd95071099 100644
os.path.normpath(expected),
)
@@ -395,7 +406,7 @@ def test_get_config_h_filename(self):
@@ -377,7 +388,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 ce17206a3c..fd95071099 100644
if HAS_USER_BASE:
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
@@ -407,6 +418,8 @@ def test_symlink(self): # Issue 7880
@@ -389,6 +400,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

@ -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 ae7cec6540..7f73a8c5e7 100644
--- a/Lib/test/test_pyexpat.py
+++ b/Lib/test/test_pyexpat.py
@@ -1001,7 +1001,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)
@@ -1010,7 +1010,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')
@@ -1041,7 +1041,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 9b3014a94a..0e38c9488e 100644
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -1215,7 +1215,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):
@@ -1249,7 +1249,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 4a76a5be1e..effb899d7b 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1804,7 +1804,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):
@@ -1834,7 +1834,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 9e5d84eb5e..b008fe66c1 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -781,7 +781,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
@@ -1446,7 +1446,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;
@@ -2332,7 +2332,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
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 eb6dab4015..bd621caee4 100644
--- a/Lib/test/test_poplib.py
+++ b/Lib/test/test_poplib.py
@@ -18,6 +18,7 @@
from test.support import asynchat
from test.support import asyncore
from test.support.testcase import ExtraAssertions
+from test.support import control_characters_c0
test_support.requires_working_socket(module=True)
@@ -396,6 +397,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,173 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <encukou@gmail.com>
Date: Mon, 9 Feb 2026 10:44:21 +0100
Subject: 00477: Raise an error when importing stdlib modules compiled for a
different Python version
This is a downstream workaround "implementing" python#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.
_curses, _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/_cursesmodule.c | 6 ++++++
Modules/_tkinter.c | 6 ++++++
Modules/_tracemalloc.c | 6 ++++++
Modules/readline.c | 6 ++++++
Objects/moduleobject.c | 1 +
7 files changed, 71 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 2363b99a25..f1a07645f0 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -3159,3 +3159,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/_cursesmodule.c b/Modules/_cursesmodule.c
index 1996488a0e..cfdffd8ec4 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -5011,6 +5011,12 @@ curses_destructor(PyObject *op)
PyMODINIT_FUNC
PyInit__curses(void)
{
+ #ifdef _PyHack_check_version_on_modinit
+ if (_PyHack_CheckInternalAPIVersion("_curses") < 0) {
+ return NULL;
+ }
+ #endif
+
PyObject *m, *d, *v, *c_api_object;
/* Initialize object type */
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 4e8d75e8e1..32e58755aa 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -3499,6 +3499,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 0b85187e5f..87f358ed07 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 *m;
m = PyModule_Create(&module_def);
if (m == NULL)
diff --git a/Modules/readline.c b/Modules/readline.c
index 7a612deae4..8b2f47eec1 100644
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -1548,6 +1548,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 d787f29004..31175ceb3f 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -43,6 +43,7 @@ _PyModule_IsExtension(PyObject *obj)
}
+#undef PyModuleDef_Init
PyObject*
PyModuleDef_Init(PyModuleDef* def)
{

View file

@ -1,77 +0,0 @@
execute:
how: tmt
provision:
hardware:
memory: '>= 3 GB'
environment:
pybasever: '3.13'
discover:
- name: tests_python
how: shell
url: https://src.fedoraproject.org/tests/python.git
tests:
- name: smoke
path: /smoke
test: "VERSION=${pybasever} CYTHON=false ./venv.sh"
- name: smoke_virtualenv
path: /smoke
test: "VERSION=${pybasever} METHOD=virtualenv CYTHON=false ./venv.sh"
- name: debugsmoke
path: /smoke
test: "PYTHON=python${pybasever}d TOX=false VERSION=${pybasever} CYTHON=false ./venv.sh"
- name: selftest
path: /selftest
test: "VERSION=${pybasever} X='-i test_check_probes' ./parallel.sh"
- name: debugtest
path: /selftest
test: "VERSION=${pybasever} PYTHON=python${pybasever}d X='-i test_check_probes' ./parallel.sh"
- 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
- 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

View file

@ -1,35 +1,3 @@
# ======================
# 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
# ==================
@ -45,11 +13,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}.15
%global general_version %{pybasever}.0
#global prerel ...
%global upstream_version %{general_version}%{?prerel}
Version: %{general_version}%{?prerel:~%{prerel}}
Release: 2%{?dist}
Release: 1%{?dist}
License: Python-2.0.1
@ -57,105 +25,156 @@ License: Python-2.0.1
# Conditionals controlling the build
# ==================================
# Note that the bcond macros are named for the CLI option they create.
# "%%bcond_without" means "ENABLE by default and create a --without option"
# Main Python, i.e. whether this is the main Python version in the distribution
# that owns /usr/bin/python3 and other unique paths
# This also means the built subpackages are called python3 rather than python3X
# By default, this is determined by the %%__default_python3_pkgversion value
%bcond main_python %["%{?__default_python3_pkgversion}" == "%{pybasever}"]
%if "%{?__default_python3_pkgversion}" == "%{pybasever}"
%bcond_without main_python
%else
%bcond_with main_python
%endif
# If this is *not* Main Python, should it contain `Provides: python(abi) ...`?
# In Fedora no package shall depend on an alternative Python via this tag, so we do not provide it.
# 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}
%if 0%{?fedora}
%bcond_with python_abi_provides_for_alt_pythons
%else
%bcond_without python_abi_provides_for_alt_pythons
%endif
# 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_with bootstrap
# Whether to use RPM build wheels from the python-{pip,setuptools,wheel}-wheel packages
# Uses upstream bundled prebuilt wheels otherwise
%bcond_without rpmwheels
# 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 24.2
%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
Provides: bundled(python3dist(certifi)) = 2024.7.4
Provides: bundled(python3dist(distlib)) = 0.3.8
Provides: bundled(python3dist(distro)) = 1.9
Provides: bundled(python3dist(idna)) = 3.7
Provides: bundled(python3dist(msgpack)) = 1.0.8
Provides: bundled(python3dist(packaging)) = 24.1
Provides: bundled(python3dist(platformdirs)) = 4.2.2
Provides: bundled(python3dist(pygments)) = 2.18
Provides: bundled(python3dist(pyproject-hooks)) = 1
Provides: bundled(python3dist(requests)) = 2.32.3
Provides: bundled(python3dist(resolvelib)) = 1.0.1
Provides: bundled(python3dist(rich)) = 13.7.1
Provides: bundled(python3dist(setuptools)) = 70.3
Provides: bundled(python3dist(tomli)) = 2.0.1
Provides: bundled(python3dist(truststore)) = 0.9.1
Provides: bundled(python3dist(typing-extensions)) = 4.12.2
Provides: bundled(python3dist(urllib3)) = 1.26.18
}
# 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_without optimizations
# Run the test suite in %%check
%bcond_without tests
# Extra build for debugging the interpreter or C-API extensions
# (the -debug subpackages)
%bcond debug_build 1
%bcond_without debug_build
# Extra build without GIL, the freethreading PEP 703 provisional way
# (the -freethreading subpackage)
%bcond freethreading_build 1
%bcond_without freethreading_build
# PEP 744: JIT Compilation
# Whether to build with the experimental JIT compiler
# We can only have this on Fedora 40+, where clang 18+ is available
# And only on certain architectures: https://peps.python.org/pep-0744/#support
# The freethreading build (when enabled) does not support JIT yet
%bcond jit %[(0%{?fedora} >= 40 || 0%{?epel} >= 10) && ("%{_arch}" == "x86_64" || "%{_arch}" == "aarch64")]
%bcond_with jit
%ifarch x86_64 aarch64
%if 0%{?fedora} >= 40 || 0%{?rhel} >= 10
%bcond_without jit
%endif
%endif
%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
%endif
# Support for the GDB debugger
%bcond_without gdb_hooks
# The dbm.gnu module (key-value database)
%bcond_without gdbm
# Main interpreter loop optimization
%bcond computed_gotos 1
%bcond_without computed_gotos
# Support for the Valgrind debugger/profiler
%ifarch %{valgrind_arches}
%bcond_without valgrind
%else
%bcond_with valgrind
%endif
# =====================
# 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}
@ -254,10 +273,10 @@ Obsoletes: python%{pybasever}%{?1:-%{1}}\
BuildRequires: autoconf
BuildRequires: bluez-libs-devel
BuildRequires: bzip2-devel
BuildRequires: expat-devel >= 2.5.0-2
# See the runtime requirement in the -libs subpackage
BuildRequires: expat-devel >= 2.6
BuildRequires: findutils
BuildRequires: gcc
BuildRequires: gdbm-devel
BuildRequires: git-core
BuildRequires: glibc-devel
BuildRequires: gnupg2
@ -267,22 +286,19 @@ BuildRequires: libuuid-devel
BuildRequires: make
BuildRequires: mpdecimal-devel
BuildRequires: ncurses-devel
BuildRequires: openssl-devel
BuildRequires: pkgconfig
BuildRequires: python-rpm-macros
BuildRequires: readline-devel
BuildRequires: redhat-rpm-config >= 127
BuildRequires: sqlite-devel
BuildRequires: systemtap-sdt-devel
BuildRequires: tcl-devel < 1:9
BuildRequires: tk-devel < 1:9
BuildRequires: tcl-devel
BuildRequires: tk-devel
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 %{undefined rhel}
BuildRequires: libb2-devel
%endif
@ -299,10 +315,14 @@ BuildRequires: clang(major) = 18
BuildRequires: llvm(major) = 18
%endif
%ifarch %{valgrind_arches}
%if %{with valgrind}
BuildRequires: valgrind-devel
%endif
%if %{with gdbm}
BuildRequires: gdbm-devel
%endif
%if %{with main_python}
BuildRequires: desktop-file-utils
BuildRequires: libappstream-glib
@ -314,7 +334,7 @@ BuildRequires: libappstream-glib
BuildRequires: %{python_wheel_pkg_prefix}-pip-wheel >= 23.1.2
%if %{with tests}
BuildRequires: %{python_wheel_pkg_prefix}-setuptools-wheel
BuildRequires: (%{python_wheel_pkg_prefix}-wheel-wheel if %{python_wheel_pkg_prefix}-setuptools-wheel < 71)
BuildRequires: %{python_wheel_pkg_prefix}-wheel-wheel
%endif
%endif
@ -353,7 +373,7 @@ Source11: idle3.appdata.xml
# (Patches taken from github.com/fedora-python/cpython)
# 00251 # 5ac6e7781923cbb3e4606e3bca381a1167d322e5
# 00251 # 60dd97be7bf3662ff65edd8471e948924b4175b2
# Change user install location
#
# Set values of base and platbase in sysconfig from /usr
@ -370,46 +390,6 @@ Source11: idle3.appdata.xml
# pypa/distutils integration: https://github.com/pypa/distutils/pull/70
Patch251: 00251-change-user-install-location.patch
# 00466 # 713a1368544eddd55088d67f88a23ce31722a4cb
# 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.
Patch466: 00466-downstream-only-lower-xml_combined_version-threshold-for-reparse-deferral.patch
# 00475 # d44fac01037662db286449a78c8fb819788f764c
# CVE-2025-15367
#
# Reject control characters in POP3 commands
Patch475: 00475-cve-2025-15367.patch
# 00477 # 9c62c492e7f2e3b152dbf287c08d307c3f013221
# Raise an error when importing stdlib modules compiled for a different Python version
#
# This is a downstream workaround "implementing" python#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.
#
# _curses, _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
# (New patches go here ^^^)
#
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
@ -530,38 +510,9 @@ This package contains /usr/bin/python - the "python" command that runs Python 3.
%package -n %{pkgname}-libs
Summary: Python runtime libraries
# Python is generally licensed as Python-2.0.1 but also includes incorporated software
# Combined manually from https://docs.python.org/3.13/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 952ac05720d7f1dcb63589b35eb0931b1442eb250230a4ad31198eddf0ad6abc
# 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
# An extract of the `Unicode Character Database` converted to an internal format is Unicode-3.0
# Bundled libb2 is not declared in the upstream document, but it's:
# CC0-1.0, covered by grandfathering exception
# We don't query upstream for changes, as 3.13 is the last Python version containing it.
%global libs_license Python-2.0.1 AND CC0-1.0 AND MIT AND BSD-3-Clause AND MIT-CMU AND HPND-SMC AND BSD-2-Clause AND dtoa AND Unicode-3.0
# Bundled libb2 is CC0, covered by grandfathering exception
# Bundled mimalloc is MIT
%global libs_license Python-2.0.1 AND CC0-1.0 AND MIT
%if %{with rpmwheels}
Requires: %{python_wheel_pkg_prefix}-pip-wheel >= 23.1.2
License: %{libs_license}
@ -569,7 +520,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 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 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
%unversioned_obsoletes_of_python3_X_if_main libs
@ -598,26 +549,12 @@ Recommends: (%{pkgname}-tkinter%{?_isa} = %{version}-%{release} if tk%{?_isa})
Requires: tzdata
# The requirement on libexpat is generated, but we need to version it.
# When built with a specific expat version, but installed with an older one,
# we sometimes get:
# When built with expat >= 2.6, but installed with older expat, we get:
# ImportError: /usr/lib64/python3.X/lib-dynload/pyexpat.cpython-....so:
# 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.
# undefined symbol: XML_SetReparseDeferralEnabled
# 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.
# 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
Requires: expat >= 2.6
%description -n %{pkgname}-libs
This package contains runtime libraries for use by Python:
@ -715,10 +652,12 @@ Requires: %{pkgname}-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)
Requires: %{python_wheel_pkg_prefix}-wheel-wheel
%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
@ -778,15 +717,17 @@ Summary: Free Threading (PEP 703) version of the Python runtime
%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)
Requires: %{python_wheel_pkg_prefix}-wheel-wheel
License: %{libs_license}
%else
Provides: bundled(python3dist(pip)) = %{pip_version}
%pip_bundled_provides
Provides: bundled(python3dist(setuptools)) = %{setuptools_version}
%setuptools_bundled_provides
# License combined from Python libs + pip + setuptools
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)
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
# This package doesn't depend on python3-libs, so we need to explicitly
@ -795,9 +736,7 @@ License: %{libs_license} AND Apache-2.0 AND ISC AND LGPL-2.1-only AND MPL-2.0 AN
Provides: bundled(libb2) = 0.98.1
Provides: bundled(mimalloc) = 2.12
Requires: tzdata
%if v"%{expat_version}" < v"2.7.4"
Requires: expat%{?_isa} >= %{expat_version}
%endif
Requires: expat >= 2.6
%description -n python%{pybasever}-freethreading
The provisional Free Threading (PEP 703) build of Python.
@ -850,22 +789,15 @@ 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 -l Lib/test/wheeldata/setuptools-*.whl | grep -E '_vendor/.+dist-info/RECORD' | sed -E 's@^.*/([^-]+)-([^-]+)\.dist-info/.*$@\1==\2@') --compare-with '%setuptools_bundled_provides'
%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/test/wheeldata/wheel-*.whl wheel/vendored/vendor.txt) --compare-with '%wheel_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
@ -879,8 +811,6 @@ rm -r Modules/_decimal/libmpdec
# (This is after patching, so that we can use patches directly from upstream)
rm configure pyconfig.h.in
# Lower the minimal required version of autoconf to enable build for EPEL 9
sed -i "s/AC_PREREQ(\[2\.71\])/AC_PREREQ([2.69])/" configure.ac
# ======================================================
# Configuring and building the code:
@ -961,6 +891,7 @@ BuildPython() {
--with-computed-gotos=%{computed_gotos_flag} \
--with-dbmliborder=gdbm:ndbm:bdb \
--with-system-expat \
--with-system-ffi \
--with-system-libmpdec \
--enable-loadable-sqlite-extensions \
--with-dtrace \
@ -970,23 +901,12 @@ BuildPython() {
%if %{with rpmwheels}
--with-wheel-pkg-dir=%{python_wheel_dir} \
%endif
%ifarch %{valgrind_arches}
%if %{with valgrind}
--with-valgrind \
%endif
$ExtraConfigArgs \
%{nil}
%if 0%{?fedora} && 0%{?fedora} < 42
# Statically compile the _datetime module to mitigate:
# Segfault when updating from 3.13.0 to 3.13.1 while Python is running
# https://bugzilla.redhat.com/2333852
# Note that this is an incomplete workaround for the case we know about,
# we'd like to see the cause fixed properly in Python 3.14 upstream:
# https://github.com/python/cpython/issues/128341
# This is only carried on Fedoras released before Python 3.13.1.
echo -e '*static*\n_datetime _datetimemodule.c' > Modules/Setup.local
%endif
%global flags_override EXTRA_CFLAGS="$MoreCFlags" CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags"
%if %{without bootstrap}
@ -1057,8 +977,10 @@ topdir=$(pwd)
# See https://fedoraproject.org/wiki/Features/EasierPythonDebugging for more
# information
%if %{with gdb_hooks}
DirHoldingGdbPy=%{_usr}/lib/debug/%{_libdir}
mkdir -p %{buildroot}$DirHoldingGdbPy
%endif # with gdb_hooks
# 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
@ -1095,9 +1017,11 @@ InstallPython() {
popd
%if %{with gdb_hooks}
# See comment on $DirHoldingGdbPy above
PathOfGdbPy=$DirHoldingGdbPy/$PyInstSoName-%{version}-%{release}.%{_arch}.debug-gdb.py
cp Tools/gdb/libpython.py %{buildroot}$PathOfGdbPy
%endif # with gdb_hooks
# Rename the -devel script that differs on different arches to arch specific name
mv %{buildroot}%{_bindir}/python${LDVersion}-{,`uname -m`-}config
@ -1204,7 +1128,7 @@ LD_LIBRARY_PATH=./build/optimized ./build/optimized/python \
-i "%{_bindir}/python%{pybasever}" -pn \
%{buildroot} \
%{buildroot}%{_bindir}/*%{pybasever}.py \
%{buildroot}$DirHoldingGdbPy/*.py
%{?with_gdb_hooks:%{buildroot}$DirHoldingGdbPy/*.py}
# Remove shebang lines from .py files that aren't executable, and
# remove executability from .py files that don't have a shebang line:
@ -1301,11 +1225,6 @@ 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
# ======================================================
@ -1372,12 +1291,7 @@ CheckPython() {
# freethreading{,-debug} build, skipping it to shorten the build time
# see: https://github.com/python/cpython/issues/121719
LD_LIBRARY_PATH=$ConfDir $ConfDir/python -m test.regrtest \
-wW --slowest %{_smp_mflags} \
%ifarch riscv64
--timeout=8100 \
%else
--timeout=2700 \
%endif
-wW --slowest %{_smp_mflags} --timeout=2700 \
-i test_freeze_simple_script \
-i test_check_probes \
%ifarch %{mips64}
@ -1522,11 +1436,11 @@ CheckPython freethreading
%{1}/_ctypes.%{2}.so\
%{1}/_curses.%{2}.so\
%{1}/_curses_panel.%{2}.so\
%if !(0%{?fedora} && 0%{?fedora} < 42)\
%{1}/_datetime.%{2}.so\
%endif\
%{1}/_dbm.%{2}.so\
%if %{with gdbm}\
%{1}/_gdbm.%{2}.so\
%endif\
%{1}/_decimal.%{2}.so\
%{1}/_elementtree.%{2}.so\
%{1}/_hashlib.%{2}.so\
@ -1818,106 +1732,6 @@ CheckPython freethreading
# ======================================================
%changelog
* Wed Aug 12 2026 Miro Hrončok <mhroncok@redhat.com> - 3.13.15-2
- On EPEL 9, also supports reparse deferral in expat
* Mon Aug 10 2026 Karolina Surma <ksurma@redhat.com> - 3.13.15-1
- Update to Python 3.13.15
* Thu Jul 16 2026 Fedora Release Engineering <releng@fedoraproject.org> - 3.13.14-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
* Thu Jun 11 2026 Karolina Surma <ksurma@redhat.com> - 3.13.14-1
- Update to Python 3.13.14
* Wed Apr 08 2026 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.13.13-1
- Update to 3.13.13
* Thu Mar 26 2026 Lumír Balhar <lbalhar@redhat.com> - 3.13.12-2
- Security fix for CVE-2026-4519 (rhbz#2449729)
* Wed Feb 04 2026 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.13.12-1
- Update to 3.13.12
* Sat Jan 17 2026 Fedora Release Engineering <releng@fedoraproject.org> - 3.13.11-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild
* Tue Jan 06 2026 Karolina Surma <ksurma@redhat.com> - 3.13.11-2
- Require at least the same expat version as used during the build time
* Fri Dec 05 2025 Miro Hrončok <mhroncok@redhat.com> - 3.13.11-1
- Update to 3.13.11
* Wed Dec 03 2025 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.13.10-1
- Update to 3.13.10
* Tue Oct 14 2025 Miro Hrončok <mhroncok@redhat.com> - 3.13.9-1
- Update to Python 3.13.9
* Tue Oct 07 2025 Karolina Surma <ksurma@redhat.com> - 3.13.8-1
- Update to Python 3.13.8
* Thu Aug 14 2025 Miro Hrončok <mhroncok@redhat.com> - 3.13.7-1
- Update to 3.13.7
* Thu Aug 07 2025 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.13.5-5
- Update to 3.13.6
* Mon Jul 28 2025 Miro Hrončok <mhroncok@redhat.com> - 3.13.5-4
- Fix CVE-2025-8194: Tarfile infinite loop during parsing with negative member offset
* Fri Jul 25 2025 Fedora Release Engineering <releng@fedoraproject.org> - 3.13.5-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
* Wed Jun 25 2025 Karolina Surma <ksurma@redhat.com> - 3.13.5-2
- Conditionally skip tests not working with the older expat version
* Thu Jun 12 2025 Miro Hrončok <mhroncok@redhat.com> - 3.13.5-1
- Update to 3.13.5
* Thu Jun 12 2025 Charalampos Stratakis <cstratak@redhat.com> - 3.13.4-2
- Enable PAC and BTI hardware protections for aarch64
* Wed Jun 04 2025 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.13.4-1
- Update to 3.13.4
* Mon Jun 02 2025 Python Maint <python-maint@redhat.com> - 3.13.3-4
- Rebuilt as non-main Python on Fedora 43
* Tue May 06 2025 Miro Hrončok <mhroncok@redhat.com> - 3.13.3-3
- Drop requirement on python-wheel-wheel with setuptools >= 71
* Tue Apr 22 2025 Charalampos Stratakis <cstratak@redhat.com> - 3.13.3-2
- Apply Intel's CET for mitigation against control-flow hijacking attacks
* Wed Apr 09 2025 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.13.3-1
- Update to 3.13.1
* Thu Feb 06 2025 Miro Hrončok <mhroncok@redhat.com> - 3.13.2-2
- Rebuilt with mpdecimal 4.0.0
* Tue Feb 04 2025 Charalampos Stratakis <cstratak@redhat.com> - 3.13.2-1
- Update to 3.13.2
- Security fix for CVE-2025-0938
- Fixes: rhbz#2343274
* Wed Jan 29 2025 Miro Hrončok <mhroncok@redhat.com> - 3.13.1-4
- On Fedora 41 or older, statically build the _datetime module into libpython
- This fixes a segfault when importing it from Python 3.13.0 updated to 3.13.1+ while running
- Fixes: rhbz#2333852
* Sat Jan 18 2025 Fedora Release Engineering <releng@fedoraproject.org> - 3.13.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
* Mon Dec 09 2024 Miro Hrončok <mhroncok@redhat.com> - 3.13.1-2
- Security fix for CVE-2024-12254
- Fixes: rhbz#2330927
* Tue Dec 03 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.13.1-1
- Update to 3.13.1
- Security fix for CVE-2024-9287
- Fixes: rhbz#2321657
* Tue Oct 08 2024 Karolina Surma <ksurma@redhat.com> - 3.13.0-1
- Update to Python 3.13.0

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

@ -1,2 +1,2 @@
SHA512 (Python-3.13.15.tar.xz) = b0ab766a3de0b4cfdbf0b93300d7330c734d3f7057577bb03e95e39da4cdade81993e769c7fa6dfdcc13b9d43a3b399d9cd89b5477b413662e9e691c1b7886b8
SHA512 (Python-3.13.15.tar.xz.asc) = 662c00be95f62e80db43cf42099fef91f764ff7a4433cadf7eb19dedb5e4775adb12878d5ed2295fcea187731de186163ad9672ab72cde62a2335ca58ec1ad86
SHA512 (Python-3.13.0.tar.xz) = 44a143c9b96b55b01885ec020c3364265bda55289615cd7d5071915b0d0178a6f35e7551a89090001fcb7f3172d38177a56bf8b8532b15c9dbc50295c9210152
SHA512 (Python-3.13.0.tar.xz.asc) = 1b8bb0fe4eb93e31ec1770e90b94d44b5864c0391aad5dcba3a30d8e505d9b17107385414353c0060007f8a536254f49b8e919f36ddf6421a6e4330f817f1a3e

4
tests/provision.fmf Normal file
View file

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

67
tests/tests.yml Normal file
View file

@ -0,0 +1,67 @@
---
- 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.13"
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' ./parallel.sh"
- debugtest:
dir: python/selftest
run: "VERSION={{ pybasever }} PYTHON=python{{ pybasever }}d X='-i test_check_probes' ./parallel.sh"
- optimizedflags:
dir: python/flags
run: "python{{ pybasever }} ./assertflags.py -O3"
- debugflags:
dir: python/flags
run: "python{{ pybasever }}d ./assertflags.py -O0"
- freethreadingflags:
dir: python/flags
run: "python{{ pybasever }}t ./assertflags.py -O3"
- freethreadingdebugflags:
dir: python/flags
run: "python{{ pybasever }}td ./assertflags.py -O0"
- 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