Skip to content

Commit ec25382

Browse files
committed
Merge branch 'main' into intern-dataclass-field-names
2 parents ce1ac3e + ef41182 commit ec25382

File tree

416 files changed

+18227
-10375
lines changed

Some content is hidden

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

416 files changed

+18227
-10375
lines changed

.github/workflows/project-updater.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- { project: 32, label: sprint }
2424

2525
steps:
26-
- uses: actions/add-to-project@v0.6.0
26+
- uses: actions/add-to-project@v1.0.0
2727
with:
2828
project-url: https://github.com/orgs/python/projects/${{ matrix.project }}
2929
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}

Doc/c-api/long.rst

Lines changed: 97 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -113,24 +113,28 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
113113
retrieved from the resulting value using :c:func:`PyLong_AsVoidPtr`.
114114
115115
116-
.. c:function:: PyObject* PyLong_FromNativeBytes(const void* buffer, size_t n_bytes, int endianness)
116+
.. c:function:: PyObject* PyLong_FromNativeBytes(const void* buffer, size_t n_bytes, int flags)
117117
118118
Create a Python integer from the value contained in the first *n_bytes* of
119119
*buffer*, interpreted as a two's-complement signed number.
120120
121-
*endianness* may be passed ``-1`` for the native endian that CPython was
122-
compiled with, or else ``0`` for big endian and ``1`` for little.
121+
*flags* are as for :c:func:`PyLong_AsNativeBytes`. Passing ``-1`` will select
122+
the native endian that CPython was compiled with and assume that the
123+
most-significant bit is a sign bit. Passing
124+
``Py_ASNATIVEBYTES_UNSIGNED_BUFFER`` will produce the same result as calling
125+
:c:func:`PyLong_FromUnsignedNativeBytes`. Other flags are ignored.
123126
124127
.. versionadded:: 3.13
125128
126129
127-
.. c:function:: PyObject* PyLong_FromUnsignedNativeBytes(const void* buffer, size_t n_bytes, int endianness)
130+
.. c:function:: PyObject* PyLong_FromUnsignedNativeBytes(const void* buffer, size_t n_bytes, int flags)
128131
129132
Create a Python integer from the value contained in the first *n_bytes* of
130133
*buffer*, interpreted as an unsigned number.
131134
132-
*endianness* may be passed ``-1`` for the native endian that CPython was
133-
compiled with, or else ``0`` for big endian and ``1`` for little.
135+
*flags* are as for :c:func:`PyLong_AsNativeBytes`. Passing ``-1`` will select
136+
the native endian that CPython was compiled with and assume that the
137+
most-significant bit is not a sign bit. Flags other than endian are ignored.
134138
135139
.. versionadded:: 3.13
136140
@@ -354,14 +358,41 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
354358
Returns ``NULL`` on error. Use :c:func:`PyErr_Occurred` to disambiguate.
355359
356360
357-
.. c:function:: Py_ssize_t PyLong_AsNativeBytes(PyObject *pylong, void* buffer, Py_ssize_t n_bytes, int endianness)
361+
.. c:function:: Py_ssize_t PyLong_AsNativeBytes(PyObject *pylong, void* buffer, Py_ssize_t n_bytes, int flags)
358362
359-
Copy the Python integer value to a native *buffer* of size *n_bytes*::
363+
Copy the Python integer value *pylong* to a native *buffer* of size
364+
*n_bytes*. The *flags* can be set to ``-1`` to behave similarly to a C cast,
365+
or to values documented below to control the behavior.
366+
367+
Returns ``-1`` with an exception raised on error. This may happen if
368+
*pylong* cannot be interpreted as an integer, or if *pylong* was negative
369+
and the ``Py_ASNATIVEBYTES_REJECT_NEGATIVE`` flag was set.
370+
371+
Otherwise, returns the number of bytes required to store the value.
372+
If this is equal to or less than *n_bytes*, the entire value was copied.
373+
All *n_bytes* of the buffer are written: large buffers are padded with
374+
zeroes.
375+
376+
If the returned value is greater than than *n_bytes*, the value was
377+
truncated: as many of the lowest bits of the value as could fit are written,
378+
and the higher bits are ignored. This matches the typical behavior
379+
of a C-style downcast.
380+
381+
.. note::
382+
383+
Overflow is not considered an error. If the returned value
384+
is larger than *n_bytes*, most significant bits were discarded.
385+
386+
``0`` will never be returned.
387+
388+
Values are always copied as two's-complement.
389+
390+
Usage example::
360391
361392
int32_t value;
362393
Py_ssize_t bytes = PyLong_AsNativeBits(pylong, &value, sizeof(value), -1);
363394
if (bytes < 0) {
364-
// A Python exception was set with the reason.
395+
// Failed. A Python exception was set with the reason.
365396
return NULL;
366397
}
367398
else if (bytes <= (Py_ssize_t)sizeof(value)) {
@@ -372,19 +403,24 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
372403
// lowest bits of pylong.
373404
}
374405
375-
The above example may look *similar* to
376-
:c:func:`PyLong_As* <PyLong_AsSize_t>`
377-
but instead fills in a specific caller defined type and never raises an
378-
error about of the :class:`int` *pylong*'s value regardless of *n_bytes*
379-
or the returned byte count.
406+
Passing zero to *n_bytes* will return the size of a buffer that would
407+
be large enough to hold the value. This may be larger than technically
408+
necessary, but not unreasonably so.
380409
381-
To get at the entire potentially big Python value, this can be used to
382-
reserve enough space and copy it::
410+
.. note::
411+
412+
Passing *n_bytes=0* to this function is not an accurate way to determine
413+
the bit length of a value.
414+
415+
If *n_bytes=0*, *buffer* may be ``NULL``.
416+
417+
To get at the entire Python value of an unknown size, the function can be
418+
called twice: first to determine the buffer size, then to fill it::
383419
384420
// Ask how much space we need.
385421
Py_ssize_t expected = PyLong_AsNativeBits(pylong, NULL, 0, -1);
386422
if (expected < 0) {
387-
// A Python exception was set with the reason.
423+
// Failed. A Python exception was set with the reason.
388424
return NULL;
389425
}
390426
assert(expected != 0); // Impossible per the API definition.
@@ -395,11 +431,11 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
395431
}
396432
// Safely get the entire value.
397433
Py_ssize_t bytes = PyLong_AsNativeBits(pylong, bignum, expected, -1);
398-
if (bytes < 0) { // Exception set.
434+
if (bytes < 0) { // Exception has been set.
399435
free(bignum);
400436
return NULL;
401437
}
402-
else if (bytes > expected) { // Be safe, should not be possible.
438+
else if (bytes > expected) { // This should not be possible.
403439
PyErr_SetString(PyExc_RuntimeError,
404440
"Unexpected bignum truncation after a size check.");
405441
free(bignum);
@@ -409,35 +445,51 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate.
409445
// ... use bignum ...
410446
free(bignum);
411447
412-
*endianness* may be passed ``-1`` for the native endian that CPython was
413-
compiled with, or ``0`` for big endian and ``1`` for little.
414-
415-
Returns ``-1`` with an exception raised if *pylong* cannot be interpreted as
416-
an integer. Otherwise, return the size of the buffer required to store the
417-
value. If this is equal to or less than *n_bytes*, the entire value was
418-
copied. ``0`` will never be returned.
419-
420-
Unless an exception is raised, all *n_bytes* of the buffer will always be
421-
written. In the case of truncation, as many of the lowest bits of the value
422-
as could fit are written. This allows the caller to ignore all non-negative
423-
results if the intent is to match the typical behavior of a C-style
424-
downcast. No exception is set on truncation.
425-
426-
Values are always copied as two's-complement and sufficient buffer will be
427-
requested to include a sign bit. For example, this may cause an value that
428-
fits into 8 bytes when treated as unsigned to request 9 bytes, even though
429-
all eight bytes were copied into the buffer. What has been omitted is the
430-
zero sign bit -- redundant if the caller's intention is to treat the value
431-
as unsigned.
432-
433-
Passing zero to *n_bytes* will return the size of a buffer that would
434-
be large enough to hold the value. This may be larger than technically
435-
necessary, but not unreasonably so.
448+
*flags* is either ``-1`` (``Py_ASNATIVEBYTES_DEFAULTS``) to select defaults
449+
that behave most like a C cast, or a combintation of the other flags in
450+
the table below.
451+
Note that ``-1`` cannot be combined with other flags.
452+
453+
Currently, ``-1`` corresponds to
454+
``Py_ASNATIVEBYTES_NATIVE_ENDIAN | Py_ASNATIVEBYTES_UNSIGNED_BUFFER``.
455+
456+
============================================= ======
457+
Flag Value
458+
============================================= ======
459+
.. c:macro:: Py_ASNATIVEBYTES_DEFAULTS ``-1``
460+
.. c:macro:: Py_ASNATIVEBYTES_BIG_ENDIAN ``0``
461+
.. c:macro:: Py_ASNATIVEBYTES_LITTLE_ENDIAN ``1``
462+
.. c:macro:: Py_ASNATIVEBYTES_NATIVE_ENDIAN ``3``
463+
.. c:macro:: Py_ASNATIVEBYTES_UNSIGNED_BUFFER ``4``
464+
.. c:macro:: Py_ASNATIVEBYTES_REJECT_NEGATIVE ``8``
465+
============================================= ======
466+
467+
Specifying ``Py_ASNATIVEBYTES_NATIVE_ENDIAN`` will override any other endian
468+
flags. Passing ``2`` is reserved.
469+
470+
By default, sufficient buffer will be requested to include a sign bit.
471+
For example, when converting 128 with *n_bytes=1*, the function will return
472+
2 (or more) in order to store a zero sign bit.
473+
474+
If ``Py_ASNATIVEBYTES_UNSIGNED_BUFFER`` is specified, a zero sign bit
475+
will be omitted from size calculations. This allows, for example, 128 to fit
476+
in a single-byte buffer. If the destination buffer is later treated as
477+
signed, a positive input value may become negative.
478+
Note that the flag does not affect handling of negative values: for those,
479+
space for a sign bit is always requested.
480+
481+
Specifying ``Py_ASNATIVEBYTES_REJECT_NEGATIVE`` causes an exception to be set
482+
if *pylong* is negative. Without this flag, negative values will be copied
483+
provided there is enough space for at least one sign bit, regardless of
484+
whether ``Py_ASNATIVEBYTES_UNSIGNED_BUFFER`` was specified.
436485
437486
.. note::
438487
439-
Passing *n_bytes=0* to this function is not an accurate way to determine
440-
the bit length of a value.
488+
With the default *flags* (``-1``, or *UNSIGNED_BUFFER* without
489+
*REJECT_NEGATIVE*), multiple Python integers can map to a single value
490+
without overflow. For example, both ``255`` and ``-1`` fit a single-byte
491+
buffer and set all its bits.
492+
This matches typical C cast behavior.
441493
442494
.. versionadded:: 3.13
443495

Doc/c-api/unicode.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ APIs:
523523
- Get the fully qualified name of an object type;
524524
call :c:func:`PyType_GetFullyQualifiedName`.
525525
526-
* - ``T#``
526+
* - ``#T``
527527
- :c:expr:`PyObject*`
528528
- Similar to ``T`` format, but use a colon (``:``) as separator between
529529
the module name and the qualified name.
@@ -533,7 +533,7 @@ APIs:
533533
- Get the fully qualified name of a type;
534534
call :c:func:`PyType_GetFullyQualifiedName`.
535535
536-
* - ``N#``
536+
* - ``#N``
537537
- :c:expr:`PyTypeObject*`
538538
- Similar to ``N`` format, but use a colon (``:``) as separator between
539539
the module name and the qualified name.
@@ -574,7 +574,7 @@ APIs:
574574
copied as-is to the result string, and any extra arguments discarded.
575575
576576
.. versionchanged:: 3.13
577-
Support for ``%T``, ``%T#``, ``%N`` and ``%N#`` formats added.
577+
Support for ``%T``, ``%#T``, ``%N`` and ``%#N`` formats added.
578578
579579
580580
.. c:function:: PyObject* PyUnicode_FromFormatV(const char *format, va_list vargs)

Doc/howto/logging-cookbook.rst

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,14 +1915,15 @@ In a similar way to the above section, we can implement a listener and handler
19151915
using `pynng <https://pypi.org/project/pynng/>`_, which is a Python binding to
19161916
`NNG <https://nng.nanomsg.org/>`_, billed as a spiritual successor to ZeroMQ.
19171917
The following snippets illustrate -- you can test them in an environment which has
1918-
``pynng`` installed. Juat for variety, we present the listener first.
1918+
``pynng`` installed. Just for variety, we present the listener first.
19191919

19201920

19211921
Subclass ``QueueListener``
19221922
^^^^^^^^^^^^^^^^^^^^^^^^^^
19231923

19241924
.. code-block:: python
19251925
1926+
# listener.py
19261927
import json
19271928
import logging
19281929
import logging.handlers
@@ -1955,7 +1956,7 @@ Subclass ``QueueListener``
19551956
break
19561957
except pynng.Timeout:
19571958
pass
1958-
except pynng.Closed: # sometimes hit when you hit Ctrl-C
1959+
except pynng.Closed: # sometimes happens when you hit Ctrl-C
19591960
break
19601961
if data is None:
19611962
return None
@@ -1988,6 +1989,7 @@ Subclass ``QueueHandler``
19881989

19891990
.. code-block:: python
19901991
1992+
# sender.py
19911993
import json
19921994
import logging
19931995
import logging.handlers
@@ -2015,9 +2017,10 @@ Subclass ``QueueHandler``
20152017
20162018
logging.getLogger('pynng').propagate = False
20172019
handler = NNGSocketHandler(DEFAULT_ADDR)
2020+
# Make sure the process ID is in the output
20182021
logging.basicConfig(level=logging.DEBUG,
20192022
handlers=[logging.StreamHandler(), handler],
2020-
format='%(levelname)-8s %(name)10s %(message)s')
2023+
format='%(levelname)-8s %(name)10s %(process)6s %(message)s')
20212024
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
20222025
logging.CRITICAL)
20232026
logger_names = ('myapp', 'myapp.lib1', 'myapp.lib2')
@@ -2031,7 +2034,64 @@ Subclass ``QueueHandler``
20312034
delay = random.random() * 2 + 0.5
20322035
time.sleep(delay)
20332036
2034-
You can run the above two snippets in separate command shells.
2037+
You can run the above two snippets in separate command shells. If we run the
2038+
listener in one shell and run the sender in two separate shells, we should see
2039+
something like the following. In the first sender shell:
2040+
2041+
.. code-block:: console
2042+
2043+
$ python sender.py
2044+
DEBUG myapp 613 Message no. 1
2045+
WARNING myapp.lib2 613 Message no. 2
2046+
CRITICAL myapp.lib2 613 Message no. 3
2047+
WARNING myapp.lib2 613 Message no. 4
2048+
CRITICAL myapp.lib1 613 Message no. 5
2049+
DEBUG myapp 613 Message no. 6
2050+
CRITICAL myapp.lib1 613 Message no. 7
2051+
INFO myapp.lib1 613 Message no. 8
2052+
(and so on)
2053+
2054+
In the second sender shell:
2055+
2056+
.. code-block:: console
2057+
2058+
$ python sender.py
2059+
INFO myapp.lib2 657 Message no. 1
2060+
CRITICAL myapp.lib2 657 Message no. 2
2061+
CRITICAL myapp 657 Message no. 3
2062+
CRITICAL myapp.lib1 657 Message no. 4
2063+
INFO myapp.lib1 657 Message no. 5
2064+
WARNING myapp.lib2 657 Message no. 6
2065+
CRITICAL myapp 657 Message no. 7
2066+
DEBUG myapp.lib1 657 Message no. 8
2067+
(and so on)
2068+
2069+
In the listener shell:
2070+
2071+
.. code-block:: console
2072+
2073+
$ python listener.py
2074+
Press Ctrl-C to stop.
2075+
DEBUG myapp 613 Message no. 1
2076+
WARNING myapp.lib2 613 Message no. 2
2077+
INFO myapp.lib2 657 Message no. 1
2078+
CRITICAL myapp.lib2 613 Message no. 3
2079+
CRITICAL myapp.lib2 657 Message no. 2
2080+
CRITICAL myapp 657 Message no. 3
2081+
WARNING myapp.lib2 613 Message no. 4
2082+
CRITICAL myapp.lib1 613 Message no. 5
2083+
CRITICAL myapp.lib1 657 Message no. 4
2084+
INFO myapp.lib1 657 Message no. 5
2085+
DEBUG myapp 613 Message no. 6
2086+
WARNING myapp.lib2 657 Message no. 6
2087+
CRITICAL myapp 657 Message no. 7
2088+
CRITICAL myapp.lib1 613 Message no. 7
2089+
INFO myapp.lib1 613 Message no. 8
2090+
DEBUG myapp.lib1 657 Message no. 8
2091+
(and so on)
2092+
2093+
As you can see, the logging from the two sender processes is interleaved in the
2094+
listener's output.
20352095

20362096

20372097
An example dictionary-based configuration

0 commit comments

Comments
 (0)