Imported Upstream version 3.10.4 upstream/3.10.4
authorJinWang An <jinwang.an@samsung.com>
Wed, 18 Jan 2023 06:01:40 +0000 (15:01 +0900)
committerJinWang An <jinwang.an@samsung.com>
Wed, 18 Jan 2023 06:01:40 +0000 (15:01 +0900)
75 files changed:
Doc/library/aifc.rst
Doc/library/asynchat.rst
Doc/library/asyncore.rst
Doc/library/audioop.rst
Doc/library/binascii.rst
Doc/library/cgi.rst
Doc/library/cgitb.rst
Doc/library/chunk.rst
Doc/library/configparser.rst
Doc/library/crypt.rst
Doc/library/fileformats.rst
Doc/library/imghdr.rst
Doc/library/internet.rst
Doc/library/ipc.rst
Doc/library/mm.rst
Doc/library/msilib.rst
Doc/library/netdata.rst
Doc/library/nis.rst
Doc/library/nntplib.rst
Doc/library/ossaudiodev.rst
Doc/library/pathlib.rst
Doc/library/pipes.rst
Doc/library/smtpd.rst
Doc/library/sndhdr.rst
Doc/library/spwd.rst
Doc/library/sunau.rst
Doc/library/superseded.rst
Doc/library/telnetlib.rst
Doc/library/tempfile.rst
Doc/library/textwrap.rst
Doc/library/typing.rst
Doc/library/unix.rst
Doc/library/uu.rst
Doc/library/windows.rst
Doc/library/xdrlib.rst
Doc/library/zlib.rst
Doc/reference/compound_stmts.rst
Doc/reference/datamodel.rst
Doc/reference/executionmodel.rst
Doc/tools/susp-ignored.csv
Include/patchlevel.h
Lib/asynchat.py
Lib/asyncio/locks.py
Lib/asyncore.py
Lib/doctest.py
Lib/pydoc.py
Lib/pydoc_data/topics.py
Lib/smtpd.py
Lib/sre_parse.py
Lib/test/libregrtest/main.py
Lib/test/libregrtest/win_utils.py
Lib/test/pydoc_mod.py
Lib/test/test_asyncio/test_asyncio_waitfor.py [deleted file]
Lib/test/test_asyncio/test_locks.py
Lib/test/test_asyncio/test_tasks.py
Lib/test/test_asyncio/test_waitfor.py [new file with mode: 0644]
Lib/test/test_binascii.py
Lib/test/test_cmd_line.py
Lib/test/test_doctest.py
Lib/test/test_pydoc.py
Lib/test/test_re.py
Lib/tkinter/test/test_tkinter/test_widgets.py
Lib/tkinter/test/test_ttk/test_style.py
Lib/unittest/main.py
Lib/zipfile.py
Misc/ACKS
Misc/NEWS
Modules/_sre.c
Modules/binascii.c
Modules/faulthandler.c
Modules/sre.h
README.rst
configure
configure.ac
pyconfig.h.in

index 2e917cf7321b857bb7a0bcb317e93d2ab88ba443..edb4bf86e5a0aae57c83db8e2d9d14fcfa6cc681 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: aifc
    :synopsis: Read and write audio files in AIFF or AIFC format.
+   :deprecated:
 
 **Source code:** :source:`Lib/aifc.py`
 
    single: AIFF
    single: AIFF-C
 
+
+.. deprecated:: 3.11
+   The :mod:`aifc` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 This module provides support for reading and writing AIFF and AIFF-C files.
index 9e51416b83a570b45964431e85ef8b07070b27f5..4354444a1d3314a57d63dd5c38f15034143bd378 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: asynchat
    :synopsis: Support for asynchronous command/response protocols.
+   :deprecated:
 
 .. moduleauthor:: Sam Rushing <rushing@nightmare.com>
 .. sectionauthor:: Steve Holden <sholden@holdenweb.com>
@@ -10,6 +11,7 @@
 **Source code:** :source:`Lib/asynchat.py`
 
 .. deprecated:: 3.6
+   :mod:`asynchat` will be removed in Python 3.12 (:pep:`594`).
    Please use :mod:`asyncio` instead.
 
 --------------
index a86518ebff2777eb12e75fb361950392145a2699..e481e13db76f70204b0990839170d9050bce22d1 100644 (file)
@@ -4,6 +4,7 @@
 .. module:: asyncore
    :synopsis: A base class for developing asynchronous socket handling
               services.
+   :deprecated:
 
 .. moduleauthor:: Sam Rushing <rushing@nightmare.com>
 .. sectionauthor:: Christopher Petrilli <petrilli@amber.org>
@@ -13,6 +14,7 @@
 **Source code:** :source:`Lib/asyncore.py`
 
 .. deprecated:: 3.6
+   :mod:`asyncore` will be removed in Python 3.12 (:pep:`594`).
    Please use :mod:`asyncio` instead.
 
 --------------
index bad9da2ec62e565d50bfdd0ed45519251f07ae35..eae206084f09004ffb7cf888ca48efb09437082d 100644 (file)
@@ -3,6 +3,10 @@
 
 .. module:: audioop
    :synopsis: Manipulate raw audio data.
+   :deprecated:
+
+.. deprecated:: 3.11
+   The :mod:`audioop` module is deprecated (see :pep:`594` for details).
 
 --------------
 
index 2c0c1bce5d7f8f9a0f18f0be815a0c4c5605b6df..5cd058c0b6d74f97cd85f2917783e4de14d964d3 100644 (file)
@@ -135,7 +135,7 @@ The :mod:`binascii` module defines the following functions:
 
 .. function:: crc32(data[, value])
 
-   Compute CRC-32, the 32-bit checksum of *data*, starting with an
+   Compute CRC-32, the unsigned 32-bit checksum of *data*, starting with an
    initial CRC of *value*.  The default initial CRC is zero.  The algorithm
    is consistent with the ZIP file checksum.  Since the algorithm is designed for
    use as a checksum algorithm, it is not suitable for use as a general hash
@@ -149,9 +149,8 @@ The :mod:`binascii` module defines the following functions:
 
    .. versionchanged:: 3.0
       The result is always unsigned.
-      To generate the same numeric value across all Python versions and
-      platforms, use ``crc32(data) & 0xffffffff``.
-
+      To generate the same numeric value when using Python 2 or earlier,
+      use ``crc32(data) & 0xffffffff``.
 
 .. function:: b2a_hex(data[, sep[, bytes_per_sep=1]])
               hexlify(data[, sep[, bytes_per_sep=1]])
index c151f04dfb8d01b06b7b1ad169f2b1e8fd22b22c..306aa8d19ad72685c45ea744e007d79b8ca0227b 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: cgi
    :synopsis: Helpers for running Python scripts via the Common Gateway Interface.
+   :deprecated:
 
 **Source code:** :source:`Lib/cgi.py`
 
@@ -14,6 +15,9 @@
    single: URL
    single: Common Gateway Interface
 
+.. deprecated:: 3.11
+   The :mod:`cgi` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 Support module for Common Gateway Interface (CGI) scripts.
index 5f3a6476dd8cdcf5431425576ea14f3b0c638fd5..349414610bd40a7375b5c4b5436660f3688f8f97 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: cgitb
    :synopsis: Configurable traceback handler for CGI scripts.
+   :deprecated:
 
 .. moduleauthor:: Ka-Ping Yee <ping@lfw.org>
 .. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
@@ -15,6 +16,9 @@
    single: exceptions; in CGI scripts
    single: tracebacks; in CGI scripts
 
+.. deprecated:: 3.11
+   The :mod:`cgitb` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`cgitb` module provides a special exception handler for Python scripts.
index 5e24df923ed21024f986d8597921f1ac6938b344..7999420f536d762becefbb06a39589ec0379b1a4 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: chunk
    :synopsis: Module to read IFF chunks.
+   :deprecated:
 
 .. moduleauthor:: Sjoerd Mullender <sjoerd@acm.org>
 .. sectionauthor:: Sjoerd Mullender <sjoerd@acm.org>
@@ -16,6 +17,9 @@
    single: Real Media File Format
    single: RMFF
 
+.. deprecated:: 3.11
+   The :mod:`chunk` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 This module provides an interface for reading files that use EA IFF 85 chunks.
index 323dd2affc78fc9a987d2927a125e7b07db9816c..72aa20d73d8bd3b82950f19d48646ac7729634aa 100644 (file)
@@ -347,7 +347,8 @@ from ``get()`` calls.
       my_pictures: %(my_dir)s/Pictures
 
       [Escape]
-      gain: 80%%  # use a %% to escape the % sign (% is the only character that needs to be escaped)
+      # use a %% to escape the % sign (% is the only character that needs to be escaped):
+      gain: 80%%
 
    In the example above, :class:`ConfigParser` with *interpolation* set to
    ``BasicInterpolation()`` would resolve ``%(home_dir)s`` to the value of
@@ -382,7 +383,8 @@ from ``get()`` calls.
       my_pictures: ${my_dir}/Pictures
 
       [Escape]
-      cost: $$80  # use a $$ to escape the $ sign ($ is the only character that needs to be escaped)
+      # use a $$ to escape the $ sign ($ is the only character that needs to be escaped):
+      cost: $$80
 
    Values from other sections can be fetched as well:
 
index d25c626a175854ac5edca4c2f5d30a30bdb60e94..73df87ca0db8d183702102d61568a0037f5f3fe5 100644 (file)
@@ -4,6 +4,7 @@
 .. module:: crypt
    :platform: Unix
    :synopsis: The crypt() function used to check Unix passwords.
+   :deprecated:
 
 .. moduleauthor:: Steven D. Majewski <sdm7g@virginia.edu>
 .. sectionauthor:: Steven D. Majewski <sdm7g@virginia.edu>
@@ -15,6 +16,9 @@
    single: crypt(3)
    pair: cipher; DES
 
+.. deprecated:: 3.11
+   The :mod:`crypt` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 This module implements an interface to the :manpage:`crypt(3)` routine, which is
index e9c2e1fbbdf3e8975400c8f1bb67f36e11f822df..7b33b3364572d92ce02ae1a40b4eac1945e3bfe9 100644 (file)
@@ -13,5 +13,4 @@ that aren't markup languages and are not related to e-mail.
    csv.rst
    configparser.rst
    netrc.rst
-   xdrlib.rst
    plistlib.rst
index 3d7f6de7a1bec045d3a9ca6362bf6e5e2dc8c6e7..084fef73daf28dd474315cac88dd7fd25f00a3c7 100644 (file)
@@ -3,9 +3,13 @@
 
 .. module:: imghdr
    :synopsis: Determine the type of image contained in a file or byte stream.
+   :deprecated:
 
 **Source code:** :source:`Lib/imghdr.py`
 
+.. deprecated:: 3.11
+   The :mod:`imghdr` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`imghdr` module determines the type of image contained in a file or
index e745dd1243512e1975803574ed21e61c2a375997..ff58dcf4d89c36f26c9956e936bd6f234ed9514d 100644 (file)
@@ -20,8 +20,6 @@ is currently supported on most popular platforms.  Here is an overview:
 .. toctree::
 
    webbrowser.rst
-   cgi.rst
-   cgitb.rst
    wsgiref.rst
    urllib.rst
    urllib.request.rst
@@ -33,10 +31,7 @@ is currently supported on most popular platforms.  Here is an overview:
    ftplib.rst
    poplib.rst
    imaplib.rst
-   nntplib.rst
    smtplib.rst
-   smtpd.rst
-   telnetlib.rst
    uuid.rst
    socketserver.rst
    http.server.rst
index b88a174eb97f15c0067664902b6aca8cb0185f8b..4849c82f317d97ec704e72f3da037081abaa9cb4 100644 (file)
@@ -22,7 +22,5 @@ The list of modules described in this chapter is:
    ssl.rst
    select.rst
    selectors.rst
-   asyncore.rst
-   asynchat.rst
    signal.rst
    mmap.rst
index c8f79c4de1cdf258d00f4c546b13ea57ade708fa..cd06e9385a26124ed93ee002db8c317182e3b9e7 100644 (file)
@@ -11,12 +11,5 @@ discretion of the installation.  Here's an overview:
 
 .. toctree::
 
-   audioop.rst
-   aifc.rst
-   sunau.rst
    wave.rst
-   chunk.rst
    colorsys.rst
-   imghdr.rst
-   sndhdr.rst
-   ossaudiodev.rst
index 83b3d4973bf0d96dc4880c2ff3581eced2f91c6d..5ce18a1f75fc21a29eca8ba009ce83a0747aeae3 100644 (file)
@@ -4,6 +4,7 @@
 .. module:: msilib
    :platform: Windows
    :synopsis: Creation of Microsoft Installer files, and CAB files.
+   :deprecated:
 
 .. moduleauthor:: Martin v. Löwis <martin@v.loewis.de>
 .. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
@@ -12,6 +13,9 @@
 
 .. index:: single: msi
 
+.. deprecated:: 3.11
+   The :mod:`msilib` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`msilib` supports the creation of Microsoft Installer (``.msi``) files.
index e76280f2fe3f4c229804910c6297e647df799a74..0e6ebd3b02ddde498d392b876d83caa80bb412de 100644 (file)
@@ -20,4 +20,3 @@ on the internet.
    binhex.rst
    binascii.rst
    quopri.rst
-   uu.rst
index 10c67cbb81b2f057470ff6f039f37da10336f3a2..f6b6ea83946b0ed496abbea6b4e3cb981bf9435e 100644 (file)
@@ -5,10 +5,14 @@
 .. module:: nis
    :platform: Unix
    :synopsis: Interface to Sun's NIS (Yellow Pages) library.
+   :deprecated:
 
 .. moduleauthor:: Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
 .. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
 
+.. deprecated:: 3.11
+   The :mod:`nis` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`nis` module gives a thin wrapper around the NIS library, useful for
index e7ec9047e015e6cd66f07ad09160cdb72bad8b4e..2a996e451bf7c535c81f17b05c571e754f3ccc08 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: nntplib
    :synopsis: NNTP protocol client (requires sockets).
+   :deprecated:
 
 **Source code:** :source:`Lib/nntplib.py`
 
@@ -10,6 +11,9 @@
    pair: NNTP; protocol
    single: Network News Transfer Protocol
 
+.. deprecated:: 3.11
+   The :mod:`nntplib` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 This module defines the class :class:`NNTP` which implements the client side of
index a7d3dac363cdf24ae0f65e11a05eca9d444fd324..e0f0a6b8259e4f4deb19214e091213a9f53d90d0 100644 (file)
@@ -4,6 +4,10 @@
 .. module:: ossaudiodev
    :platform: Linux, FreeBSD
    :synopsis: Access to OSS-compatible audio devices.
+   :deprecated:
+
+.. deprecated:: 3.11
+   The :mod:`ossaudiodev` module is deprecated (see :pep:`594` for details).
 
 --------------
 
index b6507eb4d6fa2c1e9e581f8059ee3ebb3a68ec9f..fedea34bcd0c4b9dc0e1f08ce41412a2b1523c21 100644 (file)
@@ -914,7 +914,7 @@ call fails (for example because the path doesn't exist).
 
    The children are yielded in arbitrary order, and the special entries
    ``'.'`` and ``'..'`` are not included.  If a file is removed from or added
-   to the directory after creating the iterator, whether an path object for
+   to the directory after creating the iterator, whether a path object for
    that file be included is unspecified.
 
 .. method:: Path.lchmod(mode)
index 57e27a6acf4b6624137ec7004ac1ab3e5f4b9e36..4de8c51bcae049f9f48176c68937f5718e60e88c 100644 (file)
@@ -4,11 +4,15 @@
 .. module:: pipes
    :platform: Unix
    :synopsis: A Python interface to Unix shell pipelines.
+   :deprecated:
 
 .. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
 
 **Source code:** :source:`Lib/pipes.py`
 
+.. deprecated:: 3.11
+   The :mod:`pipes` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`pipes` module defines a class to abstract the concept of a *pipeline*
index 803430f1bde1734f89ec37a8a843bb9cd0675c5e..a39bc024047fd34681e17b17e747dc874d1d35a0 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: smtpd
    :synopsis: A SMTP server implementation in Python.
+   :deprecated:
 
 .. moduleauthor:: Barry Warsaw <barry@python.org>
 .. sectionauthor:: Moshe Zadka <moshez@moshez.org>
@@ -14,6 +15,7 @@
 This module offers several classes to implement SMTP (email) servers.
 
 .. deprecated:: 3.6
+   :mod:`smtpd` will be removed in Python 3.12 (:pep:`594`).
    The `aiosmtpd <https://aiosmtpd.readthedocs.io/>`_ package is a recommended
    replacement for this module.  It is based on :mod:`asyncio` and provides a
    more straightforward API.
index 6bfa9a9fd210bef3fee5aaffa7c2054853d7175c..41bce18b9cd849a4fb85630aec5e390033e946a7 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: sndhdr
    :synopsis: Determine type of a sound file.
+   :deprecated:
 
 .. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
 .. Based on comments in the module source file.
@@ -13,6 +14,9 @@
    single: A-LAW
    single: u-LAW
 
+.. deprecated:: 3.11
+   The :mod:`sndhdr` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`sndhdr` provides utility functions which attempt to determine the type
index c6cad2a3c32849fba0aef2c63d0c242809e06ae7..cb31a10a52e0017a850be468b1dd8197fef9ef74 100644 (file)
@@ -4,6 +4,10 @@
 .. module:: spwd
    :platform: Unix
    :synopsis: The shadow password database (getspnam() and friends).
+   :deprecated:
+
+.. deprecated:: 3.11
+   The :mod:`spwd` module is deprecated (see :pep:`594` for details).
 
 --------------
 
index aad6f93b6bff18ebc2f431481fd4d7631ccbbbe1..cfb1257f585484b91a09b95488b9a11650e50254 100644 (file)
@@ -3,11 +3,15 @@
 
 .. module:: sunau
    :synopsis: Provide an interface to the Sun AU sound format.
+   :deprecated:
 
 .. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
 
 **Source code:** :source:`Lib/sunau.py`
 
+.. deprecated:: 3.11
+   The :mod:`sunau` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`sunau` module provides a convenient interface to the Sun AU sound
index 50a5983236e76ae605e2399383c2f8f83ff66a2b..e3f9b0d37fe10bdbd9acf86a8f74d6a923108ad9 100644 (file)
@@ -10,5 +10,26 @@ backwards compatibility. They have been superseded by other modules.
 
 .. toctree::
 
-   optparse.rst
+   aifc.rst
+   asynchat.rst
+   asyncore.rst
+   audioop.rst
+   cgi.rst
+   cgitb.rst
+   chunk.rst
+   crypt.rst
+   imghdr.rst
    imp.rst
+   msilib.rst
+   nntplib.rst
+   nis.rst
+   optparse.rst
+   ossaudiodev.rst
+   pipes.rst
+   smtpd.rst
+   sndhdr.rst
+   spwd.rst
+   sunau.rst
+   telnetlib.rst
+   uu.rst
+   xdrlib.rst
index 48a9aea50dddd1aecdfc102ca99c9fad131aa03b..97b0a713e442238d1e73301112d48aa999acb15a 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: telnetlib
    :synopsis: Telnet client class.
+   :deprecated:
 
 .. sectionauthor:: Skip Montanaro <skip@pobox.com>
 
@@ -10,6 +11,9 @@
 
 .. index:: single: protocol; Telnet
 
+.. deprecated:: 3.11
+   The :mod:`telnetlib` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`telnetlib` module provides a :class:`Telnet` class that implements the
index 6b23a1bcd630bc9bfeb8dadc1eeafbb2d81a7ece..30491d48e10ef0dce4d9036442c5c63182403c84 100644 (file)
@@ -96,9 +96,9 @@ The module defines the following user-callable items:
       Added *errors* parameter.
 
 
-.. function:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)
+.. class:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None)
 
-   This function operates exactly as :func:`TemporaryFile` does, except that
+   This class operates exactly as :func:`TemporaryFile` does, except that
    data is spooled in memory until the file size exceeds *max_size*, or
    until the file's :func:`fileno` method is called, at which point the
    contents are written to disk and operation proceeds as with
@@ -121,9 +121,9 @@ The module defines the following user-callable items:
       Added *errors* parameter.
 
 
-.. function:: TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False)
+.. class:: TemporaryDirectory(suffix=None, prefix=None, dir=None, ignore_cleanup_errors=False)
 
-   This function securely creates a temporary directory using the same rules as :func:`mkdtemp`.
+   This class securely creates a temporary directory using the same rules as :func:`mkdtemp`.
    The resulting object can be used as a context manager (see
    :ref:`tempfile-examples`).  On completion of the context or destruction
    of the temporary directory object, the newly created temporary directory
index 7780e241769657e5d79b9804bf0ebb7859de043e..1a9d5f98f78a7e89e01e696c972b912d403ee520 100644 (file)
@@ -21,7 +21,8 @@ functions should be good enough; otherwise, you should use an instance of
                    subsequent_indent="", expand_tabs=True, \
                    replace_whitespace=True, fix_sentence_endings=False, \
                    break_long_words=True, drop_whitespace=True, \
-                   break_on_hyphens=True, tabsize=8, max_lines=None)
+                   break_on_hyphens=True, tabsize=8, max_lines=None, \
+                   placeholder=' [...]')
 
    Wraps the single paragraph in *text* (a string) so every line is at most
    *width* characters long.  Returns a list of output lines, without final
@@ -39,7 +40,7 @@ functions should be good enough; otherwise, you should use an instance of
                    replace_whitespace=True, fix_sentence_endings=False, \
                    break_long_words=True, drop_whitespace=True, \
                    break_on_hyphens=True, tabsize=8, \
-                   max_lines=None)
+                   max_lines=None, placeholder=' [...]')
 
    Wraps the single paragraph in *text*, and returns a single string containing the
    wrapped paragraph.  :func:`fill` is shorthand for  ::
index 6fa3eeeaf011904eeeb16429aa772e1b5720d6d6..ea0bcee81c50aa531194e0b89e77234dc3a4cebd 100644 (file)
@@ -247,7 +247,7 @@ subscription to denote expected types for container elements.
    def notify_by_email(employees: Sequence[Employee],
                        overrides: Mapping[str, str]) -> None: ...
 
-Generics can be parameterized by using a new factory available in typing
+Generics can be parameterized by using a factory available in typing
 called :class:`TypeVar`.
 
 ::
@@ -304,16 +304,16 @@ that ``LoggedVar[t]`` is valid as a type::
        for var in vars:
            var.set(0)
 
-A generic type can have any number of type variables, and type variables may
-be constrained::
+A generic type can have any number of type variables. All varieties of
+:class:`TypeVar` are permissible as parameters for a generic type::
 
-   from typing import TypeVar, Generic
-   ...
+   from typing import TypeVar, Generic, Sequence
 
-   T = TypeVar('T')
+   T = TypeVar('T', contravariant=True)
+   B = TypeVar('B', bound=Sequence[bytes], covariant=True)
    S = TypeVar('S', int, str)
 
-   class StrangePair(Generic[T, S]):
+   class WeirdTrio(Generic[T, B, S]):
        ...
 
 Each type variable argument to :class:`Generic` must be distinct.
@@ -1084,7 +1084,8 @@ These are not used in annotations. They are building blocks for creating generic
     Usage::
 
       T = TypeVar('T')  # Can be anything
-      A = TypeVar('A', str, bytes)  # Must be str or bytes
+      S = TypeVar('S', bound=str)  # Can be any subtype of str
+      A = TypeVar('A', str, bytes)  # Must be exactly str or bytes
 
     Type variables exist primarily for the benefit of static type
     checkers.  They serve as the parameters for generic types as well
@@ -1095,25 +1096,91 @@ These are not used in annotations. They are building blocks for creating generic
            """Return a list containing n references to x."""
            return [x]*n
 
-       def longest(x: A, y: A) -> A:
-           """Return the longest of two strings."""
-           return x if len(x) >= len(y) else y
 
-    The latter example's signature is essentially the overloading
-    of ``(str, str) -> str`` and ``(bytes, bytes) -> bytes``.  Also note
-    that if the arguments are instances of some subclass of :class:`str`,
-    the return type is still plain :class:`str`.
+       def print_capitalized(x: S) -> S:
+           """Print x capitalized, and return x."""
+           print(x.capitalize())
+           return x
+
+
+       def concatenate(x: A, y: A) -> A:
+           """Add two strings or bytes objects together."""
+           return x + y
+
+    Note that type variables can be *bound*, *constrained*, or neither, but
+    cannot be both bound *and* constrained.
+
+    Constrained type variables and bound type variables have different
+    semantics in several important ways. Using a *constrained* type variable
+    means that the ``TypeVar`` can only ever be solved as being exactly one of
+    the constraints given::
+
+       a = concatenate('one', 'two')  # Ok, variable 'a' has type 'str'
+       b = concatenate(StringSubclass('one'), StringSubclass('two'))  # Inferred type of variable 'b' is 'str',
+                                                                      # despite 'StringSubclass' being passed in
+       c = concatenate('one', b'two')  # error: type variable 'A' can be either 'str' or 'bytes' in a function call, but not both
+
+    Using a *bound* type variable, however, means that the ``TypeVar`` will be
+    solved using the most specific type possible::
+
+       print_capitalized('a string')  # Ok, output has type 'str'
+
+       class StringSubclass(str):
+           pass
+
+       print_capitalized(StringSubclass('another string'))  # Ok, output has type 'StringSubclass'
+       print_capitalized(45)  # error: int is not a subtype of str
+
+    Type variables can be bound to concrete types, abstract types (ABCs or
+    protocols), and even unions of types::
+
+       U = TypeVar('U', bound=str|bytes)  # Can be any subtype of the union str|bytes
+       V = TypeVar('V', bound=SupportsAbs)  # Can be anything with an __abs__ method
+
+    Bound type variables are particularly useful for annotating
+    :func:`classmethods <classmethod>` that serve as alternative constructors.
+    In the following example (©
+    `Raymond Hettinger <https://www.youtube.com/watch?v=HTLu2DFOdTg>`_), the
+    type variable ``C`` is bound to the ``Circle`` class through the use of a
+    forward reference. Using this type variable to annotate the
+    ``with_circumference`` classmethod, rather than hardcoding the return type
+    as ``Circle``, means that a type checker can correctly infer the return
+    type even if the method is called on a subclass::
+
+       import math
+
+       C = TypeVar('C', bound='Circle')
+
+       class Circle:
+           """An abstract circle"""
+
+           def __init__(self, radius: float) -> None:
+               self.radius = radius
+
+           # Use a type variable to show that the return type
+           # will always be an instance of whatever `cls` is
+           @classmethod
+           def with_circumference(cls: type[C], circumference: float) -> C:
+               """Create a circle with the specified circumference"""
+               radius = circumference / (math.pi * 2)
+               return cls(radius)
+
+
+       class Tire(Circle):
+           """A specialised circle (made out of rubber)"""
+
+           MATERIAL = 'rubber'
+
+
+       c = Circle.with_circumference(3)  # Ok, variable 'c' has type 'Circle'
+       t = Tire.with_circumference(4)  # Ok, variable 't' has type 'Tire' (not 'Circle')
 
     At runtime, ``isinstance(x, T)`` will raise :exc:`TypeError`.  In general,
     :func:`isinstance` and :func:`issubclass` should not be used with types.
 
     Type variables may be marked covariant or contravariant by passing
     ``covariant=True`` or ``contravariant=True``.  See :pep:`484` for more
-    details.  By default type variables are invariant.  Alternatively,
-    a type variable may specify an upper bound using ``bound=<type>``.
-    This means that an actual type substituted (explicitly or implicitly)
-    for the type variable must be a subclass of the boundary type,
-    see :pep:`484`.
+    details.  By default, type variables are invariant.
 
 .. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False)
 
@@ -1215,7 +1282,7 @@ These are not used in annotations. They are building blocks for creating generic
 
 .. data:: AnyStr
 
-   ``AnyStr`` is a type variable defined as
+   ``AnyStr`` is a :class:`constrained type variable <TypeVar>` defined as
    ``AnyStr = TypeVar('AnyStr', str, bytes)``.
 
    It is meant to be used for functions that may accept any kind of string
index 04d4081f4a0736ed658a1c51ac9f0bca9d62b11e..4553a104d15a24d16921b856f2ae368e076e28ff 100644 (file)
@@ -13,14 +13,10 @@ of it.  Here's an overview:
 
    posix.rst
    pwd.rst
-   spwd.rst
    grp.rst
-   crypt.rst
    termios.rst
    tty.rst
    pty.rst
    fcntl.rst
-   pipes.rst
    resource.rst
-   nis.rst
    syslog.rst
index 0bc8021e1bdfc7445aaf4a5ac662ef57f90e7e63..c341bc83dcfed0aca91303c15f6728ffd6961771 100644 (file)
@@ -3,11 +3,15 @@
 
 .. module:: uu
    :synopsis: Encode and decode files in uuencode format.
+   :deprecated:
 
 .. moduleauthor:: Lance Ellinghouse
 
 **Source code:** :source:`Lib/uu.py`
 
+.. deprecated:: 3.11
+   The :mod:`uu` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 This module encodes and decodes files in uuencode format, allowing arbitrary
index b60d4e4ccf51d9c2a8a192ebb061842ce1bc6883..4d72ead12aadc7f3f6f0a6ccc8144b1715e16d52 100644 (file)
@@ -9,7 +9,6 @@ This chapter describes modules that are only available on MS Windows platforms.
 
 .. toctree::
 
-   msilib.rst
    msvcrt.rst
    winreg.rst
    winsound.rst
index 42a03a46754d03f0012f1660226eca4ffb863f5f..060b2e2c60df6d6cba3225f1f47dd8577e35cf58 100644 (file)
@@ -3,6 +3,7 @@
 
 .. module:: xdrlib
    :synopsis: Encoders and decoders for the External Data Representation (XDR).
+   :deprecated:
 
 **Source code:** :source:`Lib/xdrlib.py`
 
@@ -10,6 +11,9 @@
    single: XDR
    single: External Data Representation
 
+.. deprecated:: 3.11
+   The :mod:`xdrlib` module is deprecated (see :pep:`594` for details).
+
 --------------
 
 The :mod:`xdrlib` module supports the External Data Representation Standard as
index ec60ea24db662709f0745715e91cf3c738885164..6758c615d74db8242a65fd7f352b5495bd156107 100644 (file)
@@ -42,10 +42,9 @@ The available exception and functions in this module are:
    for use as a general hash algorithm.
 
    .. versionchanged:: 3.0
-      Always returns an unsigned value.
-      To generate the same numeric value across all Python versions and
-      platforms, use ``adler32(data) & 0xffffffff``.
-
+      The result is always unsigned.
+      To generate the same numeric value when using Python 2 or earlier,
+      use ``adler32(data) & 0xffffffff``.
 
 .. function:: compress(data, /, level=-1)
 
@@ -127,10 +126,9 @@ The available exception and functions in this module are:
    for use as a general hash algorithm.
 
    .. versionchanged:: 3.0
-      Always returns an unsigned value.
-      To generate the same numeric value across all Python versions and
-      platforms, use ``crc32(data) & 0xffffffff``.
-
+      The result is always unsigned.
+      To generate the same numeric value when using Python 2 or earlier,
+      use ``crc32(data) & 0xffffffff``.
 
 .. function:: decompress(data, /, wbits=MAX_WBITS, bufsize=DEF_BUF_SIZE)
 
index 7f37bb4fdf9c999352bc1711fb36a6329a8bec4b..871c101996b155e9dd22526ea3c5a1ecb2288c66 100644 (file)
@@ -233,9 +233,10 @@ is found that matches the exception.  An expression-less except clause, if
 present, must be last; it matches any exception.  For an except clause with an
 expression, that expression is evaluated, and the clause matches the exception
 if the resulting object is "compatible" with the exception.  An object is
-compatible with an exception if it is the class or a base class of the exception
-object, or a tuple containing an item that is the class or a base class of
-the exception object.
+compatible with an exception if the object is the class or a
+:term:`non-virtual base class <abstract base class>` of the exception object,
+or a tuple containing an item that is the class or a non-virtual base class
+of the exception object.
 
 If no except clause matches the exception, the search for an exception handler
 continues in the surrounding code and on the invocation stack.  [#]_
index 55ac99c3927551df698923ca929ca62eb7ab7d07..3c32210a6ac7b0f0c666200d4ded631786ef7349 100644 (file)
@@ -1466,7 +1466,7 @@ Basic customization
 
    Called by built-in function :func:`hash` and for operations on members of
    hashed collections including :class:`set`, :class:`frozenset`, and
-   :class:`dict`.  :meth:`__hash__` should return an integer. The only required
+   :class:`dict`.  The ``__hash__()`` method should return an integer. The only required
    property is that objects which compare equal have the same hash value; it is
    advised to mix together the hash values of the components of the object that
    also play a part in comparison of objects by packing them into a tuple and
index e652915bd271c375e3767b06abb16ae9c1d34758..d9183561820b2beedbb200068775e3862bab9f0a 100644 (file)
@@ -259,8 +259,9 @@ a stack traceback, except when the exception is :exc:`SystemExit`.
 
 Exceptions are identified by class instances.  The :keyword:`except` clause is
 selected depending on the class of the instance: it must reference the class of
-the instance or a base class thereof.  The instance can be received by the
-handler and can carry additional information about the exceptional condition.
+the instance or a :term:`non-virtual base class <abstract base class>` thereof.
+The instance can be received by the handler and can carry additional information
+about the exceptional condition.
 
 .. note::
 
index 9f4a44f1de64e1cb2dd61449d8412d89fc74bb48..0a8d702f96bce29d359bf8eb866d595501855744 100644 (file)
@@ -384,3 +384,4 @@ library/typing,,`,# Type of ``val`` is narrowed to ``str``
 library/typing,,`,"# Else, type of ``val`` is narrowed to ``float``."
 library/typing,,`,# Type of ``val`` is narrowed to ``List[str]``.
 library/typing,,`,# Type of ``val`` remains as ``List[object]``.
+library/typing,,`,    # will always be an instance of whatever `cls` is
index 5bb246e9419d1faa2d8d70b6fdeaae9e5122d794..482069c791a91ffa695f827c6e2af2345f702c70 100644 (file)
 /*--start constants--*/
 #define PY_MAJOR_VERSION        3
 #define PY_MINOR_VERSION        10
-#define PY_MICRO_VERSION        3
+#define PY_MICRO_VERSION        4
 #define PY_RELEASE_LEVEL        PY_RELEASE_LEVEL_FINAL
 #define PY_RELEASE_SERIAL       0
 
 /* Version as a string */
-#define PY_VERSION              "3.10.3"
+#define PY_VERSION              "3.10.4"
 /*--end constants--*/
 
 /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
index de26ffa648ffecd3b98beebd45e0846267e6edd7..e081e67c75acb01332bee52dcc05e81eac34d436 100644 (file)
@@ -50,7 +50,7 @@ from collections import deque
 
 from warnings import warn
 warn(
-    'The asynchat module is deprecated. '
+    'The asynchat module is deprecated and will be removed in Python 3.12. '
     'The recommended replacement is asyncio',
     DeprecationWarning,
     stacklevel=2)
index 4fef64e3921e17004f2dbd16426002daea85fae2..7b81c25b2d9e76571834a91d070169c89a10c4aa 100644 (file)
@@ -6,6 +6,7 @@ import collections
 
 from . import exceptions
 from . import mixins
+from . import tasks
 
 
 class _ContextManagerMixin:
@@ -350,6 +351,7 @@ class Semaphore(_ContextManagerMixin, mixins._LoopBoundMixin):
             raise ValueError("Semaphore initial value must be >= 0")
         self._value = value
         self._waiters = collections.deque()
+        self._wakeup_scheduled = False
 
     def __repr__(self):
         res = super().__repr__()
@@ -363,6 +365,7 @@ class Semaphore(_ContextManagerMixin, mixins._LoopBoundMixin):
             waiter = self._waiters.popleft()
             if not waiter.done():
                 waiter.set_result(None)
+                self._wakeup_scheduled = True
                 return
 
     def locked(self):
@@ -378,16 +381,17 @@ class Semaphore(_ContextManagerMixin, mixins._LoopBoundMixin):
         called release() to make it larger than 0, and then return
         True.
         """
-        while self._value <= 0:
+        # _wakeup_scheduled is set if *another* task is scheduled to wakeup
+        # but its acquire() is not resumed yet
+        while self._wakeup_scheduled or self._value <= 0:
             fut = self._get_loop().create_future()
             self._waiters.append(fut)
             try:
                 await fut
-            except:
-                # See the similar code in Queue.get.
-                fut.cancel()
-                if self._value > 0 and not fut.cancelled():
-                    self._wake_up_next()
+                # reset _wakeup_scheduled *after* waiting for a future
+                self._wakeup_scheduled = False
+            except exceptions.CancelledError:
+                self._wake_up_next()
                 raise
         self._value -= 1
         return True
index b1eea4bf652118498a0664152d3f87ca1807283d..a360d404395e5b1623b1b1393839b1174afd1865 100644 (file)
@@ -58,7 +58,7 @@ from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
      errorcode
 
 warnings.warn(
-    'The asyncore module is deprecated. '
+    'The asyncore module is deprecated and will be removed in Python 3.12. '
     'The recommended replacement is asyncio',
     DeprecationWarning,
     stacklevel=2)
index b27cbdfed46ffd2e4f2364f00fac61c1132ac2cc..67cc34347bdf7ae427b491a1d7dd2514fec46eb8 100644 (file)
@@ -2171,6 +2171,7 @@ class DocTestCase(unittest.TestCase):
         unittest.TestCase.__init__(self)
         self._dt_optionflags = optionflags
         self._dt_checker = checker
+        self._dt_globs = test.globs.copy()
         self._dt_test = test
         self._dt_setUp = setUp
         self._dt_tearDown = tearDown
@@ -2187,7 +2188,9 @@ class DocTestCase(unittest.TestCase):
         if self._dt_tearDown is not None:
             self._dt_tearDown(test)
 
+        # restore the original globs
         test.globs.clear()
+        test.globs.update(self._dt_globs)
 
     def runTest(self):
         test = self._dt_test
index 4a8c10a379ed827285a6c8b744cdf4a2325a2a11..e00ba4191c41005fb56a75147a2bac90c8d9b2fe 100755 (executable)
@@ -69,6 +69,7 @@ import sys
 import sysconfig
 import time
 import tokenize
+import types
 import urllib.parse
 import warnings
 from collections import deque
@@ -90,13 +91,16 @@ def pathdirs():
             normdirs.append(normdir)
     return dirs
 
+def _isclass(object):
+    return inspect.isclass(object) and not isinstance(object, types.GenericAlias)
+
 def _findclass(func):
     cls = sys.modules.get(func.__module__)
     if cls is None:
         return None
     for name in func.__qualname__.split('.')[:-1]:
         cls = getattr(cls, name)
-    if not inspect.isclass(cls):
+    if not _isclass(cls):
         return None
     return cls
 
@@ -104,7 +108,7 @@ def _finddoc(obj):
     if inspect.ismethod(obj):
         name = obj.__func__.__name__
         self = obj.__self__
-        if (inspect.isclass(self) and
+        if (_isclass(self) and
             getattr(getattr(self, name, None), '__func__') is obj.__func__):
             # classmethod
             cls = self
@@ -118,7 +122,7 @@ def _finddoc(obj):
     elif inspect.isbuiltin(obj):
         name = obj.__name__
         self = obj.__self__
-        if (inspect.isclass(self) and
+        if (_isclass(self) and
             self.__qualname__ + '.' + name == obj.__qualname__):
             # classmethod
             cls = self
@@ -205,7 +209,7 @@ def classname(object, modname):
 
 def isdata(object):
     """Check if an object is of a type that probably means it's data."""
-    return not (inspect.ismodule(object) or inspect.isclass(object) or
+    return not (inspect.ismodule(object) or _isclass(object) or
                 inspect.isroutine(object) or inspect.isframe(object) or
                 inspect.istraceback(object) or inspect.iscode(object))
 
@@ -470,7 +474,7 @@ class Doc:
         # by lacking a __name__ attribute) and an instance.
         try:
             if inspect.ismodule(object): return self.docmodule(*args)
-            if inspect.isclass(object): return self.docclass(*args)
+            if _isclass(object): return self.docclass(*args)
             if inspect.isroutine(object): return self.docroutine(*args)
         except AttributeError:
             pass
@@ -775,7 +779,7 @@ class HTMLDoc(Doc):
         modules = inspect.getmembers(object, inspect.ismodule)
 
         classes, cdict = [], {}
-        for key, value in inspect.getmembers(object, inspect.isclass):
+        for key, value in inspect.getmembers(object, _isclass):
             # if __all__ exists, believe it.  Otherwise use old heuristic.
             if (all is not None or
                 (inspect.getmodule(value) or object) is object):
@@ -1217,7 +1221,7 @@ location listed above.
             result = result + self.section('DESCRIPTION', desc)
 
         classes = []
-        for key, value in inspect.getmembers(object, inspect.isclass):
+        for key, value in inspect.getmembers(object, _isclass):
             # if __all__ exists, believe it.  Otherwise use old heuristic.
             if (all is not None
                 or (inspect.getmodule(value) or object) is object):
@@ -1699,7 +1703,7 @@ def describe(thing):
         return 'member descriptor %s.%s.%s' % (
             thing.__objclass__.__module__, thing.__objclass__.__name__,
             thing.__name__)
-    if inspect.isclass(thing):
+    if _isclass(thing):
         return 'class ' + thing.__name__
     if inspect.isfunction(thing):
         return 'function ' + thing.__name__
@@ -1760,7 +1764,7 @@ def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
         desc += ' in module ' + module.__name__
 
     if not (inspect.ismodule(object) or
-              inspect.isclass(object) or
+              _isclass(object) or
               inspect.isroutine(object) or
               inspect.isdatadescriptor(object) or
               _getdoc(object)):
index ac7d16c346fe3c9614f90389b87f8612146f73d4..76db0426df3318a1e6007c8cfaba61f963ba7f31 100644 (file)
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Autogenerated by Sphinx on Wed Mar 16 11:26:55 2022
+# Autogenerated by Sphinx on Wed Mar 23 20:11:40 2022
 topics = {'assert': 'The "assert" statement\n'
            '**********************\n'
            '\n'
@@ -2418,11 +2418,11 @@ topics = {'assert': 'The "assert" statement\n'
              'resulting\n'
              'object is “compatible” with the exception.  An object is '
              'compatible\n'
-             'with an exception if it is the class or a base class of the '
-             'exception\n'
-             'object, or a tuple containing an item that is the class or a '
+             'with an exception if the object is the class or a *non-virtual '
              'base\n'
-             'class of the exception object.\n'
+             'class* of the exception object, or a tuple containing an item '
+             'that is\n'
+             'the class or a non-virtual base class of the exception object.\n'
              '\n'
              'If no except clause matches the exception, the search for an '
              'exception\n'
@@ -4399,15 +4399,17 @@ topics = {'assert': 'The "assert" statement\n'
                   'on members\n'
                   '   of hashed collections including "set", "frozenset", and '
                   '"dict".\n'
-                  '   "__hash__()" should return an integer. The only required '
-                  'property\n'
-                  '   is that objects which compare equal have the same hash '
-                  'value; it is\n'
-                  '   advised to mix together the hash values of the '
-                  'components of the\n'
-                  '   object that also play a part in comparison of objects by '
-                  'packing\n'
-                  '   them into a tuple and hashing the tuple. Example:\n'
+                  '   The "__hash__()" method should return an integer. The '
+                  'only required\n'
+                  '   property is that objects which compare equal have the '
+                  'same hash\n'
+                  '   value; it is advised to mix together the hash values of '
+                  'the\n'
+                  '   components of the object that also play a part in '
+                  'comparison of\n'
+                  '   objects by packing them into a tuple and hashing the '
+                  'tuple.\n'
+                  '   Example:\n'
                   '\n'
                   '      def __hash__(self):\n'
                   '          return hash((self.name, self.nick, self.color))\n'
@@ -5391,11 +5393,11 @@ topics = {'assert': 'The "assert" statement\n'
                'clause is\n'
                'selected depending on the class of the instance: it must '
                'reference the\n'
-               'class of the instance or a base class thereof.  The instance '
-               'can be\n'
-               'received by the handler and can carry additional information '
-               'about the\n'
-               'exceptional condition.\n'
+               'class of the instance or a *non-virtual base class* thereof. '
+               'The\n'
+               'instance can be received by the handler and can carry '
+               'additional\n'
+               'information about the exceptional condition.\n'
                '\n'
                'Note:\n'
                '\n'
@@ -5730,11 +5732,11 @@ topics = {'assert': 'The "assert" statement\n'
               'clause is\n'
               'selected depending on the class of the instance: it must '
               'reference the\n'
-              'class of the instance or a base class thereof.  The instance '
-              'can be\n'
-              'received by the handler and can carry additional information '
-              'about the\n'
-              'exceptional condition.\n'
+              'class of the instance or a *non-virtual base class* thereof. '
+              'The\n'
+              'instance can be received by the handler and can carry '
+              'additional\n'
+              'information about the exceptional condition.\n'
               '\n'
               'Note:\n'
               '\n'
@@ -9303,15 +9305,17 @@ topics = {'assert': 'The "assert" statement\n'
                  'on members\n'
                  '   of hashed collections including "set", "frozenset", and '
                  '"dict".\n'
-                 '   "__hash__()" should return an integer. The only required '
-                 'property\n'
-                 '   is that objects which compare equal have the same hash '
-                 'value; it is\n'
-                 '   advised to mix together the hash values of the components '
-                 'of the\n'
-                 '   object that also play a part in comparison of objects by '
-                 'packing\n'
-                 '   them into a tuple and hashing the tuple. Example:\n'
+                 '   The "__hash__()" method should return an integer. The '
+                 'only required\n'
+                 '   property is that objects which compare equal have the '
+                 'same hash\n'
+                 '   value; it is advised to mix together the hash values of '
+                 'the\n'
+                 '   components of the object that also play a part in '
+                 'comparison of\n'
+                 '   objects by packing them into a tuple and hashing the '
+                 'tuple.\n'
+                 '   Example:\n'
                  '\n'
                  '      def __hash__(self):\n'
                  '          return hash((self.name, self.nick, self.color))\n'
@@ -12428,10 +12432,10 @@ topics = {'assert': 'The "assert" statement\n'
         'exception.  For an except clause with an expression, that expression\n'
         'is evaluated, and the clause matches the exception if the resulting\n'
         'object is “compatible” with the exception.  An object is compatible\n'
-        'with an exception if it is the class or a base class of the '
-        'exception\n'
-        'object, or a tuple containing an item that is the class or a base\n'
-        'class of the exception object.\n'
+        'with an exception if the object is the class or a *non-virtual base\n'
+        'class* of the exception object, or a tuple containing an item that '
+        'is\n'
+        'the class or a non-virtual base class of the exception object.\n'
         '\n'
         'If no except clause matches the exception, the search for an '
         'exception\n'
index bc4333125100975161b4ad154eac63ddca8c498f..963e0a7689c269fe0998127946ec190cf8d1a1c1 100755 (executable)
@@ -93,7 +93,8 @@ __all__ = [
 ]
 
 warn(
-    'The smtpd module is deprecated and unmaintained.  Please see aiosmtpd '
+    'The smtpd module is deprecated and unmaintained and will be removed '
+    'in Python 3.12.  Please see aiosmtpd '
     '(https://aiosmtpd.readthedocs.io/) for the recommended replacement.',
     DeprecationWarning,
     stacklevel=2)
index 83119168e6376ee83bb41f7b75d2c9a0cd3058d7..53706676e9f7b8ae2dff7ebce28e226d328fd37b 100644 (file)
@@ -807,9 +807,11 @@ def _parse(source, state, verbose, nested, first=False):
                         if not first or subpattern:
                             import warnings
                             warnings.warn(
-                                'Flags not at the start of the expression %r%s' % (
+                                'Flags not at the start of the expression %r%s'
+                                ' but at position %d' % (
                                     source.string[:20],  # truncate long regexes
                                     ' (truncated)' if len(source.string) > 20 else '',
+                                    start,
                                 ),
                                 DeprecationWarning, stacklevel=nested + 6
                             )
index 52cc065da115d9826a905c37a21b9e23d04ec3a5..400a3db5de4d27282cdf347d803bc08e21f6eac0 100644 (file)
@@ -533,7 +533,24 @@ class Regrtest:
 
         if self.ns.use_mp:
             from test.libregrtest.runtest_mp import run_tests_multiprocess
-            run_tests_multiprocess(self)
+            # If we're on windows and this is the parent runner (not a worker),
+            # track the load average.
+            if sys.platform == 'win32' and self.worker_test_name is None:
+                from test.libregrtest.win_utils import WindowsLoadTracker
+
+                try:
+                    self.win_load_tracker = WindowsLoadTracker()
+                except PermissionError as error:
+                    # Standard accounts may not have access to the performance
+                    # counters.
+                    print(f'Failed to create WindowsLoadTracker: {error}')
+
+            try:
+                run_tests_multiprocess(self)
+            finally:
+                if self.win_load_tracker is not None:
+                    self.win_load_tracker.close()
+                    self.win_load_tracker = None
         else:
             self.run_tests_sequential()
 
@@ -695,28 +712,11 @@ class Regrtest:
             self.list_cases()
             sys.exit(0)
 
-        # If we're on windows and this is the parent runner (not a worker),
-        # track the load average.
-        if sys.platform == 'win32' and self.worker_test_name is None:
-            from test.libregrtest.win_utils import WindowsLoadTracker
-
-            try:
-                self.win_load_tracker = WindowsLoadTracker()
-            except FileNotFoundError as error:
-                # Windows IoT Core and Windows Nano Server do not provide
-                # typeperf.exe for x64, x86 or ARM
-                print(f'Failed to create WindowsLoadTracker: {error}')
+        self.run_tests()
+        self.display_result()
 
-        try:
-            self.run_tests()
-            self.display_result()
-
-            if self.ns.verbose2 and self.bad:
-                self.rerun_failed_tests()
-        finally:
-            if self.win_load_tracker is not None:
-                self.win_load_tracker.close()
-                self.win_load_tracker = None
+        if self.ns.verbose2 and self.bad:
+            self.rerun_failed_tests()
 
         self.finalize()
 
index a1cc2201147dbc720b637f03fd5aad098fa63f7d..5736cdfd3c72926630acfa5c465a83fe5392c757 100644 (file)
@@ -1,16 +1,11 @@
+import _overlapped
+import _thread
 import _winapi
 import math
-import msvcrt
-import os
-import subprocess
-import uuid
+import struct
 import winreg
-from test.support import os_helper
-from test.libregrtest.utils import print_warning
 
 
-# Max size of asynchronous reads
-BUFSIZE = 8192
 # Seconds per measurement
 SAMPLING_INTERVAL = 1
 # Exponential damping factor to compute exponentially weighted moving average
@@ -19,174 +14,111 @@ LOAD_FACTOR_1 = 1 / math.exp(SAMPLING_INTERVAL / 60)
 # Initialize the load using the arithmetic mean of the first NVALUE values
 # of the Processor Queue Length
 NVALUE = 5
-# Windows registry subkey of HKEY_LOCAL_MACHINE where the counter names
-# of typeperf are registered
-COUNTER_REGISTRY_KEY = (r"SOFTWARE\Microsoft\Windows NT\CurrentVersion"
-                        r"\Perflib\CurrentLanguage")
 
 
 class WindowsLoadTracker():
     """
-    This class asynchronously interacts with the `typeperf` command to read
-    the system load on Windows. Multiprocessing and threads can't be used
-    here because they interfere with the test suite's cases for those
-    modules.
+    This class asynchronously reads the performance counters to calculate
+    the system load on Windows.  A "raw" thread is used here to prevent
+    interference with the test suite's cases for the threading module.
     """
 
     def __init__(self):
+        # Pre-flight test for access to the performance data;
+        # `PermissionError` will be raised if not allowed
+        winreg.QueryInfoKey(winreg.HKEY_PERFORMANCE_DATA)
+
         self._values = []
         self._load = None
-        self._buffer = ''
-        self._popen = None
-        self.start()
-
-    def start(self):
-        # Create a named pipe which allows for asynchronous IO in Windows
-        pipe_name =  r'\\.\pipe\typeperf_output_' + str(uuid.uuid4())
-
-        open_mode =  _winapi.PIPE_ACCESS_INBOUND
-        open_mode |= _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE
-        open_mode |= _winapi.FILE_FLAG_OVERLAPPED
-
-        # This is the read end of the pipe, where we will be grabbing output
-        self.pipe = _winapi.CreateNamedPipe(
-            pipe_name, open_mode, _winapi.PIPE_WAIT,
-            1, BUFSIZE, BUFSIZE, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL
-        )
-        # The write end of the pipe which is passed to the created process
-        pipe_write_end = _winapi.CreateFile(
-            pipe_name, _winapi.GENERIC_WRITE, 0, _winapi.NULL,
-            _winapi.OPEN_EXISTING, 0, _winapi.NULL
-        )
-        # Open up the handle as a python file object so we can pass it to
-        # subprocess
-        command_stdout = msvcrt.open_osfhandle(pipe_write_end, 0)
-
-        # Connect to the read end of the pipe in overlap/async mode
-        overlap = _winapi.ConnectNamedPipe(self.pipe, overlapped=True)
-        overlap.GetOverlappedResult(True)
-
-        # Spawn off the load monitor
-        counter_name = self._get_counter_name()
-        command = ['typeperf', counter_name, '-si', str(SAMPLING_INTERVAL)]
-        self._popen = subprocess.Popen(' '.join(command),
-                                       stdout=command_stdout,
-                                       cwd=os_helper.SAVEDCWD)
-
-        # Close our copy of the write end of the pipe
-        os.close(command_stdout)
-
-    def _get_counter_name(self):
-        # accessing the registry to get the counter localization name
-        with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, COUNTER_REGISTRY_KEY) as perfkey:
-            counters = winreg.QueryValueEx(perfkey, 'Counter')[0]
-
-        # Convert [key1, value1, key2, value2, ...] list
-        # to {key1: value1, key2: value2, ...} dict
-        counters = iter(counters)
-        counters_dict = dict(zip(counters, counters))
-
-        # System counter has key '2' and Processor Queue Length has key '44'
-        system = counters_dict['2']
-        process_queue_length = counters_dict['44']
-        return f'"\\{system}\\{process_queue_length}"'
-
-    def close(self, kill=True):
-        if self._popen is None:
+        self._running = _overlapped.CreateEvent(None, True, False, None)
+        self._stopped = _overlapped.CreateEvent(None, True, False, None)
+
+        _thread.start_new_thread(self._update_load, (), {})
+
+    def _update_load(self,
+                    # localize module access to prevent shutdown errors
+                     _wait=_winapi.WaitForSingleObject,
+                     _signal=_overlapped.SetEvent):
+        # run until signaled to stop
+        while _wait(self._running, 1000):
+            self._calculate_load()
+        # notify stopped
+        _signal(self._stopped)
+
+    def _calculate_load(self,
+                        # localize module access to prevent shutdown errors
+                        _query=winreg.QueryValueEx,
+                        _hkey=winreg.HKEY_PERFORMANCE_DATA,
+                        _unpack=struct.unpack_from):
+        # get the 'System' object
+        data, _ = _query(_hkey, '2')
+        # PERF_DATA_BLOCK {
+        #   WCHAR Signature[4]      8 +
+        #   DWOWD LittleEndian      4 +
+        #   DWORD Version           4 +
+        #   DWORD Revision          4 +
+        #   DWORD TotalByteLength   4 +
+        #   DWORD HeaderLength      = 24 byte offset
+        #   ...
+        # }
+        obj_start, = _unpack('L', data, 24)
+        # PERF_OBJECT_TYPE {
+        #   DWORD TotalByteLength
+        #   DWORD DefinitionLength
+        #   DWORD HeaderLength
+        #   ...
+        # }
+        data_start, defn_start = _unpack('4xLL', data, obj_start)
+        data_base = obj_start + data_start
+        defn_base = obj_start + defn_start
+        # find the 'Processor Queue Length' counter (index=44)
+        while defn_base < data_base:
+            # PERF_COUNTER_DEFINITION {
+            #   DWORD ByteLength
+            #   DWORD CounterNameTitleIndex
+            #   ... [7 DWORDs/28 bytes]
+            #   DWORD CounterOffset
+            # }
+            size, idx, offset = _unpack('LL28xL', data, defn_base)
+            defn_base += size
+            if idx == 44:
+                counter_offset = data_base + offset
+                # the counter is known to be PERF_COUNTER_RAWCOUNT (DWORD)
+                processor_queue_length, = _unpack('L', data, counter_offset)
+                break
+        else:
             return
 
-        self._load = None
-
-        if kill:
-            self._popen.kill()
-        self._popen.wait()
-        self._popen = None
-
-    def __del__(self):
-        self.close()
-
-    def _parse_line(self, line):
-        # typeperf outputs in a CSV format like this:
-        # "07/19/2018 01:32:26.605","3.000000"
-        # (date, process queue length)
-        tokens = line.split(',')
-        if len(tokens) != 2:
-            raise ValueError
-
-        value = tokens[1]
-        if not value.startswith('"') or not value.endswith('"'):
-            raise ValueError
-        value = value[1:-1]
-        return float(value)
-
-    def _read_lines(self):
-        overlapped, _ = _winapi.ReadFile(self.pipe, BUFSIZE, True)
-        bytes_read, res = overlapped.GetOverlappedResult(False)
-        if res != 0:
-            return ()
-
-        output = overlapped.getbuffer()
-        output = output.decode('oem', 'replace')
-        output = self._buffer + output
-        lines = output.splitlines(True)
-
-        # bpo-36670: typeperf only writes a newline *before* writing a value,
-        # not after. Sometimes, the written line in incomplete (ex: only
-        # timestamp, without the process queue length). Only pass the last line
-        # to the parser if it's a valid value, otherwise store it in
-        # self._buffer.
-        try:
-            self._parse_line(lines[-1])
-        except ValueError:
-            self._buffer = lines.pop(-1)
+        # We use an exponentially weighted moving average, imitating the
+        # load calculation on Unix systems.
+        # https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation
+        # https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
+        if self._load is not None:
+            self._load = (self._load * LOAD_FACTOR_1
+                            + processor_queue_length  * (1.0 - LOAD_FACTOR_1))
+        elif len(self._values) < NVALUE:
+            self._values.append(processor_queue_length)
         else:
-            self._buffer = ''
+            self._load = sum(self._values) / len(self._values)
 
-        return lines
+    def close(self, kill=True):
+        self.__del__()
+        return
+
+    def __del__(self,
+                # localize module access to prevent shutdown errors
+                _wait=_winapi.WaitForSingleObject,
+                _close=_winapi.CloseHandle,
+                _signal=_overlapped.SetEvent):
+        if self._running is not None:
+            # tell the update thread to quit
+            _signal(self._running)
+            # wait for the update thread to signal done
+            _wait(self._stopped, -1)
+            # cleanup events
+            _close(self._running)
+            _close(self._stopped)
+            self._running = self._stopped = None
 
     def getloadavg(self):
-        if self._popen is None:
-            return None
-
-        returncode = self._popen.poll()
-        if returncode is not None:
-            self.close(kill=False)
-            return None
-
-        try:
-            lines = self._read_lines()
-        except BrokenPipeError:
-            self.close()
-            return None
-
-        for line in lines:
-            line = line.rstrip()
-
-            # Ignore the initial header:
-            # "(PDH-CSV 4.0)","\\\\WIN\\System\\Processor Queue Length"
-            if 'PDH-CSV' in line:
-                continue
-
-            # Ignore blank lines
-            if not line:
-                continue
-
-            try:
-                processor_queue_length = self._parse_line(line)
-            except ValueError:
-                print_warning("Failed to parse typeperf output: %a" % line)
-                continue
-
-            # We use an exponentially weighted moving average, imitating the
-            # load calculation on Unix systems.
-            # https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation
-            # https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
-            if self._load is not None:
-                self._load = (self._load * LOAD_FACTOR_1
-                              + processor_queue_length  * (1.0 - LOAD_FACTOR_1))
-            elif len(self._values) < NVALUE:
-                self._values.append(processor_queue_length)
-            else:
-                self._load = sum(self._values) / len(self._values)
-
         return self._load
index 9c1fff5c2f2c1491d676e7ce75c2752497a64b71..f9bc4b89d3d0a46086d12c2cf1481eb26587ab3b 100644 (file)
@@ -1,5 +1,8 @@
 """This is a test module for test_pydoc"""
 
+import types
+import typing
+
 __author__ = "Benjamin Peterson"
 __credits__ = "Nobody"
 __version__ = "1.2.3.4"
@@ -24,6 +27,8 @@ class C(object):
     def is_it_true(self):
         """ Return self.get_answer() """
         return self.get_answer()
+    def __class_getitem__(self, item):
+        return types.GenericAlias(self, item)
 
 def doc_func():
     """
@@ -35,3 +40,10 @@ def doc_func():
 
 def nodoc_func():
     pass
+
+
+list_alias1 = typing.List[int]
+list_alias2 = list[int]
+c_alias = C[int]
+type_union1 = typing.Union[int, str]
+type_union2 = int | str
diff --git a/Lib/test/test_asyncio/test_asyncio_waitfor.py b/Lib/test/test_asyncio/test_asyncio_waitfor.py
deleted file mode 100644 (file)
index 2ca64ab..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-import asyncio
-import unittest
-import time
-
-def tearDownModule():
-    asyncio.set_event_loop_policy(None)
-
-
-class SlowTask:
-    """ Task will run for this defined time, ignoring cancel requests """
-    TASK_TIMEOUT = 0.2
-
-    def __init__(self):
-        self.exited = False
-
-    async def run(self):
-        exitat = time.monotonic() + self.TASK_TIMEOUT
-
-        while True:
-            tosleep = exitat - time.monotonic()
-            if tosleep <= 0:
-                break
-
-            try:
-                await asyncio.sleep(tosleep)
-            except asyncio.CancelledError:
-                pass
-
-        self.exited = True
-
-class AsyncioWaitForTest(unittest.TestCase):
-
-    async def atest_asyncio_wait_for_cancelled(self):
-        t  = SlowTask()
-
-        waitfortask = asyncio.create_task(asyncio.wait_for(t.run(), t.TASK_TIMEOUT * 2))
-        await asyncio.sleep(0)
-        waitfortask.cancel()
-        await asyncio.wait({waitfortask})
-
-        self.assertTrue(t.exited)
-
-    def test_asyncio_wait_for_cancelled(self):
-        asyncio.run(self.atest_asyncio_wait_for_cancelled())
-
-    async def atest_asyncio_wait_for_timeout(self):
-        t  = SlowTask()
-
-        try:
-            await asyncio.wait_for(t.run(), t.TASK_TIMEOUT / 2)
-        except asyncio.TimeoutError:
-            pass
-
-        self.assertTrue(t.exited)
-
-    def test_asyncio_wait_for_timeout(self):
-        asyncio.run(self.atest_asyncio_wait_for_timeout())
-
-
-if __name__ == '__main__':
-    unittest.main()
index e2cd2ba0365fdaf7b1ae47dd54c6f4bf58ad0406..c5e3fdcbc955a5c837a6636949020365b187469f 100644 (file)
@@ -933,6 +933,32 @@ class SemaphoreTests(unittest.IsolatedAsyncioTestCase):
         sem.release()
         self.assertFalse(sem.locked())
 
+    async def test_acquire_fifo_order(self):
+        sem = asyncio.Semaphore(1)
+        result = []
+
+        async def coro(tag):
+            await sem.acquire()
+            result.append(f'{tag}_1')
+            await asyncio.sleep(0.01)
+            sem.release()
+
+            await sem.acquire()
+            result.append(f'{tag}_2')
+            await asyncio.sleep(0.01)
+            sem.release()
+
+        t1 = asyncio.create_task(coro('c1'))
+        t2 = asyncio.create_task(coro('c2'))
+        t3 = asyncio.create_task(coro('c3'))
+
+        await asyncio.gather(t1, t2, t3)
+
+        self.assertEqual(
+            ['c1_1', 'c2_1', 'c3_1', 'c1_2', 'c2_2', 'c3_2'],
+            result
+        )
+
 
 if __name__ == '__main__':
     unittest.main()
index 398b143d2d0c6601d0612434076ffafd6e4aae18..0007b44a220c475a13c6a07dfd3b8fc16ce08918 100644 (file)
@@ -98,12 +98,6 @@ class CoroLikeObject:
         return self
 
 
-# The following value can be used as a very small timeout:
-# it passes check "timeout > 0", but has almost
-# no effect on the test performance
-_EPSILON = 0.0001
-
-
 class BaseTaskTests:
 
     Task = None
@@ -121,7 +115,6 @@ class BaseTaskTests:
         self.loop.set_task_factory(self.new_task)
         self.loop.create_future = lambda: self.new_future(self.loop)
 
-
     def test_generic_alias(self):
         task = self.__class__.Task[str]
         self.assertEqual(task.__args__, (str,))
@@ -1031,251 +1024,6 @@ class BaseTaskTests:
             task._log_traceback = True
         self.loop.run_until_complete(task)
 
-    def test_wait_for_timeout_less_then_0_or_0_future_done(self):
-        def gen():
-            when = yield
-            self.assertAlmostEqual(0, when)
-
-        loop = self.new_test_loop(gen)
-
-        fut = self.new_future(loop)
-        fut.set_result('done')
-
-        ret = loop.run_until_complete(asyncio.wait_for(fut, 0))
-
-        self.assertEqual(ret, 'done')
-        self.assertTrue(fut.done())
-        self.assertAlmostEqual(0, loop.time())
-
-    def test_wait_for_timeout_less_then_0_or_0_coroutine_do_not_started(self):
-        def gen():
-            when = yield
-            self.assertAlmostEqual(0, when)
-
-        loop = self.new_test_loop(gen)
-
-        foo_started = False
-
-        async def foo():
-            nonlocal foo_started
-            foo_started = True
-
-        with self.assertRaises(asyncio.TimeoutError):
-            loop.run_until_complete(asyncio.wait_for(foo(), 0))
-
-        self.assertAlmostEqual(0, loop.time())
-        self.assertEqual(foo_started, False)
-
-    def test_wait_for_timeout_less_then_0_or_0(self):
-        def gen():
-            when = yield
-            self.assertAlmostEqual(0.2, when)
-            when = yield 0
-            self.assertAlmostEqual(0, when)
-
-        for timeout in [0, -1]:
-            with self.subTest(timeout=timeout):
-                loop = self.new_test_loop(gen)
-
-                foo_running = None
-
-                async def foo():
-                    nonlocal foo_running
-                    foo_running = True
-                    try:
-                        await asyncio.sleep(0.2)
-                    finally:
-                        foo_running = False
-                    return 'done'
-
-                fut = self.new_task(loop, foo())
-
-                with self.assertRaises(asyncio.TimeoutError):
-                    loop.run_until_complete(asyncio.wait_for(fut, timeout))
-                self.assertTrue(fut.done())
-                # it should have been cancelled due to the timeout
-                self.assertTrue(fut.cancelled())
-                self.assertAlmostEqual(0, loop.time())
-                self.assertEqual(foo_running, False)
-
-    def test_wait_for(self):
-
-        def gen():
-            when = yield
-            self.assertAlmostEqual(0.2, when)
-            when = yield 0
-            self.assertAlmostEqual(0.1, when)
-            when = yield 0.1
-
-        loop = self.new_test_loop(gen)
-
-        foo_running = None
-
-        async def foo():
-            nonlocal foo_running
-            foo_running = True
-            try:
-                await asyncio.sleep(0.2)
-            finally:
-                foo_running = False
-            return 'done'
-
-        fut = self.new_task(loop, foo())
-
-        with self.assertRaises(asyncio.TimeoutError):
-            loop.run_until_complete(asyncio.wait_for(fut, 0.1))
-        self.assertTrue(fut.done())
-        # it should have been cancelled due to the timeout
-        self.assertTrue(fut.cancelled())
-        self.assertAlmostEqual(0.1, loop.time())
-        self.assertEqual(foo_running, False)
-
-    def test_wait_for_blocking(self):
-        loop = self.new_test_loop()
-
-        async def coro():
-            return 'done'
-
-        res = loop.run_until_complete(asyncio.wait_for(coro(), timeout=None))
-        self.assertEqual(res, 'done')
-
-    def test_wait_for_race_condition(self):
-
-        def gen():
-            yield 0.1
-            yield 0.1
-            yield 0.1
-
-        loop = self.new_test_loop(gen)
-
-        fut = self.new_future(loop)
-        task = asyncio.wait_for(fut, timeout=0.2)
-        loop.call_later(0.1, fut.set_result, "ok")
-        res = loop.run_until_complete(task)
-        self.assertEqual(res, "ok")
-
-    def test_wait_for_cancellation_race_condition(self):
-        async def inner():
-            with contextlib.suppress(asyncio.CancelledError):
-                await asyncio.sleep(1)
-            return 1
-
-        async def main():
-            result = await asyncio.wait_for(inner(), timeout=.01)
-            self.assertEqual(result, 1)
-
-        asyncio.run(main())
-
-    def test_wait_for_waits_for_task_cancellation(self):
-        loop = asyncio.new_event_loop()
-        self.addCleanup(loop.close)
-
-        task_done = False
-
-        async def foo():
-            async def inner():
-                nonlocal task_done
-                try:
-                    await asyncio.sleep(0.2)
-                except asyncio.CancelledError:
-                    await asyncio.sleep(_EPSILON)
-                    raise
-                finally:
-                    task_done = True
-
-            inner_task = self.new_task(loop, inner())
-
-            await asyncio.wait_for(inner_task, timeout=_EPSILON)
-
-        with self.assertRaises(asyncio.TimeoutError) as cm:
-            loop.run_until_complete(foo())
-
-        self.assertTrue(task_done)
-        chained = cm.exception.__context__
-        self.assertEqual(type(chained), asyncio.CancelledError)
-
-    def test_wait_for_waits_for_task_cancellation_w_timeout_0(self):
-        loop = asyncio.new_event_loop()
-        self.addCleanup(loop.close)
-
-        task_done = False
-
-        async def foo():
-            async def inner():
-                nonlocal task_done
-                try:
-                    await asyncio.sleep(10)
-                except asyncio.CancelledError:
-                    await asyncio.sleep(_EPSILON)
-                    raise
-                finally:
-                    task_done = True
-
-            inner_task = self.new_task(loop, inner())
-            await asyncio.sleep(_EPSILON)
-            await asyncio.wait_for(inner_task, timeout=0)
-
-        with self.assertRaises(asyncio.TimeoutError) as cm:
-            loop.run_until_complete(foo())
-
-        self.assertTrue(task_done)
-        chained = cm.exception.__context__
-        self.assertEqual(type(chained), asyncio.CancelledError)
-
-    def test_wait_for_reraises_exception_during_cancellation(self):
-        loop = asyncio.new_event_loop()
-        self.addCleanup(loop.close)
-
-        class FooException(Exception):
-            pass
-
-        async def foo():
-            async def inner():
-                try:
-                    await asyncio.sleep(0.2)
-                finally:
-                    raise FooException
-
-            inner_task = self.new_task(loop, inner())
-
-            await asyncio.wait_for(inner_task, timeout=_EPSILON)
-
-        with self.assertRaises(FooException):
-            loop.run_until_complete(foo())
-
-    def test_wait_for_self_cancellation(self):
-        loop = asyncio.new_event_loop()
-        self.addCleanup(loop.close)
-
-        async def foo():
-            async def inner():
-                try:
-                    await asyncio.sleep(0.3)
-                except asyncio.CancelledError:
-                    try:
-                        await asyncio.sleep(0.3)
-                    except asyncio.CancelledError:
-                        await asyncio.sleep(0.3)
-
-                return 42
-
-            inner_task = self.new_task(loop, inner())
-
-            wait = asyncio.wait_for(inner_task, timeout=0.1)
-
-            # Test that wait_for itself is properly cancellable
-            # even when the initial task holds up the initial cancellation.
-            task = self.new_task(loop, wait)
-            await asyncio.sleep(0.2)
-            task.cancel()
-
-            with self.assertRaises(asyncio.CancelledError):
-                await task
-
-            self.assertEqual(await inner_task, 42)
-
-        loop.run_until_complete(foo())
-
     def test_wait(self):
 
         def gen():
@@ -2544,32 +2292,6 @@ class BaseTaskTests:
                           'test_task_source_traceback'))
         self.loop.run_until_complete(task)
 
-    def _test_cancel_wait_for(self, timeout):
-        loop = asyncio.new_event_loop()
-        self.addCleanup(loop.close)
-
-        async def blocking_coroutine():
-            fut = self.new_future(loop)
-            # Block: fut result is never set
-            await fut
-
-        task = loop.create_task(blocking_coroutine())
-
-        wait = loop.create_task(asyncio.wait_for(task, timeout))
-        loop.call_soon(wait.cancel)
-
-        self.assertRaises(asyncio.CancelledError,
-                          loop.run_until_complete, wait)
-
-        # Python issue #23219: cancelling the wait must also cancel the task
-        self.assertTrue(task.cancelled())
-
-    def test_cancel_blocking_wait_for(self):
-        self._test_cancel_wait_for(None)
-
-    def test_cancel_wait_for(self):
-        self._test_cancel_wait_for(60.0)
-
     def test_cancel_gather_1(self):
         """Ensure that a gathering future refuses to be cancelled once all
         children are done"""
diff --git a/Lib/test/test_asyncio/test_waitfor.py b/Lib/test/test_asyncio/test_waitfor.py
new file mode 100644 (file)
index 0000000..45498fa
--- /dev/null
@@ -0,0 +1,294 @@
+import asyncio
+import unittest
+import time
+
+
+def tearDownModule():
+    asyncio.set_event_loop_policy(None)
+
+
+# The following value can be used as a very small timeout:
+# it passes check "timeout > 0", but has almost
+# no effect on the test performance
+_EPSILON = 0.0001
+
+
+class SlowTask:
+    """ Task will run for this defined time, ignoring cancel requests """
+    TASK_TIMEOUT = 0.2
+
+    def __init__(self):
+        self.exited = False
+
+    async def run(self):
+        exitat = time.monotonic() + self.TASK_TIMEOUT
+
+        while True:
+            tosleep = exitat - time.monotonic()
+            if tosleep <= 0:
+                break
+
+            try:
+                await asyncio.sleep(tosleep)
+            except asyncio.CancelledError:
+                pass
+
+        self.exited = True
+
+
+class AsyncioWaitForTest(unittest.IsolatedAsyncioTestCase):
+
+    async def test_asyncio_wait_for_cancelled(self):
+        t = SlowTask()
+
+        waitfortask = asyncio.create_task(
+            asyncio.wait_for(t.run(), t.TASK_TIMEOUT * 2))
+        await asyncio.sleep(0)
+        waitfortask.cancel()
+        await asyncio.wait({waitfortask})
+
+        self.assertTrue(t.exited)
+
+    async def test_asyncio_wait_for_timeout(self):
+        t = SlowTask()
+
+        try:
+            await asyncio.wait_for(t.run(), t.TASK_TIMEOUT / 2)
+        except asyncio.TimeoutError:
+            pass
+
+        self.assertTrue(t.exited)
+
+    async def test_wait_for_timeout_less_then_0_or_0_future_done(self):
+        loop = asyncio.get_running_loop()
+
+        fut = loop.create_future()
+        fut.set_result('done')
+
+        t0 = loop.time()
+        ret = await asyncio.wait_for(fut, 0)
+        t1 = loop.time()
+
+        self.assertEqual(ret, 'done')
+        self.assertTrue(fut.done())
+        self.assertLess(t1 - t0, 0.1)
+
+    async def test_wait_for_timeout_less_then_0_or_0_coroutine_do_not_started(self):
+        loop = asyncio.get_running_loop()
+
+        foo_started = False
+
+        async def foo():
+            nonlocal foo_started
+            foo_started = True
+
+        with self.assertRaises(asyncio.TimeoutError):
+            t0 = loop.time()
+            await asyncio.wait_for(foo(), 0)
+        t1 = loop.time()
+
+        self.assertEqual(foo_started, False)
+        self.assertLess(t1 - t0, 0.1)
+
+    async def test_wait_for_timeout_less_then_0_or_0(self):
+        loop = asyncio.get_running_loop()
+
+        for timeout in [0, -1]:
+            with self.subTest(timeout=timeout):
+                foo_running = None
+                started = loop.create_future()
+
+                async def foo():
+                    nonlocal foo_running
+                    foo_running = True
+                    started.set_result(None)
+                    try:
+                        await asyncio.sleep(10)
+                    finally:
+                        foo_running = False
+                    return 'done'
+
+                fut = asyncio.create_task(foo())
+                await started
+
+                with self.assertRaises(asyncio.TimeoutError):
+                    t0 = loop.time()
+                    await asyncio.wait_for(fut, timeout)
+                t1 = loop.time()
+
+                self.assertTrue(fut.done())
+                # it should have been cancelled due to the timeout
+                self.assertTrue(fut.cancelled())
+                self.assertEqual(foo_running, False)
+                self.assertLess(t1 - t0, 0.1)
+
+    async def test_wait_for(self):
+        loop = asyncio.get_running_loop()
+        foo_running = None
+
+        async def foo():
+            nonlocal foo_running
+            foo_running = True
+            try:
+                await asyncio.sleep(10)
+            finally:
+                foo_running = False
+            return 'done'
+
+        fut = asyncio.create_task(foo())
+
+        with self.assertRaises(asyncio.TimeoutError):
+            t0 = loop.time()
+            await asyncio.wait_for(fut, 0.1)
+        t1 = loop.time()
+        self.assertTrue(fut.done())
+        # it should have been cancelled due to the timeout
+        self.assertTrue(fut.cancelled())
+        self.assertLess(t1 - t0, 0.5)
+        self.assertEqual(foo_running, False)
+
+    async def test_wait_for_blocking(self):
+        async def coro():
+            return 'done'
+
+        res = await asyncio.wait_for(coro(), timeout=None)
+        self.assertEqual(res, 'done')
+
+    async def test_wait_for_race_condition(self):
+        loop = asyncio.get_running_loop()
+
+        fut = loop.create_future()
+        task = asyncio.wait_for(fut, timeout=0.2)
+        loop.call_later(0.1, fut.set_result, "ok")
+        res = await task
+        self.assertEqual(res, "ok")
+
+    async def test_wait_for_cancellation_race_condition(self):
+        async def inner():
+            with self.assertRaises(asyncio.CancelledError):
+                await asyncio.sleep(1)
+            return 1
+
+        result = await asyncio.wait_for(inner(), timeout=.01)
+        self.assertEqual(result, 1)
+
+    async def test_wait_for_waits_for_task_cancellation(self):
+        task_done = False
+
+        async def inner():
+            nonlocal task_done
+            try:
+                await asyncio.sleep(10)
+            except asyncio.CancelledError:
+                await asyncio.sleep(_EPSILON)
+                raise
+            finally:
+                task_done = True
+
+        inner_task = asyncio.create_task(inner())
+
+        with self.assertRaises(asyncio.TimeoutError) as cm:
+            await asyncio.wait_for(inner_task, timeout=_EPSILON)
+
+        self.assertTrue(task_done)
+        chained = cm.exception.__context__
+        self.assertEqual(type(chained), asyncio.CancelledError)
+
+    async def test_wait_for_waits_for_task_cancellation_w_timeout_0(self):
+        task_done = False
+
+        async def foo():
+            async def inner():
+                nonlocal task_done
+                try:
+                    await asyncio.sleep(10)
+                except asyncio.CancelledError:
+                    await asyncio.sleep(_EPSILON)
+                    raise
+                finally:
+                    task_done = True
+
+            inner_task = asyncio.create_task(inner())
+            await asyncio.sleep(_EPSILON)
+            await asyncio.wait_for(inner_task, timeout=0)
+
+        with self.assertRaises(asyncio.TimeoutError) as cm:
+            await foo()
+
+        self.assertTrue(task_done)
+        chained = cm.exception.__context__
+        self.assertEqual(type(chained), asyncio.CancelledError)
+
+    async def test_wait_for_reraises_exception_during_cancellation(self):
+        class FooException(Exception):
+            pass
+
+        async def foo():
+            async def inner():
+                try:
+                    await asyncio.sleep(0.2)
+                finally:
+                    raise FooException
+
+            inner_task = asyncio.create_task(inner())
+
+            await asyncio.wait_for(inner_task, timeout=_EPSILON)
+
+        with self.assertRaises(FooException):
+            await foo()
+
+    async def test_wait_for_self_cancellation(self):
+        async def inner():
+            try:
+                await asyncio.sleep(0.3)
+            except asyncio.CancelledError:
+                try:
+                    await asyncio.sleep(0.3)
+                except asyncio.CancelledError:
+                    await asyncio.sleep(0.3)
+
+            return 42
+
+        inner_task = asyncio.create_task(inner())
+
+        wait = asyncio.wait_for(inner_task, timeout=0.1)
+
+        # Test that wait_for itself is properly cancellable
+        # even when the initial task holds up the initial cancellation.
+        task = asyncio.create_task(wait)
+        await asyncio.sleep(0.2)
+        task.cancel()
+
+        with self.assertRaises(asyncio.CancelledError):
+            await task
+
+        self.assertEqual(await inner_task, 42)
+
+    async def _test_cancel_wait_for(self, timeout):
+        loop = asyncio.get_running_loop()
+
+        async def blocking_coroutine():
+            fut = loop.create_future()
+            # Block: fut result is never set
+            await fut
+
+        task = asyncio.create_task(blocking_coroutine())
+
+        wait = asyncio.create_task(asyncio.wait_for(task, timeout))
+        loop.call_soon(wait.cancel)
+
+        with self.assertRaises(asyncio.CancelledError):
+            await wait
+
+        # Python issue #23219: cancelling the wait must also cancel the task
+        self.assertTrue(task.cancelled())
+
+    async def test_cancel_blocking_wait_for(self):
+        await self._test_cancel_wait_for(None)
+
+    async def test_cancel_wait_for(self):
+        await self._test_cancel_wait_for(60.0)
+
+
+if __name__ == '__main__':
+    unittest.main()
index 4d1bf2cce1f1e3274351502f67234253df8ca853..13d4e67e586e98137c97b8077d33f696b8d4a919 100644 (file)
@@ -4,7 +4,7 @@ import unittest
 import binascii
 import array
 import re
-from test.support import warnings_helper
+from test.support import bigmemtest, _1G, _4G, warnings_helper
 
 
 # Note: "*_hex" functions are aliases for "(un)hexlify"
@@ -449,6 +449,14 @@ class BytearrayBinASCIITest(BinASCIITest):
 class MemoryviewBinASCIITest(BinASCIITest):
     type2test = memoryview
 
+class ChecksumBigBufferTestCase(unittest.TestCase):
+    """bpo-38256 - check that inputs >=4 GiB are handled correctly."""
+
+    @bigmemtest(size=_4G + 4, memuse=1, dry_run=False)
+    def test_big_buffer(self, size):
+        data = b"nyan" * (_1G + 1)
+        self.assertEqual(binascii.crc32(data), 1044521549)
+
 
 if __name__ == "__main__":
     unittest.main()
index d93e98f372532f00257357d6fe1271912af29ee2..d299f766dc500b1efb9954ea54991509acdedbf2 100644 (file)
@@ -137,6 +137,17 @@ class CmdLineTest(unittest.TestCase):
         self.assertTrue(data.find(b'1 loop') != -1)
         self.assertTrue(data.find(b'__main__.Timer') != -1)
 
+    def test_relativedir_bug46421(self):
+        # Test `python -m unittest` with a relative directory beginning with ./
+        # Note: We have to switch to the project's top module's directory, as per
+        # the python unittest wiki. We will switch back when we are done.
+        defaultwd = os.getcwd()
+        projectlibpath = os.path.dirname(__file__).removesuffix("test")
+        with os_helper.change_cwd(projectlibpath):
+            # Testing with and without ./
+            assert_python_ok('-m', 'unittest', "test/test_longexp.py")
+            assert_python_ok('-m', 'unittest', "./test/test_longexp.py")
+
     def test_run_code(self):
         # Test expected operation of the '-c' switch
         # Switch needs an argument
index 9703f871ad640c38761ba3c1d931894614380886..1098a7b9f471f0e25d7ca8009445ffd06063016c 100644 (file)
@@ -3126,6 +3126,22 @@ def test_no_trailing_whitespace_stripping():
     """
 
 
+def test_run_doctestsuite_multiple_times():
+    """
+    It was not possible to run the same DocTestSuite multiple times
+    http://bugs.python.org/issue2604
+    http://bugs.python.org/issue9736
+
+    >>> import unittest
+    >>> import test.sample_doctest
+    >>> suite = doctest.DocTestSuite(test.sample_doctest)
+    >>> suite.run(unittest.TestResult())
+    <unittest.result.TestResult run=9 errors=0 failures=4>
+    >>> suite.run(unittest.TestResult())
+    <unittest.result.TestResult run=9 errors=0 failures=4>
+    """
+
+
 def load_tests(loader, tests, pattern):
     tests.addTest(doctest.DocTestSuite(doctest))
     tests.addTest(doctest.DocTestSuite())
index 44c16989716a0dd51d408dd880b2e40e1bf00300..bd37ab9d3324ed9d627307f005bd836e6111637b 100644 (file)
@@ -95,6 +95,11 @@ CLASSES
      |  say_no(self)
      |\x20\x20
      |  ----------------------------------------------------------------------
+     |  Class methods defined here:
+     |\x20\x20
+     |  __class_getitem__(item) from builtins.type
+     |\x20\x20
+     |  ----------------------------------------------------------------------
      |  Data descriptors defined here:
      |\x20\x20
      |  __dict__
@@ -114,6 +119,11 @@ FUNCTIONS
 
 DATA
     __xyz__ = 'X, Y and Z'
+    c_alias = test.pydoc_mod.C[int]
+    list_alias1 = typing.List[int]
+    list_alias2 = list[int]
+    type_union1 = typing.Union[int, str]
+    type_union2 = int | str
 
 VERSION
     1.2.3.4
@@ -141,6 +151,15 @@ expected_html_pattern = """
     <p><tt>This&nbsp;is&nbsp;a&nbsp;test&nbsp;module&nbsp;for&nbsp;test_pydoc</tt></p>
 <p>
 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+\x20\x20\x20\x20
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%%"><table width="100%%" summary="list"><tr><td width="25%%" valign=top><a href="types.html">types</a><br>
+</td><td width="25%%" valign=top><a href="typing.html">typing</a><br>
+</td><td width="25%%" valign=top></td><td width="25%%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
 <tr bgcolor="#ee77aa">
 <td colspan=3 valign=bottom>&nbsp;<br>
 <font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
@@ -210,6 +229,10 @@ Data and other attributes defined here:<br>
 
 <dl><dt><a name="C-say_no"><strong>say_no</strong></a>(self)</dt></dl>
 
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="C-__class_getitem__"><strong>__class_getitem__</strong></a>(item)<font color="#909090"><font face="helvetica, arial"> from <a href="builtins.html#type">builtins.type</a></font></font></dt></dl>
+
 <hr>
 Data descriptors defined here:<br>
 <dl><dt><strong>__dict__</strong></dt>
@@ -237,7 +260,12 @@ war</tt></dd></dl>
 <font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
 \x20\x20\x20\x20
 <tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
-<td width="100%%"><strong>__xyz__</strong> = 'X, Y and Z'</td></tr></table><p>
+<td width="100%%"><strong>__xyz__</strong> = 'X, Y and Z'<br>
+<strong>c_alias</strong> = test.pydoc_mod.C[int]<br>
+<strong>list_alias1</strong> = typing.List[int]<br>
+<strong>list_alias2</strong> = list[int]<br>
+<strong>type_union1</strong> = typing.Union[int, str]<br>
+<strong>type_union2</strong> = int | str</td></tr></table><p>
 <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
 <tr bgcolor="#7799ee">
 <td colspan=3 valign=bottom>&nbsp;<br>
@@ -1048,6 +1076,43 @@ class TestDescriptions(unittest.TestCase):
         expected = 'C in module %s object' % __name__
         self.assertIn(expected, pydoc.render_doc(c))
 
+    def test_generic_alias(self):
+        self.assertEqual(pydoc.describe(typing.List[int]), '_GenericAlias')
+        doc = pydoc.render_doc(typing.List[int], renderer=pydoc.plaintext)
+        self.assertIn('_GenericAlias in module typing', doc)
+        self.assertIn('List = class list(object)', doc)
+        self.assertIn(list.__doc__.strip().splitlines()[0], doc)
+
+        self.assertEqual(pydoc.describe(list[int]), 'GenericAlias')
+        doc = pydoc.render_doc(list[int], renderer=pydoc.plaintext)
+        self.assertIn('GenericAlias in module builtins', doc)
+        self.assertIn('\nclass list(object)', doc)
+        self.assertIn(list.__doc__.strip().splitlines()[0], doc)
+
+    def test_union_type(self):
+        self.assertEqual(pydoc.describe(typing.Union[int, str]), '_UnionGenericAlias')
+        doc = pydoc.render_doc(typing.Union[int, str], renderer=pydoc.plaintext)
+        self.assertIn('_UnionGenericAlias in module typing', doc)
+        self.assertIn('Union = typing.Union', doc)
+        if typing.Union.__doc__:
+            self.assertIn(typing.Union.__doc__.strip().splitlines()[0], doc)
+
+        self.assertEqual(pydoc.describe(int | str), 'UnionType')
+        doc = pydoc.render_doc(int | str, renderer=pydoc.plaintext)
+        self.assertIn('UnionType in module types object', doc)
+        self.assertIn('\nclass UnionType(builtins.object)', doc)
+        self.assertIn(types.UnionType.__doc__.strip().splitlines()[0], doc)
+
+    def test_special_form(self):
+        self.assertEqual(pydoc.describe(typing.Any), '_SpecialForm')
+        doc = pydoc.render_doc(typing.Any, renderer=pydoc.plaintext)
+        self.assertIn('_SpecialForm in module typing', doc)
+        if typing.Any.__doc__:
+            self.assertIn('Any = typing.Any', doc)
+            self.assertIn(typing.Any.__doc__.strip().splitlines()[0], doc)
+        else:
+            self.assertIn('Any = class _SpecialForm(_Final)', doc)
+
     def test_typing_pydoc(self):
         def foo(data: typing.List[typing.Any],
                 x: int) -> typing.Iterator[typing.Tuple[int, typing.Any]]:
index 588cc7930c327c29d0da7fe3671204d19c26c04e..3d0637817da9847d2bc8451464dd2d4aa82b972c 100644 (file)
@@ -1444,7 +1444,8 @@ class ReTests(unittest.TestCase):
             self.assertTrue(re.match(p, lower_char))
         self.assertEqual(
             str(warns.warnings[0].message),
-            'Flags not at the start of the expression %r' % p
+            'Flags not at the start of the expression %r'
+            ' but at position 1' % p
         )
         self.assertEqual(warns.warnings[0].filename, __file__)
 
@@ -1453,7 +1454,8 @@ class ReTests(unittest.TestCase):
             self.assertTrue(re.match(p, lower_char))
         self.assertEqual(
             str(warns.warnings[0].message),
-            'Flags not at the start of the expression %r (truncated)' % p[:20]
+            'Flags not at the start of the expression %r (truncated)'
+            ' but at position 1' % p[:20]
         )
         self.assertEqual(warns.warnings[0].filename, __file__)
 
@@ -1465,7 +1467,8 @@ class ReTests(unittest.TestCase):
                 self.assertTrue(re.match(p, b'a'))
             self.assertEqual(
                 str(warns.warnings[0].message),
-                'Flags not at the start of the expression %r' % p
+                'Flags not at the start of the expression %r'
+                ' but at position 1' % p
             )
             self.assertEqual(warns.warnings[0].filename, __file__)
 
index cc227e579679b739d7a8c14167c64b57427021ae..c0b92bf3b1921b0373debc93ebe4abd8666bebb8 100644 (file)
@@ -800,7 +800,7 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase):
         self.checkEnumParam(widget, 'activestyle',
                             'dotbox', 'none', 'underline')
 
-    test_justify = requires_tcl(8, 6, 5)(StandardOptionsTests.test_configure_justify)
+    test_configure_justify = requires_tcl(8, 6, 5)(StandardOptionsTests.test_configure_justify)
 
     def test_configure_listvariable(self):
         widget = self.create()
@@ -939,7 +939,7 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
 
     def test_configure_from(self):
         widget = self.create()
-        conv = False if get_tk_patchlevel() >= (8, 6, 10) else float_round
+        conv = float if get_tk_patchlevel() >= (8, 6, 10) else float_round
         self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=conv)
 
     def test_configure_label(self):
index a33c24ac55beefab7f50c18740abb32b15099a0f..54ad3437168fe1195e70f6b05746072248d79786 100644 (file)
@@ -4,7 +4,7 @@ import tkinter
 from tkinter import ttk
 from test import support
 from test.support import requires
-from tkinter.test.support import AbstractTkTest
+from tkinter.test.support import AbstractTkTest, get_tk_patchlevel
 
 requires('gui')
 
@@ -170,6 +170,8 @@ class StyleTest(AbstractTkTest, unittest.TestCase):
                     newname = f'C.{name}'
                     self.assertEqual(style.map(newname), {})
                     style.map(newname, **default)
+                    if theme == 'alt' and name == '.' and get_tk_patchlevel() < (8, 6, 1):
+                        default['embossed'] = [('disabled', '1')]
                     self.assertEqual(style.map(newname), default)
                     for key, value in default.items():
                         self.assertEqual(style.map(newname, key), value)
index e62469aa2a170f2bc1894adc232cf46cdeb2b4d9..88a188c545cd073acef54789fe07ca9875c5cf27 100644 (file)
@@ -39,7 +39,7 @@ def _convert_name(name):
             name = rel_path
         # on Windows both '\' and '/' are used as path
         # separators. Better to replace both than rely on os.path.sep
-        return name[:-3].replace('\\', '.').replace('/', '.')
+        return os.path.normpath(name)[:-3].replace('\\', '.').replace('/', '.')
     return name
 
 def _convert_names(names):
index 67cfdfb6aafc45e029f7d36873e9ffd69dec9266..34d2fa4b8642223a932347403317f652b23df83b 100644 (file)
@@ -721,7 +721,9 @@ class _SharedFile:
         self._lock = lock
         self._writing = writing
         self.seekable = file.seekable
-        self.tell = file.tell
+
+    def tell(self):
+        return self._pos
 
     def seek(self, offset, whence=0):
         with self._lock:
index 7668caf43bc3682b00a7e46648d826fffefe18c2..1f1364e4f0bb87138a226eb1c0c5bbb02b64cb85 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1983,6 +1983,7 @@ Masazumi Yoshikawa
 Arnaud Ysmal
 Bernard Yue
 Moshe Zadka
+Bader Zaidan
 Elias Zamaria
 Milan Zamazal
 Artur Zaprzala
index 919d2408f706ba318e19c97f91a4ecbd7d3bd2e0..474c5299613ffec4ef536012f34602a7ef09c5d1 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -2,6 +2,59 @@
 Python News
 +++++++++++
 
+What's New in Python 3.10.4 final?
+==================================
+
+*Release date: 2022-03-23*
+
+Core and Builtins
+-----------------
+
+- bpo-46968: Check for the existence of the "sys/auxv.h" header in
+  :mod:`faulthandler` to avoid compilation problems in systems where this
+  header doesn't exist. Patch by Pablo Galindo
+
+Library
+-------
+
+- bpo-23691: Protect the :func:`re.finditer` iterator from re-entering.
+
+- bpo-42369: Fix thread safety of :meth:`zipfile._SharedFile.tell` to avoid
+  a "zipfile.BadZipFile: Bad CRC-32 for file" exception when reading a
+  :class:`ZipFile` from multiple threads.
+
+- bpo-38256: Fix :func:`binascii.crc32` when it is compiled to use zlib'c
+  crc32 to work properly on inputs 4+GiB in length instead of returning the
+  wrong result. The workaround prior to this was to always feed the function
+  data in increments smaller than 4GiB or to just call the zlib module
+  function.
+
+- bpo-39394: A warning about inline flags not at the start of the regular
+  expression now contains the position of the flag.
+
+- bpo-47061: Deprecate the various modules listed by :pep:`594`:
+
+  aifc, asynchat, asyncore, audioop, cgi, cgitb, chunk, crypt, imghdr,
+  msilib, nntplib, nis, ossaudiodev, pipes, smtpd, sndhdr, spwd, sunau,
+  telnetlib, uu, xdrlib
+
+- bpo-2604: Fix bug where doctests using globals would fail when run
+  multiple times.
+
+- bpo-45997: Fix :class:`asyncio.Semaphore` re-aquiring FIFO order.
+
+- bpo-47022: The :mod:`asynchat`, :mod:`asyncore` and  :mod:`smtpd` modules
+  have been deprecated since at least Python 3.6. Their documentation and
+  deprecation warnings and have now been updated to note they will removed
+  in Python 3.12 (:pep:`594`).
+
+- bpo-46421: Fix a unittest issue where if the command was invoked as
+  ``python -m unittest`` and the filename(s) began with a dot (.), a
+  ``ValueError`` is returned.
+
+- bpo-40296: Fix supporting generic aliases in :mod:`pydoc`.
+
+
 What's New in Python 3.10.3 final?
 ==================================
 
index d21b533530187e733e94452e4a4af131585ceabf..911626dafc977f0ffb26b67fc25d8d9e224035b2 100644 (file)
@@ -2510,6 +2510,25 @@ scanner_dealloc(ScannerObject* self)
     Py_DECREF(tp);
 }
 
+static int
+scanner_begin(ScannerObject* self)
+{
+    if (self->executing) {
+        PyErr_SetString(PyExc_ValueError,
+                        "regular expression scanner already executing");
+        return 0;
+    }
+    self->executing = 1;
+    return 1;
+}
+
+static void
+scanner_end(ScannerObject* self)
+{
+    assert(self->executing);
+    self->executing = 0;
+}
+
 /*[clinic input]
 _sre.SRE_Scanner.match
 
@@ -2527,16 +2546,23 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls)
     PyObject* match;
     Py_ssize_t status;
 
-    if (state->start == NULL)
+    if (!scanner_begin(self)) {
+        return NULL;
+    }
+    if (state->start == NULL) {
+        scanner_end(self);
         Py_RETURN_NONE;
+    }
 
     state_reset(state);
 
     state->ptr = state->start;
 
     status = sre_match(state, PatternObject_GetCode(self->pattern));
-    if (PyErr_Occurred())
+    if (PyErr_Occurred()) {
+        scanner_end(self);
         return NULL;
+    }
 
     match = pattern_new_match(module_state, (PatternObject*) self->pattern,
                               state, status);
@@ -2548,6 +2574,7 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls)
         state->start = state->ptr;
     }
 
+    scanner_end(self);
     return match;
 }
 
@@ -2569,16 +2596,23 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls)
     PyObject* match;
     Py_ssize_t status;
 
-    if (state->start == NULL)
+    if (!scanner_begin(self)) {
+        return NULL;
+    }
+    if (state->start == NULL) {
+        scanner_end(self);
         Py_RETURN_NONE;
+    }
 
     state_reset(state);
 
     state->ptr = state->start;
 
     status = sre_search(state, PatternObject_GetCode(self->pattern));
-    if (PyErr_Occurred())
+    if (PyErr_Occurred()) {
+        scanner_end(self);
         return NULL;
+    }
 
     match = pattern_new_match(module_state, (PatternObject*) self->pattern,
                               state, status);
@@ -2590,6 +2624,7 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls)
         state->start = state->ptr;
     }
 
+    scanner_end(self);
     return match;
 }
 
@@ -2607,6 +2642,7 @@ pattern_scanner(_sremodulestate *module_state,
     if (!scanner)
         return NULL;
     scanner->pattern = NULL;
+    scanner->executing = 0;
 
     /* create search state object */
     if (!state_init(&scanner->state, self, string, pos, endpos)) {
index 1f3248b6049b31e98328e8962d21b95b33c98e22..3777580a79f2a92d7a94c43fc0e29f0d1ba2bf9a 100644 (file)
@@ -1120,16 +1120,20 @@ binascii_crc32_impl(PyObject *module, Py_buffer *data, unsigned int crc)
 /*[clinic end generated code: output=52cf59056a78593b input=bbe340bc99d25aa8]*/
 
 #ifdef USE_ZLIB_CRC32
-/* This was taken from zlibmodule.c PyZlib_crc32 (but is PY_SSIZE_T_CLEAN) */
+/* The same core as zlibmodule.c zlib_crc32_impl. */
 {
-    const Byte *buf;
-    Py_ssize_t len;
-    int signed_val;
-
-    buf = (Byte*)data->buf;
-    len = data->len;
-    signed_val = crc32(crc, buf, len);
-    return (unsigned int)signed_val & 0xffffffffU;
+    unsigned char *buf = data->buf;
+    Py_ssize_t len = data->len;
+
+    /* Avoid truncation of length for very large buffers. crc32() takes
+       length as an unsigned int, which may be narrower than Py_ssize_t. */
+    while ((size_t)len > UINT_MAX) {
+        crc = crc32(crc, buf, UINT_MAX);
+        buf += (size_t) UINT_MAX;
+        len -= (size_t) UINT_MAX;
+    }
+    crc = crc32(crc, buf, (unsigned int)len);
+    return crc & 0xffffffff;
 }
 #else  /* USE_ZLIB_CRC32 */
 { /* By Jim Ahlstrom; All rights transferred to CNRI */
index 88a5b9376aa7deac2121b167440e14f311a3c6bd..4af8702068b14b8a7e537ec4d497b5c3698b66b6 100644 (file)
@@ -23,9 +23,9 @@
 #  define FAULTHANDLER_USE_ALT_STACK
 #endif
 
-#if defined(FAULTHANDLER_USE_ALT_STACK) && defined(HAVE_LINUX_AUXVEC_H)
-#  include <linux/auxvec.h>
-#  include <sys/auxv.h>
+#if defined(FAULTHANDLER_USE_ALT_STACK) && defined(HAVE_LINUX_AUXVEC_H) && defined(HAVE_SYS_AUXV_H)
+#  include <linux/auxvec.h>       // AT_MINSIGSTKSZ
+#  include <sys/auxv.h>           // getauxval()
 #endif
 
 /* Allocate at maximum 100 MiB of the stack to raise the stack overflow */
index 9b0d8b190426acf96d431de8ee9c6bd94e5a352c..785adbd003e7fd93d3f445e446992310ed194d54 100644 (file)
@@ -89,6 +89,7 @@ typedef struct {
     PyObject_HEAD
     PyObject* pattern;
     SRE_STATE state;
+    int executing;
 } ScannerObject;
 
 #endif
index 9b708f10a2f71c476905a11b5f410bc9cb065b3b..215ff1e5b94cea74831eebe3c0f1db74bebe66ae 100644 (file)
@@ -1,4 +1,4 @@
-This is Python version 3.10.3
+This is Python version 3.10.4
 =============================
 
 .. image:: https://travis-ci.com/python/cpython.svg?branch=master
index 0cc86f9ed7687bca33fb086ec7d574dda6e6e42e..19f1bd59ba8b185d05eaea5dc94fc9c5b5c3880b 100755 (executable)
--- a/configure
+++ b/configure
@@ -8101,7 +8101,7 @@ sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
 sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
 libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
 linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
-sys/endian.h sys/sysmacros.h linux/auxvec.h linux/memfd.h linux/wait.h sys/memfd.h \
+sys/endian.h sys/sysmacros.h linux/auxvec.h sys/auxv.h linux/memfd.h linux/wait.h sys/memfd.h \
 sys/mman.h sys/eventfd.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
index 547255ff31ebc6ff4ab9b073c7b0c0cdc1debad1..763fc697be7bcce701011aa6a9508e22f2d815b2 100644 (file)
@@ -2225,7 +2225,7 @@ sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
 sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
 libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
 linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
-sys/endian.h sys/sysmacros.h linux/auxvec.h linux/memfd.h linux/wait.h sys/memfd.h \
+sys/endian.h sys/sysmacros.h linux/auxvec.h sys/auxv.h linux/memfd.h linux/wait.h sys/memfd.h \
 sys/mman.h sys/eventfd.h)
 AC_HEADER_DIRENT
 AC_HEADER_MAJOR
index b0948e9b9b79d262a00adfe2a3625b531d90762f..57c84e5f8fac01b74273b87fbaa3577150283063 100644 (file)
 /* Define to 1 if you have the <sys/audioio.h> header file. */
 #undef HAVE_SYS_AUDIOIO_H
 
+/* Define to 1 if you have the <sys/auxv.h> header file. */
+#undef HAVE_SYS_AUXV_H
+
 /* Define to 1 if you have the <sys/bsdtty.h> header file. */
 #undef HAVE_SYS_BSDTTY_H