Skip to content

Commit c2c0514

Browse files
Merge remote-tracking branch 'upstream/main' into clinic-param-aliases
2 parents 1b5387c + 228b1bf commit c2c0514

43 files changed

Lines changed: 761 additions & 257 deletions

Some content is hidden

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

Doc/c-api/import.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ Importing Modules
146146
alternatives.
147147
148148
.. versionchanged:: 3.15
149-
``__cached__`` is no longer set.
149+
The ``__cached__`` attribute is no longer set.
150150
151151
152152
.. c:function:: PyObject* PyImport_ExecCodeModuleEx(const char *name, PyObject *co, const char *pathname)
@@ -170,7 +170,7 @@ Importing Modules
170170
:class:`~importlib.machinery.ModuleSpec` for alternatives.
171171
172172
.. versionchanged:: 3.15
173-
``__cached__`` no longer set.
173+
The ``__cached__`` attribute no longer set.
174174
175175
176176
.. c:function:: PyObject* PyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co, const char *pathname, const char *cpathname)

Doc/library/runpy.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ The :mod:`!runpy` module provides two functions:
9797
:class:`~importlib.machinery.ModuleSpec` for alternatives.
9898

9999
.. versionchanged:: 3.15
100-
``__cached__`` is no longer set.
100+
The global variable ``__cached__`` is no longer set.
101101

102102
.. function:: run_path(path_name, init_globals=None, run_name=None)
103103

@@ -175,7 +175,7 @@ The :mod:`!runpy` module provides two functions:
175175
``__package__`` are deprecated.
176176

177177
.. versionchanged:: 3.15
178-
``__cached__`` is no longer set.
178+
The global variable ``__cached__`` is no longer set.
179179

180180
.. seealso::
181181

Doc/library/tarfile.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,10 @@ reused in custom filters:
11121112
paths (in case the name is absolute
11131113
even after stripping slashes, e.g. ``C:/foo`` on Windows).
11141114
This raises :class:`~tarfile.AbsolutePathError`.
1115+
- Normalize filenames (:attr:`TarInfo.name`) that contain ``..`` components
1116+
using :func:`os.path.normpath`.
1117+
Note that this removes internal ``..`` components, which may change the
1118+
meaning of the name if it traverses symbolic links.
11151119
- :ref:`Refuse <tarfile-extraction-refuse>` to extract files whose absolute
11161120
path (after following symlinks) would end up outside the destination.
11171121
This raises :class:`~tarfile.OutsideDestinationError`.
@@ -1120,6 +1124,10 @@ reused in custom filters:
11201124

11211125
Return the modified ``TarInfo`` member.
11221126

1127+
.. versionchanged:: next
1128+
1129+
Filenames containing ``..`` components are now normalized.
1130+
11231131
.. function:: data_filter(member, path)
11241132

11251133
Implements the ``'data'`` filter.

Doc/reference/datamodel.rst

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,14 +1099,9 @@ this approach.
10991099
:ref:`import system <importsystem>` may opt to leave it unset if it
11001100
has no semantic meaning (for example, a module loaded from a database).
11011101

1102-
.. deprecated-removed:: 3.13 3.15
1103-
Setting ``__cached__`` on a module while failing to set
1104-
:attr:`!__spec__.cached` is deprecated. In Python 3.15,
1105-
``__cached__`` will cease to be set or taken into consideration by
1106-
the import system or standard library.
1107-
1108-
.. versionchanged:: 3.15
1109-
``__cached__`` is no longer set.
1102+
.. versionchanged:: 3.15
1103+
The ``__cached__`` attribute is no longer set on modules or taken into
1104+
consideration by the import system or standard library.
11101105

11111106
Other writable attributes on module objects
11121107
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Doc/tutorial/stdlib.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ aids for working with large modules like :mod:`os`::
3636
<returns an extensive manual page created from the module's docstrings>
3737

3838
For daily file and directory management tasks, the :mod:`shutil` module provides
39-
a higher level interface that is easier to use::
39+
a higher-level interface that is easier to use::
4040

4141
>>> import shutil
4242
>>> shutil.copyfile('data.db', 'archive.db')
@@ -63,7 +63,7 @@ wildcard searches::
6363
Command-line arguments
6464
======================
6565

66-
Common utility scripts often need to process command line arguments. These
66+
Common utility scripts often need to process command-line arguments. These
6767
arguments are stored in the :mod:`sys` module's *argv* attribute as a list. For
6868
instance, let's take the following :file:`demo.py` file::
6969

@@ -77,7 +77,7 @@ line::
7777
['demo.py', 'one', 'two', 'three']
7878

7979
The :mod:`argparse` module provides a more sophisticated mechanism to process
80-
command line arguments. The following script extracts one or more filenames
80+
command-line arguments. The following script extracts one or more filenames
8181
and an optional number of lines to be displayed::
8282

8383
import argparse

Doc/whatsnew/3.15.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,14 @@ Other language changes
880880
other, as regular dynamic extensions do.
881881
(Contributed by Stefano Rivera in :gh:`122931`.)
882882

883+
* The ``__cached__`` attribute on modules, which was deprecated since version
884+
3.13, is no longer set or taken into consideration by the import system or
885+
standard library.
886+
Use :attr:`__spec__.cached <importlib.machinery.ModuleSpec.cached>` instead.
887+
(Contributed by Brett Cannon in :gh:`97879`)
888+
889+
Note that the :attr:`~module.__loader__` and :attr:`~module.__package__`
890+
attributes are also deprecated and scheduled for removal.
883891

884892

885893
Default interactive shell

Lib/tarfile.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,13 @@ def _get_filtered_attrs(member, dest_path, for_data=True):
833833
# For example, 'C:/foo' on Windows.
834834
raise AbsolutePathError(member)
835835
# Ensure we stay in the destination
836+
if '..' in name.replace(os.sep, '/').split('/'):
837+
# Directories are created from the name as given, so a name that
838+
# leaves the destination part-way through would create them
839+
# outside it even if the resolved path stays inside.
840+
normalized = os.path.normpath(name)
841+
if normalized != name:
842+
name = new_attrs['name'] = normalized
836843
target_path = os.path.realpath(os.path.join(dest_path, name),
837844
strict=os.path.ALLOW_MISSING)
838845
if os.path.commonpath([target_path, dest_path]) != dest_path:

Lib/test/support/__init__.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,15 +1271,20 @@ def set_memlimit(limit: str) -> None:
12711271

12721272

12731273
def _memory_watchdog(pid):
1274-
"""Return a function printing the memory usage of process *pid*."""
1274+
"""Return a function printing the memory usage of process *pid*.
1275+
1276+
The largest value it saw is kept in its ``peak`` attribute.
1277+
"""
12751278
# Imported here: test.support does not depend on test.libregrtest.
12761279
from test.libregrtest.utils import get_process_memory_usage
12771280

12781281
def watch():
12791282
mem = get_process_memory_usage(pid)
12801283
if mem is not None:
1284+
watch.peak = max(watch.peak, mem)
12811285
print(f" ... process data size: {mem / (1024 ** 3):.1f} GiB",
12821286
flush=True)
1287+
watch.peak = 0
12831288
return watch
12841289

12851290

@@ -1333,7 +1338,23 @@ def wrapper(self):
13331338
qualname = f'{cls.__qualname__}.{f.__name__}'
13341339
proc = isolation._start_test(cls.__module__, qualname)
13351340
watchdog = _memory_watchdog(proc.pid) if verbose else None
1336-
isolation._replay_test(self, *proc.wait(tick=watchdog))
1341+
payload, output, returncode = proc.wait(tick=watchdog)
1342+
if watchdog:
1343+
# The subprocess measures its own peak exactly. What the
1344+
# parent sampled is only a lower bound.
1345+
maxrss = payload and payload.get('maxrss')
1346+
peak = maxrss or watchdog.peak
1347+
if peak:
1348+
print(f" ... peak memory use: "
1349+
f"{peak / (1024 ** 3):.1f} GiB"
1350+
f"{'' if maxrss else ' or more'}", flush=True)
1351+
majflt = payload and payload.get('majflt')
1352+
if majflt:
1353+
# The test did not fit in memory, so its timing means
1354+
# little.
1355+
print(f" ... {majflt} major page faults: the test "
1356+
f"waited for the disk", flush=True)
1357+
isolation._replay_test(self, payload, output, returncode)
13371358
return
13381359

13391360
return f(self, maxsize)

Lib/test/support/subprocess_runner.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,45 @@ def _outcome(kind, test, detail):
7272
for t, tb in result.expectedFailures]
7373
outcomes += [_outcome('skipped', t, reason) for t, reason in result.skipped]
7474

75-
payload = {'outcomes': outcomes, 'durations': result.id_durations}
75+
def _usage():
76+
"""What this process used: peak resident set size in bytes, and the
77+
number of major page faults it took, either of which can be None.
78+
79+
A major page fault is served from disk, so a non-zero count means swapping.
80+
81+
The modules are imported here, after the test has run, so that the test
82+
does not see them.
83+
"""
84+
try:
85+
import resource
86+
except ImportError:
87+
pass
88+
else:
89+
usage = resource.getrusage(resource.RUSAGE_SELF)
90+
# Solaris and illumos leave these fields at 0, which no live process
91+
# has, so treat it as "not supported".
92+
if not usage.ru_maxrss:
93+
return {'maxrss': None, 'majflt': None}
94+
# ru_maxrss is in bytes on macOS, in kilobytes on Linux and the BSDs.
95+
maxrss = usage.ru_maxrss
96+
return {'maxrss': maxrss if sys.platform == 'darwin' else maxrss * 1024,
97+
'majflt': usage.ru_majflt}
98+
try:
99+
import os
100+
import _winapi
101+
handle = _winapi.OpenProcess(
102+
_winapi.PROCESS_QUERY_LIMITED_INFORMATION, False, os.getpid())
103+
except (ImportError, OSError):
104+
return {'maxrss': None, 'majflt': None}
105+
try:
106+
info = _winapi.GetProcessMemoryInfo(handle)
107+
finally:
108+
_winapi.CloseHandle(handle)
109+
# PageFaultCount counts all faults, not only the ones served from disk.
110+
return {'maxrss': info['PeakWorkingSetSize'], 'majflt': None}
111+
112+
113+
payload = {'outcomes': outcomes, 'durations': result.id_durations, **_usage()}
76114
with open(outfile, 'wb') as f:
77115
marshal.dump(payload, f)
78116

0 commit comments

Comments
 (0)