Skip to content

Commit e834a8f

Browse files
authored
Merge branch 'main' into setobject-note
2 parents a9d1068 + 70185de commit e834a8f

23 files changed

+663
-44
lines changed

Doc/c-api/init.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ Process-wide parameters
513513
program name is ``'/usr/local/bin/python'``, the prefix is ``'/usr/local'``. The
514514
returned string points into static storage; the caller should not modify its
515515
value. This corresponds to the :makevar:`prefix` variable in the top-level
516-
:file:`Makefile` and the ``--prefix`` argument to the :program:`configure`
516+
:file:`Makefile` and the :option:`--prefix` argument to the :program:`configure`
517517
script at build time. The value is available to Python code as ``sys.prefix``.
518518
It is only useful on Unix. See also the next function.
519519

Doc/c-api/intro.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,19 @@ used by extension writers. Structure member names do not have a reserved prefix.
7878

7979
The header files are typically installed with Python. On Unix, these are
8080
located in the directories :file:`{prefix}/include/pythonversion/` and
81-
:file:`{exec_prefix}/include/pythonversion/`, where :envvar:`prefix` and
82-
:envvar:`exec_prefix` are defined by the corresponding parameters to Python's
81+
:file:`{exec_prefix}/include/pythonversion/`, where :option:`prefix <--prefix>` and
82+
:option:`exec_prefix <--exec-prefix>` are defined by the corresponding parameters to Python's
8383
:program:`configure` script and *version* is
8484
``'%d.%d' % sys.version_info[:2]``. On Windows, the headers are installed
85-
in :file:`{prefix}/include`, where :envvar:`prefix` is the installation
85+
in :file:`{prefix}/include`, where ``prefix`` is the installation
8686
directory specified to the installer.
8787

8888
To include the headers, place both directories (if different) on your compiler's
8989
search path for includes. Do *not* place the parent directories on the search
9090
path and then use ``#include <pythonX.Y/Python.h>``; this will break on
9191
multi-platform builds since the platform independent headers under
92-
:envvar:`prefix` include the platform specific headers from
93-
:envvar:`exec_prefix`.
92+
:option:`prefix <--prefix>` include the platform specific headers from
93+
:option:`exec_prefix <--exec-prefix>`.
9494

9595
C++ users should note that although the API is defined entirely using C, the
9696
header files properly declare the entry points to be ``extern "C"``. As a result,

Doc/library/sys.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,7 @@ always available.
13231323

13241324
A string giving the site-specific directory prefix where the platform
13251325
independent Python files are installed; on Unix, the default is
1326-
``'/usr/local'``. This can be set at build time with the ``--prefix``
1326+
:file:`/usr/local`. This can be set at build time with the :option:`--prefix`
13271327
argument to the :program:`configure` script. See
13281328
:ref:`installation_paths` for derived paths.
13291329

Doc/library/venv.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ running from a virtual environment.
6161
A virtual environment may be "activated" using a script in its binary directory
6262
(``bin`` on POSIX; ``Scripts`` on Windows).
6363
This will prepend that directory to your :envvar:`!PATH`, so that running
64-
:program:`!python` will invoke the environment's Python interpreter
64+
:program:`python` will invoke the environment's Python interpreter
6565
and you can run installed scripts without having to use their full path.
6666
The invocation of the activation script is platform-specific
6767
(:samp:`{<venv>}` must be replaced by the path to the directory
@@ -84,7 +84,7 @@ containing the virtual environment):
8484
+-------------+------------+--------------------------------------------------+
8585

8686
.. versionadded:: 3.4
87-
:program:`!fish` and :program:`!csh` activation scripts.
87+
:program:`fish` and :program:`csh` activation scripts.
8888

8989
.. versionadded:: 3.8
9090
PowerShell activation scripts installed under POSIX for PowerShell Core

Doc/tutorial/modules.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ When importing the package, Python searches through the directories on
438438

439439
The :file:`__init__.py` files are required to make Python treat directories
440440
containing the file as packages. This prevents directories with a common name,
441-
such as ``string``, unintentionally hiding valid modules that occur later
441+
such as ``string``, from unintentionally hiding valid modules that occur later
442442
on the module search path. In the simplest case, :file:`__init__.py` can just be
443443
an empty file, but it can also execute initialization code for the package or
444444
set the ``__all__`` variable, described later.

Doc/using/configure.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,22 @@ WebAssembly Options
216216
Install Options
217217
---------------
218218

219+
.. cmdoption:: --prefix=PREFIX
220+
221+
Install architecture-independent files in PREFIX. On Unix, it
222+
defaults to :file:`/usr/local`.
223+
224+
This value can be retrived at runtime using :data:`sys.prefix`.
225+
226+
As an example, one can use ``--prefix="$HOME/.local/"`` to install
227+
a Python in its home directory.
228+
229+
.. cmdoption:: --exec-prefix=EPREFIX
230+
231+
Install architecture-dependent files in EPREFIX, defaults to :option:`--prefix`.
232+
233+
This value can be retrived at runtime using :data:`sys.exec_prefix`.
234+
219235
.. cmdoption:: --disable-test-modules
220236

221237
Don't build nor install test modules, like the :mod:`test` package or the

Doc/using/unix.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Python-related paths and files
9393
==============================
9494

9595
These are subject to difference depending on local installation conventions;
96-
:envvar:`prefix` (``${prefix}``) and :envvar:`exec_prefix` (``${exec_prefix}``)
96+
:option:`prefix <--prefix>` and :option:`exec_prefix <--exec-prefix>`
9797
are installation-dependent and should be interpreted as for GNU software; they
9898
may be the same.
9999

Doc/whatsnew/3.12.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,11 @@ Porting to Python 3.12
982982
effects, these side effects are no longer duplicated.
983983
(Contributed by Victor Stinner in :gh:`98724`.)
984984

985+
* The interpreter's error indicator is now always normalized. This means
986+
that :c:func:`PyErr_SetObject`, :c:func:`PyErr_SetString` and the other
987+
functions that set the error indicator now normalize the exception
988+
before storing it. (Contributed by Mark Shannon in :gh:`101578`.)
989+
985990
Deprecated
986991
----------
987992

Lib/asyncio/taskgroups.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,21 @@
1010

1111

1212
class TaskGroup:
13+
"""Asynchronous context manager for managing groups of tasks.
1314
15+
Example use:
16+
17+
async with asyncio.TaskGroup() as group:
18+
task1 = group.create_task(some_coroutine(...))
19+
task2 = group.create_task(other_coroutine(...))
20+
print("Both tasks have completed now.")
21+
22+
All tasks are awaited when the context manager exits.
23+
24+
Any exceptions other than `asyncio.CancelledError` raised within
25+
a task will cancel all remaining tasks and wait for them to exit.
26+
The exceptions are then combined and raised as an `ExceptionGroup`.
27+
"""
1428
def __init__(self):
1529
self._entered = False
1630
self._exiting = False
@@ -135,6 +149,10 @@ async def __aexit__(self, et, exc, tb):
135149
self._errors = None
136150

137151
def create_task(self, coro, *, name=None, context=None):
152+
"""Create a new task in this group and return it.
153+
154+
Similar to `asyncio.create_task`.
155+
"""
138156
if not self._entered:
139157
raise RuntimeError(f"TaskGroup {self!r} has not been entered")
140158
if self._exiting and not self._tasks:

Lib/test/test_calendar.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,11 +568,15 @@ def test_locale_calendar_formatweekday(self):
568568
try:
569569
# formatweekday uses different day names based on the available width.
570570
cal = calendar.LocaleTextCalendar(locale='en_US')
571+
# For really short widths, the abbreviated name is truncated.
572+
self.assertEqual(cal.formatweekday(0, 1), "M")
573+
self.assertEqual(cal.formatweekday(0, 2), "Mo")
571574
# For short widths, a centered, abbreviated name is used.
575+
self.assertEqual(cal.formatweekday(0, 3), "Mon")
572576
self.assertEqual(cal.formatweekday(0, 5), " Mon ")
573-
# For really short widths, even the abbreviated name is truncated.
574-
self.assertEqual(cal.formatweekday(0, 2), "Mo")
577+
self.assertEqual(cal.formatweekday(0, 8), " Mon ")
575578
# For long widths, the full day name is used.
579+
self.assertEqual(cal.formatweekday(0, 9), " Monday ")
576580
self.assertEqual(cal.formatweekday(0, 10), " Monday ")
577581
except locale.Error:
578582
raise unittest.SkipTest('cannot set the en_US locale')

Lib/test/test_enum.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4579,15 +4579,14 @@ class Double(Enum):
45794579
TWO = 2
45804580
self.assertEqual(Double.__doc__, None)
45814581

4582-
4583-
def test_doc_1(self):
4582+
def test_doc_3(self):
45844583
class Triple(Enum):
45854584
ONE = 1
45864585
TWO = 2
45874586
THREE = 3
45884587
self.assertEqual(Triple.__doc__, None)
45894588

4590-
def test_doc_1(self):
4589+
def test_doc_4(self):
45914590
class Quadruple(Enum):
45924591
ONE = 1
45934592
TWO = 2

Lib/test/test_os.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2683,12 +2683,17 @@ def test_listvolumes(self):
26832683

26842684
def test_listmounts(self):
26852685
for volume in os.listvolumes():
2686-
mounts = os.listmounts(volume)
2687-
self.assertIsInstance(mounts, list)
2688-
self.assertSetEqual(
2689-
set(mounts),
2690-
self.known_mounts & set(mounts),
2691-
)
2686+
try:
2687+
mounts = os.listmounts(volume)
2688+
except OSError as ex:
2689+
if support.verbose:
2690+
print("Skipping", volume, "because of", ex)
2691+
else:
2692+
self.assertIsInstance(mounts, list)
2693+
self.assertSetEqual(
2694+
set(mounts),
2695+
self.known_mounts & set(mounts),
2696+
)
26922697

26932698

26942699
@unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()')

Lib/test/test_typing.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3809,6 +3809,51 @@ class Y(C[int]):
38093809
self.assertEqual(Y.__qualname__,
38103810
'GenericTests.test_repr_2.<locals>.Y')
38113811

3812+
def test_repr_3(self):
3813+
T = TypeVar('T')
3814+
T1 = TypeVar('T1')
3815+
P = ParamSpec('P')
3816+
P2 = ParamSpec('P2')
3817+
Ts = TypeVarTuple('Ts')
3818+
3819+
class MyCallable(Generic[P, T]):
3820+
pass
3821+
3822+
class DoubleSpec(Generic[P, P2, T]):
3823+
pass
3824+
3825+
class TsP(Generic[*Ts, P]):
3826+
pass
3827+
3828+
object_to_expected_repr = {
3829+
MyCallable[P, T]: "MyCallable[~P, ~T]",
3830+
MyCallable[Concatenate[T1, P], T]: "MyCallable[typing.Concatenate[~T1, ~P], ~T]",
3831+
MyCallable[[], bool]: "MyCallable[[], bool]",
3832+
MyCallable[[int], bool]: "MyCallable[[int], bool]",
3833+
MyCallable[[int, str], bool]: "MyCallable[[int, str], bool]",
3834+
MyCallable[[int, list[int]], bool]: "MyCallable[[int, list[int]], bool]",
3835+
MyCallable[Concatenate[*Ts, P], T]: "MyCallable[typing.Concatenate[*Ts, ~P], ~T]",
3836+
3837+
DoubleSpec[P2, P, T]: "DoubleSpec[~P2, ~P, ~T]",
3838+
DoubleSpec[[int], [str], bool]: "DoubleSpec[[int], [str], bool]",
3839+
DoubleSpec[[int, int], [str, str], bool]: "DoubleSpec[[int, int], [str, str], bool]",
3840+
3841+
TsP[*Ts, P]: "TsP[*Ts, ~P]",
3842+
TsP[int, str, list[int], []]: "TsP[int, str, list[int], []]",
3843+
TsP[int, [str, list[int]]]: "TsP[int, [str, list[int]]]",
3844+
3845+
# These lines are just too long to fit:
3846+
MyCallable[Concatenate[*Ts, P], int][int, str, [bool, float]]:
3847+
"MyCallable[[int, str, bool, float], int]",
3848+
}
3849+
3850+
for obj, expected_repr in object_to_expected_repr.items():
3851+
with self.subTest(obj=obj, expected_repr=expected_repr):
3852+
self.assertRegex(
3853+
repr(obj),
3854+
fr"^{re.escape(MyCallable.__module__)}.*\.{re.escape(expected_repr)}$",
3855+
)
3856+
38123857
def test_eq_1(self):
38133858
self.assertEqual(Generic, Generic)
38143859
self.assertEqual(Generic[T], Generic[T])

Lib/typing.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,16 +230,17 @@ def _type_repr(obj):
230230
typically enough to uniquely identify a type. For everything
231231
else, we fall back on repr(obj).
232232
"""
233-
if isinstance(obj, types.GenericAlias):
234-
return repr(obj)
235233
if isinstance(obj, type):
236234
if obj.__module__ == 'builtins':
237235
return obj.__qualname__
238236
return f'{obj.__module__}.{obj.__qualname__}'
239237
if obj is ...:
240-
return('...')
238+
return '...'
241239
if isinstance(obj, types.FunctionType):
242240
return obj.__name__
241+
if isinstance(obj, tuple):
242+
# Special case for `repr` of types with `ParamSpec`:
243+
return '[' + ', '.join(_type_repr(t) for t in obj) + ']'
243244
return repr(obj)
244245

245246

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,7 @@ regen-cases:
14851485
PYTHONPATH=$(srcdir)/Tools/cases_generator \
14861486
$(PYTHON_FOR_REGEN) \
14871487
$(srcdir)/Tools/cases_generator/generate_cases.py \
1488+
--emit-line-directives \
14881489
-o $(srcdir)/Python/generated_cases.c.h.new \
14891490
-m $(srcdir)/Python/opcode_metadata.h.new \
14901491
$(srcdir)/Python/bytecodes.c

Misc/NEWS.d/3.12.0a2.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ Fix ``make regen-test-levenshtein`` for out-of-tree builds.
959959
960960
Don't use vendored ``libmpdec`` headers if :option:`--with-system-libmpdec`
961961
is passed to :program:`configure`. Don't use vendored ``libexpat`` headers
962-
if :option:`--with-system-expat` is passed to :program:`!configure`.
962+
if :option:`--with-system-expat` is passed to :program:`configure`.
963963

964964
..
965965
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix potential nullptr dereference and use of uninitialized memory in fileutils. Patch by Max Bachmann.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Typing: Improve the ``repr`` of generic aliases for classes generic over a
2+
:class:`~typing.ParamSpec`. (Use square brackets to represent a parameter
3+
list.)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improved test_locale_calendar_formatweekday of calendar.

Modules/getpath.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,10 @@ getpath_realpath(PyObject *Py_UNUSED(self) , PyObject *args)
446446
if (s) {
447447
*s = L'\0';
448448
}
449-
path2 = _Py_normpath(_Py_join_relfile(path, resolved), -1);
449+
path2 = _Py_join_relfile(path, resolved);
450+
if (path2) {
451+
path2 = _Py_normpath(path2, -1);
452+
}
450453
PyMem_RawFree((void *)path);
451454
path = path2;
452455
}

Python/fileutils.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2233,7 +2233,10 @@ _Py_join_relfile(const wchar_t *dirname, const wchar_t *relfile)
22332233
}
22342234
assert(wcslen(dirname) < MAXPATHLEN);
22352235
assert(wcslen(relfile) < MAXPATHLEN - wcslen(dirname));
2236-
join_relfile(filename, bufsize, dirname, relfile);
2236+
if (join_relfile(filename, bufsize, dirname, relfile) < 0) {
2237+
PyMem_RawFree(filename);
2238+
return NULL;
2239+
}
22372240
return filename;
22382241
}
22392242

@@ -2271,6 +2274,7 @@ _Py_find_basename(const wchar_t *filename)
22712274
wchar_t *
22722275
_Py_normpath(wchar_t *path, Py_ssize_t size)
22732276
{
2277+
assert(path != NULL);
22742278
if (!path[0] || size == 0) {
22752279
return path;
22762280
}

0 commit comments

Comments
 (0)