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, 303 insertions, 188 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' -                  '\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' +                  '   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' +                  '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' -                  '\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', +                  '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" 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)  | 
