Compare commits
22 Commits
factory
...
slfo-main-
| Author | SHA256 | Date | |
|---|---|---|---|
| c0f5d18c1e | |||
| f1f4736355 | |||
| e51fa4e692 | |||
| da11e6e10a | |||
| a7efa91dcd | |||
| b58f975be7 | |||
| c7e438c2e0 | |||
| eb2298e3f2 | |||
| f9c64528f8 | |||
| 3386fc12ed | |||
| e8c68d65d4 | |||
| 96acb778b3 | |||
| 8d20edb449 | |||
| 64bae1f84b | |||
| 201e349852 | |||
| a90f4e560b | |||
| 0f47302d79 | |||
| 24d06dc05c | |||
| 3837884001 | |||
| a23dbf9cdf | |||
| 208ac0bda6 | |||
| 88b70a09e9 |
247
CVE-2025-6069-quad-complex-HTMLParser.patch
Normal file
247
CVE-2025-6069-quad-complex-HTMLParser.patch
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
From 9043edabc7e2f0dd655146e0a4571e2a0b2906af Mon Sep 17 00:00:00 2001
|
||||||
|
From: Serhiy Storchaka <storchaka@gmail.com>
|
||||||
|
Date: Fri, 13 Jun 2025 19:57:48 +0300
|
||||||
|
Subject: [PATCH] gh-135462: Fix quadratic complexity in processing special
|
||||||
|
input in HTMLParser (GH-135464)
|
||||||
|
|
||||||
|
End-of-file errors are now handled according to the HTML5 specs --
|
||||||
|
comments and declarations are automatically closed, tags are ignored.
|
||||||
|
(cherry picked from commit 6eb6c5dbfb528bd07d77b60fd71fd05d81d45c41)
|
||||||
|
|
||||||
|
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
|
||||||
|
---
|
||||||
|
Lib/html/parser.py | 41 +++-
|
||||||
|
Lib/test/test_htmlparser.py | 97 +++++++---
|
||||||
|
Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst | 4
|
||||||
|
3 files changed, 111 insertions(+), 31 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst
|
||||||
|
|
||||||
|
Index: Python-3.13.5/Lib/html/parser.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Lib/html/parser.py 2025-06-11 17:36:57.000000000 +0200
|
||||||
|
+++ Python-3.13.5/Lib/html/parser.py 2025-07-02 16:49:52.020175099 +0200
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
attr_charref = re.compile(r'&(#[0-9]+|#[xX][0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*)[;=]?')
|
||||||
|
|
||||||
|
starttagopen = re.compile('<[a-zA-Z]')
|
||||||
|
+endtagopen = re.compile('</[a-zA-Z]')
|
||||||
|
piclose = re.compile('>')
|
||||||
|
commentclose = re.compile(r'--\s*>')
|
||||||
|
# Note:
|
||||||
|
@@ -195,7 +196,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:
|
||||||
|
@@ -203,17 +204,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.13.5/Lib/test/test_htmlparser.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Lib/test/test_htmlparser.py 2025-06-11 17:36:57.000000000 +0200
|
||||||
|
+++ Python-3.13.5/Lib/test/test_htmlparser.py 2025-07-02 16:49:52.020821697 +0200
|
||||||
|
@@ -5,6 +5,7 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
+from test import support
|
||||||
|
|
||||||
|
|
||||||
|
class EventCollector(html.parser.HTMLParser):
|
||||||
|
@@ -430,28 +431,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')])])
|
||||||
|
@@ -576,21 +583,50 @@
|
||||||
|
for html, expected in data:
|
||||||
|
self._run_check(html, expected)
|
||||||
|
|
||||||
|
- def test_EOF_in_comments_or_decls(self):
|
||||||
|
+ def test_eof_in_comments(self):
|
||||||
|
data = [
|
||||||
|
- ('<!', [('data', '<!')]),
|
||||||
|
- ('<!-', [('data', '<!-')]),
|
||||||
|
- ('<!--', [('data', '<!--')]),
|
||||||
|
- ('<![', [('data', '<![')]),
|
||||||
|
- ('<![CDATA[', [('data', '<![CDATA[')]),
|
||||||
|
- ('<![CDATA[x', [('data', '<![CDATA[x')]),
|
||||||
|
- ('<!DOCTYPE', [('data', '<!DOCTYPE')]),
|
||||||
|
- ('<!DOCTYPE HTML', [('data', '<!DOCTYPE HTML')]),
|
||||||
|
+ ('<!--', [('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 = ('<! not really a comment >'
|
||||||
|
+ html = ('<!ELEMENT br EMPTY>'
|
||||||
|
+ '<! not really a comment >'
|
||||||
|
'<! not a comment either -->'
|
||||||
|
'<! -- close enough -->'
|
||||||
|
'<!><!<-- this was an empty comment>'
|
||||||
|
@@ -604,6 +640,7 @@
|
||||||
|
'<![CDATA]]>' # required '[' after CDATA
|
||||||
|
)
|
||||||
|
expected = [
|
||||||
|
+ ('comment', 'ELEMENT br EMPTY'),
|
||||||
|
('comment', ' not really a comment '),
|
||||||
|
('comment', ' not a comment either --'),
|
||||||
|
('comment', ' -- close enough --'),
|
||||||
|
@@ -684,6 +721,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.13.5/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.13.5/Misc/NEWS.d/next/Security/2025-06-13-15-55-22.gh-issue-135462.KBeJpc.rst 2025-07-02 16:49:52.021124951 +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 fd29bcd380150035ef825b762d8cd085bdab6e53 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.13.5/Lib/tarfile.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Lib/tarfile.py 2025-08-01 22:13:44.185826095 +0200
|
||||||
|
+++ Python-3.13.5/Lib/tarfile.py 2025-08-01 22:13:45.524140183 +0200
|
||||||
|
@@ -1636,6 +1636,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.13.5/Lib/test/test_tarfile.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Lib/test/test_tarfile.py 2025-06-11 17:36:57.000000000 +0200
|
||||||
|
+++ Python-3.13.5/Lib/test/test_tarfile.py 2025-08-01 22:13:45.524778259 +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"
|
||||||
|
@@ -4578,6 +4579,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.13.5/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.13.5/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst 2025-08-01 22:13:45.525174751 +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`.)
|
||||||
@@ -28,9 +28,11 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
|||||||
Lib/test/test_sysconfig.py | 17 +++++++++++--
|
Lib/test/test_sysconfig.py | 17 +++++++++++--
|
||||||
2 files changed, 67 insertions(+), 7 deletions(-)
|
2 files changed, 67 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
--- a/Lib/sysconfig/__init__.py
|
Index: Python-3.13.3/Lib/sysconfig/__init__.py
|
||||||
+++ b/Lib/sysconfig/__init__.py
|
===================================================================
|
||||||
@@ -106,6 +106,11 @@ if os.name == 'nt':
|
--- Python-3.13.3.orig/Lib/sysconfig/__init__.py 2025-04-08 15:54:08.000000000 +0200
|
||||||
|
+++ Python-3.13.3/Lib/sysconfig/__init__.py 2025-04-11 21:52:31.769387873 +0200
|
||||||
|
@@ -106,6 +106,11 @@
|
||||||
else:
|
else:
|
||||||
_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv']
|
_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv']
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
|||||||
def _get_implementation():
|
def _get_implementation():
|
||||||
return 'Python'
|
return 'Python'
|
||||||
|
|
||||||
@@ -167,13 +172,28 @@ if _HAS_USER_BASE:
|
@@ -167,13 +172,28 @@
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +73,7 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
|||||||
_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
|
_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
|
||||||
# Mutex guarding initialization of _CONFIG_VARS.
|
# Mutex guarding initialization of _CONFIG_VARS.
|
||||||
_CONFIG_VARS_LOCK = threading.RLock()
|
_CONFIG_VARS_LOCK = threading.RLock()
|
||||||
@@ -259,11 +279,40 @@ def _extend_dict(target_dict, other_dict
|
@@ -266,11 +286,40 @@
|
||||||
target_dict[key] = value
|
target_dict[key] = value
|
||||||
|
|
||||||
|
|
||||||
@@ -113,7 +115,7 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
|||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
# On Windows we want to substitute 'lib' for schemes rather
|
# On Windows we want to substitute 'lib' for schemes rather
|
||||||
# than the native value (without modifying vars, in case it
|
# than the native value (without modifying vars, in case it
|
||||||
@@ -464,10 +513,8 @@ def _init_config_vars():
|
@@ -471,10 +520,8 @@
|
||||||
# Normalized versions of prefix and exec_prefix are handy to have;
|
# Normalized versions of prefix and exec_prefix are handy to have;
|
||||||
# in fact, these are the standard versions used most places in the
|
# in fact, these are the standard versions used most places in the
|
||||||
# Distutils.
|
# Distutils.
|
||||||
@@ -126,9 +128,11 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
|||||||
_CONFIG_VARS['py_version'] = _PY_VERSION
|
_CONFIG_VARS['py_version'] = _PY_VERSION
|
||||||
_CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
|
_CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
|
||||||
_CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT
|
_CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT
|
||||||
--- a/Lib/test/test_sysconfig.py
|
Index: Python-3.13.3/Lib/test/test_sysconfig.py
|
||||||
+++ b/Lib/test/test_sysconfig.py
|
===================================================================
|
||||||
@@ -130,8 +130,19 @@ class TestSysConfig(unittest.TestCase):
|
--- Python-3.13.3.orig/Lib/test/test_sysconfig.py 2025-04-08 15:54:08.000000000 +0200
|
||||||
|
+++ Python-3.13.3/Lib/test/test_sysconfig.py 2025-04-11 21:52:31.769841915 +0200
|
||||||
|
@@ -130,8 +130,19 @@
|
||||||
for scheme in _INSTALL_SCHEMES:
|
for scheme in _INSTALL_SCHEMES:
|
||||||
for name in _INSTALL_SCHEMES[scheme]:
|
for name in _INSTALL_SCHEMES[scheme]:
|
||||||
expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
|
expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
|
||||||
@@ -149,7 +153,7 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
|||||||
os.path.normpath(expected),
|
os.path.normpath(expected),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -386,7 +397,7 @@ class TestSysConfig(unittest.TestCase):
|
@@ -386,7 +397,7 @@
|
||||||
self.assertTrue(os.path.isfile(config_h), config_h)
|
self.assertTrue(os.path.isfile(config_h), config_h)
|
||||||
|
|
||||||
def test_get_scheme_names(self):
|
def test_get_scheme_names(self):
|
||||||
@@ -158,7 +162,7 @@ Co-authored-by: Lumír Balhar <frenzy.madness@gmail.com>
|
|||||||
if HAS_USER_BASE:
|
if HAS_USER_BASE:
|
||||||
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
|
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
|
||||||
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
|
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
|
||||||
@@ -398,6 +409,8 @@ class TestSysConfig(unittest.TestCase):
|
@@ -398,6 +409,8 @@
|
||||||
cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
|
cmd = "-c", "import sysconfig; print(sysconfig.get_platform())"
|
||||||
self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
|
self.assertEqual(py.call_real(*cmd), py.call_link(*cmd))
|
||||||
|
|
||||||
|
|||||||
BIN
Python-3.13.2.tar.xz
(Stored with Git LFS)
BIN
Python-3.13.2.tar.xz
(Stored with Git LFS)
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
Python-3.13.5.tar.xz
(Stored with Git LFS)
Normal file
BIN
Python-3.13.5.tar.xz
(Stored with Git LFS)
Normal file
Binary file not shown.
1
Python-3.13.5.tar.xz.sigstore
Normal file
1
Python-3.13.5.tar.xz.sigstore
Normal file
File diff suppressed because one or more lines are too long
@@ -5,28 +5,30 @@ Subject: [PATCH] bpo-31046: ensurepip does not honour the value of $(prefix)
|
|||||||
|
|
||||||
Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
|
Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
|
||||||
---
|
---
|
||||||
Doc/library/ensurepip.rst | 9 +++--
|
Doc/library/ensurepip.rst | 12 +++++-
|
||||||
Lib/ensurepip/__init__.py | 18 +++++++---
|
Lib/ensurepip/__init__.py | 18 +++++++---
|
||||||
Lib/test/test_ensurepip.py | 11 ++++++
|
Lib/test/test_ensurepip.py | 11 ++++++
|
||||||
Makefile.pre.in | 4 +-
|
Makefile.pre.in | 4 +-
|
||||||
Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst | 1
|
Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst | 1
|
||||||
5 files changed, 34 insertions(+), 9 deletions(-)
|
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
|
create mode 100644 Misc/NEWS.d/next/Build/2019-12-16-17-50-42.bpo-31046.XA-Qfr.rst
|
||||||
|
|
||||||
--- a/Doc/library/ensurepip.rst
|
--- a/Doc/library/ensurepip.rst
|
||||||
+++ b/Doc/library/ensurepip.rst
|
+++ b/Doc/library/ensurepip.rst
|
||||||
@@ -59,8 +59,9 @@ is at least as recent as the one availab
|
@@ -61,7 +61,11 @@ is at least as recent as the one availab
|
||||||
By default, ``pip`` is installed into the current virtual environment
|
By default, ``pip`` is installed into the current virtual environment
|
||||||
(if one is active) or into the system site packages (if there is no
|
(if one is active) or into the system site packages (if there is no
|
||||||
active virtual environment). The installation location can be controlled
|
active virtual environment). The installation location can be controlled
|
||||||
-through two additional command line options:
|
-through two additional command line options:
|
||||||
+through some additional command line options:
|
+through some additional command line options:
|
||||||
|
+
|
||||||
|
+.. option:: --prefix <dir>
|
||||||
|
+
|
||||||
|
+ Installs ``pip`` using the given directory prefix.
|
||||||
|
|
||||||
+* ``--prefix <dir>``: Installs ``pip`` using the given directory prefix.
|
.. option:: --root <dir>
|
||||||
* :samp:`--root {dir}`: Installs ``pip`` relative to the given root directory
|
|
||||||
rather than the root of the currently active virtual environment (if any)
|
@@ -102,7 +106,7 @@ Module API
|
||||||
or the default root for the current Python installation.
|
|
||||||
@@ -92,7 +93,7 @@ Module API
|
|
||||||
Returns a string specifying the available version of pip that will be
|
Returns a string specifying the available version of pip that will be
|
||||||
installed when bootstrapping an environment.
|
installed when bootstrapping an environment.
|
||||||
|
|
||||||
@@ -35,7 +37,7 @@ Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
|
|||||||
altinstall=False, default_pip=False, \
|
altinstall=False, default_pip=False, \
|
||||||
verbosity=0)
|
verbosity=0)
|
||||||
|
|
||||||
@@ -102,6 +103,8 @@ Module API
|
@@ -112,6 +116,8 @@ Module API
|
||||||
If *root* is ``None``, then installation uses the default install location
|
If *root* is ``None``, then installation uses the default install location
|
||||||
for the current environment.
|
for the current environment.
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
|
|||||||
*upgrade* indicates whether or not to upgrade an existing installation
|
*upgrade* indicates whether or not to upgrade an existing installation
|
||||||
of an earlier version of ``pip`` to the available version.
|
of an earlier version of ``pip`` to the available version.
|
||||||
|
|
||||||
@@ -122,6 +125,8 @@ Module API
|
@@ -132,6 +138,8 @@ Module API
|
||||||
*verbosity* controls the level of output to :data:`sys.stdout` from the
|
*verbosity* controls the level of output to :data:`sys.stdout` from the
|
||||||
bootstrapping operation.
|
bootstrapping operation.
|
||||||
|
|
||||||
@@ -139,7 +141,7 @@ Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
|
|||||||
|
|
||||||
--- a/Makefile.pre.in
|
--- a/Makefile.pre.in
|
||||||
+++ b/Makefile.pre.in
|
+++ b/Makefile.pre.in
|
||||||
@@ -2139,7 +2139,7 @@ install: @FRAMEWORKINSTALLFIRST@ @INSTAL
|
@@ -2145,7 +2145,7 @@ install: @FRAMEWORKINSTALLFIRST@ @INSTAL
|
||||||
install|*) ensurepip="" ;; \
|
install|*) ensurepip="" ;; \
|
||||||
esac; \
|
esac; \
|
||||||
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
|
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
|
||||||
@@ -148,7 +150,7 @@ Co-Authored-By: Xavier de Gaye <xdegaye@gmail.com>
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: altinstall
|
.PHONY: altinstall
|
||||||
@@ -2150,7 +2150,7 @@ altinstall: commoninstall
|
@@ -2156,7 +2156,7 @@ altinstall: commoninstall
|
||||||
install|*) ensurepip="--altinstall" ;; \
|
install|*) ensurepip="--altinstall" ;; \
|
||||||
esac; \
|
esac; \
|
||||||
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m ensurepip \
|
$(RUNSHARED) $(PYTHON_FOR_BUILD) -m 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.13.5/Doc/tools/extensions/audit_events.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/audit_events.py 2025-07-02 15:51:58.388560540 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/audit_events.py 2025-07-02 15:51:58.411254070 +0200
|
||||||
|
@@ -72,8 +72,13 @@
|
||||||
|
logger.warning(msg)
|
||||||
|
return
|
||||||
|
|
||||||
|
- def id_for(self, name) -> str:
|
||||||
|
- source_count = len(self.sources.get(name, set()))
|
||||||
|
+ 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}"
|
||||||
|
|
||||||
|
@@ -148,7 +153,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))
|
||||||
|
|
||||||
@@ -1,35 +1,152 @@
|
|||||||
---
|
---
|
||||||
Doc/conf.py | 17 ++++++++--
|
Doc/Makefile | 8 +--
|
||||||
Doc/tools/check-warnings.py | 3 +
|
Doc/c-api/arg.rst | 1
|
||||||
Doc/tools/extensions/audit_events.py | 54 ++++++++++++++++----------------
|
Doc/c-api/typeobj.rst | 8 +--
|
||||||
Doc/tools/extensions/availability.py | 15 ++++----
|
Doc/conf.py | 29 ++++++++++---
|
||||||
Doc/tools/extensions/c_annotations.py | 45 ++++++++++++++++----------
|
Doc/howto/free-threading-python.rst | 2
|
||||||
Doc/tools/extensions/glossary_search.py | 10 +----
|
Doc/library/doctest.rst | 1
|
||||||
Doc/tools/extensions/patchlevel.py | 9 ++---
|
Doc/library/email.compat32-message.rst | 1
|
||||||
7 files changed, 87 insertions(+), 66 deletions(-)
|
Doc/library/xml.etree.elementtree.rst | 1
|
||||||
|
Doc/Makefile | 8 +--
|
||||||
|
Doc/c-api/arg.rst | 1
|
||||||
|
Doc/c-api/typeobj.rst | 8 +--
|
||||||
|
Doc/conf.py | 29 ++++++++++---
|
||||||
|
Doc/library/doctest.rst | 1
|
||||||
|
Doc/library/email.compat32-message.rst | 1
|
||||||
|
Doc/library/xml.etree.elementtree.rst | 1
|
||||||
|
Doc/tools/check-warnings.py | 5 +-
|
||||||
|
Doc/tools/extensions/audit_events.py | 56 ++++++++++++++------------
|
||||||
|
Doc/tools/extensions/availability.py | 15 +++---
|
||||||
|
Doc/tools/extensions/c_annotations.py | 53 ++++++++++++++++--------
|
||||||
|
Doc/tools/extensions/changes.py | 8 +--
|
||||||
|
Doc/tools/extensions/glossary_search.py | 20 ++++++---
|
||||||
|
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 +++++-----
|
||||||
|
18 files changed, 159 insertions(+), 130 deletions(-)
|
||||||
|
|
||||||
--- a/Doc/conf.py
|
Index: Python-3.13.5/Doc/Makefile
|
||||||
+++ b/Doc/conf.py
|
===================================================================
|
||||||
@@ -17,6 +17,9 @@ sys.path.append(os.path.abspath('include
|
--- Python-3.13.5.orig/Doc/Makefile 2025-06-12 21:37:37.257659788 +0200
|
||||||
# Python specific content from Doc/Tools/extensions/pyspecific.py
|
+++ Python-3.13.5/Doc/Makefile 2025-06-12 21:38:04.908380762 +0200
|
||||||
from pyspecific import SOURCE_URI
|
@@ -14,15 +14,15 @@
|
||||||
|
SOURCES =
|
||||||
|
DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py)
|
||||||
|
REQUIREMENTS = requirements.txt
|
||||||
|
-SPHINXERRORHANDLING = --fail-on-warning
|
||||||
|
+SPHINXERRORHANDLING =
|
||||||
|
|
||||||
+# Needed for fixing extlinks modification
|
# Internal variables.
|
||||||
+from sphinx import version_info as sphinx_version
|
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.13.5/Doc/c-api/arg.rst
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/c-api/arg.rst 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/c-api/arg.rst 2025-06-12 21:38:04.908705133 +0200
|
||||||
|
@@ -334,7 +334,6 @@
|
||||||
|
should raise an exception and leave the content of *address* unmodified.
|
||||||
|
|
||||||
|
.. c:macro:: Py_CLEANUP_SUPPORTED
|
||||||
|
- :no-typesetting:
|
||||||
|
|
||||||
|
If the *converter* returns :c:macro:`!Py_CLEANUP_SUPPORTED`, it may get called a
|
||||||
|
second time if the argument parsing eventually fails, giving the converter a
|
||||||
|
Index: Python-3.13.5/Doc/c-api/typeobj.rst
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/c-api/typeobj.rst 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/c-api/typeobj.rst 2025-06-12 21:38:04.908874058 +0200
|
||||||
|
@@ -610,7 +610,7 @@
|
||||||
|
Functions like :c:func:`PyObject_NewVar` will take the value of N as an
|
||||||
|
argument, and store in the instance's :c:member:`~PyVarObject.ob_size` field.
|
||||||
|
Note that the :c:member:`~PyVarObject.ob_size` field may later be used for
|
||||||
|
- other purposes. For example, :py:type:`int` instances use the bits of
|
||||||
|
+ other purposes. For example, :py:obj:`int` instances use the bits of
|
||||||
|
:c:member:`~PyVarObject.ob_size` in an implementation-defined
|
||||||
|
way; the underlying storage and its size should be accessed using
|
||||||
|
:c:func:`PyLong_Export`.
|
||||||
|
@@ -622,9 +622,9 @@
|
||||||
|
|
||||||
|
Also, the presence of an :c:member:`~PyVarObject.ob_size` field in the
|
||||||
|
instance layout doesn't mean that the instance structure is variable-length.
|
||||||
|
- For example, the :py:type:`list` type has fixed-length instances, yet those
|
||||||
|
+ For example, the :py:obj:`list` type has fixed-length instances, yet those
|
||||||
|
instances have a :c:member:`~PyVarObject.ob_size` field.
|
||||||
|
- (As with :py:type:`int`, avoid reading lists' :c:member:`!ob_size` directly.
|
||||||
|
+ (As with :py:obj:`int`, avoid reading lists' :c:member:`!ob_size` directly.
|
||||||
|
Call :c:func:`PyList_Size` instead.)
|
||||||
|
|
||||||
|
The :c:member:`!tp_basicsize` includes size needed for data of the type's
|
||||||
|
@@ -637,7 +637,7 @@
|
||||||
|
In other words, :c:member:`!tp_basicsize` must be greater than or equal
|
||||||
|
to the base's :c:member:`!tp_basicsize`.
|
||||||
|
|
||||||
|
- Since every type is a subtype of :py:type:`object`, this struct must
|
||||||
|
+ Since every type is a subtype of :py:obj:`object`, this struct must
|
||||||
|
include :c:type:`PyObject` or :c:type:`PyVarObject` (depending on
|
||||||
|
whether :c:member:`~PyVarObject.ob_size` should be included). These are
|
||||||
|
usually defined by the macro :c:macro:`PyObject_HEAD` or
|
||||||
|
Index: Python-3.13.5/Doc/conf.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/conf.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/conf.py 2025-06-12 21:38:04.909609597 +0200
|
||||||
|
@@ -11,6 +11,8 @@
|
||||||
|
from importlib import import_module
|
||||||
|
from importlib.util import find_spec
|
||||||
|
|
||||||
|
+from sphinx import version_info
|
||||||
+
|
+
|
||||||
# General configuration
|
# Make our custom extensions available to Sphinx
|
||||||
# ---------------------
|
sys.path.append(os.path.abspath('tools/extensions'))
|
||||||
|
sys.path.append(os.path.abspath('includes'))
|
||||||
|
@@ -57,11 +59,11 @@
|
||||||
|
import _tkinter
|
||||||
|
except ImportError:
|
||||||
|
_tkinter = None
|
||||||
|
-# Treat warnings as errors, done here to prevent warnings in Sphinx code from
|
||||||
|
-# causing spurious CPython test failures.
|
||||||
|
-import warnings
|
||||||
|
-warnings.simplefilter('error')
|
||||||
|
-del warnings
|
||||||
|
+# # Treat warnings as errors, done here to prevent warnings in Sphinx code from
|
||||||
|
+# # causing spurious CPython test failures.
|
||||||
|
+# import warnings
|
||||||
|
+# warnings.simplefilter('error')
|
||||||
|
+# del warnings
|
||||||
|
'''
|
||||||
|
|
||||||
@@ -90,7 +93,7 @@ highlight_language = 'python3'
|
manpages_url = 'https://manpages.debian.org/{path}'
|
||||||
|
@@ -92,7 +94,7 @@
|
||||||
|
|
||||||
# Minimum version of sphinx required
|
# Minimum version of sphinx required
|
||||||
# Keep this version in sync with ``Doc/requirements.txt``.
|
# Keep this version in sync with ``Doc/requirements.txt``.
|
||||||
-needs_sphinx = '8.1.3'
|
-needs_sphinx = '8.2.0'
|
||||||
+needs_sphinx = '4.2.0'
|
+needs_sphinx = '4.2.0'
|
||||||
|
|
||||||
# Create table of contents entries for domain objects (e.g. functions, classes,
|
# Create table of contents entries for domain objects (e.g. functions, classes,
|
||||||
# attributes, etc.). Default is True.
|
# attributes, etc.). Default is True.
|
||||||
@@ -359,7 +362,7 @@ html_short_title = f'{release} Documenta
|
@@ -323,6 +325,9 @@
|
||||||
|
# Avoid a warning with Sphinx >= 4.0
|
||||||
|
root_doc = 'contents'
|
||||||
|
|
||||||
|
+# Compatibility on old Sphinx
|
||||||
|
+suppress_warnings = ['pygments.ParserNotFound']
|
||||||
|
+
|
||||||
|
# Allow translation of index directives
|
||||||
|
gettext_additional_targets = [
|
||||||
|
'index',
|
||||||
|
@@ -362,7 +367,7 @@
|
||||||
# (See .readthedocs.yml and https://docs.readthedocs.io/en/stable/reference/environment-variables.html)
|
# (See .readthedocs.yml and https://docs.readthedocs.io/en/stable/reference/environment-variables.html)
|
||||||
is_deployment_preview = os.getenv("READTHEDOCS_VERSION_TYPE") == "external"
|
is_deployment_preview = os.getenv("READTHEDOCS_VERSION_TYPE") == "external"
|
||||||
repository_url = os.getenv("READTHEDOCS_GIT_CLONE_URL", "")
|
repository_url = os.getenv("READTHEDOCS_GIT_CLONE_URL", "")
|
||||||
@@ -38,11 +155,11 @@
|
|||||||
html_context = {
|
html_context = {
|
||||||
"is_deployment_preview": is_deployment_preview,
|
"is_deployment_preview": is_deployment_preview,
|
||||||
"repository_url": repository_url or None,
|
"repository_url": repository_url or None,
|
||||||
@@ -604,6 +607,16 @@ extlinks = {
|
@@ -607,6 +612,16 @@
|
||||||
}
|
}
|
||||||
extlinks_detect_hardcoded_links = True
|
extlinks_detect_hardcoded_links = True
|
||||||
|
|
||||||
+if sphinx_version[:2] < (8, 1):
|
+if version_info[:2] < (8, 1):
|
||||||
+ # Sphinx 8.1 has in-built CVE and CWE roles.
|
+ # Sphinx 8.1 has in-built CVE and CWE roles.
|
||||||
+ extlinks.update({
|
+ extlinks.update({
|
||||||
+ "cve": (
|
+ "cve": (
|
||||||
@@ -55,9 +172,47 @@
|
|||||||
# Options for c_annotations extension
|
# Options for c_annotations extension
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
|
|
||||||
--- a/Doc/tools/check-warnings.py
|
Index: Python-3.13.5/Doc/library/doctest.rst
|
||||||
+++ b/Doc/tools/check-warnings.py
|
===================================================================
|
||||||
@@ -228,7 +228,8 @@ def fail_if_regression(
|
--- Python-3.13.5.orig/Doc/library/doctest.rst 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/library/doctest.rst 2025-06-12 21:38:04.909944989 +0200
|
||||||
|
@@ -308,7 +308,6 @@
|
||||||
|
searched. Objects imported into the module are not searched.
|
||||||
|
|
||||||
|
.. attribute:: module.__test__
|
||||||
|
- :no-typesetting:
|
||||||
|
|
||||||
|
In addition, there are cases when you want tests to be part of a module but not part
|
||||||
|
of the help text, which requires that the tests not be included in the docstring.
|
||||||
|
Index: Python-3.13.5/Doc/library/email.compat32-message.rst
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/library/email.compat32-message.rst 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/library/email.compat32-message.rst 2025-06-12 21:38:04.910320877 +0200
|
||||||
|
@@ -7,7 +7,6 @@
|
||||||
|
:synopsis: The base class representing email messages in a fashion
|
||||||
|
backward compatible with Python 3.2
|
||||||
|
:noindex:
|
||||||
|
- :no-index:
|
||||||
|
|
||||||
|
|
||||||
|
The :class:`Message` class is very similar to the
|
||||||
|
Index: Python-3.13.5/Doc/library/xml.etree.elementtree.rst
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/library/xml.etree.elementtree.rst 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/library/xml.etree.elementtree.rst 2025-06-12 21:38:04.910594893 +0200
|
||||||
|
@@ -874,7 +874,6 @@
|
||||||
|
|
||||||
|
.. module:: xml.etree.ElementTree
|
||||||
|
:noindex:
|
||||||
|
- :no-index:
|
||||||
|
|
||||||
|
.. class:: Element(tag, attrib={}, **extra)
|
||||||
|
|
||||||
|
Index: Python-3.13.5/Doc/tools/check-warnings.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/check-warnings.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/check-warnings.py 2025-06-12 21:38:04.910896050 +0200
|
||||||
|
@@ -228,7 +228,8 @@
|
||||||
print(filename)
|
print(filename)
|
||||||
for warning in warnings:
|
for warning in warnings:
|
||||||
if filename in warning:
|
if filename in warning:
|
||||||
@@ -67,8 +222,19 @@
|
|||||||
print(" {line}: {msg}".format_map(match))
|
print(" {line}: {msg}".format_map(match))
|
||||||
return -1
|
return -1
|
||||||
return 0
|
return 0
|
||||||
--- a/Doc/tools/extensions/audit_events.py
|
@@ -316,7 +317,7 @@
|
||||||
+++ b/Doc/tools/extensions/audit_events.py
|
|
||||||
|
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.13.5/Doc/tools/extensions/audit_events.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/audit_events.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/audit_events.py 2025-06-12 21:38:04.911151491 +0200
|
||||||
@@ -1,9 +1,6 @@
|
@@ -1,9 +1,6 @@
|
||||||
"""Support for documenting audit events."""
|
"""Support for documenting audit events."""
|
||||||
|
|
||||||
@@ -79,34 +245,42 @@
|
|||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from sphinx.errors import NoUri
|
from sphinx.errors import NoUri
|
||||||
@@ -12,12 +9,11 @@ from sphinx.transforms.post_transforms i
|
@@ -12,12 +9,19 @@
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.docutils import SphinxDirective
|
from sphinx.util.docutils import SphinxDirective
|
||||||
|
|
||||||
-if TYPE_CHECKING:
|
-if TYPE_CHECKING:
|
||||||
- from collections.abc import Iterator
|
- from collections.abc import Iterator, Set
|
||||||
+from typing import Any, List, Tuple
|
+from typing import Any, Iterator, List, Set, Tuple
|
||||||
|
+
|
||||||
|
+from sphinx.application import Sphinx
|
||||||
|
+from sphinx.builders import Builder
|
||||||
|
+from sphinx.environment import BuildEnvironment
|
||||||
|
+
|
||||||
|
+# --- The Monkey Patch ---
|
||||||
|
+def findall_patch(self, *args, **kwargs):
|
||||||
|
+ """A backwards-compatible findall method that calls traverse."""
|
||||||
|
+ return self.traverse(*args, **kwargs)
|
||||||
|
|
||||||
- from sphinx.application import Sphinx
|
- from sphinx.application import Sphinx
|
||||||
- from sphinx.builders import Builder
|
- from sphinx.builders import Builder
|
||||||
- from sphinx.environment import BuildEnvironment
|
- from sphinx.environment import BuildEnvironment
|
||||||
+from sphinx.application import Sphinx
|
+if not hasattr(nodes.Node, 'findall'):
|
||||||
+from sphinx.builders import Builder
|
+ nodes.Node.findall = findall_patch
|
||||||
+from sphinx.environment import BuildEnvironment
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -32,16 +28,16 @@ _SYNONYMS = [
|
@@ -32,16 +36,16 @@
|
||||||
|
|
||||||
class AuditEvents:
|
class AuditEvents:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
- self.events: dict[str, list[str]] = {}
|
- self.events: dict[str, list[str]] = {}
|
||||||
- self.sources: dict[str, list[tuple[str, str]]] = {}
|
- self.sources: dict[str, set[tuple[str, str]]] = {}
|
||||||
+ self.events: dict[str, List[str]] = {}
|
+ self.events: dict[str, List[str]] = {}
|
||||||
+ self.sources: dict[str, List[Tuple[str, str]]] = {}
|
+ self.sources: dict[str, Set[Tuple[str, str]]] = {}
|
||||||
|
|
||||||
- def __iter__(self) -> Iterator[tuple[str, list[str], tuple[str, str]]]:
|
- def __iter__(self) -> Iterator[tuple[str, list[str], tuple[str, str]]]:
|
||||||
+ def __iter__(self) -> Any:
|
+ def __iter__(self) -> Iterator[Any]:
|
||||||
for name, args in self.events.items():
|
for name, args in self.events.items():
|
||||||
for source in self.sources[name]:
|
for source in self.sources[name]:
|
||||||
yield name, args, source
|
yield name, args, source
|
||||||
@@ -117,16 +291,16 @@
|
|||||||
) -> None:
|
) -> None:
|
||||||
if name in self.events:
|
if name in self.events:
|
||||||
self._check_args_match(name, args)
|
self._check_args_match(name, args)
|
||||||
@@ -49,7 +45,7 @@ class AuditEvents:
|
@@ -49,7 +53,7 @@
|
||||||
self.events[name] = args
|
self.events[name] = args
|
||||||
self.sources.setdefault(name, []).append(source)
|
self.sources.setdefault(name, set()).add(source)
|
||||||
|
|
||||||
- def _check_args_match(self, name: str, args: list[str]) -> None:
|
- def _check_args_match(self, name: str, args: list[str]) -> None:
|
||||||
+ 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]
|
current_args = self.events[name]
|
||||||
msg = (
|
msg = (
|
||||||
f"Mismatched arguments for audit-event {name}: "
|
f"Mismatched arguments for audit-event {name}: "
|
||||||
@@ -60,7 +56,7 @@ class AuditEvents:
|
@@ -60,7 +64,7 @@
|
||||||
if len(current_args) != len(args):
|
if len(current_args) != len(args):
|
||||||
logger.warning(msg)
|
logger.warning(msg)
|
||||||
return
|
return
|
||||||
@@ -135,16 +309,16 @@
|
|||||||
if a1 == a2:
|
if a1 == a2:
|
||||||
continue
|
continue
|
||||||
if any(a1 in s and a2 in s for s in _SYNONYMS):
|
if any(a1 in s and a2 in s for s in _SYNONYMS):
|
||||||
@@ -73,7 +69,7 @@ class AuditEvents:
|
@@ -73,7 +77,7 @@
|
||||||
name_clean = re.sub(r"\W", "_", name)
|
name_clean = re.sub(r"\W", "_", name)
|
||||||
return f"audit_event_{name_clean}_{source_count}"
|
return f"audit_event_{name_clean}_{source_count}"
|
||||||
|
|
||||||
- def rows(self) -> Iterator[tuple[str, list[str], list[tuple[str, str]]]]:
|
- def rows(self) -> Iterator[tuple[str, list[str], Set[tuple[str, str]]]]:
|
||||||
+ def rows(self) -> Any:
|
+ def rows(self) -> Iterator[Any]:
|
||||||
for name in sorted(self.events.keys()):
|
for name in sorted(self.events.keys()):
|
||||||
yield name, self.events[name], self.sources[name]
|
yield name, self.events[name], self.sources[name]
|
||||||
|
|
||||||
@@ -97,7 +93,7 @@ def audit_events_purge(
|
@@ -97,7 +101,7 @@
|
||||||
def audit_events_merge(
|
def audit_events_merge(
|
||||||
app: Sphinx,
|
app: Sphinx,
|
||||||
env: BuildEnvironment,
|
env: BuildEnvironment,
|
||||||
@@ -153,7 +327,7 @@
|
|||||||
other: BuildEnvironment,
|
other: BuildEnvironment,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""In Sphinx parallel builds, this merges audit_events from subprocesses."""
|
"""In Sphinx parallel builds, this merges audit_events from subprocesses."""
|
||||||
@@ -126,14 +122,16 @@ class AuditEvent(SphinxDirective):
|
@@ -126,14 +130,16 @@
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -176,7 +350,7 @@
|
|||||||
else:
|
else:
|
||||||
args = []
|
args = []
|
||||||
ids = []
|
ids = []
|
||||||
@@ -169,7 +167,7 @@ class audit_event_list(nodes.General, no
|
@@ -169,7 +175,7 @@
|
||||||
|
|
||||||
|
|
||||||
class AuditEventListDirective(SphinxDirective):
|
class AuditEventListDirective(SphinxDirective):
|
||||||
@@ -185,32 +359,21 @@
|
|||||||
return [audit_event_list()]
|
return [audit_event_list()]
|
||||||
|
|
||||||
|
|
||||||
@@ -181,7 +179,11 @@ class AuditEventListTransform(SphinxPost
|
@@ -217,8 +223,8 @@
|
||||||
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 @@ class AuditEventListTransform(SphinxPost
|
|
||||||
builder: Builder,
|
builder: Builder,
|
||||||
docname: str,
|
docname: str,
|
||||||
name: str,
|
name: str,
|
||||||
- args: list[str],
|
- args: list[str],
|
||||||
- sources: list[tuple[str, str]],
|
- sources: Set[tuple[str, str]],
|
||||||
+ args: List[str],
|
+ args: List[str],
|
||||||
+ sources: List[Tuple[str, str]],
|
+ sources: Set[Tuple[str, str]],
|
||||||
) -> nodes.row:
|
) -> nodes.row:
|
||||||
row = nodes.row()
|
row = nodes.row()
|
||||||
name_node = nodes.paragraph("", nodes.Text(name))
|
name_node = nodes.paragraph("", nodes.Text(name))
|
||||||
--- a/Doc/tools/extensions/availability.py
|
Index: Python-3.13.5/Doc/tools/extensions/availability.py
|
||||||
+++ b/Doc/tools/extensions/availability.py
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/availability.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/availability.py 2025-06-12 21:38:04.911376735 +0200
|
||||||
@@ -1,8 +1,6 @@
|
@@ -1,8 +1,6 @@
|
||||||
"""Support for documenting platform availability"""
|
"""Support for documenting platform availability"""
|
||||||
|
|
||||||
@@ -221,7 +384,7 @@
|
|||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
@@ -55,7 +53,7 @@ class Availability(SphinxDirective):
|
@@ -55,7 +53,7 @@
|
||||||
optional_arguments = 0
|
optional_arguments = 0
|
||||||
final_argument_whitespace = True
|
final_argument_whitespace = True
|
||||||
|
|
||||||
@@ -230,7 +393,7 @@
|
|||||||
title = sphinx_gettext("Availability")
|
title = sphinx_gettext("Availability")
|
||||||
refnode = addnodes.pending_xref(
|
refnode = addnodes.pending_xref(
|
||||||
title,
|
title,
|
||||||
@@ -79,7 +77,7 @@ class Availability(SphinxDirective):
|
@@ -79,7 +77,7 @@
|
||||||
|
|
||||||
return [cnode]
|
return [cnode]
|
||||||
|
|
||||||
@@ -239,7 +402,7 @@
|
|||||||
"""Parse platform information from arguments
|
"""Parse platform information from arguments
|
||||||
|
|
||||||
Arguments is a comma-separated string of platforms. A platform may
|
Arguments is a comma-separated string of platforms. A platform may
|
||||||
@@ -98,12 +96,13 @@ class Availability(SphinxDirective):
|
@@ -98,12 +96,13 @@
|
||||||
platform, _, version = arg.partition(" >= ")
|
platform, _, version = arg.partition(" >= ")
|
||||||
if platform.startswith("not "):
|
if platform.startswith("not "):
|
||||||
version = False
|
version = False
|
||||||
@@ -255,7 +418,7 @@
|
|||||||
logger.warning(
|
logger.warning(
|
||||||
"Unknown platform%s or syntax '%s' in '.. availability:: %s', "
|
"Unknown platform%s or syntax '%s' in '.. availability:: %s', "
|
||||||
"see %s:KNOWN_PLATFORMS for a set of known platforms.",
|
"see %s:KNOWN_PLATFORMS for a set of known platforms.",
|
||||||
@@ -116,7 +115,7 @@ class Availability(SphinxDirective):
|
@@ -116,7 +115,7 @@
|
||||||
return platforms
|
return platforms
|
||||||
|
|
||||||
|
|
||||||
@@ -264,9 +427,11 @@
|
|||||||
app.add_directive("availability", Availability)
|
app.add_directive("availability", Availability)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
--- a/Doc/tools/extensions/c_annotations.py
|
Index: Python-3.13.5/Doc/tools/extensions/c_annotations.py
|
||||||
+++ b/Doc/tools/extensions/c_annotations.py
|
===================================================================
|
||||||
@@ -9,22 +9,18 @@ Configuration:
|
--- Python-3.13.5.orig/Doc/tools/extensions/c_annotations.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/c_annotations.py 2025-06-12 21:38:04.911575881 +0200
|
||||||
|
@@ -9,22 +9,26 @@
|
||||||
* Set ``stable_abi_file`` to the path to stable ABI list.
|
* Set ``stable_abi_file`` to the path to stable ABI list.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -289,10 +454,18 @@
|
|||||||
- from sphinx.application import Sphinx
|
- from sphinx.application import Sphinx
|
||||||
- from sphinx.util.typing import ExtensionMetadata
|
- from sphinx.util.typing import ExtensionMetadata
|
||||||
+from sphinx.application import Sphinx
|
+from sphinx.application import Sphinx
|
||||||
|
+
|
||||||
|
+# --- The Monkey Patch ---
|
||||||
|
+def findall_patch(self, *args, **kwargs):
|
||||||
|
+ """A backwards-compatible findall method that calls traverse."""
|
||||||
|
+ return self.traverse(*args, **kwargs)
|
||||||
|
+
|
||||||
|
+if not hasattr(nodes.Node, 'findall'):
|
||||||
|
+ nodes.Node.findall = findall_patch
|
||||||
|
|
||||||
ROLE_TO_OBJECT_TYPE = {
|
ROLE_TO_OBJECT_TYPE = {
|
||||||
"func": "function",
|
"func": "function",
|
||||||
@@ -35,20 +31,20 @@ ROLE_TO_OBJECT_TYPE = {
|
@@ -35,20 +39,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -317,7 +490,7 @@
|
|||||||
class StableABIEntry:
|
class StableABIEntry:
|
||||||
# Role of the object.
|
# Role of the object.
|
||||||
# Source: Each [item_kind] in stable_abi.toml is mapped to a C Domain role.
|
# Source: Each [item_kind] in stable_abi.toml is mapped to a C Domain role.
|
||||||
@@ -67,7 +63,7 @@ class StableABIEntry:
|
@@ -67,7 +71,7 @@
|
||||||
struct_abi_kind: str
|
struct_abi_kind: str
|
||||||
|
|
||||||
|
|
||||||
@@ -326,7 +499,7 @@
|
|||||||
refcount_data = {}
|
refcount_data = {}
|
||||||
refcounts = refcount_filename.read_text(encoding="utf8")
|
refcounts = refcount_filename.read_text(encoding="utf8")
|
||||||
for line in refcounts.splitlines():
|
for line in refcounts.splitlines():
|
||||||
@@ -103,7 +99,7 @@ def read_refcount_data(refcount_filename
|
@@ -103,7 +107,7 @@
|
||||||
return refcount_data
|
return refcount_data
|
||||||
|
|
||||||
|
|
||||||
@@ -335,7 +508,7 @@
|
|||||||
stable_abi_data = {}
|
stable_abi_data = {}
|
||||||
with open(stable_abi_file, encoding="utf8") as fp:
|
with open(stable_abi_file, encoding="utf8") as fp:
|
||||||
for record in csv.DictReader(fp):
|
for record in csv.DictReader(fp):
|
||||||
@@ -123,11 +119,14 @@ def add_annotations(app: Sphinx, doctree
|
@@ -123,11 +127,14 @@
|
||||||
continue
|
continue
|
||||||
if not par[0].get("ids", None):
|
if not par[0].get("ids", None):
|
||||||
continue
|
continue
|
||||||
@@ -352,7 +525,7 @@
|
|||||||
if ROLE_TO_OBJECT_TYPE[record.role] != objtype:
|
if ROLE_TO_OBJECT_TYPE[record.role] != objtype:
|
||||||
msg = (
|
msg = (
|
||||||
f"Object type mismatch in limited API annotation for {name}: "
|
f"Object type mismatch in limited API annotation for {name}: "
|
||||||
@@ -234,7 +233,7 @@ def _unstable_api_annotation() -> nodes.
|
@@ -234,7 +241,7 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -361,7 +534,7 @@
|
|||||||
classes = ["refcount"]
|
classes = ["refcount"]
|
||||||
if result_refs is None:
|
if result_refs is None:
|
||||||
rc = sphinx_gettext("Return value: Always NULL.")
|
rc = sphinx_gettext("Return value: Always NULL.")
|
||||||
@@ -254,7 +253,7 @@ class LimitedAPIList(SphinxDirective):
|
@@ -254,7 +261,7 @@
|
||||||
optional_arguments = 0
|
optional_arguments = 0
|
||||||
final_argument_whitespace = True
|
final_argument_whitespace = True
|
||||||
|
|
||||||
@@ -370,7 +543,7 @@
|
|||||||
state = self.env.domaindata["c_annotations"]
|
state = self.env.domaindata["c_annotations"]
|
||||||
content = [
|
content = [
|
||||||
f"* :c:{record.role}:`{record.name}`"
|
f"* :c:{record.role}:`{record.name}`"
|
||||||
@@ -277,13 +276,23 @@ def init_annotations(app: Sphinx) -> Non
|
@@ -277,13 +284,23 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -395,9 +568,50 @@
|
|||||||
return {
|
return {
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"parallel_read_safe": True,
|
"parallel_read_safe": True,
|
||||||
--- a/Doc/tools/extensions/glossary_search.py
|
Index: Python-3.13.5/Doc/tools/extensions/changes.py
|
||||||
+++ b/Doc/tools/extensions/glossary_search.py
|
===================================================================
|
||||||
@@ -1,18 +1,14 @@
|
--- Python-3.13.5.orig/Doc/tools/extensions/changes.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/changes.py 2025-06-12 21:38:04.911758715 +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.13.5/Doc/tools/extensions/glossary_search.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/glossary_search.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/glossary_search.py 2025-06-12 21:38:04.911907976 +0200
|
||||||
|
@@ -1,21 +1,27 @@
|
||||||
"""Feature search results for glossary items prominently."""
|
"""Feature search results for glossary items prominently."""
|
||||||
|
|
||||||
-from __future__ import annotations
|
-from __future__ import annotations
|
||||||
@@ -418,7 +632,20 @@
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -52,7 +48,7 @@ def write_glossary_json(app: Sphinx, _ex
|
+from docutils import nodes
|
||||||
|
+from sphinx import addnodes
|
||||||
|
+
|
||||||
|
+# --- The Monkey Patch ---
|
||||||
|
+def findall_patch(self, *args, **kwargs):
|
||||||
|
+ """A backwards-compatible findall method that calls traverse."""
|
||||||
|
+ return self.traverse(*args, **kwargs)
|
||||||
|
+
|
||||||
|
+if not hasattr(nodes.Node, 'findall'):
|
||||||
|
+ nodes.Node.findall = findall_patch
|
||||||
|
|
||||||
|
def process_glossary_nodes(
|
||||||
|
app: Sphinx,
|
||||||
|
@@ -52,7 +58,7 @@
|
||||||
dest.write_text(json.dumps(app.env.glossary_terms), encoding='utf-8')
|
dest.write_text(json.dumps(app.env.glossary_terms), encoding='utf-8')
|
||||||
|
|
||||||
|
|
||||||
@@ -427,8 +654,169 @@
|
|||||||
app.connect('doctree-resolved', process_glossary_nodes)
|
app.connect('doctree-resolved', process_glossary_nodes)
|
||||||
app.connect('build-finished', write_glossary_json)
|
app.connect('build-finished', write_glossary_json)
|
||||||
|
|
||||||
--- a/Doc/tools/extensions/patchlevel.py
|
Index: Python-3.13.5/Doc/tools/extensions/implementation_detail.py
|
||||||
+++ b/Doc/tools/extensions/patchlevel.py
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/implementation_detail.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/implementation_detail.py 2025-06-12 21:38:04.912061736 +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.13.5/Doc/tools/extensions/issue_role.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/issue_role.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/issue_role.py 2025-06-12 21:38:04.912236134 +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.13.5/Doc/tools/extensions/misc_news.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/misc_news.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/misc_news.py 2025-06-12 21:38:04.912390144 +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.13.5/Doc/tools/extensions/patchlevel.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/patchlevel.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/patchlevel.py 2025-06-12 21:38:04.912563631 +0200
|
||||||
@@ -3,7 +3,7 @@
|
@@ -3,7 +3,7 @@
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
@@ -438,7 +826,7 @@
|
|||||||
|
|
||||||
CPYTHON_ROOT = Path(
|
CPYTHON_ROOT = Path(
|
||||||
__file__, # cpython/Doc/tools/extensions/patchlevel.py
|
__file__, # cpython/Doc/tools/extensions/patchlevel.py
|
||||||
@@ -26,7 +26,7 @@ class version_info(NamedTuple): # noqa:
|
@@ -26,7 +26,7 @@
|
||||||
major: int #: Major release number
|
major: int #: Major release number
|
||||||
minor: int #: Minor release number
|
minor: int #: Minor release number
|
||||||
micro: int #: Patch release number
|
micro: int #: Patch release number
|
||||||
@@ -447,7 +835,7 @@
|
|||||||
serial: int #: Serial release number
|
serial: int #: Serial release number
|
||||||
|
|
||||||
|
|
||||||
@@ -37,7 +37,8 @@ def get_header_version_info() -> version
|
@@ -37,7 +37,8 @@
|
||||||
defines = {}
|
defines = {}
|
||||||
patchlevel_h = PATCHLEVEL_H.read_text(encoding="utf-8")
|
patchlevel_h = PATCHLEVEL_H.read_text(encoding="utf-8")
|
||||||
for line in patchlevel_h.splitlines():
|
for line in patchlevel_h.splitlines():
|
||||||
@@ -457,7 +845,7 @@
|
|||||||
name, value = m.groups()
|
name, value = m.groups()
|
||||||
defines[name] = value
|
defines[name] = value
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ def get_header_version_info() -> version
|
@@ -50,7 +51,7 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -466,3 +854,65 @@
|
|||||||
version = f"{info.major}.{info.minor}"
|
version = f"{info.major}.{info.minor}"
|
||||||
release = f"{info.major}.{info.minor}.{info.micro}"
|
release = f"{info.major}.{info.minor}.{info.micro}"
|
||||||
if info.releaselevel != "final":
|
if info.releaselevel != "final":
|
||||||
|
Index: Python-3.13.5/Doc/tools/extensions/pydoc_topics.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Doc/tools/extensions/pydoc_topics.py 2025-06-12 21:37:37.257659788 +0200
|
||||||
|
+++ Python-3.13.5/Doc/tools/extensions/pydoc_topics.py 2025-06-12 21:38:04.912726688 +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__)
|
||||||
|
|
||||||
|
@@ -162,7 +164,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:
|
||||||
|
@@ -170,7 +172,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}'''"
|
||||||
|
@@ -178,7 +180,7 @@
|
||||||
|
return f"'''{text}'''"
|
||||||
|
|
||||||
|
|
||||||
|
-def setup(app: Sphinx) -> ExtensionMetadata:
|
||||||
|
+def setup(app: Sphinx) -> "ExtensionMetadata":
|
||||||
|
app.add_builder(PydocTopicsBuilder)
|
||||||
|
|
||||||
|
return {
|
||||||
|
|||||||
95
gh126985-mv-pyvenv.cfg2getpath.patch
Normal file
95
gh126985-mv-pyvenv.cfg2getpath.patch
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
commit 2b0e2b2893a821ca36cd65a204bed932741ac189
|
||||||
|
Author: Filipe Laíns 🇵🇸 <lains@riseup.net>
|
||||||
|
Date: Tue Nov 26 13:46:33 2024 +0000
|
||||||
|
|
||||||
|
GH-126985: move pyvenv.cfg detection from site to getpath (#126987)
|
||||||
|
|
||||||
|
---
|
||||||
|
Lib/test/test_sysconfig.py | 67 ---------------------------------------------
|
||||||
|
1 file changed, 1 insertion(+), 66 deletions(-)
|
||||||
|
|
||||||
|
Index: Python-3.13.5/Lib/test/test_sysconfig.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.13.5.orig/Lib/test/test_sysconfig.py 2025-06-12 19:55:42.184491497 +0200
|
||||||
|
+++ Python-3.13.5/Lib/test/test_sysconfig.py 2025-06-12 19:56:05.737665419 +0200
|
||||||
|
@@ -110,6 +110,7 @@
|
||||||
|
**venv_create_args,
|
||||||
|
)
|
||||||
|
|
||||||
|
+
|
||||||
|
def test_get_path_names(self):
|
||||||
|
self.assertEqual(get_path_names(), sysconfig._SCHEME_KEYS)
|
||||||
|
|
||||||
|
@@ -604,72 +605,6 @@
|
||||||
|
suffix = sysconfig.get_config_var('EXT_SUFFIX')
|
||||||
|
self.assertTrue(suffix.endswith('-darwin.so'), suffix)
|
||||||
|
|
||||||
|
- @requires_subprocess()
|
||||||
|
- def test_config_vars_depend_on_site_initialization(self):
|
||||||
|
- script = textwrap.dedent("""
|
||||||
|
- import sysconfig
|
||||||
|
-
|
||||||
|
- config_vars = sysconfig.get_config_vars()
|
||||||
|
-
|
||||||
|
- import json
|
||||||
|
- print(json.dumps(config_vars, indent=2))
|
||||||
|
- """)
|
||||||
|
-
|
||||||
|
- with self.venv() as venv:
|
||||||
|
- site_config_vars = json.loads(venv.run('-c', script).stdout)
|
||||||
|
- no_site_config_vars = json.loads(venv.run('-S', '-c', script).stdout)
|
||||||
|
-
|
||||||
|
- self.assertNotEqual(site_config_vars, no_site_config_vars)
|
||||||
|
- # With the site initialization, the virtual environment should be enabled.
|
||||||
|
- self.assertEqual(site_config_vars['base'], venv.prefix)
|
||||||
|
- self.assertEqual(site_config_vars['platbase'], venv.prefix)
|
||||||
|
- #self.assertEqual(site_config_vars['prefix'], venv.prefix) # # FIXME: prefix gets overwriten by _init_posix
|
||||||
|
- # Without the site initialization, the virtual environment should be disabled.
|
||||||
|
- self.assertEqual(no_site_config_vars['base'], site_config_vars['installed_base'])
|
||||||
|
- self.assertEqual(no_site_config_vars['platbase'], site_config_vars['installed_platbase'])
|
||||||
|
-
|
||||||
|
- @requires_subprocess()
|
||||||
|
- def test_config_vars_recalculation_after_site_initialization(self):
|
||||||
|
- script = textwrap.dedent("""
|
||||||
|
- import sysconfig
|
||||||
|
-
|
||||||
|
- before = sysconfig.get_config_vars()
|
||||||
|
-
|
||||||
|
- import site
|
||||||
|
- site.main()
|
||||||
|
-
|
||||||
|
- after = sysconfig.get_config_vars()
|
||||||
|
-
|
||||||
|
- import json
|
||||||
|
- print(json.dumps({'before': before, 'after': after}, indent=2))
|
||||||
|
- """)
|
||||||
|
-
|
||||||
|
- with self.venv() as venv:
|
||||||
|
- config_vars = json.loads(venv.run('-S', '-c', script).stdout)
|
||||||
|
-
|
||||||
|
- self.assertNotEqual(config_vars['before'], config_vars['after'])
|
||||||
|
- self.assertEqual(config_vars['after']['base'], venv.prefix)
|
||||||
|
- #self.assertEqual(config_vars['after']['prefix'], venv.prefix) # FIXME: prefix gets overwriten by _init_posix
|
||||||
|
- #self.assertEqual(config_vars['after']['exec_prefix'], venv.prefix) # FIXME: exec_prefix gets overwriten by _init_posix
|
||||||
|
-
|
||||||
|
- @requires_subprocess()
|
||||||
|
- def test_paths_depend_on_site_initialization(self):
|
||||||
|
- script = textwrap.dedent("""
|
||||||
|
- import sysconfig
|
||||||
|
-
|
||||||
|
- paths = sysconfig.get_paths()
|
||||||
|
-
|
||||||
|
- import json
|
||||||
|
- print(json.dumps(paths, indent=2))
|
||||||
|
- """)
|
||||||
|
-
|
||||||
|
- with self.venv() as venv:
|
||||||
|
- site_paths = json.loads(venv.run('-c', script).stdout)
|
||||||
|
- no_site_paths = json.loads(venv.run('-S', '-c', script).stdout)
|
||||||
|
-
|
||||||
|
- self.assertNotEqual(site_paths, no_site_paths)
|
||||||
|
-
|
||||||
|
-
|
||||||
|
class MakefileTests(unittest.TestCase):
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.platform.startswith('win'),
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
--- a/Makefile.pre.in
|
--- a/Makefile.pre.in
|
||||||
+++ b/Makefile.pre.in
|
+++ b/Makefile.pre.in
|
||||||
@@ -1679,11 +1679,18 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
|
@@ -1684,11 +1684,18 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
|
||||||
$(DTRACE_OBJS) \
|
$(DTRACE_OBJS) \
|
||||||
$(srcdir)/Modules/getbuildinfo.c
|
$(srcdir)/Modules/getbuildinfo.c
|
||||||
$(CC) -c $(PY_CORE_CFLAGS) \
|
$(CC) -c $(PY_CORE_CFLAGS) \
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
Index: Python-3.13.0a3/Lib/site.py
|
---
|
||||||
===================================================================
|
Lib/site.py | 2 +-
|
||||||
--- Python-3.13.0a3.orig/Lib/site.py
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
+++ Python-3.13.0a3/Lib/site.py
|
|
||||||
@@ -77,7 +77,7 @@ import io
|
--- a/Lib/site.py
|
||||||
import stat
|
+++ b/Lib/site.py
|
||||||
|
@@ -78,7 +78,7 @@ import stat
|
||||||
|
import errno
|
||||||
|
|
||||||
# Prefixes for site-packages; add additional prefixes like /usr/local here
|
# Prefixes for site-packages; add additional prefixes like /usr/local here
|
||||||
-PREFIXES = [sys.prefix, sys.exec_prefix]
|
-PREFIXES = [sys.prefix, sys.exec_prefix]
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
Lib/test/test_posix.py | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
--- a/Lib/test/test_posix.py
|
|
||||||
+++ b/Lib/test/test_posix.py
|
|
||||||
@@ -437,7 +437,7 @@ class PosixTester(unittest.TestCase):
|
|
||||||
def test_posix_fadvise(self):
|
|
||||||
fd = os.open(os_helper.TESTFN, os.O_RDONLY)
|
|
||||||
try:
|
|
||||||
- posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_WILLNEED)
|
|
||||||
+ posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_RANDOM)
|
|
||||||
finally:
|
|
||||||
os.close(fd)
|
|
||||||
|
|
||||||
@@ -1,3 +1,641 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Aug 1 20:09:24 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add CVE-2025-8194-tarfile-no-neg-offsets.patch which now
|
||||||
|
validates archives to ensure member offsets are non-negative
|
||||||
|
(gh#python/cpython#130577, CVE-2025-8194, bsc#1247249).
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Jul 10 09:33:26 UTC 2025 - Daniel Garcia <daniel.garcia@suse.com>
|
||||||
|
|
||||||
|
- Fix gil/nogil package description, bsc#1246229
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Jul 2 14:47:20 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add CVE-2025-6069-quad-complex-HTMLParser.patch to avoid worst
|
||||||
|
case quadratic complexity when processing certain crafted
|
||||||
|
malformed inputs with HTMLParser (CVE-2025-6069, bsc#1244705).
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Jul 2 13:14:28 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add bsc1243155-sphinx-non-determinism.patch (bsc#1243155) to
|
||||||
|
generate ids for audit_events using docname (reproducible
|
||||||
|
builds).
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Jul 1 08:23:22 UTC 2025 - Daniel Garcia <daniel.garcia@suse.com>
|
||||||
|
|
||||||
|
- Use one core to build doc. This will make sphinx doc build
|
||||||
|
reproducible.
|
||||||
|
bsc#1243155
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Sat Jun 21 14:32:16 UTC 2025 - Marcus Meissner <meissner@suse.com>
|
||||||
|
|
||||||
|
- adjusted sofilename for "nogil" build correctly.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Jun 11 22:02:59 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Update to 3.13.5:
|
||||||
|
- Tests
|
||||||
|
- gh-135120: Add test.support.subTests().
|
||||||
|
- Library
|
||||||
|
- gh-133967: Do not normalize locale name ‘C.UTF-8’ to
|
||||||
|
‘en_US.UTF-8’.
|
||||||
|
- gh-135326: Restore support of integer-like objects with
|
||||||
|
__index__() in random.getrandbits().
|
||||||
|
- gh-135321: Raise a correct exception for values greater
|
||||||
|
than 0x7fffffff for the BINSTRING opcode in the C
|
||||||
|
implementation of pickle.
|
||||||
|
- gh-135276: Backported bugfixes in zipfile.Path from
|
||||||
|
zipp 3.23. Fixed .name, .stem and other basename-based
|
||||||
|
properties on Windows when working with a zipfile on disk.
|
||||||
|
- gh-134151: email: Fix TypeError in
|
||||||
|
email.utils.decode_params() when sorting RFC 2231
|
||||||
|
continuations that contain an unnumbered section.
|
||||||
|
- gh-134152: email: Fix parsing of email message ID with
|
||||||
|
invalid domain.
|
||||||
|
- gh-127081: Fix libc thread safety issues with os by
|
||||||
|
replacing getlogin with getlogin_r re-entrant version.
|
||||||
|
- gh-131884: Fix formatting issues in json.dump() when both
|
||||||
|
indent and skipkeys are used.
|
||||||
|
- Core and Builtins
|
||||||
|
- gh-135171: Roll back changes to generator and list
|
||||||
|
comprehensions that went into 3.13.4 to fix gh-127682,
|
||||||
|
but which involved semantic and bytecode changes not
|
||||||
|
appropriate for a bugfix release.
|
||||||
|
- C API
|
||||||
|
- gh-134989: Fix Py_RETURN_NONE, Py_RETURN_TRUE and
|
||||||
|
Py_RETURN_FALSE macros in the limited C API 3.11 and
|
||||||
|
older: don’t treat Py_None, Py_True and Py_False as
|
||||||
|
immortal. Patch by Victor Stinner.
|
||||||
|
- gh-134989: Implement PyObject_DelAttr() and
|
||||||
|
PyObject_DelAttrString() as macros in the limited C API
|
||||||
|
3.12 and older. Patch by Victor Stinner.
|
||||||
|
- Substantially rewritten doc-py38-to-py36.patch patch to be more
|
||||||
|
flexible and covering even unexpected changes.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Jun 9 21:24:09 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Update to 3.13.4:
|
||||||
|
- Security
|
||||||
|
- gh-135034: Fixes multiple issues that allowed tarfile
|
||||||
|
extraction filters (filter="data" and filter="tar") to be
|
||||||
|
bypassed using crafted symlinks and hard links.
|
||||||
|
Addresses CVE-2024-12718 (bsc#1244056), CVE-2025-4138
|
||||||
|
(bsc#1244059), CVE-2025-4330 (bsc#1244060), and
|
||||||
|
CVE-2025-4517 (bsc#1244032). Also addresses CVE-2025-4435
|
||||||
|
(gh#135034, bsc#1244061).
|
||||||
|
- gh-133767: Fix use-after-free in the “unicode-escape”
|
||||||
|
decoder with a non-“strict” error handler (CVE-2025-4516,
|
||||||
|
bsc#1243273).
|
||||||
|
- gh-128840: Short-circuit the processing of long IPv6
|
||||||
|
addresses early in ipaddress to prevent excessive memory
|
||||||
|
consumption and a minor denial-of-service.
|
||||||
|
- Library
|
||||||
|
- gh-134718: ast.dump() now only omits None and [] values if
|
||||||
|
they are default values.
|
||||||
|
- gh-128840: Fix parsing long IPv6 addresses with embedded
|
||||||
|
IPv4 address.
|
||||||
|
- gh-134696: Built-in HACL* and OpenSSL implementations of
|
||||||
|
hash function constructors now correctly accept the same
|
||||||
|
documented named arguments. For instance, md5() could be
|
||||||
|
previously invoked as md5(data=data) or md5(string=string)
|
||||||
|
depending on the underlying implementation but these calls
|
||||||
|
were not compatible. Patch by Bénédikt Tran.
|
||||||
|
- gh-134210: curses.window.getch() now correctly handles
|
||||||
|
signals. Patch by Bénédikt Tran.
|
||||||
|
- gh-80334: multiprocessing.freeze_support() now checks for
|
||||||
|
work on any “spawn” start method platform rather than only
|
||||||
|
on Windows.
|
||||||
|
- gh-114177: Fix asyncio to not close subprocess pipes which
|
||||||
|
would otherwise error out when the event loop is already
|
||||||
|
closed.
|
||||||
|
- gh-134152: Fixed UnboundLocalError that could occur during
|
||||||
|
email header parsing if an expected trailing delimiter is
|
||||||
|
missing in some contexts.
|
||||||
|
- gh-62184: Remove import of C implementation of io.FileIO
|
||||||
|
from Python implementation which has its own implementation
|
||||||
|
- gh-133982: Emit RuntimeWarning in the Python implementation
|
||||||
|
of io when the file-like object is not closed explicitly in
|
||||||
|
the presence of multiple I/O layers.
|
||||||
|
- gh-133890: The tarfile module now handles
|
||||||
|
UnicodeEncodeError in the same way as OSError when cannot
|
||||||
|
extract a member.
|
||||||
|
- gh-134097: Fix interaction of the new REPL and -X
|
||||||
|
showrefcount command line option.
|
||||||
|
- gh-133889: The generated directory listing page in
|
||||||
|
http.server.SimpleHTTPRequestHandler now only shows the
|
||||||
|
decoded path component of the requested URL, and not the
|
||||||
|
query and fragment.
|
||||||
|
- gh-134098: Fix handling paths that end with
|
||||||
|
a percent-encoded slash (%2f or %2F) in
|
||||||
|
http.server.SimpleHTTPRequestHandler.
|
||||||
|
- gh-134062: ipaddress: fix collisions in __hash__() for
|
||||||
|
IPv4Network and IPv6Network objects.
|
||||||
|
- gh-133745: In 3.13.3 we accidentally changed the signature
|
||||||
|
of the asyncio create_task() family of methods and how it
|
||||||
|
calls a custom task factory in a backwards incompatible
|
||||||
|
way. Since some 3rd party libraries have already made
|
||||||
|
changes to work around the issue that might break if
|
||||||
|
we simply reverted the changes, we’re instead changing
|
||||||
|
things to be backwards compatible with 3.13.2 while still
|
||||||
|
supporting those workarounds for 3.13.3. In particular, the
|
||||||
|
special-casing of name and context is back (until 3.14) and
|
||||||
|
consequently eager tasks may still find that their name
|
||||||
|
hasn’t been set before they execute their first yielding
|
||||||
|
await.
|
||||||
|
- gh-71253: Raise ValueError in open() if opener returns a
|
||||||
|
negative file-descriptor in the Python implementation of io
|
||||||
|
to match the C implementation.
|
||||||
|
- gh-77057: Fix handling of invalid markup declarations in
|
||||||
|
html.parser.HTMLParser.
|
||||||
|
- gh-133489: random.getrandbits() can now generate more that
|
||||||
|
231 bits. random.randbytes() can now generate more that 256
|
||||||
|
MiB.
|
||||||
|
- gh-133290: Fix attribute caching issue when setting
|
||||||
|
ctypes._Pointer._type_ in the undocumented and deprecated
|
||||||
|
ctypes.SetPointerType() function and the undocumented
|
||||||
|
set_type() method.
|
||||||
|
- gh-132876: ldexp() on Windows doesn’t round subnormal
|
||||||
|
results before Windows 11, but should. Python’s
|
||||||
|
math.ldexp() wrapper now does round them, so results may
|
||||||
|
change slightly, in rare cases of very small results, on
|
||||||
|
Windows versions before 11.
|
||||||
|
- gh-133089: Use original timeout value for
|
||||||
|
subprocess.TimeoutExpired when the func subprocess.run()
|
||||||
|
is called with a timeout instead of sometimes a confusing
|
||||||
|
partial remaining time out value used internally on the
|
||||||
|
final wait().
|
||||||
|
- gh-133009: xml.etree.ElementTree: Fix a crash in
|
||||||
|
Element.__deepcopy__ when the element is concurrently
|
||||||
|
mutated. Patch by Bénédikt Tran.
|
||||||
|
- gh-132995: Bump the version of pip bundled in ensurepip to
|
||||||
|
version 25.1.1
|
||||||
|
- gh-132017: Fix error when pyrepl is suspended, then resumed
|
||||||
|
and terminated.
|
||||||
|
- gh-132673: Fix a crash when using _align_ = 0 and _fields_
|
||||||
|
= [] in a ctypes.Structure.
|
||||||
|
- gh-132527: Include the valid typecode ‘w’ in the error
|
||||||
|
message when an invalid typecode is passed to array.array.
|
||||||
|
- gh-132439: Fix PyREPL on Windows: characters entered via
|
||||||
|
AltGr are swallowed. Patch by Chris Eibl.
|
||||||
|
- gh-132429: Fix support of Bluetooth sockets on NetBSD and
|
||||||
|
DragonFly BSD.
|
||||||
|
- gh-132106: QueueListener.start now raises a RuntimeError if
|
||||||
|
the listener is already started.
|
||||||
|
- gh-132417: Fix a NULL pointer dereference when a C function
|
||||||
|
called using ctypes with restype py_object returns NULL.
|
||||||
|
- gh-132385: Fix instance error suggestions trigger potential
|
||||||
|
exceptions in object.__getattr__() in traceback.
|
||||||
|
- gh-132308: A traceback.TracebackException now correctly
|
||||||
|
renders the __context__ and __cause__ attributes from
|
||||||
|
falsey Exception, and the exceptions attribute from falsey
|
||||||
|
ExceptionGroup.
|
||||||
|
- gh-132250: Fixed the SystemError in cProfile when locating
|
||||||
|
the actual C function of a method raises an exception.
|
||||||
|
- gh-132063: Prevent exceptions that evaluate as
|
||||||
|
falsey (namely, when their __bool__ method returns
|
||||||
|
False or their __len__ method returns 0) from being
|
||||||
|
ignored by concurrent.futures.ProcessPoolExecutor and
|
||||||
|
concurrent.futures.ThreadPoolExecutor.
|
||||||
|
- gh-119605: Respect follow_wrapped for __init__() and
|
||||||
|
__new__() methods when getting the class signature for a
|
||||||
|
class with inspect.signature(). Preserve class signature
|
||||||
|
after wrapping with warnings.deprecated(). Patch by Xuehai
|
||||||
|
Pan.
|
||||||
|
- gh-91555: Ignore log messages generated during handling of
|
||||||
|
log messages, to avoid deadlock or infinite recursion.
|
||||||
|
- gh-131434: Improve error reporting for incorrect format in
|
||||||
|
time.strptime().
|
||||||
|
- gh-131127: Systems using LibreSSL now successfully build.
|
||||||
|
- gh-130999: Avoid exiting the new REPL and offer suggestions
|
||||||
|
even if there are non-string candidates when errors occur.
|
||||||
|
- gh-130941: Fix configparser.ConfigParser parsing empty
|
||||||
|
interpolation with allow_no_value set to True.
|
||||||
|
- gh-129098: Fix REPL traceback reporting when using
|
||||||
|
compile() with an inexisting file. Patch by Bénédikt Tran.
|
||||||
|
- gh-130631: http.cookiejar.join_header_words() is now more
|
||||||
|
similar to the original Perl version. It now quotes the
|
||||||
|
same set of characters and always quote values that end
|
||||||
|
with "\n".
|
||||||
|
- gh-129719: Fix missing socket.CAN_RAW_ERR_FILTER constant
|
||||||
|
in the socket module on Linux systems. It was missing since
|
||||||
|
Python 3.11.
|
||||||
|
- gh-124096: Turn on virtual terminal mode and enable
|
||||||
|
bracketed paste in REPL on Windows console. (If the
|
||||||
|
terminal does not support bracketed paste, enabling it does
|
||||||
|
nothing.)
|
||||||
|
- gh-122559: Remove __reduce__() and __reduce_ex__() methods
|
||||||
|
that always raise TypeError in the C implementation
|
||||||
|
of io.FileIO, io.BufferedReader, io.BufferedWriter
|
||||||
|
and io.BufferedRandom and replace them with default
|
||||||
|
__getstate__() methods that raise TypeError. This restores
|
||||||
|
fine details of behavior of Python 3.11 and older versions.
|
||||||
|
- gh-122179: hashlib.file_digest() now raises BlockingIOError
|
||||||
|
when no data is available during non-blocking I/O. Before,
|
||||||
|
it added spurious null bytes to the digest.
|
||||||
|
- gh-86155: html.parser.HTMLParser.close() no longer loses
|
||||||
|
data when the <script> tag is not closed. Patch by Waylan
|
||||||
|
Limberg.
|
||||||
|
- gh-69426: Fix html.parser.HTMLParser to not unescape
|
||||||
|
character entities in attribute values if they are followed
|
||||||
|
by an ASCII alphanumeric or an equals sign.
|
||||||
|
- bpo-44172: Keep a reference to original curses windows in
|
||||||
|
subwindows so that the original window does not get deleted
|
||||||
|
before subwindows.
|
||||||
|
- Tests
|
||||||
|
- gh-133744: Fix multiprocessing interrupt test. Add an event
|
||||||
|
to synchronize the parent process with the child process:
|
||||||
|
wait until the child process starts sleeping. Patch by
|
||||||
|
Victor Stinner.
|
||||||
|
- gh-133639: Fix
|
||||||
|
TestPyReplAutoindent.test_auto_indent_default() doesn’t run
|
||||||
|
input_code.
|
||||||
|
- gh-133131: The iOS testbed will now select the most
|
||||||
|
recently released “SE-class” device for testing if a device
|
||||||
|
isn’t explicitly specified.
|
||||||
|
- gh-109981: The test helper that counts the list of open
|
||||||
|
file descriptors now uses the optimised /dev/fd approach on
|
||||||
|
all Apple platforms, not just macOS. This avoids crashes
|
||||||
|
caused by guarded file descriptors.
|
||||||
|
- IDLE
|
||||||
|
- gh-112936: fix IDLE: no Shell menu item in single-process
|
||||||
|
mode.
|
||||||
|
- Documentation
|
||||||
|
- gh-107006: Move documentation and example code for
|
||||||
|
threading.local from its docstring to the official docs.
|
||||||
|
- Core and Builtins
|
||||||
|
- gh-134908: Fix crash when iterating over lines in a text
|
||||||
|
file on the free threaded build.
|
||||||
|
- gh-127682: No longer call __iter__ twice in list
|
||||||
|
comprehensions. This brings the behavior of list
|
||||||
|
comprehensions in line with other forms of iteration
|
||||||
|
- gh-134381: Fix RuntimeError when using a not-started
|
||||||
|
threading.Thread after calling os.fork()
|
||||||
|
- gh-128066: Fixes an edge case where PyREPL improperly threw
|
||||||
|
an error when Python is invoked on a read only filesystem
|
||||||
|
while trying to write history file entries.
|
||||||
|
- gh-134100: Fix a use-after-free bug that occurs when an
|
||||||
|
imported module isn’t in sys.modules after its initial
|
||||||
|
import. Patch by Nico-Posada.
|
||||||
|
- gh-133703: Fix hashtable in dict can be bigger than
|
||||||
|
intended in some situations.
|
||||||
|
- gh-132869: Fix crash in the free threading build when
|
||||||
|
accessing an object attribute that may be concurrently
|
||||||
|
inserted or deleted.
|
||||||
|
- gh-132762: fromkeys() no longer loops forever when adding
|
||||||
|
a small set of keys to a large base dict. Patch by Angela
|
||||||
|
Liss.
|
||||||
|
- gh-133543: Fix a possible memory leak that could occur when
|
||||||
|
directly accessing instance dictionaries (__dict__) that
|
||||||
|
later become part of a reference cycle.
|
||||||
|
- gh-133516: Raise ValueError when constants True, False or
|
||||||
|
None are used as an identifier after NFKC normalization.
|
||||||
|
- gh-133441: Fix crash upon setting an attribute with a dict
|
||||||
|
subclass. Patch by Victor Stinner.
|
||||||
|
- gh-132942: Fix two races in the type lookup cache. This
|
||||||
|
affected the free-threaded build and could cause crashes
|
||||||
|
(apparently quite difficult to trigger).
|
||||||
|
- gh-132713: Fix repr(list) race condition: hold a strong
|
||||||
|
reference to the item while calling repr(item). Patch by
|
||||||
|
Victor Stinner.
|
||||||
|
- gh-132747: Fix a crash when calling __get__() of a method
|
||||||
|
with a None second argument.
|
||||||
|
- gh-132542: Update Thread.native_id after fork(2) to ensure
|
||||||
|
accuracy. Patch by Noam Cohen.
|
||||||
|
- gh-124476: Fix decoding from the locale encoding in the
|
||||||
|
C.UTF-8 locale.
|
||||||
|
- gh-131927: Compiler warnings originating from the same
|
||||||
|
module and line number are now only emitted once, matching
|
||||||
|
the behaviour of warnings emitted from user code. This can
|
||||||
|
also be configured with warnings filters.
|
||||||
|
- gh-127682: No longer call __iter__ twice when creating and
|
||||||
|
executing a generator expression. Creating a generator
|
||||||
|
expression from a non-interable will raise only when the
|
||||||
|
generator expression is executed. This brings the behavior
|
||||||
|
of generator expressions in line with other generators.
|
||||||
|
- gh-131878: Handle uncaught exceptions in the main input
|
||||||
|
loop for the new REPL.
|
||||||
|
- gh-131878: Fix support of unicode characters with two or
|
||||||
|
more codepoints on Windows in the new REPL.
|
||||||
|
- gh-130804: Fix support of unicode characters on Windows in
|
||||||
|
the new REPL.
|
||||||
|
- gh-130070: Fixed an assertion error for exec() passed a
|
||||||
|
string source and a non-None closure. Patch by Bartosz
|
||||||
|
Sławecki.
|
||||||
|
- gh-129958: Fix a bug that was allowing newlines
|
||||||
|
inconsitently in format specifiers for single-quoted
|
||||||
|
f-strings. Patch by Pablo Galindo.
|
||||||
|
- C API
|
||||||
|
- gh-132909: Fix an overflow when handling the K format in
|
||||||
|
Py_BuildValue(). Patch by Bénédikt Tran.
|
||||||
|
- Remove upstreamed patches:
|
||||||
|
- CVE-2025-4516-DecodeError-handler.patch
|
||||||
|
- gh-132535-rsrc-warn-test_timeout.patch
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed May 28 09:46:40 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Don't use %elif, it is supported only from rpm 4.15.0, which is
|
||||||
|
not in SLE-15.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri May 16 13:44:12 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Add CVE-2025-4516-DecodeError-handler.patch fixing
|
||||||
|
CVE-2025-4516 (bsc#1243273) blocking DecodeError handling
|
||||||
|
vulnerability, which could lead to DoS.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Sat May 10 11:38:27 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Remove python-3.3.0b1-test-posix_fadvise.patch (not needed
|
||||||
|
since kernel 3.6-rc1)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Apr 11 19:47:34 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Update to 3.13.3:
|
||||||
|
- Tools/Demos
|
||||||
|
- gh-131852: msgfmt no longer adds the POT-Creation-Date to
|
||||||
|
generated .mo files for consistency with GNU msgfmt.
|
||||||
|
- gh-85012: Correctly reset msgctxt when compiling messages
|
||||||
|
in msgfmt.
|
||||||
|
- gh-130025: The iOS testbed now correctly handles symlinks
|
||||||
|
used as Python framework references.
|
||||||
|
- Tests
|
||||||
|
- gh-131050: test_ssl.test_dh_params is skipped if the
|
||||||
|
underlying TLS library does not support finite-field
|
||||||
|
ephemeral Diffie-Hellman.
|
||||||
|
- gh-129200: Multiple iOS testbed runners can now be started
|
||||||
|
at the same time without introducing an ambiguity over
|
||||||
|
simulator ownership.
|
||||||
|
- gh-130292: The iOS testbed will now run successfully on a
|
||||||
|
machine that has not previously run Xcode tests (such as CI
|
||||||
|
configurations).
|
||||||
|
- gh-130293: The tests of terminal colorization are no longer
|
||||||
|
sensitive to the value of the TERM variable in the testing
|
||||||
|
environment.
|
||||||
|
- gh-126332: Add unit tests for pyrepl.
|
||||||
|
- Security
|
||||||
|
- gh-131809: Update bundled libexpat to 2.7.1
|
||||||
|
- gh-131261: Upgrade to libexpat 2.7.0
|
||||||
|
- gh-127371: Avoid unbounded buffering for
|
||||||
|
tempfile.SpooledTemporaryFile.writelines(). Previously,
|
||||||
|
disk spillover was only checked after the lines iterator
|
||||||
|
had been exhausted. This is now done after each line is
|
||||||
|
written.
|
||||||
|
- gh-121284: Fix bug in the folding of rfc2047 encoded-words
|
||||||
|
when flattening an email message using a modern email
|
||||||
|
policy. Previously when an encoded-word was too long for
|
||||||
|
a line, it would be decoded, split across lines, and
|
||||||
|
re-encoded. But commas and other special characters in the
|
||||||
|
original text could be left unencoded and unquoted. This
|
||||||
|
could theoretically be used to spoof header lines using
|
||||||
|
a carefully constructed encoded-word if the resulting
|
||||||
|
rendered email was transmitted or re-parsed.
|
||||||
|
- Library
|
||||||
|
- gh-132174: Fix function name in error message of
|
||||||
|
_interpreters.run_string.
|
||||||
|
- gh-132171: Fix crash of _interpreters.run_string on string
|
||||||
|
subclasses.
|
||||||
|
- gh-129204: Introduce new _PYTHON_SUBPROCESS_USE_POSIX_SPAWN
|
||||||
|
environment variable knob in subprocess to control the use
|
||||||
|
of os.posix_spawn().
|
||||||
|
- gh-132159: Do not shadow user arguments in generated
|
||||||
|
__new__() by decorator warnings.deprecated. Patch by Xuehai
|
||||||
|
Pan.
|
||||||
|
- gh-132075: Fix possible use of socket address structures
|
||||||
|
with uninitialized members. Now all structure members are
|
||||||
|
initialized with zeroes by default.
|
||||||
|
- gh-132002: Fix crash when deallocating
|
||||||
|
contextvars.ContextVar with weird unahashable string names.
|
||||||
|
- gh-131668: socket: Fix code parsing AF_BLUETOOTH socket
|
||||||
|
addresses.
|
||||||
|
- gh-131492: Fix a resource leak when constructing a
|
||||||
|
gzip.GzipFile with a filename fails, for example when
|
||||||
|
passing an invalid compresslevel.
|
||||||
|
- gh-131325: Fix sendfile fallback implementation to drain
|
||||||
|
data after writing to transport in asyncio.
|
||||||
|
- gh-129843: Fix incorrect argument passing in
|
||||||
|
warnings.warn_explicit().
|
||||||
|
- gh-131204: Use monospace font from System Font Stack for
|
||||||
|
cross-platform support in difflib.HtmlDiff.
|
||||||
|
- gh-130940: The PyConfig.use_system_logger attribute,
|
||||||
|
introduced in Python 3.13.2, has been removed. The
|
||||||
|
introduction of this attribute inadvertently introduced an
|
||||||
|
ABI breakage on macOS and iOS. The use of the system logger
|
||||||
|
is now enabled by default on iOS, and disabled by default
|
||||||
|
on macOS.
|
||||||
|
- gh-131045: Fix issue with __contains__, values, and
|
||||||
|
pseudo-members for enum.Flag.
|
||||||
|
- gh-130959: Fix pure-Python implementation of
|
||||||
|
datetime.time.fromisoformat() to reject times with spaces
|
||||||
|
in fractional part (for example, 12:34:56.400 +02:00),
|
||||||
|
matching the C implementation. Patch by Michał Gorny.
|
||||||
|
- gh-130637: Add validation for numeric response data in
|
||||||
|
poplib.POP3.stat() method
|
||||||
|
- gh-130461: Remove .. index:: directives from the uuid
|
||||||
|
module documentation. These directives previously created
|
||||||
|
entries in the general index for getnode() as well as
|
||||||
|
the uuid1(), uuid3(), uuid4(), and uuid5() constructor
|
||||||
|
functions.
|
||||||
|
- gh-130379: The zipapp module now calculates the list of
|
||||||
|
files to be added to the archive before creating the
|
||||||
|
archive. This avoids accidentally including the target when
|
||||||
|
it is being created in the source directory.
|
||||||
|
- gh-130285: Fix corner case for random.sample() allowing the
|
||||||
|
counts parameter to specify an empty population. So now,
|
||||||
|
sample([], 0, counts=[]) and sample('abc', k=0, counts=[0,
|
||||||
|
0, 0]) both give the same result as sample([], 0).
|
||||||
|
- gh-130250: Fix regression in traceback.print_last().
|
||||||
|
- gh-130230: Fix crash in pow() with only Decimal third
|
||||||
|
argument.
|
||||||
|
- gh-118761: Reverts a change in the previous release
|
||||||
|
attempting to make some stdlib imports used within the
|
||||||
|
subprocess module lazy as this was causing errors during
|
||||||
|
__del__ finalizers calling methods such as terminate, or
|
||||||
|
kill, or send_signal.
|
||||||
|
- gh-130164: Fixed failure to raise TypeError in
|
||||||
|
inspect.Signature.bind() for positional-only arguments
|
||||||
|
provided by keyword when a variadic keyword argument (e.g.
|
||||||
|
--kwargs) is present.
|
||||||
|
- gh-130151: Fix reference leaks in _hashlib.hmac_new() and
|
||||||
|
_hashlib.hmac_digest(). Patch by Bénédikt Tran.
|
||||||
|
- gh-130145: Fix asyncio.AbstractEventloop.run_forever() when
|
||||||
|
another loop is already running.
|
||||||
|
- gh-129726: Fix gzip.GzipFile raising an unraisable
|
||||||
|
exception during garbage collection when referring to
|
||||||
|
a temporary object by breaking the reference loop with
|
||||||
|
weakref.
|
||||||
|
- gh-127750: Remove broken functools.singledispatchmethod()
|
||||||
|
caching introduced in gh-85160.
|
||||||
|
- gh-129583: Update bundled pip to 25.0.1
|
||||||
|
- gh-97850: Update the deprecation warning of
|
||||||
|
importlib.abc.Loader.load_module().
|
||||||
|
- gh-129646: Update the locale alias mapping in the locale
|
||||||
|
module to match the latest X Org locale alias mapping and
|
||||||
|
support new locales in Glibc 2.41.
|
||||||
|
- gh-129603: Fix bugs where sqlite3.Row objects could
|
||||||
|
segfault if their inherited description was set to
|
||||||
|
None. Patch by Erlend Aasland.
|
||||||
|
- gh-128231: Execution of multiple statements in the new
|
||||||
|
REPL now stops immediately upon the first exception
|
||||||
|
encountered. Patch by Bartosz Sławecki.
|
||||||
|
- gh-117779: Fix reading duplicated entries in zipfile by
|
||||||
|
name. Reading duplicated entries (except the last one)
|
||||||
|
by ZipInfo now emits a warning instead of raising an
|
||||||
|
exception.
|
||||||
|
- gh-128772: Fix pydoc for methods with the __module__
|
||||||
|
attribute equal to None.
|
||||||
|
- gh-92897: Scheduled the deprecation of the check_home
|
||||||
|
argument of sysconfig.is_python_build() to Python 3.15.
|
||||||
|
- gh-128657: Fix possible extra reference when using objects
|
||||||
|
returned by hashlib.sha256() under free threading.
|
||||||
|
- gh-128703: Fix mimetypes.guess_type() to use default
|
||||||
|
mapping for empty Content-Type in registry.
|
||||||
|
- gh-128308: Support the name keyword argument
|
||||||
|
for eager tasks in asyncio.loop.create_task(),
|
||||||
|
asyncio.create_task() and asyncio.TaskGroup.create_task(),
|
||||||
|
by passing on all kwargs to the task factory set by
|
||||||
|
asyncio.loop.set_task_factory().
|
||||||
|
- gh-128388: Fix PyREPL on Windows to support more
|
||||||
|
keybindings, like the Control-← and Control-→ word-skipping
|
||||||
|
keybindings and those with meta (i.e. Alt), e.g. Alt-d to
|
||||||
|
kill-word or Alt-Backspace backward-kill-word.
|
||||||
|
- gh-126037: xml.etree.ElementTree: Fix a crash in
|
||||||
|
Element.find, Element.findtext and Element.findall when
|
||||||
|
the tag to find implements an __eq__() method mutating the
|
||||||
|
element being queried. Patch by Bénédikt Tran.
|
||||||
|
- gh-127712: Fix handling of the secure argument of
|
||||||
|
logging.handlers.SMTPHandler.
|
||||||
|
- gh-126033: xml.etree.ElementTree: Fix a crash in
|
||||||
|
Element.remove when the element is concurrently
|
||||||
|
mutated. Patch by Bénédikt Tran.
|
||||||
|
- gh-118201: Fixed intermittent failures of os.confstr,
|
||||||
|
os.pathconf and os.sysconf on iOS and Android.
|
||||||
|
- gh-124927: Non-printing characters are now properly handled
|
||||||
|
in the new REPL.
|
||||||
|
- IDLE
|
||||||
|
- gh-129873: Simplify displaying the IDLE doc by only copying
|
||||||
|
the text section of idle.html to idlelib/help.html. Patch
|
||||||
|
by Stan Ulbrych.
|
||||||
|
- Documentation
|
||||||
|
- gh-131417: Mention asyncio.Future and asyncio.Task in
|
||||||
|
generic classes list.
|
||||||
|
- gh-125722: Require Sphinx 8.2.0 or later to build the
|
||||||
|
Python documentation. Patch by Adam Turner.
|
||||||
|
- gh-129712: The wheel tags supported by each macOS universal
|
||||||
|
SDK option are now documented.
|
||||||
|
- gh-46236: C API: Document PyUnicode_RSplit(),
|
||||||
|
PyUnicode_Partition() and PyUnicode_RPartition().
|
||||||
|
- Core and Builtins
|
||||||
|
- gh-132011: Fix crash when calling list.append() as an
|
||||||
|
unbound method.
|
||||||
|
- gh-131998: Fix a crash when using an unbound method
|
||||||
|
descriptor object in a function where a bound method
|
||||||
|
descriptor was used.
|
||||||
|
- gh-131988: Fix a performance regression that caused scaling
|
||||||
|
bottlenecks in the free threaded build in 3.13.1 and
|
||||||
|
3.13.2.
|
||||||
|
- gh-131719: Fix missing NULL check in _PyMem_FreeDelayed in
|
||||||
|
free-threaded build.
|
||||||
|
- gh-131670: Fix anext() failing on sync __anext__() raising
|
||||||
|
an exception.
|
||||||
|
- gh-131141: Fix data race in sys.monitoring instrumentation
|
||||||
|
while registering callback.
|
||||||
|
- gh-130932: Fix incorrect exception handling in
|
||||||
|
_PyModule_IsPossiblyShadowing
|
||||||
|
- gh-130851: Fix a crash in the free threading build when
|
||||||
|
constructing a code object with co_consts that contains
|
||||||
|
instances of types that are not otherwise generated by the
|
||||||
|
bytecode compiler.
|
||||||
|
- gh-130794: Fix memory leak in the free threaded build
|
||||||
|
when resizing a shared list or dictionary from multiple
|
||||||
|
short-lived threads.
|
||||||
|
- gh-130775: Do not crash on negative column and end_column
|
||||||
|
in ast locations.
|
||||||
|
- gh-130382: Fix PyRefTracer_DESTROY not being sent from
|
||||||
|
Python/ceval.c Py_DECREF().
|
||||||
|
- gh-130618: Fix a bug that was causing UnicodeDecodeError or
|
||||||
|
SystemError to be raised when using f-strings with lambda
|
||||||
|
expressions with non-ASCII characters. Patch by Pablo
|
||||||
|
Galindo
|
||||||
|
- gh-130163: Fix possible crashes related to concurrent
|
||||||
|
change and use of the sys module attributes.
|
||||||
|
- gh-88887: Fixing multiprocessing Resource Tracker process
|
||||||
|
leaking, usually observed when running Python as PID 1.
|
||||||
|
- gh-130115: Fix an issue with thread identifiers being
|
||||||
|
sign-extended on some platforms.
|
||||||
|
- gh-128396: Fix a crash that occurs when calling locals()
|
||||||
|
inside an inline comprehension that uses the same local
|
||||||
|
variable as the outer frame scope where the variable is a
|
||||||
|
free or cell var.
|
||||||
|
- gh-116042: Fix location for SyntaxErrors of invalid escapes
|
||||||
|
in the tokenizer. Patch by Pablo Galindo
|
||||||
|
- gh-129983: Fix data race in compile_template in sre.c.
|
||||||
|
- gh-129967: Fix a race condition in the free threading build
|
||||||
|
when repr(set) is called concurrently with set.clear().
|
||||||
|
- gh-129900: Fix return codes inside SystemExit not getting
|
||||||
|
returned by the REPL.
|
||||||
|
- gh-129732: Fixed a race in _Py_qsbr_reserve in the free
|
||||||
|
threading build.
|
||||||
|
- gh-129643: Fix thread safety of PyList_Insert() in
|
||||||
|
free-threading builds.
|
||||||
|
- gh-129668: Fix race condition when raising MemoryError in
|
||||||
|
the free threaded build.
|
||||||
|
- gh-129643: Fix thread safety of PyList_SetItem() in
|
||||||
|
free-threading builds. Patch by Kumar Aditya.
|
||||||
|
- gh-128714: Fix the potential races in get/set dunder
|
||||||
|
methods __annotations__, __annotate__ and __type_params__
|
||||||
|
for function object, and add related tests.
|
||||||
|
- gh-128632: Disallow __classdict__ as the name of a type
|
||||||
|
parameter. Using this name would previously crash the
|
||||||
|
interpreter in some circumstances.
|
||||||
|
- gh-127953: The time to handle a LINE event in
|
||||||
|
sys.monitoring (and sys.settrace) is now independent of the
|
||||||
|
number of lines in the code object.
|
||||||
|
- gh-125331: from __future__ import barry_as_FLUFL now works
|
||||||
|
in more contexts, including when it is used in files,
|
||||||
|
with the -c flag, and in the REPL when there are multiple
|
||||||
|
statements on the same line. Previously, it worked only
|
||||||
|
on subsequent lines in the REPL, and when the appropriate
|
||||||
|
flags were passed directly to compile(). Patch by Pablo
|
||||||
|
Galindo.
|
||||||
|
- C API
|
||||||
|
- gh-131740: Update PyUnstable_GC_VisitObjects to traverse
|
||||||
|
perm gen.
|
||||||
|
- gh-129533: Update PyGC_Enable(), PyGC_Disable(),
|
||||||
|
PyGC_IsEnabled() to use atomic operation for thread-safety
|
||||||
|
at free-threading build. Patch by Donghee Na.
|
||||||
|
- Build
|
||||||
|
- gh-131865: The DTrace build now properly passes the CC
|
||||||
|
and CFLAGS variables to the dtrace command when utilizing
|
||||||
|
SystemTap on Linux.
|
||||||
|
- gh-131675: Fix mimalloc library builds for 32-bit ARM
|
||||||
|
targets.
|
||||||
|
- gh-130673: Fix potential KeyError when handling object
|
||||||
|
sections during JIT building process.
|
||||||
|
- gh-130740: Ensure that Python.h is included before
|
||||||
|
stdbool.h unless pyconfig.h is included before or in some
|
||||||
|
platform-specific contexts.
|
||||||
|
- gh-129838: Don’t redefine _Py_NO_SANITIZE_UNDEFINED when
|
||||||
|
compiling with a recent GCC version and undefined sanitizer
|
||||||
|
enabled.
|
||||||
|
- gh-129660: Drop test_embed from PGO training, whose
|
||||||
|
contribution in recent versions is considered to be
|
||||||
|
ignorable.
|
||||||
|
- Add gh126985-mv-pyvenv.cfg2getpath.patch to remove failing
|
||||||
|
tests in test_sysconfig.
|
||||||
|
- Add gh-132535-rsrc-warn-test_timeout.patch to fix
|
||||||
|
failing tests in the build system without network access
|
||||||
|
(gh#python/cpython#132535).
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Mon Mar 10 15:44:31 UTC 2025 - Bernhard Wiedemann <bwiedemann@suse.com>
|
Mon Mar 10 15:44:31 UTC 2025 - Bernhard Wiedemann <bwiedemann@suse.com>
|
||||||
|
|
||||||
|
|||||||
@@ -83,19 +83,20 @@
|
|||||||
# No experimental_jit in SLES, there's no clang >=18
|
# No experimental_jit in SLES, there's no clang >=18
|
||||||
%if 0%{?suse_version} <= 1600
|
%if 0%{?suse_version} <= 1600
|
||||||
%bcond_with experimental_jit
|
%bcond_with experimental_jit
|
||||||
# Disable experimental_jit for primary python.
|
|
||||||
# llvm is not part of ring0 and experimental_jit requires clang >= 18
|
|
||||||
%elif !%{primary_interpreter}
|
|
||||||
# Currently supported architectures
|
|
||||||
# https://peps.python.org/pep-0744/#support
|
|
||||||
%ifarch x86_64 %{x86_64} aarch64
|
|
||||||
%bcond_without experimental_jit
|
|
||||||
%else
|
%else
|
||||||
%bcond_with experimental_jit
|
# Disable experimental_jit for primary python.
|
||||||
%endif
|
# llvm is not part of ring0 and experimental_jit requires clang >= 18
|
||||||
|
%if !%{primary_interpreter}
|
||||||
%else
|
# Currently supported architectures
|
||||||
%bcond_with experimental_jit
|
# https://peps.python.org/pep-0744/#support
|
||||||
|
%ifarch x86_64 %{x86_64} aarch64
|
||||||
|
%bcond_without experimental_jit
|
||||||
|
%else
|
||||||
|
%bcond_with experimental_jit
|
||||||
|
%endif
|
||||||
|
%else
|
||||||
|
%bcond_with experimental_jit
|
||||||
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
# %%if 0%%{?sle_version} && 0%%{?suse_version} < 1550
|
# %%if 0%%{?sle_version} && 0%%{?suse_version} < 1550
|
||||||
@@ -139,7 +140,11 @@
|
|||||||
# version part of "libpython" package
|
# version part of "libpython" package
|
||||||
%define so_major 1
|
%define so_major 1
|
||||||
%define so_minor 0
|
%define so_minor 0
|
||||||
|
%if "%{abi_kind}" == "t"
|
||||||
|
%define so_version %{python_version_soname}t%{so_major}_%{so_minor}
|
||||||
|
%else
|
||||||
%define so_version %{python_version_soname}%{abi_kind}-%{so_major}_%{so_minor}
|
%define so_version %{python_version_soname}%{abi_kind}-%{so_major}_%{so_minor}
|
||||||
|
%endif
|
||||||
# rpm and python have different ideas about what is an arch-dependent name, so:
|
# rpm and python have different ideas about what is an arch-dependent name, so:
|
||||||
%if "%{__isa_name}" == "ppc"
|
%if "%{__isa_name}" == "ppc"
|
||||||
%define archname %(echo %{_arch} | sed s/ppc/powerpc/)
|
%define archname %(echo %{_arch} | sed s/ppc/powerpc/)
|
||||||
@@ -162,7 +167,7 @@
|
|||||||
# _md5.cpython-38m-x86_64-linux-gnu.so
|
# _md5.cpython-38m-x86_64-linux-gnu.so
|
||||||
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
|
%define dynlib() %{sitedir}/lib-dynload/%{1}.cpython-%{abi_tag}-%{archname}-%{_os}%{?_gnu}%{?armsuffix}.so
|
||||||
Name: %{python_pkg_name}%{psuffix}
|
Name: %{python_pkg_name}%{psuffix}
|
||||||
Version: 3.13.2
|
Version: 3.13.5
|
||||||
%define tarversion %{version}
|
%define tarversion %{version}
|
||||||
%define tarname Python-%{tarversion}
|
%define tarname Python-%{tarversion}
|
||||||
Release: 0
|
Release: 0
|
||||||
@@ -206,8 +211,6 @@ Patch02: F00251-change-user-install-location.patch
|
|||||||
Patch03: python-3.3.0b1-localpath.patch
|
Patch03: python-3.3.0b1-localpath.patch
|
||||||
# replace DATE, TIME and COMPILER by fixed definitions to aid reproducible builds
|
# replace DATE, TIME and COMPILER by fixed definitions to aid reproducible builds
|
||||||
Patch04: python-3.3.0b1-fix_date_time_compiler.patch
|
Patch04: python-3.3.0b1-fix_date_time_compiler.patch
|
||||||
# POSIX_FADV_WILLNEED throws EINVAL. Use a different constant in test
|
|
||||||
Patch05: python-3.3.0b1-test-posix_fadvise.patch
|
|
||||||
# Raise timeout value for test_subprocess
|
# Raise timeout value for test_subprocess
|
||||||
Patch06: subprocess-raise-timeout.patch
|
Patch06: subprocess-raise-timeout.patch
|
||||||
# PATCH-FEATURE-UPSTREAM bpo-31046_ensurepip_honours_prefix.patch bpo#31046 mcepl@suse.com
|
# PATCH-FEATURE-UPSTREAM bpo-31046_ensurepip_honours_prefix.patch bpo#31046 mcepl@suse.com
|
||||||
@@ -222,6 +225,18 @@ Patch40: fix-test-recursion-limit-15.6.patch
|
|||||||
# PATCH-FIX-SLE doc-py38-to-py36.patch mcepl@suse.com
|
# PATCH-FIX-SLE doc-py38-to-py36.patch mcepl@suse.com
|
||||||
# Make documentation extensions working with Python 3.6
|
# Make documentation extensions working with Python 3.6
|
||||||
Patch41: doc-py38-to-py36.patch
|
Patch41: doc-py38-to-py36.patch
|
||||||
|
# PATCH-FIX-UPSTREAM gh126985-mv-pyvenv.cfg2getpath.patch mcepl@suse.com
|
||||||
|
# Remove tests failing in test_sysconfig
|
||||||
|
Patch42: gh126985-mv-pyvenv.cfg2getpath.patch
|
||||||
|
# PATCH-FIX-UPSTREAM bsc1243155-sphinx-non-determinism.patch bsc#1243155 mcepl@suse.com
|
||||||
|
# Doc: Generate ids for audit_events using docname
|
||||||
|
Patch43: bsc1243155-sphinx-non-determinism.patch
|
||||||
|
# PATCH-FIX-UPSTREAM CVE-2025-6069-quad-complex-HTMLParser.patch bsc#1244705 mcepl@suse.com
|
||||||
|
# avoid quadratic complexity when processing malformed inputs with HTMLParser
|
||||||
|
Patch44: CVE-2025-6069-quad-complex-HTMLParser.patch
|
||||||
|
# PATCH-FIX-UPSTREAM CVE-2025-8194-tarfile-no-neg-offsets.patch bsc#1247249 mcepl@suse.com
|
||||||
|
# tarfile now validates archives to ensure member offsets are non-negative
|
||||||
|
Patch45: CVE-2025-8194-tarfile-no-neg-offsets.patch
|
||||||
BuildRequires: autoconf-archive
|
BuildRequires: autoconf-archive
|
||||||
BuildRequires: automake
|
BuildRequires: automake
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
@@ -258,7 +273,9 @@ BuildRequires: python3-Sphinx >= 4.0.0
|
|||||||
%if 0%{?suse_version} >= 1500
|
%if 0%{?suse_version} >= 1500
|
||||||
BuildRequires: python3-python-docs-theme >= 2022.1
|
BuildRequires: python3-python-docs-theme >= 2022.1
|
||||||
%endif
|
%endif
|
||||||
|
%if 0%{?suse_version} < 1599
|
||||||
|
BuildRequires: python3-dataclasses
|
||||||
|
%endif
|
||||||
%endif
|
%endif
|
||||||
%endif
|
%endif
|
||||||
# end of {with doc}
|
# end of {with doc}
|
||||||
@@ -313,7 +330,7 @@ Installing "python3" is sufficient for the vast majority of usecases.
|
|||||||
In addition, recommended packages provide UI toolkit support (python3-curses,
|
In addition, recommended packages provide UI toolkit support (python3-curses,
|
||||||
python3-tk), legacy UNIX database bindings (python3-dbm), and the IDLE
|
python3-tk), legacy UNIX database bindings (python3-dbm), and the IDLE
|
||||||
development environment (python3-idle).
|
development environment (python3-idle).
|
||||||
%if %{with GIL}
|
%if %{without GIL}
|
||||||
|
|
||||||
This package has been built with the Global Interpreter Lock removed.
|
This package has been built with the Global Interpreter Lock removed.
|
||||||
This feature is still considered to be experimental. This package is
|
This feature is still considered to be experimental. This package is
|
||||||
@@ -434,7 +451,7 @@ This package contains the interpreter core and most commonly used modules
|
|||||||
from the standard library. This is sufficient for many usecases, but it
|
from the standard library. This is sufficient for many usecases, but it
|
||||||
excludes components that depend on external libraries, most notably XML,
|
excludes components that depend on external libraries, most notably XML,
|
||||||
database and UI toolkits support.
|
database and UI toolkits support.
|
||||||
%if %{with GIL}
|
%if %{without GIL}
|
||||||
|
|
||||||
This package has been built with the Global Interpreter Lock removed.
|
This package has been built with the Global Interpreter Lock removed.
|
||||||
This feature is still considered to be experimental. This package is
|
This feature is still considered to be experimental. This package is
|
||||||
@@ -554,7 +571,7 @@ TODAY_DATE=`date -r %{SOURCE0} "+%%B %%d, %%Y"`
|
|||||||
|
|
||||||
cd Doc
|
cd Doc
|
||||||
sed -i "s/^today = .*/today = '$TODAY_DATE'/" conf.py
|
sed -i "s/^today = .*/today = '$TODAY_DATE'/" conf.py
|
||||||
%make_build -j1 html
|
%make_build -j1 JOBS=1 html
|
||||||
|
|
||||||
# Build also devhelp files
|
# Build also devhelp files
|
||||||
sphinx-build -a -b devhelp . build/devhelp
|
sphinx-build -a -b devhelp . build/devhelp
|
||||||
@@ -656,12 +673,6 @@ EXCLUDE="$EXCLUDE test_external_inspection test_faulthandler test_os test_posix
|
|||||||
# done have any such interface breaking the uuid module.
|
# done have any such interface breaking the uuid module.
|
||||||
EXCLUDE="$EXCLUDE test_uuid"
|
EXCLUDE="$EXCLUDE test_uuid"
|
||||||
|
|
||||||
# bsc#1195140 and bpo#37169 - test_capi is failing on openSUSE, and not sure why
|
|
||||||
EXCLUDE="$EXCLUDE test_capi"
|
|
||||||
|
|
||||||
# Failing tests on python 3.13
|
|
||||||
EXCLUDE="$EXCLUDE test_regrtest test_sysconfig"
|
|
||||||
|
|
||||||
# Limit virtual memory to avoid spurious failures
|
# Limit virtual memory to avoid spurious failures
|
||||||
if test $(ulimit -v) = unlimited || test $(ulimit -v) -gt 10000000; then
|
if test $(ulimit -v) = unlimited || test $(ulimit -v) -gt 10000000; then
|
||||||
ulimit -v 11000000 || :
|
ulimit -v 11000000 || :
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
---
|
---
|
||||||
Lib/test/test_subprocess.py | 3 ++-
|
Lib/test/test_subprocess.py | 6 +++++-
|
||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
--- a/Lib/test/test_subprocess.py
|
--- a/Lib/test/test_subprocess.py
|
||||||
+++ b/Lib/test/test_subprocess.py
|
+++ b/Lib/test/test_subprocess.py
|
||||||
@@ -280,7 +280,8 @@ class ProcessTestCase(BaseTestCase):
|
@@ -292,7 +292,11 @@ class ProcessTestCase(BaseTestCase):
|
||||||
"time.sleep(3600)"],
|
output = subprocess.check_output(
|
||||||
# Some heavily loaded buildbots (sparc Debian 3.x) require
|
[sys.executable, "-c",
|
||||||
# this much time to start and print.
|
"import time; time.sleep(3600)"],
|
||||||
- timeout=3)
|
- timeout=0.1)
|
||||||
+ # OBS might require even more
|
+ # Some heavily loaded buildbots (sparc Debian 3.x) require
|
||||||
+ timeout=10)
|
+ # this much time to start and print.
|
||||||
self.fail("Expected TimeoutExpired.")
|
+ # timeout=3)
|
||||||
self.assertEqual(c.exception.output, b'BDFL')
|
+ # OBS might require even more
|
||||||
|
+ timeout=10)
|
||||||
|
|
||||||
|
def test_call_kwargs(self):
|
||||||
|
# call() function with keyword args
|
||||||
|
|||||||
Reference in New Issue
Block a user