Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 17f1f32

Browse files
committed
Merge remote-tracking branch 'upstream/main' into asyncio-queue-shutdown
2 parents 2c6156f + 8945b7f commit 17f1f32

89 files changed

Lines changed: 1268 additions & 473 deletions

File tree

Some content is hidden

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

Doc/c-api/bytes.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,10 @@ called with a non-bytes parameter.
191191
192192
.. c:function:: int _PyBytes_Resize(PyObject **bytes, Py_ssize_t newsize)
193193
194-
A way to resize a bytes object even though it is "immutable". Only use this
195-
to build up a brand new bytes object; don't use this if the bytes may already
196-
be known in other parts of the code. It is an error to call this function if
197-
the refcount on the input bytes object is not one. Pass the address of an
194+
Resize a bytes object. *newsize* will be the new length of the bytes object.
195+
You can think of it as creating a new bytes object and destroying the old
196+
one, only more efficiently.
197+
Pass the address of an
198198
existing bytes object as an lvalue (it may be written into), and the new size
199199
desired. On success, *\*bytes* holds the resized bytes object and ``0`` is
200200
returned; the address in *\*bytes* may differ from its input value. If the

Doc/c-api/hash.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,14 @@ See also the :c:member:`PyTypeObject.tp_hash` member and :ref:`numeric-hash`.
8282
The function cannot fail: it cannot return ``-1``.
8383
8484
.. versionadded:: 3.13
85+
86+
.. c:function:: Py_hash_t PyObject_GenericHash(PyObject *obj)
87+
88+
Generic hashing function that is meant to be put into a type
89+
object's ``tp_hash`` slot.
90+
Its result only depends on the object's identity.
91+
92+
.. impl-detail::
93+
In CPython, it is equivalent to :c:func:`Py_HashPointer`.
94+
95+
.. versionadded:: 3.13

Doc/c-api/typeobj.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,10 @@ and :c:data:`PyType_Type` effectively act as defaults.)
883883
:c:member:`~PyTypeObject.tp_richcompare` and :c:member:`~PyTypeObject.tp_hash`, when the subtype's
884884
:c:member:`~PyTypeObject.tp_richcompare` and :c:member:`~PyTypeObject.tp_hash` are both ``NULL``.
885885

886+
**Default:**
887+
888+
:c:data:`PyBaseObject_Type` uses :c:func:`PyObject_GenericHash`.
889+
886890

887891
.. c:member:: ternaryfunc PyTypeObject.tp_call
888892

Doc/data/stable_abi.dat

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Doc/howto/logging-cookbook.rst

Lines changed: 126 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,8 +1846,11 @@ the use of a :class:`Filter` does not provide the desired result.
18461846

18471847
.. _zeromq-handlers:
18481848

1849-
Subclassing QueueHandler - a ZeroMQ example
1850-
-------------------------------------------
1849+
Subclassing QueueHandler and QueueListener- a ZeroMQ example
1850+
------------------------------------------------------------
1851+
1852+
Subclass ``QueueHandler``
1853+
^^^^^^^^^^^^^^^^^^^^^^^^^
18511854

18521855
You can use a :class:`QueueHandler` subclass to send messages to other kinds
18531856
of queues, for example a ZeroMQ 'publish' socket. In the example below,the
@@ -1885,8 +1888,8 @@ data needed by the handler to create the socket::
18851888
self.queue.close()
18861889

18871890

1888-
Subclassing QueueListener - a ZeroMQ example
1889-
--------------------------------------------
1891+
Subclass ``QueueListener``
1892+
^^^^^^^^^^^^^^^^^^^^^^^^^^
18901893

18911894
You can also subclass :class:`QueueListener` to get messages from other kinds
18921895
of queues, for example a ZeroMQ 'subscribe' socket. Here's an example::
@@ -1903,25 +1906,134 @@ of queues, for example a ZeroMQ 'subscribe' socket. Here's an example::
19031906
msg = self.queue.recv_json()
19041907
return logging.makeLogRecord(msg)
19051908

1909+
.. _pynng-handlers:
19061910

1907-
.. seealso::
1911+
Subclassing QueueHandler and QueueListener- a ``pynng`` example
1912+
---------------------------------------------------------------
19081913

1909-
Module :mod:`logging`
1910-
API reference for the logging module.
1914+
In a similar way to the above section, we can implement a listener and handler
1915+
using `pynng <https://pypi.org/project/pynng/>`_, which is a Python binding to
1916+
`NNG <https://nng.nanomsg.org/>`_, billed as a spiritual successor to ZeroMQ.
1917+
The following snippets illustrate -- you can test them in an environment which has
1918+
``pynng`` installed. Juat for variety, we present the listener first.
19111919

1912-
Module :mod:`logging.config`
1913-
Configuration API for the logging module.
19141920

1915-
Module :mod:`logging.handlers`
1916-
Useful handlers included with the logging module.
1921+
Subclass ``QueueListener``
1922+
^^^^^^^^^^^^^^^^^^^^^^^^^^
1923+
1924+
.. code-block:: python
1925+
1926+
import json
1927+
import logging
1928+
import logging.handlers
1929+
1930+
import pynng
19171931
1918-
:ref:`A basic logging tutorial <logging-basic-tutorial>`
1932+
DEFAULT_ADDR = "tcp://localhost:13232"
19191933
1920-
:ref:`A more advanced logging tutorial <logging-advanced-tutorial>`
1934+
interrupted = False
19211935
1936+
class NNGSocketListener(logging.handlers.QueueListener):
1937+
1938+
def __init__(self, uri, /, *handlers, **kwargs):
1939+
# Have a timeout for interruptability, and open a
1940+
# subscriber socket
1941+
socket = pynng.Sub0(listen=uri, recv_timeout=500)
1942+
# The b'' subscription matches all topics
1943+
topics = kwargs.pop('topics', None) or b''
1944+
socket.subscribe(topics)
1945+
# We treat the socket as a queue
1946+
super().__init__(socket, *handlers, **kwargs)
1947+
1948+
def dequeue(self, block):
1949+
data = None
1950+
# Keep looping while not interrupted and no data received over the
1951+
# socket
1952+
while not interrupted:
1953+
try:
1954+
data = self.queue.recv(block=block)
1955+
break
1956+
except pynng.Timeout:
1957+
pass
1958+
except pynng.Closed: # sometimes hit when you hit Ctrl-C
1959+
break
1960+
if data is None:
1961+
return None
1962+
# Get the logging event sent from a publisher
1963+
event = json.loads(data.decode('utf-8'))
1964+
return logging.makeLogRecord(event)
1965+
1966+
def enqueue_sentinel(self):
1967+
# Not used in this implementation, as the socket isn't really a
1968+
# queue
1969+
pass
1970+
1971+
logging.getLogger('pynng').propagate = False
1972+
listener = NNGSocketListener(DEFAULT_ADDR, logging.StreamHandler(), topics=b'')
1973+
listener.start()
1974+
print('Press Ctrl-C to stop.')
1975+
try:
1976+
while True:
1977+
pass
1978+
except KeyboardInterrupt:
1979+
interrupted = True
1980+
finally:
1981+
listener.stop()
1982+
1983+
1984+
Subclass ``QueueHandler``
1985+
^^^^^^^^^^^^^^^^^^^^^^^^^
19221986

19231987
.. currentmodule:: logging
19241988

1989+
.. code-block:: python
1990+
1991+
import json
1992+
import logging
1993+
import logging.handlers
1994+
import time
1995+
import random
1996+
1997+
import pynng
1998+
1999+
DEFAULT_ADDR = "tcp://localhost:13232"
2000+
2001+
class NNGSocketHandler(logging.handlers.QueueHandler):
2002+
2003+
def __init__(self, uri):
2004+
socket = pynng.Pub0(dial=uri, send_timeout=500)
2005+
super().__init__(socket)
2006+
2007+
def enqueue(self, record):
2008+
# Send the record as UTF-8 encoded JSON
2009+
d = dict(record.__dict__)
2010+
data = json.dumps(d)
2011+
self.queue.send(data.encode('utf-8'))
2012+
2013+
def close(self):
2014+
self.queue.close()
2015+
2016+
logging.getLogger('pynng').propagate = False
2017+
handler = NNGSocketHandler(DEFAULT_ADDR)
2018+
logging.basicConfig(level=logging.DEBUG,
2019+
handlers=[logging.StreamHandler(), handler],
2020+
format='%(levelname)-8s %(name)10s %(message)s')
2021+
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
2022+
logging.CRITICAL)
2023+
logger_names = ('myapp', 'myapp.lib1', 'myapp.lib2')
2024+
msgno = 1
2025+
while True:
2026+
# Just randomly select some loggers and levels and log away
2027+
level = random.choice(levels)
2028+
logger = logging.getLogger(random.choice(logger_names))
2029+
logger.log(level, 'Message no. %5d' % msgno)
2030+
msgno += 1
2031+
delay = random.random() * 2 + 0.5
2032+
time.sleep(delay)
2033+
2034+
You can run the above two snippets in separate command shells.
2035+
2036+
19252037
An example dictionary-based configuration
19262038
-----------------------------------------
19272039

@@ -3418,7 +3530,7 @@ The worker thread is implemented using Qt's ``QThread`` class rather than the
34183530
:mod:`threading` module, as there are circumstances where one has to use
34193531
``QThread``, which offers better integration with other ``Qt`` components.
34203532

3421-
The code should work with recent releases of either ``PySide6``, ``PyQt6``,
3533+
The code should work with recent releases of any of ``PySide6``, ``PyQt6``,
34223534
``PySide2`` or ``PyQt5``. You should be able to adapt the approach to earlier
34233535
versions of Qt. Please refer to the comments in the code snippet for more
34243536
detailed information.

Doc/library/imaplib.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ retrieves and prints all messages::
622622

623623
import getpass, imaplib
624624

625-
M = imaplib.IMAP4()
625+
M = imaplib.IMAP4(host='example.org')
626626
M.login(getpass.getuser(), getpass.getpass())
627627
M.select()
628628
typ, data = M.search(None, 'ALL')

Doc/library/ipaddress.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,18 @@ write code that handles both IP versions correctly. Address objects are
192192
``is_private`` has value opposite to :attr:`is_global`, except for the shared address space
193193
(``100.64.0.0/10`` range) where they are both ``False``.
194194

195+
.. versionchanged:: 3.13
196+
197+
Fixed some false positives and false negatives.
198+
199+
* ``192.0.0.0/24`` is considered private with the exception of ``192.0.0.9/32`` and
200+
``192.0.0.10/32`` (previously: only the ``192.0.0.0/29`` sub-range was considered private).
201+
* ``64:ff9b:1::/48`` is considered private.
202+
* ``2002::/16`` is considered private.
203+
* There are exceptions within ``2001::/23`` (otherwise considered private): ``2001:1::1/128``,
204+
``2001:1::2/128``, ``2001:3::/32``, ``2001:4:112::/48``, ``2001:20::/28``, ``2001:30::/28``.
205+
The exceptions are not considered private.
206+
195207
.. attribute:: is_global
196208

197209
``True`` if the address is defined as globally reachable by
@@ -209,6 +221,10 @@ write code that handles both IP versions correctly. Address objects are
209221

210222
.. versionadded:: 3.4
211223

224+
.. versionchanged:: 3.13
225+
226+
Fixed some false positives and false negatives, see :attr:`is_private` for details.
227+
212228
.. attribute:: is_unspecified
213229

214230
``True`` if the address is unspecified. See :RFC:`5735` (for IPv4)

Doc/library/os.path.rst

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
.. module:: os.path
55
:synopsis: Operations on pathnames.
66

7-
**Source code:** :source:`Lib/posixpath.py` (for POSIX) and
7+
**Source code:** :source:`Lib/genericpath.py`, :source:`Lib/posixpath.py` (for POSIX) and
88
:source:`Lib/ntpath.py` (for Windows).
99

1010
.. index:: single: path; operations
@@ -85,8 +85,6 @@ the :mod:`glob` module.)
8585
if *paths* is empty. Unlike :func:`commonprefix`, this returns a
8686
valid path.
8787

88-
.. availability:: Unix, Windows.
89-
9088
.. versionadded:: 3.5
9189

9290
.. versionchanged:: 3.6
@@ -324,10 +322,11 @@ the :mod:`glob` module.)
324322
Dev Drives. See `the Windows documentation <https://learn.microsoft.com/windows/dev-drive/>`_
325323
for information on enabling and creating Dev Drives.
326324

327-
.. availability:: Windows.
328-
329325
.. versionadded:: 3.12
330326

327+
.. versionchanged:: 3.13
328+
The function is now available on all platforms, and will always return ``False`` on those that have no support for Dev Drives
329+
331330

332331
.. function:: isreserved(path)
333332

@@ -442,8 +441,6 @@ the :mod:`glob` module.)
442441

443442
*start* defaults to :data:`os.curdir`.
444443

445-
.. availability:: Unix, Windows.
446-
447444
.. versionchanged:: 3.6
448445
Accepts a :term:`path-like object`.
449446

@@ -454,8 +451,6 @@ the :mod:`glob` module.)
454451
This is determined by the device number and i-node number and raises an
455452
exception if an :func:`os.stat` call on either pathname fails.
456453

457-
.. availability:: Unix, Windows.
458-
459454
.. versionchanged:: 3.2
460455
Added Windows support.
461456

@@ -470,8 +465,6 @@ the :mod:`glob` module.)
470465

471466
Return ``True`` if the file descriptors *fp1* and *fp2* refer to the same file.
472467

473-
.. availability:: Unix, Windows.
474-
475468
.. versionchanged:: 3.2
476469
Added Windows support.
477470

@@ -486,8 +479,6 @@ the :mod:`glob` module.)
486479
:func:`os.lstat`, or :func:`os.stat`. This function implements the
487480
underlying comparison used by :func:`samefile` and :func:`sameopenfile`.
488481

489-
.. availability:: Unix, Windows.
490-
491482
.. versionchanged:: 3.4
492483
Added Windows support.
493484

Doc/library/pathlib.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,6 +1682,10 @@ The patterns accepted and results generated by :meth:`Path.glob` and
16821682
5. The values returned from pathlib's ``path.glob()`` and ``path.rglob()``
16831683
include the *path* as a prefix, unlike the results of
16841684
``glob.glob(root_dir=path)``.
1685+
6. The values returned from pathlib's ``path.glob()`` and ``path.rglob()``
1686+
may include *path* itself, for example when globbing "``**``", whereas the
1687+
results of ``glob.glob(root_dir=path)`` never include an empty string that
1688+
would correspond to *path*.
16851689

16861690

16871691
Comparison to the :mod:`os` and :mod:`os.path` modules

0 commit comments

Comments
 (0)