Skip to content

Commit 24f98d5

Browse files
Merge remote-tracking branch 'upstream/main' into decref_elimination_floats
2 parents 01004c2 + b265a7d commit 24f98d5

Some content is hidden

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

43 files changed

+1062
-375
lines changed

Doc/extending/extending.rst

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,32 @@ value must be in a particular range or must satisfy other conditions,
204204
:c:data:`PyExc_ValueError` is appropriate.
205205

206206
You can also define a new exception that is unique to your module.
207-
For this, you can declare a static global object variable at the beginning
208-
of the file::
207+
The simplest way to do this is to declare a static global object variable at
208+
the beginning of the file::
209209

210-
static PyObject *SpamError;
210+
static PyObject *SpamError = NULL;
211211

212-
and initialize it with an exception object in the module's
212+
and initialize it by calling :c:func:`PyErr_NewException` in the module's
213213
:c:data:`Py_mod_exec` function (:c:func:`!spam_module_exec`)::
214214

215+
SpamError = PyErr_NewException("spam.error", NULL, NULL);
216+
217+
Since :c:data:`!SpamError` is a global variable, it will be overwitten every time
218+
the module is reinitialized, when the :c:data:`Py_mod_exec` function is called.
219+
220+
For now, let's avoid the issue: we will block repeated initialization by raising an
221+
:py:exc:`ImportError`::
222+
223+
static PyObject *SpamError = NULL;
224+
215225
static int
216226
spam_module_exec(PyObject *m)
217227
{
228+
if (SpamError != NULL) {
229+
PyErr_SetString(PyExc_ImportError,
230+
"cannot initialize spam module more than once");
231+
return -1;
232+
}
218233
SpamError = PyErr_NewException("spam.error", NULL, NULL);
219234
if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
220235
return -1;
@@ -253,6 +268,11 @@ needed to ensure that it will not be discarded, causing :c:data:`!SpamError` to
253268
become a dangling pointer. Should it become a dangling pointer, C code which
254269
raises the exception could cause a core dump or other unintended side effects.
255270

271+
For now, the :c:func:`Py_DECREF` call to remove this reference is missing.
272+
Even when the Python interpreter shuts down, the global :c:data:`!SpamError`
273+
variable will not be garbage-collected. It will "leak".
274+
We did, however, ensure that this will happen at most once per process.
275+
256276
We discuss the use of :c:macro:`PyMODINIT_FUNC` as a function return type later in this
257277
sample.
258278

Doc/library/logging.handlers.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,10 @@ module, supports rotation of disk log files.
352352
Outputs the record to the file, catering for rollover as described
353353
previously.
354354

355+
.. method:: shouldRollover(record)
356+
357+
See if the supplied record would cause the file to exceed the configured size limit.
358+
355359
.. _timed-rotating-file-handler:
356360

357361
TimedRotatingFileHandler
@@ -459,7 +463,11 @@ timed intervals.
459463
.. method:: getFilesToDelete()
460464

461465
Returns a list of filenames which should be deleted as part of rollover. These
462-
are the absolute paths of the oldest backup log files written by the handler.
466+
467+
.. method:: shouldRollover(record)
468+
469+
See if enough time has passed for a rollover to occur and if it has, compute
470+
the next rollover time.
463471

464472
.. _socket-handler:
465473

Doc/library/math.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
--------------
1212

13-
This module provides access to the mathematical functions defined by the C
14-
standard.
13+
This module provides access to common mathematical functions and constants,
14+
including those defined by the C standard.
1515

1616
These functions cannot be used with complex numbers; use the functions of the
1717
same name from the :mod:`cmath` module if you require support for complex

Doc/library/stdtypes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,8 @@ accepts integers that meet the value restriction ``0 <= x <= 255``).
12141214
| ``s[i] = x`` | item *i* of *s* is replaced by | |
12151215
| | *x* | |
12161216
+------------------------------+--------------------------------+---------------------+
1217+
| ``del s[i]`` | removes item *i* of *s* | |
1218+
+------------------------------+--------------------------------+---------------------+
12171219
| ``s[i:j] = t`` | slice of *s* from *i* to *j* | |
12181220
| | is replaced by the contents of | |
12191221
| | the iterable *t* | |

Doc/library/typing.rst

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3530,28 +3530,32 @@ Constant
35303530
.. data:: TYPE_CHECKING
35313531

35323532
A special constant that is assumed to be ``True`` by 3rd party static
3533-
type checkers. It is ``False`` at runtime.
3533+
type checkers. It's ``False`` at runtime.
3534+
3535+
A module which is expensive to import, and which only contain types
3536+
used for typing annotations, can be safely imported inside an
3537+
``if TYPE_CHECKING:`` block. This prevents the module from actually
3538+
being imported at runtime; annotations aren't eagerly evaluated
3539+
(see :pep:`649`) so using undefined symbols in annotations is
3540+
harmless--as long as you don't later examine them.
3541+
Your static type analysis tool will set ``TYPE_CHECKING`` to
3542+
``True`` during static type analysis, which means the module will
3543+
be imported and the types will be checked properly during such analysis.
35343544

35353545
Usage::
35363546

35373547
if TYPE_CHECKING:
35383548
import expensive_mod
35393549

3540-
def fun(arg: 'expensive_mod.SomeType') -> None:
3550+
def fun(arg: expensive_mod.SomeType) -> None:
35413551
local_var: expensive_mod.AnotherType = other_fun()
35423552

3543-
The first type annotation must be enclosed in quotes, making it a
3544-
"forward reference", to hide the ``expensive_mod`` reference from the
3545-
interpreter runtime. Type annotations for local variables are not
3546-
evaluated, so the second annotation does not need to be enclosed in quotes.
3547-
3548-
.. note::
3549-
3550-
If ``from __future__ import annotations`` is used,
3551-
annotations are not evaluated at function definition time.
3552-
Instead, they are stored as strings in ``__annotations__``.
3553-
This makes it unnecessary to use quotes around the annotation
3554-
(see :pep:`563`).
3553+
If you occasionally need to examine type annotations at runtime
3554+
which may contain undefined symbols, use
3555+
:meth:`annotationlib.get_annotations` with a ``format`` parameter
3556+
of :attr:`annotationlib.Format.STRING` or
3557+
:attr:`annotationlib.Format.FORWARDREF` to safely retrieve the
3558+
annotations without raising :exc:`NameError`.
35553559

35563560
.. versionadded:: 3.5.2
35573561

Doc/tools/extensions/audit_events.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from sphinx.util.docutils import SphinxDirective
1414

1515
if TYPE_CHECKING:
16-
from collections.abc import Iterator
16+
from collections.abc import Iterator, Set
1717

1818
from sphinx.application import Sphinx
1919
from sphinx.builders import Builder
@@ -33,7 +33,7 @@
3333
class AuditEvents:
3434
def __init__(self) -> None:
3535
self.events: dict[str, list[str]] = {}
36-
self.sources: dict[str, list[tuple[str, str]]] = {}
36+
self.sources: dict[str, set[tuple[str, str]]] = {}
3737

3838
def __iter__(self) -> Iterator[tuple[str, list[str], tuple[str, str]]]:
3939
for name, args in self.events.items():
@@ -47,7 +47,7 @@ def add_event(
4747
self._check_args_match(name, args)
4848
else:
4949
self.events[name] = args
50-
self.sources.setdefault(name, []).append(source)
50+
self.sources.setdefault(name, set()).add(source)
5151

5252
def _check_args_match(self, name: str, args: list[str]) -> None:
5353
current_args = self.events[name]
@@ -69,11 +69,11 @@ def _check_args_match(self, name: str, args: list[str]) -> None:
6969
return
7070

7171
def id_for(self, name) -> str:
72-
source_count = len(self.sources.get(name, ()))
72+
source_count = len(self.sources.get(name, set()))
7373
name_clean = re.sub(r"\W", "_", name)
7474
return f"audit_event_{name_clean}_{source_count}"
7575

76-
def rows(self) -> Iterator[tuple[str, list[str], list[tuple[str, str]]]]:
76+
def rows(self) -> Iterator[tuple[str, list[str], Set[tuple[str, str]]]]:
7777
for name in sorted(self.events.keys()):
7878
yield name, self.events[name], self.sources[name]
7979

@@ -218,7 +218,7 @@ def _make_row(
218218
docname: str,
219219
name: str,
220220
args: list[str],
221-
sources: list[tuple[str, str]],
221+
sources: Set[tuple[str, str]],
222222
) -> nodes.row:
223223
row = nodes.row()
224224
name_node = nodes.paragraph("", nodes.Text(name))
@@ -233,7 +233,7 @@ def _make_row(
233233
row += nodes.entry("", args_node)
234234

235235
backlinks_node = nodes.paragraph()
236-
backlinks = enumerate(sorted(set(sources)), start=1)
236+
backlinks = enumerate(sorted(sources), start=1)
237237
for i, (doc, label) in backlinks:
238238
if isinstance(label, str):
239239
ref = nodes.reference("", f"[{i}]", internal=True)
@@ -258,7 +258,7 @@ def setup(app: Sphinx):
258258
app.connect("env-purge-doc", audit_events_purge)
259259
app.connect("env-merge-info", audit_events_merge)
260260
return {
261-
"version": "1.0",
261+
"version": "2.0",
262262
"parallel_read_safe": True,
263263
"parallel_write_safe": True,
264264
}

Doc/whatsnew/3.15.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ New modules
8989
Improved modules
9090
================
9191

92+
difflib
93+
-------
94+
95+
* Improved the styling of HTML diff pages generated by the :class:`difflib.HtmlDiff`
96+
class, and migrated the output to the HTML5 standard.
97+
(Contributed by Jiahao Li in :gh:`134580`.)
98+
9299
ssl
93100
---
94101

Include/internal/pycore_interp_structs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,11 @@ struct _Py_interp_cached_objects {
677677

678678
/* object.__reduce__ */
679679
PyObject *objreduce;
680+
#ifndef Py_GIL_DISABLED
681+
/* resolve_slotdups() */
680682
PyObject *type_slots_pname;
681683
pytype_slotdef *type_slots_ptrs[MAX_EQUIV];
684+
#endif
682685

683686
/* TypeVar and related types */
684687
PyTypeObject *generic_type;

Include/internal/pycore_object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ extern int _PyDict_CheckConsistency(PyObject *mp, int check_content);
313313
// Fast inlined version of PyType_HasFeature()
314314
static inline int
315315
_PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
316-
return ((FT_ATOMIC_LOAD_ULONG_RELAXED(type->tp_flags) & feature) != 0);
316+
return ((type->tp_flags) & feature) != 0;
317317
}
318318

319319
extern void _PyType_InitCache(PyInterpreterState *interp);

Include/internal/pycore_typeobject.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ extern int _PyType_AddMethod(PyTypeObject *, PyMethodDef *);
134134
extern void _PyType_SetFlagsRecursive(PyTypeObject *self, unsigned long mask,
135135
unsigned long flags);
136136

137-
extern unsigned int _PyType_GetVersionForCurrentState(PyTypeObject *tp);
138137
PyAPI_FUNC(void) _PyType_SetVersion(PyTypeObject *tp, unsigned int version);
139138
PyTypeObject *_PyType_LookupByVersion(unsigned int version);
140139

0 commit comments

Comments
 (0)