commit c3b20ea06a9441c9a55cf77ac4db2e06f70402f1d582e51a7b933e7db38f7a1e Author: Matej Cepl Date: Thu Oct 16 16:27:30 2025 +0000 - Update to 3.11.14: - Security - gh-139700: Check consistency of the zip64 end of central directory record. Support records with “zip64 extensible data” if there are no bytes prepended to the ZIP file. - gh-139400: xml.parsers.expat: Make sure that parent Expat parsers are only garbage-collected once they are no longer referenced by subparsers created by ExternalEntityParserCreate(). Patch by Sebastian Pipping. - gh-135661: Fix parsing start and end tags in html.parser.HTMLParser according to the HTML5 standard. * Whitespaces no longer accepted between does not end the script section. * Vertical tabulation (\v) and non-ASCII whitespaces no longer recognized as whitespaces. The only whitespaces are \t\n\r\f and space. * Null character (U+0000) no longer ends the tag name. * Attributes and slashes after the tag name in end tags are now ignored, instead of terminating after the first > in quoted attribute value. E.g. . * Multiple slashes and whitespaces between the last attribute and closing > are now ignored in both start and end tags. E.g. . * Multiple = between attribute name and value are no longer collapsed. E.g. produces attribute “foo” with value “=bar”. - gh-135661: Fix CDATA section parsing in html.parser.HTMLParser according to the HTML5 standard: ] ]> and ]] > no longer end the CDATA section. Add private method _set_support_cdata() which can be used to specify how to parse <[CDATA[ — as a CDATA section in OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python311?expand=0&rev=199 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57affb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.osc diff --git a/CVE-2023-52425-libexpat-2.6.0-backport.patch b/CVE-2023-52425-libexpat-2.6.0-backport.patch new file mode 100644 index 0000000..1acc25a --- /dev/null +++ b/CVE-2023-52425-libexpat-2.6.0-backport.patch @@ -0,0 +1,233 @@ +--- + Lib/test/support/__init__.py | 16 ++++++++++++++-- + Lib/test/test_minidom.py | 23 +++++++++-------------- + Lib/test/test_pyexpat.py | 12 +++++------- + Lib/test/test_sax.py | 18 +++++++++--------- + Lib/test/test_xml_etree.py | 12 ------------ + 5 files changed, 37 insertions(+), 44 deletions(-) + +Index: Python-3.11.12/Lib/test/support/__init__.py +=================================================================== +--- Python-3.11.12.orig/Lib/test/support/__init__.py 2025-04-11 10:52:43.191010503 +0200 ++++ Python-3.11.12/Lib/test/support/__init__.py 2025-04-11 10:52:44.802161741 +0200 +@@ -8,6 +8,7 @@ + import functools + import os + import re ++import pyexpat + import stat + import sys + import sysconfig +@@ -56,7 +57,7 @@ + "run_with_tz", "PGO", "missing_compiler_executable", + "ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST", + "LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT", +- "skip_on_s390x", ++ "skip_on_s390x", "fails_with_expat_2_6_0", "is_expat_2_6_0" + ] + + +@@ -2244,6 +2245,17 @@ + } + return ignored + +-#Windows doesn't have os.uname() but it doesn't support s390x. ++ ++# Windows doesn't have os.uname() but it doesn't support s390x. + skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x', + 'skipped on s390x') ++ ++ ++@functools.lru_cache ++def _is_expat_2_6_0(): ++ return hasattr(pyexpat.ParserCreate(), 'SetReparseDeferralEnabled') ++is_expat_2_6_0 = _is_expat_2_6_0() ++ ++fails_with_expat_2_6_0 = (unittest.expectedFailure ++ if is_expat_2_6_0 ++ else lambda test: test) +Index: Python-3.11.12/Lib/test/test_minidom.py +=================================================================== +--- Python-3.11.12.orig/Lib/test/test_minidom.py 2025-04-11 10:52:21.907086938 +0200 ++++ Python-3.11.12/Lib/test/test_minidom.py 2025-04-11 10:52:44.802522893 +0200 +@@ -6,7 +6,6 @@ + from test import support + import unittest + +-import pyexpat + import xml.dom.minidom + + from xml.dom.minidom import parse, Attr, Node, Document, parseString +@@ -1163,13 +1162,11 @@ + + # Verify that character decoding errors raise exceptions instead + # of crashing +- if pyexpat.version_info >= (2, 4, 5): +- self.assertRaises(ExpatError, parseString, +- b'') +- self.assertRaises(ExpatError, parseString, +- b'Comment \xe7a va ? Tr\xe8s bien ?') +- else: +- self.assertRaises(UnicodeDecodeError, parseString, ++ # It doesn’t make any sense to insist on the exact text of the ++ # error message, or even the exact Exception … it is enough that ++ # the error has been discovered. ++ with self.assertRaises((UnicodeDecodeError, ExpatError)): ++ parseString( + b'Comment \xe7a va ? Tr\xe8s bien ?') + + doc.unlink() +@@ -1631,12 +1628,10 @@ + self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE) + + def testExceptionOnSpacesInXMLNSValue(self): +- if pyexpat.version_info >= (2, 4, 5): +- context = self.assertRaisesRegex(ExpatError, 'syntax error') +- else: +- context = self.assertRaisesRegex(ValueError, 'Unsupported syntax') +- +- with context: ++ # It doesn’t make any sense to insist on the exact text of the ++ # error message, or even the exact Exception … it is enough that ++ # the error has been discovered. ++ with self.assertRaises((ExpatError, ValueError)): + parseString('') + + def testDocRemoveChild(self): +Index: Python-3.11.12/Lib/test/test_pyexpat.py +=================================================================== +--- Python-3.11.12.orig/Lib/test/test_pyexpat.py 2025-04-11 10:52:22.076696906 +0200 ++++ Python-3.11.12/Lib/test/test_pyexpat.py 2025-04-11 10:52:44.803228085 +0200 +@@ -14,8 +14,7 @@ + from xml.parsers import expat + from xml.parsers.expat import errors + +-from test.support import sortdict, is_emscripten, is_wasi +- ++from test.support import sortdict, is_emscripten, is_wasi, is_expat_2_6_0 + + class SetAttributeTest(unittest.TestCase): + def setUp(self): +@@ -770,9 +769,8 @@ + self.assertIs(parser.GetReparseDeferralEnabled(), enabled) + + def test_reparse_deferral_enabled(self): +- if expat.version_info < (2, 6, 0): +- self.skipTest(f'Expat {expat.version_info} does not ' +- 'support reparse deferral') ++ if not is_expat_2_6_0: ++ self.skipTest("Linked libexpat doesn't support reparse deferral") + + started = [] + +@@ -801,9 +799,9 @@ + + parser = expat.ParserCreate() + parser.StartElementHandler = start_element +- if expat.version_info >= (2, 6, 0): ++ if is_expat_2_6_0: + parser.SetReparseDeferralEnabled(False) +- self.assertFalse(parser.GetReparseDeferralEnabled()) ++ self.assertFalse(parser.GetReparseDeferralEnabled()) + + for chunk in (b''): + parser.Parse(chunk, False) +Index: Python-3.11.12/Lib/test/test_sax.py +=================================================================== +--- Python-3.11.12.orig/Lib/test/test_sax.py 2025-04-11 10:52:22.111440337 +0200 ++++ Python-3.11.12/Lib/test/test_sax.py 2025-04-11 10:52:44.803567098 +0200 +@@ -19,13 +19,11 @@ + from io import BytesIO, StringIO + import codecs + import os.path +-import pyexpat + import shutil + import sys + from urllib.error import URLError + import urllib.request +-from test.support import os_helper +-from test.support import findfile ++from test.support import os_helper, findfile, is_expat_2_6_0 + from test.support.os_helper import FakePath, TESTFN + + +@@ -1215,10 +1213,10 @@ + + self.assertEqual(result.getvalue(), start + b"text") + +- @unittest.skipIf(pyexpat.version_info < (2, 6, 0), +- f'Expat {pyexpat.version_info} does not ' +- 'support reparse deferral') + def test_flush_reparse_deferral_enabled(self): ++ if not is_expat_2_6_0: ++ self.skipTest("Linked libexpat doesn't support reparse deferral") ++ + result = BytesIO() + xmlgen = XMLGenerator(result) + parser = create_parser() +@@ -1241,6 +1239,9 @@ + self.assertEqual(result.getvalue(), start + b"") + + def test_flush_reparse_deferral_disabled(self): ++ if not is_expat_2_6_0: ++ self.skipTest("Linked libexpat doesn't support reparse deferral") ++ + result = BytesIO() + xmlgen = XMLGenerator(result) + parser = create_parser() +@@ -1249,9 +1250,8 @@ + for chunk in (""): + parser.feed(chunk) + +- if pyexpat.version_info >= (2, 6, 0): +- parser._parser.SetReparseDeferralEnabled(False) +- self.assertEqual(result.getvalue(), start) # i.e. no elements started ++ parser._parser.SetReparseDeferralEnabled(False) ++ self.assertEqual(result.getvalue(), start) # i.e. no elements started + + self.assertFalse(parser._parser.GetReparseDeferralEnabled()) + +Index: Python-3.11.12/Lib/test/test_xml_etree.py +=================================================================== +--- Python-3.11.12.orig/Lib/test/test_xml_etree.py 2025-04-11 10:52:22.425637912 +0200 ++++ Python-3.11.12/Lib/test/test_xml_etree.py 2025-04-11 10:52:44.804234785 +0200 +@@ -13,7 +13,6 @@ + import operator + import os + import pickle +-import pyexpat + import sys + import textwrap + import types +@@ -1424,12 +1423,6 @@ + self.assert_event_tags(parser, [('end', 'root')]) + self.assertIsNone(parser.close()) + +- def test_simple_xml_chunk_1(self): +- self.test_simple_xml(chunk_size=1, flush=True) +- +- def test_simple_xml_chunk_5(self): +- self.test_simple_xml(chunk_size=5, flush=True) +- + def test_simple_xml_chunk_22(self): + self.test_simple_xml(chunk_size=22) + +@@ -1627,9 +1620,6 @@ + with self.assertRaises(ValueError): + ET.XMLPullParser(events=('start', 'end', 'bogus')) + +- @unittest.skipIf(pyexpat.version_info < (2, 6, 0), +- f'Expat {pyexpat.version_info} does not ' +- 'support reparse deferral') + def test_flush_reparse_deferral_enabled(self): + parser = ET.XMLPullParser(events=('start', 'end')) + +@@ -1656,8 +1646,6 @@ + + for chunk in (""): + parser.feed(chunk) +- +- if pyexpat.version_info >= (2, 6, 0): + if not ET is pyET: + self.skipTest(f'XMLParser.(Get|Set)ReparseDeferralEnabled ' + 'methods not available in C') diff --git a/CVE-2023-52425-remove-reparse_deferral-tests.patch b/CVE-2023-52425-remove-reparse_deferral-tests.patch new file mode 100644 index 0000000..553bdf8 --- /dev/null +++ b/CVE-2023-52425-remove-reparse_deferral-tests.patch @@ -0,0 +1,60 @@ +--- + Lib/test/test_pyexpat.py | 2 ++ + Lib/test/test_sax.py | 2 ++ + Lib/test/test_xml_etree.py | 2 ++ + 3 files changed, 6 insertions(+) + +--- a/Lib/test/test_pyexpat.py ++++ b/Lib/test/test_pyexpat.py +@@ -768,6 +768,7 @@ class ReparseDeferralTest(unittest.TestC + parser.SetReparseDeferralEnabled(True) + self.assertIs(parser.GetReparseDeferralEnabled(), enabled) + ++ @unittest.skip('Tests are failing.') + def test_reparse_deferral_enabled(self): + if not is_expat_2_6_0: + self.skipTest("Linked libexpat doesn't support reparse deferral") +@@ -791,6 +792,7 @@ class ReparseDeferralTest(unittest.TestC + + self.assertEqual(started, ['doc']) + ++ @unittest.skip('Tests are failing.') + def test_reparse_deferral_disabled(self): + started = [] + +--- a/Lib/test/test_sax.py ++++ b/Lib/test/test_sax.py +@@ -1213,6 +1213,7 @@ class ExpatReaderTest(XmlTestBase): + + self.assertEqual(result.getvalue(), start + b"text") + ++ @unittest.skip('Tests are failing.') + def test_flush_reparse_deferral_enabled(self): + if not is_expat_2_6_0: + self.skipTest("Linked libexpat doesn't support reparse deferral") +@@ -1238,6 +1239,7 @@ class ExpatReaderTest(XmlTestBase): + + self.assertEqual(result.getvalue(), start + b"") + ++ @unittest.skip('Tests are failing.') + def test_flush_reparse_deferral_disabled(self): + if not is_expat_2_6_0: + self.skipTest("Linked libexpat doesn't support reparse deferral") +--- a/Lib/test/test_xml_etree.py ++++ b/Lib/test/test_xml_etree.py +@@ -1620,6 +1620,7 @@ class XMLPullParserTest(unittest.TestCas + with self.assertRaises(ValueError): + ET.XMLPullParser(events=('start', 'end', 'bogus')) + ++ @unittest.skip('Tests are failing.') + def test_flush_reparse_deferral_enabled(self): + parser = ET.XMLPullParser(events=('start', 'end')) + +@@ -1641,6 +1642,7 @@ class XMLPullParserTest(unittest.TestCas + + self.assert_event_tags(parser, [('end', 'doc')]) + ++ @unittest.skip('Tests are failing.') + def test_flush_reparse_deferral_disabled(self): + parser = ET.XMLPullParser(events=('start', 'end')) + diff --git a/CVE-2025-6069-quad-complex-HTMLParser.patch b/CVE-2025-6069-quad-complex-HTMLParser.patch new file mode 100644 index 0000000..1a731c8 --- /dev/null +++ b/CVE-2025-6069-quad-complex-HTMLParser.patch @@ -0,0 +1,190 @@ +From 9043edabc7e2f0dd655146e0a4571e2a0b2906af Mon Sep 17 00:00:00 2001 +From: Serhiy Storchaka +Date: Fri, 13 Jun 2025 19:57:48 +0300 +Subject: [PATCH] gh-135462: Fix quadratic complexity in processing special + input in HTMLParser (GH-135464) + +End-of-file errors are now handled according to the HTML5 specs -- +comments and declarations are automatically closed, tags are ignored. +(cherry picked from commit 6eb6c5dbfb528bd07d77b60fd71fd05d81d45c41) + +Co-authored-by: Serhiy Storchaka +--- + Lib/html/parser.py | 41 +++++--- + Lib/test/test_htmlparser.py | 51 +++++++--- + Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst | 4 + 3 files changed, 74 insertions(+), 22 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst + +Index: Python-3.11.13/Lib/html/parser.py +=================================================================== +--- Python-3.11.13.orig/Lib/html/parser.py 2025-07-02 18:12:07.084569398 +0200 ++++ Python-3.11.13/Lib/html/parser.py 2025-07-02 18:12:12.582519793 +0200 +@@ -25,6 +25,7 @@ + charref = re.compile('&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]') + + starttagopen = re.compile('<[a-zA-Z]') ++endtagopen = re.compile('') + commentclose = re.compile(r'--\s*>') + # Note: +@@ -176,7 +177,7 @@ + k = self.parse_pi(i) + elif startswith("', i + 1) +- if k < 0: +- k = rawdata.find('<', i + 1) +- if k < 0: +- k = i + 1 ++ if starttagopen.match(rawdata, i): # < + letter ++ pass ++ elif startswith("'), +- ('comment', '/img'), +- ('endtag', 'html<')]) ++ ('data', '\n')]) + + def test_starttag_junk_chars(self): ++ self._run_check("<", [('data', '<')]) ++ self._run_check("<>", [('data', '<>')]) ++ self._run_check("< >", [('data', '< >')]) ++ self._run_check("< ", [('data', '< ')]) + self._run_check("", []) ++ self._run_check("<$>", [('data', '<$>')]) + self._run_check("", [('comment', '$')]) + self._run_check("", [('endtag', 'a')]) ++ self._run_check("", [('starttag', 'a", [('endtag', 'a'", [('data', "'", []) ++ self._run_check("", [('starttag', 'a$b', [])]) + self._run_check("", [('startendtag', 'a$b', [])]) + self._run_check("", [('starttag', 'a$b', [])]) + self._run_check("", [('startendtag', 'a$b', [])]) ++ self._run_check("", [('endtag', 'a$b')]) + + def test_slashes_in_starttag(self): + self._run_check('', [('startendtag', 'a', [('foo', 'var')])]) +@@ -549,8 +557,9 @@ + ('comment', ' -- close enough --'), + ('comment', ''), + ('comment', '<-- this was an empty comment'), +- ('comment', '!! another bogus comment !!!'), ++ ('comment', '!! another bogus comment !!!') + ] ++ + self._run_check(html, expected) + + def test_broken_condcoms(self): +@@ -598,6 +607,26 @@ + ('endtag', 'a'), ('data', ' bar & baz')] + ) + ++ @support.requires_resource('cpu') ++ def test_eof_no_quadratic_complexity(self): ++ # Each of these examples used to take about an hour. ++ # Now they take a fraction of a second. ++ def check(source): ++ parser = html.parser.HTMLParser() ++ parser.feed(source) ++ parser.close() ++ n = 120_000 ++ check(" +Date: Mon, 28 Jul 2025 17:37:26 +0200 +Subject: [PATCH] gh-130577: tarfile now validates archives to ensure member + offsets are non-negative (GH-137027) (cherry picked from commit + 7040aa54f14676938970e10c5f74ea93cd56aa38) + +Co-authored-by: Alexander Urieles +Co-authored-by: Gregory P. Smith +--- + Lib/tarfile.py | 3 + Lib/test/test_tarfile.py | 156 ++++++++++ + Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst | 3 + 3 files changed, 162 insertions(+) + create mode 100644 Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst + +Index: Python-3.11.13/Lib/tarfile.py +=================================================================== +--- Python-3.11.13.orig/Lib/tarfile.py 2025-08-01 22:21:29.158050900 +0200 ++++ Python-3.11.13/Lib/tarfile.py 2025-08-01 22:21:33.121079687 +0200 +@@ -1613,6 +1613,9 @@ + """Round up a byte count by BLOCKSIZE and return it, + e.g. _block(834) => 1024. + """ ++ # Only non-negative offsets are allowed ++ if count < 0: ++ raise InvalidHeaderError("invalid offset") + blocks, remainder = divmod(count, BLOCKSIZE) + if remainder: + blocks += 1 +Index: Python-3.11.13/Lib/test/test_tarfile.py +=================================================================== +--- Python-3.11.13.orig/Lib/test/test_tarfile.py 2025-08-01 22:21:30.644301786 +0200 ++++ Python-3.11.13/Lib/test/test_tarfile.py 2025-08-01 22:21:33.121718600 +0200 +@@ -50,6 +50,7 @@ + xzname = os.path.join(TEMPDIR, "testtar.tar.xz") + tmpname = os.path.join(TEMPDIR, "tmp.tar") + dotlessname = os.path.join(TEMPDIR, "testtar") ++SPACE = b" " + + sha256_regtype = ( + "e09e4bc8b3c9d9177e77256353b36c159f5f040531bbd4b024a8f9b9196c71ce" +@@ -4386,6 +4387,161 @@ + ar.extractall(self.testdir, filter='fully_trusted') + + ++class OffsetValidationTests(unittest.TestCase): ++ tarname = tmpname ++ invalid_posix_header = ( ++ # name: 100 bytes ++ tarfile.NUL * tarfile.LENGTH_NAME ++ # mode, space, null terminator: 8 bytes ++ + b"000755" + SPACE + tarfile.NUL ++ # uid, space, null terminator: 8 bytes ++ + b"000001" + SPACE + tarfile.NUL ++ # gid, space, null terminator: 8 bytes ++ + b"000001" + SPACE + tarfile.NUL ++ # size, space: 12 bytes ++ + b"\xff" * 11 + SPACE ++ # mtime, space: 12 bytes ++ + tarfile.NUL * 11 + SPACE ++ # chksum: 8 bytes ++ + b"0011407" + tarfile.NUL ++ # type: 1 byte ++ + tarfile.REGTYPE ++ # linkname: 100 bytes ++ + tarfile.NUL * tarfile.LENGTH_LINK ++ # magic: 6 bytes, version: 2 bytes ++ + tarfile.POSIX_MAGIC ++ # uname: 32 bytes ++ + tarfile.NUL * 32 ++ # gname: 32 bytes ++ + tarfile.NUL * 32 ++ # devmajor, space, null terminator: 8 bytes ++ + tarfile.NUL * 6 + SPACE + tarfile.NUL ++ # devminor, space, null terminator: 8 bytes ++ + tarfile.NUL * 6 + SPACE + tarfile.NUL ++ # prefix: 155 bytes ++ + tarfile.NUL * tarfile.LENGTH_PREFIX ++ # padding: 12 bytes ++ + tarfile.NUL * 12 ++ ) ++ invalid_gnu_header = ( ++ # name: 100 bytes ++ tarfile.NUL * tarfile.LENGTH_NAME ++ # mode, null terminator: 8 bytes ++ + b"0000755" + tarfile.NUL ++ # uid, null terminator: 8 bytes ++ + b"0000001" + tarfile.NUL ++ # gid, space, null terminator: 8 bytes ++ + b"0000001" + tarfile.NUL ++ # size, space: 12 bytes ++ + b"\xff" * 11 + SPACE ++ # mtime, space: 12 bytes ++ + tarfile.NUL * 11 + SPACE ++ # chksum: 8 bytes ++ + b"0011327" + tarfile.NUL ++ # type: 1 byte ++ + tarfile.REGTYPE ++ # linkname: 100 bytes ++ + tarfile.NUL * tarfile.LENGTH_LINK ++ # magic: 8 bytes ++ + tarfile.GNU_MAGIC ++ # uname: 32 bytes ++ + tarfile.NUL * 32 ++ # gname: 32 bytes ++ + tarfile.NUL * 32 ++ # devmajor, null terminator: 8 bytes ++ + tarfile.NUL * 8 ++ # devminor, null terminator: 8 bytes ++ + tarfile.NUL * 8 ++ # padding: 167 bytes ++ + tarfile.NUL * 167 ++ ) ++ invalid_v7_header = ( ++ # name: 100 bytes ++ tarfile.NUL * tarfile.LENGTH_NAME ++ # mode, space, null terminator: 8 bytes ++ + b"000755" + SPACE + tarfile.NUL ++ # uid, space, null terminator: 8 bytes ++ + b"000001" + SPACE + tarfile.NUL ++ # gid, space, null terminator: 8 bytes ++ + b"000001" + SPACE + tarfile.NUL ++ # size, space: 12 bytes ++ + b"\xff" * 11 + SPACE ++ # mtime, space: 12 bytes ++ + tarfile.NUL * 11 + SPACE ++ # chksum: 8 bytes ++ + b"0010070" + tarfile.NUL ++ # type: 1 byte ++ + tarfile.REGTYPE ++ # linkname: 100 bytes ++ + tarfile.NUL * tarfile.LENGTH_LINK ++ # padding: 255 bytes ++ + tarfile.NUL * 255 ++ ) ++ valid_gnu_header = tarfile.TarInfo("filename").tobuf(tarfile.GNU_FORMAT) ++ data_block = b"\xff" * tarfile.BLOCKSIZE ++ ++ def _write_buffer(self, buffer): ++ with open(self.tarname, "wb") as f: ++ f.write(buffer) ++ ++ def _get_members(self, ignore_zeros=None): ++ with open(self.tarname, "rb") as f: ++ with tarfile.open( ++ mode="r", fileobj=f, ignore_zeros=ignore_zeros ++ ) as tar: ++ return tar.getmembers() ++ ++ def _assert_raises_read_error_exception(self): ++ with self.assertRaisesRegex( ++ tarfile.ReadError, "file could not be opened successfully" ++ ): ++ self._get_members() ++ ++ def test_invalid_offset_header_validations(self): ++ for tar_format, invalid_header in ( ++ ("posix", self.invalid_posix_header), ++ ("gnu", self.invalid_gnu_header), ++ ("v7", self.invalid_v7_header), ++ ): ++ with self.subTest(format=tar_format): ++ self._write_buffer(invalid_header) ++ self._assert_raises_read_error_exception() ++ ++ def test_early_stop_at_invalid_offset_header(self): ++ buffer = self.valid_gnu_header + self.invalid_gnu_header + self.valid_gnu_header ++ self._write_buffer(buffer) ++ members = self._get_members() ++ self.assertEqual(len(members), 1) ++ self.assertEqual(members[0].name, "filename") ++ self.assertEqual(members[0].offset, 0) ++ ++ def test_ignore_invalid_archive(self): ++ # 3 invalid headers with their respective data ++ buffer = (self.invalid_gnu_header + self.data_block) * 3 ++ self._write_buffer(buffer) ++ members = self._get_members(ignore_zeros=True) ++ self.assertEqual(len(members), 0) ++ ++ def test_ignore_invalid_offset_headers(self): ++ for first_block, second_block, expected_offset in ( ++ ( ++ (self.valid_gnu_header), ++ (self.invalid_gnu_header + self.data_block), ++ 0, ++ ), ++ ( ++ (self.invalid_gnu_header + self.data_block), ++ (self.valid_gnu_header), ++ 1024, ++ ), ++ ): ++ self._write_buffer(first_block + second_block) ++ members = self._get_members(ignore_zeros=True) ++ self.assertEqual(len(members), 1) ++ self.assertEqual(members[0].name, "filename") ++ self.assertEqual(members[0].offset, expected_offset) ++ ++ + def setUpModule(): + os_helper.unlink(TEMPDIR) + os.makedirs(TEMPDIR) +Index: Python-3.11.13/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ Python-3.11.13/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst 2025-08-01 22:21:33.122108946 +0200 +@@ -0,0 +1,3 @@ ++:mod:`tarfile` now validates archives to ensure member offsets are ++non-negative. (Contributed by Alexander Enrique Urieles Nieto in ++:gh:`130577`.) diff --git a/F00251-change-user-install-location.patch b/F00251-change-user-install-location.patch new file mode 100644 index 0000000..fa38a94 --- /dev/null +++ b/F00251-change-user-install-location.patch @@ -0,0 +1,215 @@ +From 910f38d9768d39d4d31426743ae4081ed1ab66b6 Mon Sep 17 00:00:00 2001 +From: Michal Cyprian +Date: Mon, 26 Jun 2017 16:32:56 +0200 +Subject: [PATCH] 00251: Change user install location + +Set values of prefix and exec_prefix in distutils install command +to /usr/local if executable is /usr/bin/python* and RPM build +is not detected to make pip and distutils install into separate location. + +Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe +--- + Lib/distutils/command/install.py | 15 +++++++++++++-- + Lib/site.py | 9 ++++++++- + 2 files changed, 21 insertions(+), 3 deletions(-) + +Index: Python-3.11.8/Lib/distutils/command/install.py +=================================================================== +--- Python-3.11.8.orig/Lib/distutils/command/install.py ++++ Python-3.11.8/Lib/distutils/command/install.py +@@ -441,8 +441,19 @@ class install(Command): + raise DistutilsOptionError( + "must not supply exec-prefix without prefix") + +- self.prefix = os.path.normpath(sys.prefix) +- self.exec_prefix = os.path.normpath(sys.exec_prefix) ++ # self.prefix is set to sys.prefix + /local/ ++ # if neither RPM build nor virtual environment is ++ # detected to make pip and distutils install packages ++ # into the separate location. ++ if (not (hasattr(sys, 'real_prefix') or ++ sys.prefix != sys.base_prefix) and ++ 'RPM_BUILD_ROOT' not in os.environ): ++ addition = "/local" ++ else: ++ addition = "" ++ ++ self.prefix = os.path.normpath(sys.prefix) + addition ++ self.exec_prefix = os.path.normpath(sys.exec_prefix) + addition + + else: + if self.exec_prefix is None: +Index: Python-3.11.8/Lib/site.py +=================================================================== +--- Python-3.11.8.orig/Lib/site.py ++++ Python-3.11.8/Lib/site.py +@@ -387,8 +387,15 @@ def getsitepackages(prefixes=None): + return sitepackages + + def addsitepackages(known_paths, prefixes=None): +- """Add site-packages to sys.path""" ++ """Add site-packages to sys.path ++ ++ '/usr/local' is included in PREFIXES if RPM build is not detected ++ to make packages installed into this location visible. ++ ++ """ + _trace("Processing global site-packages") ++ if ENABLE_USER_SITE and 'RPM_BUILD_ROOT' not in os.environ: ++ PREFIXES.insert(0, "/usr/local") + for sitedir in getsitepackages(prefixes): + if os.path.isdir(sitedir): + addsitedir(sitedir, known_paths) + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= +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 +Co-authored-by: Miro Hrončok +Co-authored-by: Michal Cyprian +Co-authored-by: Lumír Balhar +--- + Lib/site.py | 9 ++++++- + Lib/sysconfig.py | 49 +++++++++++++++++++++++++++++++++++++- + Lib/test/test_sysconfig.py | 17 +++++++++++-- + 3 files changed, 71 insertions(+), 4 deletions(-) + +Index: Python-3.11.9/Lib/sysconfig.py +=================================================================== +--- Python-3.11.9.orig/Lib/sysconfig.py ++++ Python-3.11.9/Lib/sysconfig.py +@@ -103,6 +103,11 @@ if os.name == 'nt': + 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'] ++ + + # NOTE: site.py has copy of this function. + # Sync it when modify this function. +@@ -162,6 +167,19 @@ if _HAS_USER_BASE: + }, + } + ++# 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') + +@@ -258,11 +276,40 @@ def _extend_dict(target_dict, other_dict + 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.11.9/Lib/test/test_sysconfig.py +=================================================================== +--- Python-3.11.9.orig/Lib/test/test_sysconfig.py ++++ Python-3.11.9/Lib/test/test_sysconfig.py +@@ -111,8 +111,19 @@ class TestSysConfig(unittest.TestCase): + 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), + ) + +@@ -345,7 +356,7 @@ class TestSysConfig(unittest.TestCase): + 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))) +@@ -357,6 +368,8 @@ class TestSysConfig(unittest.TestCase): + 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 diff --git a/PACKAGING-NOTES b/PACKAGING-NOTES new file mode 100644 index 0000000..e28c88c --- /dev/null +++ b/PACKAGING-NOTES @@ -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. diff --git a/Python-3.11.13.tar.xz b/Python-3.11.13.tar.xz new file mode 100644 index 0000000..80a2b4d --- /dev/null +++ b/Python-3.11.13.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8fb5f9fbc7609fa822cb31549884575db7fd9657cbffb89510b5d7975963a83a +size 20117496 diff --git a/Python-3.11.13.tar.xz.sigstore b/Python-3.11.13.tar.xz.sigstore new file mode 100644 index 0000000..a6d0be7 --- /dev/null +++ b/Python-3.11.13.tar.xz.sigstore @@ -0,0 +1 @@ +{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzjCCAlSgAwIBAgIUfnOGm4U1QCsCXWiDvPy5Tgni2HUwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNjAzMTkyNzM1WhcNMjUwNjAzMTkzNzM1WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpTsf/wrCdu4Domf4WOtO4CLkj51wmj4iesYv5N6DYhghPjqQFwGYI9gFc/WX6QMIWh5YHU2NGxrmM7KfbAYzz6OCAXMwggFvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUkQ2/O4Fivj1bTq7NTQczm1RdtYAwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wIgYDVR0RAQH/BBgwFoEUcGFibG9nc2FsQHB5dGhvbi5vcmcwKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGLBgorBgEEAdZ5AgQCBH0EewB5AHcA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGXN0NwGwAABAMASDBGAiEA6pD8PjS+5z2SQre/NS/wOdFSjVMsxvtfF6A1jg+1T3YCIQDC44S/Z3c0dNddM7EkE+A3j7Vft3hqRUoFkNe4U6g5qTAKBggqhkjOPQQDAwNoADBlAjA6lBI2r3KCZFc+2affpH3S3Xj3gMOKh8Lr5Z7TgkGp3Q6QsnExGmJJ0leXhqH6rQkCMQDfxk/6DyhbO7KTrIUfmrbZoa7dV75cresJS69Xk67XN57qsqY52DZj9o4fbUIw4ro="}, "tlogEntries": [{"logIndex": "228953871", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1748978856", "inclusionPromise": {"signedEntryTimestamp": "MEUCIQC9nXmfcRqyOL2Zmw1zI7+kulTbmDE3Yfzew81mXJGU4QIgF8Uhdg2uzttSA6erOuEchX68PCyJ0cVFHE0XJX2+ZfE="}, "inclusionProof": {"logIndex": "107049609", "rootHash": "Ilofw5POqC/C3zqfrdMQP1DyhNW+UfB9fHdjrbK6qaM=", "treeSize": "107049610", "hashes": ["AcD1iyjU7nuIPqAq29ynz7PEdq6zPXglj6e2tkH+/do=", "1BNDCN01B3dbUo/TfLaQgKIYTvPyrkcrHKd69GxuF2E=", "t59A0CV2pHM2S9AgZgcEA6FbXhgNZGo0jMRIXHiqsJ0=", "bCrkgWpJ8MBic+mIfCRsKi+5XAMqgM8Lc6G0LLfzZ7M=", "4iwdOrGkcqdN0qqZUx/gv8a8qpLMqVj8aXRVmhQ558c=", "mAX/zvx1jR0ujLtDApsQpHyxmoDGidClHMOn0BX1aQA=", "u5LKLBPTYgXZg0fBi6/8LuEeNy3EBAxJF0AkkB4Co6E=", "SPUVncwJRVX/n/RICCYqLpAzraqx7S0eMdXRr1RLRgg=", "uEJFtwcGQJMd9kjQhkXb7gl2WD3WMElCc15uDFvFGxs=", "VdOKzpQhJlpXgijzXANf/hNlje1G/N1kUuVnKNskkso=", "mta5fH/gFwxJ/0fT8yGpn3sFCY0G1RY555Iflm0LInM=", "7v8qPHNDLerpduaMx06eb/MwgoQwczTn/cYGKX/9wZ4="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n107049610\nIlofw5POqC/C3zqfrdMQP1DyhNW+UfB9fHdjrbK6qaM=\n\n\u2014 rekor.sigstore.dev wNI9ajBGAiEAjtzTnsnrGx0G3Dg99s89cPUh6EA+cxkicQ9j4qYU60wCIQCKcAL4kdakbq2JrBVgk7bRNf3FoJRrEI6SCjv16f7Crg==\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI4ZmI1ZjlmYmM3NjA5ZmE4MjJjYjMxNTQ5ODg0NTc1ZGI3ZmQ5NjU3Y2JmZmI4OTUxMGI1ZDc5NzU5NjNhODNhIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUM5Q1JZRjNSWGUzdDNxQlBJd2UrR3pMMTJCOXVLTjIrRFpWa2JjZW1FTS93SWdPMDFKaVhnbUJxZEN5RVhoM05JUEt5QlRBb2hpcjZHTkhZdXhiSUxKNDlRPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZha05EUVd4VFowRjNTVUpCWjBsVlptNVBSMjAwVlRGUlEzTkRXRmRwUkhaUWVUVlVaMjVwTWtoVmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZkMDVxUVhwTlZHdDVUbnBOTVZkb1kwNU5hbFYzVG1wQmVrMVVhM3BPZWsweFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZ3VkhObUwzZHlRMlIxTkVSdmJXWTBWMDkwVHpSRFRHdHFOVEYzYldvMGFXVnpXWFlLTlU0MlJGbG9aMmhRYW5GUlJuZEhXVWs1WjBaakwxZFlObEZOU1Zkb05WbElWVEpPUjNoeWJVMDNTMlppUVZsNmVqWlBRMEZZVFhkblowWjJUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZyVVRJdkNrODBSbWwyYWpGaVZIRTNUbFJSWTNwdE1WSmtkRmxCZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBsbldVUldVakJTUVZGSUwwSkNaM2RHYjBWVlkwZEdhV0pIT1c1ak1rWnpVVWhDTldSSGFIWmlhVFYyWTIxamQwdFJXVXRMZDFsQ1FrRkhSQXAyZWtGQ1FWRlJZbUZJVWpCalNFMDJUSGs1YUZreVRuWmtWelV3WTNrMWJtSXlPVzVpUjFWMVdUSTVkRTFEYzBkRGFYTkhRVkZSUW1jM09IZEJVV2RGQ2toUmQySmhTRkl3WTBoTk5reDVPV2haTWs1MlpGYzFNR041Tlc1aU1qbHVZa2RWZFZreU9YUk5TVWRNUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJTUVVS1pYZENOVUZJWTBFelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIxaE9NRTUzUjNkQlFRcENRVTFCVTBSQ1IwRnBSVUUyY0VRNFVHcFRLelY2TWxOUmNtVXZUbE12ZDA5a1JsTnFWazF6ZUhaMFprWTJRVEZxWnlzeFZETlpRMGxSUkVNME5GTXZDbG96WXpCa1RtUmtUVGRGYTBVclFUTnFOMVptZEROb2NWSlZiMFpyVG1VMFZUWm5OWEZVUVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV2UVVSQ2JFRnFRVFlLYkVKSk1uSXpTME5hUm1Nck1tRm1abkJJTTFNeldHb3paMDFQUzJnNFRISTFXamRVWjJ0SGNETlJObEZ6YmtWNFIyMUtTakJzWlZob2NVZzJjbEZyUXdwTlVVUm1lR3N2TmtSNWFHSlBOMHRVY2tsVlptMXlZbHB2WVRka1ZqYzFZM0psYzBwVE5qbFlhelkzV0U0MU4zRnpjVmsxTWtSYWFqbHZOR1ppVlVsM0NqUnliejBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "j7X5+8dgn6giyzFUmIRXXbf9llfL/7iVELXXl1ljqDo="}, "signature": "MEUCIQC9CRYF3RXe3t3qBPIwe+GzL12B9uKN2+DZVkbcemEM/wIgO01JiXgmBqdCyEXh3NIPKyBTAohir6GNHYuxbILJ49Q="}} diff --git a/Python-3.11.14.tar.xz b/Python-3.11.14.tar.xz new file mode 100644 index 0000000..d4542fc --- /dev/null +++ b/Python-3.11.14.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d3ed8ec5c88c1c95f5e558612a725450d2452813ddad5e58fdb1a53b1209b78 +size 20326860 diff --git a/Python-3.11.14.tar.xz.sigstore b/Python-3.11.14.tar.xz.sigstore new file mode 100644 index 0000000..6749507 --- /dev/null +++ b/Python-3.11.14.tar.xz.sigstore @@ -0,0 +1 @@ +{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzjCCAlSgAwIBAgIUa/Cqr03VT8ZG9vr8vnKbBg+smbAwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUxMDA5MTcwNjE1WhcNMjUxMDA5MTcxNjE1WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEV8hmCidc4iLoE7KY0EoSx+WzOVw+SRGe3TqZASn60wUXvIAGEngDUM2GJGZ2zciFho4j5aL3QiN9iXRluy1KgqOCAXMwggFvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUTkropBHt0kanFqilhuJTKPsup4EwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wIgYDVR0RAQH/BBgwFoEUcGFibG9nc2FsQHB5dGhvbi5vcmcwKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGLBgorBgEEAdZ5AgQCBH0EewB5AHcA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGZyfAIbAAABAMASDBGAiEA4/DdAlVJKgAy0hm3sqtUk8eDDPrlFeYNhPJLNI6CgnECIQCxS/bIAbLLdlzAcy6oNNNiUOdVCU7a1Wf0qL8inGhBzTAKBggqhkjOPQQDAwNoADBlAjEAqwMoQEolvvwMVety1mnyufr6P+YikV6nd1aZZnGQAlbvwgv/mac7l0DysGh40Gs6AjAZVV5V/fNk4RpyKJCRvWkYe9ciAu6QXHbj4dWXTsjxqkx42zgZ2SOEx4951KqOX/0="}, "tlogEntries": [{"logIndex": "597736248", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1760029575", "inclusionPromise": {"signedEntryTimestamp": "MEQCIGcnPF/TJIG89Te/QJ2plfcmZaFwWMS5gwUj/i4UD+lHAiA6U8MIzjmRCPkoV9GAiUhcS8Y+EfKoxjkhkuaRsZr+1A=="}, "inclusionProof": {"logIndex": "475831986", "rootHash": "2ivwpfqfDfFhP4xZsUzcUodxk2RqHL7UJtjrVnNC+aY=", "treeSize": "475831987", "hashes": ["EcNr6novO9JFYu0MhiZEkbLuFQ0Fu33e/EikpWhJfSc=", "JUI3wLXg1JVyXKG83MkLnF48cYp3AvZ5owiKHlrcNT0=", "2/6dc8665sZ7nRZxfMqTRpwkYyvJC3vhCTtENDZ/Xg0=", "N/EKp5CRZK9LCux3vDsddWopaheQu0XNoNsWQ0+QVp8=", "CY4WrDD4KG0hsBLDiG+NQtd+muyaPZ5U48/sqDhod7s=", "b8mEVvlpxhRNmn5Z2Sg5pTM4nTx+G0MIDaE/JGACftg=", "xVDKr3yUl/tQsbx7ocbC8nBJwKmRqVd7Hl4VohToH/Y=", "BQdEs/qH6M+bN2pXY4iylKeXMJIVCIts/G7pNbq0Pe4=", "qitr//U2XNNlKMCHm7tD8fHXneUmKumQFG9lYb3sxMk=", "7hzNnRc2wXwu0fNMVF1BVE2rgN+7YiNho0SMqXqadcc=", "qXhJobQjWl6SO/pue3trUW2uL4jXx24Ip7lpd4hc5bU=", "56ObhlROm9L8Q4JyN+mxEQ5pZD5QdobB1xZFIeL0lVg=", "EGaD/cNavzxGYLx1Gl0uNNWBZvyXlSHSdlIeH7m+63A=", "2Wv4GiithwNukRKV06clevnQQYCzXmSS/+/OJtXgsXQ=", "1mfy94KpcItqshH9+gwqV6jccupcaMpVsF28New8zDY=", "vS7O4ozHIQZJWBiov+mkpI27GE8zAmVCEkRcP3NDyNE="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n475831987\n2ivwpfqfDfFhP4xZsUzcUodxk2RqHL7UJtjrVnNC+aY=\n\n\u2014 rekor.sigstore.dev wNI9ajBFAiEAnD+Qljgsyi38h/qMtYdENwkJz0F/seAi4gExs1pm4bYCIFCTOElI5MtH4Lm61GXhPyTHiQ8T8TaLZnbx6D4I8G+H\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI4ZDNlZDhlYzVjODhjMWM5NWY1ZTU1ODYxMmE3MjU0NTBkMjQ1MjgxM2RkYWQ1ZTU4ZmRiMWE1M2IxMjA5Yjc4In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRUwvOHkrREM3QkpPaUVuUGM5R2F6VGN3MTZYc2xNMlNEU2dYVlEyTVl2REFpQVBrbk1GcjNRMVZoenRnR3VtVjVDUHFvb2JQTzVSUVIzYU9SanVvSXgyN1E9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZha05EUVd4VFowRjNTVUpCWjBsVllTOURjWEl3TTFaVU9GcEhPWFp5T0hadVMySkNaeXR6YldKQmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZlRTFFUVRWTlZHTjNUbXBGTVZkb1kwNU5hbFY0VFVSQk5VMVVZM2hPYWtVeFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZXT0dodFEybGtZelJwVEc5Rk4wdFpNRVZ2VTNnclYzcFBWbmNyVTFKSFpUTlVjVm9LUVZOdU5qQjNWVmgyU1VGSFJXNW5SRlZOTWtkS1Ixb3llbU5wUm1odk5HbzFZVXd6VVdsT09XbFlVbXgxZVRGTFozRlBRMEZZVFhkblowWjJUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZVYTNKdkNuQkNTSFF3YTJGdVJuRnBiR2gxU2xSTFVITjFjRFJGZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBsbldVUldVakJTUVZGSUwwSkNaM2RHYjBWVlkwZEdhV0pIT1c1ak1rWnpVVWhDTldSSGFIWmlhVFYyWTIxamQwdFJXVXRMZDFsQ1FrRkhSQXAyZWtGQ1FWRlJZbUZJVWpCalNFMDJUSGs1YUZreVRuWmtWelV3WTNrMWJtSXlPVzVpUjFWMVdUSTVkRTFEYzBkRGFYTkhRVkZSUW1jM09IZEJVV2RGQ2toUmQySmhTRkl3WTBoTk5reDVPV2haTWs1MlpGYzFNR041Tlc1aU1qbHVZa2RWZFZreU9YUk5TVWRNUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJTUVVS1pYZENOVUZJWTBFelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIxcDVaa0ZKWWtGQlFRcENRVTFCVTBSQ1IwRnBSVUUwTDBSa1FXeFdTa3RuUVhrd2FHMHpjM0YwVldzNFpVUkVVSEpzUm1WWlRtaFFTa3hPU1RaRFoyNUZRMGxSUTNoVEwySkpDa0ZpVEV4a2JIcEJZM2syYjA1T1RtbFZUMlJXUTFVM1lURlhaakJ4VERocGJrZG9RbnBVUVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV2UVVSQ2JFRnFSVUVLY1hkTmIxRkZiMngyZG5kTlZtVjBlVEZ0Ym5sMVpuSTJVQ3RaYVd0V05tNWtNV0ZhV201SFVVRnNZblozWjNZdmJXRmpOMnd3UkhselIyZzBNRWR6TmdwQmFrRmFWbFkxVmk5bVRtczBVbkI1UzBwRFVuWlhhMWxsT1dOcFFYVTJVVmhJWW1vMFpGZFlWSE5xZUhGcmVEUXllbWRhTWxOUFJYZzBPVFV4UzNGUENsZ3ZNRDBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "jT7Y7FyIwclfXlWGEqclRQ0kUoE92tXlj9saU7Egm3g="}, "signature": "MEQCIEL/8y+DC7BJOiEnPc9GazTcw16XslM2SDSgXVQ2MYvDAiAPknMFr3Q1VhztgGumV5CPqoobPO5RQR3aORjuoIx27Q=="}} diff --git a/README.SUSE b/README.SUSE new file mode 100644 index 0000000..0053bcf --- /dev/null +++ b/README.SUSE @@ -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. diff --git a/_multibuild b/_multibuild new file mode 100644 index 0000000..1d50bc4 --- /dev/null +++ b/_multibuild @@ -0,0 +1,4 @@ + + base + doc + diff --git a/add-loongarch64-support.patch b/add-loongarch64-support.patch new file mode 100644 index 0000000..10cc846 --- /dev/null +++ b/add-loongarch64-support.patch @@ -0,0 +1,29 @@ +Description: Add platform triplets for LoongArch. + +--- + configure.ac | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/configure.ac ++++ b/configure.ac +@@ -976,6 +976,20 @@ cat > conftest.c <=6) && defined(_MIPSEL) diff --git a/baselibs.conf b/baselibs.conf new file mode 100644 index 0000000..1793de8 --- /dev/null +++ b/baselibs.conf @@ -0,0 +1,3 @@ +python311-base +python311 +libpython3_11-1_0 diff --git a/bluez-devel-vendor.tar.xz b/bluez-devel-vendor.tar.xz new file mode 100644 index 0000000..57fb3e5 --- /dev/null +++ b/bluez-devel-vendor.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:868fbfba2ddaed62f2c45cf869fe2c648527ac3bac738f4f41f3c2872f5b0211 +size 25040 diff --git a/bpo-31046_ensurepip_honours_prefix.patch b/bpo-31046_ensurepip_honours_prefix.patch new file mode 100644 index 0000000..86882ae --- /dev/null +++ b/bpo-31046_ensurepip_honours_prefix.patch @@ -0,0 +1,173 @@ +From 5754521af1d51aa8e445cba07a093bbc0c88596d Mon Sep 17 00:00:00 2001 +From: Zackery Spytz +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 +--- + Doc/library/ensurepip.rst | 9 +++-- + 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, 34 insertions(+), 9 deletions(-) + create mode 100644 Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst + +Index: Python-3.11.8/Doc/library/ensurepip.rst +=================================================================== +--- Python-3.11.8.orig/Doc/library/ensurepip.rst ++++ Python-3.11.8/Doc/library/ensurepip.rst +@@ -59,7 +59,9 @@ 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: ++ ++* ``--prefix ``: Installs ``pip`` using the given directory prefix. + + * :samp:`--root {dir}`: Installs ``pip`` relative to the given root directory + rather than the root of the currently active virtual environment (if any) +@@ -92,7 +94,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) + +@@ -102,6 +104,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. + +@@ -122,6 +126,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:: +Index: Python-3.11.8/Lib/ensurepip/__init__.py +=================================================================== +--- Python-3.11.8.orig/Lib/ensurepip/__init__.py ++++ Python-3.11.8/Lib/ensurepip/__init__.py +@@ -122,27 +122,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. + """ +@@ -192,6 +192,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: +@@ -267,6 +269,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, +@@ -285,6 +292,7 @@ def _main(argv=None): + + return _bootstrap( + root=args.root, ++ prefix=args.prefix, + upgrade=args.upgrade, + user=args.user, + verbosity=args.verbosity, +Index: Python-3.11.8/Lib/test/test_ensurepip.py +=================================================================== +--- Python-3.11.8.orig/Lib/test/test_ensurepip.py ++++ Python-3.11.8/Lib/test/test_ensurepip.py +@@ -112,6 +112,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/", ++ "setuptools", "pip", ++ ], ++ unittest.mock.ANY, ++ ) ++ + def test_bootstrapping_with_user(self): + ensurepip.bootstrap(user=True) + +Index: Python-3.11.8/Makefile.pre.in +=================================================================== +--- Python-3.11.8.orig/Makefile.pre.in ++++ Python-3.11.8/Makefile.pre.in +@@ -1761,7 +1761,7 @@ install: @FRAMEWORKINSTALLFIRST@ commoni + install|*) ensurepip="" ;; \ + esac; \ + $(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \ +- $$ensurepip --root=$(DESTDIR)/ ; \ ++ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \ + fi + + altinstall: commoninstall +@@ -1771,7 +1771,7 @@ altinstall: commoninstall + install|*) ensurepip="--altinstall" ;; \ + esac; \ + $(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \ +- $$ensurepip --root=$(DESTDIR)/ ; \ ++ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \ + fi + + commoninstall: check-clean-src @FRAMEWORKALTINSTALLFIRST@ \ +Index: Python-3.11.8/Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst +=================================================================== +--- /dev/null ++++ Python-3.11.8/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`. diff --git a/bsc1221260-test_asyncio-ResourceWarning.patch b/bsc1221260-test_asyncio-ResourceWarning.patch new file mode 100644 index 0000000..15d6b8d --- /dev/null +++ b/bsc1221260-test_asyncio-ResourceWarning.patch @@ -0,0 +1,21 @@ +From a3052035485bd2836e40f5284657ca105382cbfd Mon Sep 17 00:00:00 2001 +From: sobolevn +Date: Tue, 5 Mar 2024 20:24:16 +0300 +Subject: [PATCH] gh-116112: Fix `ResourceWarning` in + `test_asyncio.test_stream` + +Co-authored-by: @CendioOssman +--- + Lib/test/test_asyncio/test_streams.py | 1 + + 1 file changed, 1 insertion(+) + +--- a/Lib/test/test_asyncio/test_streams.py ++++ b/Lib/test/test_asyncio/test_streams.py +@@ -1156,6 +1156,7 @@ os.close(fd) + + def test_unhandled_cancel(self): + async def handle_echo(reader, writer): ++ writer.close() + asyncio.current_task().cancel() + messages = self._basetest_unhandled_exceptions(handle_echo) + self.assertEqual(messages, []) diff --git a/bso1227999-reproducible-builds.patch b/bso1227999-reproducible-builds.patch new file mode 100644 index 0000000..fb33d18 --- /dev/null +++ b/bso1227999-reproducible-builds.patch @@ -0,0 +1,37 @@ +From ac2b8869724d7a57d9b5efbdce2f20423214e8bb Mon Sep 17 00:00:00 2001 +From: "Bernhard M. Wiedemann" +Date: Tue, 16 Jul 2024 21:39:33 +0200 +Subject: [PATCH] Allow to override build date with SOURCE_DATE_EPOCH + +to make builds reproducible. +See https://reproducible-builds.org/ for why this is good +and https://reproducible-builds.org/specs/source-date-epoch/ +for the definition of this variable. +--- + Doc/conf.py | 3 ++- + Doc/library/functions.rst | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- a/Doc/conf.py ++++ b/Doc/conf.py +@@ -316,7 +316,8 @@ html_context = { + } + + # This 'Last updated on:' timestamp is inserted at the bottom of every page. +-html_last_updated_fmt = time.strftime('%b %d, %Y (%H:%M UTC)', time.gmtime()) ++html_time = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) ++html_last_updated_fmt = time.strftime('%b %d, %Y (%H:%M UTC)', time.gmtime(html_time)) + + # Path to find HTML templates. + templates_path = ['tools/templates'] +--- a/Doc/library/functions.rst ++++ b/Doc/library/functions.rst +@@ -1356,7 +1356,7 @@ are always available. They are listed h + (where :func:`open` is declared), :mod:`os`, :mod:`os.path`, :mod:`tempfile`, + and :mod:`shutil`. + +- .. audit-event:: open file,mode,flags open ++ .. audit-event:: open path,mode,flags open + + The ``mode`` and ``flags`` arguments may have been modified or inferred from + the original call. diff --git a/distutils-reproducible-compile.patch b/distutils-reproducible-compile.patch new file mode 100644 index 0000000..17e8bd2 --- /dev/null +++ b/distutils-reproducible-compile.patch @@ -0,0 +1,17 @@ +--- + Lib/distutils/util.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: Python-3.11.8/Lib/distutils/util.py +=================================================================== +--- Python-3.11.8.orig/Lib/distutils/util.py ++++ Python-3.11.8/Lib/distutils/util.py +@@ -436,7 +436,7 @@ byte_compile(files, optimize=%r, force=% + else: + from py_compile import compile + +- for file in py_files: ++ for file in sorted(py_files): + if file[-3:] != ".py": + # This lets us be lazy and not filter filenames in + # the "install_lib" command. diff --git a/externally_managed.in b/externally_managed.in new file mode 100644 index 0000000..54606b6 --- /dev/null +++ b/externally_managed.in @@ -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` . diff --git a/fix_configure_rst.patch b/fix_configure_rst.patch new file mode 100644 index 0000000..a5fe82c --- /dev/null +++ b/fix_configure_rst.patch @@ -0,0 +1,40 @@ +--- + Doc/using/configure.rst | 3 --- + Misc/NEWS | 2 +- + 2 files changed, 1 insertion(+), 4 deletions(-) + +--- a/Doc/using/configure.rst ++++ b/Doc/using/configure.rst +@@ -43,7 +43,6 @@ General Options + + See :data:`sys.int_info.bits_per_digit `. + +-.. option:: --with-cxx-main + .. option:: --with-cxx-main=COMPILER + + Compile the Python ``main()`` function and link Python executable with C++ +@@ -529,13 +528,11 @@ macOS Options + + See ``Mac/README.rst``. + +-.. option:: --enable-universalsdk + .. option:: --enable-universalsdk=SDKDIR + + Create a universal binary build. *SDKDIR* specifies which macOS SDK should + be used to perform the build (default is no). + +-.. option:: --enable-framework + .. option:: --enable-framework=INSTALLDIR + + Create a Python.framework rather than a traditional Unix install. Optional +--- a/Misc/NEWS ++++ b/Misc/NEWS +@@ -9911,7 +9911,7 @@ C API + - bpo-40939: Removed documentation for the removed ``PyParser_*`` C API. + + - bpo-43795: The list in :ref:`limited-api-list` now shows the public name +- :c:struct:`PyFrameObject` rather than ``_frame``. The non-existing entry ++ :c:type:`PyFrameObject` rather than ``_frame``. The non-existing entry + ``_node`` no longer appears in the list. + + - bpo-44378: :c:func:`Py_IS_TYPE` no longer uses :c:func:`Py_TYPE` to avoid diff --git a/gh120226-fix-sendfile-test-kernel-610.patch b/gh120226-fix-sendfile-test-kernel-610.patch new file mode 100644 index 0000000..2eb6f63 --- /dev/null +++ b/gh120226-fix-sendfile-test-kernel-610.patch @@ -0,0 +1,35 @@ +From 1b3f6523a5c83323cdc44031b33a1c062e5dc698 Mon Sep 17 00:00:00 2001 +From: Xi Ruoyao +Date: Fri, 7 Jun 2024 23:51:32 +0800 +Subject: [PATCH] gh-120226: Fix + test_sendfile_close_peer_in_the_middle_of_receiving on Linux >= 6.10 + (GH-120227) + +The worst case is that the kernel buffers 17 pages with a page size of 64k. +(cherry picked from commit a7584245661102a5768c643fbd7db8395fd3c90e) + +Co-authored-by: Xi Ruoyao +--- + Lib/test/test_asyncio/test_sendfile.py | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/Lib/test/test_asyncio/test_sendfile.py ++++ b/Lib/test/test_asyncio/test_sendfile.py +@@ -93,13 +93,10 @@ class MyProto(asyncio.Protocol): + + class SendfileBase: + +- # 256 KiB plus small unaligned to buffer chunk +- # Newer versions of Windows seems to have increased its internal +- # buffer and tries to send as much of the data as it can as it +- # has some form of buffering for this which is less than 256KiB +- # on newer server versions and Windows 11. +- # So DATA should be larger than 256 KiB to make this test reliable. +- DATA = b"x" * (1024 * 256 + 1) ++ # Linux >= 6.10 seems buffering up to 17 pages of data. ++ # So DATA should be large enough to make this test reliable even with a ++ # 64 KiB page configuration. ++ DATA = b"x" * (1024 * 17 * 64 + 1) + # Reduce socket buffer size to test on relative small data sets. + BUF_SIZE = 4 * 1024 # 4 KiB + diff --git a/gh139257-Support-docutils-0.22.patch b/gh139257-Support-docutils-0.22.patch new file mode 100644 index 0000000..a4835e3 --- /dev/null +++ b/gh139257-Support-docutils-0.22.patch @@ -0,0 +1,36 @@ +From 19b61747df3d62c822285c488753d6fbdf91e3ac Mon Sep 17 00:00:00 2001 +From: Daniel Garcia Moreno +Date: Tue, 23 Sep 2025 10:20:16 +0200 +Subject: [PATCH 1/2] gh-139257: Support docutils >= 0.22 + +--- + Doc/tools/extensions/pyspecific.py | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +Index: Python-3.11.13/Doc/tools/extensions/pyspecific.py +=================================================================== +--- Python-3.11.13.orig/Doc/tools/extensions/pyspecific.py 2025-06-03 20:38:25.000000000 +0200 ++++ Python-3.11.13/Doc/tools/extensions/pyspecific.py 2025-09-30 18:20:10.096471679 +0200 +@@ -48,11 +48,21 @@ + SOURCE_URI = 'https://github.com/python/cpython/tree/3.11/%s' + + # monkey-patch reST parser to disable alphabetic and roman enumerated lists ++def _disable_alphabetic_and_roman(text): ++ try: ++ # docutils >= 0.22 ++ from docutils.parsers.rst.states import InvalidRomanNumeralError ++ raise InvalidRomanNumeralError(text) ++ except ImportError: ++ # docutils < 0.22 ++ return None ++ ++ + from docutils.parsers.rst.states import Body + Body.enum.converters['loweralpha'] = \ + Body.enum.converters['upperalpha'] = \ + Body.enum.converters['lowerroman'] = \ +- Body.enum.converters['upperroman'] = lambda x: None ++ Body.enum.converters['upperroman'] = _disable_alphabetic_and_roman + + # monkey-patch the productionlist directive to allow hyphens in group names + # https://github.com/sphinx-doc/sphinx/issues/11854 diff --git a/idle3.appdata.xml b/idle3.appdata.xml new file mode 100644 index 0000000..b494f1e --- /dev/null +++ b/idle3.appdata.xml @@ -0,0 +1,51 @@ + + + + org.python.IDLE3 + idle3.desktop + + IDLE3 + Python 3 Integrated Development and Learning Environment + + +

+ IDLE is Python’s Integrated Development and Learning Environment. + The GUI is uniform between Windows, Unix, and macOS. + IDLE provides an easy way to start writing, running, and debugging + Python code. +

+

+ IDLE is written in pure Python, and uses the tkinter GUI toolkit. + It provides: +

+
    +
  • a Python shell window (interactive interpreter) with colorizing of code input, output, and error messages,
  • +
  • a multi-window text editor with multiple undo, Python colorizing, smart indent, call tips, auto completion, and other features,
  • +
  • search within any window, replace within editor windows, and search through multiple files (grep),
  • +
  • a debugger with persistent breakpoints, stepping, and viewing of global and local namespaces.
  • +
+
+ + + Python Software Foundation + + + https://docs.python.org/3/library/idle.html + + + + https://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-main-window.png + + + https://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-class-browser.png + + + https://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-code-viewer.png + + + + Python-2.0 + CC0-1.0 + zbyszek@in.waw.pl +
+ diff --git a/idle3.desktop b/idle3.desktop new file mode 100644 index 0000000..43f5a4c --- /dev/null +++ b/idle3.desktop @@ -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; diff --git a/import_failed.map b/import_failed.map new file mode 100644 index 0000000..f33690c --- /dev/null +++ b/import_failed.map @@ -0,0 +1,7 @@ +python311-curses: curses _curses _curses_panel +python311-dbm: dbm _dbm _gdbm +python311-idle: idlelib +python311-testsuite: test _ctypes_test _testbuffer _testcapi _testinternalcapi _testimportmultiple _testmultiphase xxlimited +python311-tk: tkinter _tkinter +python311-tools: turtledemo +python311: sqlite3 readline _sqlite3 nis diff --git a/import_failed.py b/import_failed.py new file mode 100644 index 0000000..258b5a5 --- /dev/null +++ b/import_failed.py @@ -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.""") diff --git a/macros.python3 b/macros.python3 new file mode 100644 index 0000000..2bd193b --- /dev/null +++ b/macros.python3 @@ -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\ +} + + diff --git a/no-skipif-doctests.patch b/no-skipif-doctests.patch new file mode 100644 index 0000000..7e412d7 --- /dev/null +++ b/no-skipif-doctests.patch @@ -0,0 +1,653 @@ +only in patch2: +unchanged: +--- + Doc/library/turtle.rst | 82 ------------------------------------------------- + 1 file changed, 82 deletions(-) + +--- a/Doc/library/turtle.rst ++++ b/Doc/library/turtle.rst +@@ -440,7 +440,6 @@ Turtle motion + turtle is headed. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.position() + (0.00,0.00) +@@ -467,7 +466,6 @@ Turtle motion + >>> turtle.goto(0, 0) + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.position() + (0.00,0.00) +@@ -486,13 +484,11 @@ Turtle motion + orientation depends on the turtle mode, see :func:`mode`. + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.setheading(22) + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.heading() + 22.0 +@@ -511,13 +507,11 @@ Turtle motion + orientation depends on the turtle mode, see :func:`mode`. + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.setheading(22) + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.heading() + 22.0 +@@ -540,13 +534,11 @@ Turtle motion + not change the turtle's orientation. + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.goto(0, 0) + + .. doctest:: +- :skipif: _tkinter is None + + >>> tp = turtle.pos() + >>> tp +@@ -570,13 +562,11 @@ Turtle motion + unchanged. + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.goto(0, 240) + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.position() + (0.00,240.00) +@@ -592,13 +582,11 @@ Turtle motion + Set the turtle's second coordinate to *y*, leave first coordinate unchanged. + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.goto(0, 40) + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.position() + (0.00,40.00) +@@ -625,7 +613,6 @@ Turtle motion + =================== ==================== + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.setheading(90) + >>> turtle.heading() +@@ -638,14 +625,12 @@ Turtle motion + its start-orientation (which depends on the mode, see :func:`mode`). + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.setheading(90) + >>> turtle.goto(0, -10) + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.heading() + 90.0 +@@ -677,7 +662,6 @@ Turtle motion + calculated automatically. May be used to draw regular polygons. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.position() +@@ -706,7 +690,6 @@ Turtle motion + + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.dot() +@@ -724,7 +707,6 @@ Turtle motion + it by calling ``clearstamp(stamp_id)``. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.color("blue") + >>> turtle.stamp() +@@ -740,7 +722,6 @@ Turtle motion + Delete stamp with given *stampid*. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.position() + (150.00,-0.00) +@@ -785,7 +766,6 @@ Turtle motion + undo actions is determined by the size of the undobuffer. + + .. doctest:: +- :skipif: _tkinter is None + + >>> for i in range(4): + ... turtle.fd(50); turtle.lt(80) +@@ -818,7 +798,6 @@ Turtle motion + turtle turn instantly. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.speed() + 3 +@@ -839,7 +818,6 @@ Tell Turtle's state + Return the turtle's current location (x,y) (as a :class:`Vec2D` vector). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.pos() + (440.00,-0.00) +@@ -855,7 +833,6 @@ Tell Turtle's state + orientation which depends on the mode - "standard"/"world" or "logo". + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.goto(10, 10) + >>> turtle.towards(0,0) +@@ -867,7 +844,6 @@ Tell Turtle's state + Return the turtle's x coordinate. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(50) +@@ -883,7 +859,6 @@ Tell Turtle's state + Return the turtle's y coordinate. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(60) +@@ -900,7 +875,6 @@ Tell Turtle's state + :func:`mode`). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(67) +@@ -917,7 +891,6 @@ Tell Turtle's state + other turtle, in turtle step units. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.distance(30,40) +@@ -941,7 +914,6 @@ Settings for measurement + Default value is 360 degrees. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(90) +@@ -964,7 +936,6 @@ Settings for measurement + ``degrees(2*math.pi)``. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(90) +@@ -975,7 +946,6 @@ Settings for measurement + 1.5707963267948966 + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.degrees(360) +@@ -1011,7 +981,6 @@ Drawing state + thickness. If no argument is given, the current pensize is returned. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.pensize() + 1 +@@ -1043,7 +1012,6 @@ Drawing state + attributes in one statement. + + .. doctest:: +- :skipif: _tkinter is None + :options: +NORMALIZE_WHITESPACE + + >>> turtle.pen(fillcolor="black", pencolor="red", pensize=10) +@@ -1066,7 +1034,6 @@ Drawing state + Return ``True`` if pen is down, ``False`` if it's up. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.penup() + >>> turtle.isdown() +@@ -1107,7 +1074,6 @@ Color control + newly set pencolor. + + .. doctest:: +- :skipif: _tkinter is None + + >>> colormode() + 1.0 +@@ -1156,7 +1122,6 @@ Color control + with the newly set fillcolor. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.fillcolor("violet") + >>> turtle.fillcolor() +@@ -1195,7 +1160,6 @@ Color control + with the newly set colors. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.color("red", "green") + >>> turtle.color() +@@ -1212,7 +1176,6 @@ Filling + ~~~~~~~ + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.home() +@@ -1222,7 +1185,6 @@ Filling + Return fillstate (``True`` if filling, ``False`` else). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.begin_fill() + >>> if turtle.filling(): +@@ -1247,7 +1209,6 @@ Filling + above may be either all yellow or have some white regions. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.color("black", "red") + >>> turtle.begin_fill() +@@ -1264,7 +1225,6 @@ More drawing control + variables to the default values. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.goto(0,-22) + >>> turtle.left(100) +@@ -1315,7 +1275,6 @@ Visibility + drawing observably. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.hideturtle() + +@@ -1326,7 +1285,6 @@ Visibility + Make the turtle visible. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.showturtle() + +@@ -1357,7 +1315,6 @@ Appearance + deal with shapes see Screen method :func:`register_shape`. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.shape() + 'classic' +@@ -1383,7 +1340,6 @@ Appearance + ``resizemode("user")`` is called by :func:`shapesize` when used with arguments. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.resizemode() + 'noresize' +@@ -1407,7 +1363,6 @@ Appearance + of the shape's outline. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.shapesize() + (1.0, 1.0, 1) +@@ -1432,7 +1387,6 @@ Appearance + heading of the turtle are sheared. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.shape("circle") + >>> turtle.shapesize(5,2) +@@ -1449,7 +1403,6 @@ Appearance + change the turtle's heading (direction of movement). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.reset() + >>> turtle.shape("circle") +@@ -1469,7 +1422,6 @@ Appearance + (direction of movement). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.reset() + >>> turtle.shape("circle") +@@ -1495,7 +1447,6 @@ Appearance + turtle (its direction of movement). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.reset() + >>> turtle.shape("circle") +@@ -1524,7 +1475,6 @@ Appearance + given matrix. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle = Turtle() + >>> turtle.shape("square") +@@ -1540,7 +1490,6 @@ Appearance + can be used to define a new shape or components of a compound shape. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.shape("square") + >>> turtle.shapetransform(4, -1, 0, 2) +@@ -1565,7 +1514,6 @@ Using events + procedural way: + + .. doctest:: +- :skipif: _tkinter is None + + >>> def turn(x, y): + ... left(180) +@@ -1586,7 +1534,6 @@ Using events + ``None``, existing bindings are removed. + + .. doctest:: +- :skipif: _tkinter is None + + >>> class MyTurtle(Turtle): + ... def glow(self,x,y): +@@ -1614,7 +1561,6 @@ Using events + mouse-click event on that turtle. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.ondrag(turtle.goto) + +@@ -1642,7 +1588,6 @@ Special Turtle methods + Return the last recorded polygon. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.begin_poly() +@@ -1662,7 +1607,6 @@ Special Turtle methods + turtle properties. + + .. doctest:: +- :skipif: _tkinter is None + + >>> mick = Turtle() + >>> joe = mick.clone() +@@ -1675,7 +1619,6 @@ Special Turtle methods + return the "anonymous turtle": + + .. doctest:: +- :skipif: _tkinter is None + + >>> pet = getturtle() + >>> pet.fd(50) +@@ -1689,7 +1632,6 @@ Special Turtle methods + TurtleScreen methods can then be called for that object. + + .. doctest:: +- :skipif: _tkinter is None + + >>> ts = turtle.getscreen() + >>> ts +@@ -1707,7 +1649,6 @@ Special Turtle methods + ``None``, the undobuffer is disabled. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.setundobuffer(42) + +@@ -1717,7 +1658,6 @@ Special Turtle methods + Return number of entries in the undobuffer. + + .. doctest:: +- :skipif: _tkinter is None + + >>> while undobufferentries(): + ... undo() +@@ -1740,7 +1680,6 @@ below: + For example: + + .. doctest:: +- :skipif: _tkinter is None + + >>> s = Shape("compound") + >>> poly1 = ((0,0),(10,-5),(0,10),(-10,-5)) +@@ -1751,7 +1690,6 @@ below: + 3. Now add the Shape to the Screen's shapelist and use it: + + .. doctest:: +- :skipif: _tkinter is None + + >>> register_shape("myshape", s) + >>> shape("myshape") +@@ -1771,7 +1709,6 @@ Most of the examples in this section ref + ``screen``. + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> screen = Screen() +@@ -1788,7 +1725,6 @@ Window control + Set or return background color of the TurtleScreen. + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.bgcolor("orange") + >>> screen.bgcolor() +@@ -1880,7 +1816,6 @@ Window control + distorted. + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.reset() + >>> screen.setworldcoordinates(-50,-7.5,50,7.5) +@@ -1891,7 +1826,6 @@ Window control + ... left(45); fd(2) # a regular octagon + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> screen.reset() +@@ -1913,7 +1847,6 @@ Animation control + Optional argument: + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.delay() + 10 +@@ -1935,7 +1868,6 @@ Animation control + :func:`delay`). + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.tracer(8, 25) + >>> dist = 2 +@@ -1972,7 +1904,6 @@ Using screen events + must have the focus. (See method :func:`listen`.) + + .. doctest:: +- :skipif: _tkinter is None + + >>> def f(): + ... fd(50) +@@ -1993,7 +1924,6 @@ Using screen events + must have focus. (See method :func:`listen`.) + + .. doctest:: +- :skipif: _tkinter is None + + >>> def f(): + ... fd(50) +@@ -2018,7 +1948,6 @@ Using screen events + named ``turtle``: + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.onclick(turtle.goto) # Subsequently clicking into the TurtleScreen will + >>> # make the turtle move to the clicked point. +@@ -2038,7 +1967,6 @@ Using screen events + Install a timer that calls *fun* after *t* milliseconds. + + .. doctest:: +- :skipif: _tkinter is None + + >>> running = True + >>> def f(): +@@ -2120,7 +2048,6 @@ Settings and special methods + ============ ========================= =================== + + .. doctest:: +- :skipif: _tkinter is None + + >>> mode("logo") # resets turtle heading to north + >>> mode() +@@ -2135,7 +2062,6 @@ Settings and special methods + values of color triples have to be in the range 0..*cmode*. + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.colormode(1) + >>> turtle.pencolor(240, 160, 80) +@@ -2156,7 +2082,6 @@ Settings and special methods + do with a Tkinter Canvas. + + .. doctest:: +- :skipif: _tkinter is None + + >>> cv = screen.getcanvas() + >>> cv +@@ -2168,7 +2093,6 @@ Settings and special methods + Return a list of names of all currently available turtle shapes. + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.getshapes() + ['arrow', 'blank', 'circle', ..., 'turtle'] +@@ -2192,7 +2116,6 @@ Settings and special methods + coordinates: Install the corresponding polygon shape. + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.register_shape("triangle", ((5,-3), (0,5), (-5,-3))) + +@@ -2208,7 +2131,6 @@ Settings and special methods + Return the list of turtles on the screen. + + .. doctest:: +- :skipif: _tkinter is None + + >>> for turtle in screen.turtles(): + ... turtle.color("red") +@@ -2270,7 +2192,6 @@ Methods specific to Screen, not inherite + center window vertically + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.setup (width=200, height=200, startx=0, starty=0) + >>> # sets window to 200x200 pixels, in upper left of screen +@@ -2286,7 +2207,6 @@ Methods specific to Screen, not inherite + Set title of turtle window to *titlestring*. + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.title("Welcome to the turtle zoo!") + +@@ -2357,7 +2277,6 @@ Public classes + Example: + + .. doctest:: +- :skipif: _tkinter is None + + >>> poly = ((0,0),(10,-5),(0,10),(-10,-5)) + >>> s = Shape("compound") +@@ -2743,7 +2662,6 @@ Changes since Python 3.0 + + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> for turtle in turtles(): diff --git a/pre_checkin.sh b/pre_checkin.sh new file mode 100644 index 0000000..a2cf992 --- /dev/null +++ b/pre_checkin.sh @@ -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 + diff --git a/python-3.3.0b1-fix_date_time_compiler.patch b/python-3.3.0b1-fix_date_time_compiler.patch new file mode 100644 index 0000000..cda20d7 --- /dev/null +++ b/python-3.3.0b1-fix_date_time_compiler.patch @@ -0,0 +1,27 @@ +--- + Makefile.pre.in | 7 +++++++ + 1 file changed, 7 insertions(+) + +Index: Python-3.11.8/Makefile.pre.in +=================================================================== +--- Python-3.11.8.orig/Makefile.pre.in ++++ Python-3.11.8/Makefile.pre.in +@@ -1240,11 +1240,18 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \ + $(DTRACE_OBJS) \ + $(srcdir)/Modules/getbuildinfo.c + $(CC) -c $(PY_CORE_CFLAGS) \ ++ -DDATE="\"`date -u -r Makefile.pre.in +"%b %d %Y"`\"" \ ++ -DTIME="\"`date -u -r Makefile.pre.in +"%T"`\"" \ + -DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \ + -DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \ + -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='"$(prefix)"' \ diff --git a/python-3.3.0b1-localpath.patch b/python-3.3.0b1-localpath.patch new file mode 100644 index 0000000..475497e --- /dev/null +++ b/python-3.3.0b1-localpath.patch @@ -0,0 +1,13 @@ +Index: Python-3.11.8/Lib/site.py +=================================================================== +--- Python-3.11.8.orig/Lib/site.py ++++ Python-3.11.8/Lib/site.py +@@ -77,7 +77,7 @@ import io + import stat + + # 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 diff --git a/python.keyring b/python.keyring new file mode 100644 index 0000000..747bc27 --- /dev/null +++ b/python.keyring @@ -0,0 +1,109 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFq+ToQBEADRYvIVtbK6owynD3j3nxwpW2KEk/p+aDvtXmc2SR2dBcZ8sFW2 +R5vEsG8d3/D3wgv5pcL3KfNNXQYUnXVbobrFUUWQYc79qIsE3MgiPf5NVOtwKPUR +i5g9YJgKvpBxkQfqp3LYGm9ZBtwo3DVLA3yn7KsazCmAgTNFJYw7ku1XxgmIzY6K +5J30DfbJiqDqj4f9GslCCCCH3qiPnuLG/HUyVLHMpbWlaiy9NI0GcaLxjJewHj9w +W2D2lydkxe5JGo7egUkV3ILcuLVSVKA35SKY27dYqfuyqp9tAzaRbjDYjsYdHA6G +BqrNrKBn/GwlFDPrVdcvN3ZSY2wMLTxWE3Axc/FweuHxFnou/80FwX7F3JD+oEQ6 +rofmcxOBCC7J98I7HZAhP9jBn88XIS2hztbLq8d6rZJZRtcz0k61VR0ddO+TrFmf +9rMYCPgCckRtVxeFIVIabrN1IzKynLFeo040h8hSGswd6YKDOVwjJY6Oa6EmVefZ +a8QSt4+M65RSzH6SEPY008F3nJUAK6MEkzTak+tFltZNrVWu8p2xd1j9nmxAwEhZ +/lgbxLqzYgaUWmfyHeZ8yVA0MhHzdiAL8nVUEdG3KecIq0RWCJLGLWWIjd6KAJl1 +yAmhRYKK/sjPDsL3elHsFACfZbyx3o5GGQNlas1FYoPLWbaNGaJtgFTF2QARAQAB +tCtQYWJsbyBHYWxpbmRvIFNhbGdhZG8gPHBhYmxvZ3NhbEBnbWFpbC5jb20+iQJO +BBMBCgA4FiEEoDXIwZIZuoIezqhrZOYo+NaEaW0FAlq+ToQCGwMFCwkIBwMFFQoJ +CAsFFgIDAQACHgECF4AACgkQZOYo+NaEaW2bmA/+PXIap2udLoUVOHxnsIBdqYwp +sv1Aj5lfIJmNhmxPbHShwp1Jg+w4urxe+2Dj5ofKVlIo1i83bQkvnKJMDXDVuc/K +P6zqhBJ3rT4Q3qx2mzX8bIfQoJ2JHuH4lkP+I7doDcHHRyeNASyk72VdQmU4twNw +Ibn8nSNV6ThKHdoPYzVnO2rZUFcGIqH5HNsvR+B7cc1MBCHsgURYwSVhSePIFGlZ +iasdBD6QQkDSe4QWi7AcJFWFElw4kbOKJWxAWsrEk+tMXJVGRjnmL289EmPCx/vx +BqKy7Mse0yWCSRR3vB+O6TB1S5SgEyEgqlYsfGNv1qf/rfRD4KkyCbNU3LhY1Aim +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 +=6Zb4 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/python311-rpmlintrc b/python311-rpmlintrc new file mode 100644 index 0000000..6c3d3b0 --- /dev/null +++ b/python311-rpmlintrc @@ -0,0 +1,4 @@ +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") +addFilter("python-bytecode-inconsistent-mtime.*\.pyc") diff --git a/python311.changes b/python311.changes new file mode 100644 index 0000000..5c5eef1 --- /dev/null +++ b/python311.changes @@ -0,0 +1,5725 @@ +------------------------------------------------------------------- +Wed Oct 15 08:52:35 UTC 2025 - Daniel Garcia + +- Update to 3.11.14: + - Security + - gh-139700: Check consistency of the zip64 end of central + directory record. Support records with “zip64 extensible data” + if there are no bytes prepended to the ZIP file. + - gh-139400: xml.parsers.expat: Make sure that parent Expat + parsers are only garbage-collected once they are no longer + referenced by subparsers created by + ExternalEntityParserCreate(). Patch by Sebastian Pipping. + - gh-135661: Fix parsing start and end tags in + html.parser.HTMLParser according to the HTML5 standard. + * Whitespaces no longer accepted between does not end the script section. + * Vertical tabulation (\v) and non-ASCII whitespaces no longer + recognized as whitespaces. The only whitespaces are \t\n\r\f and + space. + * Null character (U+0000) no longer ends the tag name. + * Attributes and slashes after the tag name in end tags are now + ignored, instead of terminating after the first > in quoted + attribute value. E.g. . + * Multiple slashes and whitespaces between the last attribute and + closing > are now ignored in both start and end tags. E.g.
. + * Multiple = between attribute name and value are no longer + collapsed. E.g. produces attribute “foo” with value + “=bar”. + - gh-135661: Fix CDATA section parsing in html.parser.HTMLParser + according to the HTML5 standard: ] ]> and ]] > no longer end the + CDATA section. Add private method _set_support_cdata() which can + be used to specify how to parse <[CDATA[ — as a CDATA section in + foreign content (SVG or MathML) or as a bogus comment in the + HTML namespace. + - gh-102555: Fix comment parsing in html.parser.HTMLParser + according to the HTML5 standard. --!> now ends the comment. -- > + no longer ends the comment. Support abnormally ended empty + comments <--> and <--->. + - gh-135462: Fix quadratic complexity in processing specially + crafted input in html.parser.HTMLParser. End-of-file errors are + now handled according to the HTML5 specs – comments and + declarations are automatically closed, tags are ignored. + - gh-118350: Fix support of escapable raw text mode (elements + “textarea” and “title”) in html.parser.HTMLParser. + - gh-86155: html.parser.HTMLParser.close() no longer loses data + when the