forked from pool/python312
- Require AppStream to validate appdata file instead of deprecated
appstream-glib. - Update idle3.appdata.xml to pass the more pedantic appstreamcli. OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python312?expand=0&rev=158
This commit is contained in:
23
.gitattributes
vendored
Normal file
23
.gitattributes
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
## Default LFS
|
||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
*.bsp filter=lfs diff=lfs merge=lfs -text
|
||||
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.gem filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.jar filter=lfs diff=lfs merge=lfs -text
|
||||
*.lz filter=lfs diff=lfs merge=lfs -text
|
||||
*.lzma filter=lfs diff=lfs merge=lfs -text
|
||||
*.obscpio filter=lfs diff=lfs merge=lfs -text
|
||||
*.oxt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.rpm filter=lfs diff=lfs merge=lfs -text
|
||||
*.tbz filter=lfs diff=lfs merge=lfs -text
|
||||
*.tbz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
*.txz filter=lfs diff=lfs merge=lfs -text
|
||||
*.whl filter=lfs diff=lfs merge=lfs -text
|
||||
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.zst filter=lfs diff=lfs merge=lfs -text
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.osc
|
||||
237
CVE-2025-6069-quad-complex-HTMLParser.patch
Normal file
237
CVE-2025-6069-quad-complex-HTMLParser.patch
Normal file
@@ -0,0 +1,237 @@
|
||||
From 1d53c3e7343bddb064182e02c21b13be9b63390f Mon Sep 17 00:00:00 2001
|
||||
From: Serhiy Storchaka <storchaka@gmail.com>
|
||||
Date: Fri, 13 Jun 2025 19:57:48 +0300
|
||||
Subject: [PATCH] [3.12] 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 <storchaka@gmail.com>
|
||||
---
|
||||
Lib/html/parser.py | 41 +++-
|
||||
Lib/test/test_htmlparser.py | 94 ++++++++--
|
||||
Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst | 4
|
||||
3 files changed, 116 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.12.11/Lib/html/parser.py
|
||||
===================================================================
|
||||
--- Python-3.12.11.orig/Lib/html/parser.py 2025-07-02 17:09:00.904899297 +0200
|
||||
+++ Python-3.12.11/Lib/html/parser.py 2025-07-02 17:09:12.496469955 +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('</[a-zA-Z]')
|
||||
piclose = re.compile('>')
|
||||
commentclose = re.compile(r'--\s*>')
|
||||
# Note:
|
||||
@@ -177,7 +178,7 @@
|
||||
k = self.parse_pi(i)
|
||||
elif startswith("<!", i):
|
||||
k = self.parse_html_declaration(i)
|
||||
- elif (i + 1) < n:
|
||||
+ elif (i + 1) < n or end:
|
||||
self.handle_data("<")
|
||||
k = i + 1
|
||||
else:
|
||||
@@ -185,17 +186,35 @@
|
||||
if k < 0:
|
||||
if not end:
|
||||
break
|
||||
- k = rawdata.find('>', 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("</", i):
|
||||
+ if i + 2 == n:
|
||||
+ self.handle_data("</")
|
||||
+ elif endtagopen.match(rawdata, i): # </ + letter
|
||||
+ pass
|
||||
+ else:
|
||||
+ # bogus comment
|
||||
+ self.handle_comment(rawdata[i+2:])
|
||||
+ elif startswith("<!--", i):
|
||||
+ j = n
|
||||
+ for suffix in ("--!", "--", "-"):
|
||||
+ if rawdata.endswith(suffix, i+4):
|
||||
+ j -= len(suffix)
|
||||
+ break
|
||||
+ self.handle_comment(rawdata[i+4:j])
|
||||
+ elif startswith("<![CDATA[", i):
|
||||
+ self.unknown_decl(rawdata[i+3:])
|
||||
+ elif rawdata[i:i+9].lower() == '<!doctype':
|
||||
+ self.handle_decl(rawdata[i+2:])
|
||||
+ elif startswith("<!", i):
|
||||
+ # bogus comment
|
||||
+ self.handle_comment(rawdata[i+2:])
|
||||
+ elif startswith("<?", i):
|
||||
+ self.handle_pi(rawdata[i+2:])
|
||||
else:
|
||||
- k += 1
|
||||
- if self.convert_charrefs and not self.cdata_elem:
|
||||
- self.handle_data(unescape(rawdata[i:k]))
|
||||
- else:
|
||||
- self.handle_data(rawdata[i:k])
|
||||
+ raise AssertionError("we should not get here!")
|
||||
+ k = n
|
||||
i = self.updatepos(i, k)
|
||||
elif startswith("&#", i):
|
||||
match = charref.match(rawdata, i)
|
||||
Index: Python-3.12.11/Lib/test/test_htmlparser.py
|
||||
===================================================================
|
||||
--- Python-3.12.11.orig/Lib/test/test_htmlparser.py 2025-07-02 17:09:02.385825386 +0200
|
||||
+++ Python-3.12.11/Lib/test/test_htmlparser.py 2025-07-02 17:09:12.496693449 +0200
|
||||
@@ -5,6 +5,7 @@
|
||||
import unittest
|
||||
|
||||
from unittest.mock import patch
|
||||
+from test import support
|
||||
|
||||
|
||||
class EventCollector(html.parser.HTMLParser):
|
||||
@@ -393,28 +394,34 @@
|
||||
('data', '<'),
|
||||
('starttag', 'bc<', [('a', None)]),
|
||||
('endtag', 'html'),
|
||||
- ('data', '\n<img src="URL>'),
|
||||
- ('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("</", [('data', '</')])
|
||||
- self._run_check("</a", [('data', '</a')])
|
||||
+ self._run_check("</a", [])
|
||||
+ self._run_check("</ a>", [('endtag', 'a')])
|
||||
+ self._run_check("</ a", [('comment', ' a')])
|
||||
self._run_check("<a<a>", [('starttag', 'a<a', [])])
|
||||
self._run_check("</a<a>", [('endtag', 'a<a')])
|
||||
- self._run_check("<!", [('data', '<!')])
|
||||
- self._run_check("<a", [('data', '<a')])
|
||||
- self._run_check("<a foo='bar'", [('data', "<a foo='bar'")])
|
||||
- self._run_check("<a foo='bar", [('data', "<a foo='bar")])
|
||||
- self._run_check("<a foo='>'", [('data', "<a foo='>'")])
|
||||
- self._run_check("<a foo='>", [('data', "<a foo='>")])
|
||||
+ self._run_check("<!", [('comment', '')])
|
||||
+ self._run_check("<a", [])
|
||||
+ self._run_check("<a foo='bar'", [])
|
||||
+ self._run_check("<a foo='bar", [])
|
||||
+ self._run_check("<a foo='>'", [])
|
||||
+ self._run_check("<a foo='>", [])
|
||||
self._run_check("<a$>", [('starttag', 'a$', [])])
|
||||
self._run_check("<a$b>", [('starttag', 'a$b', [])])
|
||||
self._run_check("<a$b/>", [('startendtag', 'a$b', [])])
|
||||
self._run_check("<a$b >", [('starttag', 'a$b', [])])
|
||||
self._run_check("<a$b />", [('startendtag', 'a$b', [])])
|
||||
+ self._run_check("</a$b>", [('endtag', 'a$b')])
|
||||
|
||||
def test_slashes_in_starttag(self):
|
||||
self._run_check('<a foo="var"/>', [('startendtag', 'a', [('foo', 'var')])])
|
||||
@@ -539,13 +546,56 @@
|
||||
for html, expected in data:
|
||||
self._run_check(html, expected)
|
||||
|
||||
- def test_broken_comments(self):
|
||||
- html = ('<! not really a comment >'
|
||||
+ def test_eof_in_comments(self):
|
||||
+ data = [
|
||||
+ ('<!--', [('comment', '')]),
|
||||
+ ('<!---', [('comment', '')]),
|
||||
+ ('<!----', [('comment', '')]),
|
||||
+ ('<!-----', [('comment', '-')]),
|
||||
+ ('<!------', [('comment', '--')]),
|
||||
+ ('<!----!', [('comment', '')]),
|
||||
+ ('<!---!', [('comment', '-!')]),
|
||||
+ ('<!---!>', [('comment', '-!>')]),
|
||||
+ ('<!--foo', [('comment', 'foo')]),
|
||||
+ ('<!--foo-', [('comment', 'foo')]),
|
||||
+ ('<!--foo--', [('comment', 'foo')]),
|
||||
+ ('<!--foo--!', [('comment', 'foo')]),
|
||||
+ ('<!--<!--', [('comment', '<!')]),
|
||||
+ ('<!--<!--!', [('comment', '<!')]),
|
||||
+ ]
|
||||
+ for html, expected in data:
|
||||
+ self._run_check(html, expected)
|
||||
+
|
||||
+ def test_eof_in_declarations(self):
|
||||
+ data = [
|
||||
+ ('<!', [('comment', '')]),
|
||||
+ ('<!-', [('comment', '-')]),
|
||||
+ ('<![', [('comment', '[')]),
|
||||
+ ('<![CDATA[', [('unknown decl', 'CDATA[')]),
|
||||
+ ('<![CDATA[x', [('unknown decl', 'CDATA[x')]),
|
||||
+ ('<![CDATA[x]', [('unknown decl', 'CDATA[x]')]),
|
||||
+ ('<![CDATA[x]]', [('unknown decl', 'CDATA[x]]')]),
|
||||
+ ('<!DOCTYPE', [('decl', 'DOCTYPE')]),
|
||||
+ ('<!DOCTYPE ', [('decl', 'DOCTYPE ')]),
|
||||
+ ('<!DOCTYPE html', [('decl', 'DOCTYPE html')]),
|
||||
+ ('<!DOCTYPE html ', [('decl', 'DOCTYPE html ')]),
|
||||
+ ('<!DOCTYPE html PUBLIC', [('decl', 'DOCTYPE html PUBLIC')]),
|
||||
+ ('<!DOCTYPE html PUBLIC "foo', [('decl', 'DOCTYPE html PUBLIC "foo')]),
|
||||
+ ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "foo',
|
||||
+ [('decl', 'DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "foo')]),
|
||||
+ ]
|
||||
+ for html, expected in data:
|
||||
+ self._run_check(html, expected)
|
||||
+
|
||||
+ def test_bogus_comments(self):
|
||||
+ html = ('<!ELEMENT br EMPTY>'
|
||||
+ '<! not really a comment >'
|
||||
'<! not a comment either -->'
|
||||
'<! -- close enough -->'
|
||||
'<!><!<-- this was an empty comment>'
|
||||
'<!!! another bogus comment !!!>')
|
||||
expected = [
|
||||
+ ('comment', 'ELEMENT br EMPTY'),
|
||||
('comment', ' not really a comment '),
|
||||
('comment', ' not a comment either --'),
|
||||
('comment', ' -- close enough --'),
|
||||
@@ -600,6 +650,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("<a " * n)
|
||||
+ check("<a a=" * n)
|
||||
+ check("</a " * 14 * n)
|
||||
+ check("</a a=" * 11 * n)
|
||||
+ check("<!--" * 4 * n)
|
||||
+ check("<!" * 60 * n)
|
||||
+ check("<?" * 19 * n)
|
||||
+ check("</$" * 15 * n)
|
||||
+ check("<![CDATA[" * 9 * n)
|
||||
+ check("<!doctype" * 35 * n)
|
||||
+
|
||||
|
||||
class AttributesTestCase(TestCaseBase):
|
||||
|
||||
Index: Python-3.12.11/Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ Python-3.12.11/Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst 2025-07-02 17:09:12.496947674 +0200
|
||||
@@ -0,0 +1,4 @@
|
||||
+Fix quadratic complexity in processing specially crafted input in
|
||||
+:class:`html.parser.HTMLParser`. End-of-file errors are now handled according
|
||||
+to the HTML5 specs -- comments and declarations are automatically closed,
|
||||
+tags are ignored.
|
||||
212
CVE-2025-8194-tarfile-no-neg-offsets.patch
Normal file
212
CVE-2025-8194-tarfile-no-neg-offsets.patch
Normal file
@@ -0,0 +1,212 @@
|
||||
From 8f381056d7364b6771b3dce3ebe54dd9f675811b Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Urieles <aeurielesn@users.noreply.github.com>
|
||||
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 <aeurielesn@users.noreply.github.com>
|
||||
Co-authored-by: Gregory P. Smith <greg@krypto.org>
|
||||
---
|
||||
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.12.11/Lib/tarfile.py
|
||||
===================================================================
|
||||
--- Python-3.12.11.orig/Lib/tarfile.py 2025-08-01 22:20:38.061933888 +0200
|
||||
+++ Python-3.12.11/Lib/tarfile.py 2025-08-01 22:20:42.185990406 +0200
|
||||
@@ -1614,6 +1614,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.12.11/Lib/test/test_tarfile.py
|
||||
===================================================================
|
||||
--- Python-3.12.11.orig/Lib/test/test_tarfile.py 2025-08-01 22:20:39.792514772 +0200
|
||||
+++ Python-3.12.11/Lib/test/test_tarfile.py 2025-08-01 22:20:42.187347433 +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"
|
||||
@@ -4488,6 +4489,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.12.11/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.12.11/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst 2025-08-01 22:20:42.187819145 +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`.)
|
||||
160
F00251-change-user-install-location.patch
Normal file
160
F00251-change-user-install-location.patch
Normal file
@@ -0,0 +1,160 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
|
||||
Date: Mon, 15 Feb 2021 12:19:27 +0100
|
||||
Subject: [PATCH] 00251: Change user install location
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Set values of base and platbase in sysconfig from /usr
|
||||
to /usr/local when RPM build is not detected
|
||||
to make pip and similar tools install into separate location.
|
||||
|
||||
Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
Downstream only.
|
||||
|
||||
We've tried to rework in Fedora 36/Python 3.10 to follow https://bugs.python.org/issue43976
|
||||
but we have identified serious problems with that approach,
|
||||
see https://bugzilla.redhat.com/2026979 or https://bugzilla.redhat.com/2097183
|
||||
|
||||
pypa/distutils integration: https://github.com/pypa/distutils/pull/70
|
||||
|
||||
Co-authored-by: Petr Viktorin <encukou@gmail.com>
|
||||
Co-authored-by: Miro Hrončok <miro@hroncok.cz>
|
||||
Co-authored-by: Michal Cyprian <m.cyprian@gmail.com>
|
||||
Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
||||
---
|
||||
Lib/sysconfig.py | 51 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
Lib/test/test_sysconfig.py | 17 +++++++++++++--
|
||||
2 files changed, 65 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: Python-3.12.10/Lib/sysconfig.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Lib/sysconfig.py 2025-04-11 21:04:43.494305425 +0200
|
||||
+++ Python-3.12.10/Lib/sysconfig.py 2025-04-11 21:04:51.517931810 +0200
|
||||
@@ -104,6 +104,11 @@
|
||||
else:
|
||||
_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv']
|
||||
|
||||
+# For a brief period of time in the Fedora 36 life cycle,
|
||||
+# this installation scheme existed and was documented in the release notes.
|
||||
+# For backwards compatibility, we keep it here (at least on 3.10 and 3.11).
|
||||
+_INSTALL_SCHEMES['rpm_prefix'] = _INSTALL_SCHEMES['posix_prefix']
|
||||
+
|
||||
|
||||
# NOTE: site.py has copy of this function.
|
||||
# Sync it when modify this function.
|
||||
@@ -163,13 +168,28 @@
|
||||
},
|
||||
}
|
||||
|
||||
+# This is used by distutils.command.install in the stdlib
|
||||
+# as well as pypa/distutils (e.g. bundled in setuptools).
|
||||
+# The self.prefix value is set to sys.prefix + /local/
|
||||
+# if neither RPM build nor virtual environment is
|
||||
+# detected to make distutils install packages
|
||||
+# into the separate location.
|
||||
+# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
+if (not (hasattr(sys, 'real_prefix') or
|
||||
+ sys.prefix != sys.base_prefix) and
|
||||
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||
+ _prefix_addition = '/local'
|
||||
+
|
||||
+
|
||||
_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
|
||||
'scripts', 'data')
|
||||
|
||||
_PY_VERSION = sys.version.split()[0]
|
||||
_PY_VERSION_SHORT = f'{sys.version_info[0]}.{sys.version_info[1]}'
|
||||
_PY_VERSION_SHORT_NO_DOT = f'{sys.version_info[0]}{sys.version_info[1]}'
|
||||
+_PREFIX = os.path.normpath(sys.prefix)
|
||||
_BASE_PREFIX = os.path.normpath(sys.base_prefix)
|
||||
+_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
|
||||
_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
|
||||
# Mutex guarding initialization of _CONFIG_VARS.
|
||||
_CONFIG_VARS_LOCK = threading.RLock()
|
||||
@@ -268,11 +288,40 @@
|
||||
target_dict[key] = value
|
||||
|
||||
|
||||
+_CONFIG_VARS_LOCAL = None
|
||||
+
|
||||
+
|
||||
+def _config_vars_local():
|
||||
+ # This function returns the config vars with prefixes amended to /usr/local
|
||||
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
+ global _CONFIG_VARS_LOCAL
|
||||
+ if _CONFIG_VARS_LOCAL is None:
|
||||
+ _CONFIG_VARS_LOCAL = dict(get_config_vars())
|
||||
+ _CONFIG_VARS_LOCAL['base'] = '/usr/local'
|
||||
+ _CONFIG_VARS_LOCAL['platbase'] = '/usr/local'
|
||||
+ return _CONFIG_VARS_LOCAL
|
||||
+
|
||||
+
|
||||
def _expand_vars(scheme, vars):
|
||||
res = {}
|
||||
if vars is None:
|
||||
vars = {}
|
||||
- _extend_dict(vars, get_config_vars())
|
||||
+
|
||||
+ # when we are not in a virtual environment or an RPM build
|
||||
+ # we change '/usr' to '/usr/local'
|
||||
+ # to avoid surprises, we explicitly check for the /usr/ prefix
|
||||
+ # Python virtual environments have different prefixes
|
||||
+ # we only do this for posix_prefix, not to mangle the venv scheme
|
||||
+ # posix_prefix is used by sudo pip install
|
||||
+ # we only change the defaults here, so explicit --prefix will take precedence
|
||||
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
+ if (scheme == 'posix_prefix' and
|
||||
+ _PREFIX == '/usr' and
|
||||
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||
+ _extend_dict(vars, _config_vars_local())
|
||||
+ else:
|
||||
+ _extend_dict(vars, get_config_vars())
|
||||
+
|
||||
if os.name == 'nt':
|
||||
# On Windows we want to substitute 'lib' for schemes rather
|
||||
# than the native value (without modifying vars, in case it
|
||||
Index: Python-3.12.10/Lib/test/test_sysconfig.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Lib/test/test_sysconfig.py 2025-04-11 21:04:45.175417431 +0200
|
||||
+++ Python-3.12.10/Lib/test/test_sysconfig.py 2025-04-11 21:04:51.518393464 +0200
|
||||
@@ -119,8 +119,19 @@
|
||||
for scheme in _INSTALL_SCHEMES:
|
||||
for name in _INSTALL_SCHEMES[scheme]:
|
||||
expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
|
||||
+ tested = get_path(name, scheme)
|
||||
+ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||
+ if tested.startswith('/usr/local'):
|
||||
+ # /usr/local should only be used in posix_prefix
|
||||
+ self.assertEqual(scheme, 'posix_prefix')
|
||||
+ # Fedora CI runs tests for venv and virtualenv that check for other prefixes
|
||||
+ self.assertEqual(sys.prefix, '/usr')
|
||||
+ # When building the RPM of Python, %check runs this with RPM_BUILD_ROOT set
|
||||
+ # Fedora CI runs this with RPM_BUILD_ROOT unset
|
||||
+ self.assertNotIn('RPM_BUILD_ROOT', os.environ)
|
||||
+ tested = tested.replace('/usr/local', '/usr')
|
||||
self.assertEqual(
|
||||
- os.path.normpath(get_path(name, scheme)),
|
||||
+ os.path.normpath(tested),
|
||||
os.path.normpath(expected),
|
||||
)
|
||||
|
||||
@@ -353,7 +364,7 @@
|
||||
self.assertTrue(os.path.isfile(config_h), config_h)
|
||||
|
||||
def test_get_scheme_names(self):
|
||||
- wanted = ['nt', 'posix_home', 'posix_prefix', 'posix_venv', 'nt_venv', 'venv']
|
||||
+ wanted = ['nt', 'posix_home', 'posix_prefix', 'posix_venv', 'nt_venv', 'venv', 'rpm_prefix']
|
||||
if HAS_USER_BASE:
|
||||
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
|
||||
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
|
||||
@@ -365,6 +376,8 @@
|
||||
cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
|
||||
self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
|
||||
|
||||
+ @unittest.skipIf('RPM_BUILD_ROOT' not in os.environ,
|
||||
+ "Test doesn't expect Fedora's paths")
|
||||
def test_user_similar(self):
|
||||
# Issue #8759: make sure the posix scheme for the users
|
||||
# is similar to the global posix_prefix one
|
||||
26
PACKAGING-NOTES
Normal file
26
PACKAGING-NOTES
Normal file
@@ -0,0 +1,26 @@
|
||||
Notes for packagers of Python3
|
||||
==============================
|
||||
|
||||
0. Faster build turnaround
|
||||
--------------------------
|
||||
|
||||
By default, python builds with profile-guided optimization. This needs
|
||||
an additional run of the test suite and it is generally slow.
|
||||
PGO build takes around 50 minutes.
|
||||
|
||||
For development, use "--without profileopt" option to disable PGO. This
|
||||
shortens the build time to ~5 minutes including test suite.
|
||||
|
||||
1. import_failed.map
|
||||
----------------------
|
||||
|
||||
This is a mechanism installed as part of python3-base, that places shim modules
|
||||
on python's path (through a generated zzzz-import-failed-hooks.pth file, so that
|
||||
it is imported as much at the end as makes sense; and an _import_failed subdir
|
||||
of /usr/lib/pythonX.Y). Then when the user tries to import a module that is part
|
||||
of a subpackage, the ImportError will contain a helpful message telling them
|
||||
which missing subpackage to install.
|
||||
|
||||
This can sometimes cause problems on non-standard configurations, if the pth
|
||||
gets included too early (for instance if you are using a script to include all
|
||||
pths by hand in some strange order). Just something to look out for.
|
||||
BIN
Python-3.12.11.tar.xz
(Stored with Git LFS)
Normal file
BIN
Python-3.12.11.tar.xz
(Stored with Git LFS)
Normal file
Binary file not shown.
18
Python-3.12.11.tar.xz.asc
Normal file
18
Python-3.12.11.tar.xz.asc
Normal file
@@ -0,0 +1,18 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQKTBAABCgB9FiEEcWlgX2LHUTVtBUomqCHmgOX6YwUFAmg/MbpfFIAAAAAALgAo
|
||||
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDcx
|
||||
Njk2MDVGNjJDNzUxMzU2RDA1NEEyNkE4MjFFNjgwRTVGQTYzMDUACgkQqCHmgOX6
|
||||
YwXySQ/7Ba9qlnTLmxqTCO8C7Gf545WNMBL2Ep6JZPgjOcgNk9e1QdAnNV5OOtGm
|
||||
gW5nNPSTNNcIcPn058GuI24D4RpTQCJfMbMLsfYgvio0E7ij1gC19PsJHb6ejtCS
|
||||
H2kK237Y1kuqRUdbTZssFDoAR4R9+UCaDuo4XdW+UKQk2GgdNQDMWLKmWF/Xk6Ob
|
||||
/LihMXj27mDU9nXVdWR55sJzTFzfGB015vmORvcpuctkf1lZ4AfVFMgGw1CgjRjF
|
||||
kjrOkrDErjDUQ8BIhMh90deiTpigfg7cg1HBDI6GRzklFg6cMfIdfvmfM0MfamX3
|
||||
Tow08TGBzmYXWgrqjYXW6JknKhBGOrjXMB7/yNDk9bJVLcOJaLbOmbcG0WRQF/Py
|
||||
DMOCvr09l0yt5KFYpdKrDvyCuKYfpX33B4C60kU9JzmfXGyQ6LDTPXapZooJ+8Fg
|
||||
GRTUsc0YWXoaDVCcxMIdiG+jEMQkjWVwW7E/nC/d7WT5L9KPoYFA1sZ834kKq3jr
|
||||
NmZynbBnKH7m7L+u6HP6B+pa84FKEME69osAXZk0HJOIHB+SOX3E6BXRo6IV8Q/K
|
||||
J6f5Ja26gJ7KXcUxTgkTkYh7tz0bhb+WeL3j6N/BC0eK7ZVsKRZ/3WnntGsG5B2m
|
||||
FjVOYKolfkF4tf63SjdFuudgaKGCaDK1PvfwIr7k0oozxrB2ZEA=
|
||||
=SYH/
|
||||
-----END PGP SIGNATURE-----
|
||||
1
Python-3.12.11.tar.xz.sigstore
Normal file
1
Python-3.12.11.tar.xz.sigstore
Normal file
File diff suppressed because one or more lines are too long
43
README.SUSE
Normal file
43
README.SUSE
Normal file
@@ -0,0 +1,43 @@
|
||||
Python 3 in SUSE
|
||||
==============
|
||||
|
||||
* Subpackages *
|
||||
|
||||
Python 3 is split into several subpackages, based on external dependencies.
|
||||
The main package 'python3' has soft dependencies on all subpackages needed to
|
||||
assemble the standard library; however, these might not all be installed by default.
|
||||
|
||||
If you attempt to import a module that is currently not installed, an ImportError is thrown,
|
||||
with instructions to install the missing subpackage. Installing the subpackage might result
|
||||
in installing libraries that the subpackage requires to function.
|
||||
|
||||
|
||||
* ensurepip *
|
||||
|
||||
The 'ensurepip' module from Python 3 standard library (PEP 453) is supposed to deploy
|
||||
a bundled copy of the pip installer. This makes no sense in a managed distribution like SUSE.
|
||||
Instead, you need to install package 'python3-pip'. Usually this will be installed automatically
|
||||
with 'python3'.
|
||||
|
||||
Using 'ensurepip' when pip is not installed will result in an ImportError with instructions
|
||||
to install 'python3-pip'.
|
||||
|
||||
|
||||
* Documentation *
|
||||
|
||||
You can find documentation in seprarate packages: python3-doc and
|
||||
python3-doc-pdf. These contan following documents:
|
||||
|
||||
Tutorial, What's New in Python, Global Module Index, Library Reference,
|
||||
Macintosh Module Reference, Installing Python Modules, Distributing Python
|
||||
Modules, Language Reference, Extending and Embedding, Python/C API,
|
||||
Documenting Python
|
||||
|
||||
The python3-doc package constains many text files from source tarball.
|
||||
|
||||
|
||||
* Interactive mode *
|
||||
|
||||
Interactive mode is by default enhanced with of history and command completion.
|
||||
If you don't like these features, you can unset the PYTHONSTARTUP variable
|
||||
in your .profile or disable it system wide in /etc/profile.d/python.sh.
|
||||
4
_multibuild
Normal file
4
_multibuild
Normal file
@@ -0,0 +1,4 @@
|
||||
<multibuild>
|
||||
<package>base</package>
|
||||
<package>doc</package>
|
||||
</multibuild>
|
||||
3
baselibs.conf
Normal file
3
baselibs.conf
Normal file
@@ -0,0 +1,3 @@
|
||||
python312-base
|
||||
python312
|
||||
libpython3_12-1_0
|
||||
BIN
bluez-devel-vendor.tar.xz
(Stored with Git LFS)
Normal file
BIN
bluez-devel-vendor.tar.xz
(Stored with Git LFS)
Normal file
Binary file not shown.
175
bpo-31046_ensurepip_honours_prefix.patch
Normal file
175
bpo-31046_ensurepip_honours_prefix.patch
Normal file
@@ -0,0 +1,175 @@
|
||||
From 5754521af1d51aa8e445cba07a093bbc0c88596d Mon Sep 17 00:00:00 2001
|
||||
From: Zackery Spytz <zspytz@gmail.com>
|
||||
Date: Mon, 16 Dec 2019 18:24:08 -0700
|
||||
Subject: [PATCH] bpo-31046: ensurepip does not honour the value of $(prefix)
|
||||
|
||||
Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
|
||||
---
|
||||
Doc/library/ensurepip.rst | 12 +++++-
|
||||
Lib/ensurepip/__init__.py | 18 +++++++---
|
||||
Lib/test/test_ensurepip.py | 11 ++++++
|
||||
Makefile.pre.in | 4 +-
|
||||
Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst | 1
|
||||
5 files changed, 37 insertions(+), 9 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst
|
||||
|
||||
Index: Python-3.12.10/Doc/library/ensurepip.rst
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/library/ensurepip.rst 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/library/ensurepip.rst 2025-04-11 21:16:06.140273604 +0200
|
||||
@@ -61,7 +61,11 @@
|
||||
By default, ``pip`` is installed into the current virtual environment
|
||||
(if one is active) or into the system site packages (if there is no
|
||||
active virtual environment). The installation location can be controlled
|
||||
-through two additional command line options:
|
||||
+through some additional command line options:
|
||||
+
|
||||
+.. option:: --prefix <dir>
|
||||
+
|
||||
+ Installs ``pip`` using the given directory prefix.
|
||||
|
||||
.. option:: --root <dir>
|
||||
|
||||
@@ -102,7 +106,7 @@
|
||||
Returns a string specifying the available version of pip that will be
|
||||
installed when bootstrapping an environment.
|
||||
|
||||
-.. function:: bootstrap(root=None, upgrade=False, user=False, \
|
||||
+.. function:: bootstrap(root=None, prefix=None, upgrade=False, user=False, \
|
||||
altinstall=False, default_pip=False, \
|
||||
verbosity=0)
|
||||
|
||||
@@ -112,6 +116,8 @@
|
||||
If *root* is ``None``, then installation uses the default install location
|
||||
for the current environment.
|
||||
|
||||
+ *prefix* specifies the directory prefix to use when installing.
|
||||
+
|
||||
*upgrade* indicates whether or not to upgrade an existing installation
|
||||
of an earlier version of ``pip`` to the available version.
|
||||
|
||||
@@ -132,6 +138,8 @@
|
||||
*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.12.10/Lib/ensurepip/__init__.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Lib/ensurepip/__init__.py 2025-04-11 21:04:42.789443156 +0200
|
||||
+++ Python-3.12.10/Lib/ensurepip/__init__.py 2025-04-11 21:13:01.303399067 +0200
|
||||
@@ -120,27 +120,27 @@
|
||||
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.
|
||||
"""
|
||||
@@ -190,6 +190,8 @@
|
||||
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:
|
||||
@@ -265,6 +267,11 @@
|
||||
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,
|
||||
@@ -283,6 +290,7 @@
|
||||
|
||||
return _bootstrap(
|
||||
root=args.root,
|
||||
+ prefix=args.prefix,
|
||||
upgrade=args.upgrade,
|
||||
user=args.user,
|
||||
verbosity=args.verbosity,
|
||||
Index: Python-3.12.10/Lib/test/test_ensurepip.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Lib/test/test_ensurepip.py 2025-04-11 21:04:44.274413027 +0200
|
||||
+++ Python-3.12.10/Lib/test/test_ensurepip.py 2025-04-11 21:13:01.303691075 +0200
|
||||
@@ -105,6 +105,17 @@
|
||||
unittest.mock.ANY,
|
||||
)
|
||||
|
||||
+ def test_bootstrapping_with_prefix(self):
|
||||
+ ensurepip.bootstrap(prefix="/foo/bar/")
|
||||
+ self.run_pip.assert_called_once_with(
|
||||
+ [
|
||||
+ "install", "--no-cache-dir", "--no-index", "--find-links",
|
||||
+ unittest.mock.ANY, "--prefix", "/foo/bar/",
|
||||
+ "pip",
|
||||
+ ],
|
||||
+ unittest.mock.ANY,
|
||||
+ )
|
||||
+
|
||||
def test_bootstrapping_with_user(self):
|
||||
ensurepip.bootstrap(user=True)
|
||||
|
||||
Index: Python-3.12.10/Makefile.pre.in
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Makefile.pre.in 2025-04-11 21:04:58.388346212 +0200
|
||||
+++ Python-3.12.10/Makefile.pre.in 2025-04-11 21:13:01.304095180 +0200
|
||||
@@ -1914,7 +1914,7 @@
|
||||
install|*) ensurepip="" ;; \
|
||||
esac; \
|
||||
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
|
||||
- $$ensurepip --root=$(DESTDIR)/ ; \
|
||||
+ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \
|
||||
fi
|
||||
|
||||
.PHONY: altinstall
|
||||
@@ -1925,7 +1925,7 @@
|
||||
install|*) ensurepip="--altinstall" ;; \
|
||||
esac; \
|
||||
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
|
||||
- $$ensurepip --root=$(DESTDIR)/ ; \
|
||||
+ $$ensurepip --root=$(DESTDIR)/ --prefix=$(prefix) ; \
|
||||
fi
|
||||
|
||||
.PHONY: commoninstall
|
||||
Index: Python-3.12.10/Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ Python-3.12.10/Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst 2025-04-11 21:13:01.304672632 +0200
|
||||
@@ -0,0 +1 @@
|
||||
+A directory prefix can now be specified when using :mod:`ensurepip`.
|
||||
45
bsc1243155-sphinx-non-determinism.patch
Normal file
45
bsc1243155-sphinx-non-determinism.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
From 906a590df191f66f4f0c4a70e3edb6fd82c156ef Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Garcia Moreno <daniel.garcia@suse.com>
|
||||
Date: Tue, 1 Jul 2025 12:13:28 +0200
|
||||
Subject: [PATCH] Doc: Generate ids for audit_events using docname
|
||||
|
||||
This patch generates ids for audit_events using the docname so the id is
|
||||
not global but depend on the source file. This make the doc build
|
||||
reproducible with multiple cores because it doesn't which file is parsed
|
||||
first, the id for audit_events will always be consistent independently
|
||||
of what file is parsed first.
|
||||
|
||||
https://github.com/python/cpython/issues/130979
|
||||
---
|
||||
Doc/tools/extensions/audit_events.py | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: Python-3.12.11/Doc/tools/extensions/audit_events.py
|
||||
===================================================================
|
||||
--- Python-3.12.11.orig/Doc/tools/extensions/audit_events.py 2025-07-02 16:10:55.447792590 +0200
|
||||
+++ Python-3.12.11/Doc/tools/extensions/audit_events.py 2025-07-02 16:12:00.124596479 +0200
|
||||
@@ -64,8 +64,13 @@
|
||||
logger.warning(msg)
|
||||
return
|
||||
|
||||
- def id_for(self, name) -> str:
|
||||
- source_count = len(self.sources.get(name, ()))
|
||||
+ def _source_count(self, name, docname) -> int:
|
||||
+ """Count the event name in the same source"""
|
||||
+ sources = self.sources.get(name, set())
|
||||
+ return len([s for s, t in sources if s == docname])
|
||||
+
|
||||
+ def id_for(self, name, docname) -> str:
|
||||
+ source_count = self._source_count(name, docname)
|
||||
name_clean = re.sub(r"\W", "_", name)
|
||||
return f"audit_event_{name_clean}_{source_count}"
|
||||
|
||||
@@ -140,7 +145,7 @@
|
||||
except (IndexError, TypeError):
|
||||
target = None
|
||||
if not target:
|
||||
- target = self.env.audit_events.id_for(name)
|
||||
+ target = self.env.audit_events.id_for(name, self.env.docname)
|
||||
ids.append(target)
|
||||
self.env.audit_events.add_event(name, args, (self.env.docname, target))
|
||||
|
||||
780
doc-py38-to-py36.patch
Normal file
780
doc-py38-to-py36.patch
Normal file
@@ -0,0 +1,780 @@
|
||||
---
|
||||
Doc/Makefile | 8 +--
|
||||
Doc/conf.py | 16 ++++++-
|
||||
Doc/tools/check-warnings.py | 5 +-
|
||||
Doc/tools/extensions/audit_events.py | 54 +++++++++++++-------------
|
||||
Doc/tools/extensions/availability.py | 15 +++----
|
||||
Doc/tools/extensions/c_annotations.py | 45 +++++++++++++--------
|
||||
Doc/tools/extensions/changes.py | 8 +--
|
||||
Doc/tools/extensions/glossary_search.py | 10 +---
|
||||
Doc/tools/extensions/implementation_detail.py | 22 +++-------
|
||||
Doc/tools/extensions/issue_role.py | 16 ++-----
|
||||
Doc/tools/extensions/misc_news.py | 14 ++----
|
||||
Doc/tools/extensions/patchlevel.py | 9 ++--
|
||||
Doc/tools/extensions/pydoc_topics.py | 22 +++++-----
|
||||
13 files changed, 126 insertions(+), 118 deletions(-)
|
||||
|
||||
Index: Python-3.12.10/Doc/Makefile
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/Makefile 2025-04-29 22:11:50.013198738 +0200
|
||||
+++ Python-3.12.10/Doc/Makefile 2025-04-29 22:11:52.047098026 +0200
|
||||
@@ -14,15 +14,15 @@
|
||||
SOURCES =
|
||||
DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py)
|
||||
REQUIREMENTS = requirements.txt
|
||||
-SPHINXERRORHANDLING = --fail-on-warning
|
||||
+SPHINXERRORHANDLING = -W
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = --define latex_elements.papersize=a4paper
|
||||
PAPEROPT_letter = --define latex_elements.papersize=letterpaper
|
||||
|
||||
-ALLSPHINXOPTS = --builder $(BUILDER) \
|
||||
- --doctree-dir build/doctrees \
|
||||
- --jobs $(JOBS) \
|
||||
+ALLSPHINXOPTS = -b $(BUILDER) \
|
||||
+ -d build/doctrees \
|
||||
+ -j $(JOBS) \
|
||||
$(PAPEROPT_$(PAPER)) \
|
||||
$(SPHINXOPTS) $(SPHINXERRORHANDLING) \
|
||||
. build/$(BUILDER) $(SOURCES)
|
||||
Index: Python-3.12.10/Doc/conf.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/conf.py 2025-04-29 22:11:46.161835452 +0200
|
||||
+++ Python-3.12.10/Doc/conf.py 2025-04-29 22:11:52.047459667 +0200
|
||||
@@ -11,6 +11,8 @@
|
||||
from importlib import import_module
|
||||
from importlib.util import find_spec
|
||||
|
||||
+from sphinx import version_info
|
||||
+
|
||||
# Make our custom extensions available to Sphinx
|
||||
sys.path.append(os.path.abspath('tools/extensions'))
|
||||
sys.path.append(os.path.abspath('includes'))
|
||||
@@ -87,7 +89,7 @@
|
||||
|
||||
# Minimum version of sphinx required
|
||||
# Keep this version in sync with ``Doc/requirements.txt``.
|
||||
-needs_sphinx = '8.2.0'
|
||||
+needs_sphinx = '4.2.0'
|
||||
|
||||
# Create table of contents entries for domain objects (e.g. functions, classes,
|
||||
# attributes, etc.). Default is True.
|
||||
@@ -342,7 +344,7 @@
|
||||
# (See .readthedocs.yml and https://docs.readthedocs.io/en/stable/reference/environment-variables.html)
|
||||
is_deployment_preview = os.getenv("READTHEDOCS_VERSION_TYPE") == "external"
|
||||
repository_url = os.getenv("READTHEDOCS_GIT_CLONE_URL", "")
|
||||
-repository_url = repository_url.removesuffix(".git")
|
||||
+repository_url = repository_url[:-len(".git")]
|
||||
html_context = {
|
||||
"is_deployment_preview": is_deployment_preview,
|
||||
"repository_url": repository_url or None,
|
||||
@@ -588,6 +590,16 @@
|
||||
}
|
||||
extlinks_detect_hardcoded_links = True
|
||||
|
||||
+if version_info[:2] < (8, 1):
|
||||
+ # Sphinx 8.1 has in-built CVE and CWE roles.
|
||||
+ extlinks.update({
|
||||
+ "cve": (
|
||||
+ "https://www.cve.org/CVERecord?id=CVE-%s",
|
||||
+ "CVE-%s",
|
||||
+ ),
|
||||
+ "cwe": ("https://cwe.mitre.org/data/definitions/%s.html", "CWE-%s"),
|
||||
+ })
|
||||
+
|
||||
# Options for c_annotations extension
|
||||
# -----------------------------------
|
||||
|
||||
Index: Python-3.12.10/Doc/tools/check-warnings.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/check-warnings.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/check-warnings.py 2025-04-29 22:11:52.047704324 +0200
|
||||
@@ -228,7 +228,8 @@
|
||||
print(filename)
|
||||
for warning in warnings:
|
||||
if filename in warning:
|
||||
- if match := WARNING_PATTERN.fullmatch(warning):
|
||||
+ match = WARNING_PATTERN.fullmatch(warning)
|
||||
+ if match:
|
||||
print(" {line}: {msg}".format_map(match))
|
||||
return -1
|
||||
return 0
|
||||
@@ -316,7 +317,7 @@
|
||||
|
||||
cwd = str(Path.cwd()) + os.path.sep
|
||||
files_with_nits = {
|
||||
- warning.removeprefix(cwd).split(":")[0]
|
||||
+ (warning[len(cwd):].split(":")[0] if warning.startswith(cwd) else warning.split(":")[0])
|
||||
for warning in warnings
|
||||
if "Doc/" in warning
|
||||
}
|
||||
Index: Python-3.12.10/Doc/tools/extensions/audit_events.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/audit_events.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/audit_events.py 2025-04-29 22:11:52.047967558 +0200
|
||||
@@ -1,9 +1,6 @@
|
||||
"""Support for documenting audit events."""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
import re
|
||||
-from typing import TYPE_CHECKING
|
||||
|
||||
from docutils import nodes
|
||||
from sphinx.errors import NoUri
|
||||
@@ -12,12 +9,11 @@
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
|
||||
-if TYPE_CHECKING:
|
||||
- from collections.abc import Iterator
|
||||
+from typing import Any, List, Tuple
|
||||
|
||||
- from sphinx.application import Sphinx
|
||||
- from sphinx.builders import Builder
|
||||
- from sphinx.environment import BuildEnvironment
|
||||
+from sphinx.application import Sphinx
|
||||
+from sphinx.builders import Builder
|
||||
+from sphinx.environment import BuildEnvironment
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -32,16 +28,16 @@
|
||||
|
||||
class AuditEvents:
|
||||
def __init__(self) -> None:
|
||||
- self.events: dict[str, list[str]] = {}
|
||||
- self.sources: dict[str, list[tuple[str, str]]] = {}
|
||||
+ self.events: dict[str, List[str]] = {}
|
||||
+ self.sources: dict[str, List[Tuple[str, str]]] = {}
|
||||
|
||||
- def __iter__(self) -> Iterator[tuple[str, list[str], tuple[str, str]]]:
|
||||
+ def __iter__(self) -> Any:
|
||||
for name, args in self.events.items():
|
||||
for source in self.sources[name]:
|
||||
yield name, args, source
|
||||
|
||||
def add_event(
|
||||
- self, name, args: list[str], source: tuple[str, str]
|
||||
+ self, name, args: List[str], source: Tuple[str, str]
|
||||
) -> None:
|
||||
if name in self.events:
|
||||
self._check_args_match(name, args)
|
||||
@@ -49,7 +45,7 @@
|
||||
self.events[name] = args
|
||||
self.sources.setdefault(name, []).append(source)
|
||||
|
||||
- def _check_args_match(self, name: str, args: list[str]) -> None:
|
||||
+ def _check_args_match(self, name: str, args: List[str]) -> None:
|
||||
current_args = self.events[name]
|
||||
msg = (
|
||||
f"Mismatched arguments for audit-event {name}: "
|
||||
@@ -60,7 +56,7 @@
|
||||
if len(current_args) != len(args):
|
||||
logger.warning(msg)
|
||||
return
|
||||
- for a1, a2 in zip(current_args, args, strict=False):
|
||||
+ for a1, a2 in zip(current_args, args):
|
||||
if a1 == a2:
|
||||
continue
|
||||
if any(a1 in s and a2 in s for s in _SYNONYMS):
|
||||
@@ -73,7 +69,7 @@
|
||||
name_clean = re.sub(r"\W", "_", name)
|
||||
return f"audit_event_{name_clean}_{source_count}"
|
||||
|
||||
- def rows(self) -> Iterator[tuple[str, list[str], list[tuple[str, str]]]]:
|
||||
+ def rows(self) -> Any:
|
||||
for name in sorted(self.events.keys()):
|
||||
yield name, self.events[name], self.sources[name]
|
||||
|
||||
@@ -97,7 +93,7 @@
|
||||
def audit_events_merge(
|
||||
app: Sphinx,
|
||||
env: BuildEnvironment,
|
||||
- docnames: list[str],
|
||||
+ docnames: List[str],
|
||||
other: BuildEnvironment,
|
||||
) -> None:
|
||||
"""In Sphinx parallel builds, this merges audit_events from subprocesses."""
|
||||
@@ -126,14 +122,16 @@
|
||||
),
|
||||
]
|
||||
|
||||
- def run(self) -> list[nodes.paragraph]:
|
||||
+ def run(self) -> List[nodes.paragraph]:
|
||||
+ def _no_walrus_op(args):
|
||||
+ for arg in args.strip("'\"").split(","):
|
||||
+ aarg = arg.strip()
|
||||
+ if aarg:
|
||||
+ yield aarg
|
||||
+
|
||||
name = self.arguments[0]
|
||||
if len(self.arguments) >= 2 and self.arguments[1]:
|
||||
- args = [
|
||||
- arg
|
||||
- for argument in self.arguments[1].strip("'\"").split(",")
|
||||
- if (arg := argument.strip())
|
||||
- ]
|
||||
+ args = list(_no_walrus_op(self.arguments[1]))
|
||||
else:
|
||||
args = []
|
||||
ids = []
|
||||
@@ -169,7 +167,7 @@
|
||||
|
||||
|
||||
class AuditEventListDirective(SphinxDirective):
|
||||
- def run(self) -> list[audit_event_list]:
|
||||
+ def run(self) -> List[audit_event_list]:
|
||||
return [audit_event_list()]
|
||||
|
||||
|
||||
@@ -181,7 +179,11 @@
|
||||
return
|
||||
|
||||
table = self._make_table(self.app.builder, self.env.docname)
|
||||
- for node in self.document.findall(audit_event_list):
|
||||
+ try:
|
||||
+ findall = self.document.findall
|
||||
+ except AttributeError:
|
||||
+ findall = self.document.traverse
|
||||
+ for node in findall(audit_event_list):
|
||||
node.replace_self(table)
|
||||
|
||||
def _make_table(self, builder: Builder, docname: str) -> nodes.table:
|
||||
@@ -217,8 +219,8 @@
|
||||
builder: Builder,
|
||||
docname: str,
|
||||
name: str,
|
||||
- args: list[str],
|
||||
- sources: list[tuple[str, str]],
|
||||
+ args: List[str],
|
||||
+ sources: List[Tuple[str, str]],
|
||||
) -> nodes.row:
|
||||
row = nodes.row()
|
||||
name_node = nodes.paragraph("", nodes.Text(name))
|
||||
Index: Python-3.12.10/Doc/tools/extensions/availability.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/availability.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/availability.py 2025-04-29 22:11:52.048206976 +0200
|
||||
@@ -1,8 +1,6 @@
|
||||
"""Support for documenting platform availability"""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
-from typing import TYPE_CHECKING
|
||||
+from typing import Dict, List, TYPE_CHECKING, Union
|
||||
|
||||
from docutils import nodes
|
||||
from sphinx import addnodes
|
||||
@@ -53,7 +51,7 @@
|
||||
optional_arguments = 0
|
||||
final_argument_whitespace = True
|
||||
|
||||
- def run(self) -> list[nodes.container]:
|
||||
+ def run(self) -> List[nodes.container]:
|
||||
title = sphinx_gettext("Availability")
|
||||
refnode = addnodes.pending_xref(
|
||||
title,
|
||||
@@ -77,7 +75,7 @@
|
||||
|
||||
return [cnode]
|
||||
|
||||
- def parse_platforms(self) -> dict[str, str | bool]:
|
||||
+ def parse_platforms(self) -> Dict[str, Union[str, bool]]:
|
||||
"""Parse platform information from arguments
|
||||
|
||||
Arguments is a comma-separated string of platforms. A platform may
|
||||
@@ -96,12 +94,13 @@
|
||||
platform, _, version = arg.partition(" >= ")
|
||||
if platform.startswith("not "):
|
||||
version = False
|
||||
- platform = platform.removeprefix("not ")
|
||||
+ platform = platform[len("not "):]
|
||||
elif not version:
|
||||
version = True
|
||||
platforms[platform] = version
|
||||
|
||||
- if unknown := set(platforms).difference(KNOWN_PLATFORMS):
|
||||
+ unknown = set(platforms).difference(KNOWN_PLATFORMS)
|
||||
+ if unknown:
|
||||
logger.warning(
|
||||
"Unknown platform%s or syntax '%s' in '.. availability:: %s', "
|
||||
"see %s:KNOWN_PLATFORMS for a set of known platforms.",
|
||||
@@ -114,7 +113,7 @@
|
||||
return platforms
|
||||
|
||||
|
||||
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
+def setup(app):
|
||||
app.add_directive("availability", Availability)
|
||||
|
||||
return {
|
||||
Index: Python-3.12.10/Doc/tools/extensions/c_annotations.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/c_annotations.py 2025-04-29 22:11:52.033400629 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/c_annotations.py 2025-04-29 22:11:52.048411194 +0200
|
||||
@@ -9,22 +9,18 @@
|
||||
* Set ``stable_abi_file`` to the path to stable ABI list.
|
||||
"""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
import csv
|
||||
import dataclasses
|
||||
from pathlib import Path
|
||||
-from typing import TYPE_CHECKING
|
||||
+from typing import Any, Dict, List, TYPE_CHECKING, Union
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.statemachine import StringList
|
||||
-from sphinx import addnodes
|
||||
+from sphinx import addnodes, version_info
|
||||
from sphinx.locale import _ as sphinx_gettext
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
|
||||
-if TYPE_CHECKING:
|
||||
- from sphinx.application import Sphinx
|
||||
- from sphinx.util.typing import ExtensionMetadata
|
||||
+from sphinx.application import Sphinx
|
||||
|
||||
ROLE_TO_OBJECT_TYPE = {
|
||||
"func": "function",
|
||||
@@ -35,20 +31,20 @@
|
||||
}
|
||||
|
||||
|
||||
-@dataclasses.dataclass(slots=True)
|
||||
+@dataclasses.dataclass()
|
||||
class RefCountEntry:
|
||||
# Name of the function.
|
||||
name: str
|
||||
# List of (argument name, type, refcount effect) tuples.
|
||||
# (Currently not used. If it was, a dataclass might work better.)
|
||||
- args: list = dataclasses.field(default_factory=list)
|
||||
+ args: List = dataclasses.field(default_factory=list)
|
||||
# Return type of the function.
|
||||
result_type: str = ""
|
||||
# Reference count effect for the return value.
|
||||
- result_refs: int | None = None
|
||||
+ result_refs: Union[int, None] = None
|
||||
|
||||
|
||||
-@dataclasses.dataclass(frozen=True, slots=True)
|
||||
+@dataclasses.dataclass(frozen=True)
|
||||
class StableABIEntry:
|
||||
# Role of the object.
|
||||
# Source: Each [item_kind] in stable_abi.toml is mapped to a C Domain role.
|
||||
@@ -67,7 +63,7 @@
|
||||
struct_abi_kind: str
|
||||
|
||||
|
||||
-def read_refcount_data(refcount_filename: Path) -> dict[str, RefCountEntry]:
|
||||
+def read_refcount_data(refcount_filename: Path) -> Dict[str, RefCountEntry]:
|
||||
refcount_data = {}
|
||||
refcounts = refcount_filename.read_text(encoding="utf8")
|
||||
for line in refcounts.splitlines():
|
||||
@@ -103,7 +99,7 @@
|
||||
return refcount_data
|
||||
|
||||
|
||||
-def read_stable_abi_data(stable_abi_file: Path) -> dict[str, StableABIEntry]:
|
||||
+def read_stable_abi_data(stable_abi_file: Path) -> Dict[str, StableABIEntry]:
|
||||
stable_abi_data = {}
|
||||
with open(stable_abi_file, encoding="utf8") as fp:
|
||||
for record in csv.DictReader(fp):
|
||||
@@ -127,11 +123,14 @@
|
||||
continue
|
||||
if not par[0].get("ids", None):
|
||||
continue
|
||||
- name = par[0]["ids"][0].removeprefix("c.")
|
||||
+ name = par[0]["ids"][0]
|
||||
+ if name.startswith("c."):
|
||||
+ name = name[len("c."):]
|
||||
objtype = par["objtype"]
|
||||
|
||||
# Stable ABI annotation.
|
||||
- if record := stable_abi_data.get(name):
|
||||
+ record = stable_abi_data.get(name)
|
||||
+ if record:
|
||||
if ROLE_TO_OBJECT_TYPE[record.role] != objtype:
|
||||
msg = (
|
||||
f"Object type mismatch in limited API annotation for {name}: "
|
||||
@@ -238,7 +237,7 @@
|
||||
)
|
||||
|
||||
|
||||
-def _return_value_annotation(result_refs: int | None) -> nodes.emphasis:
|
||||
+def _return_value_annotation(result_refs: Union[int, None]) -> nodes.emphasis:
|
||||
classes = ["refcount"]
|
||||
if result_refs is None:
|
||||
rc = sphinx_gettext("Return value: Always NULL.")
|
||||
@@ -258,7 +257,7 @@
|
||||
optional_arguments = 0
|
||||
final_argument_whitespace = True
|
||||
|
||||
- def run(self) -> list[nodes.Node]:
|
||||
+ def run(self) -> List[nodes.Node]:
|
||||
state = self.env.domaindata["c_annotations"]
|
||||
content = [
|
||||
f"* :c:{record.role}:`{record.name}`"
|
||||
@@ -281,13 +280,23 @@
|
||||
)
|
||||
|
||||
|
||||
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
+def setup(app: Sphinx) -> Any:
|
||||
app.add_config_value("refcount_file", "", "env", types={str})
|
||||
app.add_config_value("stable_abi_file", "", "env", types={str})
|
||||
app.add_directive("limited-api-list", LimitedAPIList)
|
||||
app.connect("builder-inited", init_annotations)
|
||||
app.connect("doctree-read", add_annotations)
|
||||
|
||||
+ if version_info[:2] < (7, 2):
|
||||
+ from docutils.parsers.rst import directives
|
||||
+ from sphinx.domains.c import CObject
|
||||
+
|
||||
+ # monkey-patch C object...
|
||||
+ CObject.option_spec.update({
|
||||
+ "no-index-entry": directives.flag,
|
||||
+ "no-contents-entry": directives.flag,
|
||||
+ })
|
||||
+
|
||||
return {
|
||||
"version": "1.0",
|
||||
"parallel_read_safe": True,
|
||||
Index: Python-3.12.10/Doc/tools/extensions/changes.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/changes.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/changes.py 2025-04-29 22:11:52.048619113 +0200
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Support for documenting version of changes, additions, deprecations."""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sphinx.domains.changeset import (
|
||||
@@ -25,7 +23,7 @@
|
||||
|
||||
|
||||
class PyVersionChange(VersionChange):
|
||||
- def run(self) -> list[Node]:
|
||||
+ def run(self) -> "list[Node]":
|
||||
# Replace the 'next' special token with the current development version
|
||||
self.arguments[0] = expand_version_arg(
|
||||
self.arguments[0], self.config.release
|
||||
@@ -43,7 +41,7 @@
|
||||
"Deprecated since version %s, removed in version %s"
|
||||
)
|
||||
|
||||
- def run(self) -> list[Node]:
|
||||
+ def run(self) -> "list[Node]":
|
||||
# Replace the first two arguments (deprecated version and removed version)
|
||||
# with a single tuple of both versions.
|
||||
version_deprecated = expand_version_arg(
|
||||
@@ -73,7 +71,7 @@
|
||||
versionlabel_classes[self.name] = ""
|
||||
|
||||
|
||||
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
+def setup(app: "Sphinx") -> "ExtensionMetadata":
|
||||
# Override Sphinx's directives with support for 'next'
|
||||
app.add_directive("versionadded", PyVersionChange, override=True)
|
||||
app.add_directive("versionchanged", PyVersionChange, override=True)
|
||||
Index: Python-3.12.10/Doc/tools/extensions/glossary_search.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/glossary_search.py 2025-04-29 22:11:52.033722879 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/glossary_search.py 2025-04-29 22:11:52.048797629 +0200
|
||||
@@ -1,18 +1,14 @@
|
||||
"""Feature search results for glossary items prominently."""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
import json
|
||||
from pathlib import Path
|
||||
-from typing import TYPE_CHECKING
|
||||
+from typing import Any, TYPE_CHECKING
|
||||
|
||||
from docutils import nodes
|
||||
from sphinx.addnodes import glossary
|
||||
from sphinx.util import logging
|
||||
|
||||
-if TYPE_CHECKING:
|
||||
- from sphinx.application import Sphinx
|
||||
- from sphinx.util.typing import ExtensionMetadata
|
||||
+from sphinx.application import Sphinx
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -60,7 +56,7 @@
|
||||
dest.write_text(json.dumps(app.env.glossary_terms), encoding='utf-8')
|
||||
|
||||
|
||||
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
+def setup(app: Sphinx) -> Any:
|
||||
app.connect('doctree-resolved', process_glossary_nodes)
|
||||
app.connect('build-finished', write_glossary_json)
|
||||
|
||||
Index: Python-3.12.10/Doc/tools/extensions/implementation_detail.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/implementation_detail.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/implementation_detail.py 2025-04-29 22:48:23.397548211 +0200
|
||||
@@ -1,17 +1,10 @@
|
||||
"""Support for marking up implementation details."""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
-from typing import TYPE_CHECKING
|
||||
-
|
||||
from docutils import nodes
|
||||
from sphinx.locale import _ as sphinx_gettext
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
|
||||
-if TYPE_CHECKING:
|
||||
- from sphinx.application import Sphinx
|
||||
- from sphinx.util.typing import ExtensionMetadata
|
||||
-
|
||||
+from sphinx.application import Sphinx
|
||||
|
||||
class ImplementationDetail(SphinxDirective):
|
||||
has_content = True
|
||||
@@ -21,23 +14,24 @@
|
||||
label_text = sphinx_gettext("CPython implementation detail:")
|
||||
|
||||
def run(self):
|
||||
- self.assert_has_content()
|
||||
- content_nodes = self.parse_content_to_nodes()
|
||||
+ container_node = nodes.container()
|
||||
+ container_node.document = self.state.document # Ensure node has document context
|
||||
+ self.state.nested_parse(self.content, self.content_offset, container_node)
|
||||
+ parsed_nodes = container_node.children
|
||||
|
||||
# insert our prefix at the start of the first paragraph
|
||||
- first_node = content_nodes[0]
|
||||
+ first_node = parsed_nodes[0]
|
||||
first_node[:0] = [
|
||||
nodes.strong(self.label_text, self.label_text),
|
||||
nodes.Text(" "),
|
||||
]
|
||||
|
||||
- # create a new compound container node
|
||||
- cnode = nodes.compound("", *content_nodes, classes=["impl-detail"])
|
||||
+ cnode = nodes.compound("", *parsed_nodes, classes=["impl-detail"])
|
||||
self.set_source_info(cnode)
|
||||
return [cnode]
|
||||
|
||||
|
||||
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
+def setup(app: Sphinx):
|
||||
app.add_directive("impl-detail", ImplementationDetail)
|
||||
|
||||
return {
|
||||
Index: Python-3.12.10/Doc/tools/extensions/issue_role.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/issue_role.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/issue_role.py 2025-04-29 22:21:55.278961032 +0200
|
||||
@@ -1,22 +1,18 @@
|
||||
"""Support for referencing issues in the tracker."""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
-from typing import TYPE_CHECKING
|
||||
+from typing import TYPE_CHECKING, List, Tuple
|
||||
|
||||
from docutils import nodes
|
||||
from sphinx.util.docutils import SphinxRole
|
||||
|
||||
-if TYPE_CHECKING:
|
||||
- from docutils.nodes import Element
|
||||
- from sphinx.application import Sphinx
|
||||
- from sphinx.util.typing import ExtensionMetadata
|
||||
+from docutils.nodes import Element
|
||||
+from sphinx.application import Sphinx
|
||||
|
||||
|
||||
class BPOIssue(SphinxRole):
|
||||
ISSUE_URI = "https://bugs.python.org/issue?@action=redirect&bpo={0}"
|
||||
|
||||
- def run(self) -> tuple[list[Element], list[nodes.system_message]]:
|
||||
+ def run(self) -> Tuple[List[Element], List[nodes.system_message]]:
|
||||
issue = self.text
|
||||
|
||||
# sanity check: there are no bpo issues within these two values
|
||||
@@ -38,7 +34,7 @@
|
||||
class GitHubIssue(SphinxRole):
|
||||
ISSUE_URI = "https://github.com/python/cpython/issues/{0}"
|
||||
|
||||
- def run(self) -> tuple[list[Element], list[nodes.system_message]]:
|
||||
+ def run(self) -> Tuple[List[Element], List[nodes.system_message]]:
|
||||
issue = self.text
|
||||
|
||||
# sanity check: all GitHub issues have ID >= 32426
|
||||
@@ -58,7 +54,7 @@
|
||||
return [refnode], []
|
||||
|
||||
|
||||
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
+def setup(app: Sphinx) -> "ExtensionMetadata":
|
||||
app.add_role("issue", BPOIssue())
|
||||
app.add_role("gh", GitHubIssue())
|
||||
|
||||
Index: Python-3.12.10/Doc/tools/extensions/misc_news.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/misc_news.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/misc_news.py 2025-04-29 22:11:52.049046825 +0200
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Support for including Misc/NEWS."""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
@@ -24,13 +22,13 @@
|
||||
+++++++++++
|
||||
"""
|
||||
|
||||
-bpo_issue_re: Final[re.Pattern[str]] = re.compile(
|
||||
+bpo_issue_re: "Final[re.Pattern[str]]" = re.compile(
|
||||
"(?:issue #|bpo-)([0-9]+)", re.ASCII
|
||||
)
|
||||
-gh_issue_re: Final[re.Pattern[str]] = re.compile(
|
||||
+gh_issue_re: "Final[re.Pattern[str]]" = re.compile(
|
||||
"gh-(?:issue-)?([0-9]+)", re.ASCII | re.IGNORECASE
|
||||
)
|
||||
-whatsnew_re: Final[re.Pattern[str]] = re.compile(
|
||||
+whatsnew_re: "Final[re.Pattern[str]]" = re.compile(
|
||||
r"^what's new in (.*?)\??$", re.ASCII | re.IGNORECASE | re.MULTILINE
|
||||
)
|
||||
|
||||
@@ -42,7 +40,7 @@
|
||||
final_argument_whitespace = False
|
||||
option_spec = {}
|
||||
|
||||
- def run(self) -> list[Node]:
|
||||
+ def run(self) -> "list[Node]":
|
||||
# Get content of NEWS file
|
||||
source, _ = self.get_source_info()
|
||||
news_file = Path(source).resolve().parent / self.arguments[0]
|
||||
@@ -54,7 +52,7 @@
|
||||
return [nodes.strong(text, text)]
|
||||
|
||||
# remove first 3 lines as they are the main heading
|
||||
- news_text = news_text.removeprefix(BLURB_HEADER)
|
||||
+ news_text = news_text[len(BLURB_HEADER):] if news_text.startswith(BLURB_HEADER) else news_text
|
||||
|
||||
news_text = bpo_issue_re.sub(r":issue:`\1`", news_text)
|
||||
# Fallback handling for GitHub issues
|
||||
@@ -65,7 +63,7 @@
|
||||
return []
|
||||
|
||||
|
||||
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
+def setup(app: "Sphinx") -> "ExtensionMetadata":
|
||||
app.add_directive("miscnews", MiscNews)
|
||||
|
||||
return {
|
||||
Index: Python-3.12.10/Doc/tools/extensions/patchlevel.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/patchlevel.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/patchlevel.py 2025-04-29 22:11:52.049253068 +0200
|
||||
@@ -3,7 +3,7 @@
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
-from typing import Literal, NamedTuple
|
||||
+from typing import NamedTuple, Tuple
|
||||
|
||||
CPYTHON_ROOT = Path(
|
||||
__file__, # cpython/Doc/tools/extensions/patchlevel.py
|
||||
@@ -26,7 +26,7 @@
|
||||
major: int #: Major release number
|
||||
minor: int #: Minor release number
|
||||
micro: int #: Patch release number
|
||||
- releaselevel: Literal["alpha", "beta", "candidate", "final"]
|
||||
+ releaselevel: str
|
||||
serial: int #: Serial release number
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
defines = {}
|
||||
patchlevel_h = PATCHLEVEL_H.read_text(encoding="utf-8")
|
||||
for line in patchlevel_h.splitlines():
|
||||
- if (m := pat.match(line)) is not None:
|
||||
+ m = pat.match(line)
|
||||
+ if m is not None:
|
||||
name, value = m.groups()
|
||||
defines[name] = value
|
||||
|
||||
@@ -50,7 +51,7 @@
|
||||
)
|
||||
|
||||
|
||||
-def format_version_info(info: version_info) -> tuple[str, str]:
|
||||
+def format_version_info(info: version_info) -> Tuple[str, str]:
|
||||
version = f"{info.major}.{info.minor}"
|
||||
release = f"{info.major}.{info.minor}.{info.micro}"
|
||||
if info.releaselevel != "final":
|
||||
Index: Python-3.12.10/Doc/tools/extensions/pydoc_topics.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/pydoc_topics.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/pydoc_topics.py 2025-04-29 22:33:59.916893510 +0200
|
||||
@@ -1,21 +1,23 @@
|
||||
"""Support for building "topic help" for pydoc."""
|
||||
|
||||
-from __future__ import annotations
|
||||
-
|
||||
from time import asctime
|
||||
-from typing import TYPE_CHECKING
|
||||
+from typing import TYPE_CHECKING, Tuple
|
||||
|
||||
from sphinx.builders.text import TextBuilder
|
||||
from sphinx.util import logging
|
||||
-from sphinx.util.display import status_iterator
|
||||
+try:
|
||||
+ from sphinx.util.display import status_iterator
|
||||
+except ModuleNotFoundError:
|
||||
+ from sphinx.util import status_iterator
|
||||
from sphinx.util.docutils import new_document
|
||||
from sphinx.writers.text import TextTranslator
|
||||
|
||||
-if TYPE_CHECKING:
|
||||
+try:
|
||||
+ from typing import Sequence, Set
|
||||
+except ModuleNotFoundError:
|
||||
from collections.abc import Sequence, Set
|
||||
|
||||
- from sphinx.application import Sphinx
|
||||
- from sphinx.util.typing import ExtensionMetadata
|
||||
+from sphinx.application import Sphinx
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -161,7 +163,7 @@
|
||||
self.outdir.joinpath("topics.py").write_text(topics, encoding="utf-8")
|
||||
|
||||
|
||||
-def _display_labels(item: tuple[str, Sequence[tuple[str, str]]]) -> str:
|
||||
+def _display_labels(item: Tuple[str, Sequence[Tuple[str, str]]]) -> str:
|
||||
_docname, label_ids = item
|
||||
labels = [name for name, _id in label_ids]
|
||||
if len(labels) > 4:
|
||||
@@ -169,7 +171,7 @@
|
||||
return ", ".join(labels)
|
||||
|
||||
|
||||
-def _repr(text: str, /) -> str:
|
||||
+def _repr(text: str) -> str:
|
||||
"""Return a triple-single-quoted representation of text."""
|
||||
if "'''" not in text:
|
||||
return f"r'''{text}'''"
|
||||
@@ -177,7 +179,7 @@
|
||||
return f"'''{text}'''"
|
||||
|
||||
|
||||
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||
+def setup(app: Sphinx) -> "ExtensionMetadata":
|
||||
app.add_builder(PydocTopicsBuilder)
|
||||
|
||||
return {
|
||||
45
docs-docutils_014-Sphinx_420.patch
Normal file
45
docs-docutils_014-Sphinx_420.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
Doc/tools/extensions/c_annotations.py | 6 +++++-
|
||||
Doc/tools/extensions/glossary_search.py | 12 ++++++++++--
|
||||
2 files changed, 15 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: Python-3.12.10/Doc/tools/extensions/c_annotations.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/c_annotations.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/c_annotations.py 2025-04-11 21:16:39.007011463 +0200
|
||||
@@ -117,7 +117,11 @@
|
||||
state = app.env.domaindata["c_annotations"]
|
||||
refcount_data = state["refcount_data"]
|
||||
stable_abi_data = state["stable_abi_data"]
|
||||
- for node in doctree.findall(addnodes.desc_content):
|
||||
+ try:
|
||||
+ findall = doctree.findall
|
||||
+ except AttributeError:
|
||||
+ findall = doctree.traverse
|
||||
+ for node in findall(addnodes.desc_content):
|
||||
par = node.parent
|
||||
if par["domain"] != "c":
|
||||
continue
|
||||
Index: Python-3.12.10/Doc/tools/extensions/glossary_search.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Doc/tools/extensions/glossary_search.py 2025-04-08 13:35:47.000000000 +0200
|
||||
+++ Python-3.12.10/Doc/tools/extensions/glossary_search.py 2025-04-11 21:16:39.007340209 +0200
|
||||
@@ -30,8 +30,16 @@
|
||||
else:
|
||||
terms = app.env.glossary_terms = {}
|
||||
|
||||
- for node in doctree.findall(glossary):
|
||||
- for glossary_item in node.findall(nodes.definition_list_item):
|
||||
+ try:
|
||||
+ findall = doctree.findall
|
||||
+ except AttributeError:
|
||||
+ findall = doctree.traverse
|
||||
+ for node in findall(glossary):
|
||||
+ try:
|
||||
+ node_findall = node.findall
|
||||
+ except AttributeError:
|
||||
+ node_findall = node.traverse
|
||||
+ for glossary_item in node_findall(nodes.definition_list_item):
|
||||
term = glossary_item[0].astext()
|
||||
definition = glossary_item[-1]
|
||||
|
||||
12
externally_managed.in
Normal file
12
externally_managed.in
Normal file
@@ -0,0 +1,12 @@
|
||||
[externally-managed]
|
||||
Error=To install Python packages system-wide, try
|
||||
zypper install __PYTHONPREFIX__-xyz, where xyz is the package
|
||||
you are trying to install.
|
||||
|
||||
If you wish to install a non-rpm packaged Python package,
|
||||
create a virtual environment using __PYTHON__ -m venv path/to/venv.
|
||||
Then use path/to/venv/bin/python and path/to/venv/bin/pip.
|
||||
|
||||
If you wish to install a non-rpm packaged Python application,
|
||||
it may be easiest to use `pipx install xyz`, which will manage a
|
||||
virtual environment for you. Install pipx via `zypper install __PYTHONPREFIX__-pipx` .
|
||||
32
fix-test-recursion-limit-15.6.patch
Normal file
32
fix-test-recursion-limit-15.6.patch
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
Lib/test/test_compile.py | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/Lib/test/test_compile.py
|
||||
+++ b/Lib/test/test_compile.py
|
||||
@@ -14,6 +14,9 @@ from test.support import (script_helper,
|
||||
requires_specialization, C_RECURSION_LIMIT)
|
||||
from test.support.os_helper import FakePath
|
||||
|
||||
+IS_SLE_15_6 = os.environ.get("SLE_VERSION", "") == "0150600"
|
||||
+IS_32bit = hasattr(os, "uname") and os.uname().machine in ["i386", "i486", "i586", "i686"]
|
||||
+
|
||||
class TestSpecifics(unittest.TestCase):
|
||||
|
||||
def compile_single(self, source):
|
||||
@@ -110,6 +113,7 @@ class TestSpecifics(unittest.TestCase):
|
||||
self.assertEqual(d['z'], 12)
|
||||
|
||||
@unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
|
||||
+ @unittest.skipIf(IS_SLE_15_6 and IS_32bit, "fails on 15.6 i586")
|
||||
def test_extended_arg(self):
|
||||
repeat = int(C_RECURSION_LIMIT * 0.9)
|
||||
longexpr = 'x = x or ' + '-x' * repeat
|
||||
@@ -603,6 +607,7 @@ class TestSpecifics(unittest.TestCase):
|
||||
|
||||
@support.cpython_only
|
||||
@unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
|
||||
+ @unittest.skipIf(IS_SLE_15_6 and IS_32bit, "fails on 15.6 i586")
|
||||
def test_compiler_recursion_limit(self):
|
||||
# Expected limit is C_RECURSION_LIMIT * 2
|
||||
# Duplicating the limit here is a little ugly.
|
||||
32
fix_configure_rst.patch
Normal file
32
fix_configure_rst.patch
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
Doc/using/configure.rst | 2 --
|
||||
Misc/NEWS | 2 +-
|
||||
2 files changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
--- a/Doc/using/configure.rst
|
||||
+++ b/Doc/using/configure.rst
|
||||
@@ -640,13 +640,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
|
||||
@@ -15146,7 +15146,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
|
||||
51
idle3.appdata.xml
Normal file
51
idle3.appdata.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<component type="desktop-application">
|
||||
<id>org.python.IDLE3</id>
|
||||
<launchable type="desktop-id">idle3.desktop</launchable>
|
||||
|
||||
<name>IDLE3</name>
|
||||
<summary>Python 3 Integrated Development and Learning Environment</summary>
|
||||
|
||||
<description>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
IDLE is written in pure Python, and uses the tkinter GUI toolkit.
|
||||
It provides:
|
||||
</p>
|
||||
<ul>
|
||||
<li>a Python shell window (interactive interpreter) with colorizing of code input, output, and error messages,</li>
|
||||
<li>a multi-window text editor with multiple undo, Python colorizing, smart indent, call tips, auto completion, and other features,</li>
|
||||
<li>search within any window, replace within editor windows, and search through multiple files (grep),</li>
|
||||
<li>a debugger with persistent breakpoints, stepping, and viewing of global and local namespaces.</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<developer id="org.python">
|
||||
<name>Python Software Foundation</name>
|
||||
</developer>
|
||||
|
||||
<url type="homepage">https://docs.python.org/3/library/idle.html</url>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-main-window.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-class-browser.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://in.waw.pl/~zbyszek/fedora/idle3-appdata/idle3-code-viewer.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<project_license>Python-2.0</project_license>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<update_contact>zbyszek@in.waw.pl</update_contact>
|
||||
</component>
|
||||
|
||||
12
idle3.desktop
Normal file
12
idle3.desktop
Normal file
@@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Name=IDLE 3
|
||||
GenericName=Python 3 IDE
|
||||
Comment=Python 3 Integrated Development and Learning Environment
|
||||
Exec=idle3 %F
|
||||
TryExec=idle3
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Icon=idle3
|
||||
Categories=Development;IDE;
|
||||
MimeType=text/x-python;
|
||||
7
import_failed.map
Normal file
7
import_failed.map
Normal file
@@ -0,0 +1,7 @@
|
||||
python312-curses: curses _curses
|
||||
python312-dbm: dbm _dbm _gdbm
|
||||
python312-idle: idlelib
|
||||
python312-testsuite: test _ctypes_test _testbuffer _testcapi _testclinic _testinternalcapi _testimportmultiple _testmultiphase _testsinglephase _xxinterpchannels _xxtestfuzz
|
||||
python312-tk: tkinter _tkinter
|
||||
python312-tools: turtledemo
|
||||
python312: sqlite3 readline _sqlite3 nis
|
||||
23
import_failed.py
Normal file
23
import_failed.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import sys, os
|
||||
from sysconfig import get_path
|
||||
|
||||
failed_map_path = os.path.join(get_path('stdlib'), '_import_failed', 'import_failed.map')
|
||||
|
||||
if __spec__:
|
||||
failed_name = __spec__.name
|
||||
else:
|
||||
failed_name = __name__
|
||||
|
||||
with open(failed_map_path) as fd:
|
||||
for line in fd:
|
||||
package = line.split(':')[0]
|
||||
imports = line.split(':')[1]
|
||||
if failed_name in imports:
|
||||
raise ImportError(f"""Module '{failed_name}' is not installed.
|
||||
Use:
|
||||
sudo zypper install {package}
|
||||
to install it.""")
|
||||
|
||||
raise ImportError(f"""Module '{failed_name}' is not installed.
|
||||
It is supposed to be part of python3 distribution, but missing from failed import map.
|
||||
Please file a bug on the SUSE Bugzilla.""")
|
||||
28
macros.python3
Normal file
28
macros.python3
Normal file
@@ -0,0 +1,28 @@
|
||||
%have_python3 1
|
||||
|
||||
# commented out legacy macro definitions
|
||||
#py3_prefix /usr
|
||||
#py3_incdir /usr/include/python3.5m
|
||||
#py3_ver 3.5
|
||||
|
||||
# these should now be provided by macros.python_all
|
||||
#python3_sitearch /usr/lib64/python3.5/site-packages
|
||||
#python3_sitelib /usr/lib/python3.5/site-packages
|
||||
#python3_version 3.5
|
||||
|
||||
# hard to say if anyone ever used these?
|
||||
#py3_soflags cpython-35m-x86_64-linux-gnu
|
||||
#py3_abiflags m
|
||||
%cpython3_soabi %(python3 -c "import sysconfig; print(sysconfig.get_config_var('SOABI'))")
|
||||
%py3_soflags %cpython3_soabi
|
||||
|
||||
# compilation macros that might be in use somewhere
|
||||
%py3_compile(O) \
|
||||
find %1 -name '*.pyc' -exec rm -f {} ";"\
|
||||
python3 -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1\
|
||||
%{-O:\
|
||||
find %1 -name '*.pyo' -exec rm -f {} ";"\
|
||||
python3 -O -c "import sys, os, compileall; br='%{buildroot}'; compileall.compile_dir(sys.argv[1], ddir=br and (sys.argv[1][len(os.path.abspath(br)):]+'/') or None)" %1\
|
||||
}
|
||||
|
||||
|
||||
647
no-skipif-doctests.patch
Normal file
647
no-skipif-doctests.patch
Normal file
@@ -0,0 +1,647 @@
|
||||
only in patch2:
|
||||
unchanged:
|
||||
---
|
||||
Doc/library/turtle.rst | 81 -------------------------------------------------
|
||||
1 file changed, 81 deletions(-)
|
||||
|
||||
Index: Python-3.12.2/Doc/library/turtle.rst
|
||||
===================================================================
|
||||
--- Python-3.12.2.orig/Doc/library/turtle.rst
|
||||
+++ Python-3.12.2/Doc/library/turtle.rst
|
||||
@@ -441,7 +441,6 @@ Turtle motion
|
||||
turtle is headed.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.position()
|
||||
(0.00,0.00)
|
||||
@@ -468,7 +467,6 @@ Turtle motion
|
||||
>>> turtle.goto(0, 0)
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.position()
|
||||
(0.00,0.00)
|
||||
@@ -487,13 +485,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
|
||||
@@ -512,13 +508,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
|
||||
@@ -541,13 +535,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
|
||||
@@ -609,13 +601,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)
|
||||
@@ -631,13 +621,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)
|
||||
@@ -664,7 +652,6 @@ Turtle motion
|
||||
=================== ====================
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.setheading(90)
|
||||
>>> turtle.heading()
|
||||
@@ -677,14 +664,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
|
||||
@@ -716,7 +701,6 @@ Turtle motion
|
||||
calculated automatically. May be used to draw regular polygons.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.position()
|
||||
@@ -745,7 +729,6 @@ Turtle motion
|
||||
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.dot()
|
||||
@@ -763,7 +746,6 @@ Turtle motion
|
||||
it by calling ``clearstamp(stamp_id)``.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.color("blue")
|
||||
>>> stamp_id = turtle.stamp()
|
||||
@@ -778,7 +760,6 @@ Turtle motion
|
||||
Delete stamp with given *stampid*.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.position()
|
||||
(150.00,-0.00)
|
||||
@@ -816,7 +797,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)
|
||||
@@ -849,7 +829,6 @@ Turtle motion
|
||||
turtle turn instantly.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.speed()
|
||||
3
|
||||
@@ -870,7 +849,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)
|
||||
@@ -886,7 +864,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)
|
||||
@@ -898,7 +875,6 @@ Tell Turtle's state
|
||||
Return the turtle's x coordinate.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(50)
|
||||
@@ -914,7 +890,6 @@ Tell Turtle's state
|
||||
Return the turtle's y coordinate.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(60)
|
||||
@@ -931,7 +906,6 @@ Tell Turtle's state
|
||||
:func:`mode`).
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(67)
|
||||
@@ -948,7 +922,6 @@ Tell Turtle's state
|
||||
other turtle, in turtle step units.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.distance(30,40)
|
||||
@@ -972,7 +945,6 @@ Settings for measurement
|
||||
Default value is 360 degrees.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(90)
|
||||
@@ -995,7 +967,6 @@ Settings for measurement
|
||||
``degrees(2*math.pi)``.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.left(90)
|
||||
@@ -1006,7 +977,6 @@ Settings for measurement
|
||||
1.5707963267948966
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.degrees(360)
|
||||
@@ -1042,7 +1012,6 @@ Drawing state
|
||||
thickness. If no argument is given, the current pensize is returned.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.pensize()
|
||||
1
|
||||
@@ -1074,7 +1043,6 @@ Drawing state
|
||||
attributes in one statement.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
|
||||
>>> turtle.pen(fillcolor="black", pencolor="red", pensize=10)
|
||||
@@ -1097,7 +1065,6 @@ Drawing state
|
||||
Return ``True`` if pen is down, ``False`` if it's up.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.penup()
|
||||
>>> turtle.isdown()
|
||||
@@ -1138,7 +1105,6 @@ Color control
|
||||
newly set pencolor.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> colormode()
|
||||
1.0
|
||||
@@ -1187,7 +1153,6 @@ Color control
|
||||
with the newly set fillcolor.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.fillcolor("violet")
|
||||
>>> turtle.fillcolor()
|
||||
@@ -1226,7 +1191,6 @@ Color control
|
||||
with the newly set colors.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.color("red", "green")
|
||||
>>> turtle.color()
|
||||
@@ -1243,7 +1207,6 @@ Filling
|
||||
~~~~~~~
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> turtle.home()
|
||||
@@ -1253,7 +1216,6 @@ Filling
|
||||
Return fillstate (``True`` if filling, ``False`` else).
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.begin_fill()
|
||||
>>> if turtle.filling():
|
||||
@@ -1278,7 +1240,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()
|
||||
@@ -1295,7 +1256,6 @@ More drawing control
|
||||
variables to the default values.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.goto(0,-22)
|
||||
>>> turtle.left(100)
|
||||
@@ -1346,7 +1306,6 @@ Visibility
|
||||
drawing observably.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.hideturtle()
|
||||
|
||||
@@ -1357,7 +1316,6 @@ Visibility
|
||||
Make the turtle visible.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.showturtle()
|
||||
|
||||
@@ -1388,7 +1346,6 @@ Appearance
|
||||
deal with shapes see Screen method :func:`register_shape`.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.shape()
|
||||
'classic'
|
||||
@@ -1414,7 +1371,6 @@ Appearance
|
||||
``resizemode("user")`` is called by :func:`shapesize` when used with arguments.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.resizemode()
|
||||
'noresize'
|
||||
@@ -1438,7 +1394,6 @@ Appearance
|
||||
of the shape's outline.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.shapesize()
|
||||
(1.0, 1.0, 1)
|
||||
@@ -1463,7 +1418,6 @@ Appearance
|
||||
heading of the turtle are sheared.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.shape("circle")
|
||||
>>> turtle.shapesize(5,2)
|
||||
@@ -1480,7 +1434,6 @@ Appearance
|
||||
change the turtle's heading (direction of movement).
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.reset()
|
||||
>>> turtle.shape("circle")
|
||||
@@ -1526,7 +1479,6 @@ Appearance
|
||||
turtle (its direction of movement).
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.reset()
|
||||
>>> turtle.shape("circle")
|
||||
@@ -1555,7 +1507,6 @@ Appearance
|
||||
given matrix.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle = Turtle()
|
||||
>>> turtle.shape("square")
|
||||
@@ -1571,7 +1522,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)
|
||||
@@ -1596,7 +1546,6 @@ Using events
|
||||
procedural way:
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> def turn(x, y):
|
||||
... left(180)
|
||||
@@ -1617,7 +1566,6 @@ Using events
|
||||
``None``, existing bindings are removed.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> class MyTurtle(Turtle):
|
||||
... def glow(self,x,y):
|
||||
@@ -1645,7 +1593,6 @@ Using events
|
||||
mouse-click event on that turtle.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.ondrag(turtle.goto)
|
||||
|
||||
@@ -1673,7 +1620,6 @@ Special Turtle methods
|
||||
Return the last recorded polygon.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.home()
|
||||
>>> turtle.begin_poly()
|
||||
@@ -1693,7 +1639,6 @@ Special Turtle methods
|
||||
turtle properties.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> mick = Turtle()
|
||||
>>> joe = mick.clone()
|
||||
@@ -1706,7 +1651,6 @@ Special Turtle methods
|
||||
return the "anonymous turtle":
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> pet = getturtle()
|
||||
>>> pet.fd(50)
|
||||
@@ -1720,7 +1664,6 @@ Special Turtle methods
|
||||
TurtleScreen methods can then be called for that object.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> ts = turtle.getscreen()
|
||||
>>> ts
|
||||
@@ -1738,7 +1681,6 @@ Special Turtle methods
|
||||
``None``, the undobuffer is disabled.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> turtle.setundobuffer(42)
|
||||
|
||||
@@ -1748,7 +1690,6 @@ Special Turtle methods
|
||||
Return number of entries in the undobuffer.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> while undobufferentries():
|
||||
... undo()
|
||||
@@ -1771,7 +1712,6 @@ below:
|
||||
For example:
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> s = Shape("compound")
|
||||
>>> poly1 = ((0,0),(10,-5),(0,10),(-10,-5))
|
||||
@@ -1782,7 +1722,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")
|
||||
@@ -1802,7 +1741,6 @@ Most of the examples in this section ref
|
||||
``screen``.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> screen = Screen()
|
||||
@@ -1819,7 +1757,6 @@ Window control
|
||||
Set or return background color of the TurtleScreen.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> screen.bgcolor("orange")
|
||||
>>> screen.bgcolor()
|
||||
@@ -1911,7 +1848,6 @@ Window control
|
||||
distorted.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> screen.reset()
|
||||
>>> screen.setworldcoordinates(-50,-7.5,50,7.5)
|
||||
@@ -1922,7 +1858,6 @@ Window control
|
||||
... left(45); fd(2) # a regular octagon
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> screen.reset()
|
||||
@@ -1944,7 +1879,6 @@ Animation control
|
||||
Optional argument:
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> screen.delay()
|
||||
10
|
||||
@@ -1966,7 +1900,6 @@ Animation control
|
||||
:func:`delay`).
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> screen.tracer(8, 25)
|
||||
>>> dist = 2
|
||||
@@ -2003,7 +1936,6 @@ Using screen events
|
||||
must have the focus. (See method :func:`listen`.)
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> def f():
|
||||
... fd(50)
|
||||
@@ -2024,7 +1956,6 @@ Using screen events
|
||||
must have focus. (See method :func:`listen`.)
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> def f():
|
||||
... fd(50)
|
||||
@@ -2049,7 +1980,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.
|
||||
@@ -2069,7 +1999,6 @@ Using screen events
|
||||
Install a timer that calls *fun* after *t* milliseconds.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> running = True
|
||||
>>> def f():
|
||||
@@ -2151,7 +2080,6 @@ Settings and special methods
|
||||
============ ========================= ===================
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> mode("logo") # resets turtle heading to north
|
||||
>>> mode()
|
||||
@@ -2166,7 +2094,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)
|
||||
@@ -2187,7 +2114,6 @@ Settings and special methods
|
||||
do with a Tkinter Canvas.
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> cv = screen.getcanvas()
|
||||
>>> cv
|
||||
@@ -2199,7 +2125,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']
|
||||
@@ -2223,7 +2148,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)))
|
||||
|
||||
@@ -2239,7 +2163,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")
|
||||
@@ -2301,7 +2224,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
|
||||
@@ -2317,7 +2239,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!")
|
||||
|
||||
@@ -2388,7 +2309,6 @@ Public classes
|
||||
Example:
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
|
||||
>>> poly = ((0,0),(10,-5),(0,10),(-10,-5))
|
||||
>>> s = Shape("compound")
|
||||
@@ -2774,7 +2694,6 @@ Changes since Python 3.0
|
||||
|
||||
|
||||
.. doctest::
|
||||
- :skipif: _tkinter is None
|
||||
:hide:
|
||||
|
||||
>>> for turtle in turtles():
|
||||
78
pre_checkin.sh
Normal file
78
pre_checkin.sh
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
master=python*.spec
|
||||
|
||||
# create import_failed.map from package definitions
|
||||
pkgname=$(grep python_pkg_name $master |grep define |awk -F' ' '{print $3}')
|
||||
MAPFILE=import_failed.map
|
||||
function new_map_line () {
|
||||
package=$1
|
||||
package=$(echo $1 |sed -e "s:%{python_pkg_name}:$pkgname:")
|
||||
modules=$2
|
||||
if [ -z "$package" -o -z "$modules" ]; then
|
||||
return
|
||||
fi
|
||||
if [[ "$package" =~ "-base" ]]; then
|
||||
return
|
||||
fi
|
||||
echo "$package:$modules" >> $MAPFILE.tmp
|
||||
}
|
||||
|
||||
for spec in *.spec; do
|
||||
basename=${spec%.spec}
|
||||
package=
|
||||
modules=
|
||||
while read line; do
|
||||
case $line in
|
||||
"%files -n "*)
|
||||
new_map_line $package "$modules"
|
||||
package=${line#"%files -n "}
|
||||
modules=
|
||||
;;
|
||||
"%files "*)
|
||||
new_map_line $package "$modules"
|
||||
package=$basename-${line#"%files "}
|
||||
modules=
|
||||
;;
|
||||
"%files")
|
||||
new_map_line $package "$modules"
|
||||
package=$basename
|
||||
modules=
|
||||
;;
|
||||
"%{sitedir}/config-"*)
|
||||
# ignore
|
||||
;;
|
||||
"%{sitedir}/"*)
|
||||
word=${line#"%{sitedir}/"}
|
||||
if ! echo $word | grep -q /; then
|
||||
modules="$modules $word"
|
||||
fi
|
||||
;;
|
||||
"%{dynlib "*"}")
|
||||
word=${line#"%{dynlib "}
|
||||
word=${word%"}"}
|
||||
modules="$modules $word"
|
||||
;;
|
||||
esac
|
||||
done < $spec
|
||||
new_map_line $package "$modules"
|
||||
done
|
||||
|
||||
cat $MAPFILE.tmp |sort -u > $MAPFILE
|
||||
rm $MAPFILE.tmp
|
||||
|
||||
# run test inclusion check
|
||||
tar xJf Python-*.xz
|
||||
python3 skipped_tests.py
|
||||
|
||||
# generate baselibs.conf
|
||||
VERSION=$(grep ^Version $master|awk -F':' '{print $2}' |sed -e 's/ //g')
|
||||
python_version=${VERSION:0:3} # 3.3
|
||||
python_version_abitag=${python_version//./} # 33
|
||||
python_version_soname=${python_version//./_} # 3_3
|
||||
echo "$pkgname-base" > baselibs.conf
|
||||
echo "$pkgname" >> baselibs.conf
|
||||
echo "libpython$python_version_soname-1_0" >> baselibs.conf
|
||||
|
||||
27
python-3.3.0b1-fix_date_time_compiler.patch
Normal file
27
python-3.3.0b1-fix_date_time_compiler.patch
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
Makefile.pre.in | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
Index: Python-3.12.4/Makefile.pre.in
|
||||
===================================================================
|
||||
--- Python-3.12.4.orig/Makefile.pre.in
|
||||
+++ Python-3.12.4/Makefile.pre.in
|
||||
@@ -1337,11 +1337,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)"' \
|
||||
13
python-3.3.0b1-localpath.patch
Normal file
13
python-3.3.0b1-localpath.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
Index: Python-3.12.2/Lib/site.py
|
||||
===================================================================
|
||||
--- Python-3.12.2.orig/Lib/site.py
|
||||
+++ Python-3.12.2/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
|
||||
78
python.keyring
Normal file
78
python.keyring
Normal file
@@ -0,0 +1,78 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=J6BY
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
3
python312-rpmlintrc
Normal file
3
python312-rpmlintrc
Normal file
@@ -0,0 +1,3 @@
|
||||
addFilter("pem-certificate.*/usr/lib.*/python.*/test/*.pem")
|
||||
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/tests/*.c")
|
||||
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/test/*.cpp")
|
||||
7234
python312.changes
Normal file
7234
python312.changes
Normal file
File diff suppressed because it is too large
Load Diff
1062
python312.spec
Normal file
1062
python312.spec
Normal file
File diff suppressed because it is too large
Load Diff
16
skip-test_pyobject_freed_is_freed.patch
Normal file
16
skip-test_pyobject_freed_is_freed.patch
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
Lib/test/test_capi/test_mem.py | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
Index: Python-3.12.2/Lib/test/test_capi/test_mem.py
|
||||
===================================================================
|
||||
--- Python-3.12.2.orig/Lib/test/test_capi/test_mem.py
|
||||
+++ Python-3.12.2/Lib/test/test_capi/test_mem.py
|
||||
@@ -110,6 +110,7 @@ class PyMemDebugTests(unittest.TestCase)
|
||||
def test_pyobject_forbidden_bytes_is_freed(self):
|
||||
self.check_pyobject_is_freed('check_pyobject_forbidden_bytes_is_freed')
|
||||
|
||||
+ @unittest.skip('Failing on Leap 15.*')
|
||||
def test_pyobject_freed_is_freed(self):
|
||||
self.check_pyobject_is_freed('check_pyobject_freed_is_freed')
|
||||
|
||||
69
skipped_tests.py
Normal file
69
skipped_tests.py
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/python3
|
||||
"""
|
||||
Simple regexp-based skipped test checker.
|
||||
It lists tests that are mentioned (presumably for exclusion)
|
||||
in BASE, and in MAIN (presumably for inclusion)
|
||||
and reports discrepancies.
|
||||
|
||||
This will have a number of
|
||||
"""
|
||||
|
||||
MAIN = "python39.spec"
|
||||
|
||||
import glob
|
||||
import re
|
||||
from os.path import basename
|
||||
|
||||
alltests = set()
|
||||
qemu_exclusions = set()
|
||||
|
||||
for item in glob.glob("Python-*/Lib/test/test_*"):
|
||||
testname = basename(item)
|
||||
if testname.endswith(".py"):
|
||||
testname = testname[:-3]
|
||||
alltests.add(testname)
|
||||
|
||||
testre = re.compile(r'[\s"](test_\w+)\b')
|
||||
|
||||
def find_tests_in_spec(specname):
|
||||
global qemu_exclusions
|
||||
|
||||
found_tests = set()
|
||||
with open(specname) as spec:
|
||||
in_qemu = False
|
||||
for line in spec:
|
||||
line = line.strip()
|
||||
if "#" in line:
|
||||
line = line[:line.index("#")]
|
||||
tests = set(testre.findall(line))
|
||||
found_tests |= tests
|
||||
if line == "%if 0%{?qemu_user_space_build} > 0":
|
||||
in_qemu = True
|
||||
if in_qemu:
|
||||
if line == "%endif":
|
||||
in_qemu = False
|
||||
qemu_exclusions |= tests
|
||||
return found_tests
|
||||
|
||||
excluded = find_tests_in_spec(MAIN)
|
||||
|
||||
#print("--- excluded tests:", " ".join(sorted(excluded)))
|
||||
#print("--- included tests:", " ".join(sorted(included)))
|
||||
|
||||
mentioned = excluded
|
||||
nonexistent = mentioned - alltests
|
||||
missing = excluded - qemu_exclusions
|
||||
|
||||
print("--- the following tests are excluded for QEMU and not tested in python")
|
||||
print("--- (that probably means we don't need to worry about them)")
|
||||
for test in sorted(qemu_exclusions - excluded):
|
||||
print(test)
|
||||
|
||||
print("--- the following tests might be excluded in python:")
|
||||
for test in sorted(missing):
|
||||
print(test)
|
||||
|
||||
if nonexistent:
|
||||
print("--- the following tests don't exist:")
|
||||
for test in sorted(nonexistent):
|
||||
print(test)
|
||||
21
subprocess-raise-timeout.patch
Normal file
21
subprocess-raise-timeout.patch
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
Lib/test/test_subprocess.py | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: Python-3.12.10/Lib/test/test_subprocess.py
|
||||
===================================================================
|
||||
--- Python-3.12.10.orig/Lib/test/test_subprocess.py 2025-04-11 21:04:45.154639562 +0200
|
||||
+++ Python-3.12.10/Lib/test/test_subprocess.py 2025-04-11 21:12:03.374471647 +0200
|
||||
@@ -274,7 +274,11 @@
|
||||
output = subprocess.check_output(
|
||||
[sys.executable, "-c",
|
||||
"import time; time.sleep(3600)"],
|
||||
- timeout=0.1)
|
||||
+ # Some heavily loaded buildbots (sparc Debian 3.x) require
|
||||
+ # this much time to start and print.
|
||||
+ # timeout=0.1)
|
||||
+ # OBS might require even more
|
||||
+ timeout=10)
|
||||
|
||||
def test_call_kwargs(self):
|
||||
# call() function with keyword args
|
||||
Reference in New Issue
Block a user