Skip to content

Commit 19b3d9e

Browse files
committed
Merge branch 'main' into supermon
* main: (27 commits) pythongh-87849: fix SEND specialization family definition (pythonGH-104268) pythongh-101819: Adapt _io.IOBase.seek and _io.IOBase.truncate to Argument Clinic (python#104384) pythongh-101819: Adapt _io._Buffered* methods to Argument Clinic (python#104367) pythongh-101819: Refactor `_io` futher in preparation for module isolation (python#104369) pythongh-101819: Adapt _io.TextIOBase methods to Argument Clinic (python#104383) pythongh-101117: Improve accuracy of sqlite3.Cursor.rowcount docs (python#104287) pythonGH-92184: Convert os.altsep to '/' in filenames when creating ZipInfo objects (python#92185) pythongh-104357: fix inlined comprehensions that close over iteration var (python#104368) pythonGH-90208: Suppress OSError exceptions from `pathlib.Path.glob()` (pythonGH-104141) pythonGH-102181: Improve specialization stats for SEND (pythonGH-102182) pythongh-103000: Optimise `dataclasses.asdict` for the common case (python#104364) pythongh-103538: Remove unused TK_AQUA code (pythonGH-103539) pythonGH-87695: Fix OSError from `pathlib.Path.glob()` (pythonGH-104292) pythongh-104263: Rely on Py_NAN and introduce Py_INFINITY (pythonGH-104202) pythongh-104010: Separate and improve docs for `typing.get_origin` and `typing.get_args` (python#104013) pythongh-101819: Adapt _io._BufferedIOBase_Type methods to Argument Clinic (python#104355) pythongh-103960: Dark mode: invert image brightness (python#103983) pythongh-104252: Immortalize Py_EMPTY_KEYS (pythongh-104253) pythongh-101819: Clean up _io windows console io after pythongh-104197 (python#104354) pythongh-101819: Harden _io init (python#104352) ...
2 parents 8fb9b52 + 1670729 commit 19b3d9e

Some content is hidden

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

60 files changed

+1780
-918
lines changed

Doc/howto/logging.rst

+1
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ The flow of log event information in loggers and handlers is illustrated in the
418418
following diagram.
419419

420420
.. image:: logging_flow.png
421+
:class: invert-in-dark-mode
421422

422423
Loggers
423424
^^^^^^^

Doc/library/hashlib.rst

+1
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ Constructor functions also accept the following tree hashing parameters:
430430

431431
.. figure:: hashlib-blake2-tree.png
432432
:alt: Explanation of tree mode parameters.
433+
:class: invert-in-dark-mode
433434

434435
See section 2.10 in `BLAKE2 specification
435436
<https://www.blake2.net/blake2_20130129.pdf>`_ for comprehensive review of tree

Doc/library/http.client.rst

+18-2
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,10 @@ HTTPConnection Objects
264264
encode_chunked=False)
265265

266266
This will send a request to the server using the HTTP request
267-
method *method* and the selector *url*.
267+
method *method* and the request URI *url*. The provided *url* must be
268+
an absolute path to conform with :rfc:`RFC 2616 §5.1.2 <2616#section-5.1.2>`
269+
(unless connecting to an HTTP proxy server or using the ``OPTIONS`` or
270+
``CONNECT`` methods).
268271

269272
If *body* is specified, the specified data is sent after the headers are
270273
finished. It may be a :class:`str`, a :term:`bytes-like object`, an
@@ -279,7 +282,10 @@ HTTPConnection Objects
279282
iterable are sent as is until the iterable is exhausted.
280283

281284
The *headers* argument should be a mapping of extra HTTP headers to send
282-
with the request.
285+
with the request. A :rfc:`Host header <2616#section-14.23>`
286+
must be provided to conform with :rfc:`RFC 2616 §5.1.2 <2616#section-5.1.2>`
287+
(unless connecting to an HTTP proxy server or using the ``OPTIONS`` or
288+
``CONNECT`` methods).
283289

284290
If *headers* contains neither Content-Length nor Transfer-Encoding,
285291
but there is a request body, one of those
@@ -298,6 +304,16 @@ HTTPConnection Objects
298304
HTTPConnection object assumes that all encoding is handled by the
299305
calling code. If it is ``True``, the body will be chunk-encoded.
300306

307+
For example, to perform a ``GET`` request to ``https://docs.python.org/3/``::
308+
309+
>>> import http.client
310+
>>> host = "docs.python.org"
311+
>>> conn = http.client.HTTPSConnection(host)
312+
>>> conn.request("GET", "/3/", headers={"Host": host})
313+
>>> response = conn.getresponse()
314+
>>> print(response.status, response.reason)
315+
200 OK
316+
301317
.. note::
302318
Chunked transfer encoding has been added to the HTTP protocol
303319
version 1.1. Unless the HTTP server is known to handle HTTP 1.1,

Doc/library/pathlib.rst

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ inherit from pure paths but also provide I/O operations.
2121

2222
.. image:: pathlib-inheritance.png
2323
:align: center
24+
:class: invert-in-dark-mode
2425

2526
If you've never used this module before or just aren't sure which class is
2627
right for your task, :class:`Path` is most likely what you need. It instantiates

Doc/library/sqlite3.rst

+4-1
Original file line numberDiff line numberDiff line change
@@ -1694,7 +1694,10 @@ Cursor objects
16941694
``INSERT``, ``UPDATE``, ``DELETE``, and ``REPLACE`` statements;
16951695
is ``-1`` for other statements,
16961696
including :abbr:`CTE (Common Table Expression)` queries.
1697-
It is only updated by the :meth:`execute` and :meth:`executemany` methods.
1697+
It is only updated by the :meth:`execute` and :meth:`executemany` methods,
1698+
after the statement has run to completion.
1699+
This means that any resulting rows must be fetched in order for
1700+
:attr:`!rowcount` to be updated.
16981701

16991702
.. attribute:: row_factory
17001703

Doc/library/typing.rst

+22-9
Original file line numberDiff line numberDiff line change
@@ -2876,24 +2876,37 @@ Introspection helpers
28762876
if a default value equal to ``None`` was set.
28772877
Now the annotation is returned unchanged.
28782878

2879-
.. function:: get_args(tp)
28802879
.. function:: get_origin(tp)
28812880

2882-
Provide basic introspection for generic types and special typing forms.
2883-
2884-
For a typing object of the form ``X[Y, Z, ...]`` these functions return
2885-
``X`` and ``(Y, Z, ...)``. If ``X`` is a generic alias for a builtin or
2881+
Get the unsubscripted version of a type: for a typing object of the form
2882+
``X[Y, Z, ...]`` return ``X``. If ``X`` is a generic alias for a builtin or
28862883
:mod:`collections` class, it gets normalized to the original class.
2884+
If ``X`` is an instance of :class:`ParamSpecArgs` or :class:`ParamSpecKwargs`,
2885+
return the underlying :class:`ParamSpec`.
2886+
Return ``None`` for unsupported objects.
2887+
Examples::
2888+
2889+
assert get_origin(str) is None
2890+
assert get_origin(Dict[str, int]) is dict
2891+
assert get_origin(Union[int, str]) is Union
2892+
P = ParamSpec('P')
2893+
assert get_origin(P.args) is P
2894+
assert get_origin(P.kwargs) is P
2895+
2896+
.. versionadded:: 3.8
2897+
2898+
.. function:: get_args(tp)
2899+
2900+
Get type arguments with all substitutions performed: for a typing object
2901+
of the form ``X[Y, Z, ...]`` return ``(Y, Z, ...)``.
28872902
If ``X`` is a union or :class:`Literal` contained in another
28882903
generic type, the order of ``(Y, Z, ...)`` may be different from the order
28892904
of the original arguments ``[Y, Z, ...]`` due to type caching.
2890-
For unsupported objects return ``None`` and ``()`` correspondingly.
2905+
Return ``()`` for unsupported objects.
28912906
Examples::
28922907

2893-
assert get_origin(Dict[str, int]) is dict
2908+
assert get_args(int) == ()
28942909
assert get_args(Dict[int, str]) == (int, str)
2895-
2896-
assert get_origin(Union[int, str]) is Union
28972910
assert get_args(Union[int, str]) == (int, str)
28982911

28992912
.. versionadded:: 3.8

Include/cpython/genobject.h

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ PyAPI_FUNC(PyObject *) PyAsyncGen_New(PyFrameObject *,
7777

7878
#define PyAsyncGen_CheckExact(op) Py_IS_TYPE((op), &PyAsyncGen_Type)
7979

80+
#define PyAsyncGenASend_CheckExact(op) Py_IS_TYPE((op), &_PyAsyncGenASend_Type)
81+
8082

8183
#undef _PyGenObject_HEAD
8284

Include/internal/pycore_dict_state.h

+5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ struct _Py_dict_state {
3838
PyDict_WatchCallback watchers[DICT_MAX_WATCHERS];
3939
};
4040

41+
#define _dict_state_INIT \
42+
{ \
43+
.next_keys_version = 2, \
44+
}
45+
4146

4247
#ifdef __cplusplus
4348
}

Include/internal/pycore_dtoa.h

-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ PyAPI_FUNC(double) _Py_dg_strtod(const char *str, char **ptr);
6464
PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits,
6565
int *decpt, int *sign, char **rve);
6666
PyAPI_FUNC(void) _Py_dg_freedtoa(char *s);
67-
PyAPI_FUNC(double) _Py_dg_stdnan(int sign);
68-
PyAPI_FUNC(double) _Py_dg_infinity(int sign);
6967

7068
#endif // _PY_SHORT_FLOAT_REPR == 1
7169

Include/internal/pycore_runtime_init.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,7 @@ extern PyTypeObject _PyExc_MemoryError;
107107
}, \
108108
}, \
109109
.dtoa = _dtoa_state_INIT(&(INTERP)), \
110-
.dict_state = { \
111-
.next_keys_version = 2, \
112-
}, \
110+
.dict_state = _dict_state_INIT, \
113111
.func_state = { \
114112
.next_version = 1, \
115113
}, \

Include/pymath.h

+11-14
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,24 @@
3939
// Return 1 if float or double arg is neither infinite nor NAN, else 0.
4040
#define Py_IS_FINITE(X) isfinite(X)
4141

42-
/* HUGE_VAL is supposed to expand to a positive double infinity. Python
43-
* uses Py_HUGE_VAL instead because some platforms are broken in this
44-
* respect. We used to embed code in pyport.h to try to worm around that,
45-
* but different platforms are broken in conflicting ways. If you're on
46-
* a platform where HUGE_VAL is defined incorrectly, fiddle your Python
47-
* config to #define Py_HUGE_VAL to something that works on your platform.
42+
// Py_INFINITY: Value that evaluates to a positive double infinity.
43+
#ifndef Py_INFINITY
44+
# define Py_INFINITY ((double)INFINITY)
45+
#endif
46+
47+
/* Py_HUGE_VAL should always be the same as Py_INFINITY. But historically
48+
* this was not reliable and Python did not require IEEE floats and C99
49+
* conformity. Prefer Py_INFINITY for new code.
4850
*/
4951
#ifndef Py_HUGE_VAL
5052
# define Py_HUGE_VAL HUGE_VAL
5153
#endif
5254

53-
// Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN).
55+
/* Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN). The sign is
56+
* undefined and normally not relevant, but e.g. fixed for float("nan").
57+
*/
5458
#if !defined(Py_NAN)
55-
# if _Py__has_builtin(__builtin_nan)
56-
// Built-in implementation of the ISO C99 function nan(): quiet NaN.
57-
# define Py_NAN (__builtin_nan(""))
58-
#else
59-
// Use C99 NAN constant: quiet Not-A-Number.
60-
// NAN is a float, Py_NAN is a double: cast to double.
6159
# define Py_NAN ((double)NAN)
62-
# endif
6360
#endif
6461

6562
#endif /* Py_PYMATH_H */

Lib/dataclasses.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -1324,11 +1324,18 @@ def _asdict_inner(obj, dict_factory):
13241324
if type(obj) in _ATOMIC_TYPES:
13251325
return obj
13261326
elif _is_dataclass_instance(obj):
1327-
result = []
1328-
for f in fields(obj):
1329-
value = _asdict_inner(getattr(obj, f.name), dict_factory)
1330-
result.append((f.name, value))
1331-
return dict_factory(result)
1327+
# fast path for the common case
1328+
if dict_factory is dict:
1329+
return {
1330+
f.name: _asdict_inner(getattr(obj, f.name), dict)
1331+
for f in fields(obj)
1332+
}
1333+
else:
1334+
result = []
1335+
for f in fields(obj):
1336+
value = _asdict_inner(getattr(obj, f.name), dict_factory)
1337+
result.append((f.name, value))
1338+
return dict_factory(result)
13321339
elif isinstance(obj, tuple) and hasattr(obj, '_fields'):
13331340
# obj is a namedtuple. Recurse into it, but the returned
13341341
# object is another namedtuple of the same type. This is

Lib/pathlib.py

+15-22
Original file line numberDiff line numberDiff line change
@@ -142,25 +142,21 @@ def _select_from(self, parent_path, scandir):
142142
# avoid exhausting file descriptors when globbing deep trees.
143143
with scandir(parent_path) as scandir_it:
144144
entries = list(scandir_it)
145+
except OSError:
146+
pass
147+
else:
145148
for entry in entries:
146149
if self.dironly:
147150
try:
148-
# "entry.is_dir()" can raise PermissionError
149-
# in some cases (see bpo-38894), which is not
150-
# among the errors ignored by _ignore_error()
151151
if not entry.is_dir():
152152
continue
153-
except OSError as e:
154-
if not _ignore_error(e):
155-
raise
153+
except OSError:
156154
continue
157155
name = entry.name
158156
if self.match(name):
159157
path = parent_path._make_child_relpath(name)
160158
for p in self.successor._select_from(path, scandir):
161159
yield p
162-
except PermissionError:
163-
return
164160

165161

166162
class _RecursiveWildcardSelector(_Selector):
@@ -175,28 +171,25 @@ def _iterate_directories(self, parent_path, scandir):
175171
# avoid exhausting file descriptors when globbing deep trees.
176172
with scandir(parent_path) as scandir_it:
177173
entries = list(scandir_it)
174+
except OSError:
175+
pass
176+
else:
178177
for entry in entries:
179178
entry_is_dir = False
180179
try:
181-
entry_is_dir = entry.is_dir()
182-
except OSError as e:
183-
if not _ignore_error(e):
184-
raise
185-
if entry_is_dir and not entry.is_symlink():
180+
entry_is_dir = entry.is_dir(follow_symlinks=False)
181+
except OSError:
182+
pass
183+
if entry_is_dir:
186184
path = parent_path._make_child_relpath(entry.name)
187185
for p in self._iterate_directories(path, scandir):
188186
yield p
189-
except PermissionError:
190-
return
191187

192188
def _select_from(self, parent_path, scandir):
193-
try:
194-
successor_select = self.successor._select_from
195-
for starting_point in self._iterate_directories(parent_path, scandir):
196-
for p in successor_select(starting_point, scandir):
197-
yield p
198-
except PermissionError:
199-
return
189+
successor_select = self.successor._select_from
190+
for starting_point in self._iterate_directories(parent_path, scandir):
191+
for p in successor_select(starting_point, scandir):
192+
yield p
200193

201194

202195
class _DoubleRecursiveWildcardSelector(_RecursiveWildcardSelector):

Lib/test/test_cmath.py

+5
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ def test_infinity_and_nan_constants(self):
166166
self.assertEqual(cmath.nan.imag, 0.0)
167167
self.assertEqual(cmath.nanj.real, 0.0)
168168
self.assertTrue(math.isnan(cmath.nanj.imag))
169+
# Also check that the sign of all of these is positive:
170+
self.assertEqual(math.copysign(1., cmath.nan.real), 1.)
171+
self.assertEqual(math.copysign(1., cmath.nan.imag), 1.)
172+
self.assertEqual(math.copysign(1., cmath.nanj.real), 1.)
173+
self.assertEqual(math.copysign(1., cmath.nanj.imag), 1.)
169174

170175
# Check consistency with reprs.
171176
self.assertEqual(repr(cmath.inf), "inf")

Lib/test/test_complex.py

+7
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,12 @@ class complex2(complex):
529529
self.assertFloatsAreIdentical(z.real, x)
530530
self.assertFloatsAreIdentical(z.imag, y)
531531

532+
def test_constructor_negative_nans_from_string(self):
533+
self.assertEqual(copysign(1., complex("-nan").real), -1.)
534+
self.assertEqual(copysign(1., complex("-nanj").imag), -1.)
535+
self.assertEqual(copysign(1., complex("-nan-nanj").real), -1.)
536+
self.assertEqual(copysign(1., complex("-nan-nanj").imag), -1.)
537+
532538
def test_underscores(self):
533539
# check underscores
534540
for lit in VALID_UNDERSCORE_LITERALS:
@@ -569,6 +575,7 @@ def test(v, expected, test_fn=self.assertEqual):
569575
test(complex(NAN, 1), "(nan+1j)")
570576
test(complex(1, NAN), "(1+nanj)")
571577
test(complex(NAN, NAN), "(nan+nanj)")
578+
test(complex(-NAN, -NAN), "(nan+nanj)")
572579

573580
test(complex(0, INF), "infj")
574581
test(complex(0, -INF), "-infj")

Lib/test/test_float.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -1040,11 +1040,8 @@ def test_inf_signs(self):
10401040
self.assertEqual(copysign(1.0, float('inf')), 1.0)
10411041
self.assertEqual(copysign(1.0, float('-inf')), -1.0)
10421042

1043-
@unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
1044-
"applies only when using short float repr style")
10451043
def test_nan_signs(self):
1046-
# When using the dtoa.c code, the sign of float('nan') should
1047-
# be predictable.
1044+
# The sign of float('nan') should be predictable.
10481045
self.assertEqual(copysign(1.0, float('nan')), 1.0)
10491046
self.assertEqual(copysign(1.0, float('-nan')), -1.0)
10501047

Lib/test/test_importlib/extension/test_loader.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,16 @@ def test_reload(self):
262262

263263
def test_try_registration(self):
264264
# Assert that the PyState_{Find,Add,Remove}Module C API doesn't work.
265-
module = self.load_module()
266-
with self.subTest('PyState_FindModule'):
267-
self.assertEqual(module.call_state_registration_func(0), None)
268-
with self.subTest('PyState_AddModule'):
269-
with self.assertRaises(SystemError):
270-
module.call_state_registration_func(1)
271-
with self.subTest('PyState_RemoveModule'):
272-
with self.assertRaises(SystemError):
273-
module.call_state_registration_func(2)
265+
with util.uncache(self.name):
266+
module = self.load_module()
267+
with self.subTest('PyState_FindModule'):
268+
self.assertEqual(module.call_state_registration_func(0), None)
269+
with self.subTest('PyState_AddModule'):
270+
with self.assertRaises(SystemError):
271+
module.call_state_registration_func(1)
272+
with self.subTest('PyState_RemoveModule'):
273+
with self.assertRaises(SystemError):
274+
module.call_state_registration_func(2)
274275

275276
def test_load_submodule(self):
276277
# Test loading a simulated submodule.

Lib/test/test_listcomps.py

+10
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ def test_inner_cell_shadows_outer(self):
163163
outputs = {"y": [4, 4, 4, 4, 4], "i": 20}
164164
self._check_in_scopes(code, outputs)
165165

166+
def test_inner_cell_shadows_outer_no_store(self):
167+
code = """
168+
def f(x):
169+
return [lambda: x for x in range(x)], x
170+
fns, x = f(2)
171+
y = [fn() for fn in fns]
172+
"""
173+
outputs = {"y": [1, 1], "x": 2}
174+
self._check_in_scopes(code, outputs)
175+
166176
def test_closure_can_jump_over_comp_scope(self):
167177
code = """
168178
items = [(lambda: y) for i in range(5)]

0 commit comments

Comments
 (0)