Skip to content

Commit 563706a

Browse files
committed
Merge remote-tracking branch 'upstream/main' into zstd-immutable-types
2 parents 9be36ca + dc191d2 commit 563706a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+797
-468
lines changed

Doc/library/datetime.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,22 @@ A :class:`timedelta` object represents a duration, the difference between two
261261
>>> (d.days, d.seconds, d.microseconds)
262262
(-1, 86399, 999999)
263263

264+
Since the string representation of :class:`!timedelta` objects can be confusing,
265+
use the following recipe to produce a more readable format:
266+
267+
.. code-block:: pycon
268+
269+
>>> def pretty_timedelta(td):
270+
... if td.days >= 0:
271+
... return str(td)
272+
... return f'-({-td!s})'
273+
...
274+
>>> d = timedelta(hours=-1)
275+
>>> str(d) # not human-friendly
276+
'-1 day, 23:00:00'
277+
>>> pretty_timedelta(d)
278+
'-(1:00:00)'
279+
264280
265281
Class attributes:
266282

Doc/library/shutil.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,10 @@ Directory and files operations
454454
:envvar:`PATH` environment variable is read from :data:`os.environ`,
455455
falling back to :data:`os.defpath` if it is not set.
456456

457+
If *cmd* contains a directory component, :func:`!which` only checks the
458+
specified path directly and does not search the directories listed in
459+
*path* or in the system's :envvar:`PATH` environment variable.
460+
457461
On Windows, the current directory is prepended to the *path* if *mode* does
458462
not include ``os.X_OK``. When the *mode* does include ``os.X_OK``, the
459463
Windows API ``NeedCurrentDirectoryForExePathW`` will be consulted to

Doc/using/windows.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ When you first install a runtime, you will likely be prompted to add a directory
9191
to your :envvar:`PATH`. This is optional, if you prefer to use the ``py``
9292
command, but is offered for those who prefer the full range of aliases (such
9393
as ``python3.14.exe``) to be available. The directory will be
94-
:file:`%LocalAppData%\Python\bin` by default, but may be customized by an
94+
:file:`%LocalAppData%\\Python\\bin` by default, but may be customized by an
9595
administrator. Click Start and search for "Edit environment variables for your
9696
account" for the system settings page to add the path.
9797

Doc/whatsnew/3.14.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ and improvements in user-friendliness and correctness.
8888
* :ref:`PEP 758: Allow except and except* expressions without parentheses <whatsnew314-pep758>`
8989
* :ref:`PEP 761: Discontinuation of PGP signatures <whatsnew314-pep761>`
9090
* :ref:`PEP 765: Disallow return/break/continue that exit a finally block <whatsnew314-pep765>`
91+
* :ref:`Free-threaded mode improvements <whatsnew314-free-threaded-cpython>`
9192
* :ref:`PEP 768: Safe external debugger interface for CPython <whatsnew314-pep768>`
9293
* :ref:`PEP 784: Adding Zstandard to the standard library <whatsnew314-pep784>`
9394
* :ref:`A new type of interpreter <whatsnew314-tail-call>`
@@ -794,6 +795,27 @@ For further information on how to build Python, see
794795
(Contributed by Ken Jin in :gh:`128563`, with ideas on how to implement this
795796
in CPython by Mark Shannon, Garrett Gu, Haoran Xu, and Josh Haberman.)
796797

798+
.. _whatsnew314-free-threaded-cpython:
799+
800+
Free-threaded mode
801+
------------------
802+
803+
Free-threaded mode (:pep:`703`), initially added in 3.13, has been significantly improved.
804+
The implementation described in PEP 703 was finished, including C API changes,
805+
and temporary workarounds in the interpreter were replaced with more permanent solutions.
806+
The specializing adaptive interpreter (:pep:`659`) is now enabled in free-threaded mode,
807+
which along with many other optimizations greatly improves its performance.
808+
The performance penalty on single-threaded code in free-threaded mode is now roughly 5-10%,
809+
depending on platform and C compiler used.
810+
811+
This work was done by many contributors: Sam Gross, Matt Page, Neil Schemenauer,
812+
Thomas Wouters, Donghee Na, Kirill Podoprigora, Ken Jin, Itamar Oren,
813+
Brett Simmers, Dino Viehland, Nathan Goldbaum, Ralf Gommers, Lysandros Nikolaou,
814+
Kumar Aditya, Edgar Margffoy, and many others.
815+
816+
Some of these contributors are employed by Meta, which has continued to provide
817+
significant engineering resources to support this project.
818+
797819

798820
.. _whatsnew314-pyrepl-highlighting:
799821

Doc/whatsnew/3.15.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ New features
7575
Other language changes
7676
======================
7777

78+
* Several error messages incorrectly using the term "argument" have been corrected.
79+
(Contributed by Stan Ulbrych in :gh:`133382`.)
80+
7881

7982

8083
New modules

Grammar/python.gram

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,7 +1305,7 @@ invalid_dict_comprehension:
13051305
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "dict unpacking cannot be used in dict comprehension") }
13061306
invalid_parameters:
13071307
| a="/" ',' {
1308-
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "at least one argument must precede /") }
1308+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "at least one parameter must precede /") }
13091309
| (slash_no_default | slash_with_default) param_maybe_default* a='/' {
13101310
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "/ may appear only once") }
13111311
| slash_no_default? param_no_default* invalid_parameters_helper a=param_no_default {
@@ -1319,21 +1319,21 @@ invalid_parameters:
13191319
invalid_default:
13201320
| a='=' &(')'|',') { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "expected default value expression") }
13211321
invalid_star_etc:
1322-
| a='*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "named arguments must follow bare *") }
1322+
| a='*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "named parameters must follow bare *") }
13231323
| '*' ',' TYPE_COMMENT { RAISE_SYNTAX_ERROR("bare * has associated type comment") }
1324-
| '*' param a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "var-positional argument cannot have default value") }
1324+
| '*' param a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "var-positional parameter cannot have default value") }
13251325
| '*' (param_no_default | ',') param_maybe_default* a='*' (param_no_default | ',') {
1326-
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "* argument may appear only once") }
1326+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "* may appear only once") }
13271327
invalid_kwds:
1328-
| '**' param a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "var-keyword argument cannot have default value") }
1329-
| '**' param ',' a=param { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "arguments cannot follow var-keyword argument") }
1330-
| '**' param ',' a[Token*]=('*'|'**'|'/') { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "arguments cannot follow var-keyword argument") }
1328+
| '**' param a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "var-keyword parameter cannot have default value") }
1329+
| '**' param ',' a=param { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "parameters cannot follow var-keyword parameter") }
1330+
| '**' param ',' a[Token*]=('*'|'**'|'/') { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "parameters cannot follow var-keyword parameter") }
13311331
invalid_parameters_helper: # This is only there to avoid type errors
13321332
| a=slash_with_default { _PyPegen_singleton_seq(p, a) }
13331333
| param_with_default+
13341334
invalid_lambda_parameters:
13351335
| a="/" ',' {
1336-
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "at least one argument must precede /") }
1336+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "at least one parameter must precede /") }
13371337
| (lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* a='/' {
13381338
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "/ may appear only once") }
13391339
| lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper a=lambda_param_no_default {
@@ -1348,14 +1348,14 @@ invalid_lambda_parameters_helper:
13481348
| a=lambda_slash_with_default { _PyPegen_singleton_seq(p, a) }
13491349
| lambda_param_with_default+
13501350
invalid_lambda_star_etc:
1351-
| '*' (':' | ',' (':' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") }
1352-
| '*' lambda_param a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "var-positional argument cannot have default value") }
1351+
| '*' (':' | ',' (':' | '**')) { RAISE_SYNTAX_ERROR("named parameters must follow bare *") }
1352+
| '*' lambda_param a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "var-positional parameter cannot have default value") }
13531353
| '*' (lambda_param_no_default | ',') lambda_param_maybe_default* a='*' (lambda_param_no_default | ',') {
1354-
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "* argument may appear only once") }
1354+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "* may appear only once") }
13551355
invalid_lambda_kwds:
1356-
| '**' lambda_param a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "var-keyword argument cannot have default value") }
1357-
| '**' lambda_param ',' a=lambda_param { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "arguments cannot follow var-keyword argument") }
1358-
| '**' lambda_param ',' a[Token*]=('*'|'**'|'/') { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "arguments cannot follow var-keyword argument") }
1356+
| '**' lambda_param a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "var-keyword parameter cannot have default value") }
1357+
| '**' lambda_param ',' a=lambda_param { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "parameters cannot follow var-keyword parameter") }
1358+
| '**' lambda_param ',' a[Token*]=('*'|'**'|'/') { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "parameters cannot follow var-keyword parameter") }
13591359
invalid_double_type_comments:
13601360
| TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT {
13611361
RAISE_SYNTAX_ERROR("Cannot have two type comments on def") }

Include/internal/pycore_interpframe.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ static inline _PyStackRef *_PyFrame_Stackbase(_PyInterpreterFrame *f) {
4848
}
4949

5050
static inline _PyStackRef _PyFrame_StackPeek(_PyInterpreterFrame *f) {
51-
assert(f->stackpointer > f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus);
51+
assert(f->stackpointer > _PyFrame_Stackbase(f));
5252
assert(!PyStackRef_IsNull(f->stackpointer[-1]));
5353
return f->stackpointer[-1];
5454
}
5555

5656
static inline _PyStackRef _PyFrame_StackPop(_PyInterpreterFrame *f) {
57-
assert(f->stackpointer > f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus);
57+
assert(f->stackpointer > _PyFrame_Stackbase(f));
5858
f->stackpointer--;
5959
return *f->stackpointer;
6060
}

Lib/compression/zstd/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def get_frame_info(frame_buffer):
7171
the frame may or may not need a dictionary to be decoded,
7272
and the ID of such a dictionary is not specified.
7373
"""
74-
return FrameInfo(*_zstd._get_frame_info(frame_buffer))
74+
return FrameInfo(*_zstd.get_frame_info(frame_buffer))
7575

7676

7777
def train_dict(samples, dict_size):
@@ -91,7 +91,7 @@ def train_dict(samples, dict_size):
9191
chunk_sizes = tuple(_nbytes(sample) for sample in samples)
9292
if not chunks:
9393
raise ValueError("samples contained no data; can't train dictionary.")
94-
dict_content = _zstd._train_dict(chunks, chunk_sizes, dict_size)
94+
dict_content = _zstd.train_dict(chunks, chunk_sizes, dict_size)
9595
return ZstdDict(dict_content)
9696

9797

@@ -127,7 +127,7 @@ def finalize_dict(zstd_dict, /, samples, dict_size, level):
127127
if not chunks:
128128
raise ValueError("The samples are empty content, can't finalize the"
129129
"dictionary.")
130-
dict_content = _zstd._finalize_dict(zstd_dict.dict_content,
130+
dict_content = _zstd.finalize_dict(zstd_dict.dict_content,
131131
chunks, chunk_sizes,
132132
dict_size, level)
133133
return ZstdDict(dict_content)
@@ -201,7 +201,7 @@ def bounds(self):
201201
202202
Both the lower and upper bounds are inclusive.
203203
"""
204-
return _zstd._get_param_bounds(self.value, is_compress=True)
204+
return _zstd.get_param_bounds(self.value, is_compress=True)
205205

206206

207207
class DecompressionParameter(enum.IntEnum):
@@ -214,7 +214,7 @@ def bounds(self):
214214
215215
Both the lower and upper bounds are inclusive.
216216
"""
217-
return _zstd._get_param_bounds(self.value, is_compress=False)
217+
return _zstd.get_param_bounds(self.value, is_compress=False)
218218

219219

220220
class Strategy(enum.IntEnum):
@@ -237,4 +237,4 @@ class Strategy(enum.IntEnum):
237237

238238

239239
# Check validity of the CompressionParameter & DecompressionParameter types
240-
_zstd._set_parameter_types(CompressionParameter, DecompressionParameter)
240+
_zstd.set_parameter_types(CompressionParameter, DecompressionParameter)

Lib/compression/zstd/_zstdfile.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ def __init__(self, file, /, mode="r", *,
8989
raw = _streams.DecompressReader(
9090
self._fp,
9191
ZstdDecompressor,
92-
trailing_error=ZstdError,
9392
zstd_dict=zstd_dict,
9493
options=options,
9594
)

Lib/html/parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ def goahead(self, end):
260260
else:
261261
assert 0, "interesting.search() lied"
262262
# end while
263-
if end and i < n and not self.cdata_elem:
263+
if end and i < n:
264264
if self.convert_charrefs and not self.cdata_elem:
265265
self.handle_data(unescape(rawdata[i:n]))
266266
else:
@@ -278,7 +278,7 @@ def parse_html_declaration(self, i):
278278
if rawdata[i:i+4] == '<!--':
279279
# this case is actually already handled in goahead()
280280
return self.parse_comment(i)
281-
elif rawdata[i:i+3] == '<![':
281+
elif rawdata[i:i+9] == '<![CDATA[':
282282
return self.parse_marked_section(i)
283283
elif rawdata[i:i+9].lower() == '<!doctype':
284284
# find the closing >
@@ -295,7 +295,7 @@ def parse_html_declaration(self, i):
295295
def parse_bogus_comment(self, i, report=1):
296296
rawdata = self.rawdata
297297
assert rawdata[i:i+2] in ('<!', '</'), ('unexpected call to '
298-
'parse_comment()')
298+
'parse_bogus_comment()')
299299
pos = rawdata.find('>', i+2)
300300
if pos == -1:
301301
return -1

0 commit comments

Comments
 (0)