Skip to content

Commit 27bb251

Browse files
authored
Merge branch 'main' into tempdir_delete
2 parents b0b2f83 + 004f9fd commit 27bb251

Some content is hidden

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

56 files changed

+1188
-541
lines changed

Doc/library/calendar.rst

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,33 @@ interpreted as prescribed by the ISO 8601 standard. Year 0 is 1 BC, year -1 is
3838
itself. This is the job of subclasses.
3939

4040

41-
:class:`Calendar` instances have the following methods:
41+
:class:`Calendar` instances have the following methods and attributes:
42+
43+
.. attribute:: firstweekday
44+
45+
The first weekday as an integer (0--6).
46+
47+
This property can also be set and read using
48+
:meth:`~Calendar.setfirstweekday` and
49+
:meth:`~Calendar.getfirstweekday` respectively.
50+
51+
.. method:: getfirstweekday()
52+
53+
Return an :class:`int` for the current first weekday (0--6).
54+
55+
Identical to reading the :attr:`~Calendar.firstweekday` property.
56+
57+
.. method:: setfirstweekday(firstweekday)
58+
59+
Set the first weekday to *firstweekday*, passed as an :class:`int` (0--6)
60+
61+
Identical to setting the :attr:`~Calendar.firstweekday` property.
4262

4363
.. method:: iterweekdays()
4464

4565
Return an iterator for the week day numbers that will be used for one
4666
week. The first value from the iterator will be the same as the value of
47-
the :attr:`firstweekday` property.
67+
the :attr:`~Calendar.firstweekday` property.
4868

4969

5070
.. method:: itermonthdates(year, month)

Doc/library/ctypes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,8 @@ different ways, depending on the type and number of the parameters in the call:
18121812
the COM interface as first argument, in addition to those parameters that
18131813
are specified in the :attr:`!argtypes` tuple.
18141814

1815+
.. availability:: Windows
1816+
18151817

18161818
The optional *paramflags* parameter creates foreign function wrappers with much
18171819
more functionality than the features described above.

Doc/library/json.rst

Lines changed: 75 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -258,75 +258,100 @@ Basic Usage
258258
the original one. That is, ``loads(dumps(x)) != x`` if x has non-string
259259
keys.
260260

261-
.. function:: load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
261+
.. function:: load(fp, *, cls=None, object_hook=None, parse_float=None, \
262+
parse_int=None, parse_constant=None, \
263+
object_pairs_hook=None, **kw)
262264
263-
Deserialize *fp* (a ``.read()``-supporting :term:`text file` or
264-
:term:`binary file` containing a JSON document) to a Python object using
265-
this :ref:`conversion table <json-to-py-table>`.
265+
Deserialize *fp* to a Python object
266+
using the :ref:`JSON-to-Python conversion table <json-to-py-table>`.
266267

267-
*object_hook* is an optional function that will be called with the result of
268-
any object literal decoded (a :class:`dict`). The return value of
269-
*object_hook* will be used instead of the :class:`dict`. This feature can
270-
be used to implement custom decoders (e.g. `JSON-RPC
271-
<https://www.jsonrpc.org>`_ class hinting).
268+
:param fp:
269+
A ``.read()``-supporting :term:`text file` or :term:`binary file`
270+
containing the JSON document to be deserialized.
271+
:type fp: :term:`file-like object`
272272

273-
*object_pairs_hook* is an optional function that will be called with the
274-
result of any object literal decoded with an ordered list of pairs. The
275-
return value of *object_pairs_hook* will be used instead of the
276-
:class:`dict`. This feature can be used to implement custom decoders. If
277-
*object_hook* is also defined, the *object_pairs_hook* takes priority.
273+
:param cls:
274+
If set, a custom JSON decoder.
275+
Additional keyword arguments to :func:`!load`
276+
will be passed to the constructor of *cls*.
277+
If ``None`` (the default), :class:`!JSONDecoder` is used.
278+
:type cls: a :class:`JSONDecoder` subclass
279+
280+
:param object_hook:
281+
If set, a function that is called with the result of
282+
any object literal decoded (a :class:`dict`).
283+
The return value of this function will be used
284+
instead of the :class:`dict`.
285+
This feature can be used to implement custom decoders,
286+
for example `JSON-RPC <https://www.jsonrpc.org>`_ class hinting.
287+
Default ``None``.
288+
:type object_hook: :term:`callable` | None
289+
290+
:param object_pairs_hook:
291+
If set, a function that is called with the result of
292+
any object literal decoded with an ordered list of pairs.
293+
The return value of this function will be used
294+
instead of the :class:`dict`.
295+
This feature can be used to implement custom decoders.
296+
If *object_hook* is also set, *object_pairs_hook* takes priority.
297+
Default ``None``.
298+
:type object_pairs_hook: :term:`callable` | None
299+
300+
:param parse_float:
301+
If set, a function that is called with
302+
the string of every JSON float to be decoded.
303+
If ``None`` (the default), it is equivalent to ``float(num_str)``.
304+
This can be used to parse JSON floats into custom datatypes,
305+
for example :class:`decimal.Decimal`.
306+
:type parse_float: :term:`callable` | None
307+
308+
:param parse_int:
309+
If set, a function that is called with
310+
the string of every JSON int to be decoded.
311+
If ``None`` (the default), it is equivalent to ``int(num_str)``.
312+
This can be used to parse JSON integers into custom datatypes,
313+
for example :class:`float`.
314+
:type parse_int: :term:`callable` | None
315+
316+
:param parse_constant:
317+
If set, a function that is called with one of the following strings:
318+
``'-Infinity'``, ``'Infinity'``, or ``'NaN'``.
319+
This can be used to raise an exception
320+
if invalid JSON numbers are encountered.
321+
Default ``None``.
322+
:type parse_constant: :term:`callable` | None
323+
324+
:raises JSONDecodeError:
325+
When the data being deserialized is not a valid JSON document.
326+
327+
:raises UnicodeDecodeError:
328+
When the data being deserialized does not contain
329+
UTF-8, UTF-16 or UTF-32 encoded data.
278330

279331
.. versionchanged:: 3.1
280-
Added support for *object_pairs_hook*.
281332

282-
*parse_float* is an optional function that will be called with the string of
283-
every JSON float to be decoded. By default, this is equivalent to
284-
``float(num_str)``. This can be used to use another datatype or parser for
285-
JSON floats (e.g. :class:`decimal.Decimal`).
333+
* Added the optional *object_pairs_hook* parameter.
334+
* *parse_constant* doesn't get called on 'null', 'true', 'false' anymore.
286335

287-
*parse_int* is an optional function that will be called with the string of
288-
every JSON int to be decoded. By default, this is equivalent to
289-
``int(num_str)``. This can be used to use another datatype or parser for
290-
JSON integers (e.g. :class:`float`).
336+
.. versionchanged:: 3.6
337+
338+
* All optional parameters are now :ref:`keyword-only <keyword-only_parameter>`.
339+
* *fp* can now be a :term:`binary file`.
340+
The input encoding should be UTF-8, UTF-16 or UTF-32.
291341

292342
.. versionchanged:: 3.11
293343
The default *parse_int* of :func:`int` now limits the maximum length of
294344
the integer string via the interpreter's :ref:`integer string
295345
conversion length limitation <int_max_str_digits>` to help avoid denial
296346
of service attacks.
297347

298-
*parse_constant* is an optional function that will be called with one of the
299-
following strings: ``'-Infinity'``, ``'Infinity'``, ``'NaN'``. This can be
300-
used to raise an exception if invalid JSON numbers are encountered.
301-
302-
.. versionchanged:: 3.1
303-
*parse_constant* doesn't get called on 'null', 'true', 'false' anymore.
304-
305-
To use a custom :class:`JSONDecoder` subclass, specify it with the ``cls``
306-
kwarg; otherwise :class:`JSONDecoder` is used. Additional keyword arguments
307-
will be passed to the constructor of the class.
308-
309-
If the data being deserialized is not a valid JSON document, a
310-
:exc:`JSONDecodeError` will be raised.
311-
312-
.. versionchanged:: 3.6
313-
All optional parameters are now :ref:`keyword-only <keyword-only_parameter>`.
314-
315-
.. versionchanged:: 3.6
316-
*fp* can now be a :term:`binary file`. The input encoding should be
317-
UTF-8, UTF-16 or UTF-32.
318-
319348
.. function:: loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
320349

321-
Deserialize *s* (a :class:`str`, :class:`bytes` or :class:`bytearray`
350+
Identical to :func:`load`, but instead of a file-like object,
351+
deserialize *s* (a :class:`str`, :class:`bytes` or :class:`bytearray`
322352
instance containing a JSON document) to a Python object using this
323353
:ref:`conversion table <json-to-py-table>`.
324354

325-
The other arguments have the same meaning as in :func:`load`.
326-
327-
If the data being deserialized is not a valid JSON document, a
328-
:exc:`JSONDecodeError` will be raised.
329-
330355
.. versionchanged:: 3.6
331356
*s* can now be of type :class:`bytes` or :class:`bytearray`. The
332357
input encoding should be UTF-8, UTF-16 or UTF-32.

Lib/asyncio/base_events.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,12 @@ def create_task(self, coro, *, name=None, context=None):
477477

478478
task.set_name(name)
479479

480-
return task
480+
try:
481+
return task
482+
finally:
483+
# gh-128552: prevent a refcycle of
484+
# task.exception().__traceback__->BaseEventLoop.create_task->task
485+
del task
481486

482487
def set_task_factory(self, factory):
483488
"""Set a task factory that will be used by loop.create_task().

Lib/asyncio/taskgroups.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,12 @@ def create_task(self, coro, *, name=None, context=None):
205205
else:
206206
self._tasks.add(task)
207207
task.add_done_callback(self._on_task_done)
208-
return task
208+
try:
209+
return task
210+
finally:
211+
# gh-128552: prevent a refcycle of
212+
# task.exception().__traceback__->TaskGroup.create_task->task
213+
del task
209214

210215
# Since Python 3.8 Tasks propagate all exceptions correctly,
211216
# except for KeyboardInterrupt and SystemExit which are

Lib/asyncio/timeouts.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import enum
22

33
from types import TracebackType
4-
from typing import final, Optional, Type
54

65
from . import events
76
from . import exceptions
@@ -23,14 +22,13 @@ class _State(enum.Enum):
2322
EXITED = "finished"
2423

2524

26-
@final
2725
class Timeout:
2826
"""Asynchronous context manager for cancelling overdue coroutines.
2927
3028
Use `timeout()` or `timeout_at()` rather than instantiating this class directly.
3129
"""
3230

33-
def __init__(self, when: Optional[float]) -> None:
31+
def __init__(self, when: float | None) -> None:
3432
"""Schedule a timeout that will trigger at a given loop time.
3533
3634
- If `when` is `None`, the timeout will never trigger.
@@ -39,15 +37,15 @@ def __init__(self, when: Optional[float]) -> None:
3937
"""
4038
self._state = _State.CREATED
4139

42-
self._timeout_handler: Optional[events.TimerHandle] = None
43-
self._task: Optional[tasks.Task] = None
40+
self._timeout_handler: events.TimerHandle | None = None
41+
self._task: tasks.Task | None = None
4442
self._when = when
4543

46-
def when(self) -> Optional[float]:
44+
def when(self) -> float | None:
4745
"""Return the current deadline."""
4846
return self._when
4947

50-
def reschedule(self, when: Optional[float]) -> None:
48+
def reschedule(self, when: float | None) -> None:
5149
"""Reschedule the timeout."""
5250
if self._state is not _State.ENTERED:
5351
if self._state is _State.CREATED:
@@ -96,10 +94,10 @@ async def __aenter__(self) -> "Timeout":
9694

9795
async def __aexit__(
9896
self,
99-
exc_type: Optional[Type[BaseException]],
100-
exc_val: Optional[BaseException],
101-
exc_tb: Optional[TracebackType],
102-
) -> Optional[bool]:
97+
exc_type: type[BaseException] | None,
98+
exc_val: BaseException | None,
99+
exc_tb: TracebackType | None,
100+
) -> bool | None:
103101
assert self._state in (_State.ENTERED, _State.EXPIRING)
104102

105103
if self._timeout_handler is not None:
@@ -142,7 +140,7 @@ def _insert_timeout_error(exc_val: BaseException) -> None:
142140
exc_val = exc_val.__context__
143141

144142

145-
def timeout(delay: Optional[float]) -> Timeout:
143+
def timeout(delay: float | None) -> Timeout:
146144
"""Timeout async context manager.
147145
148146
Useful in cases when you want to apply timeout logic around block
@@ -162,7 +160,7 @@ def timeout(delay: Optional[float]) -> Timeout:
162160
return Timeout(loop.time() + delay if delay is not None else None)
163161

164162

165-
def timeout_at(when: Optional[float]) -> Timeout:
163+
def timeout_at(when: float | None) -> Timeout:
166164
"""Schedule the timeout at absolute time.
167165
168166
Like timeout() but argument gives absolute time in the same clock system

Lib/pydoc.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class or function within a module or module in a package. If the
5353
# the current directory is changed with os.chdir(), an incorrect
5454
# path will be displayed.
5555

56+
import ast
5657
import __future__
5758
import builtins
5859
import importlib._bootstrap
@@ -384,21 +385,29 @@ def ispackage(path):
384385
return False
385386

386387
def source_synopsis(file):
387-
line = file.readline()
388-
while line[:1] == '#' or not line.strip():
389-
line = file.readline()
390-
if not line: break
391-
line = line.strip()
392-
if line[:4] == 'r"""': line = line[1:]
393-
if line[:3] == '"""':
394-
line = line[3:]
395-
if line[-1:] == '\\': line = line[:-1]
396-
while not line.strip():
397-
line = file.readline()
398-
if not line: break
399-
result = line.split('"""')[0].strip()
400-
else: result = None
401-
return result
388+
"""Return the one-line summary of a file object, if present"""
389+
390+
string = ''
391+
try:
392+
tokens = tokenize.generate_tokens(file.readline)
393+
for tok_type, tok_string, _, _, _ in tokens:
394+
if tok_type == tokenize.STRING:
395+
string += tok_string
396+
elif tok_type == tokenize.NEWLINE:
397+
with warnings.catch_warnings():
398+
# Ignore the "invalid escape sequence" warning.
399+
warnings.simplefilter("ignore", SyntaxWarning)
400+
docstring = ast.literal_eval(string)
401+
if not isinstance(docstring, str):
402+
return None
403+
return docstring.strip().split('\n')[0].strip()
404+
elif tok_type == tokenize.OP and tok_string in ('(', ')'):
405+
string += tok_string
406+
elif tok_type not in (tokenize.COMMENT, tokenize.NL, tokenize.ENCODING):
407+
return None
408+
except (tokenize.TokenError, UnicodeDecodeError, SyntaxError):
409+
return None
410+
return None
402411

403412
def synopsis(filename, cache={}):
404413
"""Get the one-line summary out of a module file."""

0 commit comments

Comments
 (0)