Skip to content

Commit 123498f

Browse files
authored
Merge branch 'main' into docs-readline-repl
2 parents cfb2487 + 1481384 commit 123498f

23 files changed

+434
-190
lines changed

Doc/library/asyncio-eventloop.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,12 @@ Opening network connections
611611
to bind the socket locally. The *local_host* and *local_port*
612612
are looked up using :meth:`getaddrinfo`.
613613

614+
.. note::
615+
616+
On Windows, when using the proactor event loop with ``local_addr=None``,
617+
an :exc:`OSError` with :attr:`!errno.WSAEINVAL` will be raised
618+
when running it.
619+
614620
* *remote_addr*, if given, is a ``(remote_host, remote_port)`` tuple used
615621
to connect the socket to a remote address. The *remote_host* and
616622
*remote_port* are looked up using :meth:`getaddrinfo`.

Doc/library/codecs.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,36 @@ to :class:`bytes` mappings. They are not supported by :meth:`bytes.decode`
14831483
Restoration of the aliases for the binary transforms.
14841484

14851485

1486+
.. _standalone-codec-functions:
1487+
1488+
Standalone Codec Functions
1489+
^^^^^^^^^^^^^^^^^^^^^^^^^^
1490+
1491+
The following functions provide encoding and decoding functionality similar to codecs,
1492+
but are not available as named codecs through :func:`codecs.encode` or :func:`codecs.decode`.
1493+
They are used internally (for example, by :mod:`pickle`) and behave similarly to the
1494+
``string_escape`` codec that was removed in Python 3.
1495+
1496+
.. function:: codecs.escape_encode(input, errors=None)
1497+
1498+
Encode *input* using escape sequences. Similar to how :func:`repr` on bytes
1499+
produces escaped byte values.
1500+
1501+
*input* must be a :class:`bytes` object.
1502+
1503+
Returns a tuple ``(output, length)`` where *output* is a :class:`bytes`
1504+
object and *length* is the number of bytes consumed.
1505+
1506+
.. function:: codecs.escape_decode(input, errors=None)
1507+
1508+
Decode *input* from escape sequences back to the original bytes.
1509+
1510+
*input* must be a :term:`bytes-like object`.
1511+
1512+
Returns a tuple ``(output, length)`` where *output* is a :class:`bytes`
1513+
object and *length* is the number of bytes consumed.
1514+
1515+
14861516
.. _text-transforms:
14871517

14881518
Text Transforms

Doc/library/concurrent.futures.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,11 @@ that :class:`ProcessPoolExecutor` will not work in the interactive interpreter.
342342
Calling :class:`Executor` or :class:`Future` methods from a callable submitted
343343
to a :class:`ProcessPoolExecutor` will result in deadlock.
344344

345+
Note that the restrictions on functions and arguments needing to picklable as
346+
per :class:`multiprocessing.Process` apply when using :meth:`~Executor.submit`
347+
and :meth:`~Executor.map` on a :class:`ProcessPoolExecutor`. A function defined
348+
in a REPL or a lambda should not be expected to work.
349+
345350
.. class:: ProcessPoolExecutor(max_workers=None, mp_context=None, initializer=None, initargs=(), max_tasks_per_child=None)
346351

347352
An :class:`Executor` subclass that executes calls asynchronously using a pool

Doc/library/multiprocessing.rst

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ To show the individual process IDs involved, here is an expanded example::
9797
For an explanation of why the ``if __name__ == '__main__'`` part is
9898
necessary, see :ref:`multiprocessing-programming`.
9999

100+
The arguments to :class:`Process` usually need to be unpickleable from within
101+
the child process. If you tried typing the above example directly into a REPL it
102+
could lead to an :exc:`AttributeError` in the child process trying to locate the
103+
*f* function in the ``__main__`` module.
100104

101105

102106
.. _multiprocessing-start-methods:
@@ -233,9 +237,12 @@ processes for a different context. In particular, locks created using
233237
the *fork* context cannot be passed to processes started using the
234238
*spawn* or *forkserver* start methods.
235239

236-
A library which wants to use a particular start method should probably
237-
use :func:`get_context` to avoid interfering with the choice of the
238-
library user.
240+
Libraries using :mod:`multiprocessing` or
241+
:class:`~concurrent.futures.ProcessPoolExecutor` should be designed to allow
242+
their users to provide their own multiprocessing context. Using a specific
243+
context of your own within a library can lead to incompatibilities with the
244+
rest of the library user's application. Always document if your library
245+
requires a specific start method.
239246

240247
.. warning::
241248

@@ -538,9 +545,42 @@ The :mod:`multiprocessing` package mostly replicates the API of the
538545
to pass to *target*.
539546

540547
If a subclass overrides the constructor, it must make sure it invokes the
541-
base class constructor (:meth:`Process.__init__`) before doing anything else
548+
base class constructor (``super().__init__()``) before doing anything else
542549
to the process.
543550

551+
.. note::
552+
553+
In general, all arguments to :class:`Process` must be picklable. This is
554+
frequently observed when trying to create a :class:`Process` or use a
555+
:class:`concurrent.futures.ProcessPoolExecutor` from a REPL with a
556+
locally defined *target* function.
557+
558+
Passing a callable object defined in the current REPL session causes the
559+
child process to die via an uncaught :exc:`AttributeError` exception when
560+
starting as *target* must have been defined within an importable module
561+
in order to be loaded during unpickling.
562+
563+
Example of this uncatchable error from the child::
564+
565+
>>> import multiprocessing as mp
566+
>>> def knigit():
567+
... print("Ni!")
568+
...
569+
>>> process = mp.Process(target=knigit)
570+
>>> process.start()
571+
>>> Traceback (most recent call last):
572+
File ".../multiprocessing/spawn.py", line ..., in spawn_main
573+
File ".../multiprocessing/spawn.py", line ..., in _main
574+
AttributeError: module '__main__' has no attribute 'knigit'
575+
>>> process
576+
<SpawnProcess name='SpawnProcess-1' pid=379473 parent=378707 stopped exitcode=1>
577+
578+
See :ref:`multiprocessing-programming-spawn`. While this restriction is
579+
not true if using the ``"fork"`` start method, as of Python ``3.14`` that
580+
is no longer the default on any platform. See
581+
:ref:`multiprocessing-start-methods`.
582+
See also :gh:`132898`.
583+
544584
.. versionchanged:: 3.3
545585
Added the *daemon* parameter.
546586

@@ -3070,10 +3110,10 @@ start method.
30703110

30713111
More picklability
30723112

3073-
Ensure that all arguments to :meth:`Process.__init__` are picklable.
3074-
Also, if you subclass :class:`~multiprocessing.Process` then make sure that
3075-
instances will be picklable when the :meth:`Process.start
3076-
<multiprocessing.Process.start>` method is called.
3113+
Ensure that all arguments to :class:`~multiprocessing.Process` are
3114+
picklable. Also, if you subclass ``Process.__init__``, you must make sure
3115+
that instances will be picklable when the
3116+
:meth:`Process.start <multiprocessing.Process.start>` method is called.
30773117

30783118
Global variables
30793119

Makefile.pre.in

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ ENSUREPIP= @ENSUREPIP@
227227
# Internal static libraries
228228
LIBMPDEC_A= Modules/_decimal/libmpdec/libmpdec.a
229229
LIBEXPAT_A= Modules/expat/libexpat.a
230+
LIBHASHLIB_INTERNAL_A=Modules/_hashlib/libhashlib.a
230231

231232
# HACL* build configuration
232233
LIBHACL_CFLAGS=@LIBHACL_CFLAGS@
@@ -761,6 +762,17 @@ LIBHACL_HMAC_HEADERS= \
761762
$(LIBHACL_BLAKE2_HEADERS) \
762763
$(LIBHACL_HEADERS)
763764

765+
##########################################################################
766+
# Internal library for cryptographic primitives
767+
768+
LIBHASHLIB_INTERNAL_OBJS= \
769+
Modules/_hashlib/hashlib_buffer.o
770+
771+
LIBHASHLIB_INTERNAL_HEADERS= \
772+
Modules/_hashlib/hashlib_buffer.h \
773+
Modules/_hashlib/hashlib_fetch.h \
774+
Modules/_hashlib/hashlib_mutex.h
775+
764776
#########################################################################
765777
# Rules
766778

@@ -1511,6 +1523,17 @@ $(LIBEXPAT_A): $(LIBEXPAT_OBJS)
15111523
-rm -f $@
15121524
$(AR) $(ARFLAGS) $@ $(LIBEXPAT_OBJS)
15131525

1526+
##########################################################################
1527+
# '_hashlib', '_hmac' and HACL*-based modules helpers
1528+
LIBHASHLIB_INTERNAL_CFLAGS=@LIBHASHLIB_INTERNAL_CFLAGS@ $(PY_STDMODULE_CFLAGS) $(CCSHARED)
1529+
1530+
Modules/_hashlib/hashlib_buffer.o: Modules/_hashlib/hashlib_buffer.c $(LIBHASHLIB_INTERNAL_HEADERS) $(PYTHON_HEADERS)
1531+
$(CC) -I$(srcdir)/Modules/_hashlib -c $(LIBHASHLIB_INTERNAL_CFLAGS) -o $@ $(srcdir)/Modules/_hashlib/hashlib_buffer.c
1532+
1533+
$(LIBHASHLIB_INTERNAL_A): $(LIBHASHLIB_INTERNAL_OBJS)
1534+
-rm -f $@
1535+
$(AR) $(ARFLAGS) $@ $(LIBHASHLIB_INTERNAL_OBJS)
1536+
15141537
##########################################################################
15151538
# HACL* library build
15161539
#
@@ -3353,21 +3376,21 @@ MODULE__CTYPES_TEST_DEPS=$(srcdir)/Modules/_ctypes/_ctypes_test_generated.c.h
33533376
MODULE__CTYPES_MALLOC_CLOSURE=@MODULE__CTYPES_MALLOC_CLOSURE@
33543377
MODULE__DECIMAL_DEPS=$(srcdir)/Modules/_decimal/docstrings.h @LIBMPDEC_INTERNAL@
33553378
MODULE__ELEMENTTREE_DEPS=$(srcdir)/Modules/pyexpat.c @LIBEXPAT_INTERNAL@
3356-
MODULE__HASHLIB_DEPS=$(srcdir)/Modules/hashlib.h
3379+
MODULE__HASHLIB_DEPS=@LIBHASHLIB_INTERNAL@
33573380
MODULE__IO_DEPS=$(srcdir)/Modules/_io/_iomodule.h
33583381

33593382
# HACL*-based cryptographic primitives
3360-
MODULE__MD5_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_MD5_HEADERS) $(LIBHACL_MD5_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3383+
MODULE__MD5_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_MD5_HEADERS) $(LIBHACL_MD5_LIB_@LIBHACL_LDEPS_LIBTYPE@)
33613384
MODULE__MD5_LDEPS=$(LIBHACL_MD5_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3362-
MODULE__SHA1_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA1_HEADERS) $(LIBHACL_SHA1_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3385+
MODULE__SHA1_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_SHA1_HEADERS) $(LIBHACL_SHA1_LIB_@LIBHACL_LDEPS_LIBTYPE@)
33633386
MODULE__SHA1_LDEPS=$(LIBHACL_SHA1_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3364-
MODULE__SHA2_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA2_HEADERS) $(LIBHACL_SHA2_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3387+
MODULE__SHA2_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_SHA2_HEADERS) $(LIBHACL_SHA2_LIB_@LIBHACL_LDEPS_LIBTYPE@)
33653388
MODULE__SHA2_LDEPS=$(LIBHACL_SHA2_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3366-
MODULE__SHA3_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_SHA3_HEADERS) $(LIBHACL_SHA3_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3389+
MODULE__SHA3_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_SHA3_HEADERS) $(LIBHACL_SHA3_LIB_@LIBHACL_LDEPS_LIBTYPE@)
33673390
MODULE__SHA3_LDEPS=$(LIBHACL_SHA3_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3368-
MODULE__BLAKE2_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_BLAKE2_HEADERS) $(LIBHACL_BLAKE2_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3391+
MODULE__BLAKE2_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_BLAKE2_HEADERS) $(LIBHACL_BLAKE2_LIB_@LIBHACL_LDEPS_LIBTYPE@)
33693392
MODULE__BLAKE2_LDEPS=$(LIBHACL_BLAKE2_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3370-
MODULE__HMAC_DEPS=$(srcdir)/Modules/hashlib.h $(LIBHACL_HMAC_HEADERS) $(LIBHACL_HMAC_LIB_@LIBHACL_LDEPS_LIBTYPE@)
3393+
MODULE__HMAC_DEPS=$(MODULE__HASHLIB_DEPS) $(LIBHACL_HMAC_HEADERS) $(LIBHACL_HMAC_LIB_@LIBHACL_LDEPS_LIBTYPE@)
33713394
MODULE__HMAC_LDEPS=$(LIBHACL_HMAC_LIB_@LIBHACL_LDEPS_LIBTYPE@)
33723395

33733396
MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h $(srcdir)/Modules/addrinfo.h $(srcdir)/Modules/getaddrinfo.c $(srcdir)/Modules/getnameinfo.c
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Remove :file:`!Modules/hashlib.h` and move its content into dedicated files
2+
now located in ``Modules/_hashlib``. Patch by Bénédikt Tran.

Modules/_hashlib/hashlib_buffer.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include "hashlib_buffer.h"
2+
3+
int
4+
_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string)
5+
{
6+
if (data != NULL && string == NULL) {
7+
// called as H(data) or H(data=...)
8+
*res = data;
9+
return 1;
10+
}
11+
else if (data == NULL && string != NULL) {
12+
// called as H(string=...)
13+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
14+
"the 'string' keyword parameter is deprecated since "
15+
"Python 3.15 and slated for removal in Python 3.19; "
16+
"use the 'data' keyword parameter or pass the data "
17+
"to hash as a positional argument instead", 1) < 0)
18+
{
19+
*res = NULL;
20+
return -1;
21+
}
22+
*res = string;
23+
return 1;
24+
}
25+
else if (data == NULL && string == NULL) {
26+
// fast path when no data is given
27+
assert(!PyErr_Occurred());
28+
*res = NULL;
29+
return 0;
30+
}
31+
else {
32+
// called as H(data=..., string)
33+
*res = NULL;
34+
PyErr_SetString(PyExc_TypeError,
35+
"'data' and 'string' are mutually exclusive "
36+
"and support for 'string' keyword parameter "
37+
"is slated for removal in a future version.");
38+
return -1;
39+
}
40+
}
41+
42+
int
43+
_Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view)
44+
{
45+
if (PyUnicode_Check(obj)) {
46+
PyErr_SetString(PyExc_TypeError,
47+
"Strings must be encoded before hashing");
48+
return -1;
49+
}
50+
if (!PyObject_CheckBuffer(obj)) {
51+
PyErr_SetString(PyExc_TypeError,
52+
"object supporting the buffer API required");
53+
return -1;
54+
}
55+
if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) {
56+
return -1;
57+
}
58+
if (view->ndim > 1) {
59+
PyErr_SetString(PyExc_BufferError,
60+
"Buffer must be single dimension");
61+
PyBuffer_Release(view);
62+
return -1;
63+
}
64+
return 0;
65+
}

Modules/_hashlib/hashlib_buffer.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef _HASHLIB_HASHLIB_BUFFER_H
2+
#define _HASHLIB_HASHLIB_BUFFER_H
3+
4+
#include "Python.h"
5+
6+
/*
7+
* Allow to use the 'data' or 'string' keyword in hashlib.new()
8+
* and other hash functions named constructors.
9+
*
10+
* - If 'data' and 'string' are both non-NULL, set an exception and return -1.
11+
* - If 'data' and 'string' are both NULL, set '*res' to NULL and return 0.
12+
* - Otherwise, set '*res' to 'data' or 'string' and return 1. A deprecation
13+
* warning is set when 'string' is specified.
14+
*
15+
* The symbol is exported for '_hashlib' and HACL*-based extension modules.
16+
*/
17+
PyAPI_FUNC(int)
18+
_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string);
19+
20+
/*
21+
* Obtain a buffer view from a buffer-like object 'obj'.
22+
*
23+
* On success, store the result in 'view' and return 0.
24+
* On error, set an exception and return -1.
25+
*
26+
* The symbol is exported for '_hashlib' and HACL*-based extension modules.
27+
*/
28+
PyAPI_FUNC(int)
29+
_Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view);
30+
31+
/*
32+
* Call _Py_hashlib_get_buffer_view() and check if it succeeded.
33+
*
34+
* On error, set an exception and execute the ERRACTION statements.
35+
*/
36+
#define GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, ERRACTION) \
37+
do { \
38+
if (_Py_hashlib_get_buffer_view(OBJ, VIEW) < 0) { \
39+
assert(PyErr_Occurred()); \
40+
ERRACTION; \
41+
} \
42+
} while (0)
43+
44+
/* Specialization of GET_BUFFER_VIEW_OR_ERROR() returning NULL on error. */
45+
#define GET_BUFFER_VIEW_OR_ERROUT(OBJ, VIEW) \
46+
GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, return NULL)
47+
48+
#endif // !_HASHLIB_HASHLIB_BUFFER_H

Modules/_hashlib/hashlib_fetch.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Utilities used when fetching a message digest from a digest-like identifier.
3+
*/
4+
5+
#ifndef _HASHLIB_HASHLIB_FETCH_H
6+
#define _HASHLIB_HASHLIB_FETCH_H
7+
8+
#include "Python.h"
9+
10+
/*
11+
* Internal error messages used for reporting an unsupported hash algorithm.
12+
* The algorithm can be given by its name, a callable or a PEP-247 module.
13+
* The same message is raised by Lib/hashlib.py::__get_builtin_constructor()
14+
* and _hmacmodule.c::find_hash_info().
15+
*/
16+
#define _Py_HASHLIB_UNSUPPORTED_ALGORITHM "unsupported hash algorithm %S"
17+
#define _Py_HASHLIB_UNSUPPORTED_STR_ALGORITHM "unsupported hash algorithm %s"
18+
19+
#endif // !_HASHLIB_HASHLIB_FETCH_H

0 commit comments

Comments
 (0)