Skip to content

Commit e778c67

Browse files
committed
Merge branch 'master' into fstring-error-message
2 parents d50dad0 + f9bd05e commit e778c67

Some content is hidden

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

61 files changed

+950
-693
lines changed

Doc/glossary.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ Glossary
189189
A list of bytecode instructions can be found in the documentation for
190190
:ref:`the dis module <bytecodes>`.
191191

192+
callback
193+
A subroutine function which is passed as an argument to be executed at
194+
some point in the future.
195+
192196
class
193197
A template for creating user-defined objects. Class definitions
194198
normally contain method definitions which operate on instances of the

Doc/library/asyncio-dev.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ event loop, no other Tasks can run in the same thread. When a Task
7373
executes an ``await`` expression, the running Task gets suspended, and
7474
the event loop executes the next Task.
7575

76-
To schedule a callback from a different OS thread, the
76+
To schedule a :term:`callback` from another OS thread, the
7777
:meth:`loop.call_soon_threadsafe` method should be used. Example::
7878

7979
loop.call_soon_threadsafe(callback, *args)

Doc/library/asyncio-eventloop.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ Scheduling callbacks
191191

192192
.. method:: loop.call_soon(callback, *args, context=None)
193193

194-
Schedule a *callback* to be called with *args* arguments at
195-
the next iteration of the event loop.
194+
Schedule the *callback* :term:`callback` to be called with
195+
*args* arguments at the next iteration of the event loop.
196196

197197
Callbacks are called in the order in which they are registered.
198198
Each callback will be called exactly once.

Include/cpython/listobject.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,3 @@ PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out);
3232
#define PyList_GET_ITEM(op, i) (_PyList_CAST(op)->ob_item[i])
3333
#define PyList_SET_ITEM(op, i, v) (_PyList_CAST(op)->ob_item[i] = (v))
3434
#define PyList_GET_SIZE(op) Py_SIZE(_PyList_CAST(op))
35-
#define _PyList_ITEMS(op) (_PyList_CAST(op)->ob_item)

Include/internal/pycore_gc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ extern void _PyFrame_ClearFreeList(PyThreadState *tstate);
169169
extern void _PyTuple_ClearFreeList(PyThreadState *tstate);
170170
extern void _PyFloat_ClearFreeList(PyThreadState *tstate);
171171
extern void _PyList_ClearFreeList(PyThreadState *tstate);
172-
extern void _PyDict_ClearFreeList(void);
172+
extern void _PyDict_ClearFreeList(PyThreadState *tstate);
173173
extern void _PyAsyncGen_ClearFreeLists(PyThreadState *tstate);
174174
extern void _PyContext_ClearFreeList(PyThreadState *tstate);
175175

Include/internal/pycore_interp.h

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,23 @@ struct _Py_unicode_fs_codec {
6565
_Py_error_handler error_handler;
6666
};
6767

68+
struct _Py_bytes_state {
69+
PyBytesObject *characters[256];
70+
PyBytesObject *empty_string;
71+
};
72+
6873
struct _Py_unicode_state {
6974
struct _Py_unicode_fs_codec fs_codec;
7075
};
7176

77+
struct _Py_float_state {
78+
/* Special free list
79+
free_list is a singly-linked list of available PyFloatObjects,
80+
linked via abuse of their ob_type members. */
81+
int numfree;
82+
PyFloatObject *free_list;
83+
};
84+
7285
/* Speed optimization to avoid frequent malloc/free of small tuples */
7386
#ifndef PyTuple_MAXSAVESIZE
7487
// Largest tuple to save on free list
@@ -99,12 +112,16 @@ struct _Py_list_state {
99112
int numfree;
100113
};
101114

102-
struct _Py_float_state {
103-
/* Special free list
104-
free_list is a singly-linked list of available PyFloatObjects,
105-
linked via abuse of their ob_type members. */
115+
#ifndef PyDict_MAXFREELIST
116+
# define PyDict_MAXFREELIST 80
117+
#endif
118+
119+
struct _Py_dict_state {
120+
/* Dictionary reuse scheme to save calls to malloc and free */
121+
PyDictObject *free_list[PyDict_MAXFREELIST];
106122
int numfree;
107-
PyFloatObject *free_list;
123+
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
124+
int keys_numfree;
108125
};
109126

110127
struct _Py_frame_state {
@@ -136,7 +153,6 @@ struct _Py_context_state {
136153
};
137154

138155

139-
140156
/* interpreter state */
141157

142158
#define _PY_NSMALLPOSINTS 257
@@ -182,8 +198,6 @@ struct _is {
182198
PyObject *codec_error_registry;
183199
int codecs_initialized;
184200

185-
struct _Py_unicode_state unicode;
186-
187201
PyConfig config;
188202
#ifdef HAVE_DLOPEN
189203
int dlopenflags;
@@ -224,16 +238,19 @@ struct _is {
224238
*/
225239
PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
226240
#endif
241+
struct _Py_bytes_state bytes;
242+
struct _Py_unicode_state unicode;
243+
struct _Py_float_state float_state;
244+
/* Using a cache is very effective since typically only a single slice is
245+
created and then deleted again. */
246+
PySliceObject *slice_cache;
247+
227248
struct _Py_tuple_state tuple;
228249
struct _Py_list_state list;
229-
struct _Py_float_state float_state;
250+
struct _Py_dict_state dict_state;
230251
struct _Py_frame_state frame;
231252
struct _Py_async_gen_state async_gen;
232253
struct _Py_context_state context;
233-
234-
/* Using a cache is very effective since typically only a single slice is
235-
created and then deleted again. */
236-
PySliceObject *slice_cache;
237254
};
238255

239256
/* Used by _PyImport_Cleanup() */

Include/internal/pycore_list.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef Py_INTERNAL_LIST_H
2+
#define Py_INTERNAL_LIST_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
#ifndef Py_BUILD_CORE
8+
# error "this header requires Py_BUILD_CORE define"
9+
#endif
10+
11+
#include "listobject.h" // _PyList_CAST()
12+
13+
14+
#define _PyList_ITEMS(op) (_PyList_CAST(op)->ob_item)
15+
16+
17+
#ifdef __cplusplus
18+
}
19+
#endif
20+
#endif /* !Py_INTERNAL_LIST_H */

Include/internal/pycore_pylifecycle.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,10 @@ extern PyStatus _PyGC_Init(PyThreadState *tstate);
5959
/* Various internal finalizers */
6060

6161
extern void _PyFrame_Fini(PyThreadState *tstate);
62-
extern void _PyDict_Fini(void);
62+
extern void _PyDict_Fini(PyThreadState *tstate);
6363
extern void _PyTuple_Fini(PyThreadState *tstate);
6464
extern void _PyList_Fini(PyThreadState *tstate);
65-
extern void _PySet_Fini(void);
66-
extern void _PyBytes_Fini(void);
65+
extern void _PyBytes_Fini(PyThreadState *tstate);
6766
extern void _PyFloat_Fini(PyThreadState *tstate);
6867
extern void _PySlice_Fini(PyThreadState *tstate);
6968
extern void _PyAsyncGen_Fini(PyThreadState *tstate);

Include/internal/pycore_tupleobject.h renamed to Include/internal/pycore_tuple.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef Py_INTERNAL_TUPLEOBJECT_H
2-
#define Py_INTERNAL_TUPLEOBJECT_H
1+
#ifndef Py_INTERNAL_TUPLE_H
2+
#define Py_INTERNAL_TUPLE_H
33
#ifdef __cplusplus
44
extern "C" {
55
#endif
@@ -11,9 +11,10 @@ extern "C" {
1111
#include "tupleobject.h" /* _PyTuple_CAST() */
1212

1313
#define _PyTuple_ITEMS(op) (_PyTuple_CAST(op)->ob_item)
14+
1415
PyAPI_FUNC(PyObject *) _PyTuple_FromArray(PyObject *const *, Py_ssize_t);
1516

1617
#ifdef __cplusplus
1718
}
1819
#endif
19-
#endif /* !Py_INTERNAL_TUPLEOBJECT_H */
20+
#endif /* !Py_INTERNAL_TUPLE_H */

Lib/random.py

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939

4040
from warnings import warn as _warn
4141
from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
42-
from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin, tau as TWOPI
42+
from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
43+
from math import tau as TWOPI, floor as _floor
4344
from os import urandom as _urandom
4445
from _collections_abc import Set as _Set, Sequence as _Sequence
4546
from itertools import accumulate as _accumulate, repeat as _repeat
@@ -234,7 +235,7 @@ def __reduce__(self):
234235

235236
## -------------------- integer methods -------------------
236237

237-
def randrange(self, start, stop=None, step=1, _int=int):
238+
def randrange(self, start, stop=None, step=1):
238239
"""Choose a random item from range(start, stop[, step]).
239240
240241
This fixes the problem with randint() which includes the
@@ -244,7 +245,7 @@ def randrange(self, start, stop=None, step=1, _int=int):
244245

245246
# This code is a bit messy to make it fast for the
246247
# common case while still doing adequate error checking.
247-
istart = _int(start)
248+
istart = int(start)
248249
if istart != start:
249250
raise ValueError("non-integer arg 1 for randrange()")
250251
if stop is None:
@@ -253,7 +254,7 @@ def randrange(self, start, stop=None, step=1, _int=int):
253254
raise ValueError("empty range for randrange()")
254255

255256
# stop argument supplied.
256-
istop = _int(stop)
257+
istop = int(stop)
257258
if istop != stop:
258259
raise ValueError("non-integer stop for randrange()")
259260
width = istop - istart
@@ -263,7 +264,7 @@ def randrange(self, start, stop=None, step=1, _int=int):
263264
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
264265

265266
# Non-unit step argument supplied.
266-
istep = _int(step)
267+
istep = int(step)
267268
if istep != step:
268269
raise ValueError("non-integer step for randrange()")
269270
if istep > 0:
@@ -296,7 +297,7 @@ def _randbelow_with_getrandbits(self, n):
296297
r = getrandbits(k)
297298
return r
298299

299-
def _randbelow_without_getrandbits(self, n, int=int, maxsize=1<<BPF):
300+
def _randbelow_without_getrandbits(self, n, maxsize=1<<BPF):
300301
"""Return a random int in the range [0,n). Returns 0 if n==0.
301302
302303
The implementation does not use getrandbits, but only random.
@@ -307,15 +308,15 @@ def _randbelow_without_getrandbits(self, n, int=int, maxsize=1<<BPF):
307308
_warn("Underlying random() generator does not supply \n"
308309
"enough bits to choose from a population range this large.\n"
309310
"To remove the range limitation, add a getrandbits() method.")
310-
return int(random() * n)
311+
return _floor(random() * n)
311312
if n == 0:
312313
return 0
313314
rem = maxsize % n
314315
limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0
315316
r = random()
316317
while r >= limit:
317318
r = random()
318-
return int(r * maxsize) % n
319+
return _floor(r * maxsize) % n
319320

320321
_randbelow = _randbelow_with_getrandbits
321322

@@ -346,10 +347,10 @@ def shuffle(self, x, random=None):
346347
'since Python 3.9 and will be removed in a subsequent '
347348
'version.',
348349
DeprecationWarning, 2)
349-
_int = int
350+
floor = _floor
350351
for i in reversed(range(1, len(x))):
351352
# pick an element in x[:i+1] with which to exchange x[i]
352-
j = _int(random() * (i + 1))
353+
j = floor(random() * (i + 1))
353354
x[i], x[j] = x[j], x[i]
354355

355356
def sample(self, population, k, *, counts=None):
@@ -462,9 +463,9 @@ def choices(self, population, weights=None, *, cum_weights=None, k=1):
462463
n = len(population)
463464
if cum_weights is None:
464465
if weights is None:
465-
_int = int
466+
floor = _floor
466467
n += 0.0 # convert to float for a small speed improvement
467-
return [population[_int(random() * n)] for i in _repeat(None, k)]
468+
return [population[floor(random() * n)] for i in _repeat(None, k)]
468469
cum_weights = list(_accumulate(weights))
469470
elif weights is not None:
470471
raise TypeError('Cannot specify both weights and cumulative weights')
@@ -814,24 +815,20 @@ def _notimplemented(self, *args, **kwds):
814815
## -------------------- test program --------------------
815816

816817
def _test_generator(n, func, args):
817-
import time
818-
print(n, 'times', func.__name__)
819-
total = 0.0
820-
sqsum = 0.0
821-
smallest = 1e10
822-
largest = -1e10
823-
t0 = time.perf_counter()
824-
for i in range(n):
825-
x = func(*args)
826-
total += x
827-
sqsum = sqsum + x*x
828-
smallest = min(x, smallest)
829-
largest = max(x, largest)
830-
t1 = time.perf_counter()
831-
print(round(t1 - t0, 3), 'sec,', end=' ')
832-
avg = total / n
833-
stddev = _sqrt(sqsum / n - avg * avg)
834-
print('avg %g, stddev %g, min %g, max %g\n' % (avg, stddev, smallest, largest))
818+
from statistics import stdev, fmean as mean
819+
from time import perf_counter
820+
821+
t0 = perf_counter()
822+
data = [func(*args) for i in range(n)]
823+
t1 = perf_counter()
824+
825+
xbar = mean(data)
826+
sigma = stdev(data, xbar)
827+
low = min(data)
828+
high = max(data)
829+
830+
print(f'{t1 - t0:.3f} sec, {n} times {func.__name__}')
831+
print('avg %g, stddev %g, min %g, max %g\n' % (xbar, sigma, low, high))
835832

836833

837834
def _test(N=2000):

Lib/test/test_marshal.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,6 @@ def test_sets(self):
158158
for constructor in (set, frozenset):
159159
self.helper(constructor(self.d.keys()))
160160

161-
@support.cpython_only
162-
def test_empty_frozenset_singleton(self):
163-
# marshal.loads() must reuse the empty frozenset singleton
164-
obj = frozenset()
165-
obj2 = marshal.loads(marshal.dumps(obj))
166-
self.assertIs(obj2, obj)
167-
168161

169162
class BufferTestCase(unittest.TestCase, HelperMixin):
170163

Lib/test/test_set.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -661,15 +661,6 @@ def test_init(self):
661661
s.__init__(self.otherword)
662662
self.assertEqual(s, set(self.word))
663663

664-
def test_singleton_empty_frozenset(self):
665-
f = frozenset()
666-
efs = [frozenset(), frozenset([]), frozenset(()), frozenset(''),
667-
frozenset(), frozenset([]), frozenset(()), frozenset(''),
668-
frozenset(range(0)), frozenset(frozenset()),
669-
frozenset(f), f]
670-
# All of the empty frozensets should have just one id()
671-
self.assertEqual(len(set(map(id, efs))), 1)
672-
673664
def test_constructor_identity(self):
674665
s = self.thetype(range(3))
675666
t = self.thetype(s)

Lib/zoneinfo/_common.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,7 @@ class _TZifHeader:
136136
]
137137

138138
def __init__(self, *args):
139-
assert len(self.__slots__) == len(args)
140-
for attr, val in zip(self.__slots__, args):
139+
for attr, val in zip(self.__slots__, args, strict=True):
141140
setattr(self, attr, val)
142141

143142
@classmethod

Makefile.pre.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,7 @@ PYTHON_HEADERS= \
11101110
$(srcdir)/Include/internal/pycore_import.h \
11111111
$(srcdir)/Include/internal/pycore_initconfig.h \
11121112
$(srcdir)/Include/internal/pycore_interp.h \
1113+
$(srcdir)/Include/internal/pycore_list.h \
11131114
$(srcdir)/Include/internal/pycore_object.h \
11141115
$(srcdir)/Include/internal/pycore_pathconfig.h \
11151116
$(srcdir)/Include/internal/pycore_pyerrors.h \
@@ -1120,7 +1121,7 @@ PYTHON_HEADERS= \
11201121
$(srcdir)/Include/internal/pycore_runtime.h \
11211122
$(srcdir)/Include/internal/pycore_sysmodule.h \
11221123
$(srcdir)/Include/internal/pycore_traceback.h \
1123-
$(srcdir)/Include/internal/pycore_tupleobject.h \
1124+
$(srcdir)/Include/internal/pycore_tuple.h \
11241125
$(srcdir)/Include/internal/pycore_warnings.h \
11251126
$(DTRACE_HEADERS)
11261127

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Port :mod:`_lzma` to multiphase initialization.
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
The tuple free lists, the empty tuple singleton, the list free list, the float
2-
free list, the slice cache, the frame free list, the asynchronous generator
3-
free lists, and the context free list are no longer shared by all interpreters:
4-
each interpreter now its has own free lists and caches.
1+
Each interpreter now its has own free lists, singletons and caches:
2+
3+
* Free lists: float, tuple, list, dict, frame, context,
4+
asynchronous generator.
5+
* Singletons: empty tuple, empty bytes string,
6+
single byte character.
7+
* Slice cache.
8+
9+
They are no longer shared by all interpreters.
10+

0 commit comments

Comments
 (0)