- Update to 3.14.0~b2:

- Tools/Demos
    - gh-134215: REPL import autocomplete only suggests private
      modules when explicitly specified.
  - Tests
    - gh-133744: Fix multiprocessing interrupt test. Add an event
      to synchronize the parent process with the child process:
      wait until the child process starts sleeping. Patch by
      Victor Stinner.
    - gh-133682: Fixed test case
      test.test_annotationlib.TestStringFormat.test_displays
      which ensures proper handling of complex data structures
      (lists, sets, dictionaries, and tuples) in string
      annotations.
    - gh-133639: Fix
      TestPyReplAutoindent.test_auto_indent_default() doesn’t run
      input_code.
  - Security
    - gh-133767: Fix use-after-free in the “unicode-escape”
      decoder with a non-“strict” error handler (CVE-2025-4516
      bsc#1243273).
    - gh-128840: Short-circuit the processing of long IPv6
      addresses early in ipaddress to prevent excessive memory
      consumption and a minor denial-of-service.
  - Library
    - gh-132710: If possible, ensure that uuid.getnode()
      returns the same result even across different
      processes. Previously, the result was constant only within
      the same process. Patch by Bénédikt Tran.
    - gh-80334: multiprocessing.freeze_support() now checks for

OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python314?expand=0&rev=71
This commit is contained in:
2025-05-29 11:50:01 +00:00
committed by Git OBS Bridge
commit 79e939b48a
44 changed files with 13973 additions and 0 deletions

23
.gitattributes vendored Normal file
View File

@@ -0,0 +1,23 @@
## Default LFS
*.7z filter=lfs diff=lfs merge=lfs -text
*.bsp filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.gem filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.lz filter=lfs diff=lfs merge=lfs -text
*.lzma filter=lfs diff=lfs merge=lfs -text
*.obscpio filter=lfs diff=lfs merge=lfs -text
*.oxt filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.rpm filter=lfs diff=lfs merge=lfs -text
*.tbz filter=lfs diff=lfs merge=lfs -text
*.tbz2 filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.txz filter=lfs diff=lfs merge=lfs -text
*.whl filter=lfs diff=lfs merge=lfs -text
*.xz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.osc

View File

@@ -0,0 +1,67 @@
---
Lib/test/test_pyexpat.py | 4 ++++
Lib/test/test_sax.py | 3 +++
Lib/test/test_xml_etree.py | 10 ++++++++++
3 files changed, 17 insertions(+)
--- a/Lib/test/test_pyexpat.py
+++ b/Lib/test/test_pyexpat.py
@@ -791,6 +791,10 @@ class ReparseDeferralTest(unittest.TestC
self.assertEqual(started, ['doc'])
def test_reparse_deferral_disabled(self):
+ if expat.version_info < (2, 6, 0):
+ self.skipTest(f'Expat {expat.version_info} does not '
+ 'support reparse deferral')
+
started = []
def start_element(name, _):
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -1241,6 +1241,9 @@ class ExpatReaderTest(XmlTestBase):
self.assertEqual(result.getvalue(), start + b"<doc></doc>")
+ @unittest.skipIf(pyexpat.version_info < (2, 6, 0),
+ f'Expat {pyexpat.version_info} does not '
+ 'support reparse deferral')
def test_flush_reparse_deferral_disabled(self):
result = BytesIO()
xmlgen = XMLGenerator(result)
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -138,6 +138,11 @@ def equal_wrapper(cls):
return mock.patch.object(cls, "__eq__", autospec=True, wraps=eq)
+IS_SLE_15_7 = os.environ.get("SLE_VERSION", "") == "0150700"
+fails_with_expat_2_6_0 = (unittest.expectedFailure
+ # 2.4 version patched in SLE
+ if IS_SLE_15_7 and pyexpat.version_info >= (2, 4, 0) else
+ lambda test: test)
def checkwarnings(*filters, quiet=False):
def decorator(test):
def newtest(*args, **kwargs):
@@ -1520,9 +1525,11 @@ class XMLPullParserTest(unittest.TestCas
self.assert_event_tags(parser, [('end', 'root')])
self.assertIsNone(parser.close())
+ @fails_with_expat_2_6_0
def test_simple_xml_chunk_1(self):
self.test_simple_xml(chunk_size=1, flush=True)
+ @fails_with_expat_2_6_0
def test_simple_xml_chunk_5(self):
self.test_simple_xml(chunk_size=5, flush=True)
@@ -1747,6 +1754,9 @@ class XMLPullParserTest(unittest.TestCas
self.assert_event_tags(parser, [('end', 'doc')])
+ @unittest.skipIf(pyexpat.version_info < (2, 6, 0),
+ f'Expat {pyexpat.version_info} does not '
+ 'support reparse deferral')
def test_flush_reparse_deferral_disabled(self):
parser = ET.XMLPullParser(events=('start', 'end'))

View File

@@ -0,0 +1,480 @@
From 3a939ff2298d147459116f98a09549d0f1954039 Mon Sep 17 00:00:00 2001
From: Serhiy Storchaka <storchaka@gmail.com>
Date: Tue, 4 Feb 2025 11:44:39 +0200
Subject: Fix use-after-free in the unicode-escape decoder with error handler
If the error handler is used, a new bytes object is created to set as
the object attribute of UnicodeDecodeError, and that bytes object then
replaces the original data. A pointer to the decoded data will became invalid
after destroying that temporary bytes object. So we need other way to return
the first invalid escape from _PyUnicode_DecodeUnicodeEscapeInternal().
_PyBytes_DecodeEscape() does not have such issue, because it does not
use the error handlers registry, but it should be changed for compatibility
with _PyUnicode_DecodeUnicodeEscapeInternal().
---
Include/internal/pycore_bytesobject.h | 5
Include/internal/pycore_unicodeobject.h | 12 +-
Lib/test/test_codeccallbacks.py | 39 +++++++
Lib/test/test_codecs.py | 52 ++++++++--
Misc/NEWS.d/next/Security/2025-05-09-20-22-54.gh-issue-133767.kN2i3Q.rst | 2
Objects/bytesobject.c | 41 ++++---
Objects/unicodeobject.c | 46 +++++---
Parser/string_parser.c | 26 +++--
8 files changed, 160 insertions(+), 63 deletions(-)
Index: Python-3.14.0b1/Include/internal/pycore_bytesobject.h
===================================================================
--- Python-3.14.0b1.orig/Include/internal/pycore_bytesobject.h 2025-05-06 15:33:52.000000000 +0000
+++ Python-3.14.0b1/Include/internal/pycore_bytesobject.h 2025-05-17 06:44:53.614667081 +0000
@@ -20,8 +20,9 @@
// Helper for PyBytes_DecodeEscape that detects invalid escape chars.
// Export for test_peg_generator.
-PyAPI_FUNC(PyObject*) _PyBytes_DecodeEscape(const char *, Py_ssize_t,
- const char *, const char **);
+PyAPI_FUNC(PyObject*) _PyBytes_DecodeEscape2(const char *, Py_ssize_t,
+ const char *,
+ int *, const char **);
// Substring Search.
Index: Python-3.14.0b1/Include/internal/pycore_unicodeobject.h
===================================================================
--- Python-3.14.0b1.orig/Include/internal/pycore_unicodeobject.h 2025-05-06 15:33:52.000000000 +0000
+++ Python-3.14.0b1/Include/internal/pycore_unicodeobject.h 2025-05-17 06:44:53.614817134 +0000
@@ -139,14 +139,18 @@
// Helper for PyUnicode_DecodeUnicodeEscape that detects invalid escape
// chars.
// Export for test_peg_generator.
-PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeInternal(
+PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscapeInternal2(
const char *string, /* Unicode-Escape encoded string */
Py_ssize_t length, /* size of string */
const char *errors, /* error handling */
Py_ssize_t *consumed, /* bytes consumed */
- const char **first_invalid_escape); /* on return, points to first
- invalid escaped char in
- string. */
+ int *first_invalid_escape_char, /* on return, if not -1, contain the first
+ invalid escaped char (<= 0xff) or invalid
+ octal escape (> 0xff) in string. */
+ const char **first_invalid_escape_ptr); /* on return, if not NULL, may
+ point to the first invalid escaped
+ char in string.
+ May be NULL if errors is not NULL. */
/* --- Raw-Unicode-Escape Codecs ---------------------------------------------- */
Index: Python-3.14.0b1/Lib/test/test_codeccallbacks.py
===================================================================
--- Python-3.14.0b1.orig/Lib/test/test_codeccallbacks.py 2025-05-17 06:44:47.673341939 +0000
+++ Python-3.14.0b1/Lib/test/test_codeccallbacks.py 2025-05-17 06:44:53.615018793 +0000
@@ -2,6 +2,7 @@
import codecs
import html.entities
import itertools
+import re
import sys
import unicodedata
import unittest
@@ -1125,7 +1126,7 @@
text = 'abc<def>ghi'*n
text.translate(charmap)
- def test_mutatingdecodehandler(self):
+ def test_mutating_decode_handler(self):
baddata = [
("ascii", b"\xff"),
("utf-7", b"++"),
@@ -1160,6 +1161,42 @@
for (encoding, data) in baddata:
self.assertEqual(data.decode(encoding, "test.mutating"), "\u4242")
+ def test_mutating_decode_handler_unicode_escape(self):
+ decode = codecs.unicode_escape_decode
+ def mutating(exc):
+ if isinstance(exc, UnicodeDecodeError):
+ r = data.get(exc.object[:exc.end])
+ if r is not None:
+ exc.object = r[0] + exc.object[exc.end:]
+ return ('\u0404', r[1])
+ raise AssertionError("don't know how to handle %r" % exc)
+
+ codecs.register_error('test.mutating2', mutating)
+ data = {
+ br'\x0': (b'\\', 0),
+ br'\x3': (b'xxx\\', 3),
+ br'\x5': (b'x\\', 1),
+ }
+ def check(input, expected, msg):
+ with self.assertWarns(DeprecationWarning) as cm:
+ self.assertEqual(decode(input, 'test.mutating2'), (expected, len(input)))
+ self.assertIn(msg, str(cm.warning))
+
+ check(br'\x0n\z', '\u0404\n\\z', r'"\z" is an invalid escape sequence')
+ check(br'\x0n\501', '\u0404\n\u0141', r'"\501" is an invalid octal escape sequence')
+ check(br'\x0z', '\u0404\\z', r'"\z" is an invalid escape sequence')
+
+ check(br'\x3n\zr', '\u0404\n\\zr', r'"\z" is an invalid escape sequence')
+ check(br'\x3zr', '\u0404\\zr', r'"\z" is an invalid escape sequence')
+ check(br'\x3z5', '\u0404\\z5', r'"\z" is an invalid escape sequence')
+ check(memoryview(br'\x3z5x')[:-1], '\u0404\\z5', r'"\z" is an invalid escape sequence')
+ check(memoryview(br'\x3z5xy')[:-2], '\u0404\\z5', r'"\z" is an invalid escape sequence')
+
+ check(br'\x5n\z', '\u0404\n\\z', r'"\z" is an invalid escape sequence')
+ check(br'\x5n\501', '\u0404\n\u0141', r'"\501" is an invalid octal escape sequence')
+ check(br'\x5z', '\u0404\\z', r'"\z" is an invalid escape sequence')
+ check(memoryview(br'\x5zy')[:-1], '\u0404\\z', r'"\z" is an invalid escape sequence')
+
# issue32583
def test_crashing_decode_handler(self):
# better generating one more character to fill the extra space slot
Index: Python-3.14.0b1/Lib/test/test_codecs.py
===================================================================
--- Python-3.14.0b1.orig/Lib/test/test_codecs.py 2025-05-17 06:44:47.696604117 +0000
+++ Python-3.14.0b1/Lib/test/test_codecs.py 2025-05-17 06:44:53.615449954 +0000
@@ -1196,23 +1196,39 @@
check(br"[\1010]", b"[A0]")
check(br"[\x41]", b"[A]")
check(br"[\x410]", b"[A0]")
+
+ def test_warnings(self):
+ decode = codecs.escape_decode
+ check = coding_checker(self, decode)
for i in range(97, 123):
b = bytes([i])
if b not in b'abfnrtvx':
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\%c" is an invalid escape sequence' % i):
check(b"\\" + b, b"\\" + b)
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\%c" is an invalid escape sequence' % (i-32)):
check(b"\\" + b.upper(), b"\\" + b.upper())
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\8" is an invalid escape sequence'):
check(br"\8", b"\\8")
with self.assertWarns(DeprecationWarning):
check(br"\9", b"\\9")
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\\xfa" is an invalid escape sequence') as cm:
check(b"\\\xfa", b"\\\xfa")
for i in range(0o400, 0o1000):
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\%o" is an invalid octal escape sequence' % i):
check(rb'\%o' % i, bytes([i & 0o377]))
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\z" is an invalid escape sequence'):
+ self.assertEqual(decode(br'\x\z', 'ignore'), (b'\\z', 4))
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\501" is an invalid octal escape sequence'):
+ self.assertEqual(decode(br'\x\501', 'ignore'), (b'A', 6))
+
def test_errors(self):
decode = codecs.escape_decode
self.assertRaises(ValueError, decode, br"\x")
@@ -2661,24 +2677,40 @@
check(br"[\x410]", "[A0]")
check(br"\u20ac", "\u20ac")
check(br"\U0001d120", "\U0001d120")
+
+ def test_decode_warnings(self):
+ decode = codecs.unicode_escape_decode
+ check = coding_checker(self, decode)
for i in range(97, 123):
b = bytes([i])
if b not in b'abfnrtuvx':
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\%c" is an invalid escape sequence' % i):
check(b"\\" + b, "\\" + chr(i))
if b.upper() not in b'UN':
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\%c" is an invalid escape sequence' % (i-32)):
check(b"\\" + b.upper(), "\\" + chr(i-32))
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\8" is an invalid escape sequence'):
check(br"\8", "\\8")
with self.assertWarns(DeprecationWarning):
check(br"\9", "\\9")
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\\xfa" is an invalid escape sequence') as cm:
check(b"\\\xfa", "\\\xfa")
for i in range(0o400, 0o1000):
- with self.assertWarns(DeprecationWarning):
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\%o" is an invalid octal escape sequence' % i):
check(rb'\%o' % i, chr(i))
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\z" is an invalid escape sequence'):
+ self.assertEqual(decode(br'\x\z', 'ignore'), ('\\z', 4))
+ with self.assertWarnsRegex(DeprecationWarning,
+ r'"\\501" is an invalid octal escape sequence'):
+ self.assertEqual(decode(br'\x\501', 'ignore'), ('\u0141', 6))
+
def test_decode_errors(self):
decode = codecs.unicode_escape_decode
for c, d in (b'x', 2), (b'u', 4), (b'U', 4):
Index: Python-3.14.0b1/Misc/NEWS.d/next/Security/2025-05-09-20-22-54.gh-issue-133767.kN2i3Q.rst
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ Python-3.14.0b1/Misc/NEWS.d/next/Security/2025-05-09-20-22-54.gh-issue-133767.kN2i3Q.rst 2025-05-17 06:44:53.615887918 +0000
@@ -0,0 +1,2 @@
+Fix use-after-free in the "unicode-escape" decoder with a non-"strict" error
+handler.
Index: Python-3.14.0b1/Objects/bytesobject.c
===================================================================
--- Python-3.14.0b1.orig/Objects/bytesobject.c 2025-05-06 15:33:52.000000000 +0000
+++ Python-3.14.0b1/Objects/bytesobject.c 2025-05-17 06:44:53.616354335 +0000
@@ -1075,10 +1075,11 @@
}
/* Unescape a backslash-escaped string. */
-PyObject *_PyBytes_DecodeEscape(const char *s,
+PyObject *_PyBytes_DecodeEscape2(const char *s,
Py_ssize_t len,
const char *errors,
- const char **first_invalid_escape)
+ int *first_invalid_escape_char,
+ const char **first_invalid_escape_ptr)
{
int c;
char *p;
@@ -1092,7 +1093,8 @@
return NULL;
writer.overallocate = 1;
- *first_invalid_escape = NULL;
+ *first_invalid_escape_char = -1;
+ *first_invalid_escape_ptr = NULL;
end = s + len;
while (s < end) {
@@ -1130,9 +1132,10 @@
c = (c<<3) + *s++ - '0';
}
if (c > 0377) {
- if (*first_invalid_escape == NULL) {
- *first_invalid_escape = s-3; /* Back up 3 chars, since we've
- already incremented s. */
+ if (*first_invalid_escape_char == -1) {
+ *first_invalid_escape_char = c;
+ /* Back up 3 chars, since we've already incremented s. */
+ *first_invalid_escape_ptr = s - 3;
}
}
*p++ = c;
@@ -1173,9 +1176,10 @@
break;
default:
- if (*first_invalid_escape == NULL) {
- *first_invalid_escape = s-1; /* Back up one char, since we've
- already incremented s. */
+ if (*first_invalid_escape_char == -1) {
+ *first_invalid_escape_char = (unsigned char)s[-1];
+ /* Back up one char, since we've already incremented s. */
+ *first_invalid_escape_ptr = s - 1;
}
*p++ = '\\';
s--;
@@ -1195,18 +1199,19 @@
Py_ssize_t Py_UNUSED(unicode),
const char *Py_UNUSED(recode_encoding))
{
- const char* first_invalid_escape;
- PyObject *result = _PyBytes_DecodeEscape(s, len, errors,
- &first_invalid_escape);
+ int first_invalid_escape_char;
+ const char *first_invalid_escape_ptr;
+ PyObject *result = _PyBytes_DecodeEscape2(s, len, errors,
+ &first_invalid_escape_char,
+ &first_invalid_escape_ptr);
if (result == NULL)
return NULL;
- if (first_invalid_escape != NULL) {
- unsigned char c = *first_invalid_escape;
- if ('4' <= c && c <= '7') {
+ if (first_invalid_escape_char != -1) {
+ if (first_invalid_escape_char > 0xff) {
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
- "b\"\\%.3s\" is an invalid octal escape sequence. "
+ "b\"\\%o\" is an invalid octal escape sequence. "
"Such sequences will not work in the future. ",
- first_invalid_escape) < 0)
+ first_invalid_escape_char) < 0)
{
Py_DECREF(result);
return NULL;
@@ -1216,7 +1221,7 @@
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"b\"\\%c\" is an invalid escape sequence. "
"Such sequences will not work in the future. ",
- c) < 0)
+ first_invalid_escape_char) < 0)
{
Py_DECREF(result);
return NULL;
Index: Python-3.14.0b1/Objects/unicodeobject.c
===================================================================
--- Python-3.14.0b1.orig/Objects/unicodeobject.c 2025-05-06 15:33:52.000000000 +0000
+++ Python-3.14.0b1/Objects/unicodeobject.c 2025-05-17 06:44:53.617547540 +0000
@@ -6621,13 +6621,15 @@
/* --- Unicode Escape Codec ----------------------------------------------- */
PyObject *
-_PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
+_PyUnicode_DecodeUnicodeEscapeInternal2(const char *s,
Py_ssize_t size,
const char *errors,
Py_ssize_t *consumed,
- const char **first_invalid_escape)
+ int *first_invalid_escape_char,
+ const char **first_invalid_escape_ptr)
{
const char *starts = s;
+ const char *initial_starts = starts;
_PyUnicodeWriter writer;
const char *end;
PyObject *errorHandler = NULL;
@@ -6635,7 +6637,8 @@
_PyUnicode_Name_CAPI *ucnhash_capi;
// so we can remember if we've seen an invalid escape char or not
- *first_invalid_escape = NULL;
+ *first_invalid_escape_char = -1;
+ *first_invalid_escape_ptr = NULL;
if (size == 0) {
if (consumed) {
@@ -6723,9 +6726,12 @@
}
}
if (ch > 0377) {
- if (*first_invalid_escape == NULL) {
- *first_invalid_escape = s-3; /* Back up 3 chars, since we've
- already incremented s. */
+ if (*first_invalid_escape_char == -1) {
+ *first_invalid_escape_char = ch;
+ if (starts == initial_starts) {
+ /* Back up 3 chars, since we've already incremented s. */
+ *first_invalid_escape_ptr = s - 3;
+ }
}
}
WRITE_CHAR(ch);
@@ -6820,9 +6826,12 @@
goto error;
default:
- if (*first_invalid_escape == NULL) {
- *first_invalid_escape = s-1; /* Back up one char, since we've
- already incremented s. */
+ if (*first_invalid_escape_char == -1) {
+ *first_invalid_escape_char = c;
+ if (starts == initial_starts) {
+ /* Back up one char, since we've already incremented s. */
+ *first_invalid_escape_ptr = s - 1;
+ }
}
WRITE_ASCII_CHAR('\\');
WRITE_CHAR(c);
@@ -6867,19 +6876,20 @@
const char *errors,
Py_ssize_t *consumed)
{
- const char *first_invalid_escape;
- PyObject *result = _PyUnicode_DecodeUnicodeEscapeInternal(s, size, errors,
+ int first_invalid_escape_char;
+ const char *first_invalid_escape_ptr;
+ PyObject *result = _PyUnicode_DecodeUnicodeEscapeInternal2(s, size, errors,
consumed,
- &first_invalid_escape);
+ &first_invalid_escape_char,
+ &first_invalid_escape_ptr);
if (result == NULL)
return NULL;
- if (first_invalid_escape != NULL) {
- unsigned char c = *first_invalid_escape;
- if ('4' <= c && c <= '7') {
+ if (first_invalid_escape_char != -1) {
+ if (first_invalid_escape_char > 0xff) {
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
- "\"\\%.3s\" is an invalid octal escape sequence. "
+ "\"\\%o\" is an invalid octal escape sequence. "
"Such sequences will not work in the future. ",
- first_invalid_escape) < 0)
+ first_invalid_escape_char) < 0)
{
Py_DECREF(result);
return NULL;
@@ -6889,7 +6899,7 @@
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"\"\\%c\" is an invalid escape sequence. "
"Such sequences will not work in the future. ",
- c) < 0)
+ first_invalid_escape_char) < 0)
{
Py_DECREF(result);
return NULL;
Index: Python-3.14.0b1/Parser/string_parser.c
===================================================================
--- Python-3.14.0b1.orig/Parser/string_parser.c 2025-05-06 15:33:52.000000000 +0000
+++ Python-3.14.0b1/Parser/string_parser.c 2025-05-17 06:44:53.618734552 +0000
@@ -196,15 +196,18 @@
len = (size_t)(p - buf);
s = buf;
- const char *first_invalid_escape;
- v = _PyUnicode_DecodeUnicodeEscapeInternal(s, (Py_ssize_t)len, NULL, NULL, &first_invalid_escape);
+ int first_invalid_escape_char;
+ const char *first_invalid_escape_ptr;
+ v = _PyUnicode_DecodeUnicodeEscapeInternal2(s, (Py_ssize_t)len, NULL, NULL,
+ &first_invalid_escape_char,
+ &first_invalid_escape_ptr);
// HACK: later we can simply pass the line no, since we don't preserve the tokens
// when we are decoding the string but we preserve the line numbers.
- if (v != NULL && first_invalid_escape != NULL && t != NULL) {
- if (warn_invalid_escape_sequence(parser, s, first_invalid_escape, t) < 0) {
- /* We have not decref u before because first_invalid_escape points
- inside u. */
+ if (v != NULL && first_invalid_escape_ptr != NULL && t != NULL) {
+ if (warn_invalid_escape_sequence(parser, s, first_invalid_escape_ptr, t) < 0) {
+ /* We have not decref u before because first_invalid_escape_ptr
+ points inside u. */
Py_XDECREF(u);
Py_DECREF(v);
return NULL;
@@ -217,14 +220,17 @@
static PyObject *
decode_bytes_with_escapes(Parser *p, const char *s, Py_ssize_t len, Token *t)
{
- const char *first_invalid_escape;
- PyObject *result = _PyBytes_DecodeEscape(s, len, NULL, &first_invalid_escape);
+ int first_invalid_escape_char;
+ const char *first_invalid_escape_ptr;
+ PyObject *result = _PyBytes_DecodeEscape2(s, len, NULL,
+ &first_invalid_escape_char,
+ &first_invalid_escape_ptr);
if (result == NULL) {
return NULL;
}
- if (first_invalid_escape != NULL) {
- if (warn_invalid_escape_sequence(p, s, first_invalid_escape, t) < 0) {
+ if (first_invalid_escape_ptr != NULL) {
+ if (warn_invalid_escape_sequence(p, s, first_invalid_escape_ptr, t) < 0) {
Py_DECREF(result);
return NULL;
}

View File

@@ -0,0 +1,160 @@
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: [PATCH] 00251: Change user install location
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Set values of base and platbase in sysconfig from /usr
to /usr/local when RPM build is not detected
to make pip and similar tools install into separate location.
Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
Downstream only.
We've tried to rework in Fedora 36/Python 3.10 to follow https://bugs.python.org/issue43976
but we have identified serious problems with that approach,
see https://bugzilla.redhat.com/2026979 or https://bugzilla.redhat.com/2097183
pypa/distutils integration: https://github.com/pypa/distutils/pull/70
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Miro Hrončok <miro@hroncok.cz>
Co-authored-by: Michal Cyprian <m.cyprian@gmail.com>
Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
---
Lib/sysconfig/__init__.py | 51 ++++++++++++++++++++++++++++++++++++++++++++-
Lib/test/test_sysconfig.py | 17 +++++++++++++--
2 files changed, 65 insertions(+), 3 deletions(-)
Index: Python-3.14.0b1/Lib/sysconfig/__init__.py
===================================================================
--- Python-3.14.0b1.orig/Lib/sysconfig/__init__.py 2025-05-09 10:36:06.529281834 +0200
+++ Python-3.14.0b1/Lib/sysconfig/__init__.py 2025-05-09 10:36:13.125444450 +0200
@@ -106,6 +106,11 @@
else:
_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv']
+# For a brief period of time in the Fedora 36 life cycle,
+# this installation scheme existed and was documented in the release notes.
+# For backwards compatibility, we keep it here (at least on 3.10 and 3.11).
+_INSTALL_SCHEMES['rpm_prefix'] = _INSTALL_SCHEMES['posix_prefix']
+
def _get_implementation():
return 'Python'
@@ -169,13 +174,28 @@
},
}
+# This is used by distutils.command.install in the stdlib
+# as well as pypa/distutils (e.g. bundled in setuptools).
+# The self.prefix value is set to sys.prefix + /local/
+# if neither RPM build nor virtual environment is
+# detected to make distutils install packages
+# into the separate location.
+# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
+if (not (hasattr(sys, 'real_prefix') or
+ sys.prefix != sys.base_prefix) and
+ 'RPM_BUILD_ROOT' not in os.environ):
+ _prefix_addition = '/local'
+
+
_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
'scripts', 'data')
_PY_VERSION = sys.version.split()[0]
_PY_VERSION_SHORT = f'{sys.version_info[0]}.{sys.version_info[1]}'
_PY_VERSION_SHORT_NO_DOT = f'{sys.version_info[0]}{sys.version_info[1]}'
+_PREFIX = os.path.normpath(sys.prefix)
_BASE_PREFIX = os.path.normpath(sys.base_prefix)
+_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
# Mutex guarding initialization of _CONFIG_VARS.
_CONFIG_VARS_LOCK = threading.RLock()
@@ -268,11 +288,40 @@
target_dict[key] = value
+_CONFIG_VARS_LOCAL = None
+
+
+def _config_vars_local():
+ # This function returns the config vars with prefixes amended to /usr/local
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
+ global _CONFIG_VARS_LOCAL
+ if _CONFIG_VARS_LOCAL is None:
+ _CONFIG_VARS_LOCAL = dict(get_config_vars())
+ _CONFIG_VARS_LOCAL['base'] = '/usr/local'
+ _CONFIG_VARS_LOCAL['platbase'] = '/usr/local'
+ return _CONFIG_VARS_LOCAL
+
+
def _expand_vars(scheme, vars):
res = {}
if vars is None:
vars = {}
- _extend_dict(vars, get_config_vars())
+
+ # when we are not in a virtual environment or an RPM build
+ # we change '/usr' to '/usr/local'
+ # to avoid surprises, we explicitly check for the /usr/ prefix
+ # Python virtual environments have different prefixes
+ # we only do this for posix_prefix, not to mangle the venv scheme
+ # posix_prefix is used by sudo pip install
+ # 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
+ _PREFIX == '/usr' and
+ 'RPM_BUILD_ROOT' not in os.environ):
+ _extend_dict(vars, _config_vars_local())
+ else:
+ _extend_dict(vars, get_config_vars())
+
if os.name == 'nt':
# On Windows we want to substitute 'lib' for schemes rather
# than the native value (without modifying vars, in case it
Index: Python-3.14.0b1/Lib/test/test_sysconfig.py
===================================================================
--- Python-3.14.0b1.orig/Lib/test/test_sysconfig.py 2025-05-09 10:36:08.169776377 +0200
+++ Python-3.14.0b1/Lib/test/test_sysconfig.py 2025-05-09 10:36:13.125842689 +0200
@@ -132,8 +132,19 @@
for scheme in _INSTALL_SCHEMES:
for name in _INSTALL_SCHEMES[scheme]:
expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
+ tested = get_path(name, scheme)
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
+ if tested.startswith('/usr/local'):
+ # /usr/local should only be used in posix_prefix
+ self.assertEqual(scheme, 'posix_prefix')
+ # Fedora CI runs tests for venv and virtualenv that check for other prefixes
+ self.assertEqual(sys.prefix, '/usr')
+ # When building the RPM of Python, %check runs this with RPM_BUILD_ROOT set
+ # Fedora CI runs this with RPM_BUILD_ROOT unset
+ self.assertNotIn('RPM_BUILD_ROOT', os.environ)
+ tested = tested.replace('/usr/local', '/usr')
self.assertEqual(
- os.path.normpath(get_path(name, scheme)),
+ os.path.normpath(tested),
os.path.normpath(expected),
)
@@ -388,7 +399,7 @@
self.assertTrue(os.path.isfile(config_h), config_h)
def test_get_scheme_names(self):
- wanted = ['nt', 'posix_home', 'posix_prefix', 'posix_venv', 'nt_venv', 'venv']
+ wanted = ['nt', 'posix_home', 'posix_prefix', 'posix_venv', 'nt_venv', 'venv', 'rpm_prefix']
if HAS_USER_BASE:
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
@@ -400,6 +411,8 @@
cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
+ @unittest.skipIf('RPM_BUILD_ROOT' not in os.environ,
+ "Test doesn't expect Fedora's paths")
def test_user_similar(self):
# Issue #8759: make sure the posix scheme for the users
# is similar to the global posix_prefix one

26
PACKAGING-NOTES Normal file
View File

@@ -0,0 +1,26 @@
Notes for packagers of Python3
==============================
0. Faster build turnaround
--------------------------
By default, python builds with profile-guided optimization. This needs
an additional run of the test suite and it is generally slow.
PGO build takes around 50 minutes.
For development, use "--without profileopt" option to disable PGO. This
shortens the build time to ~5 minutes including test suite.
1. import_failed.map
----------------------
This is a mechanism installed as part of python3-base, that places shim modules
on python's path (through a generated zzzz-import-failed-hooks.pth file, so that
it is imported as much at the end as makes sense; and an _import_failed subdir
of /usr/lib/pythonX.Y). Then when the user tries to import a module that is part
of a subpackage, the ImportError will contain a helpful message telling them
which missing subpackage to install.
This can sometimes cause problems on non-standard configurations, if the pth
gets included too early (for instance if you are using a script to include all
pths by hand in some strange order). Just something to look out for.

3
Python-3.14.0a1.tar.xz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3e464b0cbb7535e2db34262fd19a0a393d0e62be0f43b1513ed98379b054ead4
size 22613224

View File

@@ -0,0 +1 @@
{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzTCCAlOgAwIBAgIUXNqbdBZJ9fps7cdl20sumJAq9qYwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjQxMDE1MjMwNDE2WhcNMjQxMDE1MjMxNDE2WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEcg+1tju2Qlwd/FxtfGT0xvTr74Z2Y4BSc2TvaDBBmRA/PtimxzlSdMhGDsfqHQLGi+b8OuTFW3Zox2aqHpqDCaOCAXIwggFuMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUVSMKNgZVgAfm3Hd9XuRrKl5zt40wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHQYDVR0RAQH/BBMwEYEPaHVnb0BweXRob24ub3JnMCwGCisGAQQBg78wAQEEHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDAuBgorBgEEAYO/MAEIBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDCBiQYKKwYBBAHWeQIEAgR7BHkAdwB1AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABkpJsy7QAAAQDAEYwRAIgfOwKhNkvL09iC5/uS5iTGmnIQbXjbUM1woNbLOSYA8sCIEb2hbK7hH+jGAxJQEG9OUlqHb9GwD7TVMxHdVMzpmoOMAoGCCqGSM49BAMDA2gAMGUCMCBvcdz/4awBy5UdMRubMhvQD3eF8sdlrEhkk1ymjVZzJW2gD1KQdzIxHNK/7F9hegIxAJ+lw+fOlGvkIB+txzmL6pg9Pcsf2x9DVpisHPW4WUUbB7VORIamogW8OSAuQsZ6tQ=="}, "tlogEntries": [{"logIndex": "140392200", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1729033456", "inclusionPromise": {"signedEntryTimestamp": "MEUCIEXI2s1U7Sve7CZ/p571004SLB9u5/ZT3Hf4tW9plQL/AiEAvvOg7se8XhZ+UNi7Qujx6bQxP0nHTrORgbP0Rg+xLGQ="}, "inclusionProof": {"logIndex": "18487938", "rootHash": "hSjsoi7BjBrhzW7Ceq8eDHavGqCXfJDqV1uLCH43rP0=", "treeSize": "18487939", "hashes": ["u79/W8pLop367cAKW1nkrasjLkk950s+chPOGd+YM7g=", "6/AN6/VWkeVC6ibK0wOaJWLDgeGYUPzGu++z5+WRpLw=", "XDRVudeM0USBGv0wfrkbUFLX5UPIMbXd7Jn+1FaHfXw=", "scHEQm8K7oRERzNSJaNlqN0E1OdiAscc4j9riGrA62g=", "/mosl9RAejdUfiMbl+lvD5kTT8EMHe3G8ceEh5ZmcAs=", "DPPCrptvLQKGtAJAKyVPBnf+K6vDmh24s1GP202TKto=", "dXjYLwyHqcxTI9MyukBet+9OyYvXCMvvLJJl9sIYKyA=", "rAAfgmPXo8TJp1LmkVDhAYrf0WzE4X4/mDuW1pwVM3Y=", "gf+9m552B3PnkWnO0o4KdVvjcT3WVHLrCbf1DoVYKFw="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n18487939\nhSjsoi7BjBrhzW7Ceq8eDHavGqCXfJDqV1uLCH43rP0=\n\n\u2014 rekor.sigstore.dev wNI9ajBGAiEAgDgD5PWqYAJ4/g3gd2iOpEzZI/0I/WH5zpJyi9r4DcECIQC+1ibcP0dHlJ6v7Jd7rq8ojgP5eTKxsEv7tTU8erfyTQ==\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiIzZTQ2NGIwY2JiNzUzNWUyZGIzNDI2MmZkMTlhMGEzOTNkMGU2MmJlMGY0M2IxNTEzZWQ5ODM3OWIwNTRlYWQ0In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJQVRMMFNVQnVnWW5NSFZjbzYrcGtPTTkxSVd3cHQ3bis3VTdmZlNCeXU1WUFpQXU0RkxJSzJiU1puSmxranFkOUgwV3hBdnE3NmVPeFZ4L21JZytxN0N0NkE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZWRU5EUVd4UFowRjNTVUpCWjBsVldFNXhZbVJDV2tvNVpuQnpOMk5rYkRJd2MzVnRTa0Z4T1hGWmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJlRTFFUlRGTmFrMTNUa1JGTWxkb1kwNU5hbEY0VFVSRk1VMXFUWGhPUkVVeVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZqWnlzeGRHcDFNbEZzZDJRdlJuaDBaa2RVTUhoMlZISTNORm95V1RSQ1UyTXlWSFlLWVVSQ1FtMVNRUzlRZEdsdGVIcHNVMlJOYUVkRWMyWnhTRkZNUjJrcllqaFBkVlJHVnpOYWIzZ3lZWEZJY0hGRVEyRlBRMEZZU1hkblowWjFUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZXVTAxTENrNW5XbFpuUVdadE0waGtPVmgxVW5KTGJEVjZkRFF3ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoUldVUldVakJTUVZGSUwwSkNUWGRGV1VWUVlVaFdibUl3UW5kbFdGSnZZakkwZFdJelNtNU5RM2RIUTJselIwRlJVVUpuTnpoM1FWRkZSUXBJYldnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemx6WWpKa2NHSnBPWFpaV0ZZd1lVUkJkVUpuYjNKQ1owVkZRVmxQTDAxQlJVbENRMEZOQ2todGFEQmtTRUo2VDJrNGRsb3liREJoU0ZacFRHMU9kbUpUT1hOaU1tUndZbWs1ZGxsWVZqQmhSRU5DYVZGWlMwdDNXVUpDUVVoWFpWRkpSVUZuVWpjS1FraHJRV1IzUWpGQlRqQTVUVWR5UjNoNFJYbFplR3RsU0Vwc2JrNTNTMmxUYkRZME0ycDVkQzgwWlV0amIwRjJTMlUyVDBGQlFVSnJjRXB6ZVRkUlFRcEJRVkZFUVVWWmQxSkJTV2RtVDNkTGFFNXJka3d3T1dsRE5TOTFVelZwVkVkdGJrbFJZbGhxWWxWTk1YZHZUbUpNVDFOWlFUaHpRMGxGWWpKb1lrczNDbWhJSzJwSFFYaEtVVVZIT1U5VmJIRklZamxIZDBRM1ZGWk5lRWhrVmsxNmNHMXZUMDFCYjBkRFEzRkhVMDAwT1VKQlRVUkJNbWRCVFVkVlEwMURRbllLWTJSNkx6UmhkMEo1TlZWa1RWSjFZazFvZGxGRU0yVkdPSE5rYkhKRmFHdHJNWGx0YWxaYWVrcFhNbWRFTVV0UlpIcEplRWhPU3k4M1JqbG9aV2RKZUFwQlNpdHNkeXRtVDJ4SGRtdEpRaXQwZUhwdFREWndaemxRWTNObU1uZzVSRlp3YVhOSVVGYzBWMVZWWWtJM1ZrOVNTV0Z0YjJkWE9FOVRRWFZSYzFvMkNuUlJQVDBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}]}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "PkZLDLt1NeLbNCYv0ZoKOT0OYr4PQ7FRPtmDebBU6tQ="}, "signature": "MEQCIATL0SUBugYnMHVco6+pkOM91IWwpt7n+7U7ffSByu5YAiAu4FLIK2bSZnJlkjqd9H0WxAvq76eOxVx/mIg+q7Ct6A=="}}

3
Python-3.14.0a2.tar.xz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2ff9e10147342b3efd69f5cd9cc06ec46250f2a046587599d18e2cac69c05920
size 22696948

File diff suppressed because one or more lines are too long

3
Python-3.14.0a3.tar.xz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:94349df207456a575a8867c20b4ca434f870e1920dcdcc8fdf797e1af49abe90
size 22749680

View File

@@ -0,0 +1 @@
{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzjCCAlWgAwIBAgIUDuq8kxtpL3by1SpAOIOeKKlsrjYwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjQxMjE3MTYwNzI2WhcNMjQxMjE3MTYxNzI2WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbmMPLFZSDjmfOKJGlOu6KqXbfARpxcurVugL1gOpPciVb/cVrPk9lP7V6B8zpnMK5ax2CbG3otAfweTtDWrnjqOCAXQwggFwMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUDct7Hl3MxAxfP1dhgpDF6PSlUuMwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHQYDVR0RAQH/BBMwEYEPaHVnb0BweXRob24ub3JnMCwGCisGAQQBg78wAQEEHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDAuBgorBgEEAYO/MAEIBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABk9Vfz7QAAAQDAEgwRgIhALGA/GkNojAPK5EODrVG03RxOEr/0bFyv5wxxxx9otO0AiEAt8SElgsdc7QW/vevYc0lQ6aA1BmxAsjG6O333PTx2hwwCgYIKoZIzj0EAwMDZwAwZAIwd8VqF3+Jxkb1Un90vEsxZAHErNq4ed7BStBPTL+z9ngwBpNcR2NySohOZxgBZuP0AjA5hXuw9WbV15D9do4x4gSiOpCe5AMpgoU/ld0YZfbwN0v/h2rIF64Cp2J04V1RYkw="}, "tlogEntries": [{"logIndex": "156043087", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1734451646", "inclusionPromise": {"signedEntryTimestamp": "MEUCIQD1bn+1BlbnvdMGTX8cRvOVMdhE9Imcz9FMgKSDo4q3yAIgJT+Nibv1h0auGmm6in89ane7DKqcH1e6JxT4sXHO1bQ="}, "inclusionProof": {"logIndex": "34138825", "rootHash": "7Qt+3ioEkHd/WQ+ZF4zkdbZ1JExMNGx/pF6U2cmtM/Q=", "treeSize": "34138826", "hashes": ["460W3n1CZaOKfLd1/YSC0H5L84wbbSFUNol1ZwDndoM=", "y7NhKWl4yggGf0GhUE9xHzlnejEw3Hip+npVOBmV31I=", "dV++dwKBz/zC/+rg8FF5eQt3qeYLLCBeALXUFzUUDvk=", "Fxn6iOFXoaUrdLXwrSYOGfimcHgNjfjb9TnhpIjuaCc=", "BkTein2wmT1o/gL3lyKvg06L/h4CKSyJUadCatxLBTI=", "M1nIbSb6tTZeslPr6Qyo3LT16Jr+lJ+fgJD3il4tqkc=", "dvMxr6G8Mnh7ppC7ZlLdoid1OKb+1L5aNmhT6oEy3og=", "NTLDQYFQUNEJKfKO4iPdERTA3qiw5W+1lj7tBj6ucO0=", "KSSbh1+IusMZKVSTJMSjnahGEacBezafZFvtTDmdcng=", "oj35HyCM3EqQ5Lil2RUr9boiRWZlouxLnqNA7z28Glc=", "vemyaMj0Na1LMjbB/9Dmkq8T+jAb3o+yCESgAayUABU="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n34138826\n7Qt+3ioEkHd/WQ+ZF4zkdbZ1JExMNGx/pF6U2cmtM/Q=\n\n\u2014 rekor.sigstore.dev wNI9ajBEAiAk3Vso0Awrs2GLdUg8Ol1Ck4ChMQGcLf/nLMpOmTHQ3AIgIGkpE6mkns2HjIewM4H4D+BPv0UWGBaEYuDx9NXJ5Tg=\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI5NDM0OWRmMjA3NDU2YTU3NWE4ODY3YzIwYjRjYTQzNGY4NzBlMTkyMGRjZGNjOGZkZjc5N2UxYWY0OWFiZTkwIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRGRodWh6cmtJOHZrZjVVSlNiOGRIT0w5OEtpWXIvd1NwWjFVK3JNd2tQbEFpQTVCbXZjamNNaTNPMlMyak56bDVzd20zVXpXTysxSGk1VnpqTGM5bVlKcFE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZha05EUVd4WFowRjNTVUpCWjBsVlJIVnhPR3Q0ZEhCTU0ySjVNVk53UVU5SlQyVkxTMnh6Y21wWmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFJlRTFxUlROTlZGbDNUbnBKTWxkb1kwNU5hbEY0VFdwRk0wMVVXWGhPZWtreVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZpYlUxUVRFWmFVMFJxYldaUFMwcEhiRTkxTmt0eFdHSm1RVkp3ZUdOMWNsWjFaMHdLTVdkUGNGQmphVlppTDJOV2NsQnJPV3hRTjFZMlFqaDZjRzVOU3pWaGVESkRZa2N6YjNSQlpuZGxWSFJFVjNKdWFuRlBRMEZZVVhkblowWjNUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZFWTNRM0NraHNNMDE0UVhobVVERmthR2R3UkVZMlVGTnNWWFZOZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoUldVUldVakJTUVZGSUwwSkNUWGRGV1VWUVlVaFdibUl3UW5kbFdGSnZZakkwZFdJelNtNU5RM2RIUTJselIwRlJVVUpuTnpoM1FWRkZSUXBJYldnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemx6WWpKa2NHSnBPWFpaV0ZZd1lVUkJkVUpuYjNKQ1owVkZRVmxQTDAxQlJVbENRMEZOQ2todGFEQmtTRUo2VDJrNGRsb3liREJoU0ZacFRHMU9kbUpUT1hOaU1tUndZbWs1ZGxsWVZqQmhSRU5DYVhkWlMwdDNXVUpDUVVoWFpWRkpSVUZuVWprS1FraHpRV1ZSUWpOQlRqQTVUVWR5UjNoNFJYbFplR3RsU0Vwc2JrNTNTMmxUYkRZME0ycDVkQzgwWlV0amIwRjJTMlUyVDBGQlFVSnJPVlptZWpkUlFRcEJRVkZFUVVWbmQxSm5TV2hCVEVkQkwwZHJUbTlxUVZCTE5VVlBSSEpXUnpBelVuaFBSWEl2TUdKR2VYWTFkM2g0ZUhnNWIzUlBNRUZwUlVGME9GTkZDbXhuYzJSak4xRlhMM1psZGxsak1HeFJObUZCTVVKdGVFRnpha2MyVHpNek0xQlVlREpvZDNkRFoxbEpTMjlhU1hwcU1FVkJkMDFFV25kQmQxcEJTWGNLWkRoV2NVWXpLMHA0YTJJeFZXNDVNSFpGYzNoYVFVaEZjazV4TkdWa04wSlRkRUpRVkV3cmVqbHVaM2RDY0U1alVqSk9lVk52YUU5YWVHZENXblZRTUFwQmFrRTFhRmgxZHpsWFlsWXhOVVE1Wkc4MGVEUm5VMmxQY0VObE5VRk5jR2R2VlM5c1pEQlpXbVppZDA0d2RpOW9NbkpKUmpZMFEzQXlTakEwVmpGU0NsbHJkejBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}]}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "lDSd8gdFaldaiGfCC0ykNPhw4ZINzcyP33l+GvSavpA="}, "signature": "MEQCIDdhuhzrkI8vkf5UJSb8dHOL98KiYr/wSpZ1U+rMwkPlAiA5BmvcjcMi3O2S2jNzl5swm3UzWO+1Hi5VzjLc9mYJpQ=="}}

3
Python-3.14.0a4.tar.xz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c24f07881873c1d460228795ca6ca8c99130e30c773c91463d30d7ea8ff0e70b
size 22798932

View File

@@ -0,0 +1 @@
{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzzCCAlWgAwIBAgIUTNqrmr/M2mihtEwN8O2FyM2q1q4wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwMTE0MTYwMTUwWhcNMjUwMTE0MTYxMTUwWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXFyDvDOdj/YAUw6VwCbccPuaGXVlONd/+yU2w6pjOucN7XNrKQzRc2p0B87e6fBJNtrvoQskKm5g5RZRNIaTraOCAXQwggFwMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQU+FemmqqSGkLeHpehmVT+O/2VD1MwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHQYDVR0RAQH/BBMwEYEPaHVnb0BweXRob24ub3JnMCwGCisGAQQBg78wAQEEHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDAuBgorBgEEAYO/MAEIBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABlGWMvxkAAAQDAEgwRgIhAMdC5GErGZYgWadLhCcmCxR3wAZ8jSVhTikA8HyIMUjKAiEAjZQMpnwoXgxNEXGAs8J/Myxxp5Lky719397l9nhdPk8wCgYIKoZIzj0EAwMDaAAwZQIxAMcST1Hx0VxHs8dH4fVNnJHRqHV70g4gWXOUahXOh86pLbvOOsGqM3w8o3kUhjO7oAIwRCZiVhDjDq59iDX6/IO7mG/gwNXBVqKSPdcYRS6l/SxM3JRORz8QCQK3HtM5TPvm"}, "tlogEntries": [{"logIndex": "162324179", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1736870510", "inclusionPromise": {"signedEntryTimestamp": "MEQCIAXgFU1gThdT0mhc6q0AXzD3bBXTiacgiLtvj81gdZF4AiBN9qUrwxowhsD9xRkTFuRk/l7pkEkkF84mJouMltHlqw=="}, "inclusionProof": {"logIndex": "40419917", "rootHash": "sQcmJqkpVAfxguDGAn46H0Jx7wI/seLoX5hw8YAhpzE=", "treeSize": "40419918", "hashes": ["qjl0o9LTqPs1qAydDqJeuEjAe7m0r28edbu6YhwigVs=", "ld8TM/ZFyvOEsuFo6tzdkPMu1WXFFF7FkLeePNxTZgQ=", "msMDMUPWOxenW8+fKcA9KtYwJh+qOm8eJ6hD6qMLxgo=", "HB3n8ruKgQ4/hsnPPqqgZqgqrIY+bil6MZEN48iQf5o=", "s4485wmLHDIJ3Uz0cZtlQJMaGl/NcoVYyRSxf8iaGF0=", "ipeSaii1joKqXMjR8vQt0JqN3F2T64mYFe55cZTSE7k=", "Zh8tfYPsaKKLrwZBF7ddhto+2SATy+XV9dtLPctNAlU=", "GVSyTNVOEKppJTUqz+nM5IM0FJ34fKBEIv5VAyJ7Dv4=", "tlaG/ckV5gypfBxP4OGlhhoLQ/VcEe+s4IdoNM+5CJk=", "LxTVSFPuriQ2RUI8Dbu2hz4wzAG1G271/Jivqrd1etw=", "vemyaMj0Na1LMjbB/9Dmkq8T+jAb3o+yCESgAayUABU="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n40419918\nsQcmJqkpVAfxguDGAn46H0Jx7wI/seLoX5hw8YAhpzE=\n\n\u2014 rekor.sigstore.dev wNI9ajBGAiEAv+PVAciPszI4zlpSunN4bfTvMqVTy5p62XGhyX7jQwACIQCNHJdBqkgiBk7OICiGqlcnklnK9wf4okEYP4iC2UpSUQ==\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJjMjRmMDc4ODE4NzNjMWQ0NjAyMjg3OTVjYTZjYThjOTkxMzBlMzBjNzczYzkxNDYzZDMwZDdlYThmZjBlNzBiIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUROejA2OHVmUE1tRUNZL3JldUdNSGRBbUhoazc1MHNaNHdTKytsY1g1Z0xRSWdLdzN1S1oydm9Jd2FMSWk1dFl3d2JBOUZUaFVHK05NUDViYmwyS0xSYXZjPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZla05EUVd4WFowRjNTVUpCWjBsVlZFNXhjbTF5TDAweWJXbG9kRVYzVGpoUE1rWjVUVEp4TVhFMGQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZkMDFVUlRCTlZGbDNUVlJWZDFkb1kwNU5hbFYzVFZSRk1FMVVXWGhOVkZWM1YycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZZUm5sRWRrUlBaR292V1VGVmR6WldkME5pWTJOUWRXRkhXRlpzVDA1a0x5dDVWVElLZHpad2FrOTFZMDQzV0U1eVMxRjZVbU15Y0RCQ09EZGxObVpDU2s1MGNuWnZVWE5yUzIwMVp6VlNXbEpPU1dGVWNtRlBRMEZZVVhkblowWjNUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlVyUm1WdENtMXhjVk5IYTB4bFNIQmxhRzFXVkN0UEx6SldSREZOZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoUldVUldVakJTUVZGSUwwSkNUWGRGV1VWUVlVaFdibUl3UW5kbFdGSnZZakkwZFdJelNtNU5RM2RIUTJselIwRlJVVUpuTnpoM1FWRkZSUXBJYldnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemx6WWpKa2NHSnBPWFpaV0ZZd1lVUkJkVUpuYjNKQ1owVkZRVmxQTDAxQlJVbENRMEZOQ2todGFEQmtTRUo2VDJrNGRsb3liREJoU0ZacFRHMU9kbUpUT1hOaU1tUndZbWs1ZGxsWVZqQmhSRU5DYVhkWlMwdDNXVUpDUVVoWFpWRkpSVUZuVWprS1FraHpRV1ZSUWpOQlRqQTVUVWR5UjNoNFJYbFplR3RsU0Vwc2JrNTNTMmxUYkRZME0ycDVkQzgwWlV0amIwRjJTMlUyVDBGQlFVSnNSMWROZG5oclFRcEJRVkZFUVVWbmQxSm5TV2hCVFdSRE5VZEZja2RhV1dkWFlXUk1hRU5qYlVONFVqTjNRVm80YWxOV2FGUnBhMEU0U0hsSlRWVnFTMEZwUlVGcVdsRk5DbkJ1ZDI5WVozaE9SVmhIUVhNNFNpOU5lWGg0Y0RWTWEzazNNVGt6T1Rkc09XNW9aRkJyT0hkRFoxbEpTMjlhU1hwcU1FVkJkMDFFWVVGQmQxcFJTWGdLUVUxalUxUXhTSGd3Vm5oSWN6aGtTRFJtVms1dVNraFNjVWhXTnpCbk5HZFhXRTlWWVdoWVQyZzRObkJNWW5aUFQzTkhjVTB6ZHpodk0ydFZhR3BQTndwdlFVbDNVa05hYVZab1JHcEVjVFU1YVVSWU5pOUpUemR0Unk5bmQwNVlRbFp4UzFOUVpHTlpVbE0yYkM5VGVFMHpTbEpQVW5vNFVVTlJTek5JZEUwMUNsUlFkbTBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}]}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "wk8HiBhzwdRgIoeVymyoyZEw4wx3PJFGPTDX6o/w5ws="}, "signature": "MEUCIQDNz068ufPMmECY/reuGMHdAmHhk750sZ4wS++lcX5gLQIgKw3uKZ2voIwaLIi5tYwwbA9FThUG+NMP5bbl2KLRavc="}}

3
Python-3.14.0a7.tar.xz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:71adbcec3ac9edf93308e55cfb4184f2eb4b16fda2bb0a5a382929ed29c8386d
size 23015952

View File

@@ -0,0 +1 @@
{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzjCCAlSgAwIBAgIUDwqRiJH4afgF7PkW1Qo6rr2v0lkwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNDA4MTQxMDA1WhcNMjUwNDA4MTQyMDA1WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZMgeduxSbRvf4+rxh9JLHe0ESc4Xexly0NaNWHeiTHLmdg+PRLNa5wLOEMZnjbZejU7znxttN65MnOzV5cOcoKOCAXMwggFvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUJQXlBvRXJEBKte20LxybMfGrT6YwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHQYDVR0RAQH/BBMwEYEPaHVnb0BweXRob24ub3JnMCwGCisGAQQBg78wAQEEHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDAuBgorBgEEAYO/MAEIBCAMHmh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aDCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABlhW8oHwAAAQDAEcwRQIhALZwxAQ5nnFRozZP8YRDJAl6S1kWfYD5oV7AEPrj0s5CAiA5CY5C5cBFEcjroS+wQAWg1LW4HqvRZ0KVR99kcb4a/TAKBggqhkjOPQQDAwNoADBlAjAHbpNPV8nJ2q37EdYR8NElF7p7qVBSdT9VzBLh0X0WL0Df0ub0LiBPYPNELQ/n0rQCMQDd2OPfzn42qBrwT/TUP2yR0/0h9nsqGOsinLhLH/euLXXJ+xK0iHMRLfk4cABvoFs="}, "tlogEntries": [{"logIndex": "193881744", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1744121405", "inclusionPromise": {"signedEntryTimestamp": "MEUCIQDZCZJVW+h+35nY12Z9y9tOkwStyIEVZmXSPx7mQUy0DwIgYWnL18yNoypHlLRSb2WIkcRxcD589pZdPORUS442MhU="}, "inclusionProof": {"logIndex": "71977482", "rootHash": "5SzvaU4/6U0MtwYjXGh0z1gIbnBbXfoMCLyL7PyEzE8=", "treeSize": "71977483", "hashes": ["+kSGTHFAaROPxw/+007Kwz3MXdUvY3V+rrY6sn3rTWc=", "gArlaOWkPW1lG6zUi9fwcxm6cyXspC+A2q3O5EzUI28=", "9TNwbV6fOnLuQ0CrvdKWO4n2fooZCvdCTwrFZCo6a8E=", "phHq2powa3InqGTI+IN0To1CKFgq/QLjjjUOmMz73pU=", "3tDvwrpMz/XYloigErVZuQZphUjJ7mX16wnR7tq2tMY=", "QReFEOB9XSZtDKsjRtA0fGnYGMYD2Z7qn50auG1YlWo=", "K26LG80DXyb+bC58c4Nw00WigG52v0PCsZGY3ExGsts=", "WEm5OgPzJpYROv+4CcrieexCYyQKrLUH3hbxmcQQ+DM=", "7v8qPHNDLerpduaMx06eb/MwgoQwczTn/cYGKX/9wZ4="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n71977483\n5SzvaU4/6U0MtwYjXGh0z1gIbnBbXfoMCLyL7PyEzE8=\n\n\u2014 rekor.sigstore.dev wNI9ajBFAiEAxksfGmVyE0Zi4wa9fM67aL5JUeJSsJUyWeU2jqqH/yoCIHfCdL/guuSIxD8tEK6/qQoRdbugANBBjI6gG96bkluH\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI3MWFkYmNlYzNhYzllZGY5MzMwOGU1NWNmYjQxODRmMmViNGIxNmZkYTJiYjBhNWEzODI5MjllZDI5YzgzODZkIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUR3U3lCQ2swa2t3NytBNDlSL0UxVmdrRUtORXhKYUt4ejU3SjYzUWdTSlhBSWdMdUVpNGNqMnMvTFZ1VEdaaThGMkxZZVhzOUJtYXA0cnVyU3NWWHI5L21VPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZha05EUVd4VFowRjNTVUpCWjBsVlJIZHhVbWxLU0RSaFptZEdOMUJyVnpGUmJ6WnljakoyTUd4cmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZkMDVFUVRSTlZGRjRUVVJCTVZkb1kwNU5hbFYzVGtSQk5FMVVVWGxOUkVFeFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZhVFdkbFpIVjRVMkpTZG1ZMEszSjRhRGxLVEVobE1FVlRZelJZWlhoc2VUQk9ZVTRLVjBobGFWUklURzFrWnl0UVVreE9ZVFYzVEU5RlRWcHVhbUphWldwVk4zcHVlSFIwVGpZMVRXNVBlbFkxWTA5amIwdFBRMEZZVFhkblowWjJUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZLVVZoc0NrSjJVbGhLUlVKTGRHVXlNRXg0ZVdKTlprZHlWRFpaZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoUldVUldVakJTUVZGSUwwSkNUWGRGV1VWUVlVaFdibUl3UW5kbFdGSnZZakkwZFdJelNtNU5RM2RIUTJselIwRlJVVUpuTnpoM1FWRkZSUXBJYldnd1pFaENlazlwT0haYU1td3dZVWhXYVV4dFRuWmlVemx6WWpKa2NHSnBPWFpaV0ZZd1lVUkJkVUpuYjNKQ1owVkZRVmxQTDAxQlJVbENRMEZOQ2todGFEQmtTRUo2VDJrNGRsb3liREJoU0ZacFRHMU9kbUpUT1hOaU1tUndZbWs1ZGxsWVZqQmhSRU5DYVdkWlMwdDNXVUpDUVVoWFpWRkpSVUZuVWpnS1FraHZRV1ZCUWpKQlRqQTVUVWR5UjNoNFJYbFplR3RsU0Vwc2JrNTNTMmxUYkRZME0ycDVkQzgwWlV0amIwRjJTMlUyVDBGQlFVSnNhRmM0YjBoM1FRcEJRVkZFUVVWamQxSlJTV2hCVEZwM2VFRlJOVzV1UmxKdmVscFFPRmxTUkVwQmJEWlRNV3RYWmxsRU5XOVdOMEZGVUhKcU1ITTFRMEZwUVRWRFdUVkRDalZqUWtaRlkycHliMU1yZDFGQlYyY3hURmMwU0hGMlVsb3dTMVpTT1RsclkySTBZUzlVUVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV2UVVSQ2JFRnFRVWdLWW5CT1VGWTRia295Y1RNM1JXUlpVamhPUld4R04zQTNjVlpDVTJSVU9WWjZRa3hvTUZnd1Ywd3dSR1l3ZFdJd1RHbENVRmxRVGtWTVVTOXVNSEpSUXdwTlVVUmtNazlRWm5wdU5ESnhRbkozVkM5VVZWQXllVkl3THpCb09XNXpjVWRQYzJsdVRHaE1TQzlsZFV4WVdFb3JlRXN3YVVoTlVreG1helJqUVVKMkNtOUdjejBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}]}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "ca287DrJ7fkzCOVc+0GE8utLFv2iuwpaOCkp7SnIOG0="}, "signature": "MEUCIQDwSyBCk0kkw7+A49R/E1VgkEKNExJaKxz57J63QgSJXAIgLuEi4cj2s/LVuTGZi8F2LYeXs9Bmap4rurSsVXr9/mU="}}

3
Python-3.14.0b1.tar.xz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2ddd30a77c9f62e065ce648664a254b9b0c011bcdaa8c1c2787087e644cbeb39
size 23358200

File diff suppressed because one or more lines are too long

3
Python-3.14.0b2.tar.xz Normal file
View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7ac9e84844bbc0a5a8f1f79a37a68b3b8caf2a58b4aa5999c49227cb36e70ea6
size 23579860

File diff suppressed because one or more lines are too long

43
README.SUSE Normal file
View File

@@ -0,0 +1,43 @@
Python 3 in SUSE
==============
* Subpackages *
Python 3 is split into several subpackages, based on external dependencies.
The main package 'python3' has soft dependencies on all subpackages needed to
assemble the standard library; however, these might not all be installed by default.
If you attempt to import a module that is currently not installed, an ImportError is thrown,
with instructions to install the missing subpackage. Installing the subpackage might result
in installing libraries that the subpackage requires to function.
* ensurepip *
The 'ensurepip' module from Python 3 standard library (PEP 453) is supposed to deploy
a bundled copy of the pip installer. This makes no sense in a managed distribution like SUSE.
Instead, you need to install package 'python3-pip'. Usually this will be installed automatically
with 'python3'.
Using 'ensurepip' when pip is not installed will result in an ImportError with instructions
to install 'python3-pip'.
* Documentation *
You can find documentation in seprarate packages: python3-doc and
python3-doc-pdf. These contan following documents:
Tutorial, What's New in Python, Global Module Index, Library Reference,
Macintosh Module Reference, Installing Python Modules, Distributing Python
Modules, Language Reference, Extending and Embedding, Python/C API,
Documenting Python
The python3-doc package constains many text files from source tarball.
* Interactive mode *
Interactive mode is by default enhanced with of history and command completion.
If you don't like these features, you can unset the PYTHONSTARTUP variable
in your .profile or disable it system wide in /etc/profile.d/python.sh.

6
_multibuild Normal file
View File

@@ -0,0 +1,6 @@
<multibuild>
<package>base</package>
<package>doc</package>
<package>nogil</package>
<package>nogil-base</package>
</multibuild>

3
baselibs.conf Normal file
View File

@@ -0,0 +1,3 @@
python314-base
python314
libpython3_14-1_0

BIN
bluez-devel-vendor.tar.xz (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -0,0 +1,165 @@
From 5754521af1d51aa8e445cba07a093bbc0c88596d Mon Sep 17 00:00:00 2001
From: Zackery Spytz <zspytz@gmail.com>
Date: Mon, 16 Dec 2019 18:24:08 -0700
Subject: [PATCH] bpo-31046: ensurepip does not honour the value of $(prefix)
Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
---
Doc/library/ensurepip.rst | 12 +++++-
Lib/ensurepip/__init__.py | 18 +++++++---
Lib/test/test_ensurepip.py | 11 ++++++
Makefile.pre.in | 4 +-
Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst | 1
5 files changed, 37 insertions(+), 9 deletions(-)
create mode 100644 Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst
--- a/Doc/library/ensurepip.rst
+++ b/Doc/library/ensurepip.rst
@@ -61,7 +61,11 @@ is at least as recent as the one availab
By default, ``pip`` is installed into the current virtual environment
(if one is active) or into the system site packages (if there is no
active virtual environment). The installation location can be controlled
-through two additional command line options:
+through some additional command line options:
+
+.. option:: --prefix <dir>
+
+ Installs ``pip`` using the given directory prefix.
.. option:: --root <dir>
@@ -102,7 +106,7 @@ Module API
Returns a string specifying the available version of pip that will be
installed when bootstrapping an environment.
-.. function:: bootstrap(root=None, upgrade=False, user=False, \
+.. function:: bootstrap(root=None, prefix=None, upgrade=False, user=False, \
altinstall=False, default_pip=False, \
verbosity=0)
@@ -112,6 +116,8 @@ Module API
If *root* is ``None``, then installation uses the default install location
for the current environment.
+ *prefix* specifies the directory prefix to use when installing.
+
*upgrade* indicates whether or not to upgrade an existing installation
of an earlier version of ``pip`` to the available version.
@@ -132,6 +138,8 @@ Module API
*verbosity* controls the level of output to :data:`sys.stdout` from the
bootstrapping operation.
+ .. versionchanged:: 3.9 the *prefix* parameter was added.
+
.. audit-event:: ensurepip.bootstrap root ensurepip.bootstrap
.. note::
--- a/Lib/ensurepip/__init__.py
+++ b/Lib/ensurepip/__init__.py
@@ -106,27 +106,27 @@ def _disable_pip_configuration_settings(
os.environ['PIP_CONFIG_FILE'] = os.devnull
-def bootstrap(*, root=None, upgrade=False, user=False,
+def bootstrap(*, root=None, prefix=None, upgrade=False, user=False,
altinstall=False, default_pip=False,
verbosity=0):
"""
Bootstrap pip into the current Python installation (or the given root
- directory).
+ and directory prefix).
Note that calling this function will alter both sys.path and os.environ.
"""
# Discard the return value
- _bootstrap(root=root, upgrade=upgrade, user=user,
+ _bootstrap(root=root, prefix=prefix, upgrade=upgrade, user=user,
altinstall=altinstall, default_pip=default_pip,
verbosity=verbosity)
-def _bootstrap(*, root=None, upgrade=False, user=False,
+def _bootstrap(*, root=None, prefix=None, upgrade=False, user=False,
altinstall=False, default_pip=False,
verbosity=0):
"""
Bootstrap pip into the current Python installation (or the given root
- directory). Returns pip command status code.
+ and directory prefix). Returns pip command status code.
Note that calling this function will alter both sys.path and os.environ.
"""
@@ -162,6 +162,8 @@ def _bootstrap(*, root=None, upgrade=Fal
args = ["install", "--no-cache-dir", "--no-index", "--find-links", tmpdir]
if root:
args += ["--root", root]
+ if prefix:
+ args += ["--prefix", prefix]
if upgrade:
args += ["--upgrade"]
if user:
@@ -238,6 +240,11 @@ def _main(argv=None):
help="Install everything relative to this alternate root directory.",
)
parser.add_argument(
+ "--prefix",
+ default=None,
+ help="Install everything using this prefix.",
+ )
+ parser.add_argument(
"--altinstall",
action="store_true",
default=False,
@@ -256,6 +263,7 @@ def _main(argv=None):
return _bootstrap(
root=args.root,
+ prefix=args.prefix,
upgrade=args.upgrade,
user=args.user,
verbosity=args.verbosity,
--- a/Lib/test/test_ensurepip.py
+++ b/Lib/test/test_ensurepip.py
@@ -100,6 +100,17 @@ class TestBootstrap(EnsurepipMixin, unit
unittest.mock.ANY,
)
+ def test_bootstrapping_with_prefix(self):
+ ensurepip.bootstrap(prefix="/foo/bar/")
+ self.run_pip.assert_called_once_with(
+ [
+ "install", "--no-cache-dir", "--no-index", "--find-links",
+ unittest.mock.ANY, "--prefix", "/foo/bar/",
+ "pip",
+ ],
+ unittest.mock.ANY,
+ )
+
def test_bootstrapping_with_user(self):
ensurepip.bootstrap(user=True)
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -2341,7 +2341,7 @@ install: @FRAMEWORKINSTALLFIRST@ @INSTAL
install|*) ensurepip="" ;; \
esac; \
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
- $$ensurepip --root=$(DESTDIR)/ ; \
+ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \
fi
.PHONY: altinstall
@@ -2352,7 +2352,7 @@ altinstall: commoninstall
install|*) ensurepip="--altinstall" ;; \
esac; \
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
- $$ensurepip --root=$(DESTDIR)/ ; \
+ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \
fi
.PHONY: commoninstall
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst
@@ -0,0 +1 @@
+A directory prefix can now be specified when using :mod:`ensurepip`.

12
externally_managed.in Normal file
View File

@@ -0,0 +1,12 @@
[externally-managed]
Error=To install Python packages system-wide, try
zypper install __PYTHONPREFIX__-xyz, where xyz is the package
you are trying to install.
If you wish to install a non-rpm packaged Python package,
create a virtual environment using __PYTHON__ -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip.
If you wish to install a non-rpm packaged Python application,
it may be easiest to use `pipx install xyz`, which will manage a
virtual environment for you. Install pipx via `zypper install __PYTHONPREFIX__-pipx` .

View File

@@ -0,0 +1,34 @@
---
Lib/test/test_compile.py | 5 +++++
1 file changed, 5 insertions(+)
Index: Python-3.14.0a7/Lib/test/test_compile.py
===================================================================
--- Python-3.14.0a7.orig/Lib/test/test_compile.py 2025-04-12 23:55:24.033076315 +0200
+++ Python-3.14.0a7/Lib/test/test_compile.py 2025-04-12 23:58:06.932213319 +0200
@@ -24,6 +24,9 @@
from test.support.bytecode_helper import instructions_with_positions
from test.support.os_helper import FakePath
+IS_SLE_15_6 = os.environ.get("SLE_VERSION", "") == "0150700"
+IS_32bit = hasattr(os, "uname") and os.uname().machine in ["i386", "i486", "i586", "i686"]
+
class TestSpecifics(unittest.TestCase):
def compile_single(self, source):
@@ -120,6 +123,7 @@
self.assertEqual(d['z'], 12)
@unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
+ @unittest.skipIf(IS_SLE_15_6 and IS_32bit, "fails on 15.6 i586")
@support.skip_emscripten_stack_overflow()
def test_extended_arg(self):
repeat = 100
@@ -709,6 +713,7 @@
@support.cpython_only
@unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
+ @unittest.skipIf(IS_SLE_15_6 and IS_32bit, "fails on 15.6 i586")
@support.skip_emscripten_stack_overflow()
def test_compiler_recursion_limit(self):
# Compiler frames are small

40
fix_test_ftp_error.patch Normal file
View File

@@ -0,0 +1,40 @@
---
Lib/test/test_urllib2.py | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -1,3 +1,4 @@
+import logging
import unittest
from test import support
from test.support import os_helper
@@ -29,6 +30,10 @@ import http.client
support.requires_working_socket(module=True)
+logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s',
+ level=logging.DEBUG)
+log = logging.getLogger()
+
# XXX
# Request
# CacheFTPHandler (hard to write)
@@ -731,6 +736,9 @@ def sanepathname2url(path):
class HandlerTests(unittest.TestCase):
+ def setUp(self):
+ log.debug('Is network available: {}'.format(support.is_resource_enabled('network')))
+
def test_ftp(self):
class MockFTPWrapper:
def __init__(self, data):
@@ -794,6 +802,7 @@ class HandlerTests(unittest.TestCase):
self.assertEqual(headers.get("Content-type"), mimetype)
self.assertEqual(int(headers["Content-length"]), len(data))
+ @support.requires_resource('network')
def test_ftp_error(self):
class ErrorFTPHandler(urllib.request.FTPHandler):
def __init__(self, exception):

View File

@@ -0,0 +1,34 @@
---
Lib/test/test_ctypes/test_generated_structs.py | 7 +++++++
1 file changed, 7 insertions(+)
--- a/Lib/test/test_ctypes/test_generated_structs.py
+++ b/Lib/test/test_ctypes/test_generated_structs.py
@@ -12,6 +12,7 @@ Run this module to regenerate the files:
import unittest
from test.support import import_helper
import re
+import sys
from dataclasses import dataclass
from functools import cached_property
@@ -21,6 +22,11 @@ from ctypes import sizeof, alignment, po
_ctypes_test = import_helper.import_module("_ctypes_test")
+def is_32bit():
+ # or alternatively (slightly slower)
+ # (struct.calcsize("P") * 8) == 32
+ return not (sys.maxsize > 2**32)
+
# ctypes erases the difference between `c_int` and e.g.`c_int16`.
# To keep it, we'll use custom subclasses with the C name stashed in `_c_name`:
class c_bool(ctypes.c_bool):
@@ -415,6 +421,7 @@ class AnonBitfields(Structure):
class GeneratedTest(unittest.TestCase):
+ @unittest.skipIf(is_32bit(), 'fails on 32bit platform (gh#python/cpython#121938)')
def test_generated_data(self):
"""Check that a ctypes struct/union matches its C equivalent.

View File

@@ -0,0 +1,37 @@
From 091fd6240c6b263d848e8a5d20da042258f648b5 Mon Sep 17 00:00:00 2001
From: Jonathan Protzenko <protz@microsoft.com>
Date: Thu, 10 Oct 2024 11:59:06 +0200
Subject: [PATCH 1/2] Try for Debian x86
---
Misc/sbom.spdx.json | 4 ++--
Modules/_hacl/libintvector.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
--- a/Misc/sbom.spdx.json
+++ b/Misc/sbom.spdx.json
@@ -804,11 +804,11 @@
"checksums": [
{
"algorithm": "SHA1",
- "checksumValue": "d5d85ee8f0bd52781fe470d0bf73ec388ddb3999"
+ "checksumValue": "f4a33ad535768b860362ab0bd033a70da0b524b7"
},
{
"algorithm": "SHA256",
- "checksumValue": "9a421b998add98fe366374641c4edb27617ff539a59f0963879f345065d3d39d"
+ "checksumValue": "433cdf4ba80bc72e0cea5d4b420ff18676baeafdb5ba19adf5b7fb33e90b424b"
}
],
"fileName": "Modules/_hacl/libintvector.h"
--- a/Modules/_hacl/libintvector.h
+++ b/Modules/_hacl/libintvector.h
@@ -19,7 +19,7 @@
#define Lib_IntVector_Intrinsics_bit_mask64(x) -((x) & 1)
-#if defined(__x86_64__) || defined(_M_X64)
+#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
#if defined(HACL_CAN_COMPILE_VEC128)

35
idle3.appdata.xml Normal file
View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2017 Zbigniew Jędrzejewski-Szmek -->
<application>
<id type="desktop">idle3.desktop</id>
<name>IDLE3</name>
<metadata_licence>CC0</metadata_licence>
<project_license>Python-2.0</project_license>
<summary>Python 3 Integrated Development and Learning Environment</summary>
<description>
<p>
IDLE is Pythons Integrated Development and Learning Environment.
The GUI is uniform between Windows, Unix, and Mac OS X.
IDLE provides an easy way to start writing, running, and debugging
Python code.
</p>
<p>
IDLE is written in pure Python, and uses the tkinter GUI toolkit.
It provides:
</p>
<ul>
<li>a Python shell window (interactive interpreter) with colorizing of code input, output, and error messages,</li>
<li>a multi-window text editor with multiple undo, Python colorizing, smart indent, call tips, auto completion, and other features,</li>
<li>search within any window, replace within editor windows, and search through multiple files (grep),</li>
<li>a debugger with persistent breakpoints, stepping, and viewing of global and local namespaces.</li>
</ul>
</description>
<url type="homepage">https://docs.python.org/3/library/idle.html</url>
<screenshots>
<screenshot type="default">http://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-main-window.png</screenshot>
<screenshot>http://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-class-browser.png</screenshot>
<screenshot>http://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-code-viewer.png</screenshot>
</screenshots>
<update_contact>zbyszek@in.waw.pl</update_contact>
</application>

12
idle3.desktop Normal file
View File

@@ -0,0 +1,12 @@
[Desktop Entry]
Version=1.0
Name=IDLE 3
GenericName=Python 3 IDE
Comment=Python 3 Integrated Development and Learning Environment
Exec=idle3 %F
TryExec=idle3
Terminal=false
Type=Application
Icon=idle3
Categories=Development;IDE;
MimeType=text/x-python;

7
import_failed.map Normal file
View File

@@ -0,0 +1,7 @@
python313-curses: curses _curses _curses_panel
python313-dbm: dbm _dbm _gdbm
python313-idle: idlelib
python313-testsuite: test _ctypes_test _testbuffer _testcapi _testinternalcapi _testimportmultiple _testmultiphase xxlimited
python313-tk: tkinter _tkinter
python313-tools: turtledemo
python313: sqlite3 readline _sqlite3 nis

23
import_failed.py Normal file
View File

@@ -0,0 +1,23 @@
import sys, os
from sysconfig import get_path
failed_map_path = os.path.join(get_path('stdlib'), '_import_failed', 'import_failed.map')
if __spec__:
failed_name = __spec__.name
else:
failed_name = __name__
with open(failed_map_path) as fd:
for line in fd:
package = line.split(':')[0]
imports = line.split(':')[1]
if failed_name in imports:
raise ImportError(f"""Module '{failed_name}' is not installed.
Use:
sudo zypper install {package}
to install it.""")
raise ImportError(f"""Module '{failed_name}' is not installed.
It is supposed to be part of python3 distribution, but missing from failed import map.
Please file a bug on the SUSE Bugzilla.""")

28
macros.python3 Normal file
View File

@@ -0,0 +1,28 @@
%have_python3 1
# commented out legacy macro definitions
#py3_prefix /usr
#py3_incdir /usr/include/python3.5m
#py3_ver 3.5
# these should now be provided by macros.python_all
#python3_sitearch /usr/lib64/python3.5/site-packages
#python3_sitelib /usr/lib/python3.5/site-packages
#python3_version 3.5
# hard to say if anyone ever used these?
#py3_soflags cpython-35m-x86_64-linux-gnu
#py3_abiflags m
%cpython3_soabi %(python3 -c "import sysconfig; print(sysconfig.get_config_var('SOABI'))")
%py3_soflags %cpython3_soabi
# compilation macros that might be in use somewhere
%py3_compile(O) \
find %1 -name '*.pyc' -exec rm -f {} ";"\
python3 -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1\
%{-O:\
find %1 -name '*.pyo' -exec rm -f {} ";"\
python3 -O -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1\
}

78
pre_checkin.sh Normal file
View File

@@ -0,0 +1,78 @@
#!/bin/bash
export LC_ALL=C
master=python*.spec
# create import_failed.map from package definitions
pkgname=$(grep python_pkg_name $master |grep define |awk -F' ' '{print $3}')
MAPFILE=import_failed.map
function new_map_line () {
package=$1
package=$(echo $1 |sed -e "s:%{python_pkg_name}:$pkgname:")
modules=$2
if [ -z "$package" -o -z "$modules" ]; then
return
fi
if [[ "$package" =~ "-base" ]]; then
return
fi
echo "$package:$modules" >> $MAPFILE.tmp
}
for spec in *.spec; do
basename=${spec%.spec}
package=
modules=
while read line; do
case $line in
"%files -n "*)
new_map_line $package "$modules"
package=${line#"%files -n "}
modules=
;;
"%files "*)
new_map_line $package "$modules"
package=$basename-${line#"%files "}
modules=
;;
"%files")
new_map_line $package "$modules"
package=$basename
modules=
;;
"%{sitedir}/config-"*)
# ignore
;;
"%{sitedir}/"*)
word=${line#"%{sitedir}/"}
if ! echo $word | grep -q /; then
modules="$modules $word"
fi
;;
"%{dynlib "*"}")
word=${line#"%{dynlib "}
word=${word%"}"}
modules="$modules $word"
;;
esac
done < $spec
new_map_line $package "$modules"
done
cat $MAPFILE.tmp |sort -u > $MAPFILE
rm $MAPFILE.tmp
# run test inclusion check
tar xJf Python-*.xz
python3 skipped_tests.py
# generate baselibs.conf
VERSION=$(grep ^Version $master|awk -F':' '{print $2}' |sed -e 's/ //g')
python_version=${VERSION:0:3} # 3.3
python_version_abitag=${python_version//./} # 33
python_version_soname=${python_version//./_} # 3_3
echo "$pkgname-base" > baselibs.conf
echo "$pkgname" >> baselibs.conf
echo "libpython$python_version_soname-1_0" >> baselibs.conf

View File

@@ -0,0 +1,18 @@
---
Makefile.pre.in | 5 +++++
1 file changed, 5 insertions(+)
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1880,6 +1880,11 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
-DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \
-o $@ $(srcdir)/Modules/getbuildinfo.c
+Python/getcompiler.o: $(srcdir)/Python/getcompiler.c Makefile
+ $(CC) -c $(PY_CORE_CFLAGS) \
+ -DCOMPILER='"[GCC]"' \
+ -o $@ $(srcdir)/Python/getcompiler.c
+
Modules/getpath.o: $(srcdir)/Modules/getpath.c Python/frozen_modules/getpath.h Makefile $(PYTHON_HEADERS)
$(CC) -c $(PY_CORE_CFLAGS) -DPYTHONPATH='"$(PYTHONPATH)"' \
-DPREFIX='"$(host_prefix)"' \

View File

@@ -0,0 +1,15 @@
---
Lib/site.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -78,7 +78,7 @@ import stat
import errno
# Prefixes for site-packages; add additional prefixes like /usr/local here
-PREFIXES = [sys.prefix, sys.exec_prefix]
+PREFIXES = [sys.prefix, sys.exec_prefix, '/usr/local']
# Enable per user site-packages directory
# set it to False to disable the feature or True to force the feature
ENABLE_USER_SITE = None

3
python314-rpmlintrc Normal file
View File

@@ -0,0 +1,3 @@
addFilter("pem-certificate.*/usr/lib.*/python.*/test/*.pem")
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/tests/*.c")
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/test/*.cpp")

11338
python314.changes Normal file

File diff suppressed because it is too large Load Diff

1150
python314.spec Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
---
Lib/test/test_capi/test_mem.py | 1 +
1 file changed, 1 insertion(+)
--- a/Lib/test/test_capi/test_mem.py
+++ b/Lib/test/test_capi/test_mem.py
@@ -114,6 +114,7 @@ class PyMemDebugTests(unittest.TestCase)
def test_pyobject_forbidden_bytes_is_freed(self):
self.check_pyobject_is_freed('check_pyobject_forbidden_bytes_is_freed')
+ @unittest.skip('Failing on Leap 15.*')
def test_pyobject_freed_is_freed(self):
self.check_pyobject_is_freed('check_pyobject_freed_is_freed')

69
skipped_tests.py Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/python3
"""
Simple regexp-based skipped test checker.
It lists tests that are mentioned (presumably for exclusion)
in BASE, and in MAIN (presumably for inclusion)
and reports discrepancies.
This will have a number of
"""
MAIN = "python39.spec"
import glob
import re
from os.path import basename
alltests = set()
qemu_exclusions = set()
for item in glob.glob("Python-*/Lib/test/test_*"):
testname = basename(item)
if testname.endswith(".py"):
testname = testname[:-3]
alltests.add(testname)
testre = re.compile(r'[\s"](test_\w+)\b')
def find_tests_in_spec(specname):
global qemu_exclusions
found_tests = set()
with open(specname) as spec:
in_qemu = False
for line in spec:
line = line.strip()
if "#" in line:
line = line[:line.index("#")]
tests = set(testre.findall(line))
found_tests |= tests
if line == "%if 0%{?qemu_user_space_build} > 0":
in_qemu = True
if in_qemu:
if line == "%endif":
in_qemu = False
qemu_exclusions |= tests
return found_tests
excluded = find_tests_in_spec(MAIN)
#print("--- excluded tests:", " ".join(sorted(excluded)))
#print("--- included tests:", " ".join(sorted(included)))
mentioned = excluded
nonexistent = mentioned - alltests
missing = excluded - qemu_exclusions
print("--- the following tests are excluded for QEMU and not tested in python")
print("--- (that probably means we don't need to worry about them)")
for test in sorted(qemu_exclusions - excluded):
print(test)
print("--- the following tests might be excluded in python:")
for test in sorted(missing):
print(test)
if nonexistent:
print("--- the following tests don't exist:")
for test in sorted(nonexistent):
print(test)

View File

@@ -0,0 +1,21 @@
---
Lib/test/test_subprocess.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
Index: Python-3.14.0b1/Lib/test/test_subprocess.py
===================================================================
--- Python-3.14.0b1.orig/Lib/test/test_subprocess.py 2025-05-09 10:36:08.150615546 +0200
+++ Python-3.14.0b1/Lib/test/test_subprocess.py 2025-05-09 10:36:21.907614565 +0200
@@ -160,7 +160,11 @@
# child.
self.assertRaises(subprocess.TimeoutExpired, subprocess.call,
[sys.executable, "-c", "while True: pass"],
- timeout=0.1)
+ # Some heavily loaded buildbots (sparc Debian 3.x) require
+ # this much time to start and print.
+ # timeout=3)
+ # OBS might require even more
+ timeout=10)
def test_timeout_exception(self):
try: