Compare commits

...
Sign in to create a new pull request.

70 commits

Author SHA1 Message Date
Karolina Surma
2260bebdb9 rpmlint: Filter out obsolete-not-provided for freethreading subpackages
The package has been split from a single -freethreading one.
This avoids:

  python3.14-freethreading-devel.aarch64: W: obsolete-not-provided python3.14-freethreading
  python3.14-freethreading-devel.i686: W: obsolete-not-provided python3.14-freethreading
  python3.14-freethreading-devel.ppc64le: W: obsolete-not-provided python3.14-freethreading
  python3.14-freethreading-devel.s390x: W: obsolete-not-provided python3.14-freethreading
  python3.14-freethreading-devel.x86_64: W: obsolete-not-provided python3.14-freethreading
  python3.14-freethreading-idle.aarch64: W: obsolete-not-provided python3.14-freethreading
  ...
2026-08-24 13:39:07 +02:00
Miro Hrončok
79d64abadf rpmlint: Also ignore file-not-in-%lang in tests
This avoids:

    python3-test.aarch64: W: file-not-in-%lang /usr/lib64/python3.15/test/test_tools/msgfmt_data/fuzzy.mo
    python3-test.aarch64: W: file-not-in-%lang /usr/lib64/python3.15/test/test_tools/msgfmt_data/general.mo
    python3-test.i686: W: file-not-in-%lang /usr/lib/python3.15/test/test_tools/msgfmt_data/fuzzy.mo
    python3-test.i686: W: file-not-in-%lang /usr/lib/python3.15/test/test_tools/msgfmt_data/general.mo
    python3-test.ppc64le: W: file-not-in-%lang /usr/lib64/python3.15/test/test_tools/msgfmt_data/fuzzy.mo
    python3-test.ppc64le: W: file-not-in-%lang /usr/lib64/python3.15/test/test_tools/msgfmt_data/general.mo
    python3-test.s390x: W: file-not-in-%lang /usr/lib64/python3.15/test/test_tools/msgfmt_data/fuzzy.mo
    python3-test.s390x: W: file-not-in-%lang /usr/lib64/python3.15/test/test_tools/msgfmt_data/general.mo
    python3-test.x86_64: W: file-not-in-%lang /usr/lib64/python3.15/test/test_tools/msgfmt_data/fuzzy.mo
    python3-test.x86_64: W: file-not-in-%lang /usr/lib64/python3.15/test/test_tools/msgfmt_data/general.mo
    python3.15-freethreading-test.aarch64: W: file-not-in-%lang /usr/lib64/python3.15t/test/test_tools/msgfmt_data/fuzzy.mo
    python3.15-freethreading-test.aarch64: W: file-not-in-%lang /usr/lib64/python3.15t/test/test_tools/msgfmt_data/general.mo
    python3.15-freethreading-test.i686: W: file-not-in-%lang /usr/lib/python3.15t/test/test_tools/msgfmt_data/fuzzy.mo
    python3.15-freethreading-test.i686: W: file-not-in-%lang /usr/lib/python3.15t/test/test_tools/msgfmt_data/general.mo
    python3.15-freethreading-test.ppc64le: W: file-not-in-%lang /usr/lib64/python3.15t/test/test_tools/msgfmt_data/fuzzy.mo
    python3.15-freethreading-test.ppc64le: W: file-not-in-%lang /usr/lib64/python3.15t/test/test_tools/msgfmt_data/general.mo
    python3.15-freethreading-test.s390x: W: file-not-in-%lang /usr/lib64/python3.15t/test/test_tools/msgfmt_data/fuzzy.mo
    python3.15-freethreading-test.s390x: W: file-not-in-%lang /usr/lib64/python3.15t/test/test_tools/msgfmt_data/general.mo
    python3.15-freethreading-test.x86_64: W: file-not-in-%lang /usr/lib64/python3.15t/test/test_tools/msgfmt_data/fuzzy.mo
    python3.15-freethreading-test.x86_64: W: file-not-in-%lang /usr/lib64/python3.15t/test/test_tools/msgfmt_data/general.mo
2026-08-21 11:19:04 +02:00
Miro Hrončok
bd2563ea47 rpmlint: Do not report idle as no-binary
python3-idle.i686: E: no-binary
    python3.15-freethreading-idle.i686: E: no-binary

We know this and we don't care.
We won't make this noarch. It installs to lib64.

Assisted-By: Claude Opus 4.6
2026-08-21 11:18:56 +02:00
Miro Hrončok
bef861129d rpmlint: Extend the rule about no-documentation for freethreading subpackages
This avoids:

    python3.15-freethreading-devel.aarch64: W: no-documentation
    python3.15-freethreading-devel.i686: W: no-documentation
    python3.15-freethreading-devel.ppc64le: W: no-documentation
    python3.15-freethreading-devel.s390x: W: no-documentation
    python3.15-freethreading-devel.x86_64: W: no-documentation
    python3.15-freethreading-idle.aarch64: W: no-documentation
    python3.15-freethreading-idle.i686: W: no-documentation
    python3.15-freethreading-idle.ppc64le: W: no-documentation
    python3.15-freethreading-idle.s390x: W: no-documentation
    python3.15-freethreading-idle.x86_64: W: no-documentation
    python3.15-freethreading-test.aarch64: W: no-documentation
    python3.15-freethreading-test.i686: W: no-documentation
    python3.15-freethreading-test.ppc64le: W: no-documentation
    python3.15-freethreading-test.s390x: W: no-documentation
    python3.15-freethreading-test.x86_64: W: no-documentation
    python3.15-freethreading-tkinter.aarch64: W: no-documentation
    python3.15-freethreading-tkinter.i686: W: no-documentation
    python3.15-freethreading-tkinter.ppc64le: W: no-documentation
    python3.15-freethreading-tkinter.s390x: W: no-documentation
    python3.15-freethreading-tkinter.x86_64: W: no-documentation
2026-08-21 11:18:52 +02:00
Miro Hrončok
f4716cbb08 rpmlint: CPython is not a spelling error
Also, the output looks different now:

    python3.15-freethreading.x86_64: E: spelling-error ("CPython's", "%description -l en_US CPython's -> C Python's, Python's, Pynchon's")
    python3.15-freethreading-devel.x86_64: E: spelling-error ('evelopment', 'Summary(en_US) evelopment -> envelopment, development, elopement')
2026-08-21 11:18:48 +02:00
Miro Hrončok
c1b886b3b6 Fix a typo in freethreading-devel package summary
Caught by rpmlint spelling-error check.
2026-08-21 11:18:43 +02:00
Miro Hrončok
9d987df726 On EL 9, also supports reparse deferral in expat
This replaces one downstream-only patch with another.
Yet arguably, this is the safer thing to do.

Read the patch description for details; won't copy paste them here.

Also, require expat >= version-release when expat < 2.7.4.

Assisted-By: Claude Opus 4.6
(cherry picked from python3.13 commit 0ca3f59c07cb0d9bf01a0746d00773ed0c625755)
2026-08-18 10:30:51 +02:00
Karolina Surma
36fa2b0895 Update to Python 3.14.7 2026-08-11 11:36:15 +02:00
Fedora Release Engineering
4669c6fce0 Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild 2026-07-16 22:48:27 +00:00
Lumir Balhar
2b1a90b181 Run a new test to monitor changes in required symbols 2026-06-24 22:07:41 +02:00
Karolina Surma
f26b7fcd3a Update to Python 3.14.6 2026-06-11 16:39:30 +02:00
Python Maint
576eed68c6 Rebuilt as non-main Python on Fedora 45+ 2026-06-03 12:28:22 +02:00
Miro Hrončok
fc230a4cf1 Update to 3.14.5 2026-05-11 12:58:21 +02:00
Miro Hrončok
b04f319cc6 Update to 3.14.5rc1
Patches 479, 480, 482 merged upstream.
2026-05-06 11:28:24 +02:00
Miro Hrončok
9025dc9760 Fixup using prebuilt JIT on ELN
See f45779a0aa for context.

After autoconf 2.73 landed in Fedora ELN,
the pre-built JIT stencils were rejected because of checksum mismatch.

This new patch adds an ability to circumvent that check.

It has been offered upstream in
https://github.com/python/cpython/issues/148646
https://github.com/python/cpython/pull/148647

While this has yet to be finalized upstream and might take a while, we need to fix the ELN build right away.

(When we build the stencils on rawhide for the next release,
the problem will shift from ELN with new autoconf to old Fedoras with old autoconf.)

Cherry-picked from python3.15 commit 4a1f3dae4f24af60227469c76acf9452f02c90dd
2026-04-17 13:37:57 +02:00
Miro Hrončok
f45779a0aa When comparing the pre-built JIT stencils for identity, exclude the checksum
When autoconf was updated from 2.72 to 2.73, we observed a change in the checksum:

    + diff -u /builddir/build/SOURCES/Python-3.15.0a7-x86_64-debug-jit_stencils.h build/debug/jit_stencils-x86_64-unknown-linux-gnu.h
    --- /builddir/build/SOURCES/Python-3.15.0a7-x86_64-debug-jit_stencils.h	2026-03-10 00:00:00.000000000 +0000
    +++ build/debug/jit_stencils-x86_64-unknown-linux-gnu.h	2026-03-31 21:12:53.391262973 +0000
    @@ -1,4 +1,4 @@
    -// 5e1dc452d67c20147c4ea13e692c2d3e7b0b47b24f8847354c58988c7ffa02bc
    +// c783e3946f774d4d83e8fdcca35678ec77006e1b96b12661fcbd3ee680d10e94
     // $ python3.14 /builddir/build/BUILD/python3.14-3.15.0_a7-build/Python-3.15.0a7/Tools/jit/build.py x86_64-redhat-linux-gnu --output-dir . --pyconfig-dir . --cflags= --llvm-version= --debug

     void
    error: Bad exit status from /var/tmp/rpm-tmp.G15BYi (%check)

The autoconf-generated pyconfig.h file is part of the checksum input:
https://github.com/python/cpython/blob/v3.15.0a8/Tools/jit/_targets.py#L75

Generally, the reason for this checksum is to prevent outdated JIT stencils
when Python is re-configured with different options
(or when the stencils generation code is updated).

As suspected, the change in checksum was caused by a change in pyconfig.h:

    --- pyconfig.h
    +++ pyconfig.h
    @@ -1882,6 +1882,10 @@
     #ifndef _ALL_SOURCE
     # define _ALL_SOURCE 1
     #endif
    +/* Enable extensions on Cosmopolitan Libc. */
    +#ifndef _COSMO_SOURCE
    +# define _COSMO_SOURCE 1
    +#endif
     /* Enable general extensions on macOS.  */
     #ifndef _DARWIN_C_SOURCE
     # define _DARWIN_C_SOURCE 1

This is expected, see https://cgit.git.savannah.gnu.org/cgit/autoconf.git/tree/NEWS?h=v2.73#n99

tl;dr when a new autoconf version changes the output of pyconfig.h, the checksum changes as well.

We cannot update the pre-built stencils with the new checksum
because that would make the build fail with older autoconf.

Instead, we ignore the checksum in this check. We care for the contents, not checksums.

Cherry-picked from python3.15 commit aab847c347b141083dbfbcf33fb38fb286dc2f62
2026-04-17 13:32:26 +02:00
Charalampos Stratakis
94e3c06cd7 Security fixes for CVE-2026-1502, CVE-2026-4786, CVE-2026-5713, CVE-2026-6100
Resolves: rhbz#2457944, rhbz#2458224, rhbz#2458488, rhbz#2458016
2026-04-16 03:25:31 +02:00
Miro Hrončok
25248beb99 Explicitly build with OpenSSL 3 for now
https://fedoraproject.org/wiki/Changes/OpenSSL40
2026-04-09 13:16:25 +02:00
Karolina Surma
e9c5c0c3c4 Update to Python 3.14.4 2026-04-08 13:03:09 +02:00
Miro Hrončok
fee84f7c55 Only explicitly require expat >= installed version when expat < 2.7.4
See https://src.fedoraproject.org/rpms/expat/c/4da0543472

(cherry picked from python3.15 commit ce1bde3e67443b7cf5df33bf58cb2ec75cc2c8e2)
2026-03-26 13:57:00 +00:00
Miro Hrončok
cf66620612 Remove a no longer needed workaround
https://github.com/python/cpython/issues/98782 was fixed in 3.12.0a6+

(cherry picked from python3.15 commit 8b2d02a1ede90cfe0392a79a4e65d5a9240b14ee)
2026-03-26 13:57:00 +00:00
Lumir Balhar
ca8cc60bc4 Security fix for CVE-2026-4519 (rhbz#2449730) 2026-03-26 09:12:33 +01:00
Karolina Surma
aaf6ec2cca Fix CVE-2025-15366, CVE-2025-15367 2026-02-10 09:55:09 +01:00
Karolina Surma
406c34b53b Update to Python 3.14.3 2026-02-09 16:54:54 +01:00
Miro Hrončok
dd282ac7f3 Remove an outdated workaround
This fix landed 6 years ago in 3.9.0a5.

3c97e1e457
2026-01-26 12:10:47 +01:00
Miro Hrončok
6e767cf9f4 Don't require the JIT stencils sources when the SRPM is built on other arch
When the SRPM is built in Koji on non-JIT architecture (such as ppc64le
or s390x), the jit_build_stencils bcond is set to false.

When we don't have the JIT stencils sources yet and we do a scratch
build to generate them,
we want the SRPM creation to succeed, regardless of architecture.

This way, the sources are only defined when they are required or when
they exist.

An alternative would be to set jit_build_stencils to true/false
in an arch-independent way, and later always check for:

%{with jit} && %{with jit_build_stencils}

But I think that might be confusing.
2026-01-26 12:10:47 +01:00
Karolina Surma
b4fbfd9335 Reenable passing tests 2026-01-26 12:10:47 +01:00
Fedora Release Engineering
8f8849fb7c Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild 2026-01-17 10:40:18 +00:00
Karolina Surma
5ce9d27cf1 Extend the expat requirement to differentiate between 32 and 64 arches
(cherry picked from python3.15 commit a5ca170d3f1e6e19f5df66f21482c2b10593af42)
2026-01-13 16:26:01 +01:00
Karolina Surma
8236063d9f Require at least the same expat version as used during the build
In the past we have had a versioned requirement on expat, e.g.:
https://src.fedoraproject.org/rpms/python3.13/c/c686992b6c25a39d0e4117053ddb669fd5998723
The explanation is still valid: if Python is built with an expat version
with new symbols, and used with an installed older expat, it won't work,
preventing crating new venvs, and many more.
This has happened again now with expat 2.7.2 introducing new symbols.

Reintroduce the versioned requirement and make it future-proof - the
generated version will always match at least the one present in the buildroot
during the Python build.
2026-01-07 12:28:29 +01:00
Miro Hrončok
78e3110af1 Make it easier to bootstrap new JIT stencils
Only define the JIT stencils sources when we must
(i.e. when building --wihtout jit_build_stencils)
or when the files already exist.

This allows to run rawhide CI scratch builds without the stencils,
but it also ensures the final SRPM contains them
even when built --with jit_build_stencils.

(cherry picked from python3.15 commit b2312d171d6a3280744a549f2c4daee492b66f44)
2025-12-21 16:48:00 +01:00
Miro Hrončok
e0d3024961 Remove a hack that was not needed on 3.14
When discussing whether to backport https://github.com/python/cpython/pull/141809
I discovered that this hack was not needed on this Python version.
2025-12-09 19:48:18 +01:00
Miro Hrončok
1f64e4dcdb Update to Python 3.14.2 2025-12-05 23:36:05 +01:00
Karolina Surma
d849d8f127 Update to Python 3.14.1 2025-12-05 22:26:25 +01:00
Miro Hrončok
e0af09b7c2 Inject SBOM into the installed wheels (when using the bundled ones) 2025-11-27 18:58:12 +00:00
Miro Hrončok
6d982d0a19 CI: Run tests with JIT enabled, assert JIT is enabled/disabled correctly
(cherry picked from python3.15 commit 687c6ece6f633bbd9e65a680bba3e3ea80eb122c)
2025-11-25 19:48:16 +01:00
Miro Hrončok
2986781bf7 Use prebuilt JIT stencils on platforms without LLVM 19
(cherry picked from python3.15 commit f3045380bba4fd8047571a76b233c5d955eb2577)
2025-11-25 19:29:30 +01:00
Karolina Surma
56eb7aad4b CI: Run selftest on freethreading build 2025-10-27 19:32:17 +01:00
Karolina Surma
e365cd89b9 CI: Fix duplicate link in a comment 2025-10-27 19:32:09 +01:00
Karolina Surma
d60c500d01 Supplement tox from -freethreading-devel package 2025-10-24 13:06:09 +02:00
Miro Hrončok
a7297274d1 Revert "CI: Disable Cython checks on the smoke test for now"
Cython supports 3.14. This should have been enabled a long time ago.

This reverts commit 204e750d2e.
2025-10-22 14:55:01 +02:00
Karolina Surma
041b6663c5 Split freethreading package into analogs of the main Python
Assisted-By: Claude Sonnet 4.5
2025-10-18 10:51:04 +02:00
Karolina Surma
0bef7f1c35 trace is officially licensed as HPND-SMC
https://gitlab.com/fedora/legal/fedora-license-data/-/issues/657#note_2815942473
2025-10-15 11:14:33 +02:00
Karolina Surma
c6a9f6fe3b Update to Python 3.14.0 2025-10-07 17:08:27 +02:00
Karolina Surma
937d86cf62 Include licenses of incorporated software (rhbz#2133426)
Python includes a lot of differently licensed functions and
modules.
We gather the list from https://docs.python.org/3.14/license.html.

Detect changes to Doc/license.rst with file hash automatically in %prep.
2025-09-24 16:04:04 +02:00
Karolina Surma
0ca0aa8525 Update to Python 3.14.0rc3 2025-09-18 15:06:56 +02:00
Lumir Balhar
cfc37cd117 rpminspect: Wrap strings with globs with single quotes
It seems to be required since rpminspect 2.0:
1593c38ce4
2025-08-26 13:26:44 +02:00
Miro Hrončok
56f34b9695 Update to Python 3.14.0rc2
- The .pyc magic number was bumped
2025-08-14 18:25:42 +02:00
Lukáš Zachar
e8a3251a5e Drop STI and use tmt instead
Resolves: rhbz#2383060
2025-07-30 16:27:45 +00:00
Fedora Release Engineering
8c03c574c2 Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild 2025-07-25 11:19:30 +00:00
Miro Hrončok
482bb556a9 Update to Python 3.14.0rc1
_datetime was removed from installed files via
ecd97caaf5
2025-07-22 22:25:10 +02:00
Miro Hrončok
278f3033f3 Update to Python 3.14.0b4 2025-07-08 20:57:41 +02:00
Miro Hrončok
797b97aa4d CI: Unskip a fixed test 2025-07-08 20:54:53 +02:00
Karolina Surma
c0c82aa771 Lower the minimal required autoconf version for EPEL 9 build 2025-06-27 08:38:41 +02:00
Karolina Surma
a419176c4c Switch the basic conditionals based on the bootstrap's value
We always switch rpmswheels, optimizations and tests when bootstrapping
new Python version, so they can be tied to the bootstrap conditional.
With that, switching the bootstrap in Koji side tag will be possible,
letting us to avoid separate "bootstrap" and "rebuild" commits.
2025-06-27 08:37:59 +02:00
Karolina Surma
ed3fc5a80b Move the bootstrapping conditionals above the global metadata
We need to have it above the Release field, in order for the build NVR
to contain the ~bootstrap suffix and sort correctly (lower than the main
build).

This enables bootstrapping the package directly in Koji side tag.
2025-06-25 12:48:51 +02:00
Karolina Surma
48ee6e9c72 Downstream patch: Skip tests not working with older expat version
This will ensure the tests run in Fedoras and EPEL 10, but are skipped
for EPEL 9.
2025-06-25 11:23:45 +02:00
Karolina Surma
1521b586f0 Define %python3_pkgversion based on the Python's status
Main Python should retain the value '3', non-main the major-minor one.
We need that to request the correctly versioned wheels for EPEL builds.
2025-06-24 14:26:44 +02:00
Karolina Surma
4041c8a86e Remove the upper version bound from expat library
It's already greater than 2.6 in all Fedoras.
2025-06-24 14:25:40 +02:00
Charalampos Stratakis
eb9909215c Enable PAC and BTI hardware protections for aarch64 2025-06-18 17:29:39 +02:00
Charalampos Stratakis
64000497af Revert "Add perf to the testing BuildRequires"
This reverts commit 1e24d38cd9.
2025-06-18 17:25:37 +02:00
Miro Hrončok
eda37b70f4 Update to Python 3.14.0b3
- The .pyc magic number was bumped
- python3.14-freethreading is no longer provisional
2025-06-18 00:25:23 +02:00
Python Maint
e3c3cbe96e Rebuilt for Python 3.14 2025-06-02 17:45:07 +02:00
Python Maint
b06a2a26f3 Bootstrap for Python 3.14 2025-06-02 10:51:01 +02:00
Miro Hrončok
09b6af7951 Build the _zstd module 2025-05-27 10:22:03 +02:00
Miro Hrončok
014f2b2430 Update to Python 3.14.0b2 2025-05-27 09:29:13 +02:00
Miro Hrončok
ef2d703504 Disable JIT on RHEL
For now on, until we figure out a way of building the JIT with pre-built stencils,
we disable the JIT on RHEL to avoid a dependency on a specific LLVM+clang version.

https://discuss.python.org/t/building-the-jit-with-pre-built-stencils/91838
https://src.fedoraproject.org/rpms/python3.14/pull-request/40
https://github.com/fedora-eln/eln/issues/207
2025-05-20 13:54:21 +02:00
Miro Hrončok
143d59d932 Verify bundled() provides for setuptools.whl 2025-05-13 19:29:44 +02:00
Charalampos Stratakis
1e24d38cd9 Add perf to the testing BuildRequires
Perf profiling showing the Python functions is only
supported on x86_64 and aarch64 at the moment.

Adding perf as a BuildRequires allows tests that utilize the
perf binary to run.
2025-05-12 16:39:54 +02:00
Karolina Surma
05411b4c04 Update to Python 3.14.0b1 2025-05-09 10:58:55 +02:00
20 changed files with 1188 additions and 558 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
/*.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 9da8b6724e..b53dd21d51 100644
index aeb7c6cfc7..86f9ae9e76 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -420,8 +420,15 @@ def getsitepackages(prefixes=None):
@@ -421,8 +421,15 @@ def getsitepackages(prefixes=None):
return sitepackages
def addsitepackages(known_paths, prefixes=None):
@ -51,7 +51,7 @@ index 9da8b6724e..b53dd21d51 100644
if os.path.isdir(sitedir):
addsitedir(sitedir, known_paths)
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index 18e6b8d25e..42df12fad4 100644
index faf8273bd0..d7667bbc77 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -106,6 +106,12 @@
@ -130,10 +130,10 @@ index 18e6b8d25e..42df12fad4 100644
# On Windows we want to substitute 'lib' for schemes rather
# than the native value (without modifying vars, in case it
diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
index cc11eade2e..b4f8aabaef 100644
index 1fe4b6849f..e0cb3ec23a 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -131,8 +131,19 @@ def test_get_path(self):
@@ -132,8 +132,19 @@ def test_get_path(self):
for scheme in _INSTALL_SCHEMES:
for name in _INSTALL_SCHEMES[scheme]:
expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
@ -154,7 +154,7 @@ index cc11eade2e..b4f8aabaef 100644
os.path.normpath(expected),
)
@@ -387,7 +398,7 @@ def test_get_config_h_filename(self):
@@ -397,7 +408,7 @@ def test_get_config_h_filename(self):
self.assertTrue(os.path.isfile(config_h), config_h)
def test_get_scheme_names(self):
@ -163,7 +163,7 @@ index cc11eade2e..b4f8aabaef 100644
if HAS_USER_BASE:
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
@@ -399,6 +410,8 @@ def test_symlink(self): # Issue 7880
@@ -409,6 +420,8 @@ def test_symlink(self): # Issue 7880
cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))

View file

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

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

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

@ -1,120 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Fri, 25 Apr 2025 00:46:20 +0100
Subject: 00460: gh-132415: Update vendored setuptools in
``Lib/test/wheeldata``
(cherry picked from commit c9f3f5b4ed52d7bed6073ffa39717ece47202558)
(actual changes in .whl files removed to make this patch smaller)
gh-127906: Add missing sys import to test_cppext
(cherry picked from commit 9cba14881b371b1e95d57877896169c4605f9b75)
Co-Authored-By: Victor Stinner <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

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

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

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

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

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

@ -0,0 +1,23 @@
set -eu
export LANG=C.utf-8
taskid=$(echo "$1" | sed -E 's/.*=|^([0-9]+)/\1/')
filter='.*-debugsource-.*\.(x86_64|aarch64)\.rpm'
download_stdout=$(koji download-task $taskid --filter "$filter" | tee /dev/stderr)
files=$(echo "$download_stdout" | grep -E '^Downloading ' | sed -E 's/.*\s+(\S+)/\1/' | sort)
for file in $files; do
nvra=${file/.rpm}
snvra=${nvra/-debugsource}
version=$(echo $nvra | sed -E -e 's|.*-([^-]+)-[^-]+|\1|' -e 's|~||')
arch=$(echo $nvra | sed -E 's|.*\.([^.]+)|\1|')
rpm2cpio $file | cpio -idmv ./usr/src/debug/${snvra}/build/{debug,optimized}/jit_stencils-${arch}-redhat-linux-gnu.h
for build in debug optimized; do
mv -v ./usr/src/debug/${snvra}/build/${build}/jit_stencils-${arch}-redhat-linux-gnu.h Python-${version}-${arch}-${build}-jit_stencils.h > /dev/stderr
echo Python-${version}-${arch}-${build}-jit_stencils.h
done
rmdir ./usr/src/debug/${snvra}{/build{/{debug,optimized},},} || :
rm -v $file > /dev/stderr
done
rmdir ./usr{/src{/debug,},} || :

93
plan.fmf Normal file
View file

@ -0,0 +1,93 @@
execute:
how: tmt
provision:
hardware:
memory: '>= 3 GB'
environment:
pybasever: '3.14'
discover:
- name: tests_python
how: shell
url: https://src.fedoraproject.org/tests/python.git
tests:
- name: smoke
path: /smoke
test: "VERSION=${pybasever} CYTHON=true ./venv.sh"
- name: smoke_virtualenv
path: /smoke
test: "VERSION=${pybasever} METHOD=virtualenv CYTHON=true ./venv.sh"
- name: debugsmoke
path: /smoke
test: "PYTHON=python${pybasever}d TOX=false VERSION=${pybasever} CYTHON=true ./venv.sh"
- name: selftest
path: /selftest
test: "VERSION=${pybasever} X='-i test_check_probes' ./parallel.sh"
- name: debugtest
path: /selftest
# test_base_interpreter: https://github.com/python/cpython/issues/131372
test: "VERSION=${pybasever} PYTHON=python${pybasever}d X='-i test_check_probes -i test_base_interpreter' ./parallel.sh"
- name: freethreadingtest
path: /selftest
test: "VERSION=${pybasever}t X='-i test_check_probes -i test_base_interpreter' ./parallel.sh"
- name: selftest_jit
path: /selftest
# test_attr_promotion_failure: https://github.com/python/cpython/issues/141833
test: "VERSION=${pybasever} PYTHON_JIT=1 X='-i test_check_probes -i test_attr_promotion_failure' ./parallel.sh"
- name: jit_disabled_by_default
test: "python${pybasever} -c 'import sys; assert not sys._jit.is_enabled()'"
- name: jit_disabled_explicitly
test: "PYTHON_JIT=0 python${pybasever} -c 'import sys; assert not sys._jit.is_enabled()'"
- name: jit_enabled_explicitly
test: "PYTHON_JIT=1 python${pybasever} -c 'import sys; assert sys._jit.is_enabled()'"
- name: optimizedflags
path: /flags
test: "python${pybasever} ./assertflags.py -O3 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS"
- name: debugflags
path: /flags
test: "python${pybasever}d ./assertflags.py -O0 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS"
- name: freethreadingflags
path: /flags
test: "python${pybasever}t ./assertflags.py -O3 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS"
- name: freethreadingdebugflags
path: /flags
test: "python${pybasever}td ./assertflags.py -O0 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS"
- name: marshalparser
path: /marshalparser
test: "VERSION=${pybasever} SAMPLE=10 ./test_marshalparser_compatibility.sh"
- name: required_symbols
path: /required-symbols
test: "VERSION=${pybasever} ./check.sh"
prepare:
- name: Install dependencies
how: install
package:
- gcc # for extension building in venv and selftest
- gcc-c++ # for test_cppext
- gdb # for test_gdb
- "python${pybasever}" # the test subject
- "python${pybasever}-debug" # for leak testing
- "python${pybasever}-devel" # for extension building in venv and selftest
- "python${pybasever}-tkinter" # for selftest
- "python${pybasever}-test" # for selftest
- "python${pybasever}-freethreading" # for -O... flag test
- "python${pybasever}-freethreading-debug" # for -O... flag test
- "python${pybasever}-freethreading-tkinter" # for freethreadingtest
- "python${pybasever}-freethreading-test" # for freethreadingtest
- tox # for venv tests
- virtualenv # for virtualenv tests
- glibc-all-langpacks # for locale tests
- marshalparser # for testing compatibility (magic numbers) with marshalparser
- binutils # for nm (symbol inspection)
- rpm # for debugging
- dnf # for upgrade and downgrade
- name: Update packages
how: shell
script: dnf upgrade -y
- name: rpm_qa
order: 100
how: shell
script: rpm -qa | sort | tee $TMT_PLAN_DATA/rpmqa.txt

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) /usr/lib(64)?/python3\.\d+t?/test',
'(zero-length|pem-certificate|uncompressed-zip|file-not-in-%lang) /usr/lib(64)?/python3\.\d+t?/test',
# OTHER DELIBERATES:
@ -21,6 +21,9 @@ Filters = [
'unversioned Obsoletes: Obsoletes: python3\.\d+$',
'self-obsoletion python3\.\d+(-\S+)? obsoletes python3\.\d+(-\S+)?',
# freethreading subpackages obsolete python3.X-freethreading, but don't provide it
'^python3(\.\d+)?-freethreading(-\w+)?\.[^:]+: (E|W): obsolete-not-provided python3(\.\d+)?-freethreading$',
# intentionally hardcoded
'hardcoded-library-path in %{_prefix}/lib/(debug/%{_libdir}|python%{pybasever})',
@ -37,6 +40,9 @@ Filters = [
# if this regex needs to be relaxed in the future, make sure it **does not** match pyc files in __pycache__
'python-bytecode-without-source /usr/lib(64)?/python3\.\d+t?/(encodings|pydoc_data)/[^/]+.pyc',
# https://docs.fedoraproject.org/en-US/packaging-guidelines/RPM_Source_Dir/#_exceptions
'use-of-RPM_SOURCE_DIR',
# DUPLICATE FILES
# test data are often duplicated
'(E|W): files-duplicate /usr/lib(64)?/python3\.\d+t?/(test|__phello__)/',
@ -55,7 +61,10 @@ Filters = [
'no-manual-page-for-binary python3\.\d+t?dm?$',
# missing documentation from subpackages
'^python3(\.\d+)?-(freethreading(-debug)?|debug|tkinter|test|idle)\.[^:]+: (E|W): no-documentation',
'^python3(\.\d+)?-(freethreading(-\w+)?|debug|tkinter|test|idle)\.[^:]+: (E|W): no-documentation',
# idle subpackages have no binaries
'^python3(\.\d+)?-(freethreading-)?idle\.[^:]+: (E|W): no-binary',
# platform python is obsoleted, but not provided
'obsolete-not-provided platform-python',
@ -101,6 +110,6 @@ Filters = [
'\bpython3(\.\d+)?\.(src|spec): (E|W): specfile-error\s+$',
# SPELLING ERRORS
'spelling-error .* en_US (bytecode|pyc|filename|tkinter|namespaces|pytest|unittest|gil) ',
'spelling-error .*\b(bytecode|pyc|filename|tkinter|namespaces|pytest|unittest|gil|CPython)\b',
]

View file

@ -1 +1,5 @@
SHA512 (Python-3.14.0a7.tar.xz) = f7e50c201cb1bbc4779d898e65408147637de7b9d9d85a2e6ad4f8dda758ec150dfb95ee1f12c686a3f46c29a986a75b45323bcbab87b81b319d91236989f6b0
SHA512 (Python-3.14.7.tar.xz) = 3d4e2e2f983b320dec47005c408d7178d3656a6de0c4430ce21514797174b972f461200898b25d3dfac2a455019ef87e45d0fb2bb6ec2ca887124d10037a2a07
SHA512 (Python-3.14.7-aarch64-debug-jit_stencils.h) = 85bf4cdf5996ede2932aa1b5ffb0c3befe7fb395efdadaeedc05969bbf8f4db1fe825666276239183ec24caa58f2307983876b29efa86ac54bd5802c85ab1d3c
SHA512 (Python-3.14.7-aarch64-optimized-jit_stencils.h) = e7245f166126184655275dd5a90a4251e73ed042fc0d9b46624f55faa698a676a6714f8d2577aecd0a03fb54a6fda3d23b1391a1872b66c130b79b817699ab82
SHA512 (Python-3.14.7-x86_64-debug-jit_stencils.h) = e34b31bcc3959b3fbd9cac07df69eababfab2ff42101a0dc14af34c67775c73ef48dcac658ac0c1f58c8c2957bd88a553a748f849e566d4cf66c0a5d9722f14d
SHA512 (Python-3.14.7-x86_64-optimized-jit_stencils.h) = d17bf0d61136580dfe589dbcac2d51bbb3fa75f467e008ad2000a7f778427f32aef3f88efb46a1c01c4aa4af8878d51d4f4e0b1d18976906ea332bfe6c11e1fe

View file

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

View file

@ -1,68 +0,0 @@
---
- hosts: localhost
tags:
- classic
tasks:
- dnf:
name: "*"
state: latest
- hosts: localhost
roles:
- role: standard-test-basic
tags:
- classic
repositories:
- repo: "https://src.fedoraproject.org/tests/python.git"
dest: "python"
pybasever: "3.14"
tests:
- rpm_qa:
run: rpm -qa
- smoke:
dir: python/smoke
run: "VERSION={{ pybasever }} CYTHON=false ./venv.sh"
- smoke_virtualenv:
dir: python/smoke
run: "VERSION={{ pybasever }} METHOD=virtualenv CYTHON=false ./venv.sh"
- debugsmoke:
dir: python/smoke
run: "PYTHON=python{{ pybasever }}d TOX=false VERSION={{ pybasever }} CYTHON=false ./venv.sh"
- selftest:
dir: python/selftest
run: "VERSION={{ pybasever }} X='-i test_check_probes -i test_sysconfigdata_json' ./parallel.sh"
- debugtest:
dir: python/selftest
# test_base_interpreter: https://github.com/python/cpython/issues/131372
run: "VERSION={{ pybasever }} PYTHON=python{{ pybasever }}d X='-i test_check_probes -i test_sysconfigdata_json -i test_base_interpreter' ./parallel.sh"
- optimizedflags:
dir: python/flags
run: "python{{ pybasever }} ./assertflags.py -O3 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS"
- debugflags:
dir: python/flags
run: "python{{ pybasever }}d ./assertflags.py -O0 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS"
- freethreadingflags:
dir: python/flags
run: "python{{ pybasever }}t ./assertflags.py -O3 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS"
- freethreadingdebugflags:
dir: python/flags
run: "python{{ pybasever }}td ./assertflags.py -O0 CFLAGS PY_BUILTIN_MODULE_CFLAGS PY_CFLAGS PY_CORE_CFLAGS PY_CFLAGS_NODIST PY_STDMODULE_CFLAGS"
- marshalparser:
dir: python/marshalparser
run: "VERSION={{ pybasever }} SAMPLE=10 test_marshalparser_compatibility.sh"
required_packages:
- gcc # for extension building in venv and selftest
- gcc-c++ # for test_cppext
- gdb # for test_gdb
- "python{{ pybasever }}" # the test subject
- "python{{ pybasever }}-debug" # for leak testing
- "python{{ pybasever }}-devel" # for extension building in venv and selftest
- "python{{ pybasever }}-tkinter" # for selftest
- "python{{ pybasever }}-test" # for selftest
- "python{{ pybasever }}-freethreading" # for -O... flag test
- "python{{ pybasever }}-freethreading-debug" # for -O... flag test
- tox # for venv tests
- virtualenv # for virtualenv tests
- glibc-all-langpacks # for locale tests
- marshalparser # for testing compatibility (magic numbers) with marshalparser
- rpm # for debugging