Skip to content

Commit 5438b66

Browse files
committed
Merge remote-tracking branch 'upstream/main' into fixes
2 parents 6c0e7fb + 9e51301 commit 5438b66

File tree

70 files changed

+7396
-926
lines changed

Some content is hidden

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

70 files changed

+7396
-926
lines changed

.github/workflows/tail-call.yml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,17 @@ jobs:
7979
with:
8080
python-version: '3.11'
8181

82-
- name: Native Windows (debug)
82+
- name: Native Windows MSVC (release)
8383
if: runner.os == 'Windows' && matrix.architecture != 'ARM64'
8484
shell: cmd
8585
run: |
86-
choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0
87-
set PlatformToolset=clangcl
88-
set LLVMToolsVersion=${{ matrix.llvm }}.1.0
89-
set LLVMInstallDir=C:\Program Files\LLVM
90-
call ./PCbuild/build.bat --tail-call-interp -d -p ${{ matrix.architecture }}
91-
call ./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
86+
choco install visualstudio2026buildtools --no-progress -y --force --params "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --locale en-US --passive"
87+
$env:PATH = "C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools\MSBuild\Current\bin;$env:PATH"
88+
./PCbuild/build.bat --tail-call-interp -c Release -p ${{ matrix.architecture }} "/p:PlatformToolset=v145"
89+
./PCbuild/rt.bat -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
9290
9391
# No tests (yet):
94-
- name: Emulated Windows (release)
92+
- name: Emulated Windows Clang (release)
9593
if: runner.os == 'Windows' && matrix.architecture == 'ARM64'
9694
shell: cmd
9795
run: |

Doc/library/datetime.rst

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2651,9 +2651,42 @@ Broadly speaking, ``d.strftime(fmt)`` acts like the :mod:`time` module's
26512651
``time.strftime(fmt, d.timetuple())`` although not all objects support a
26522652
:meth:`~date.timetuple` method.
26532653

2654-
For the :meth:`.datetime.strptime` class method, the default value is
2655-
``1900-01-01T00:00:00.000``: any components not specified in the format string
2656-
will be pulled from the default value. [#]_
2654+
For the :meth:`.datetime.strptime` and :meth:`.date.strptime` class methods,
2655+
the default value is ``1900-01-01T00:00:00.000``: any components not specified
2656+
in the format string will be pulled from the default value.
2657+
2658+
.. note::
2659+
When used to parse partial dates lacking a year, :meth:`.datetime.strptime`
2660+
and :meth:`.date.strptime` will raise when encountering February 29 because
2661+
the default year of 1900 is *not* a leap year. Always add a default leap
2662+
year to partial date strings before parsing.
2663+
2664+
2665+
.. testsetup::
2666+
2667+
# doctest seems to turn the warning into an error which makes it
2668+
# show up and require matching and prevents the actual interesting
2669+
# exception from being raised.
2670+
# Manually apply the catch_warnings context manager
2671+
import warnings
2672+
catch_warnings = warnings.catch_warnings()
2673+
catch_warnings.__enter__()
2674+
warnings.simplefilter("ignore")
2675+
2676+
.. testcleanup::
2677+
2678+
catch_warnings.__exit__()
2679+
2680+
.. doctest::
2681+
2682+
>>> from datetime import datetime
2683+
>>> value = "2/29"
2684+
>>> datetime.strptime(value, "%m/%d")
2685+
Traceback (most recent call last):
2686+
...
2687+
ValueError: day 29 must be in range 1..28 for month 2 in year 1900
2688+
>>> datetime.strptime(f"1904 {value}", "%Y %m/%d")
2689+
datetime.datetime(1904, 2, 29, 0, 0)
26572690

26582691
Using ``datetime.strptime(date_string, format)`` is equivalent to::
26592692

@@ -2790,7 +2823,7 @@ Notes:
27902823
include a year in the format. If the value you need to parse lacks a year,
27912824
append an explicit dummy leap year. Otherwise your code will raise an
27922825
exception when it encounters leap day because the default year used by the
2793-
parser is not a leap year. Users run into this bug every four years...
2826+
parser (1900) is not a leap year. Users run into that bug every leap year.
27942827

27952828
.. doctest::
27962829

@@ -2817,5 +2850,3 @@ Notes:
28172850
.. [#] See R. H. van Gent's `guide to the mathematics of the ISO 8601 calendar
28182851
<https://web.archive.org/web/20220531051136/https://webspace.science.uu.nl/~gent0113/calendar/isocalendar.htm>`_
28192852
for a good explanation.
2820-
2821-
.. [#] Passing ``datetime.strptime('Feb 29', '%b %d')`` will fail since 1900 is not a leap year.

Doc/library/pdb.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,8 @@ can be overridden by the local file.
520520
To remove all commands from a breakpoint, type ``commands`` and follow it
521521
immediately with ``end``; that is, give no commands.
522522

523-
With no *bpnumber* argument, ``commands`` refers to the last breakpoint set.
523+
With no *bpnumber* argument, ``commands`` refers to the most recently set
524+
breakpoint that still exists.
524525

525526
You can use breakpoint commands to start your program up again. Simply use
526527
the :pdbcmd:`continue` command, or :pdbcmd:`step`,

Doc/library/profiling.sampling.rst

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,36 @@ On most systems, attaching to another process requires appropriate permissions.
200200
See :ref:`profiling-permissions` for platform-specific requirements.
201201

202202

203+
.. _replay-command:
204+
205+
The ``replay`` command
206+
----------------------
207+
208+
The ``replay`` command converts binary profile files to other output formats::
209+
210+
python -m profiling.sampling replay profile.bin
211+
python -m profiling.sampling replay --flamegraph -o profile.html profile.bin
212+
213+
This command is useful when you have captured profiling data in binary format
214+
and want to analyze it later or convert it to a visualization format. Binary
215+
profiles can be replayed multiple times to different formats without
216+
re-profiling.
217+
218+
::
219+
220+
# Convert binary to pstats (default, prints to stdout)
221+
python -m profiling.sampling replay profile.bin
222+
223+
# Convert binary to flame graph
224+
python -m profiling.sampling replay --flamegraph -o output.html profile.bin
225+
226+
# Convert binary to gecko format for Firefox Profiler
227+
python -m profiling.sampling replay --gecko -o profile.json profile.bin
228+
229+
# Convert binary to heatmap
230+
python -m profiling.sampling replay --heatmap -o my_heatmap profile.bin
231+
232+
203233
Profiling in production
204234
-----------------------
205235

@@ -1087,6 +1117,59 @@ intuitive view that shows exactly where time is spent without requiring
10871117
interpretation of hierarchical visualizations.
10881118

10891119

1120+
Binary format
1121+
-------------
1122+
1123+
Binary format (:option:`--binary`) produces a compact binary file for efficient
1124+
storage of profiling data::
1125+
1126+
python -m profiling.sampling run --binary -o profile.bin script.py
1127+
python -m profiling.sampling attach --binary -o profile.bin 12345
1128+
1129+
The :option:`--compression` option controls data compression:
1130+
1131+
- ``auto`` (default): Use zstd compression if available, otherwise no
1132+
compression
1133+
- ``zstd``: Force zstd compression (requires :mod:`compression.zstd` support)
1134+
- ``none``: Disable compression
1135+
1136+
::
1137+
1138+
python -m profiling.sampling run --binary --compression=zstd -o profile.bin script.py
1139+
1140+
To analyze binary profiles, use the :ref:`replay-command` to convert them to
1141+
other formats like flame graphs or pstats output.
1142+
1143+
1144+
Record and replay workflow
1145+
==========================
1146+
1147+
The binary format combined with the replay command enables a record-and-replay
1148+
workflow that separates data capture from analysis. Rather than generating
1149+
visualizations during profiling, you capture raw data to a compact binary file
1150+
and convert it to different formats later.
1151+
1152+
This approach has three main benefits:
1153+
1154+
- Sampling runs faster because the work of building data structures for
1155+
visualization is deferred until replay.
1156+
- A single binary capture can be converted to multiple output formats
1157+
without re-profiling: pstats for a quick overview, flame graph for visual
1158+
exploration, heatmap for line-level detail.
1159+
- Binary files are compact and easy to share with colleagues who can convert
1160+
them to their preferred format.
1161+
1162+
A typical workflow::
1163+
1164+
# Capture profile in production or during tests
1165+
python -m profiling.sampling attach --binary -o profile.bin 12345
1166+
1167+
# Later, analyze with different formats
1168+
python -m profiling.sampling replay profile.bin
1169+
python -m profiling.sampling replay --flamegraph -o profile.html profile.bin
1170+
python -m profiling.sampling replay --heatmap -o heatmap profile.bin
1171+
1172+
10901173
Live mode
10911174
=========
10921175

@@ -1298,6 +1381,10 @@ Global options
12981381

12991382
Attach to and profile a running process by PID.
13001383

1384+
.. option:: replay
1385+
1386+
Convert a binary profile file to another output format.
1387+
13011388

13021389
Sampling options
13031390
----------------
@@ -1388,12 +1475,22 @@ Output options
13881475

13891476
Generate HTML heatmap with line-level sample counts.
13901477

1478+
.. option:: --binary
1479+
1480+
Generate high-performance binary format for later conversion with the
1481+
``replay`` command.
1482+
1483+
.. option:: --compression <type>
1484+
1485+
Compression for binary format: ``auto`` (use zstd if available, default),
1486+
``zstd``, or ``none``.
1487+
13911488
.. option:: -o <path>, --output <path>
13921489

13931490
Output file or directory path. Default behavior varies by format:
1394-
``--pstats`` writes to stdout, ``--flamegraph`` and ``--gecko`` generate
1395-
files like ``flamegraph.PID.html``, and ``--heatmap`` creates a directory
1396-
named ``heatmap_PID``.
1491+
:option:`--pstats` writes to stdout, while other formats generate a file
1492+
named ``<format>_<PID>.<ext>`` (for example, ``flamegraph_12345.html``).
1493+
:option:`--heatmap` creates a directory named ``heatmap_<PID>``.
13971494

13981495

13991496
pstats display options

Doc/library/stdtypes.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ Any object can be tested for truth value, for use in an :keyword:`if` or
4646
By default, an object is considered true unless its class defines either a
4747
:meth:`~object.__bool__` method that returns ``False`` or a
4848
:meth:`~object.__len__` method that
49-
returns zero, when called with the object. [1]_ Here are most of the built-in
50-
objects considered false:
49+
returns zero, when called with the object. [1]_ If one of the methods raises an
50+
exception when called, the exception is propagated and the object does
51+
not have a truth value (for example, :data:`NotImplemented`).
52+
Here are most of the built-in objects considered false:
5153

5254
.. index::
5355
single: None (Built-in object)

Doc/whatsnew/3.15.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,16 @@ zlib
849849
Optimizations
850850
=============
851851

852+
* Builds using Visual Studio 2026 (MSVC 18) may now use the new
853+
:ref:`tail-calling interpreter <whatsnew314-tail-call-interpreter>`.
854+
Results on an early experimental MSVC compiler reported roughly 15% speedup
855+
on the geometric mean of pyperformance on Windows x86-64 over
856+
the switch-case interpreter. We have
857+
observed speedups ranging from 15% for large pure-Python libraries
858+
to 40% for long-running small pure-Python scripts on Windows.
859+
(Contributed by Chris Eibl, Ken Jin, and Brandt Bucher in :gh:`143068`.
860+
Special thanks to the MSVC team including Hulon Jenkins.)
861+
852862
csv
853863
---
854864

Include/internal/pycore_ceval.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,17 @@ _Py_VectorCall_StackRefSteal(
415415
int total_args,
416416
_PyStackRef kwnames);
417417

418+
PyAPI_FUNC(PyObject*)
419+
_Py_VectorCallInstrumentation_StackRefSteal(
420+
_PyStackRef callable,
421+
_PyStackRef* arguments,
422+
int total_args,
423+
_PyStackRef kwnames,
424+
bool call_instrumentation,
425+
_PyInterpreterFrame* frame,
426+
_Py_CODEUNIT* this_instr,
427+
PyThreadState* tstate);
428+
418429
PyAPI_FUNC(PyObject *)
419430
_Py_BuiltinCallFast_StackRefSteal(
420431
_PyStackRef callable,
@@ -464,6 +475,11 @@ _Py_assert_within_stack_bounds(
464475
_PyInterpreterFrame *frame, _PyStackRef *stack_pointer,
465476
const char *filename, int lineno);
466477

478+
// Like PyMapping_GetOptionalItem, but returns the PyObject* instead of taking
479+
// it as an out parameter. This helps MSVC's escape analysis when used with
480+
// tail calling.
481+
PyAPI_FUNC(PyObject*) _PyMapping_GetOptionalItem2(PyObject* obj, PyObject* key, int* err);
482+
467483
#ifdef __cplusplus
468484
}
469485
#endif

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)