diff options
| author | arcadia-devtools <[email protected]> | 2022-03-18 09:10:23 +0300 |
|---|---|---|
| committer | arcadia-devtools <[email protected]> | 2022-03-18 09:10:23 +0300 |
| commit | fef2b3a8ed5955b63c71e8e541a5acf2e393925a (patch) | |
| tree | e55d2882d5c2c71561a0aa89158ec174d81f92fd /contrib/tools/python3/src/Lib | |
| parent | 2acc0fc3cdc40434ea286f2fac62386e3fd9c19d (diff) | |
intermediate changes
ref:102662f6c42fba80d7bfd4a328124cbb4294be48
Diffstat (limited to 'contrib/tools/python3/src/Lib')
29 files changed, 301 insertions, 186 deletions
diff --git a/contrib/tools/python3/src/Lib/_collections_abc.py b/contrib/tools/python3/src/Lib/_collections_abc.py index acfaff802f5..023ac7cf036 100644 --- a/contrib/tools/python3/src/Lib/_collections_abc.py +++ b/contrib/tools/python3/src/Lib/_collections_abc.py @@ -816,7 +816,7 @@ class KeysView(MappingView, Set): __slots__ = () @classmethod - def _from_iterable(self, it): + def _from_iterable(cls, it): return set(it) def __contains__(self, key): @@ -834,7 +834,7 @@ class ItemsView(MappingView, Set): __slots__ = () @classmethod - def _from_iterable(self, it): + def _from_iterable(cls, it): return set(it) def __contains__(self, item): diff --git a/contrib/tools/python3/src/Lib/_pyio.py b/contrib/tools/python3/src/Lib/_pyio.py index 4804ed27cd1..7a9a2779fce 100644 --- a/contrib/tools/python3/src/Lib/_pyio.py +++ b/contrib/tools/python3/src/Lib/_pyio.py @@ -314,8 +314,7 @@ except AttributeError: class IOBase(metaclass=abc.ABCMeta): - """The abstract base class for all I/O classes, acting on streams of - bytes. There is no public constructor. + """The abstract base class for all I/O classes. This class provides dummy implementations for many methods that derived classes can override selectively; the default implementations @@ -1821,7 +1820,7 @@ class TextIOBase(IOBase): """Base class for text I/O. This class provides a character and line based interface to stream - I/O. There is no public constructor. + I/O. """ def read(self, size=-1): diff --git a/contrib/tools/python3/src/Lib/argparse.py b/contrib/tools/python3/src/Lib/argparse.py index 40569437ac6..fbdfd5172fb 100644 --- a/contrib/tools/python3/src/Lib/argparse.py +++ b/contrib/tools/python3/src/Lib/argparse.py @@ -878,7 +878,7 @@ class BooleanOptionalAction(Action): option_string = '--no-' + option_string[2:] _option_strings.append(option_string) - if help is not None and default is not None: + if help is not None and default is not None and default is not SUPPRESS: help += " (default: %(default)s)" super().__init__( diff --git a/contrib/tools/python3/src/Lib/asyncio/base_events.py b/contrib/tools/python3/src/Lib/asyncio/base_events.py index 8c1fb496948..7a14e5e139f 100644 --- a/contrib/tools/python3/src/Lib/asyncio/base_events.py +++ b/contrib/tools/python3/src/Lib/asyncio/base_events.py @@ -49,7 +49,7 @@ from . import trsock from .log import logger -__all__ = 'BaseEventLoop', +__all__ = 'BaseEventLoop','Server', # Minimum number of _scheduled timer handles before cleanup of @@ -202,6 +202,11 @@ else: pass +def _check_ssl_socket(sock): + if ssl is not None and isinstance(sock, ssl.SSLSocket): + raise TypeError("Socket cannot be of type SSLSocket") + + class _SendfileFallbackProtocol(protocols.Protocol): def __init__(self, transp): if not isinstance(transp, transports._FlowControlMixin): @@ -864,6 +869,7 @@ class BaseEventLoop(events.AbstractEventLoop): *, fallback=True): if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") + _check_ssl_socket(sock) self._check_sendfile_params(sock, file, offset, count) try: return await self._sock_sendfile_native(sock, file, @@ -1005,6 +1011,9 @@ class BaseEventLoop(events.AbstractEventLoop): raise ValueError( 'ssl_handshake_timeout is only meaningful with ssl') + if sock is not None: + _check_ssl_socket(sock) + if happy_eyeballs_delay is not None and interleave is None: # If using happy eyeballs, default to interleave addresses by family interleave = 1 @@ -1438,6 +1447,9 @@ class BaseEventLoop(events.AbstractEventLoop): raise ValueError( 'ssl_handshake_timeout is only meaningful with ssl') + if sock is not None: + _check_ssl_socket(sock) + if host is not None or port is not None: if sock is not None: raise ValueError( @@ -1540,6 +1552,9 @@ class BaseEventLoop(events.AbstractEventLoop): raise ValueError( 'ssl_handshake_timeout is only meaningful with ssl') + if sock is not None: + _check_ssl_socket(sock) + transport, protocol = await self._create_connection_transport( sock, protocol_factory, ssl, '', server_side=True, ssl_handshake_timeout=ssl_handshake_timeout) diff --git a/contrib/tools/python3/src/Lib/asyncio/futures.py b/contrib/tools/python3/src/Lib/asyncio/futures.py index bed4da52fd4..aaab09c28e6 100644 --- a/contrib/tools/python3/src/Lib/asyncio/futures.py +++ b/contrib/tools/python3/src/Lib/asyncio/futures.py @@ -8,6 +8,7 @@ import concurrent.futures import contextvars import logging import sys +from types import GenericAlias from . import base_futures from . import events @@ -106,8 +107,7 @@ class Future: context['source_traceback'] = self._source_traceback self._loop.call_exception_handler(context) - def __class_getitem__(cls, type): - return cls + __class_getitem__ = classmethod(GenericAlias) @property def _log_traceback(self): diff --git a/contrib/tools/python3/src/Lib/asyncio/proactor_events.py b/contrib/tools/python3/src/Lib/asyncio/proactor_events.py index b4cd414b82d..e3f95cf21d6 100644 --- a/contrib/tools/python3/src/Lib/asyncio/proactor_events.py +++ b/contrib/tools/python3/src/Lib/asyncio/proactor_events.py @@ -158,7 +158,7 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin, # end then it may fail with ERROR_NETNAME_DELETED if we # just close our end. First calling shutdown() seems to # cure it, but maybe using DisconnectEx() would be better. - if hasattr(self._sock, 'shutdown'): + if hasattr(self._sock, 'shutdown') and self._sock.fileno() != -1: self._sock.shutdown(socket.SHUT_RDWR) self._sock.close() self._sock = None @@ -450,7 +450,8 @@ class _ProactorWritePipeTransport(_ProactorBaseWritePipeTransport): self.close() -class _ProactorDatagramTransport(_ProactorBasePipeTransport): +class _ProactorDatagramTransport(_ProactorBasePipeTransport, + transports.DatagramTransport): max_size = 256 * 1024 def __init__(self, loop, sock, protocol, address=None, waiter=None, extra=None): diff --git a/contrib/tools/python3/src/Lib/asyncio/protocols.py b/contrib/tools/python3/src/Lib/asyncio/protocols.py index 69fa43e8b65..09987b164c6 100644 --- a/contrib/tools/python3/src/Lib/asyncio/protocols.py +++ b/contrib/tools/python3/src/Lib/asyncio/protocols.py @@ -109,10 +109,6 @@ class Protocol(BaseProtocol): class BufferedProtocol(BaseProtocol): """Interface for stream protocol with manual buffer control. - Important: this has been added to asyncio in Python 3.7 - *on a provisional basis*! Consider it as an experimental API that - might be changed or removed in Python 3.8. - Event methods, such as `create_server` and `create_connection`, accept factories that return protocols that implement this interface. diff --git a/contrib/tools/python3/src/Lib/asyncio/queues.py b/contrib/tools/python3/src/Lib/asyncio/queues.py index cd3f7c6a567..14ae87e0a2d 100644 --- a/contrib/tools/python3/src/Lib/asyncio/queues.py +++ b/contrib/tools/python3/src/Lib/asyncio/queues.py @@ -3,6 +3,7 @@ __all__ = ('Queue', 'PriorityQueue', 'LifoQueue', 'QueueFull', 'QueueEmpty') import collections import heapq import warnings +from types import GenericAlias from . import events from . import locks @@ -76,8 +77,7 @@ class Queue: def __str__(self): return f'<{type(self).__name__} {self._format()}>' - def __class_getitem__(cls, type): - return cls + __class_getitem__ = classmethod(GenericAlias) def _format(self): result = f'maxsize={self._maxsize!r}' diff --git a/contrib/tools/python3/src/Lib/asyncio/selector_events.py b/contrib/tools/python3/src/Lib/asyncio/selector_events.py index 59cb6b1babe..71080b8ad16 100644 --- a/contrib/tools/python3/src/Lib/asyncio/selector_events.py +++ b/contrib/tools/python3/src/Lib/asyncio/selector_events.py @@ -40,11 +40,6 @@ def _test_selector_event(selector, fd, event): return bool(key.events & event) -def _check_ssl_socket(sock): - if ssl is not None and isinstance(sock, ssl.SSLSocket): - raise TypeError("Socket cannot be of type SSLSocket") - - class BaseSelectorEventLoop(base_events.BaseEventLoop): """Selector event loop. @@ -357,7 +352,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): The maximum amount of data to be received at once is specified by nbytes. """ - _check_ssl_socket(sock) + base_events._check_ssl_socket(sock) if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") try: @@ -398,7 +393,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): The received data is written into *buf* (a writable buffer). The return value is the number of bytes written. """ - _check_ssl_socket(sock) + base_events._check_ssl_socket(sock) if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") try: @@ -439,7 +434,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): raised, and there is no way to determine how much data, if any, was successfully processed by the receiving end of the connection. """ - _check_ssl_socket(sock) + base_events._check_ssl_socket(sock) if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") try: @@ -488,13 +483,15 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): This method is a coroutine. """ - _check_ssl_socket(sock) + base_events._check_ssl_socket(sock) if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") if not hasattr(socket, 'AF_UNIX') or sock.family != socket.AF_UNIX: resolved = await self._ensure_resolved( - address, family=sock.family, proto=sock.proto, loop=self) + address, family=sock.family, type=sock.type, proto=sock.proto, + loop=self, + ) _, _, _, _, address = resolved[0] fut = self.create_future() @@ -553,7 +550,7 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop): object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection. """ - _check_ssl_socket(sock) + base_events._check_ssl_socket(sock) if self._debug and sock.gettimeout() != 0: raise ValueError("the socket must be non-blocking") fut = self.create_future() diff --git a/contrib/tools/python3/src/Lib/asyncio/sslproto.py b/contrib/tools/python3/src/Lib/asyncio/sslproto.py index cad25b26539..00fc16c014c 100644 --- a/contrib/tools/python3/src/Lib/asyncio/sslproto.py +++ b/contrib/tools/python3/src/Lib/asyncio/sslproto.py @@ -367,6 +367,12 @@ class _SSLProtocolTransport(transports._FlowControlMixin, """Return the current size of the write buffer.""" return self._ssl_protocol._transport.get_write_buffer_size() + def get_write_buffer_limits(self): + """Get the high and low watermarks for write flow control. + Return a tuple (low, high) where low and high are + positive number of bytes.""" + return self._ssl_protocol._transport.get_write_buffer_limits() + @property def _protocol_paused(self): # Required for sendfile fallback pause_writing/resume_writing logic diff --git a/contrib/tools/python3/src/Lib/asyncio/tasks.py b/contrib/tools/python3/src/Lib/asyncio/tasks.py index 27a3c8c5a88..53252f2079d 100644 --- a/contrib/tools/python3/src/Lib/asyncio/tasks.py +++ b/contrib/tools/python3/src/Lib/asyncio/tasks.py @@ -17,6 +17,7 @@ import itertools import types import warnings import weakref +from types import GenericAlias from . import base_tasks from . import coroutines @@ -147,8 +148,7 @@ class Task(futures._PyFuture): # Inherit Python Task implementation self._loop.call_exception_handler(context) super().__del__() - def __class_getitem__(cls, type): - return cls + __class_getitem__ = classmethod(GenericAlias) def _repr_info(self): return base_tasks._task_repr_info(self) @@ -768,7 +768,7 @@ def _gather(*coros_or_futures, loop=None, return_exceptions=False): nonlocal nfinished nfinished += 1 - if outer.done(): + if outer is None or outer.done(): if not fut.cancelled(): # Mark exception retrieved. fut.exception() @@ -823,6 +823,7 @@ def _gather(*coros_or_futures, loop=None, return_exceptions=False): children = [] nfuts = 0 nfinished = 0 + outer = None # bpo-46672 for arg in coros_or_futures: if arg not in arg_to_fut: fut = ensure_future(arg, loop=loop) diff --git a/contrib/tools/python3/src/Lib/asyncio/transports.py b/contrib/tools/python3/src/Lib/asyncio/transports.py index 45e155c94ca..73b1fa2de41 100644 --- a/contrib/tools/python3/src/Lib/asyncio/transports.py +++ b/contrib/tools/python3/src/Lib/asyncio/transports.py @@ -99,6 +99,12 @@ class WriteTransport(BaseTransport): """Return the current size of the write buffer.""" raise NotImplementedError + def get_write_buffer_limits(self): + """Get the high and low watermarks for write flow control. + Return a tuple (low, high) where low and high are + positive number of bytes.""" + raise NotImplementedError + def write(self, data): """Write some data bytes to the transport. diff --git a/contrib/tools/python3/src/Lib/ensurepip/__init__.py b/contrib/tools/python3/src/Lib/ensurepip/__init__.py index 2a140a2624d..e510cc7fb2b 100644 --- a/contrib/tools/python3/src/Lib/ensurepip/__init__.py +++ b/contrib/tools/python3/src/Lib/ensurepip/__init__.py @@ -12,7 +12,7 @@ from . import _bundled __all__ = ["version", "bootstrap"] _SETUPTOOLS_VERSION = "58.1.0" -_PIP_VERSION = "21.2.4" +_PIP_VERSION = "22.0.4" _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION, "py3"), ("pip", _PIP_VERSION, "py3"), diff --git a/contrib/tools/python3/src/Lib/http/server.py b/contrib/tools/python3/src/Lib/http/server.py index d7cce20432e..2d2300c2aea 100644 --- a/contrib/tools/python3/src/Lib/http/server.py +++ b/contrib/tools/python3/src/Lib/http/server.py @@ -103,8 +103,6 @@ import socketserver import sys import time import urllib.parse -import contextlib -from functools import partial from http import HTTPStatus @@ -1240,7 +1238,6 @@ def test(HandlerClass=BaseHTTPRequestHandler, """ ServerClass.address_family, addr = _get_best_family(bind, port) - HandlerClass.protocol_version = protocol with ServerClass(addr, HandlerClass) as httpd: host, port = httpd.socket.getsockname()[:2] @@ -1257,29 +1254,29 @@ def test(HandlerClass=BaseHTTPRequestHandler, if __name__ == '__main__': import argparse + import contextlib parser = argparse.ArgumentParser() parser.add_argument('--cgi', action='store_true', - help='Run as CGI Server') + help='run as CGI server') parser.add_argument('--bind', '-b', metavar='ADDRESS', - help='Specify alternate bind address ' - '[default: all interfaces]') + help='specify alternate bind address ' + '(default: all interfaces)') parser.add_argument('--directory', '-d', default=os.getcwd(), - help='Specify alternative directory ' - '[default:current directory]') - parser.add_argument('port', action='store', - default=8000, type=int, + help='specify alternate directory ' + '(default: current directory)') + parser.add_argument('port', action='store', default=8000, type=int, nargs='?', - help='Specify alternate port [default: 8000]') + help='specify alternate port (default: 8000)') args = parser.parse_args() if args.cgi: handler_class = CGIHTTPRequestHandler else: - handler_class = partial(SimpleHTTPRequestHandler, - directory=args.directory) + handler_class = SimpleHTTPRequestHandler # ensure dual-stack is not disabled; ref #38907 class DualStackServer(ThreadingHTTPServer): + def server_bind(self): # suppress exception when protocol is IPv4 with contextlib.suppress(Exception): @@ -1287,6 +1284,10 @@ if __name__ == '__main__': socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0) return super().server_bind() + def finish_request(self, request, client_address): + self.RequestHandlerClass(request, client_address, self, + directory=args.directory) + test( HandlerClass=handler_class, ServerClass=DualStackServer, diff --git a/contrib/tools/python3/src/Lib/importlib/_bootstrap_external.py b/contrib/tools/python3/src/Lib/importlib/_bootstrap_external.py index fe31f437dac..f3828b10e1c 100644 --- a/contrib/tools/python3/src/Lib/importlib/_bootstrap_external.py +++ b/contrib/tools/python3/src/Lib/importlib/_bootstrap_external.py @@ -1209,10 +1209,15 @@ class _NamespacePath: using path_finder. For top-level modules, the parent module's path is sys.path.""" + # When invalidate_caches() is called, this epoch is incremented + # https://bugs.python.org/issue45703 + _epoch = 0 + def __init__(self, name, path, path_finder): self._name = name self._path = path self._last_parent_path = tuple(self._get_parent_path()) + self._last_epoch = self._epoch self._path_finder = path_finder def _find_parent_path_names(self): @@ -1232,7 +1237,7 @@ class _NamespacePath: def _recalculate(self): # If the parent's path has changed, recalculate _path parent_path = tuple(self._get_parent_path()) # Make a copy - if parent_path != self._last_parent_path: + if parent_path != self._last_parent_path or self._epoch != self._last_epoch: spec = self._path_finder(self._name, parent_path) # Note that no changes are made if a loader is returned, but we # do remember the new parent path @@ -1240,6 +1245,7 @@ class _NamespacePath: if spec.submodule_search_locations: self._path = spec.submodule_search_locations self._last_parent_path = parent_path # Save the copy + self._last_epoch = self._epoch return self._path def __iter__(self): @@ -1320,6 +1326,9 @@ class PathFinder: del sys.path_importer_cache[name] elif hasattr(finder, 'invalidate_caches'): finder.invalidate_caches() + # Also invalidate the caches of _NamespacePaths + # https://bugs.python.org/issue45703 + _NamespacePath._epoch += 1 @classmethod def _path_hooks(cls, path): diff --git a/contrib/tools/python3/src/Lib/importlib/metadata.py b/contrib/tools/python3/src/Lib/importlib/metadata.py index 594986ce23e..647fd3e4dbf 100644 --- a/contrib/tools/python3/src/Lib/importlib/metadata.py +++ b/contrib/tools/python3/src/Lib/importlib/metadata.py @@ -45,12 +45,21 @@ class EntryPoint( See `the packaging docs on entry points <https://packaging.python.org/specifications/entry-points/>`_ for more information. + + >>> ep = EntryPoint( + ... name=None, group=None, value='package.module:attr [extra1, extra2]') + >>> ep.module + 'package.module' + >>> ep.attr + 'attr' + >>> ep.extras + ['extra1', 'extra2'] """ pattern = re.compile( r'(?P<module>[\w.]+)\s*' - r'(:\s*(?P<attr>[\w.]+))?\s*' - r'(?P<extras>\[.*\])?\s*$' + r'(:\s*(?P<attr>[\w.]+)\s*)?' + r'((?P<extras>\[.*\])\s*)?$' ) """ A regular expression describing the syntax for an entry point, @@ -91,7 +100,7 @@ class EntryPoint( @property def extras(self): match = self.pattern.match(self.value) - return list(re.finditer(r'\w+', match.group('extras') or '')) + return re.findall(r'\w+', match.group('extras') or '') @classmethod def _from_config(cls, config): @@ -308,7 +317,7 @@ class Distribution: def _read_egg_info_reqs(self): source = self.read_text('requires.txt') - return source and self._deps_from_requires_text(source) + return None if source is None else self._deps_from_requires_text(source) @classmethod def _deps_from_requires_text(cls, source): diff --git a/contrib/tools/python3/src/Lib/inspect.py b/contrib/tools/python3/src/Lib/inspect.py index ffe0a781f7f..dd00c21fc26 100644 --- a/contrib/tools/python3/src/Lib/inspect.py +++ b/contrib/tools/python3/src/Lib/inspect.py @@ -2379,9 +2379,9 @@ def _signature_from_callable(obj, *, pass else: if text_sig: - # If 'obj' class has a __text_signature__ attribute: + # If 'base' class has a __text_signature__ attribute: # return a signature based on it - return _signature_fromstr(sigcls, obj, text_sig) + return _signature_fromstr(sigcls, base, text_sig) # No '__text_signature__' was found for the 'obj' class. # Last option is to check if its '__init__' is diff --git a/contrib/tools/python3/src/Lib/lib2to3/pytree.py b/contrib/tools/python3/src/Lib/lib2to3/pytree.py index 2a6ef2ef524..729023df028 100644 --- a/contrib/tools/python3/src/Lib/lib2to3/pytree.py +++ b/contrib/tools/python3/src/Lib/lib2to3/pytree.py @@ -720,8 +720,8 @@ class WildcardPattern(BasePattern): r[self.name] = nodes[:count] yield count, r except RuntimeError: - # We fall back to the iterative pattern matching scheme if the recursive - # scheme hits the recursion limit. + # Fall back to the iterative pattern matching scheme if the + # recursive scheme hits the recursion limit (RecursionError). for count, r in self._iterative_matches(nodes): if self.name: r[self.name] = nodes[:count] diff --git a/contrib/tools/python3/src/Lib/mimetypes.py b/contrib/tools/python3/src/Lib/mimetypes.py index d36e1664cdc..58ace01b41a 100644 --- a/contrib/tools/python3/src/Lib/mimetypes.py +++ b/contrib/tools/python3/src/Lib/mimetypes.py @@ -135,25 +135,23 @@ class MimeTypes: type = 'text/plain' return type, None # never compressed, so encoding is None base, ext = posixpath.splitext(url) - while ext in self.suffix_map: - base, ext = posixpath.splitext(base + self.suffix_map[ext]) + while (ext_lower := ext.lower()) in self.suffix_map: + base, ext = posixpath.splitext(base + self.suffix_map[ext_lower]) + # encodings_map is case sensitive if ext in self.encodings_map: encoding = self.encodings_map[ext] base, ext = posixpath.splitext(base) else: encoding = None + ext = ext.lower() types_map = self.types_map[True] if ext in types_map: return types_map[ext], encoding - elif ext.lower() in types_map: - return types_map[ext.lower()], encoding elif strict: return None, encoding types_map = self.types_map[False] if ext in types_map: return types_map[ext], encoding - elif ext.lower() in types_map: - return types_map[ext.lower()], encoding else: return None, encoding diff --git a/contrib/tools/python3/src/Lib/pdb.py b/contrib/tools/python3/src/Lib/pdb.py index 943211158ac..7ab50b4845d 100755 --- a/contrib/tools/python3/src/Lib/pdb.py +++ b/contrib/tools/python3/src/Lib/pdb.py @@ -1493,6 +1493,9 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.error('No help for %r; please do not run Python with -OO ' 'if you need command help' % arg) return + if command.__doc__ is None: + self.error('No help for %r; __doc__ string missing' % arg) + return self.message(command.__doc__.rstrip()) do_h = do_help diff --git a/contrib/tools/python3/src/Lib/pydoc_data/topics.py b/contrib/tools/python3/src/Lib/pydoc_data/topics.py index 67a51977cfe..0e63c31f1b4 100644 --- a/contrib/tools/python3/src/Lib/pydoc_data/topics.py +++ b/contrib/tools/python3/src/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Thu Jan 13 21:46:32 2022 +# Autogenerated by Sphinx on Tue Mar 15 21:44:32 2022 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -5408,19 +5408,19 @@ topics = {'assert': 'The "assert" statement\n' 'with an\n' '*alignment* type of "\'=\'".\n' '\n' - 'The *precision* is a decimal number indicating how many ' + 'The *precision* is a decimal integer indicating how many ' 'digits should\n' - 'be displayed after the decimal point for a floating point ' - 'value\n' - 'formatted with "\'f\'" and "\'F\'", or before and after the ' - 'decimal point\n' - 'for a floating point value formatted with "\'g\'" or ' - '"\'G\'". For non-\n' - 'number types the field indicates the maximum field size - ' - 'in other\n' - 'words, how many characters will be used from the field ' - 'content. The\n' - '*precision* is not allowed for integer values.\n' + 'be displayed after the decimal point for presentation types ' + '"\'f\'" and\n' + '"\'F\'", or before and after the decimal point for ' + 'presentation types\n' + '"\'g\'" or "\'G\'". For string presentation types the ' + 'field indicates the\n' + 'maximum field size - in other words, how many characters ' + 'will be used\n' + 'from the field content. The *precision* is not allowed for ' + 'integer\n' + 'presentation types.\n' '\n' 'Finally, the *type* determines how the data should be ' 'presented.\n' @@ -7515,12 +7515,12 @@ topics = {'assert': 'The "assert" statement\n' '\n' ' raise_stmt ::= "raise" [expression ["from" expression]]\n' '\n' - 'If no expressions are present, "raise" re-raises the last ' - 'exception\n' - 'that was active in the current scope. If no exception is active ' - 'in\n' - 'the current scope, a "RuntimeError" exception is raised indicating\n' - 'that this is an error.\n' + 'If no expressions are present, "raise" re-raises the exception that ' + 'is\n' + 'currently being handled, which is also known as the *active\n' + 'exception*. If there isn’t currently an active exception, a\n' + '"RuntimeError" exception is raised indicating that this is an ' + 'error.\n' '\n' 'Otherwise, "raise" evaluates the first expression as the exception\n' 'object. It must be either a subclass or an instance of\n' @@ -7575,11 +7575,14 @@ topics = {'assert': 'The "assert" statement\n' ' File "<stdin>", line 4, in <module>\n' ' RuntimeError: Something bad happened\n' '\n' - 'A similar mechanism works implicitly if an exception is raised ' - 'inside\n' - 'an exception handler or a "finally" clause: the previous exception ' - 'is\n' - 'then attached as the new exception’s "__context__" attribute:\n' + 'A similar mechanism works implicitly if a new exception is raised ' + 'when\n' + 'an exception is already being handled. An exception may be ' + 'handled\n' + 'when an "except" or "finally" clause, or a "with" statement, is ' + 'used.\n' + 'The previous exception is then attached as the new exception’s\n' + '"__context__" attribute:\n' '\n' ' >>> try:\n' ' ... print(1 / 0)\n' @@ -9079,14 +9082,14 @@ topics = {'assert': 'The "assert" statement\n' '\n' 'Whenever a class inherits from another class, ' '"__init_subclass__()" is\n' - 'called on that class. This way, it is possible to write ' - 'classes which\n' - 'change the behavior of subclasses. This is closely related ' - 'to class\n' - 'decorators, but where class decorators only affect the ' - 'specific class\n' - 'they’re applied to, "__init_subclass__" solely applies to ' - 'future\n' + 'called on the parent class. This way, it is possible to ' + 'write classes\n' + 'which change the behavior of subclasses. This is closely ' + 'related to\n' + 'class decorators, but where class decorators only affect the ' + 'specific\n' + 'class they’re applied to, "__init_subclass__" solely applies ' + 'to future\n' 'subclasses of the class defining the method.\n' '\n' 'classmethod object.__init_subclass__(cls)\n' @@ -11393,67 +11396,86 @@ topics = {'assert': 'The "assert" statement\n' 'subscriptions': 'Subscriptions\n' '*************\n' '\n' - 'Subscription of a sequence (string, tuple or list) or ' - 'mapping\n' - '(dictionary) object usually selects an item from the ' - 'collection:\n' + 'The subscription of an instance of a container class will ' + 'generally\n' + 'select an element from the container. The subscription of a ' + '*generic\n' + 'class* will generally return a GenericAlias object.\n' '\n' ' subscription ::= primary "[" expression_list "]"\n' '\n' + 'When an object is subscripted, the interpreter will ' + 'evaluate the\n' + 'primary and the expression list.\n' + '\n' 'The primary must evaluate to an object that supports ' - 'subscription\n' - '(lists or dictionaries for example). User-defined objects ' - 'can support\n' - 'subscription by defining a "__getitem__()" method.\n' + 'subscription. An\n' + 'object may support subscription through defining one or ' + 'both of\n' + '"__getitem__()" and "__class_getitem__()". When the primary ' + 'is\n' + 'subscripted, the evaluated result of the expression list ' + 'will be\n' + 'passed to one of these methods. For more details on when\n' + '"__class_getitem__" is called instead of "__getitem__", ' + 'see\n' + '__class_getitem__ versus __getitem__.\n' + '\n' + 'If the expression list contains at least one comma, it will ' + 'evaluate\n' + 'to a "tuple" containing the items of the expression list. ' + 'Otherwise,\n' + 'the expression list will evaluate to the value of the ' + 'list’s sole\n' + 'member.\n' '\n' 'For built-in objects, there are two types of objects that ' 'support\n' - 'subscription:\n' + 'subscription via "__getitem__()":\n' '\n' - 'If the primary is a mapping, the expression list must ' - 'evaluate to an\n' - 'object whose value is one of the keys of the mapping, and ' + '1. Mappings. If the primary is a *mapping*, the expression ' + 'list must\n' + ' evaluate to an object whose value is one of the keys of ' 'the\n' - 'subscription selects the value in the mapping that ' - 'corresponds to that\n' - 'key. (The expression list is a tuple except if it has ' - 'exactly one\n' - 'item.)\n' + ' mapping, and the subscription selects the value in the ' + 'mapping that\n' + ' corresponds to that key. An example of a builtin mapping ' + 'class is\n' + ' the "dict" class.\n' '\n' - 'If the primary is a sequence, the expression list must ' - 'evaluate to an\n' - 'integer or a slice (as discussed in the following ' - 'section).\n' + '2. Sequences. If the primary is a *sequence*, the ' + 'expression list must\n' + ' evaluate to an "int" or a "slice" (as discussed in the ' + 'following\n' + ' section). Examples of builtin sequence classes include ' + 'the "str",\n' + ' "list" and "tuple" classes.\n' '\n' 'The formal syntax makes no special provision for negative ' 'indices in\n' - 'sequences; however, built-in sequences all provide a ' + '*sequences*. However, built-in sequences all provide a ' '"__getitem__()"\n' 'method that interprets negative indices by adding the ' 'length of the\n' - 'sequence to the index (so that "x[-1]" selects the last ' - 'item of "x").\n' - 'The resulting value must be a nonnegative integer less than ' - 'the number\n' - 'of items in the sequence, and the subscription selects the ' - 'item whose\n' - 'index is that value (counting from zero). Since the support ' - 'for\n' - 'negative indices and slicing occurs in the object’s ' - '"__getitem__()"\n' - 'method, subclasses overriding this method will need to ' - 'explicitly add\n' - 'that support.\n' + 'sequence to the index so that, for example, "x[-1]" selects ' + 'the last\n' + 'item of "x". The resulting value must be a nonnegative ' + 'integer less\n' + 'than the number of items in the sequence, and the ' + 'subscription selects\n' + 'the item whose index is that value (counting from zero). ' + 'Since the\n' + 'support for negative indices and slicing occurs in the ' + 'object’s\n' + '"__getitem__()" method, subclasses overriding this method ' + 'will need to\n' + 'explicitly add that support.\n' '\n' - 'A string’s items are characters. A character is not a ' - 'separate data\n' - 'type but a string of exactly one character.\n' - '\n' - 'Subscription of certain *classes* or *types* creates a ' - 'generic alias.\n' - 'In this case, user-defined classes can support subscription ' - 'by\n' - 'providing a "__class_getitem__()" classmethod.\n', + 'A "string" is a special kind of sequence whose items are ' + '*characters*.\n' + 'A character is not a separate data type but a string of ' + 'exactly one\n' + 'character.\n', 'truth': 'Truth Value Testing\n' '*******************\n' '\n' diff --git a/contrib/tools/python3/src/Lib/shutil.py b/contrib/tools/python3/src/Lib/shutil.py index 752900c5889..c048cdf9b2c 100644 --- a/contrib/tools/python3/src/Lib/shutil.py +++ b/contrib/tools/python3/src/Lib/shutil.py @@ -656,6 +656,7 @@ def _rmtree_safe_fd(topfd, path, onerror): if is_dir: try: dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd) + dirfd_closed = False except OSError: onerror(os.open, fullname, sys.exc_info()) else: @@ -663,6 +664,8 @@ def _rmtree_safe_fd(topfd, path, onerror): if os.path.samestat(orig_st, os.fstat(dirfd)): _rmtree_safe_fd(dirfd, fullname, onerror) try: + os.close(dirfd) + dirfd_closed = True os.rmdir(entry.name, dir_fd=topfd) except OSError: onerror(os.rmdir, fullname, sys.exc_info()) @@ -676,7 +679,8 @@ def _rmtree_safe_fd(topfd, path, onerror): except OSError: onerror(os.path.islink, fullname, sys.exc_info()) finally: - os.close(dirfd) + if not dirfd_closed: + os.close(dirfd) else: try: os.unlink(entry.name, dir_fd=topfd) @@ -719,6 +723,7 @@ def rmtree(path, ignore_errors=False, onerror=None): return try: fd = os.open(path, os.O_RDONLY) + fd_closed = False except Exception: onerror(os.open, path, sys.exc_info()) return @@ -726,6 +731,8 @@ def rmtree(path, ignore_errors=False, onerror=None): if os.path.samestat(orig_st, os.fstat(fd)): _rmtree_safe_fd(fd, path, onerror) try: + os.close(fd) + fd_closed = True os.rmdir(path) except OSError: onerror(os.rmdir, path, sys.exc_info()) @@ -736,7 +743,8 @@ def rmtree(path, ignore_errors=False, onerror=None): except OSError: onerror(os.path.islink, path, sys.exc_info()) finally: - os.close(fd) + if not fd_closed: + os.close(fd) else: try: if _rmtree_islink(path): diff --git a/contrib/tools/python3/src/Lib/tarfile.py b/contrib/tools/python3/src/Lib/tarfile.py index 043a4ab5a52..9438b08ae39 100755 --- a/contrib/tools/python3/src/Lib/tarfile.py +++ b/contrib/tools/python3/src/Lib/tarfile.py @@ -887,15 +887,24 @@ class TarInfo(object): # Test number fields for values that exceed the field limit or values # that like to be stored as float. for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): - if name in pax_headers: - # The pax header has priority. Avoid overflow. - info[name] = 0 - continue + needs_pax = False val = info[name] - if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): - pax_headers[name] = str(val) + val_is_float = isinstance(val, float) + val_int = round(val) if val_is_float else val + if not 0 <= val_int < 8 ** (digits - 1): + # Avoid overflow. info[name] = 0 + needs_pax = True + elif val_is_float: + # Put rounded value in ustar header, and full + # precision value in pax header. + info[name] = val_int + needs_pax = True + + # The existing pax header has priority. + if needs_pax and name not in pax_headers: + pax_headers[name] = str(val) # Create a pax extended header if necessary. if pax_headers: @@ -1785,7 +1794,7 @@ class TarFile(object): than once in the archive, its last occurrence is assumed to be the most up-to-date version. """ - tarinfo = self._getmember(name) + tarinfo = self._getmember(name.rstrip('/')) if tarinfo is None: raise KeyError("filename %r not found" % name) return tarinfo diff --git a/contrib/tools/python3/src/Lib/typing.py b/contrib/tools/python3/src/Lib/typing.py index da70d4115fa..d35a2a5b018 100644 --- a/contrib/tools/python3/src/Lib/typing.py +++ b/contrib/tools/python3/src/Lib/typing.py @@ -125,16 +125,16 @@ __all__ = [ # legitimate imports of those modules. -def _type_convert(arg, module=None): +def _type_convert(arg, module=None, *, allow_special_forms=False): """For converting None to type(None), and strings to ForwardRef.""" if arg is None: return type(None) if isinstance(arg, str): - return ForwardRef(arg, module=module) + return ForwardRef(arg, module=module, is_class=allow_special_forms) return arg -def _type_check(arg, msg, is_argument=True, module=None, *, is_class=False): +def _type_check(arg, msg, is_argument=True, module=None, *, allow_special_forms=False): """Check that the argument is a type, and return it (internal helper). As a special case, accept None and return type(None) instead. Also wrap strings @@ -147,12 +147,12 @@ def _type_check(arg, msg, is_argument=True, module=None, *, is_class=False): We append the repr() of the actual value (truncated to 100 chars). """ invalid_generic_forms = (Generic, Protocol) - if not is_class: + if not allow_special_forms: invalid_generic_forms += (ClassVar,) if is_argument: invalid_generic_forms += (Final,) - arg = _type_convert(arg, module=module) + arg = _type_convert(arg, module=module, allow_special_forms=allow_special_forms) if (isinstance(arg, _GenericAlias) and arg.__origin__ in invalid_generic_forms): raise TypeError(f"{arg} is not valid as type argument") @@ -285,8 +285,8 @@ def _tp_cache(func=None, /, *, typed=False): def _eval_type(t, globalns, localns, recursive_guard=frozenset()): """Evaluate all forward references in the given type t. For use of globalns and localns see the docstring for get_type_hints(). - recursive_guard is used to prevent prevent infinite recursion - with recursive ForwardRef. + recursive_guard is used to prevent infinite recursion with a recursive + ForwardRef. """ if isinstance(t, ForwardRef): return t._evaluate(globalns, localns, recursive_guard) @@ -554,7 +554,7 @@ class ForwardRef(_Final, _root=True): eval(self.__forward_code__, globalns, localns), "Forward references must evaluate to types.", is_argument=self.__forward_is_argument__, - is_class=self.__forward_is_class__, + allow_special_forms=self.__forward_is_class__, ) self.__forward_value__ = _eval_type( type_, globalns, localns, recursive_guard | {self.__forward_arg__} @@ -568,10 +568,11 @@ class ForwardRef(_Final, _root=True): if self.__forward_evaluated__ and other.__forward_evaluated__: return (self.__forward_arg__ == other.__forward_arg__ and self.__forward_value__ == other.__forward_value__) - return self.__forward_arg__ == other.__forward_arg__ + return (self.__forward_arg__ == other.__forward_arg__ and + self.__forward_module__ == other.__forward_module__) def __hash__(self): - return hash(self.__forward_arg__) + return hash((self.__forward_arg__, self.__forward_module__)) def __repr__(self): return f'ForwardRef({self.__forward_arg__!r})' @@ -704,7 +705,7 @@ class _BaseGenericAlias(_Final, _root=True): def __getattr__(self, attr): # We are careful for copy and pickle. - # Also for simplicity we just don't relay all dunder names + # Also for simplicity we don't relay any dunder names if '__origin__' in self.__dict__ and not _is_dunder(attr): return getattr(self.__origin__, attr) raise AttributeError(attr) @@ -1336,7 +1337,7 @@ class Annotated: "with at least two arguments (a type and an " "annotation).") msg = "Annotated[t, ...]: t must be a type." - origin = _type_check(params[0], msg) + origin = _type_check(params[0], msg, allow_special_forms=True) metadata = tuple(params[1:]) return _AnnotatedAlias(origin, metadata) diff --git a/contrib/tools/python3/src/Lib/unittest/mock.py b/contrib/tools/python3/src/Lib/unittest/mock.py index 5c78274d093..3f5442ed809 100644 --- a/contrib/tools/python3/src/Lib/unittest/mock.py +++ b/contrib/tools/python3/src/Lib/unittest/mock.py @@ -1557,9 +1557,9 @@ class _patch(object): def _get_target(target): try: target, attribute = target.rsplit('.', 1) - except (TypeError, ValueError): - raise TypeError("Need a valid target to patch. You supplied: %r" % - (target,)) + except (TypeError, ValueError, AttributeError): + raise TypeError( + f"Need a valid target to patch. You supplied: {target!r}") getter = lambda: _importer(target) return getter, attribute diff --git a/contrib/tools/python3/src/Lib/unittest/result.py b/contrib/tools/python3/src/Lib/unittest/result.py index 111317b329a..528d223850e 100644 --- a/contrib/tools/python3/src/Lib/unittest/result.py +++ b/contrib/tools/python3/src/Lib/unittest/result.py @@ -173,17 +173,9 @@ class TestResult(object): def _exc_info_to_string(self, err, test): """Converts a sys.exc_info()-style tuple of values into a string.""" exctype, value, tb = err - # Skip test runner traceback levels - while tb and self._is_relevant_tb_level(tb): - tb = tb.tb_next - - if exctype is test.failureException: - # Skip assert*() traceback levels - length = self._count_relevant_tb_levels(tb) - else: - length = None + tb = self._clean_tracebacks(exctype, value, tb, test) tb_e = traceback.TracebackException( - exctype, value, tb, limit=length, capture_locals=self.tb_locals) + exctype, value, tb, capture_locals=self.tb_locals) msgLines = list(tb_e.format()) if self.buffer: @@ -199,16 +191,49 @@ class TestResult(object): msgLines.append(STDERR_LINE % error) return ''.join(msgLines) + def _clean_tracebacks(self, exctype, value, tb, test): + ret = None + first = True + excs = [(exctype, value, tb)] + while excs: + (exctype, value, tb) = excs.pop() + # Skip test runner traceback levels + while tb and self._is_relevant_tb_level(tb): + tb = tb.tb_next + + # Skip assert*() traceback levels + if exctype is test.failureException: + self._remove_unittest_tb_frames(tb) + + if first: + ret = tb + first = False + else: + value.__traceback__ = tb + + if value is not None: + for c in (value.__cause__, value.__context__): + if c is not None: + excs.append((type(c), c, c.__traceback__)) + return ret def _is_relevant_tb_level(self, tb): return '__unittest' in tb.tb_frame.f_globals - def _count_relevant_tb_levels(self, tb): - length = 0 + def _remove_unittest_tb_frames(self, tb): + '''Truncates usercode tb at the first unittest frame. + + If the first frame of the traceback is in user code, + the prefix up to the first unittest frame is returned. + If the first frame is already in the unittest module, + the traceback is not modified. + ''' + prev = None while tb and not self._is_relevant_tb_level(tb): - length += 1 + prev = tb tb = tb.tb_next - return length + if prev is not None: + prev.tb_next = None def __repr__(self): return ("<%s run=%i errors=%i failures=%i>" % diff --git a/contrib/tools/python3/src/Lib/urllib/request.py b/contrib/tools/python3/src/Lib/urllib/request.py index bbdc2254e3c..4e289fc67df 100644 --- a/contrib/tools/python3/src/Lib/urllib/request.py +++ b/contrib/tools/python3/src/Lib/urllib/request.py @@ -887,10 +887,10 @@ class HTTPPasswordMgr: return True if base[0] != test[0]: return False - common = posixpath.commonprefix((base[1], test[1])) - if len(common) == len(base[1]): - return True - return False + prefix = base[1] + if prefix[-1:] != '/': + prefix += '/' + return test[1].startswith(prefix) class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr): diff --git a/contrib/tools/python3/src/Lib/xml/etree/ElementTree.py b/contrib/tools/python3/src/Lib/xml/etree/ElementTree.py index fde303c875c..dae2251d859 100644 --- a/contrib/tools/python3/src/Lib/xml/etree/ElementTree.py +++ b/contrib/tools/python3/src/Lib/xml/etree/ElementTree.py @@ -1248,8 +1248,14 @@ def iterparse(source, events=None, parser=None): # Use the internal, undocumented _parser argument for now; When the # parser argument of iterparse is removed, this can be killed. pullparser = XMLPullParser(events=events, _parser=parser) - def iterator(): + + def iterator(source): + close_source = False try: + if not hasattr(source, "read"): + source = open(source, "rb") + close_source = True + yield None while True: yield from pullparser.read_events() # load event buffer @@ -1265,16 +1271,12 @@ def iterparse(source, events=None, parser=None): source.close() class IterParseIterator(collections.abc.Iterator): - __next__ = iterator().__next__ + __next__ = iterator(source).__next__ it = IterParseIterator() it.root = None del iterator, IterParseIterator - close_source = False - if not hasattr(source, "read"): - source = open(source, "rb") - close_source = True - + next(it) return it diff --git a/contrib/tools/python3/src/Lib/zipfile.py b/contrib/tools/python3/src/Lib/zipfile.py index 816f8582bbf..f72c6a4e0c2 100644 --- a/contrib/tools/python3/src/Lib/zipfile.py +++ b/contrib/tools/python3/src/Lib/zipfile.py @@ -1120,8 +1120,15 @@ class _ZipWriteFile(io.BufferedIOBase): def write(self, data): if self.closed: raise ValueError('I/O operation on closed file.') - nbytes = len(data) + + # Accept any data that supports the buffer protocol + if isinstance(data, (bytes, bytearray)): + nbytes = len(data) + else: + data = memoryview(data) + nbytes = data.nbytes self._file_size += nbytes + self._crc = crc32(data, self._crc) if self._compressor: data = self._compressor.compress(data) |
