commit 0b3ef5de9689e4472b6d415bd4702f15147a172ae3a0f0ced121360793be295e Author: Matej Cepl Date: Thu Oct 16 16:28:51 2025 +0000 - Update to 3.10.19: - 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/python310?expand=0&rev=196 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..25e068f --- /dev/null +++ b/CVE-2023-52425-libexpat-2.6.0-backport.patch @@ -0,0 +1,57 @@ +--- + Lib/test/test_pyexpat.py | 4 ++++ + Lib/test/test_sax.py | 3 +++ + Lib/test/test_xml_etree.py | 7 +++++++ + 3 files changed, 14 insertions(+) + +--- a/Lib/test/test_pyexpat.py ++++ b/Lib/test/test_pyexpat.py +@@ -766,6 +766,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 +@@ -1240,6 +1240,9 @@ class ExpatReaderTest(XmlTestBase): + + self.assertEqual(result.getvalue(), start + b"") + ++ @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 +@@ -1420,9 +1420,13 @@ class XMLPullParserTest(unittest.TestCas + self.assert_event_tags(parser, [('end', 'root')]) + self.assertIsNone(parser.close()) + ++ @unittest.skipIf(pyexpat.version_info < (2, 6, 0), ++ f'Fail with patched version of Expat {pyexpat.version_info}') + def test_simple_xml_chunk_1(self): + self.test_simple_xml(chunk_size=1, flush=True) + ++ @unittest.skipIf(pyexpat.version_info < (2, 6, 0), ++ f'Fail with patched version of Expat {pyexpat.version_info}') + def test_simple_xml_chunk_5(self): + self.test_simple_xml(chunk_size=5, flush=True) + +@@ -1647,6 +1651,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')) + diff --git a/CVE-2025-6069-quad-complex-HTMLParser.patch b/CVE-2025-6069-quad-complex-HTMLParser.patch new file mode 100644 index 0000000..4cfe513 --- /dev/null +++ b/CVE-2025-6069-quad-complex-HTMLParser.patch @@ -0,0 +1,238 @@ +From ec28625203b5dd4b4447dc4bb512898294cd6d0c Mon Sep 17 00:00:00 2001 +From: Serhiy Storchaka +Date: Fri, 13 Jun 2025 19:57:48 +0300 +Subject: [PATCH] [3.10] 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 | 95 ++++++++-- + Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst | 4 + 3 files changed, 117 insertions(+), 23 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst + +Index: Python-3.10.18/Lib/html/parser.py +=================================================================== +--- Python-3.10.18.orig/Lib/html/parser.py 2025-07-02 18:00:32.520419724 +0200 ++++ Python-3.10.18/Lib/html/parser.py 2025-07-02 18:00:42.616018075 +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')])]) +@@ -537,13 +545,56 @@ + for html, expected in data: + self._run_check(html, expected) + +- def test_broken_comments(self): +- html = ('' ++ def test_eof_in_comments(self): ++ data = [ ++ ('', [('comment', '-!>')]), ++ ('' + '' + '' + '') + expected = [ ++ ('comment', 'ELEMENT br EMPTY'), + ('comment', ' not really a comment '), + ('comment', ' not a comment either --'), + ('comment', ' -- close enough --'), +@@ -598,6 +649,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] [3.10] 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.10.18/Lib/tarfile.py +=================================================================== +--- Python-3.10.18.orig/Lib/tarfile.py 2025-08-02 17:52:24.521273582 +0200 ++++ Python-3.10.18/Lib/tarfile.py 2025-08-02 17:52:28.444044748 +0200 +@@ -1612,6 +1612,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.10.18/Lib/test/test_tarfile.py +=================================================================== +--- Python-3.10.18.orig/Lib/test/test_tarfile.py 2025-08-02 17:52:25.849390293 +0200 ++++ Python-3.10.18/Lib/test/test_tarfile.py 2025-08-02 17:52:39.623989523 +0200 +@@ -49,6 +49,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" +@@ -4273,6 +4274,161 @@ + self.expect_exception(TypeError) # errorlevel is not int + + ++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.10.18/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.10.18/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst 2025-08-02 17:52:28.446021271 +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..b9efb30 --- /dev/null +++ b/F00251-change-user-install-location.patch @@ -0,0 +1,187 @@ +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.10.14/Lib/distutils/command/install.py +=================================================================== +--- Python-3.10.14.orig/Lib/distutils/command/install.py ++++ Python-3.10.14/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.10.14/Lib/site.py +=================================================================== +--- Python-3.10.14.orig/Lib/site.py ++++ Python-3.10.14/Lib/site.py +@@ -390,8 +390,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) +Index: Python-3.10.14/Lib/sysconfig.py +=================================================================== +--- Python-3.10.14.orig/Lib/sysconfig.py ++++ Python-3.10.14/Lib/sysconfig.py +@@ -117,6 +117,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') + +@@ -136,6 +149,16 @@ _variable_rx = r"([a-zA-Z][a-zA-Z0-9_]+) + _findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)" + _findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}" + ++# 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'] ++ ++# 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 _safe_realpath(path): + try: +@@ -211,11 +234,39 @@ 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()) + + for key, value in _INSTALL_SCHEMES[scheme].items(): + if os.name in ('posix', 'nt'): +Index: Python-3.10.14/Lib/test/test_sysconfig.py +=================================================================== +--- Python-3.10.14.orig/Lib/test/test_sysconfig.py ++++ Python-3.10.14/Lib/test/test_sysconfig.py +@@ -105,8 +105,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), + ) + +@@ -263,7 +274,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'] ++ wanted = ['nt', 'posix_home', 'posix_prefix', 'rpm_prefix'] + if HAS_USER_BASE: + wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) + self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) +@@ -274,6 +285,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.10.18.tar.xz b/Python-3.10.18.tar.xz new file mode 100644 index 0000000..5fc6dc7 --- /dev/null +++ b/Python-3.10.18.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae665bc678abd9ab6a6e1573d2481625a53719bc517e9a634ed2b9fefae3817f +size 19619316 diff --git a/Python-3.10.18.tar.xz.sigstore b/Python-3.10.18.tar.xz.sigstore new file mode 100644 index 0000000..367da25 --- /dev/null +++ b/Python-3.10.18.tar.xz.sigstore @@ -0,0 +1 @@ +{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzDCCAlOgAwIBAgIUPPj8WFgcPzKI0f+pcaxc3TPA/yswCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNjAzMTg1ODI4WhcNMjUwNjAzMTkwODI4WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4NqgXmbx5LR/ICb4FcCE0psZ0nEPhnhmk36DOselqJIUA54Dj0SKcFUP3wbmqi9h9bo7ZqbQ5HTZR0ditz16KKOCAXIwggFuMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQU91EDPL5bqZeofhdNBEBL98Ga+MEwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wIgYDVR0RAQH/BBgwFoEUcGFibG9nc2FsQHB5dGhvbi5vcmcwKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGKBgorBgEEAdZ5AgQCBHwEegB4AHYA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGXNyjEogAABAMARzBFAiBenFTetr0d9XKM2FxuhUPv7YJVxt4F5reAl9D4IOX2JwIhAOULSuk4H79udCf1i4QEIPCrs3oEV3u+VpJ9GTC2Y+/mMAoGCCqGSM49BAMDA2cAMGQCMGGrDPAeA+zuXcHOmXGsqPX274/sjglPqkuXX8wI1JwDUoT5mN7ZZpAJX8XAQQAixwIwfk+a9VmWcY0I1UuAu+NuRRkNQCofemUeEuzhWyK1Yn5G+DcuXVf7lNlwC6awM0mb"}, "tlogEntries": [{"logIndex": "228919874", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1748977108", "inclusionPromise": {"signedEntryTimestamp": "MEUCIBlZWCgOoVzS+qS/YuAKZFDbO/cyOLxdRdDRFQVrjbfzAiEAvs5r5K/zZEJJE5bh/OFQPTex7Hj9OzJ8SQtvX2bATVk="}, "inclusionProof": {"logIndex": "107015612", "rootHash": "SCbCVVGttK0oajRjYxDAulUQEOL1nRy9KG6JbVMfe88=", "treeSize": "107015615", "hashes": ["1jQZ0U0iztYR47T7VqVQL/XmQ1kOJ9VGJAlEV7S12Rk=", "nzFzeKP8TFHjIx2Mf5E5RHDnftKz14VXcXGOv6TjP2U=", "rYdthRwegf6R59Jn79y56HZlg/HgWGq2ThwABpgzIx8=", "itoQl5XnazIM1MaE0xAHfTyJuXWLosPRHBX6LOyQZqw=", "m4vF5qDZ/VpszDAF6BpkLLL9mJUrMqTnDGBzbP1+mAA=", "aPbPdtUCj7gO3JjjsuOf+HO0RD3cth0ZCf7GBkev2jA=", "F1AHv3JuUWYZTcWLZFEo2qDYsdVdytSXRmZu4tASPAk=", "jhwwkSRTGiVvY/O6FZ9c4ASOhW4Uktv0K324Xmy4V/k=", "m/WZEVH9CTs0KJcGZIdK4CVc1WENSbb9gjFrdzj5kYI=", "MRAzh2spHQbvIBIISBBvo0zc0n73qn6TIJ5ur8P4K/8=", "tuZDuieL5jtYIFu4Miyh8eBdvmmkGD1LcMTrLs7j/ZE=", "kbUClUnkU0UJZhuQHiwkFFDXdat+8DImNUFMe+bn0Q4=", "WdQbyoFfuhZe2IciO+mhgtPi9ev0pSFpkBr7XCWylqQ=", "uEJFtwcGQJMd9kjQhkXb7gl2WD3WMElCc15uDFvFGxs=", "VdOKzpQhJlpXgijzXANf/hNlje1G/N1kUuVnKNskkso=", "mta5fH/gFwxJ/0fT8yGpn3sFCY0G1RY555Iflm0LInM=", "7v8qPHNDLerpduaMx06eb/MwgoQwczTn/cYGKX/9wZ4="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n107015615\nSCbCVVGttK0oajRjYxDAulUQEOL1nRy9KG6JbVMfe88=\n\n\u2014 rekor.sigstore.dev wNI9ajBEAiAC5UJXNKStXDw/L3DlSxscdhpQvVI3Ann4US9sFgT0mAIgJw8zaZc5WMKv1tIRBEUSw1lTjeEO69ypVTwS3MGF7MQ=\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJhZTY2NWJjNjc4YWJkOWFiNmE2ZTE1NzNkMjQ4MTYyNWE1MzcxOWJjNTE3ZTlhNjM0ZWQyYjlmZWZhZTM4MTdmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJQ3RudW1SZHlqbUVZaHV3MlpNTWdBZFpBeXYvcjVnSjhHbnFUWTBlTS9yNUFpQklQM2pGQWN6TXFhY0N5RE9kMkFKU0VyNmEwSTQxcnRwUHJCRUJMc1ArU0E9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZSRU5EUVd4UFowRjNTVUpCWjBsVlVGQnFPRmRHWjJOUWVrdEpNR1lyY0dOaGVHTXpWRkJCTDNsemQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZkMDVxUVhwTlZHY3hUMFJKTkZkb1kwNU5hbFYzVG1wQmVrMVVhM2RQUkVrMFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVUwVG5GbldHMWllRFZNVWk5SlEySTBSbU5EUlRCd2Mxb3dia1ZRYUc1b2JXc3pOa1FLVDNObGJIRktTVlZCTlRSRWFqQlRTMk5HVlZBemQySnRjV2s1YURsaWJ6ZGFjV0pSTlVoVVdsSXdaR2wwZWpFMlMwdFBRMEZZU1hkblowWjFUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlU1TVVWRUNsQk1OV0p4V21WdlptaGtUa0pGUWt3NU9FZGhLMDFGZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBsbldVUldVakJTUVZGSUwwSkNaM2RHYjBWVlkwZEdhV0pIT1c1ak1rWnpVVWhDTldSSGFIWmlhVFYyWTIxamQwdFJXVXRMZDFsQ1FrRkhSQXAyZWtGQ1FWRlJZbUZJVWpCalNFMDJUSGs1YUZreVRuWmtWelV3WTNrMWJtSXlPVzVpUjFWMVdUSTVkRTFEYzBkRGFYTkhRVkZSUW1jM09IZEJVV2RGQ2toUmQySmhTRkl3WTBoTk5reDVPV2haTWs1MlpGYzFNR041Tlc1aU1qbHVZa2RWZFZreU9YUk5TVWRMUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJZDBVS1pXZENORUZJV1VFelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIxaE9lV3BGYjJkQlFRcENRVTFCVW5wQ1JrRnBRbVZ1UmxSbGRISXdaRGxZUzAweVJuaDFhRlZRZGpkWlNsWjRkRFJHTlhKbFFXdzVSRFJKVDFneVNuZEphRUZQVlV4VGRXczBDa2czT1hWa1EyWXhhVFJSUlVsUVEzSnpNMjlGVmpOMUsxWndTamxIVkVNeVdTc3ZiVTFCYjBkRFEzRkhVMDAwT1VKQlRVUkJNbU5CVFVkUlEwMUhSM0lLUkZCQlpVRXJlblZZWTBoUGJWaEhjM0ZRV0RJM05DOXphbWRzVUhGcmRWaFlPSGRKTVVwM1JGVnZWRFZ0VGpkYVduQkJTbGc0V0VGUlVVRnBlSGRKZHdwbWF5dGhPVlp0VjJOWk1Fa3hWWFZCZFN0T2RWSlNhMDVSUTI5bVpXMVZaVVYxZW1oWGVVc3hXVzQxUnl0RVkzVllWbVkzYkU1c2QwTTJZWGROTUcxaUNpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19"}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "rmZbxnir2atqbhVz0kgWJaU3GbxRfppjTtK5/vrjgX8="}, "signature": "MEQCICtnumRdyjmEYhuw2ZMMgAdZAyv/r5gJ8GnqTY0eM/r5AiBIP3jFAczMqacCyDOd2AJSEr6a0I41rtpPrBEBLsP+SA=="}} diff --git a/Python-3.10.19.tar.xz b/Python-3.10.19.tar.xz new file mode 100644 index 0000000..4cd42b2 --- /dev/null +++ b/Python-3.10.19.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c8f4a596572201d81dd7df91f70e177e19a70f1d489968b54b5fbbf29a97c076 +size 19873020 diff --git a/Python-3.10.19.tar.xz.sigstore b/Python-3.10.19.tar.xz.sigstore new file mode 100644 index 0000000..f88b5bd --- /dev/null +++ b/Python-3.10.19.tar.xz.sigstore @@ -0,0 +1 @@ +{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICzjCCAlSgAwIBAgIUPLyAcJBqiNboHaWs7BHcTxLyk10wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUxMDA5MTYwMzQ1WhcNMjUxMDA5MTYxMzQ1WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/Ph0DALE7DyuLJPqS8zTKbHvI4d4FTFysDKBex9xr05SkjWCKLXNIrQmtHHOMQxZHtnLqlyGWc9C6R2a1cTbTaOCAXMwggFvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUybzXPdm39+0wK3RSdJ45ttTJN3kwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wIgYDVR0RAQH/BBgwFoEUcGFibG9nc2FsQHB5dGhvbi5vcmcwKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGLBgorBgEEAdZ5AgQCBH0EewB5AHcA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGZybbSOQAABAMASDBGAiEAw9xx7UYivhAyYIxj8O/bRt/WdKL74c3MZDyXembfzTMCIQCDyspf74flglREl1yUs9/t+X2OhtzftOQdBPGH4ZWjbTAKBggqhkjOPQQDAwNoADBlAjBDE2ymGrMzZxRO+yRwzl1ujWuR6SeVI1Ty5+VVUW0QGikW9a4+3I+DB3TUxPNvh80CMQCGOyJMos1BBpAgiUyvb22OJ3BhzGgmC9dFSgcvzlyms5blKLAtBjf1+IlyFdEkBIc="}, "tlogEntries": [{"logIndex": "597674983", "logId": {"keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}, "kindVersion": {"kind": "hashedrekord", "version": "0.0.1"}, "integratedTime": "1760025826", "inclusionPromise": {"signedEntryTimestamp": "MEUCIQDOhM/d61Xhr0Tn1mq0RFlu6kVvr+yr/OqE5ztg4LdI7AIgD6WPgOpn/1MgSp/XZ+ftU8wtZR32T+2wR03bkJOtQbE="}, "inclusionProof": {"logIndex": "475770721", "rootHash": "B1gv7JXRafrhEphKVN52yfrMBZ3YKQQELBICIGE0Xbk=", "treeSize": "475770722", "hashes": ["WK4RpC4pMLkEw8wOVJNRhaVH/LNHi65GwYW198mWnlA=", "opCnXnHA8HzxF/z3Qb6GpkzKVubqUgILN9729tSo7bk=", "81B2Ob5iKGTzITexeN47H++3/4QI6rNrwIp50yNjvYs=", "y24fAVX92cj3coVxwKg7azZlV2Oy7R0nwdY1HtepWQE=", "ojBgFF5g+M4hyxvL++Yi4mkmz2qJwkCl+1EpxEvLUdk=", "mZCvajPPCTqDtyHpKtXR1PctgiNLlTcGb/DjzXpA/eY=", "wCMog5TY7QnhcGa4vMQ8Scgr8Ti0zxV/CrgLR9sXadk=", "lU4SDoAFOyhGKqjcmr+9hlvgGNEuazsT3vZ4Hl7u4Sw=", "4fiFuSaFvn0p4uqLNF0ReEHj2uOks8Djwmd/wiJjI4I=", "WlOPUw/aSCRGCD82nA+ExVSdSAGkafb1nGxd3PAXPSk=", "V/aAsI+q3p5YLtfajhhBrAJmnMLh+6w/evHpWZ4yYJI=", "qXhJobQjWl6SO/pue3trUW2uL4jXx24Ip7lpd4hc5bU=", "56ObhlROm9L8Q4JyN+mxEQ5pZD5QdobB1xZFIeL0lVg=", "EGaD/cNavzxGYLx1Gl0uNNWBZvyXlSHSdlIeH7m+63A=", "2Wv4GiithwNukRKV06clevnQQYCzXmSS/+/OJtXgsXQ=", "1mfy94KpcItqshH9+gwqV6jccupcaMpVsF28New8zDY=", "vS7O4ozHIQZJWBiov+mkpI27GE8zAmVCEkRcP3NDyNE="], "checkpoint": {"envelope": "rekor.sigstore.dev - 1193050959916656506\n475770722\nB1gv7JXRafrhEphKVN52yfrMBZ3YKQQELBICIGE0Xbk=\n\n\u2014 rekor.sigstore.dev wNI9ajBFAiEAi6W3v4n0hXFzBd/6jaKqBKmR6NSI62pITwqVgYWddeMCIG8EzMyqDkIyqMIi18EuboV6kml4tBJox32CvAaQHdnQ\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJjOGY0YTU5NjU3MjIwMWQ4MWRkN2RmOTFmNzBlMTc3ZTE5YTcwZjFkNDg5OTY4YjU0YjVmYmJmMjlhOTdjMDc2In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJQWltQ1ZnNTF3SzVCU2FoZVlGZFpNRWVPZUZrdEZJT2d3bUZRdnNEdVJ3NUFpQngzRTB5c0t5OEl5V3gyQk5KVzUrVG9GNmUxRmhaKzlNWEhoVGJnTVF6aGc9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjZha05EUVd4VFowRjNTVUpCWjBsVlVFeDVRV05LUW5GcFRtSnZTR0ZYY3pkQ1NHTlVlRXg1YXpFd2QwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFZlRTFFUVRWTlZGbDNUWHBSTVZkb1kwNU5hbFY0VFVSQk5VMVVXWGhOZWxFeFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVV2VUdnd1JFRk1SVGRFZVhWTVNsQnhVemg2VkV0aVNIWkpOR1EwUmxSR2VYTkVTMElLWlhnNWVISXdOVk5yYWxkRFMweFlUa2x5VVcxMFNFaFBUVkY0V2toMGJreHhiSGxIVjJNNVF6WlNNbUV4WTFSaVZHRlBRMEZZVFhkblowWjJUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlY1WW5wWUNsQmtiVE01S3pCM1N6TlNVMlJLTkRWMGRGUktUak5yZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBsbldVUldVakJTUVZGSUwwSkNaM2RHYjBWVlkwZEdhV0pIT1c1ak1rWnpVVWhDTldSSGFIWmlhVFYyWTIxamQwdFJXVXRMZDFsQ1FrRkhSQXAyZWtGQ1FWRlJZbUZJVWpCalNFMDJUSGs1YUZreVRuWmtWelV3WTNrMWJtSXlPVzVpUjFWMVdUSTVkRTFEYzBkRGFYTkhRVkZSUW1jM09IZEJVV2RGQ2toUmQySmhTRkl3WTBoTk5reDVPV2haTWs1MlpGYzFNR041Tlc1aU1qbHVZa2RWZFZreU9YUk5TVWRNUW1kdmNrSm5SVVZCWkZvMVFXZFJRMEpJTUVVS1pYZENOVUZJWTBFelZEQjNZWE5pU0VWVVNtcEhValJqYlZkak0wRnhTa3RZY21wbFVFc3pMMmcwY0hsblF6aHdOMjgwUVVGQlIxcDVZbUpUVDFGQlFRcENRVTFCVTBSQ1IwRnBSVUYzT1hoNE4xVlphWFpvUVhsWlNYaHFPRTh2WWxKMEwxZGtTMHczTkdNelRWcEVlVmhsYldKbWVsUk5RMGxSUTBSNWMzQm1DamMwWm14bmJGSkZiREY1VlhNNUwzUXJXREpQYUhSNlpuUlBVV1JDVUVkSU5GcFhhbUpVUVV0Q1oyZHhhR3RxVDFCUlVVUkJkMDV2UVVSQ2JFRnFRa1FLUlRKNWJVZHlUWHBhZUZKUEszbFNkM3BzTVhWcVYzVlNObE5sVmtreFZIazFLMVpXVlZjd1VVZHBhMWM1WVRRck0wa3JSRUl6VkZWNFVFNTJhRGd3UXdwTlVVTkhUM2xLVFc5ek1VSkNjRUZuYVZWNWRtSXlNazlLTTBKb2VrZG5iVU01WkVaVFoyTjJlbXg1YlhNMVlteExURUYwUW1wbU1TdEpiSGxHWkVWckNrSkpZejBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}], "timestampVerificationData": {}}, "messageSignature": {"messageDigest": {"algorithm": "SHA2_256", "digest": "yPSlllciAdgd19+R9w4XfhmnDx1ImWi1S1+78pqXwHY="}, "signature": "MEQCIAimCVg51wK5BSaheYFdZMEeOeFktFIOgwmFQvsDuRw5AiBx3E0ysKy8IyWx2BNJW5+ToF6e1FhZ+9MXHhTbgMQzhg=="}} 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/baselibs.conf b/baselibs.conf new file mode 100644 index 0000000..67e73d0 --- /dev/null +++ b/baselibs.conf @@ -0,0 +1,3 @@ +python310-base +python310 +libpython3_10-1_0 diff --git a/bluez-devel-vendor.tar.xz b/bluez-devel-vendor.tar.xz new file mode 100644 index 0000000..bb4fd89 --- /dev/null +++ b/bluez-devel-vendor.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4624c6ab6543ec4875bdd5c6c58c874d487128e44e54c8ef1924ec1d48e35928 +size 25328 diff --git a/bpo-31046_ensurepip_honours_prefix.patch b/bpo-31046_ensurepip_honours_prefix.patch new file mode 100644 index 0000000..6afc257 --- /dev/null +++ b/bpo-31046_ensurepip_honours_prefix.patch @@ -0,0 +1,163 @@ +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 + +--- a/Doc/library/ensurepip.rst ++++ b/Doc/library/ensurepip.rst +@@ -58,8 +58,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. + * ``--root ``: Installs ``pip`` relative to the given root directory + rather than the root of the currently active virtual environment (if any) + or the default root for the current Python installation. +@@ -91,7 +92,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) + +@@ -101,6 +102,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. + +@@ -121,6 +124,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 +@@ -123,27 +123,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. + """ +@@ -193,6 +193,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: +@@ -268,6 +270,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, +@@ -286,6 +293,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 +@@ -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) + +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1278,7 +1278,7 @@ install: @FRAMEWORKINSTALLFIRST@ commoni + install|*) ensurepip="" ;; \ + esac; \ + $(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \ +- $$ensurepip --root=$(DESTDIR)/ ; \ ++ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \ + fi + + altinstall: commoninstall +@@ -1288,7 +1288,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@ \ +--- /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`. diff --git a/bpo-37596-make-set-marshalling.patch b/bpo-37596-make-set-marshalling.patch new file mode 100644 index 0000000..44bc85f --- /dev/null +++ b/bpo-37596-make-set-marshalling.patch @@ -0,0 +1,103 @@ +From 33d95c6facdfda3c8c0feffa7a99184e4abc2f63 Mon Sep 17 00:00:00 2001 +From: Brandt Bucher +Date: Wed, 25 Aug 2021 04:14:34 -0700 +Subject: [PATCH] bpo-37596: Make `set` and `frozenset` marshalling + deterministic (GH-27926) + +--- + Lib/test/test_marshal.py | 26 ++++++++ + Misc/NEWS.d/next/Library/2021-08-23-21-39-59.bpo-37596.ojRcwB.rst | 2 + Python/marshal.c | 32 ++++++++++ + 3 files changed, 60 insertions(+) + create mode 100644 Misc/NEWS.d/next/Library/2021-08-23-21-39-59.bpo-37596.ojRcwB.rst + +--- a/Lib/test/test_marshal.py ++++ b/Lib/test/test_marshal.py +@@ -1,5 +1,6 @@ + from test import support + from test.support import os_helper ++from test.support.script_helper import assert_python_ok + import array + import io + import marshal +@@ -318,6 +319,31 @@ class BugsTestCase(unittest.TestCase): + for i in range(len(data)): + self.assertRaises(EOFError, marshal.loads, data[0: i]) + ++ def test_deterministic_sets(self): ++ # bpo-37596: To support reproducible builds, sets and frozensets need to ++ # have their elements serialized in a consistent order (even when they ++ # have been scrambled by hash randomization): ++ for kind in ("set", "frozenset"): ++ for elements in ( ++ "float('nan'), b'a', b'b', b'c', 'x', 'y', 'z'", ++ # Also test for bad interactions with backreferencing: ++ "('string', 1), ('string', 2), ('string', 3)", ++ ): ++ s = f"{kind}([{elements}])" ++ with self.subTest(s): ++ # First, make sure that our test case still has different ++ # orders under hash seeds 0 and 1. If this check fails, we ++ # need to update this test with different elements: ++ args = ["-c", f"print({s})"] ++ _, repr_0, _ = assert_python_ok(*args, PYTHONHASHSEED="0") ++ _, repr_1, _ = assert_python_ok(*args, PYTHONHASHSEED="1") ++ self.assertNotEqual(repr_0, repr_1) ++ # Then, perform the actual test: ++ args = ["-c", f"import marshal; print(marshal.dumps({s}))"] ++ _, dump_0, _ = assert_python_ok(*args, PYTHONHASHSEED="0") ++ _, dump_1, _ = assert_python_ok(*args, PYTHONHASHSEED="1") ++ self.assertEqual(dump_0, dump_1) ++ + LARGE_SIZE = 2**31 + pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4 + +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2021-08-23-21-39-59.bpo-37596.ojRcwB.rst +@@ -0,0 +1,2 @@ ++Ensure that :class:`set` and :class:`frozenset` objects are always ++:mod:`marshalled ` reproducibly. +--- a/Python/marshal.c ++++ b/Python/marshal.c +@@ -502,9 +502,41 @@ w_complex_object(PyObject *v, char flag, + W_TYPE(TYPE_SET, p); + n = PySet_GET_SIZE(v); + W_SIZE(n, p); ++ // bpo-37596: To support reproducible builds, sets and frozensets need ++ // to have their elements serialized in a consistent order (even when ++ // they have been scrambled by hash randomization). To ensure this, we ++ // use an order equivalent to sorted(v, key=marshal.dumps): ++ PyObject *pairs = PyList_New(0); ++ if (pairs == NULL) { ++ p->error = WFERR_NOMEMORY; ++ return; ++ } + while (_PySet_NextEntry(v, &pos, &value, &hash)) { ++ PyObject *dump = PyMarshal_WriteObjectToString(value, p->version); ++ if (dump == NULL) { ++ p->error = WFERR_UNMARSHALLABLE; ++ goto anyset_done; ++ } ++ PyObject *pair = PyTuple_Pack(2, dump, value); ++ Py_DECREF(dump); ++ if (pair == NULL || PyList_Append(pairs, pair)) { ++ p->error = WFERR_NOMEMORY; ++ Py_XDECREF(pair); ++ goto anyset_done; ++ } ++ Py_DECREF(pair); ++ } ++ if (PyList_Sort(pairs)) { ++ p->error = WFERR_NOMEMORY; ++ goto anyset_done; ++ } ++ for (Py_ssize_t i = 0; i < n; i++) { ++ PyObject *pair = PyList_GET_ITEM(pairs, i); ++ value = PyTuple_GET_ITEM(pair, 1); + w_object(value, p); + } ++ anyset_done: ++ Py_DECREF(pairs); + } + else if (PyCode_Check(v)) { + PyCodeObject *co = (PyCodeObject *)v; diff --git a/bso1227999-reproducible-builds.patch b/bso1227999-reproducible-builds.patch new file mode 100644 index 0000000..1b674a7 --- /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 +@@ -89,7 +89,8 @@ html_short_title = '%s Documentation' % + + # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, + # using the given strftime format. +-html_last_updated_fmt = '%b %d, %Y' ++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 +@@ -1320,7 +1320,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..02f6b90 --- /dev/null +++ b/distutils-reproducible-compile.patch @@ -0,0 +1,30 @@ +Index: Python-3.10.5/Lib/compileall.py +=================================================================== +--- Python-3.10.5.orig/Lib/compileall.py ++++ Python-3.10.5/Lib/compileall.py +@@ -96,6 +96,12 @@ def compile_dir(dir, maxlevels=None, ddi + maxlevels = sys.getrecursionlimit() + files = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels) + success = True ++ # work around https://github.com/python/cpython/issues/93317 ++ sys.intern('{') ++ sys.intern('{{') ++ sys.intern('}') ++ sys.intern('}}') ++ + if workers != 1 and ProcessPoolExecutor is not None: + # If workers == 0, let ProcessPoolExecutor choose + workers = workers or None +Index: Python-3.10.5/Lib/distutils/util.py +=================================================================== +--- Python-3.10.5.orig/Lib/distutils/util.py ++++ Python-3.10.5/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/fix_configure_rst.patch b/fix_configure_rst.patch new file mode 100644 index 0000000..7c52e72 --- /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 +@@ -42,7 +42,6 @@ General Options + + See :data:`sys.int_info.bits_per_digit `. + +-.. cmdoption:: --with-cxx-main + .. cmdoption:: --with-cxx-main=COMPILER + + Compile the Python ``main()`` function and link Python executable with C++ +@@ -473,13 +472,11 @@ macOS Options + + See ``Mac/README.rst``. + +-.. cmdoption:: --enable-universalsdk + .. cmdoption:: --enable-universalsdk=SDKDIR + + Create a universal binary build. *SDKDIR* specifies which macOS SDK should + be used to perform the build (default is no). + +-.. cmdoption:: --enable-framework + .. cmdoption:: --enable-framework=INSTALLDIR + + Create a Python.framework rather than a traditional Unix install. Optional +--- a/Misc/NEWS ++++ b/Misc/NEWS +@@ -3942,7 +3942,7 @@ C API + ----- + + - bpo-43795: The list in :ref:`stable-abi-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/gh-78214-marshal_stabilize_FLAG_REF.patch b/gh-78214-marshal_stabilize_FLAG_REF.patch new file mode 100644 index 0000000..3124d2a --- /dev/null +++ b/gh-78214-marshal_stabilize_FLAG_REF.patch @@ -0,0 +1,30 @@ +From 6c8ea7c1dacd42f3ba00440231ec0e6b1a38300d Mon Sep 17 00:00:00 2001 +From: Inada Naoki +Date: Sat, 14 Jul 2018 00:46:11 +0900 +Subject: [PATCH] Use FLAG_REF always for interned strings + +--- + Python/marshal.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +Index: Python-3.10.12/Python/marshal.c +=================================================================== +--- Python-3.10.12.orig/Python/marshal.c ++++ Python-3.10.12/Python/marshal.c +@@ -298,9 +298,14 @@ w_ref(PyObject *v, char *flag, WFILE *p) + if (p->version < 3 || p->hashtable == NULL) + return 0; /* not writing object references */ + +- /* if it has only one reference, it definitely isn't shared */ +- if (Py_REFCNT(v) == 1) ++ /* If it has only one reference, it definitely isn't shared. ++ * But we use TYPE_REF always for interned string, to PYC file stable ++ * as possible. ++ */ ++ if (Py_REFCNT(v) == 1 && ++ !(PyUnicode_CheckExact(v) && PyUnicode_CHECK_INTERNED(v))) { + return 0; ++ } + + entry = _Py_hashtable_get_entry(p->hashtable, v); + if (entry != NULL) { diff --git a/gh120226-fix-sendfile-test-kernel-610.patch b/gh120226-fix-sendfile-test-kernel-610.patch new file mode 100644 index 0000000..aebd6b6 --- /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..bc456f1 --- /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.10.18/Doc/tools/extensions/pyspecific.py +=================================================================== +--- Python-3.10.18.orig/Doc/tools/extensions/pyspecific.py 2025-09-30 18:24:01.155883150 +0200 ++++ Python-3.10.18/Doc/tools/extensions/pyspecific.py 2025-09-30 18:24:01.192999890 +0200 +@@ -55,11 +55,21 @@ + SOURCE_URI = 'https://github.com/python/cpython/tree/3.10/%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 + + + # Support for marking up and linking to bugs.python.org issues 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..12e5b30 --- /dev/null +++ b/import_failed.map @@ -0,0 +1,7 @@ +python310-curses: curses _curses _curses_panel +python310-dbm: dbm _dbm _gdbm +python310-idle: idlelib +python310-testsuite: test _ctypes_test _testbuffer _testcapi _testinternalcapi _testimportmultiple _testmultiphase xxlimited +python310-tk: tkinter _tkinter +python310-tools: turtledemo +python310: 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..2601c01 --- /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 +@@ -250,7 +250,6 @@ Turtle motion + turtle is headed. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.position() + (0.00,0.00) +@@ -277,7 +276,6 @@ Turtle motion + >>> turtle.goto(0, 0) + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.position() + (0.00,0.00) +@@ -296,13 +294,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 +@@ -321,13 +317,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 +@@ -350,13 +344,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 +@@ -380,13 +372,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) +@@ -402,13 +392,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) +@@ -435,7 +423,6 @@ Turtle motion + =================== ==================== + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.setheading(90) + >>> turtle.heading() +@@ -448,14 +435,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 +@@ -487,7 +472,6 @@ Turtle motion + calculated automatically. May be used to draw regular polygons. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.position() +@@ -516,7 +500,6 @@ Turtle motion + + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.dot() +@@ -534,7 +517,6 @@ Turtle motion + it by calling ``clearstamp(stamp_id)``. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.color("blue") + >>> turtle.stamp() +@@ -550,7 +532,6 @@ Turtle motion + Delete stamp with given *stampid*. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.position() + (150.00,-0.00) +@@ -595,7 +576,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) +@@ -628,7 +608,6 @@ Turtle motion + turtle turn instantly. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.speed() + 3 +@@ -649,7 +628,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) +@@ -665,7 +643,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) +@@ -677,7 +654,6 @@ Tell Turtle's state + Return the turtle's x coordinate. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(50) +@@ -693,7 +669,6 @@ Tell Turtle's state + Return the turtle's y coordinate. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(60) +@@ -710,7 +685,6 @@ Tell Turtle's state + :func:`mode`). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(67) +@@ -727,7 +701,6 @@ Tell Turtle's state + other turtle, in turtle step units. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.distance(30,40) +@@ -751,7 +724,6 @@ Settings for measurement + Default value is 360 degrees. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(90) +@@ -774,7 +746,6 @@ Settings for measurement + ``degrees(2*math.pi)``. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.left(90) +@@ -785,7 +756,6 @@ Settings for measurement + 1.5707963267948966 + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.degrees(360) +@@ -821,7 +791,6 @@ Drawing state + thickness. If no argument is given, the current pensize is returned. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.pensize() + 1 +@@ -853,7 +822,6 @@ Drawing state + attributes in one statement. + + .. doctest:: +- :skipif: _tkinter is None + :options: +NORMALIZE_WHITESPACE + + >>> turtle.pen(fillcolor="black", pencolor="red", pensize=10) +@@ -876,7 +844,6 @@ Drawing state + Return ``True`` if pen is down, ``False`` if it's up. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.penup() + >>> turtle.isdown() +@@ -917,7 +884,6 @@ Color control + newly set pencolor. + + .. doctest:: +- :skipif: _tkinter is None + + >>> colormode() + 1.0 +@@ -966,7 +932,6 @@ Color control + with the newly set fillcolor. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.fillcolor("violet") + >>> turtle.fillcolor() +@@ -1005,7 +970,6 @@ Color control + with the newly set colors. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.color("red", "green") + >>> turtle.color() +@@ -1022,7 +986,6 @@ Filling + ~~~~~~~ + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> turtle.home() +@@ -1032,7 +995,6 @@ Filling + Return fillstate (``True`` if filling, ``False`` else). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.begin_fill() + >>> if turtle.filling(): +@@ -1057,7 +1019,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() +@@ -1074,7 +1035,6 @@ More drawing control + variables to the default values. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.goto(0,-22) + >>> turtle.left(100) +@@ -1125,7 +1085,6 @@ Visibility + drawing observably. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.hideturtle() + +@@ -1136,7 +1095,6 @@ Visibility + Make the turtle visible. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.showturtle() + +@@ -1167,7 +1125,6 @@ Appearance + deal with shapes see Screen method :func:`register_shape`. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.shape() + 'classic' +@@ -1193,7 +1150,6 @@ Appearance + ``resizemode("user")`` is called by :func:`shapesize` when used with arguments. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.resizemode() + 'noresize' +@@ -1217,7 +1173,6 @@ Appearance + of the shapes's outline. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.shapesize() + (1.0, 1.0, 1) +@@ -1242,7 +1197,6 @@ Appearance + heading of the turtle are sheared. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.shape("circle") + >>> turtle.shapesize(5,2) +@@ -1259,7 +1213,6 @@ Appearance + change the turtle's heading (direction of movement). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.reset() + >>> turtle.shape("circle") +@@ -1279,7 +1232,6 @@ Appearance + (direction of movement). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.reset() + >>> turtle.shape("circle") +@@ -1305,7 +1257,6 @@ Appearance + turtle (its direction of movement). + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.reset() + >>> turtle.shape("circle") +@@ -1334,7 +1285,6 @@ Appearance + given matrix. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle = Turtle() + >>> turtle.shape("square") +@@ -1350,7 +1300,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) +@@ -1375,7 +1324,6 @@ Using events + procedural way: + + .. doctest:: +- :skipif: _tkinter is None + + >>> def turn(x, y): + ... left(180) +@@ -1396,7 +1344,6 @@ Using events + ``None``, existing bindings are removed. + + .. doctest:: +- :skipif: _tkinter is None + + >>> class MyTurtle(Turtle): + ... def glow(self,x,y): +@@ -1424,7 +1371,6 @@ Using events + mouse-click event on that turtle. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.ondrag(turtle.goto) + +@@ -1452,7 +1398,6 @@ Special Turtle methods + Return the last recorded polygon. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.home() + >>> turtle.begin_poly() +@@ -1472,7 +1417,6 @@ Special Turtle methods + turtle properties. + + .. doctest:: +- :skipif: _tkinter is None + + >>> mick = Turtle() + >>> joe = mick.clone() +@@ -1485,7 +1429,6 @@ Special Turtle methods + return the "anonymous turtle": + + .. doctest:: +- :skipif: _tkinter is None + + >>> pet = getturtle() + >>> pet.fd(50) +@@ -1499,7 +1442,6 @@ Special Turtle methods + TurtleScreen methods can then be called for that object. + + .. doctest:: +- :skipif: _tkinter is None + + >>> ts = turtle.getscreen() + >>> ts +@@ -1517,7 +1459,6 @@ Special Turtle methods + ``None``, the undobuffer is disabled. + + .. doctest:: +- :skipif: _tkinter is None + + >>> turtle.setundobuffer(42) + +@@ -1527,7 +1468,6 @@ Special Turtle methods + Return number of entries in the undobuffer. + + .. doctest:: +- :skipif: _tkinter is None + + >>> while undobufferentries(): + ... undo() +@@ -1550,7 +1490,6 @@ below: + For example: + + .. doctest:: +- :skipif: _tkinter is None + + >>> s = Shape("compound") + >>> poly1 = ((0,0),(10,-5),(0,10),(-10,-5)) +@@ -1561,7 +1500,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") +@@ -1581,7 +1519,6 @@ Most of the examples in this section ref + ``screen``. + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> screen = Screen() +@@ -1598,7 +1535,6 @@ Window control + Set or return background color of the TurtleScreen. + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.bgcolor("orange") + >>> screen.bgcolor() +@@ -1690,7 +1626,6 @@ Window control + distorted. + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.reset() + >>> screen.setworldcoordinates(-50,-7.5,50,7.5) +@@ -1701,7 +1636,6 @@ Window control + ... left(45); fd(2) # a regular octagon + + .. doctest:: +- :skipif: _tkinter is None + :hide: + + >>> screen.reset() +@@ -1723,7 +1657,6 @@ Animation control + Optional argument: + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.delay() + 10 +@@ -1745,7 +1678,6 @@ Animation control + :func:`delay`). + + .. doctest:: +- :skipif: _tkinter is None + + >>> screen.tracer(8, 25) + >>> dist = 2 +@@ -1782,7 +1714,6 @@ Using screen events + must have the focus. (See method :func:`listen`.) + + .. doctest:: +- :skipif: _tkinter is None + + >>> def f(): + ... fd(50) +@@ -1803,7 +1734,6 @@ Using screen events + must have focus. (See method :func:`listen`.) + + .. doctest:: +- :skipif: _tkinter is None + + >>> def f(): + ... fd(50) +@@ -1828,7 +1758,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. +@@ -1848,7 +1777,6 @@ Using screen events + Install a timer that calls *fun* after *t* milliseconds. + + .. doctest:: +- :skipif: _tkinter is None + + >>> running = True + >>> def f(): +@@ -1930,7 +1858,6 @@ Settings and special methods + ============ ========================= =================== + + .. doctest:: +- :skipif: _tkinter is None + + >>> mode("logo") # resets turtle heading to north + >>> mode() +@@ -1945,7 +1872,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) +@@ -1966,7 +1892,6 @@ Settings and special methods + do with a Tkinter Canvas. + + .. doctest:: +- :skipif: _tkinter is None + + >>> cv = screen.getcanvas() + >>> cv +@@ -1978,7 +1903,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'] +@@ -2002,7 +1926,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))) + +@@ -2018,7 +1941,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") +@@ -2080,7 +2002,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 +@@ -2096,7 +2017,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!") + +@@ -2167,7 +2087,6 @@ Public classes + Example: + + .. doctest:: +- :skipif: _tkinter is None + + >>> poly = ((0,0),(10,-5),(0,10),(-10,-5)) + >>> s = Shape("compound") +@@ -2514,7 +2433,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..f69846f --- /dev/null +++ b/python-3.3.0b1-fix_date_time_compiler.patch @@ -0,0 +1,25 @@ +--- + Makefile.pre.in | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -784,11 +784,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 Makefile + $(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..f527f1f --- /dev/null +++ b/python-3.3.0b1-localpath.patch @@ -0,0 +1,15 @@ +--- + Lib/site.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/Lib/site.py ++++ b/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/python310-rpmlintrc b/python310-rpmlintrc new file mode 100644 index 0000000..92241ae --- /dev/null +++ b/python310-rpmlintrc @@ -0,0 +1 @@ +addFilter("pem-certificate.*/usr/lib.*/python.*/test/*.pem") diff --git a/python310.changes b/python310.changes new file mode 100644 index 0000000..6568b0b --- /dev/null +++ b/python310.changes @@ -0,0 +1,4523 @@ +------------------------------------------------------------------- +Wed Oct 15 08:43:33 UTC 2025 - Daniel Garcia + +- Update to 3.10.19: + - 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