Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 918c083

Browse filesBrowse files
authored
Merge branch '3.14' into backport-8598e57-3.14
2 parents 74f77f7 + 4e57e21 commit 918c083
Copy full SHA for 918c083
Expand file treeCollapse file tree

33 files changed

+624
-226
lines changed

‎.github/workflows/mypy.yml

Copy file name to clipboardExpand all lines: .github/workflows/mypy.yml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ on:
1515
- "Misc/mypy/**"
1616
- "Tools/build/compute-changes.py"
1717
- "Tools/build/generate_sbom.py"
18+
- "Tools/build/generate-build-details.py"
1819
- "Tools/build/verify_ensurepip_wheels.py"
1920
- "Tools/build/update_file.py"
2021
- "Tools/cases_generator/**"

‎Doc/c-api/init.rst

Copy file name to clipboardExpand all lines: Doc/c-api/init.rst
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2.
203203

204204
Set by the :option:`-i` option.
205205

206-
.. deprecated:: 3.12
206+
.. deprecated-removed:: 3.12 3.15
207207

208208
.. c:var:: int Py_IsolatedFlag
209209

‎Doc/c-api/unicode.rst

Copy file name to clipboardExpand all lines: Doc/c-api/unicode.rst
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,17 @@ APIs:
645645
difference being that it decrements the reference count of *right* by one.
646646
647647
648+
.. c:function:: PyObject* PyUnicode_BuildEncodingMap(PyObject* string)
649+
650+
Return a mapping suitable for decoding a custom single-byte encoding.
651+
Given a Unicode string *string* of up to 256 characters representing an encoding
652+
table, returns either a compact internal mapping object or a dictionary
653+
mapping character ordinals to byte values. Raises a :exc:`TypeError` and
654+
return ``NULL`` on invalid input.
655+
656+
.. versionadded:: 3.2
657+
658+
648659
.. c:function:: const char* PyUnicode_GetDefaultEncoding(void)
649660
650661
Return the name of the default string encoding, ``"utf-8"``.

‎Doc/data/refcounts.dat

Copy file name to clipboardExpand all lines: Doc/data/refcounts.dat
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,6 +2781,9 @@ PyUnicode_AppendAndDel:void:::
27812781
PyUnicode_AppendAndDel:PyObject**:p_left:0:
27822782
PyUnicode_AppendAndDel:PyObject*:right:-1:
27832783

2784+
PyUnicode_BuildEncodingMap:PyObject*::+1:
2785+
PyUnicode_BuildEncodingMap:PyObject*:string:::
2786+
27842787
PyUnicode_GetDefaultEncoding:const char*:::
27852788
PyUnicode_GetDefaultEncoding::void::
27862789

‎Doc/library/stdtypes.rst

Copy file name to clipboardExpand all lines: Doc/library/stdtypes.rst
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,7 @@ expression support in the :mod:`re` module).
20122012

20132013
.. method:: str.isprintable()
20142014

2015-
Return true if all characters in the string are printable, false if it
2015+
Return ``True`` if all characters in the string are printable, ``False`` if it
20162016
contains at least one non-printable character.
20172017

20182018
Here "printable" means the character is suitable for :func:`repr` to use in

‎Doc/library/string.rst

Copy file name to clipboardExpand all lines: Doc/library/string.rst
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ these rules. The methods of :class:`Template` are:
858858

859859
.. method:: is_valid()
860860

861-
Returns false if the template has invalid placeholders that will cause
861+
Returns ``False`` if the template has invalid placeholders that will cause
862862
:meth:`substitute` to raise :exc:`ValueError`.
863863

864864
.. versionadded:: 3.11

‎Doc/whatsnew/3.14.rst

Copy file name to clipboardExpand all lines: Doc/whatsnew/3.14.rst
+27-5Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,10 @@ As another example, generating HTML attributes from data:
153153
.. code-block:: python
154154
155155
attributes = {"src": "shrubbery.jpg", "alt": "looks nice"}
156-
template = t"<img {attributes} />"
157-
assert html(template) == '<img src="shrubbery.jpg" alt="looks nice" class="looks-nice" />'
156+
template = t"<img {attributes}>"
157+
assert html(template) == '<img src="shrubbery.jpg" alt="looks nice" class="looks-nice">'
158158
159-
Unlike f-strings, the ``html`` function has access to template attributes
159+
Compared to using an f-string, the ``html`` function has access to template attributes
160160
containing the original information: static strings, interpolations, and values
161161
from the original scope. Unlike existing templating approaches, t-strings build
162162
from the well-known f-string syntax and rules. Template systems thus benefit
@@ -443,6 +443,9 @@ Python without deferred evaluation of annotations, reaches its end of life in 20
443443
In Python 3.14, the behavior of code using ``from __future__ import annotations``
444444
is unchanged.
445445

446+
.. seealso::
447+
:pep:`649`.
448+
446449

447450
Improved error messages
448451
-----------------------
@@ -584,8 +587,27 @@ Improved error messages
584587
^^^^^^
585588
SyntaxError: cannot use subscript as import target
586589
587-
.. seealso::
588-
:pep:`649`.
590+
* Improved error message when trying to add an instance of an unhashable type to
591+
a :class:`dict` or :class:`set`. (Contributed by CF Bolz-Tereick and Victor Stinner
592+
in :gh:`132828`.)
593+
594+
.. code-block:: pycon
595+
596+
>>> s = set()
597+
>>> s.add({'pages': 12, 'grade': 'A'})
598+
Traceback (most recent call last):
599+
File "<python-input-1>", line 1, in <module>
600+
s.add({'pages': 12, 'grade': 'A'})
601+
~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
602+
TypeError: cannot use 'dict' as a set element (unhashable type: 'dict')
603+
>>> d = {}
604+
>>> l = [1, 2, 3]
605+
>>> d[l] = 12
606+
Traceback (most recent call last):
607+
File "<python-input-4>", line 1, in <module>
608+
d[l] = 12
609+
~^^^
610+
TypeError: cannot use 'list' as a dict key (unhashable type: 'list')
589611
590612
591613
.. _whatsnew314-pep741:

‎Lib/compression/zstd/__init__.py

Copy file name to clipboardExpand all lines: Lib/compression/zstd/__init__.py
+40-34Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,16 @@
2828

2929
import _zstd
3030
import enum
31-
from _zstd import *
31+
from _zstd import (ZstdCompressor, ZstdDecompressor, ZstdDict, ZstdError,
32+
get_frame_size, zstd_version)
3233
from compression.zstd._zstdfile import ZstdFile, open, _nbytes
3334

34-
COMPRESSION_LEVEL_DEFAULT = _zstd._compressionLevel_values[0]
35+
# zstd_version_number is (MAJOR * 100 * 100 + MINOR * 100 + RELEASE)
36+
zstd_version_info = (*divmod(_zstd.zstd_version_number // 100, 100),
37+
_zstd.zstd_version_number % 100)
38+
"""Version number of the runtime zstd library as a tuple of integers."""
39+
40+
COMPRESSION_LEVEL_DEFAULT = _zstd.ZSTD_CLEVEL_DEFAULT
3541
"""The default compression level for Zstandard, currently '3'."""
3642

3743

@@ -167,28 +173,28 @@ def decompress(data, zstd_dict=None, options=None):
167173
class CompressionParameter(enum.IntEnum):
168174
"""Compression parameters."""
169175

170-
compression_level = _zstd._ZSTD_c_compressionLevel
171-
window_log = _zstd._ZSTD_c_windowLog
172-
hash_log = _zstd._ZSTD_c_hashLog
173-
chain_log = _zstd._ZSTD_c_chainLog
174-
search_log = _zstd._ZSTD_c_searchLog
175-
min_match = _zstd._ZSTD_c_minMatch
176-
target_length = _zstd._ZSTD_c_targetLength
177-
strategy = _zstd._ZSTD_c_strategy
178-
179-
enable_long_distance_matching = _zstd._ZSTD_c_enableLongDistanceMatching
180-
ldm_hash_log = _zstd._ZSTD_c_ldmHashLog
181-
ldm_min_match = _zstd._ZSTD_c_ldmMinMatch
182-
ldm_bucket_size_log = _zstd._ZSTD_c_ldmBucketSizeLog
183-
ldm_hash_rate_log = _zstd._ZSTD_c_ldmHashRateLog
184-
185-
content_size_flag = _zstd._ZSTD_c_contentSizeFlag
186-
checksum_flag = _zstd._ZSTD_c_checksumFlag
187-
dict_id_flag = _zstd._ZSTD_c_dictIDFlag
188-
189-
nb_workers = _zstd._ZSTD_c_nbWorkers
190-
job_size = _zstd._ZSTD_c_jobSize
191-
overlap_log = _zstd._ZSTD_c_overlapLog
176+
compression_level = _zstd.ZSTD_c_compressionLevel
177+
window_log = _zstd.ZSTD_c_windowLog
178+
hash_log = _zstd.ZSTD_c_hashLog
179+
chain_log = _zstd.ZSTD_c_chainLog
180+
search_log = _zstd.ZSTD_c_searchLog
181+
min_match = _zstd.ZSTD_c_minMatch
182+
target_length = _zstd.ZSTD_c_targetLength
183+
strategy = _zstd.ZSTD_c_strategy
184+
185+
enable_long_distance_matching = _zstd.ZSTD_c_enableLongDistanceMatching
186+
ldm_hash_log = _zstd.ZSTD_c_ldmHashLog
187+
ldm_min_match = _zstd.ZSTD_c_ldmMinMatch
188+
ldm_bucket_size_log = _zstd.ZSTD_c_ldmBucketSizeLog
189+
ldm_hash_rate_log = _zstd.ZSTD_c_ldmHashRateLog
190+
191+
content_size_flag = _zstd.ZSTD_c_contentSizeFlag
192+
checksum_flag = _zstd.ZSTD_c_checksumFlag
193+
dict_id_flag = _zstd.ZSTD_c_dictIDFlag
194+
195+
nb_workers = _zstd.ZSTD_c_nbWorkers
196+
job_size = _zstd.ZSTD_c_jobSize
197+
overlap_log = _zstd.ZSTD_c_overlapLog
192198

193199
def bounds(self):
194200
"""Return the (lower, upper) int bounds of a compression parameter.
@@ -201,7 +207,7 @@ def bounds(self):
201207
class DecompressionParameter(enum.IntEnum):
202208
"""Decompression parameters."""
203209

204-
window_log_max = _zstd._ZSTD_d_windowLogMax
210+
window_log_max = _zstd.ZSTD_d_windowLogMax
205211

206212
def bounds(self):
207213
"""Return the (lower, upper) int bounds of a decompression parameter.
@@ -219,15 +225,15 @@ class Strategy(enum.IntEnum):
219225
the numeric value might change.
220226
"""
221227

222-
fast = _zstd._ZSTD_fast
223-
dfast = _zstd._ZSTD_dfast
224-
greedy = _zstd._ZSTD_greedy
225-
lazy = _zstd._ZSTD_lazy
226-
lazy2 = _zstd._ZSTD_lazy2
227-
btlazy2 = _zstd._ZSTD_btlazy2
228-
btopt = _zstd._ZSTD_btopt
229-
btultra = _zstd._ZSTD_btultra
230-
btultra2 = _zstd._ZSTD_btultra2
228+
fast = _zstd.ZSTD_fast
229+
dfast = _zstd.ZSTD_dfast
230+
greedy = _zstd.ZSTD_greedy
231+
lazy = _zstd.ZSTD_lazy
232+
lazy2 = _zstd.ZSTD_lazy2
233+
btlazy2 = _zstd.ZSTD_btlazy2
234+
btopt = _zstd.ZSTD_btopt
235+
btultra = _zstd.ZSTD_btultra
236+
btultra2 = _zstd.ZSTD_btultra2
231237

232238

233239
# Check validity of the CompressionParameter & DecompressionParameter types

‎Lib/compression/zstd/_zstdfile.py

Copy file name to clipboardExpand all lines: Lib/compression/zstd/_zstdfile.py
+3-5Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import io
22
from os import PathLike
3-
from _zstd import (ZstdCompressor, ZstdDecompressor, _ZSTD_DStreamSizes,
4-
ZstdError)
3+
from _zstd import (ZstdCompressor, ZstdDecompressor, ZstdError,
4+
ZSTD_DStreamOutSize)
55
from compression._common import _streams
66

77
__all__ = ("ZstdFile", "open")
88

9-
_ZSTD_DStreamOutSize = _ZSTD_DStreamSizes[1]
10-
119
_MODE_CLOSED = 0
1210
_MODE_READ = 1
1311
_MODE_WRITE = 2
@@ -188,7 +186,7 @@ def read1(self, size=-1):
188186
# Note this should *not* be io.DEFAULT_BUFFER_SIZE.
189187
# ZSTD_DStreamOutSize is the minimum amount to read guaranteeing
190188
# a full block is read.
191-
size = _ZSTD_DStreamOutSize
189+
size = ZSTD_DStreamOutSize
192190
return self._buffer.read1(size)
193191

194192
def readinto(self, b):

‎Lib/html/parser.py

Copy file name to clipboardExpand all lines: Lib/html/parser.py
+19-1Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import _markupbase
1313

1414
from html import unescape
15+
from html.entities import html5 as html5_entities
1516

1617

1718
__all__ = ['HTMLParser']
@@ -23,6 +24,7 @@
2324

2425
entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
2526
charref = re.compile('&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]')
27+
attr_charref = re.compile(r'&(#[0-9]+|#[xX][0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*)[;=]?')
2628

2729
starttagopen = re.compile('<[a-zA-Z]')
2830
piclose = re.compile('>')
@@ -57,6 +59,22 @@
5759
# </ and the tag name, so maybe this should be fixed
5860
endtagfind = re.compile(r'</\s*([a-zA-Z][-.a-zA-Z0-9:_]*)\s*>')
5961

62+
# Character reference processing logic specific to attribute values
63+
# See: https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state
64+
def _replace_attr_charref(match):
65+
ref = match.group(0)
66+
# Numeric / hex char refs must always be unescaped
67+
if ref.startswith('&#'):
68+
return unescape(ref)
69+
# Named character / entity references must only be unescaped
70+
# if they are an exact match, and they are not followed by an equals sign
71+
if not ref.endswith('=') and ref[1:] in html5_entities:
72+
return unescape(ref)
73+
# Otherwise do not unescape
74+
return ref
75+
76+
def _unescape_attrvalue(s):
77+
return attr_charref.sub(_replace_attr_charref, s)
6078

6179

6280
class HTMLParser(_markupbase.ParserBase):
@@ -323,7 +341,7 @@ def parse_starttag(self, i):
323341
attrvalue[:1] == '"' == attrvalue[-1:]:
324342
attrvalue = attrvalue[1:-1]
325343
if attrvalue:
326-
attrvalue = unescape(attrvalue)
344+
attrvalue = _unescape_attrvalue(attrvalue)
327345
attrs.append((attrname.lower(), attrvalue))
328346
k = m.end()
329347

‎Lib/sqlite3/__main__.py

Copy file name to clipboardExpand all lines: Lib/sqlite3/__main__.py
+19-11Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,25 @@ def runsource(self, source, filename="<input>", symbol="single"):
4848
Return True if more input is needed; buffering is done automatically.
4949
Return False if input is a complete statement ready for execution.
5050
"""
51-
match source:
52-
case ".version":
53-
print(f"{sqlite3.sqlite_version}")
54-
case ".help":
55-
print("Enter SQL code and press enter.")
56-
case ".quit":
57-
sys.exit(0)
58-
case _:
59-
if not sqlite3.complete_statement(source):
60-
return True
61-
execute(self._cur, source)
51+
if not source or source.isspace():
52+
return False
53+
if source[0] == ".":
54+
match source[1:].strip():
55+
case "version":
56+
print(f"{sqlite3.sqlite_version}")
57+
case "help":
58+
print("Enter SQL code and press enter.")
59+
case "quit":
60+
sys.exit(0)
61+
case "":
62+
pass
63+
case _ as unknown:
64+
self.write("Error: unknown command or invalid arguments:"
65+
f' "{unknown}".\n')
66+
else:
67+
if not sqlite3.complete_statement(source):
68+
return True
69+
execute(self._cur, source)
6270
return False
6371

6472

‎Lib/test/test_annotationlib.py

Copy file name to clipboardExpand all lines: Lib/test/test_annotationlib.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ def f(x: a[[int, str], float]):
378378

379379
def g(
380380
w: a[[int, str], float],
381-
x: a[{int, str}, 3],
381+
x: a[{int}, 3],
382382
y: a[{int: str}, 4],
383383
z: a[(int, str), 5],
384384
):
@@ -388,7 +388,7 @@ def g(
388388
anno,
389389
{
390390
"w": "a[[int, str], float]",
391-
"x": "a[{int, str}, 3]",
391+
"x": "a[{int}, 3]",
392392
"y": "a[{int: str}, 4]",
393393
"z": "a[(int, str), 5]",
394394
},

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.