diff options
| author | Alexander Smirnov <[email protected]> | 2024-03-18 09:45:29 +0000 |
|---|---|---|
| committer | Alexander Smirnov <[email protected]> | 2024-03-18 09:45:29 +0000 |
| commit | 5ff3b38fce49645bcb7bc2f63cfc22475ead6c09 (patch) | |
| tree | 81728bf248a00ec69169aed99ad92d3b7fb35e2f /contrib/python | |
| parent | f714ab41ab9eff2692f35f7f003562d42b21f89c (diff) | |
| parent | d7c2d188d2464ce858465870a39220c4dfbb5509 (diff) | |
Merge branch 'rightlib' into mergelibs-240318-0944
Diffstat (limited to 'contrib/python')
112 files changed, 858 insertions, 409 deletions
diff --git a/contrib/python/Twisted/py3/.dist-info/METADATA b/contrib/python/Twisted/py3/.dist-info/METADATA index 6f2beda880b..2f5a63dbb8b 100644 --- a/contrib/python/Twisted/py3/.dist-info/METADATA +++ b/contrib/python/Twisted/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: Twisted -Version: 23.10.0 +Version: 24.3.0 Summary: An asynchronous networking framework written in Python Project-URL: Changelog, https://github.com/twisted/twisted/blob/HEAD/NEWS.rst Project-URL: Documentation, https://docs.twistedmatrix.com/ @@ -71,8 +71,8 @@ Requires-Dist: pyobjc-framework-cfnetwork; extra == 'macos_platform' Requires-Dist: pyobjc-framework-cocoa; extra == 'macos_platform' Requires-Dist: twisted[all-non-platform]; extra == 'macos_platform' Provides-Extra: mypy -Requires-Dist: mypy-zope~=1.0.1; extra == 'mypy' -Requires-Dist: mypy~=1.5.1; extra == 'mypy' +Requires-Dist: mypy-zope~=1.0.3; extra == 'mypy' +Requires-Dist: mypy~=1.8; extra == 'mypy' Requires-Dist: twisted[all-non-platform,dev]; extra == 'mypy' Requires-Dist: types-pyopenssl; extra == 'mypy' Requires-Dist: types-setuptools; extra == 'mypy' @@ -82,7 +82,7 @@ Provides-Extra: osx_platform Requires-Dist: twisted[macos-platform]; extra == 'osx_platform' Provides-Extra: serial Requires-Dist: pyserial>=3.0; extra == 'serial' -Requires-Dist: pywin32!=226; platform_system == 'Windows' and extra == 'serial' +Requires-Dist: pywin32!=226; (platform_system == 'Windows') and extra == 'serial' Provides-Extra: test Requires-Dist: cython-test-exception-raiser<2,>=1.0.2; extra == 'test' Requires-Dist: hypothesis>=6.56; extra == 'test' @@ -189,7 +189,7 @@ Or, for speed, use pre-commit directly:: Copyright --------- -All of the code in this distribution is Copyright (c) 2001-2023 Twisted Matrix Laboratories. +All of the code in this distribution is Copyright (c) 2001-2024 Twisted Matrix Laboratories. Twisted is made available under the MIT license. The included `LICENSE <https://github.com/twisted/twisted/blob/trunk/LICENSE>`_ file describes this in detail. diff --git a/contrib/python/Twisted/py3/LICENSE b/contrib/python/Twisted/py3/LICENSE index f3811313cd5..46747386e3e 100644 --- a/contrib/python/Twisted/py3/LICENSE +++ b/contrib/python/Twisted/py3/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2001-2023 +Copyright (c) 2001-2024 Allen Short Amber Hawkie Brown Andrew Bennetts diff --git a/contrib/python/Twisted/py3/README.rst b/contrib/python/Twisted/py3/README.rst index 73783ca21ab..ba458874ce2 100644 --- a/contrib/python/Twisted/py3/README.rst +++ b/contrib/python/Twisted/py3/README.rst @@ -88,7 +88,7 @@ Or, for speed, use pre-commit directly:: Copyright --------- -All of the code in this distribution is Copyright (c) 2001-2023 Twisted Matrix Laboratories. +All of the code in this distribution is Copyright (c) 2001-2024 Twisted Matrix Laboratories. Twisted is made available under the MIT license. The included `LICENSE <LICENSE>`_ file describes this in detail. diff --git a/contrib/python/Twisted/py3/twisted/11715.misc b/contrib/python/Twisted/py3/twisted/11715.misc deleted file mode 100644 index e69de29bb2d..00000000000 --- a/contrib/python/Twisted/py3/twisted/11715.misc +++ /dev/null diff --git a/contrib/python/Twisted/py3/twisted/_version.py b/contrib/python/Twisted/py3/twisted/_version.py index 3f2476fe9ca..1d58c477de0 100644 --- a/contrib/python/Twisted/py3/twisted/_version.py +++ b/contrib/python/Twisted/py3/twisted/_version.py @@ -7,5 +7,5 @@ Provides Twisted version information. from incremental import Version -__version__ = Version("Twisted", 23, 10, 0) +__version__ = Version("Twisted", 24, 3, 0) __all__ = ["__version__"] diff --git a/contrib/python/Twisted/py3/twisted/application/internet.py b/contrib/python/Twisted/py3/twisted/application/internet.py index 194a4dd8a70..9e702f7e844 100644 --- a/contrib/python/Twisted/py3/twisted/application/internet.py +++ b/contrib/python/Twisted/py3/twisted/application/internet.py @@ -41,7 +41,7 @@ reactor.listen/connect* methods for more information. from random import random as _goodEnoughRandom from typing import List -from automat import MethodicalMachine # type: ignore[import] +from automat import MethodicalMachine from twisted.application import service from twisted.internet import task diff --git a/contrib/python/Twisted/py3/twisted/application/runner/_runner.py b/contrib/python/Twisted/py3/twisted/application/runner/_runner.py index 17b21962ae6..01bbaeba1bd 100644 --- a/contrib/python/Twisted/py3/twisted/application/runner/_runner.py +++ b/contrib/python/Twisted/py3/twisted/application/runner/_runner.py @@ -12,7 +12,7 @@ from sys import stderr from typing import Any, Callable, Mapping, TextIO from attr import Factory, attrib, attrs -from constantly import NamedConstant # type: ignore[import] +from constantly import NamedConstant from twisted.internet.interfaces import IReactorCore from twisted.logger import ( diff --git a/contrib/python/Twisted/py3/twisted/conch/unix.py b/contrib/python/Twisted/py3/twisted/conch/unix.py index e314e3cd72d..0696aeb1ac6 100644 --- a/contrib/python/Twisted/py3/twisted/conch/unix.py +++ b/contrib/python/Twisted/py3/twisted/conch/unix.py @@ -43,7 +43,7 @@ from twisted.python import components from twisted.python.compat import nativeString try: - import utmp # type: ignore[import] + import utmp except ImportError: utmp = None diff --git a/contrib/python/Twisted/py3/twisted/copyright.py b/contrib/python/Twisted/py3/twisted/copyright.py index 9aed452d3be..848c7c2fb26 100644 --- a/contrib/python/Twisted/py3/twisted/copyright.py +++ b/contrib/python/Twisted/py3/twisted/copyright.py @@ -13,7 +13,7 @@ from twisted import __version__ as version, version as _longversion longversion = str(_longversion) copyright = """\ -Copyright (c) 2001-2023 Twisted Matrix Laboratories. +Copyright (c) 2001-2024 Twisted Matrix Laboratories. See LICENSE for details.""" disclaimer = """ diff --git a/contrib/python/Twisted/py3/twisted/internet/_dumbwin32proc.py b/contrib/python/Twisted/py3/twisted/internet/_dumbwin32proc.py index 678f54e59b2..22eb26b1a49 100644 --- a/contrib/python/Twisted/py3/twisted/internet/_dumbwin32proc.py +++ b/contrib/python/Twisted/py3/twisted/internet/_dumbwin32proc.py @@ -12,16 +12,16 @@ import sys from zope.interface import implementer -import pywintypes # type: ignore[import] +import pywintypes # Win32 imports -import win32api # type: ignore[import] -import win32con # type: ignore[import] -import win32event # type: ignore[import] -import win32file # type: ignore[import] -import win32pipe # type: ignore[import] -import win32process # type: ignore[import] -import win32security # type: ignore[import] +import win32api +import win32con +import win32event +import win32file +import win32pipe +import win32process +import win32security from twisted.internet import _pollingfile, error from twisted.internet._baseprocess import BaseProcess diff --git a/contrib/python/Twisted/py3/twisted/internet/_glibbase.py b/contrib/python/Twisted/py3/twisted/internet/_glibbase.py index 4a6d1323ab9..587ec1bd05c 100644 --- a/contrib/python/Twisted/py3/twisted/internet/_glibbase.py +++ b/contrib/python/Twisted/py3/twisted/internet/_glibbase.py @@ -22,7 +22,7 @@ from twisted.internet.abstract import FileDescriptor from twisted.internet.interfaces import IReactorFDSet, IReadDescriptor, IWriteDescriptor from twisted.python import log from twisted.python.monkey import MonkeyPatcher -from ._signals import _UnixWaker +from ._signals import _IWaker, _UnixWaker def ensureNotImported(moduleNames, errorMessage, preventImports=[]): @@ -77,7 +77,7 @@ def _signalGlue(): reactor main loop which makes our signal handling work with glib's signal handling. """ - from gi import _ossighelper as signalGlue # type: ignore[import] + from gi import _ossighelper as signalGlue patcher = MonkeyPatcher() patcher.addPatch(signalGlue, "_wakeup_fd_is_active", True) @@ -129,7 +129,7 @@ class GlibReactorBase(posixbase.PosixReactorBase, posixbase._PollLikeMixin): # Install a waker that knows it needs to call C{_simulate} in order to run # callbacks queued from a thread: - def _wakerFactory(self) -> GlibWaker: + def _wakerFactory(self) -> _IWaker: return GlibWaker(self) def __init__(self, glib_module: Any, gtk_module: Any, useGtk: bool = False) -> None: diff --git a/contrib/python/Twisted/py3/twisted/internet/_pollingfile.py b/contrib/python/Twisted/py3/twisted/internet/_pollingfile.py index 758a4cecb72..389182a69ad 100644 --- a/contrib/python/Twisted/py3/twisted/internet/_pollingfile.py +++ b/contrib/python/Twisted/py3/twisted/internet/_pollingfile.py @@ -95,10 +95,10 @@ class _PollingTimer: # If we ever (let's hope not) need the above functionality on UNIX, this could # be factored into a different module. -import pywintypes # type: ignore[import] -import win32api # type: ignore[import] -import win32file # type: ignore[import] -import win32pipe # type: ignore[import] +import pywintypes +import win32api +import win32file +import win32pipe @implementer(IPushProducer) diff --git a/contrib/python/Twisted/py3/twisted/internet/_posixserialport.py b/contrib/python/Twisted/py3/twisted/internet/_posixserialport.py index 636aefa170f..7858362dda0 100644 --- a/contrib/python/Twisted/py3/twisted/internet/_posixserialport.py +++ b/contrib/python/Twisted/py3/twisted/internet/_posixserialport.py @@ -9,8 +9,7 @@ Serial Port Protocol # dependent on pyserial ( http://pyserial.sf.net/ ) # only tested w/ 1.18 (5 Dec 2002) -from serial import PARITY_NONE # type: ignore[import] -from serial import EIGHTBITS, STOPBITS_ONE +from serial import EIGHTBITS, PARITY_NONE, STOPBITS_ONE from twisted.internet import abstract, fdesc from twisted.internet.serialport import BaseSerialPort diff --git a/contrib/python/Twisted/py3/twisted/internet/_signals.py b/contrib/python/Twisted/py3/twisted/internet/_signals.py index fa878f6cbad..18793bfbba2 100644 --- a/contrib/python/Twisted/py3/twisted/internet/_signals.py +++ b/contrib/python/Twisted/py3/twisted/internet/_signals.py @@ -271,12 +271,12 @@ class _IWaker(Interface): disconnected = Attribute("") - def wakeUp(): + def wakeUp() -> None: """ Called when the event should be wake up. """ - def doRead(): + def doRead() -> None: """ Read some data from my connection and discard it. """ diff --git a/contrib/python/Twisted/py3/twisted/internet/_sslverify.py b/contrib/python/Twisted/py3/twisted/internet/_sslverify.py index 552c30bbf0e..abb6bddf7c0 100644 --- a/contrib/python/Twisted/py3/twisted/internet/_sslverify.py +++ b/contrib/python/Twisted/py3/twisted/internet/_sslverify.py @@ -13,10 +13,10 @@ from typing import Dict from zope.interface import Interface, implementer from OpenSSL import SSL, crypto -from OpenSSL._util import lib as pyOpenSSLlib # type: ignore[import] +from OpenSSL._util import lib as pyOpenSSLlib import attr -from constantly import FlagConstant, Flags, NamedConstant, Names # type: ignore[import] +from constantly import FlagConstant, Flags, NamedConstant, Names from incremental import Version from twisted.internet.abstract import isIPAddress, isIPv6Address diff --git a/contrib/python/Twisted/py3/twisted/internet/_win32serialport.py b/contrib/python/Twisted/py3/twisted/internet/_win32serialport.py index 2dda4b9816f..59874ed2f6b 100644 --- a/contrib/python/Twisted/py3/twisted/internet/_win32serialport.py +++ b/contrib/python/Twisted/py3/twisted/internet/_win32serialport.py @@ -10,13 +10,12 @@ Requires PySerial and pywin32. """ -import win32event # type: ignore[import] -import win32file # type: ignore[import] +import win32event +import win32file # system imports -from serial import PARITY_NONE # type: ignore[import] -from serial import EIGHTBITS, STOPBITS_ONE -from serial.serialutil import to_bytes # type: ignore[import] +from serial import EIGHTBITS, PARITY_NONE, STOPBITS_ONE +from serial.serialutil import to_bytes # twisted imports from twisted.internet import abstract diff --git a/contrib/python/Twisted/py3/twisted/internet/_win32stdio.py b/contrib/python/Twisted/py3/twisted/internet/_win32stdio.py index f1ac920f606..104d65f348c 100644 --- a/contrib/python/Twisted/py3/twisted/internet/_win32stdio.py +++ b/contrib/python/Twisted/py3/twisted/internet/_win32stdio.py @@ -10,7 +10,7 @@ import os from zope.interface import implementer -import win32api # type: ignore[import] +import win32api from twisted.internet import _pollingfile, main from twisted.internet.interfaces import ( diff --git a/contrib/python/Twisted/py3/twisted/internet/cfreactor.py b/contrib/python/Twisted/py3/twisted/internet/cfreactor.py index 142c0472ef4..f686092e69d 100644 --- a/contrib/python/Twisted/py3/twisted/internet/cfreactor.py +++ b/contrib/python/Twisted/py3/twisted/internet/cfreactor.py @@ -17,7 +17,7 @@ import sys from zope.interface import implementer -from CFNetwork import ( # type: ignore[import] +from CFNetwork import ( CFSocketCreateRunLoopSource, CFSocketCreateWithNative, CFSocketDisableCallBacks, @@ -30,7 +30,7 @@ from CFNetwork import ( # type: ignore[import] kCFSocketReadCallBack, kCFSocketWriteCallBack, ) -from CoreFoundation import ( # type: ignore[import] +from CoreFoundation import ( CFAbsoluteTimeGetCurrent, CFRunLoopAddSource, CFRunLoopAddTimer, diff --git a/contrib/python/Twisted/py3/twisted/internet/defer.py b/contrib/python/Twisted/py3/twisted/internet/defer.py index 17e717cad28..caafb52210e 100644 --- a/contrib/python/Twisted/py3/twisted/internet/defer.py +++ b/contrib/python/Twisted/py3/twisted/internet/defer.py @@ -17,7 +17,7 @@ from asyncio import AbstractEventLoop, Future, iscoroutine from contextvars import Context as _Context, copy_context as _copy_context from enum import Enum from functools import wraps -from sys import exc_info +from sys import exc_info, implementation from types import CoroutineType, GeneratorType, MappingProxyType, TracebackType from typing import ( TYPE_CHECKING, @@ -58,6 +58,9 @@ log = Logger() _T = TypeVar("_T") _P = ParamSpec("_P") +# See use in _inlineCallbacks for explanation and removal timeline. +_oldPypyStack = _PYPY and implementation.version < (7, 3, 14) + class AlreadyCalledError(Exception): """ @@ -1583,7 +1586,7 @@ class DeferredList( # type: ignore[no-redef] # noqa:F811 def _parseDeferredListResult( - resultList: List[_DeferredListResultItemT[_T]], fireOnOneErrback: bool = False + resultList: List[_DeferredListResultItemT[_T]], fireOnOneErrback: bool = False, / ) -> List[_T]: if __debug__: for result in resultList: @@ -1617,9 +1620,9 @@ def gatherResults( is useful to prevent spurious 'Unhandled error in Deferred' messages from being logged. This parameter is available since 11.1.0. """ - d = DeferredList(deferredList, fireOnOneErrback=True, consumeErrors=consumeErrors) - d.addCallback(_parseDeferredListResult) - return cast(Deferred[List[_T]], d) + return DeferredList( + deferredList, fireOnOneErrback=True, consumeErrors=consumeErrors + ).addCallback(_parseDeferredListResult) class FailureGroup(Exception): @@ -2022,8 +2025,10 @@ def _inlineCallbacks( appCodeTrace = traceback.tb_next assert appCodeTrace is not None - if _PYPY: - # PyPy as of 3.7 adds an extra frame. + if _oldPypyStack: + # PyPy versions through 7.3.13 add an extra frame; 7.3.14 fixed + # this discrepancy with CPython. This code can be removed once + # we no longer need to support PyPy 7.3.13 or older. appCodeTrace = appCodeTrace.tb_next assert appCodeTrace is not None @@ -2116,14 +2121,13 @@ def _addCancelCallbackToDeferred( @param status: a L{_CancellationStatus} tracking the current status of C{gen} """ it.callbacks, tmp = [], it.callbacks - it.addErrback(_handleCancelInlineCallbacks, status) + it = it.addErrback(_handleCancelInlineCallbacks, status) it.callbacks.extend(tmp) it.errback(_InternalInlineCallbacksCancelledError()) def _handleCancelInlineCallbacks( - result: Failure, - status: _CancellationStatus[_T], + result: Failure, status: _CancellationStatus[_T], / ) -> Deferred[_T]: """ Propagate the cancellation of an C{@}L{inlineCallbacks} to the diff --git a/contrib/python/Twisted/py3/twisted/internet/endpoints.py b/contrib/python/Twisted/py3/twisted/internet/endpoints.py index 4a4cf55e8e9..7ab1d817319 100644 --- a/contrib/python/Twisted/py3/twisted/internet/endpoints.py +++ b/contrib/python/Twisted/py3/twisted/internet/endpoints.py @@ -22,7 +22,7 @@ from unicodedata import normalize from zope.interface import directlyProvides, implementer, provider -from constantly import NamedConstant, Names # type: ignore[import] +from constantly import NamedConstant, Names from incremental import Version from twisted.internet import defer, error, fdesc, interfaces, threads diff --git a/contrib/python/Twisted/py3/twisted/internet/gireactor.py b/contrib/python/Twisted/py3/twisted/internet/gireactor.py index e9c072f41a6..4a193a79ec4 100644 --- a/contrib/python/Twisted/py3/twisted/internet/gireactor.py +++ b/contrib/python/Twisted/py3/twisted/internet/gireactor.py @@ -23,7 +23,7 @@ On Python 3, pygobject v3.4 or later is required. from typing import Union -from gi.repository import GLib # type:ignore[import] +from gi.repository import GLib from twisted.internet import _glibbase from twisted.internet.error import ReactorAlreadyRunning diff --git a/contrib/python/Twisted/py3/twisted/internet/gtk2reactor.py b/contrib/python/Twisted/py3/twisted/internet/gtk2reactor.py index b4e0c4c4e1c..d0fc7440831 100644 --- a/contrib/python/Twisted/py3/twisted/internet/gtk2reactor.py +++ b/contrib/python/Twisted/py3/twisted/internet/gtk2reactor.py @@ -43,13 +43,13 @@ from twisted.python import runtime try: if not hasattr(sys, "frozen"): # Don't want to check this for py2exe - import pygtk # type: ignore[import] + import pygtk pygtk.require("2.0") except (ImportError, AttributeError): pass # maybe we're using pygtk before this hack existed. -import gobject # type: ignore[import] +import gobject if not hasattr(gobject, "IO_HUP"): # gi.repository's legacy compatibility helper raises an AttributeError with @@ -74,7 +74,7 @@ class Gtk2Reactor(_glibbase.GlibReactorBase): def __init__(self, useGtk=True): _gtk = None if useGtk is True: - import gtk as _gtk # type: ignore[import] + import gtk as _gtk _glibbase.GlibReactorBase.__init__(self, gobject, _gtk, useGtk=useGtk) diff --git a/contrib/python/Twisted/py3/twisted/internet/iocpreactor/iocpsupport.py b/contrib/python/Twisted/py3/twisted/internet/iocpreactor/iocpsupport.py index 826c976487f..9cb9f16da29 100644 --- a/contrib/python/Twisted/py3/twisted/internet/iocpreactor/iocpsupport.py +++ b/contrib/python/Twisted/py3/twisted/internet/iocpreactor/iocpsupport.py @@ -12,7 +12,7 @@ __all__ = [ "send", ] -from twisted_iocpsupport.iocpsupport import ( # type: ignore[import] +from twisted_iocpsupport.iocpsupport import ( # type: ignore[import-not-found] CompletionPort, Event, accept, diff --git a/contrib/python/Twisted/py3/twisted/internet/iocpreactor/tcp.py b/contrib/python/Twisted/py3/twisted/internet/iocpreactor/tcp.py index aadd685269c..ef72b7ed7e5 100644 --- a/contrib/python/Twisted/py3/twisted/internet/iocpreactor/tcp.py +++ b/contrib/python/Twisted/py3/twisted/internet/iocpreactor/tcp.py @@ -5,15 +5,19 @@ TCP support for IOCP reactor """ +from __future__ import annotations + import errno import socket import struct -from typing import Optional +from typing import TYPE_CHECKING, Optional, Union from zope.interface import classImplements, implementer from twisted.internet import address, defer, error, interfaces, main from twisted.internet.abstract import _LogOwner, isIPv6Address +from twisted.internet.address import IPv4Address, IPv6Address +from twisted.internet.interfaces import IProtocol from twisted.internet.iocpreactor import abstract, iocpsupport as _iocp from twisted.internet.iocpreactor.const import ( ERROR_CONNECTION_REFUSED, @@ -42,6 +46,9 @@ except ImportError: else: _startTLS = __startTLS +if TYPE_CHECKING: + # Circular import only to describe a type. + from twisted.internet.iocpreactor.reactor import IOCPReactor # ConnectEx returns these. XXX: find out what it does for timeout connectExErrors = { @@ -345,7 +352,15 @@ class Server(Connection): _tlsClientDefault = False - def __init__(self, sock, protocol, clientAddr, serverAddr, sessionno, reactor): + def __init__( + self, + sock: socket.socket, + protocol: IProtocol, + clientAddr: Union[IPv4Address, IPv6Address], + serverAddr: Union[IPv4Address, IPv6Address], + sessionno: int, + reactor: IOCPReactor, + ): """ Server(sock, protocol, client, server, sessionno) diff --git a/contrib/python/Twisted/py3/twisted/internet/posixbase.py b/contrib/python/Twisted/py3/twisted/internet/posixbase.py index bd160ec8656..ed218b37f35 100644 --- a/contrib/python/Twisted/py3/twisted/internet/posixbase.py +++ b/contrib/python/Twisted/py3/twisted/internet/posixbase.py @@ -68,7 +68,7 @@ if unixEnabled: if platform.isWindows(): try: - import win32process # type: ignore[import] + import win32process processEnabled = True except ImportError: diff --git a/contrib/python/Twisted/py3/twisted/internet/process.py b/contrib/python/Twisted/py3/twisted/internet/process.py index ef3b88d9f19..ff7684e358b 100644 --- a/contrib/python/Twisted/py3/twisted/internet/process.py +++ b/contrib/python/Twisted/py3/twisted/internet/process.py @@ -879,7 +879,7 @@ class Process(_BaseProcess): else: fdState.append((eachFD, isCloseOnExec)) if environment is None: - environment = {} + environment = os.environ setSigDef = [ everySignal diff --git a/contrib/python/Twisted/py3/twisted/internet/pyuisupport.py b/contrib/python/Twisted/py3/twisted/internet/pyuisupport.py index bfbffb9cb40..265fea24055 100644 --- a/contrib/python/Twisted/py3/twisted/internet/pyuisupport.py +++ b/contrib/python/Twisted/py3/twisted/internet/pyuisupport.py @@ -11,7 +11,7 @@ See doc/examples/pyuidemo.py for example usage. """ # System imports -import pyui # type: ignore[import] +import pyui # type: ignore[import-not-found] def _guiUpdate(reactor, delay): diff --git a/contrib/python/Twisted/py3/twisted/internet/serialport.py b/contrib/python/Twisted/py3/twisted/internet/serialport.py index d63d4ce4351..4fda3b9115d 100644 --- a/contrib/python/Twisted/py3/twisted/internet/serialport.py +++ b/contrib/python/Twisted/py3/twisted/internet/serialport.py @@ -26,7 +26,7 @@ __all__ = [ ] # all of them require pyserial at the moment, so check that first -import serial # type: ignore[import] +import serial from serial import ( EIGHTBITS, FIVEBITS, diff --git a/contrib/python/Twisted/py3/twisted/internet/ssl.py b/contrib/python/Twisted/py3/twisted/internet/ssl.py index 1ad02b3c097..902268bab49 100644 --- a/contrib/python/Twisted/py3/twisted/internet/ssl.py +++ b/contrib/python/Twisted/py3/twisted/internet/ssl.py @@ -53,6 +53,7 @@ APIs listed above. throughout the documentation. """ +from __future__ import annotations from zope.interface import implementedBy, implementer, implementer_only @@ -180,6 +181,8 @@ class Server(tcp.Server): I am an SSL server. """ + server: Port + def __init__(self, *args, **kwargs): tcp.Server.__init__(self, *args, **kwargs) self.startTLS(self.server.ctxFactory) diff --git a/contrib/python/Twisted/py3/twisted/internet/tcp.py b/contrib/python/Twisted/py3/twisted/internet/tcp.py index c87b5b73339..8f85025556b 100644 --- a/contrib/python/Twisted/py3/twisted/internet/tcp.py +++ b/contrib/python/Twisted/py3/twisted/internet/tcp.py @@ -8,13 +8,13 @@ Various asynchronous TCP/IP classes. End users shouldn't use this module directly - use the reactor APIs instead. """ -import os +from __future__ import annotations -# System Imports +import os import socket import struct import sys -from typing import Callable, ClassVar, List, Optional +from typing import Callable, ClassVar, List, Optional, Union from zope.interface import Interface, implementer @@ -24,6 +24,8 @@ import typing_extensions from twisted.internet.interfaces import ( IHalfCloseableProtocol, IListeningPort, + IProtocol, + IReactorTCP, ISystemHandle, ITCPTransport, ) @@ -781,9 +783,19 @@ class Server(_TLSServerMixin, Connection): _base = Connection - _addressType = address.IPv4Address + _addressType: Union[ + type[address.IPv4Address], type[address.IPv6Address] + ] = address.IPv4Address - def __init__(self, sock, protocol, client, server, sessionno, reactor): + def __init__( + self, + sock: socket.socket, + protocol: IProtocol, + client: tuple[object, ...], + server: Port, + sessionno: int, + reactor: IReactorTCP, + ) -> None: """ Server(sock, protocol, client, server, sessionno) diff --git a/contrib/python/Twisted/py3/twisted/internet/win32eventreactor.py b/contrib/python/Twisted/py3/twisted/internet/win32eventreactor.py index 0e96012ea58..8fbef7d554d 100644 --- a/contrib/python/Twisted/py3/twisted/internet/win32eventreactor.py +++ b/contrib/python/Twisted/py3/twisted/internet/win32eventreactor.py @@ -54,13 +54,7 @@ from weakref import WeakKeyDictionary from zope.interface import implementer # Win32 imports -from win32file import ( # type: ignore[import] - FD_ACCEPT, - FD_CLOSE, - FD_CONNECT, - FD_READ, - WSAEventSelect, -) +from win32file import FD_ACCEPT, FD_CLOSE, FD_CONNECT, FD_READ, WSAEventSelect try: # WSAEnumNetworkEvents was added in pywin32 215 @@ -77,8 +71,8 @@ except ImportError: return {FD_READ} -import win32gui # type: ignore[import] -from win32event import ( # type: ignore[import] +import win32gui # type: ignore[import-untyped] +from win32event import ( QS_ALLINPUT, WAIT_OBJECT_0, WAIT_TIMEOUT, diff --git a/contrib/python/Twisted/py3/twisted/internet/wxreactor.py b/contrib/python/Twisted/py3/twisted/internet/wxreactor.py index b988724dfa7..257c5259ce7 100644 --- a/contrib/python/Twisted/py3/twisted/internet/wxreactor.py +++ b/contrib/python/Twisted/py3/twisted/internet/wxreactor.py @@ -26,14 +26,14 @@ real applications. from queue import Empty, Queue try: - from wx import ( # type: ignore[import] + from wx import ( CallAfter as wxCallAfter, PySimpleApp as wxPySimpleApp, Timer as wxTimer, ) except ImportError: # older version of wxPython: - from wxPython.wx import wxPySimpleApp, wxCallAfter, wxTimer # type: ignore[import] + from wxPython.wx import wxPySimpleApp, wxCallAfter, wxTimer from twisted.internet import _threadedselect from twisted.python import log, runtime diff --git a/contrib/python/Twisted/py3/twisted/logger/_filter.py b/contrib/python/Twisted/py3/twisted/logger/_filter.py index fa4220ea3e0..07e443849a1 100644 --- a/contrib/python/Twisted/py3/twisted/logger/_filter.py +++ b/contrib/python/Twisted/py3/twisted/logger/_filter.py @@ -11,7 +11,7 @@ from typing import Dict, Iterable from zope.interface import Interface, implementer -from constantly import NamedConstant, Names # type: ignore[import] +from constantly import NamedConstant, Names from ._interfaces import ILogObserver, LogEvent from ._levels import InvalidLogLevelError, LogLevel diff --git a/contrib/python/Twisted/py3/twisted/logger/_format.py b/contrib/python/Twisted/py3/twisted/logger/_format.py index 4bc06ec40c4..59b44c7f723 100644 --- a/contrib/python/Twisted/py3/twisted/logger/_format.py +++ b/contrib/python/Twisted/py3/twisted/logger/_format.py @@ -6,10 +6,12 @@ Tools for formatting logging events. """ +from __future__ import annotations + from datetime import datetime as DateTime from typing import Any, Callable, Iterator, Mapping, Optional, Union, cast -from constantly import NamedConstant # type: ignore[import] +from constantly import NamedConstant from twisted.python._tzhelper import FixedOffsetTimeZone from twisted.python.failure import Failure @@ -164,6 +166,57 @@ def formatEventAsClassicLogText( return eventText + "\n" +def keycall(key: str, getter: Callable[[str], Any]) -> PotentialCallWrapper: + """ + Check to see if C{key} ends with parentheses ("C{()}"); if not, wrap up the + result of C{get} in a L{PotentialCallWrapper}. Otherwise, call the result + of C{get} first, before wrapping it up. + + @param key: The last dotted segment of a formatting key, as parsed by + L{Formatter.vformat}, which may end in C{()}. + + @param getter: A function which takes a string and returns some other + object, to be formatted and stringified for a log. + + @return: A L{PotentialCallWrapper} that will wrap up the result to allow + for subsequent usages of parens to defer execution to log-format time. + """ + callit = key.endswith("()") + realKey = key[:-2] if callit else key + value = getter(realKey) + if callit: + value = value() + return PotentialCallWrapper(value) + + +class PotentialCallWrapper(object): + """ + Object wrapper that wraps C{getattr()} so as to process call-parentheses + C{"()"} after a dotted attribute access. + """ + + def __init__(self, wrapped: object) -> None: + self._wrapped = wrapped + + def __getattr__(self, name: str) -> object: + return keycall(name, self._wrapped.__getattribute__) + + def __getitem__(self, name: str) -> object: + # The sub-object may not be indexable, but if it isn't, that's the + # caller's problem. + value = self._wrapped[name] # type:ignore[index] + return PotentialCallWrapper(value) + + def __format__(self, format_spec: str) -> str: + return self._wrapped.__format__(format_spec) + + def __repr__(self) -> str: + return self._wrapped.__repr__() + + def __str__(self) -> str: + return self._wrapped.__str__() + + class CallMapping(Mapping[str, Any]): """ Read-only mapping that turns a C{()}-suffix in key names into an invocation @@ -190,12 +243,7 @@ class CallMapping(Mapping[str, Any]): Look up an item in the submapping for this L{CallMapping}, calling it if C{key} ends with C{"()"}. """ - callit = key.endswith("()") - realKey = key[:-2] if callit else key - value = self._submapping[realKey] - if callit: - value = value() - return value + return keycall(key, self._submapping.__getitem__) def formatWithCall(formatString: str, mapping: Mapping[str, Any]) -> str: diff --git a/contrib/python/Twisted/py3/twisted/logger/_io.py b/contrib/python/Twisted/py3/twisted/logger/_io.py index 7a49718db71..96634212201 100644 --- a/contrib/python/Twisted/py3/twisted/logger/_io.py +++ b/contrib/python/Twisted/py3/twisted/logger/_io.py @@ -9,7 +9,7 @@ File-like object that logs. import sys from typing import AnyStr, Iterable, Optional -from constantly import NamedConstant # type: ignore[import] +from constantly import NamedConstant from incremental import Version from twisted.python.deprecate import deprecatedProperty diff --git a/contrib/python/Twisted/py3/twisted/logger/_json.py b/contrib/python/Twisted/py3/twisted/logger/_json.py index 2ecdd43045a..0cc05ce5011 100644 --- a/contrib/python/Twisted/py3/twisted/logger/_json.py +++ b/contrib/python/Twisted/py3/twisted/logger/_json.py @@ -10,7 +10,7 @@ from json import dumps, loads from typing import IO, Any, AnyStr, Dict, Iterable, Optional, Union, cast from uuid import UUID -from constantly import NamedConstant # type: ignore[import] +from constantly import NamedConstant from twisted.python.failure import Failure from ._file import FileLogObserver diff --git a/contrib/python/Twisted/py3/twisted/logger/_levels.py b/contrib/python/Twisted/py3/twisted/logger/_levels.py index 800a549f88c..39fab342de4 100644 --- a/contrib/python/Twisted/py3/twisted/logger/_levels.py +++ b/contrib/python/Twisted/py3/twisted/logger/_levels.py @@ -6,7 +6,7 @@ Log levels. """ -from constantly import NamedConstant, Names # type: ignore[import] +from constantly import NamedConstant, Names class InvalidLogLevelError(Exception): diff --git a/contrib/python/Twisted/py3/twisted/logger/_stdlib.py b/contrib/python/Twisted/py3/twisted/logger/_stdlib.py index 030b643883e..abc707e4a82 100644 --- a/contrib/python/Twisted/py3/twisted/logger/_stdlib.py +++ b/contrib/python/Twisted/py3/twisted/logger/_stdlib.py @@ -11,7 +11,7 @@ from typing import Mapping, Tuple from zope.interface import implementer -from constantly import NamedConstant # type: ignore[import] +from constantly import NamedConstant from twisted.python.compat import currentframe from ._format import formatEvent diff --git a/contrib/python/Twisted/py3/twisted/pair/tuntap.py b/contrib/python/Twisted/py3/twisted/pair/tuntap.py index a5f6dbef3bf..2564257966b 100644 --- a/contrib/python/Twisted/py3/twisted/pair/tuntap.py +++ b/contrib/python/Twisted/py3/twisted/pair/tuntap.py @@ -19,7 +19,7 @@ from typing import Tuple from zope.interface import Attribute, Interface, implementer -from constantly import FlagConstant, Flags # type: ignore[import] +from constantly import FlagConstant, Flags from incremental import Version from twisted.internet import abstract, defer, error, interfaces, task diff --git a/contrib/python/Twisted/py3/twisted/positioning/base.py b/contrib/python/Twisted/py3/twisted/positioning/base.py index 7ac5398cd95..460f5b4ff20 100644 --- a/contrib/python/Twisted/py3/twisted/positioning/base.py +++ b/contrib/python/Twisted/py3/twisted/positioning/base.py @@ -14,7 +14,7 @@ from typing import ClassVar, Sequence from zope.interface import implementer -from constantly import NamedConstant, Names # type: ignore[import] +from constantly import NamedConstant, Names from twisted.positioning import ipositioning from twisted.python.util import FancyEqMixin diff --git a/contrib/python/Twisted/py3/twisted/positioning/nmea.py b/contrib/python/Twisted/py3/twisted/positioning/nmea.py index 128c1b7938c..b1f761f5984 100644 --- a/contrib/python/Twisted/py3/twisted/positioning/nmea.py +++ b/contrib/python/Twisted/py3/twisted/positioning/nmea.py @@ -26,7 +26,7 @@ from functools import reduce from zope.interface import implementer -from constantly import ValueConstant, Values # type: ignore[import] +from constantly import ValueConstant, Values from twisted.positioning import _sentence, base, ipositioning from twisted.positioning.base import Angles diff --git a/contrib/python/Twisted/py3/twisted/protocols/amp.py b/contrib/python/Twisted/py3/twisted/protocols/amp.py index a8c35754a99..ac28a92bfa4 100644 --- a/contrib/python/Twisted/py3/twisted/protocols/amp.py +++ b/contrib/python/Twisted/py3/twisted/protocols/amp.py @@ -202,7 +202,18 @@ from io import BytesIO from itertools import count from struct import pack from types import MethodType -from typing import Any, Callable, Dict, List, Optional, Tuple, Type, TypeVar, Union +from typing import ( + Any, + Callable, + ClassVar, + Dict, + List, + Optional, + Tuple, + Type, + TypeVar, + Union, +) from zope.interface import Interface, implementer @@ -1686,18 +1697,23 @@ class Descriptor(Integer): return outString +_Self = TypeVar("_Self") + + class _CommandMeta(type): """ Metaclass hack to establish reverse-mappings for 'errors' and 'fatalErrors' as class vars. """ - def __new__(cls, name, bases, attrs): + def __new__( + cls: type[_Self], name: str, bases: tuple[type], attrs: dict[str, object] + ) -> Type[Command]: reverseErrors = attrs["reverseErrors"] = {} er = attrs["allErrors"] = {} if "commandName" not in attrs: attrs["commandName"] = name.encode("ascii") - newtype = type.__new__(cls, name, bases, attrs) + newtype: Type[Command] = type.__new__(cls, name, bases, attrs) # type:ignore if not isinstance(newtype.commandName, bytes): raise TypeError( @@ -1705,12 +1721,12 @@ class _CommandMeta(type): newtype.commandName ) ) - for name, _ in newtype.arguments: - if not isinstance(name, bytes): - raise TypeError(f"Argument names must be byte strings, got: {name!r}") - for name, _ in newtype.response: - if not isinstance(name, bytes): - raise TypeError(f"Response names must be byte strings, got: {name!r}") + for bname, _ in newtype.arguments: + if not isinstance(bname, bytes): + raise TypeError(f"Argument names must be byte strings, got: {bname!r}") + for bname, _ in newtype.response: + if not isinstance(bname, bytes): + raise TypeError(f"Response names must be byte strings, got: {bname!r}") errors: Dict[Type[Exception], bytes] = {} fatalErrors: Dict[Type[Exception], bytes] = {} @@ -1718,9 +1734,9 @@ class _CommandMeta(type): accumulateClassDict(newtype, "fatalErrors", fatalErrors) if not isinstance(newtype.errors, dict): - newtype.errors = dict(newtype.errors) + newtype.errors = dict(newtype.errors) # type:ignore[unreachable] if not isinstance(newtype.fatalErrors, dict): - newtype.fatalErrors = dict(newtype.fatalErrors) + newtype.fatalErrors = dict(newtype.fatalErrors) # type:ignore[unreachable] for v, k in errors.items(): reverseErrors[k] = v @@ -1729,13 +1745,13 @@ class _CommandMeta(type): reverseErrors[k] = v er[v] = k - for _, name in newtype.errors.items(): - if not isinstance(name, bytes): - raise TypeError(f"Error names must be byte strings, got: {name!r}") - for _, name in newtype.fatalErrors.items(): - if not isinstance(name, bytes): + for _, bname in newtype.errors.items(): + if not isinstance(bname, bytes): + raise TypeError(f"Error names must be byte strings, got: {bname!r}") + for _, bname in newtype.fatalErrors.items(): + if not isinstance(bname, bytes): raise TypeError( - f"Fatal error names must be byte strings, got: {name!r}" + f"Fatal error names must be byte strings, got: {bname!r}" ) return newtype @@ -1784,14 +1800,15 @@ class Command(metaclass=_CommandMeta): want one. """ - arguments: List[Tuple[bytes, Argument]] = [] - response: List[Tuple[bytes, Argument]] = [] - extra: List[Any] = [] - errors: Dict[Type[Exception], bytes] = {} - fatalErrors: Dict[Type[Exception], bytes] = {} + commandName: ClassVar[bytes] + arguments: ClassVar[List[Tuple[bytes, Argument]]] = [] + response: ClassVar[List[Tuple[bytes, Argument]]] = [] + extra: ClassVar[List[Any]] = [] + errors: ClassVar[Dict[Type[Exception], bytes]] = {} + fatalErrors: ClassVar[Dict[Type[Exception], bytes]] = {} - commandType: "Union[Type[Command], Type[Box]]" = Box - responseType: Type[AmpBox] = Box + commandType: "ClassVar[Union[Type[Command], Type[Box]]]" = Box + responseType: ClassVar[Type[AmpBox]] = Box requiresAnswer = True diff --git a/contrib/python/Twisted/py3/twisted/protocols/haproxy/_v2parser.py b/contrib/python/Twisted/py3/twisted/protocols/haproxy/_v2parser.py index 5b8e5874018..cfcf7c99bcc 100644 --- a/contrib/python/Twisted/py3/twisted/protocols/haproxy/_v2parser.py +++ b/contrib/python/Twisted/py3/twisted/protocols/haproxy/_v2parser.py @@ -13,7 +13,7 @@ from typing import Callable, Tuple, Type, Union from zope.interface import implementer -from constantly import ValueConstant, Values # type: ignore[import] +from constantly import ValueConstant, Values from typing_extensions import Literal from twisted.internet import address diff --git a/contrib/python/Twisted/py3/twisted/protocols/tls.py b/contrib/python/Twisted/py3/twisted/protocols/tls.py index d2ac2d2cf80..be7a58ce4d3 100644 --- a/contrib/python/Twisted/py3/twisted/protocols/tls.py +++ b/contrib/python/Twisted/py3/twisted/protocols/tls.py @@ -708,7 +708,7 @@ class _AggregateSmallWrites: self._write = write self._clock = clock self._buffer: list[bytes] = [] - self._bufferLen = 0 + self._bufferLeft = self.MAX_BUFFER_SIZE self._scheduled: Optional[IDelayedCall] = None def write(self, data: bytes) -> None: @@ -719,9 +719,9 @@ class _AggregateSmallWrites: Accumulating too much data can result in higher memory usage. """ self._buffer.append(data) - self._bufferLen += len(data) + self._bufferLeft -= len(data) - if self._bufferLen > self.MAX_BUFFER_SIZE: + if self._bufferLeft < 0: # We've accumulated enough we should just write it out. No need to # schedule a flush, since we just flushed everything. self.flush() @@ -744,7 +744,7 @@ class _AggregateSmallWrites: def flush(self) -> None: """Flush any buffered writes.""" if self._buffer: - self._bufferLen = 0 + self._bufferLeft = self.MAX_BUFFER_SIZE self._write(b"".join(self._buffer)) del self._buffer[:] @@ -764,19 +764,20 @@ def _get_default_clock() -> IReactorTime: class BufferingTLSTransport(TLSMemoryBIOProtocol): """ A TLS transport implemented by wrapping buffering around a - ``TLSMemoryBIOProtocol``. + L{TLSMemoryBIOProtocol}. - Doing many small writes directly to a ``OpenSSL.SSL.Connection``, as - implemented in ``TLSMemoryBIOProtocol``, can add significant CPU and + Doing many small writes directly to a L{OpenSSL.SSL.Connection}, as + implemented in L{TLSMemoryBIOProtocol}, can add significant CPU and bandwidth overhead. Thus, even when writing is possible, small writes will get aggregated and written as a single write at the next reactor iteration. """ - # Note: An implementation based on composition would be nicer, but there's - # close integration between ``ProtocolWrapper`` subclasses like - # ``TLSMemoryBIOProtocol`` and the corresponding factory. Composition broke - # things like ``TLSMemoryBIOFactory.protocols`` having the correct - # instances, whereas subclassing makes that work. + # Implementation Note: An implementation based on composition would be + # nicer, but there's close integration between L{ProtocolWrapper} + # subclasses like L{TLSMemoryBIOProtocol} and the corresponding factory. An + # attempt to implement this with broke things like + # L{TLSMemoryBIOFactory.protocols} having the correct instances, whereas + # subclassing makes that work. def __init__( self, @@ -787,11 +788,10 @@ class BufferingTLSTransport(TLSMemoryBIOProtocol): super().__init__(factory, wrappedProtocol, _connectWrapped) actual_write = super().write self._aggregator = _AggregateSmallWrites(actual_write, factory._clock) - - def write(self, data: bytes) -> None: - if isinstance(data, str): # type: ignore[unreachable] - raise TypeError("Must write bytes to a TLS transport, not str.") - self._aggregator.write(data) + # This is kinda ugly, but speeds things up a lot in a hot path with + # lots of small TLS writes. May become unnecessary in Python 3.13 or + # later if JIT and/or inlining becomes a thing. + self.write = self._aggregator.write # type: ignore[method-assign] def writeSequence(self, sequence: Iterable[bytes]) -> None: self._aggregator.write(b"".join(sequence)) diff --git a/contrib/python/Twisted/py3/twisted/python/_appdirs.py b/contrib/python/Twisted/py3/twisted/python/_appdirs.py index 8ceb1116762..90f5858c96c 100644 --- a/contrib/python/Twisted/py3/twisted/python/_appdirs.py +++ b/contrib/python/Twisted/py3/twisted/python/_appdirs.py @@ -9,7 +9,7 @@ Application data directory support. import inspect from typing import cast -import appdirs # type: ignore[import] +import appdirs # type: ignore[import-untyped] from twisted.python.compat import currentframe diff --git a/contrib/python/Twisted/py3/twisted/python/constants.py b/contrib/python/Twisted/py3/twisted/python/constants.py index fbad78e4080..df970363c62 100644 --- a/contrib/python/Twisted/py3/twisted/python/constants.py +++ b/contrib/python/Twisted/py3/twisted/python/constants.py @@ -9,13 +9,6 @@ numeric, and bit flag values. # Import and re-export Constantly -from constantly import ( # type: ignore[import] - FlagConstant, - Flags, - NamedConstant, - Names, - ValueConstant, - Values, -) +from constantly import FlagConstant, Flags, NamedConstant, Names, ValueConstant, Values __all__ = ["NamedConstant", "ValueConstant", "FlagConstant", "Names", "Values", "Flags"] diff --git a/contrib/python/Twisted/py3/twisted/python/deprecate.py b/contrib/python/Twisted/py3/twisted/python/deprecate.py index c85b98d6272..c5df556f709 100644 --- a/contrib/python/Twisted/py3/twisted/python/deprecate.py +++ b/contrib/python/Twisted/py3/twisted/python/deprecate.py @@ -601,12 +601,19 @@ def warnAboutFunction(offender, warningString): """ # inspect.getmodule() is attractive, but somewhat # broken in Python < 2.6. See Python bug 4845. + # In Python 3.13 line numbers returned by findlinestarts + # can be None for bytecode that does not map to source + # lines. offenderModule = sys.modules[offender.__module__] warn_explicit( warningString, category=DeprecationWarning, filename=inspect.getabsfile(offenderModule), - lineno=max(lineNumber for _, lineNumber in findlinestarts(offender.__code__)), + lineno=max( + lineNumber + for _, lineNumber in findlinestarts(offender.__code__) + if lineNumber is not None + ), module=offenderModule.__name__, registry=offender.__globals__.setdefault("__warningregistry__", {}), module_globals=None, diff --git a/contrib/python/Twisted/py3/twisted/python/failure.py b/contrib/python/Twisted/py3/twisted/python/failure.py index ca893ca4c94..c006d555e55 100644 --- a/contrib/python/Twisted/py3/twisted/python/failure.py +++ b/contrib/python/Twisted/py3/twisted/python/failure.py @@ -516,7 +516,7 @@ class Failure(BaseException): """ # Note that the actual magic to find the traceback information # is done in _findFailure. - return g.throw(self.type, self.value, self.tb) + return g.throw(self.value.with_traceback(self.tb)) @classmethod def _findFailure(cls): diff --git a/contrib/python/Twisted/py3/twisted/python/lockfile.py b/contrib/python/Twisted/py3/twisted/python/lockfile.py index c285d4ad102..bea04ee560f 100644 --- a/contrib/python/Twisted/py3/twisted/python/lockfile.py +++ b/contrib/python/Twisted/py3/twisted/python/lockfile.py @@ -39,8 +39,8 @@ else: # race-conditions duty. - hawkie try: - import pywintypes # type: ignore[import] - from win32api import OpenProcess # type: ignore[import] + import pywintypes + from win32api import OpenProcess except ImportError: kill = None # type: ignore[assignment] else: diff --git a/contrib/python/Twisted/py3/twisted/python/modules.py b/contrib/python/Twisted/py3/twisted/python/modules.py index aea6a6ed828..d2294a593a8 100644 --- a/contrib/python/Twisted/py3/twisted/python/modules.py +++ b/contrib/python/Twisted/py3/twisted/python/modules.py @@ -56,6 +56,7 @@ the modules outside the standard library's python-files directory:: @type theSystemPath: L{PythonPath} """ +from __future__ import annotations import inspect import sys @@ -251,7 +252,9 @@ class PythonAttribute: this class. """ - def __init__(self, name, onObject, loaded, pythonValue): + def __init__( + self, name: str, onObject: PythonAttribute, loaded: bool, pythonValue: object + ) -> None: """ Create a PythonAttribute. This is a private constructor. Do not construct me directly, use PythonModule.iterAttributes. @@ -306,7 +309,9 @@ class PythonModule(_ModuleIteratorHelper): from. """ - def __init__(self, name, filePath, pathEntry): + def __init__( + self, name: str, filePath: FilePath[str], pathEntry: PathEntry + ) -> None: """ Create a PythonModule. Do not construct this directly, instead inspect a PythonPath or other PythonModule instances. diff --git a/contrib/python/Twisted/py3/twisted/python/shortcut.py b/contrib/python/Twisted/py3/twisted/python/shortcut.py index 7d08424bdd0..a735cd67377 100644 --- a/contrib/python/Twisted/py3/twisted/python/shortcut.py +++ b/contrib/python/Twisted/py3/twisted/python/shortcut.py @@ -10,8 +10,8 @@ Requires win32all. import os -import pythoncom # type: ignore[import] -from win32com.shell import shell # type: ignore[import] +import pythoncom # type: ignore[import-untyped] +from win32com.shell import shell def open(filename): diff --git a/contrib/python/Twisted/py3/twisted/python/util.py b/contrib/python/Twisted/py3/twisted/python/util.py index 058f1044b37..6047f7eda53 100644 --- a/contrib/python/Twisted/py3/twisted/python/util.py +++ b/contrib/python/Twisted/py3/twisted/python/util.py @@ -40,7 +40,6 @@ from typing import ( Tuple, TypeVar, Union, - cast, ) from incremental import Version @@ -628,10 +627,8 @@ class FancyStrMixin: if isinstance(attr, str): r.append(f" {attr}={getattr(self, attr)!r}") elif len(attr) == 2: - attr = cast(Tuple[str, Callable[[Any], str]], attr) r.append((f" {attr[0]}=") + attr[1](getattr(self, attr[0]))) else: - attr = cast(Tuple[str, str, str], attr) r.append((" %s=" + attr[2]) % (attr[1], getattr(self, attr[0]))) r.append(">") return "".join(r) diff --git a/contrib/python/Twisted/py3/twisted/python/win32.py b/contrib/python/Twisted/py3/twisted/python/win32.py index df1b22fa1ee..f86c1ec90e3 100644 --- a/contrib/python/Twisted/py3/twisted/python/win32.py +++ b/contrib/python/Twisted/py3/twisted/python/win32.py @@ -125,7 +125,7 @@ class _ErrorFormatter: except ImportError: WinError = None try: - from win32api import FormatMessage # type: ignore[import] + from win32api import FormatMessage except ImportError: FormatMessage = None try: diff --git a/contrib/python/Twisted/py3/twisted/spread/flavors.py b/contrib/python/Twisted/py3/twisted/spread/flavors.py index ef98fee272c..4e8d11d7788 100644 --- a/contrib/python/Twisted/py3/twisted/spread/flavors.py +++ b/contrib/python/Twisted/py3/twisted/spread/flavors.py @@ -573,7 +573,7 @@ class RemoteCacheMethod: """(internal) action method.""" cacheID = self.broker.cachedRemotelyAs(self.cached) if cacheID is None: - from pb import ProtocolError # type: ignore[import] + from twisted.spread.pb import ProtocolError raise ProtocolError( "You can't call a cached method when the object hasn't been given to the peer yet." @@ -636,7 +636,7 @@ class RemoteCacheObserver: if isinstance(_name, str): _name = _name.encode("utf-8") if cacheID is None: - from pb import ProtocolError + from twisted.spread.pb import ProtocolError raise ProtocolError( "You can't call a cached method when the " diff --git a/contrib/python/Twisted/py3/twisted/trial/_dist/functional.py b/contrib/python/Twisted/py3/twisted/trial/_dist/functional.py index 3db4dca5de5..8bb5ecf7a4f 100644 --- a/contrib/python/Twisted/py3/twisted/trial/_dist/functional.py +++ b/contrib/python/Twisted/py3/twisted/trial/_dist/functional.py @@ -79,10 +79,7 @@ def compose(fx: Callable[[_B], _C], fy: Callable[[_A], _B]) -> Callable[[_A], _C # Discard the result of an awaitable and substitute None in its place. -# -# Ignore the `Cannot infer type argument 1 of "compose"` -# https://github.com/python/mypy/issues/6220 -discardResult: Callable[[Awaitable[_A]], Deferred[None]] = compose( # type: ignore[misc] +discardResult: Callable[[Awaitable[_A]], Deferred[None]] = compose( Deferred.fromCoroutine, partial(flip(sequence), succeed(None)), ) diff --git a/contrib/python/Twisted/py3/twisted/trial/_synctest.py b/contrib/python/Twisted/py3/twisted/trial/_synctest.py index 2cffc2c79e3..6b1f43dc89d 100644 --- a/contrib/python/Twisted/py3/twisted/trial/_synctest.py +++ b/contrib/python/Twisted/py3/twisted/trial/_synctest.py @@ -1189,9 +1189,14 @@ class SynchronousTestCase(_Assertions): if filename != os.path.normcase(aWarning.filename): continue + + # In Python 3.13 line numbers returned by findlinestarts + # can be None for bytecode that does not map to source + # lines. lineNumbers = [ lineNumber for _, lineNumber in _findlinestarts(aFunction.__code__) + if lineNumber is not None ] if not (min(lineNumbers) <= aWarning.lineno <= max(lineNumbers)): continue diff --git a/contrib/python/Twisted/py3/twisted/trial/reporter.py b/contrib/python/Twisted/py3/twisted/trial/reporter.py index 2664b2fe0d5..4ee67ebcf67 100644 --- a/contrib/python/Twisted/py3/twisted/trial/reporter.py +++ b/contrib/python/Twisted/py3/twisted/trial/reporter.py @@ -7,7 +7,7 @@ """ Defines classes that handle the results of tests. """ - +from __future__ import annotations import os import sys @@ -16,7 +16,7 @@ import unittest as pyunit import warnings from collections import OrderedDict from types import TracebackType -from typing import TYPE_CHECKING, List, Tuple, Type, Union +from typing import TYPE_CHECKING, List, Optional, Tuple, Type, Union from zope.interface import implementer @@ -32,7 +32,7 @@ if TYPE_CHECKING: from ._synctest import Todo try: - from subunit import TestProtocolClient # type: ignore[import] + from subunit import TestProtocolClient except ImportError: TestProtocolClient = None @@ -87,6 +87,11 @@ class TestResult(pyunit.TestResult): @ivar successes: count the number of successes achieved by the test run. @type successes: C{int} + + @ivar _startTime: The time when the current test was started. It defaults to + L{None}, which means that the test was skipped. + @ivar _lastTime: The duration of the current test run. It defaults to + L{None}, which means that the test was skipped. """ # Used when no todo provided to addExpectedFailure or addUnexpectedSuccess. @@ -96,6 +101,9 @@ class TestResult(pyunit.TestResult): expectedFailures: List[Tuple[itrial.ITestCase, str, "Todo"]] # type: ignore[assignment] unexpectedSuccesses: List[Tuple[itrial.ITestCase, str]] # type: ignore[assignment] successes: int + _testStarted: Optional[int] + # The duration of the test. It is None until the test completes. + _lastTime: Optional[int] def __init__(self): super().__init__() @@ -104,6 +112,8 @@ class TestResult(pyunit.TestResult): self.unexpectedSuccesses = [] self.successes = 0 self._timings = [] + self._testStarted = None + self._lastTime = None def __repr__(self) -> str: return "<%s run=%d errors=%d failures=%d todos=%d dones=%d skips=%d>" % ( @@ -146,7 +156,8 @@ class TestResult(pyunit.TestResult): @type test: L{pyunit.TestCase} """ super().stopTest(test) - self._lastTime = self._getTime() - self._testStarted + if self._testStarted is not None: + self._lastTime = self._getTime() - self._testStarted def addFailure(self, test, fail): """ @@ -908,7 +919,7 @@ class _Win32Colorizer: """ def __init__(self, stream): - from win32console import ( # type: ignore[import] + from win32console import ( FOREGROUND_BLUE, FOREGROUND_GREEN, FOREGROUND_INTENSITY, @@ -944,7 +955,7 @@ class _Win32Colorizer: screenBuffer = win32console.GetStdHandle(win32console.STD_OUTPUT_HANDLE) except ImportError: return False - import pywintypes # type: ignore[import] + import pywintypes try: screenBuffer.SetConsoleTextAttribute( diff --git a/contrib/python/Twisted/py3/twisted/web/_http2.py b/contrib/python/Twisted/py3/twisted/web/_http2.py index 57762e1805d..24c24fc0ffe 100644 --- a/contrib/python/Twisted/py3/twisted/web/_http2.py +++ b/contrib/python/Twisted/py3/twisted/web/_http2.py @@ -21,12 +21,12 @@ from typing import List from zope.interface import implementer -import h2.config # type: ignore[import] -import h2.connection # type: ignore[import] -import h2.errors # type: ignore[import] -import h2.events # type: ignore[import] -import h2.exceptions # type: ignore[import] -import priority # type: ignore[import] +import h2.config +import h2.connection +import h2.errors +import h2.events +import h2.exceptions +import priority from twisted.internet._producer_helpers import _PullToPush from twisted.internet.defer import Deferred diff --git a/contrib/python/Twisted/py3/twisted/web/_template_util.py b/contrib/python/Twisted/py3/twisted/web/_template_util.py index 4a9f7f21002..230c33f3e8f 100644 --- a/contrib/python/Twisted/py3/twisted/web/_template_util.py +++ b/contrib/python/Twisted/py3/twisted/web/_template_util.py @@ -24,7 +24,7 @@ from typing import ( cast, ) from xml.sax import handler, make_parser -from xml.sax.xmlreader import Locator +from xml.sax.xmlreader import AttributesNSImpl, Locator from zope.interface import implementer @@ -462,7 +462,7 @@ class _ToStan(handler.ContentHandler, handler.EntityResolver): self, namespaceAndName: Tuple[str, str], qname: Optional[str], - attrs: Mapping[Tuple[Optional[str], str], str], + attrs: AttributesNSImpl, ) -> None: """ Gets called when we encounter a new xmlns attribute. @@ -505,14 +505,14 @@ class _ToStan(handler.ContentHandler, handler.EntityResolver): render = None - attrs = OrderedDict(attrs) - for k, v in list(attrs.items()): + ordered = OrderedDict(attrs) + for k, v in list(ordered.items()): attrNS, justTheName = k if attrNS != TEMPLATE_NAMESPACE: continue if justTheName == "render": render = v - del attrs[k] + del ordered[k] # nonTemplateAttrs is a dictionary mapping attributes that are *not* in # TEMPLATE_NAMESPACE to their values. Those in TEMPLATE_NAMESPACE were @@ -522,7 +522,7 @@ class _ToStan(handler.ContentHandler, handler.EntityResolver): # preserving the xml namespace prefix given in the document. nonTemplateAttrs = OrderedDict() - for (attrNs, attrName), v in attrs.items(): + for (attrNs, attrName), v in ordered.items(): nsPrefix = self.prefixMap.get(attrNs) if nsPrefix is None: attrKey = attrName diff --git a/contrib/python/Twisted/py3/twisted/web/client.py b/contrib/python/Twisted/py3/twisted/web/client.py index 9a0d5e9e10b..e66b0cf3177 100644 --- a/contrib/python/Twisted/py3/twisted/web/client.py +++ b/contrib/python/Twisted/py3/twisted/web/client.py @@ -6,13 +6,16 @@ HTTP client. """ +from __future__ import annotations import collections import os import warnings import zlib +from dataclasses import dataclass from functools import wraps -from typing import Iterable +from http.cookiejar import CookieJar +from typing import TYPE_CHECKING, Iterable, Optional from urllib.parse import urldefrag, urljoin, urlunparse as _urlunparse from zope.interface import implementer @@ -21,6 +24,7 @@ from incremental import Version from twisted.internet import defer, protocol, task from twisted.internet.abstract import isIPv6Address +from twisted.internet.defer import Deferred from twisted.internet.endpoints import HostnameEndpoint, wrapClientTLS from twisted.internet.interfaces import IOpenSSLContextFactory, IProtocol from twisted.logger import Logger @@ -43,6 +47,20 @@ from twisted.web.iweb import ( IResponse, ) +# For the purpose of type-checking we want our faked-out types to be identical to the types they are replacing. +# For the purpose of the impementation, we want to start +# with a blank slate so that we don't accidentally use +# any of the real implementation. + +if TYPE_CHECKING: + from email.message import EmailMessage as _InfoType + from http.client import HTTPResponse as _ResponseBase + from urllib.request import Request as _RequestBase +else: + _RequestBase = object + _ResponseBase = object + _InfoType = object + def urlunparse(parts): result = _urlunparse(tuple(p.decode("charmap") for p in parts)) @@ -1200,36 +1218,38 @@ class ProxyAgent(_AgentBase): ) -class _FakeUrllib2Request: +class _FakeStdlibRequest(_RequestBase): """ - A fake C{urllib2.Request} object for C{cookielib} to work with. + A fake L{urllib.request.Request} object for L{cookiejar} to work with. - @see: U{http://docs.python.org/library/urllib2.html#request-objects} + @see: U{urllib.request.Request + <https://docs.python.org/3/library/urllib.request.html#urllib.request.Request>} - @type uri: native L{str} @ivar uri: Request URI. - @type headers: L{twisted.web.http_headers.Headers} @ivar headers: Request headers. - @type type: native L{str} @ivar type: The scheme of the URI. - @type host: native L{str} @ivar host: The host[:port] of the URI. @since: 11.1 """ - def __init__(self, uri): + uri: str + type: str + host: str + # The received headers managed using Twisted API. + _twistedHeaders: Headers + + def __init__(self, uri: bytes) -> None: """ - Create a fake Urllib2 request. + Create a fake request. @param uri: Request URI. - @type uri: L{bytes} """ self.uri = nativeString(uri) - self.headers = Headers() + self._twistedHeaders = Headers() _uri = URI.fromBytes(uri) self.type = nativeString(_uri.scheme) @@ -1240,19 +1260,19 @@ class _FakeUrllib2Request: self.host += ":" + str(_uri.port) self.origin_req_host = nativeString(_uri.host) - self.unverifiable = lambda _: False + self.unverifiable = False def has_header(self, header): - return self.headers.hasHeader(networkString(header)) + return self._twistedHeaders.hasHeader(networkString(header)) def add_unredirected_header(self, name, value): - self.headers.addRawHeader(networkString(name), networkString(value)) + self._twistedHeaders.addRawHeader(networkString(name), networkString(value)) def get_full_url(self): return self.uri def get_header(self, name, default=None): - headers = self.headers.getRawHeaders(networkString(name), default) + headers = self._twistedHeaders.getRawHeaders(networkString(name), default) if headers is not None: headers = [nativeString(x) for x in headers] return headers[0] @@ -1269,62 +1289,68 @@ class _FakeUrllib2Request: return False -class _FakeUrllib2Response: +@dataclass +class _FakeUrllibResponseInfo(_InfoType): + response: IResponse + + def get_all(self, name: str, default: bytes) -> list[str]: # type:ignore[override] + headers = self.response.headers.getRawHeaders(networkString(name), default) + h = [nativeString(x) for x in headers] + return h + + +class _FakeStdlibResponse(_ResponseBase): """ - A fake C{urllib2.Response} object for C{cookielib} to work with. + A fake L{urllib.response.Response} object for L{http.cookiejar} to work + with. - @type response: C{twisted.web.iweb.IResponse} @ivar response: Underlying Twisted Web response. @since: 11.1 """ - def __init__(self, response): - self.response = response - - def info(self): - class _Meta: - def getheaders(zelf, name): - # PY2 - headers = self.response.headers.getRawHeaders(name, []) - return headers + response: IResponse - def get_all(zelf, name, default): - # PY3 - headers = self.response.headers.getRawHeaders( - networkString(name), default - ) - h = [nativeString(x) for x in headers] - return h + def __init__(self, response: IResponse) -> None: + self.response = response - return _Meta() + def info(self) -> _InfoType: + result = _FakeUrllibResponseInfo(self.response) + return result @implementer(IAgent) class CookieAgent: """ - L{CookieAgent} extends the basic L{Agent} to add RFC-compliant - handling of HTTP cookies. Cookies are written to and extracted - from a C{cookielib.CookieJar} instance. + L{CookieAgent} extends the basic L{Agent} to add RFC-compliant handling of + HTTP cookies. Cookies are written to and extracted from a L{CookieJar} + instance. The same cookie jar instance will be used for any requests through this agent, mutating it whenever a I{Set-Cookie} header appears in a response. - @type _agent: L{twisted.web.client.Agent} @ivar _agent: Underlying Twisted Web agent to issue requests through. - @type cookieJar: C{cookielib.CookieJar} @ivar cookieJar: Initialized cookie jar to read cookies from and store cookies to. @since: 11.1 """ - def __init__(self, agent, cookieJar): + _agent: IAgent + cookieJar: CookieJar + + def __init__(self, agent: IAgent, cookieJar: CookieJar) -> None: self._agent = agent self.cookieJar = cookieJar - def request(self, method, uri, headers=None, bodyProducer=None): + def request( + self, + method: bytes, + uri: bytes, + headers: Optional[Headers] = None, + bodyProducer: Optional[IBodyProducer] = None, + ) -> Deferred[IResponse]: """ Issue a new request to the wrapped L{Agent}. @@ -1337,33 +1363,33 @@ class CookieAgent: @see: L{Agent.request} """ - if headers is None: - headers = Headers() - lastRequest = _FakeUrllib2Request(uri) + actualHeaders = headers if headers is not None else Headers() + lastRequest = _FakeStdlibRequest(uri) # Setting a cookie header explicitly will disable automatic request # cookies. - if not headers.hasHeader(b"cookie"): + if not actualHeaders.hasHeader(b"cookie"): self.cookieJar.add_cookie_header(lastRequest) cookieHeader = lastRequest.get_header("Cookie", None) if cookieHeader is not None: - headers = headers.copy() - headers.addRawHeader(b"cookie", networkString(cookieHeader)) + actualHeaders = actualHeaders.copy() + actualHeaders.addRawHeader(b"cookie", networkString(cookieHeader)) - d = self._agent.request(method, uri, headers, bodyProducer) - d.addCallback(self._extractCookies, lastRequest) - return d + return self._agent.request( + method, uri, actualHeaders, bodyProducer + ).addCallback(self._extractCookies, lastRequest) - def _extractCookies(self, response, request): + def _extractCookies( + self, response: IResponse, request: _FakeStdlibRequest + ) -> IResponse: """ Extract response cookies and store them in the cookie jar. - @type response: L{twisted.web.iweb.IResponse} - @param response: Twisted Web response. + @param response: the Twisted Web response that we are processing. - @param request: A urllib2 compatible request object. + @param request: A L{_FakeStdlibRequest} wrapping our Twisted request, + for L{CookieJar} to extract cookies from. """ - resp = _FakeUrllib2Response(response) - self.cookieJar.extract_cookies(resp, request) + self.cookieJar.extract_cookies(_FakeStdlibResponse(response), request) return response diff --git a/contrib/python/Twisted/py3/twisted/web/http.py b/contrib/python/Twisted/py3/twisted/web/http.py index 2bad1471dc8..1c598380acc 100644 --- a/contrib/python/Twisted/py3/twisted/web/http.py +++ b/contrib/python/Twisted/py3/twisted/web/http.py @@ -31,6 +31,7 @@ also useful for HTTP clients (such as the chunked encoding parser). it, as in the HTTP 1.1 chunked I{Transfer-Encoding} (RFC 7230 section 4.1). This limits how much data may be buffered when decoding the line. """ +from __future__ import annotations __all__ = [ "SWITCHING", @@ -100,15 +101,16 @@ __all__ = [ import base64 import binascii import calendar -import cgi import math import os import re import tempfile import time import warnings +from email import message_from_bytes +from email.message import EmailMessage from io import BytesIO -from typing import AnyStr, Callable, List, Optional, Tuple +from typing import AnyStr, Callable, Dict, List, Optional, Tuple from urllib.parse import ( ParseResultBytes, unquote_to_bytes as unquote, @@ -130,8 +132,6 @@ from twisted.python.compat import nativeString, networkString from twisted.python.components import proxyForInterface from twisted.python.deprecate import deprecated from twisted.python.failure import Failure - -# twisted imports from twisted.web._responses import ( ACCEPTED, BAD_GATEWAY, @@ -224,15 +224,40 @@ weekdayname_lower = [name.lower() for name in weekdayname] monthname_lower = [name and name.lower() for name in monthname] -def _parseHeader(line): - # cgi.parse_header requires a str - key, pdict = cgi.parse_header(line.decode("charmap")) +def _parseContentType(line: bytes) -> bytes: + """ + Parse the Content-Type header. + """ + msg = EmailMessage() + msg["content-type"] = line.decode("charmap") + key = msg.get_content_type() + encodedKey = key.encode("charmap") + return encodedKey - # We want the key as bytes, and cgi.parse_multipart (which consumes - # pdict) expects a dict of str keys but bytes values - key = key.encode("charmap") - pdict = {x: y.encode("charmap") for x, y in pdict.items()} - return (key, pdict) + +class _MultiPartParseException(Exception): + """ + Failed to parse the multipart/form-data payload. + """ + + +def _getMultiPartArgs(content: bytes, ctype: bytes) -> dict[bytes, list[bytes]]: + """ + Parse the content of a multipart/form-data request. + """ + result = {} + multiPartHeaders = b"MIME-Version: 1.0\r\n" + b"Content-Type: " + ctype + b"\r\n" + msg = message_from_bytes(multiPartHeaders + content) + if not msg.is_multipart(): + raise _MultiPartParseException("Not a multipart.") + + for part in msg.get_payload(): + name = part.get_param("name", header="content-disposition") + if not name: + continue + payload = part.get_payload(decode=True) + result[name.encode("utf8")] = [payload] + return result def urlparse(url): @@ -267,6 +292,9 @@ def parse_qs(qs, keep_blank_values=0, strict_parsing=0): """ Like C{cgi.parse_qs}, but with support for parsing byte strings on Python 3. + This was created to help with Python 2 to Python 3 migration. + Consider using L{urllib.parse.parse_qs}. + @type qs: C{bytes} """ d = {} @@ -829,7 +857,7 @@ class Request: _disconnected = False _log = Logger() - def __init__(self, channel, queued=_QUEUED_SENTINEL): + def __init__(self, channel: HTTPChannel, queued: object = _QUEUED_SENTINEL) -> None: """ @param channel: the channel we're connected to. @param queued: (deprecated) are we in the request queue, or can we @@ -845,9 +873,9 @@ class Request: self.host = self.channel.getHost() self.requestHeaders: Headers = Headers() - self.received_cookies = {} + self.received_cookies: Dict[bytes, bytes] = {} self.responseHeaders: Headers = Headers() - self.cookies = [] # outgoing cookies + self.cookies: List[bytes] = [] # outgoing cookies self.transport = self.channel.transport if queued is _QUEUED_SENTINEL: @@ -973,47 +1001,18 @@ class Request: if self.method == b"POST" and ctype and clength: mfd = b"multipart/form-data" - key, pdict = _parseHeader(ctype) - # This weird CONTENT-LENGTH param is required by - # cgi.parse_multipart() in some versions of Python 3.7+, see - # bpo-29979. It looks like this will be relaxed and backported, see - # https://github.com/python/cpython/pull/8530. - pdict["CONTENT-LENGTH"] = clength + key = _parseContentType(ctype) if key == b"application/x-www-form-urlencoded": args.update(parse_qs(self.content.read(), 1)) elif key == mfd: try: - cgiArgs = cgi.parse_multipart( - self.content, - pdict, - encoding="utf8", - errors="surrogateescape", - ) - - # The parse_multipart function on Python 3.7+ - # decodes the header bytes as iso-8859-1 and - # decodes the body bytes as utf8 with - # surrogateescape -- we want bytes - self.args.update( - { - x.encode("iso-8859-1"): [ - z.encode("utf8", "surrogateescape") - if isinstance(z, str) - else z - for z in y - ] - for x, y in cgiArgs.items() - if isinstance(x, str) - } - ) - except Exception as e: - # It was a bad request, or we got a signal. + self.content.seek(0) + content = self.content.read() + self.args.update(_getMultiPartArgs(content, ctype)) + except _MultiPartParseException: + # It was a bad request. self.channel._respondToBadRequestAndDisconnect() - if isinstance(e, (TypeError, ValueError, KeyError)): - return - else: - # If it's not a userspace error from CGI, reraise - raise + return self.content.seek(0, 0) @@ -1806,7 +1805,6 @@ class _IdentityTransferDecoder: maxChunkSizeLineLength = 1024 - _chunkExtChars = ( b"\t !\"#$%&'()*+,-./0123456789:;<=>?@" b"ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`" @@ -1890,12 +1888,20 @@ class _ChunkedTransferDecoder: state transition this is truncated at the front so that index 0 is where the next state shall begin. - @ivar _start: While in the C{'CHUNK_LENGTH'} state, tracks the index into - the buffer at which search for CRLF should resume. Resuming the search - at this position avoids doing quadratic work if the chunk length line - arrives over many calls to C{dataReceived}. + @ivar _start: While in the C{'CHUNK_LENGTH'} and C{'TRAILER'} states, + tracks the index into the buffer at which search for CRLF should resume. + Resuming the search at this position avoids doing quadratic work if the + chunk length line arrives over many calls to C{dataReceived}. + + @ivar _trailerHeaders: Accumulates raw/unparsed trailer headers. + See https://github.com/twisted/twisted/issues/12014 + + @ivar _maxTrailerHeadersSize: Maximum bytes for trailer header from the + response. + @type _maxTrailerHeadersSize: C{int} - Not used in any other state. + @ivar _receivedTrailerHeadersSize: Bytes received so far for the tailer headers. + @type _receivedTrailerHeadersSize: C{int} """ state = "CHUNK_LENGTH" @@ -1909,6 +1915,9 @@ class _ChunkedTransferDecoder: self.finishCallback = finishCallback self._buffer = bytearray() self._start = 0 + self._trailerHeaders: List[bytearray] = [] + self._maxTrailerHeadersSize = 2**16 + self._receivedTrailerHeadersSize = 0 def _dataReceived_CHUNK_LENGTH(self) -> bool: """ @@ -1985,23 +1994,37 @@ class _ChunkedTransferDecoder: def _dataReceived_TRAILER(self) -> bool: """ - Await the carriage return and line feed characters that follow the - terminal zero-length chunk. Then invoke C{finishCallback} and switch to - state C{'FINISHED'}. + Collect trailer headers if received and finish at the terminal zero-length + chunk. Then invoke C{finishCallback} and switch to state C{'FINISHED'}. @returns: C{False}, as there is either insufficient data to continue, or no data remains. - - @raises _MalformedChunkedDataError: when anything other than CRLF is - received. """ - if len(self._buffer) < 2: + if ( + self._receivedTrailerHeadersSize + len(self._buffer) + > self._maxTrailerHeadersSize + ): + raise _MalformedChunkedDataError("Trailer headers data is too long.") + + eolIndex = self._buffer.find(b"\r\n", self._start) + + if eolIndex == -1: + # Still no end of network line marker found. + # Continue processing more data. return False - if not self._buffer.startswith(b"\r\n"): - raise _MalformedChunkedDataError("Chunk did not end with CRLF") + if eolIndex > 0: + # A trailer header was detected. + self._trailerHeaders.append(self._buffer[0:eolIndex]) + del self._buffer[0 : eolIndex + 2] + self._start = 0 + self._receivedTrailerHeadersSize += eolIndex + 2 + return True + + # eolIndex in this part of code is equal to 0 data = memoryview(self._buffer)[2:].tobytes() + del self._buffer[:] self.state = "FINISHED" self.finishCallback(data) diff --git a/contrib/python/Twisted/py3/twisted/web/pages.py b/contrib/python/Twisted/py3/twisted/web/pages.py index 54ea1c431b8..f94f8655b95 100644 --- a/contrib/python/Twisted/py3/twisted/web/pages.py +++ b/contrib/python/Twisted/py3/twisted/web/pages.py @@ -76,7 +76,7 @@ class _ErrorPage(Resource): return self -def errorPage(code: int, brief: str, detail: str) -> IResource: +def errorPage(code: int, brief: str, detail: str) -> _ErrorPage: """ Build a resource that responds to all requests with a particular HTTP status code and an HTML body containing some descriptive text. This is diff --git a/contrib/python/Twisted/py3/twisted/web/resource.py b/contrib/python/Twisted/py3/twisted/web/resource.py index 33b172cdbfd..456db72d120 100644 --- a/contrib/python/Twisted/py3/twisted/web/resource.py +++ b/contrib/python/Twisted/py3/twisted/web/resource.py @@ -7,7 +7,7 @@ Implementation of the lowest-level Resource class. See L{twisted.web.pages} for some utility implementations. """ - +from __future__ import annotations __all__ = [ "IResource", @@ -20,6 +20,7 @@ __all__ = [ ] import warnings +from typing import Sequence from zope.interface import Attribute, Interface, implementer @@ -116,6 +117,7 @@ class Resource: """ entityType = IResource + allowedMethods: Sequence[bytes] server = None diff --git a/contrib/python/Twisted/py3/twisted/web/script.py b/contrib/python/Twisted/py3/twisted/web/script.py index bc4a90f748a..794eef8f630 100644 --- a/contrib/python/Twisted/py3/twisted/web/script.py +++ b/contrib/python/Twisted/py3/twisted/web/script.py @@ -77,7 +77,7 @@ def ResourceScript(path, registry): def ResourceTemplate(path, registry): - from quixote import ptl_compile # type: ignore[import] + from quixote import ptl_compile glob = { "__file__": _coerceToFilesystemEncoding("", path), diff --git a/contrib/python/Twisted/py3/twisted/web/server.py b/contrib/python/Twisted/py3/twisted/web/server.py index e8e01ec781b..6392a3168ae 100644 --- a/contrib/python/Twisted/py3/twisted/web/server.py +++ b/contrib/python/Twisted/py3/twisted/web/server.py @@ -101,8 +101,7 @@ class Request(Copyable, http.Request, components.Componentized): will be transmitted only over HTTPS. """ - defaultContentType = b"text/html" - + defaultContentType: Optional[bytes] = b"text/html" site = None appRootURL = None prepath: Optional[List[bytes]] = None diff --git a/contrib/python/Twisted/py3/twisted/web/soap.py b/contrib/python/Twisted/py3/twisted/web/soap.py index c60bc92b916..cc44b41e2ac 100644 --- a/contrib/python/Twisted/py3/twisted/web/soap.py +++ b/contrib/python/Twisted/py3/twisted/web/soap.py @@ -16,7 +16,7 @@ Pluggable method lookup policies. """ # SOAPpy -import SOAPpy # type: ignore[import] +import SOAPpy from twisted.internet import defer diff --git a/contrib/python/Twisted/py3/ya.make b/contrib/python/Twisted/py3/ya.make index 4a28d8ff160..47590a4139c 100644 --- a/contrib/python/Twisted/py3/ya.make +++ b/contrib/python/Twisted/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(23.10.0) +VERSION(24.3.0) LICENSE(MIT) @@ -467,7 +467,6 @@ RESOURCE_FILES( .dist-info/METADATA .dist-info/entry_points.txt .dist-info/top_level.txt - twisted/11715.misc twisted/application/newsfragments/10146.misc twisted/application/newsfragments/9746.misc twisted/conch/newsfragments/.gitignore diff --git a/contrib/python/clickhouse-connect/.dist-info/METADATA b/contrib/python/clickhouse-connect/.dist-info/METADATA index 59c9d0db259..bb7d4b45cd9 100644 --- a/contrib/python/clickhouse-connect/.dist-info/METADATA +++ b/contrib/python/clickhouse-connect/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: clickhouse-connect -Version: 0.7.0 +Version: 0.7.1 Summary: ClickHouse Database Core Driver for Python, Pandas, and Superset Home-page: https://github.com/ClickHouse/clickhouse-connect Author: ClickHouse Inc. @@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Requires-Python: ~=3.8 Description-Content-Type: text/markdown License-File: LICENSE diff --git a/contrib/python/clickhouse-connect/LICENSE b/contrib/python/clickhouse-connect/LICENSE index 31495aae118..1ac8466cc9e 100644 --- a/contrib/python/clickhouse-connect/LICENSE +++ b/contrib/python/clickhouse-connect/LICENSE @@ -1,4 +1,4 @@ -Copyright 2022-2023 ClickHouse, Inc. +Copyright 2022-2024 ClickHouse, Inc. Apache License Version 2.0, January 2004 diff --git a/contrib/python/clickhouse-connect/clickhouse_connect/__version__.py b/contrib/python/clickhouse-connect/clickhouse_connect/__version__.py index 861cc502994..104c9df52f2 100644 --- a/contrib/python/clickhouse-connect/clickhouse_connect/__version__.py +++ b/contrib/python/clickhouse-connect/clickhouse_connect/__version__.py @@ -1 +1 @@ -version = '0.7.0' +version = '0.7.1' diff --git a/contrib/python/clickhouse-connect/clickhouse_connect/driver/client.py b/contrib/python/clickhouse-connect/clickhouse_connect/driver/client.py index beaea8e0d11..e91e0baf534 100644 --- a/contrib/python/clickhouse-connect/clickhouse_connect/driver/client.py +++ b/contrib/python/clickhouse-connect/clickhouse_connect/driver/client.py @@ -157,7 +157,7 @@ class Client(ABC): # pylint: disable=too-many-arguments,unused-argument,too-many-locals def query(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, @@ -193,7 +193,7 @@ class Client(ABC): return self._query_with_context(query_context) def query_column_block_stream(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, @@ -212,7 +212,7 @@ class Client(ABC): return self._context_query(locals(), use_numpy=False, streaming=True).column_block_stream def query_row_block_stream(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, @@ -231,7 +231,7 @@ class Client(ABC): return self._context_query(locals(), use_numpy=False, streaming=True).row_block_stream def query_rows_stream(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, @@ -270,7 +270,7 @@ class Client(ABC): # pylint: disable=duplicate-code,too-many-arguments,unused-argument def query_np(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, @@ -289,7 +289,7 @@ class Client(ABC): # pylint: disable=duplicate-code,too-many-arguments,unused-argument def query_np_stream(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, @@ -308,7 +308,7 @@ class Client(ABC): # pylint: disable=duplicate-code,too-many-arguments,unused-argument def query_df(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, @@ -331,7 +331,7 @@ class Client(ABC): # pylint: disable=duplicate-code,too-many-arguments,unused-argument def query_df_stream(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, @@ -355,7 +355,7 @@ class Client(ABC): streaming=True).df_stream def create_query_context(self, - query: str = None, + query: Optional[str] = None, parameters: Optional[Union[Sequence, Dict[str, Any]]] = None, settings: Optional[Dict[str, Any]] = None, query_formats: Optional[Dict[str, str]] = None, diff --git a/contrib/python/clickhouse-connect/clickhouse_connect/driver/httpclient.py b/contrib/python/clickhouse-connect/clickhouse_connect/driver/httpclient.py index 7d72b95aa31..c4a2da23939 100644 --- a/contrib/python/clickhouse-connect/clickhouse_connect/driver/httpclient.py +++ b/contrib/python/clickhouse-connect/clickhouse_connect/driver/httpclient.py @@ -171,7 +171,7 @@ class HttpClient(Client): final_query = super()._prep_query(context) if context.is_insert: return final_query - return f'{final_query}\n FORMAT {self._write_format}' + return f'{final_query}\n FORMAT {self._read_format}' def _query_with_context(self, context: QueryContext) -> QueryResult: headers = {} diff --git a/contrib/python/clickhouse-connect/clickhouse_connect/driver/tools.py b/contrib/python/clickhouse-connect/clickhouse_connect/driver/tools.py index 420686cd64a..54b4b459492 100644 --- a/contrib/python/clickhouse-connect/clickhouse_connect/driver/tools.py +++ b/contrib/python/clickhouse-connect/clickhouse_connect/driver/tools.py @@ -13,7 +13,12 @@ def insert_file(client: Client, database: Optional[str] = None, settings: Optional[Dict[str, Any]] = None, compression: Optional[str] = None) -> QuerySummary: - full_table = f'{quote_identifier(database)}.{quote_identifier(table)}' if database else quote_identifier(table) + if not database and table[0] not in ('`', "'") and table.find('.') > 0: + full_table = table + elif database: + full_table = f'{quote_identifier(database)}.{quote_identifier(table)}' + else: + full_table = quote_identifier(table) if not fmt: fmt = 'CSV' if column_names else 'CSVWithNames' if compression is None: diff --git a/contrib/python/clickhouse-connect/ya.make b/contrib/python/clickhouse-connect/ya.make index 7db828de236..1bb663cb9b7 100644 --- a/contrib/python/clickhouse-connect/ya.make +++ b/contrib/python/clickhouse-connect/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(0.7.0) +VERSION(0.7.1) LICENSE(Apache-2.0) diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA index fa11a208885..8215d8ef3d5 100644 --- a/contrib/python/hypothesis/py3/.dist-info/METADATA +++ b/contrib/python/hypothesis/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: hypothesis -Version: 6.98.13 +Version: 6.98.16 Summary: A library for property-based testing Home-page: https://hypothesis.works Author: David R. MacIver and Zac Hatfield-Dodds diff --git a/contrib/python/hypothesis/py3/hypothesis/core.py b/contrib/python/hypothesis/py3/hypothesis/core.py index 536d7f01568..4e4411fadfc 100644 --- a/contrib/python/hypothesis/py3/hypothesis/core.py +++ b/contrib/python/hypothesis/py3/hypothesis/core.py @@ -108,6 +108,7 @@ from hypothesis.internal.reflection import ( repr_call, ) from hypothesis.internal.scrutineer import ( + MONITORING_TOOL_ID, Trace, Tracer, explanatory_lines, @@ -983,8 +984,27 @@ class StateForActualGivenExecution: """ trace: Trace = set() try: + # this is actually covered by our tests, but only on >= 3.12. + if ( + sys.version_info[:2] >= (3, 12) + and sys.monitoring.get_tool(MONITORING_TOOL_ID) is not None + ): # pragma: no cover + warnings.warn( + "avoiding tracing test function because tool id " + f"{MONITORING_TOOL_ID} is already taken by tool " + f"{sys.monitoring.get_tool(MONITORING_TOOL_ID)}.", + HypothesisWarning, + # I'm not sure computing a correct stacklevel is reasonable + # given the number of entry points here. + stacklevel=1, + ) + _can_trace = ( - sys.gettrace() is None or sys.version_info[:2] >= (3, 12) + (sys.version_info[:2] < (3, 12) and sys.gettrace() is None) + or ( + sys.version_info[:2] >= (3, 12) + and sys.monitoring.get_tool(MONITORING_TOOL_ID) is None + ) ) and not PYPY _trace_obs = TESTCASE_CALLBACKS and OBSERVABILITY_COLLECT_COVERAGE _trace_failure = ( diff --git a/contrib/python/hypothesis/py3/hypothesis/extra/array_api.py b/contrib/python/hypothesis/py3/hypothesis/extra/array_api.py index d62418f317d..e9ff8b3c9ee 100644 --- a/contrib/python/hypothesis/py3/hypothesis/extra/array_api.py +++ b/contrib/python/hypothesis/py3/hypothesis/extra/array_api.py @@ -69,10 +69,10 @@ __all__ = [ ] -RELEASED_VERSIONS = ("2021.12", "2022.12") +RELEASED_VERSIONS = ("2021.12", "2022.12", "2023.12") NOMINAL_VERSIONS = (*RELEASED_VERSIONS, "draft") assert sorted(NOMINAL_VERSIONS) == list(NOMINAL_VERSIONS) # sanity check -NominalVersion = Literal["2021.12", "2022.12", "draft"] +NominalVersion = Literal["2021.12", "2022.12", "2023.12", "draft"] assert get_args(NominalVersion) == NOMINAL_VERSIONS # sanity check diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py index b84db4df852..10c4e17fafb 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py @@ -203,6 +203,8 @@ NASTY_FLOATS.extend([-x for x in NASTY_FLOATS]) FLOAT_INIT_LOGIC_CACHE = LRUReusedCache(4096) +POOLED_KWARGS_CACHE = LRUReusedCache(4096) + DRAW_STRING_DEFAULT_MAX_SIZE = 10**10 # "arbitrarily large" @@ -334,6 +336,7 @@ class ExampleProperty: self.bytes_read = 0 self.example_count = 0 self.block_count = 0 + self.ir_node_count = 0 def run(self) -> Any: """Rerun the test case with this visitor and return the @@ -347,6 +350,10 @@ class ExampleProperty: self.block(self.block_count) self.block_count += 1 self.__pop(discarded=False) + elif record == IR_NODE_RECORD: + data = self.examples.ir_nodes[self.ir_node_count] + self.ir_node(data) + self.ir_node_count += 1 elif record >= START_EXAMPLE_RECORD: self.__push(record - START_EXAMPLE_RECORD) else: @@ -387,6 +394,9 @@ class ExampleProperty: index of the example and ``discarded`` being ``True`` if ``stop_example`` was called with ``discard=True``.""" + def ir_node(self, node: "IRNode") -> None: + """Called when an ir node is drawn.""" + def finish(self) -> Any: return self.result @@ -419,6 +429,8 @@ STOP_EXAMPLE_DISCARD_RECORD = 1 STOP_EXAMPLE_NO_DISCARD_RECORD = 2 START_EXAMPLE_RECORD = 3 +IR_NODE_RECORD = calc_label_from_name("ir draw record") + class ExampleRecord: """Records the series of ``start_example``, ``stop_example``, and @@ -435,10 +447,18 @@ class ExampleRecord: self.labels = [DRAW_BYTES_LABEL] self.__index_of_labels: "Optional[Dict[int, int]]" = {DRAW_BYTES_LABEL: 0} self.trail = IntList() + self.ir_nodes: List[IRNode] = [] def freeze(self) -> None: self.__index_of_labels = None + def record_ir_draw(self, ir_type, value, *, kwargs, was_forced): + self.trail.append(IR_NODE_RECORD) + node = IRNode( + ir_type=ir_type, value=value, kwargs=kwargs, was_forced=was_forced + ) + self.ir_nodes.append(node) + def start_example(self, label: int) -> None: assert self.__index_of_labels is not None try: @@ -454,7 +474,7 @@ class ExampleRecord: else: self.trail.append(STOP_EXAMPLE_NO_DISCARD_RECORD) - def draw_bits(self, n: int, forced: Optional[int]) -> None: + def draw_bits(self) -> None: self.trail.append(DRAW_BITS_RECORD) @@ -471,6 +491,7 @@ class Examples: def __init__(self, record: ExampleRecord, blocks: "Blocks") -> None: self.trail = record.trail + self.ir_nodes = record.ir_nodes self.labels = record.labels self.__length = ( self.trail.count(STOP_EXAMPLE_DISCARD_RECORD) @@ -556,6 +577,15 @@ class Examples: depths: IntList = calculated_example_property(_depths) + class _ir_tree_nodes(ExampleProperty): + def begin(self): + self.result = [] + + def ir_node(self, ir_node): + self.result.append(ir_node) + + ir_tree_nodes: "List[IRNode]" = calculated_example_property(_ir_tree_nodes) + class _label_indices(ExampleProperty): def start_example(self, i: int, label_index: int) -> None: self.result[i] = label_index @@ -856,31 +886,39 @@ class DataObserver: """Mark this part of the tree as not worth re-exploring.""" def draw_integer( - self, value: int, *, was_forced: bool, kwargs: IntegerKWargs + self, value: int, *, kwargs: IntegerKWargs, was_forced: bool ) -> None: pass def draw_float( - self, value: float, *, was_forced: bool, kwargs: FloatKWargs + self, value: float, *, kwargs: FloatKWargs, was_forced: bool ) -> None: pass def draw_string( - self, value: str, *, was_forced: bool, kwargs: StringKWargs + self, value: str, *, kwargs: StringKWargs, was_forced: bool ) -> None: pass def draw_bytes( - self, value: bytes, *, was_forced: bool, kwargs: BytesKWargs + self, value: bytes, *, kwargs: BytesKWargs, was_forced: bool ) -> None: pass def draw_boolean( - self, value: bool, *, was_forced: bool, kwargs: BooleanKWargs + self, value: bool, *, kwargs: BooleanKWargs, was_forced: bool ) -> None: pass [email protected](slots=True) +class IRNode: + ir_type: IRTypeName = attr.ib() + value: IRType = attr.ib() + kwargs: IRKWargsType = attr.ib() + was_forced: bool = attr.ib() + + @dataclass_transform() @attr.s(slots=True) class ConjectureResult: @@ -1142,7 +1180,9 @@ class PrimitiveProvider: result = self._draw_float( forced_sign_bit=forced_sign_bit, forced=forced ) - if math.copysign(1.0, result) == -1: + if allow_nan and math.isnan(result): + clamped = result + elif math.copysign(1.0, result) == -1: assert neg_clamper is not None clamped = -neg_clamper(-result) else: @@ -1568,16 +1608,22 @@ class ConjectureData: if forced is not None and max_value is not None: assert forced <= max_value - kwargs: IntegerKWargs = { - "min_value": min_value, - "max_value": max_value, - "weights": weights, - "shrink_towards": shrink_towards, - } + kwargs: IntegerKWargs = self._pooled_kwargs( + "integer", + { + "min_value": min_value, + "max_value": max_value, + "weights": weights, + "shrink_towards": shrink_towards, + }, + ) value = self.provider.draw_integer(**kwargs, forced=forced) if observe: self.observer.draw_integer( - value, was_forced=forced is not None, kwargs=kwargs + value, kwargs=kwargs, was_forced=forced is not None + ) + self.__example_record.record_ir_draw( + "integer", value, kwargs=kwargs, was_forced=forced is not None ) return value @@ -1605,17 +1651,23 @@ class ConjectureData: sign_aware_lte(min_value, forced) and sign_aware_lte(forced, max_value) ) - kwargs: FloatKWargs = { - "min_value": min_value, - "max_value": max_value, - "allow_nan": allow_nan, - "smallest_nonzero_magnitude": smallest_nonzero_magnitude, - } + kwargs: FloatKWargs = self._pooled_kwargs( + "float", + { + "min_value": min_value, + "max_value": max_value, + "allow_nan": allow_nan, + "smallest_nonzero_magnitude": smallest_nonzero_magnitude, + }, + ) value = self.provider.draw_float(**kwargs, forced=forced) if observe: self.observer.draw_float( value, kwargs=kwargs, was_forced=forced is not None ) + self.__example_record.record_ir_draw( + "float", value, kwargs=kwargs, was_forced=forced is not None + ) return value def draw_string( @@ -1629,16 +1681,22 @@ class ConjectureData: ) -> str: assert forced is None or min_size <= len(forced) - kwargs: StringKWargs = { - "intervals": intervals, - "min_size": min_size, - "max_size": max_size, - } + kwargs: StringKWargs = self._pooled_kwargs( + "string", + { + "intervals": intervals, + "min_size": min_size, + "max_size": max_size, + }, + ) value = self.provider.draw_string(**kwargs, forced=forced) if observe: self.observer.draw_string( value, kwargs=kwargs, was_forced=forced is not None ) + self.__example_record.record_ir_draw( + "string", value, kwargs=kwargs, was_forced=forced is not None + ) return value def draw_bytes( @@ -1652,12 +1710,15 @@ class ConjectureData: assert forced is None or len(forced) == size assert size >= 0 - kwargs: BytesKWargs = {"size": size} + kwargs: BytesKWargs = self._pooled_kwargs("bytes", {"size": size}) value = self.provider.draw_bytes(**kwargs, forced=forced) if observe: self.observer.draw_bytes( value, kwargs=kwargs, was_forced=forced is not None ) + self.__example_record.record_ir_draw( + "bytes", value, kwargs=kwargs, was_forced=forced is not None + ) return value def draw_boolean( @@ -1673,14 +1734,37 @@ class ConjectureData: if forced is False: assert p < (1 - 2 ** (-64)) - kwargs: BooleanKWargs = {"p": p} + kwargs: BooleanKWargs = self._pooled_kwargs("boolean", {"p": p}) value = self.provider.draw_boolean(**kwargs, forced=forced) if observe: self.observer.draw_boolean( value, kwargs=kwargs, was_forced=forced is not None ) + self.__example_record.record_ir_draw( + "boolean", value, kwargs=kwargs, was_forced=forced is not None + ) return value + def _pooled_kwargs(self, ir_type, kwargs): + """Memoize common dictionary objects to reduce memory pressure.""" + key = [] + for k, v in kwargs.items(): + if ir_type == "float" and k in ["min_value", "max_value"]: + # handle -0.0 vs 0.0, etc. + v = float_to_int(v) + elif ir_type == "integer" and k == "weights": + # make hashable + v = v if v is None else tuple(v) + key.append((k, v)) + + key = (ir_type, *sorted(key)) + + try: + return POOLED_KWARGS_CACHE[key] + except KeyError: + POOLED_KWARGS_CACHE[key] = kwargs + return kwargs + def as_result(self) -> Union[ConjectureResult, _Overrun]: """Convert the result of running this test into either an Overrun object or a ConjectureResult.""" @@ -1901,7 +1985,7 @@ class ConjectureData: buf = bytes(buf) result = int_from_bytes(buf) - self.__example_record.draw_bits(n, forced) + self.__example_record.draw_bits() initial = self.index diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/intervalsets.py b/contrib/python/hypothesis/py3/hypothesis/internal/intervalsets.py index 88162b63323..e48802ee77c 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/intervalsets.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/intervalsets.py @@ -102,6 +102,9 @@ class IntervalSet: def __eq__(self, other): return isinstance(other, IntervalSet) and (other.intervals == self.intervals) + def __hash__(self): + return hash(self.intervals) + def union(self, other): """Merge two sequences of intervals into a single tuple of intervals. diff --git a/contrib/python/hypothesis/py3/hypothesis/stateful.py b/contrib/python/hypothesis/py3/hypothesis/stateful.py index 60cd92721c2..58a22771617 100644 --- a/contrib/python/hypothesis/py3/hypothesis/stateful.py +++ b/contrib/python/hypothesis/py3/hypothesis/stateful.py @@ -15,7 +15,7 @@ a single value. Notably, the set of steps available at any point may depend on the execution to date. """ - +import collections import inspect from copy import copy from functools import lru_cache @@ -268,7 +268,8 @@ class RuleBasedStateMachine(metaclass=StateMachineMeta): if not self.rules(): raise InvalidDefinition(f"Type {type(self).__name__} defines no rules") self.bundles: Dict[str, list] = {} - self.name_counter = 1 + self.names_counters: collections.Counter = collections.Counter() + self.names_list: list[str] = [] self.names_to_values: Dict[str, Any] = {} self.__stream = StringIO() self.__printer = RepresentationPrinter( @@ -301,15 +302,16 @@ class RuleBasedStateMachine(metaclass=StateMachineMeta): def __repr__(self): return f"{type(self).__name__}({nicerepr(self.bundles)})" - def _new_name(self): - result = f"v{self.name_counter}" - self.name_counter += 1 + def _new_name(self, target): + result = f"{target}_{self.names_counters[target]}" + self.names_counters[target] += 1 + self.names_list.append(result) return result def _last_names(self, n): - assert self.name_counter > n - count = self.name_counter - return [f"v{i}" for i in range(count - n, count)] + len_ = len(self.names_list) + assert len_ >= n + return self.names_list[len_ - n :] def bundle(self, name): return self.bundles.setdefault(name, []) @@ -364,7 +366,8 @@ class RuleBasedStateMachine(metaclass=StateMachineMeta): if len(result.values) == 1: output_assignment = f"({self._last_names(1)[0]},) = " elif result.values: - output_names = self._last_names(len(result.values)) + number_of_last_names = len(rule.targets) * len(result.values) + output_names = self._last_names(number_of_last_names) output_assignment = ", ".join(output_names) + " = " else: output_assignment = self._last_names(1)[0] + " = " @@ -372,12 +375,14 @@ class RuleBasedStateMachine(metaclass=StateMachineMeta): return f"{output_assignment}state.{rule.function.__name__}({args})" def _add_result_to_targets(self, targets, result): - name = self._new_name() - self.__printer.singleton_pprinters.setdefault( - id(result), lambda obj, p, cycle: p.text(name) - ) - self.names_to_values[name] = result for target in targets: + name = self._new_name(target) + + def printer(obj, p, cycle, name=name): + return p.text(name) + + self.__printer.singleton_pprinters.setdefault(id(result), printer) + self.names_to_values[name] = result self.bundles.setdefault(target, []).append(VarReference(name)) def check_invariants(self, settings, output, runtimes): diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py index 187c174defd..2c4aff4b5b7 100644 --- a/contrib/python/hypothesis/py3/hypothesis/version.py +++ b/contrib/python/hypothesis/py3/hypothesis/version.py @@ -8,5 +8,5 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. -__version_info__ = (6, 98, 13) +__version_info__ = (6, 98, 16) __version__ = ".".join(map(str, __version_info__)) diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make index 1c48b292f9b..ed3cec24db3 100644 --- a/contrib/python/hypothesis/py3/ya.make +++ b/contrib/python/hypothesis/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(6.98.13) +VERSION(6.98.16) LICENSE(MPL-2.0) diff --git a/contrib/python/python-dateutil/py3/.dist-info/METADATA b/contrib/python/python-dateutil/py3/.dist-info/METADATA index 1e46c96a44b..577f2bf2b77 100644 --- a/contrib/python/python-dateutil/py3/.dist-info/METADATA +++ b/contrib/python/python-dateutil/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: python-dateutil -Version: 2.8.2 +Version: 2.9.0.post0 Summary: Extensions to the standard Python datetime module Home-page: https://github.com/dateutil/dateutil Author: Gustavo Niemeyer @@ -10,7 +10,6 @@ Maintainer-email: [email protected] License: Dual License Project-URL: Documentation, https://dateutil.readthedocs.io/en/stable/ Project-URL: Source, https://github.com/dateutil/dateutil -Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License @@ -26,11 +25,14 @@ Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 Classifier: Topic :: Software Development :: Libraries Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,>=2.7 Description-Content-Type: text/x-rst License-File: LICENSE -Requires-Dist: six (>=1.5) +Requires-Dist: six >=1.5 dateutil - powerful extensions to datetime ========================================== @@ -181,7 +183,7 @@ keys can be found below: =========== ============================ Releases Signing key fingerprint =========== ============================ -2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ +2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ =========== ============================ New releases *may* have signed tags, but binary and source distributions @@ -200,5 +202,3 @@ All contributions after December 1, 2017 released under dual license - either `A .. _6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB: https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB - - diff --git a/contrib/python/python-dateutil/py3/AUTHORS.md b/contrib/python/python-dateutil/py3/AUTHORS.md index fa9184207fd..793a2fd5958 100644 --- a/contrib/python/python-dateutil/py3/AUTHORS.md +++ b/contrib/python/python-dateutil/py3/AUTHORS.md @@ -15,6 +15,7 @@ switch, and thus all their contributions are dual-licensed. - Adrien Cossa <cossa@MASKED> - Alec Nikolas Reiter <alecreiter@MASKED> - Alec Reiter <areiter@MASKED> +- Aleksei Strizhak <alexei.mifrill.strizhak@MASKED> (gh: @Mifrill) - Alex Chamberlain (gh: @alexchamberlain) **D** - Alex Verdyan <verdyan@MASKED> - Alex Willmer <[email protected]> (gh: @moreati) **R** @@ -59,6 +60,7 @@ switch, and thus all their contributions are dual-licensed. - Ionuț Ciocîrlan <jdxlark@MASKED> - Jacqueline Chen <[email protected]> (gh: @jachen20) **D** - Jake Chorley (gh: @jakec-github) **D** +- Jakub Kulík (gh: @kulikjak) **D** - Jan Studený <jendas1@MASKED> - Jay Weisskopf <[email protected]> (gh: @jayschwa) **D** - Jitesh <jitesh@MASKED> @@ -108,6 +110,7 @@ switch, and thus all their contributions are dual-licensed. - Thierry Bastian <thierryb@MASKED> - Thomas A Caswell <tcaswell@MASKED> (gh: @tacaswell) **R** - Thomas Achtemichuk <tom@MASKED> +- Thomas Grainger <[email protected]> (gh: @graingert) **D** - Thomas Kluyver <takowl@MASKED> (gh: @takluyver) - Tim Gates <[email protected]> (gh: timgates42) - Tomasz Kluczkowski (gh: @Tomasz-Kluczkowski) **D** diff --git a/contrib/python/python-dateutil/py3/README.rst b/contrib/python/python-dateutil/py3/README.rst index 106023b3241..c9db1fd3597 100644 --- a/contrib/python/python-dateutil/py3/README.rst +++ b/contrib/python/python-dateutil/py3/README.rst @@ -147,7 +147,7 @@ keys can be found below: =========== ============================ Releases Signing key fingerprint =========== ============================ -2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ +2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ =========== ============================ New releases *may* have signed tags, but binary and source distributions diff --git a/contrib/python/python-dateutil/py3/dateutil/__init__.py b/contrib/python/python-dateutil/py3/dateutil/__init__.py index 0defb82e21f..a2c19c06fe1 100644 --- a/contrib/python/python-dateutil/py3/dateutil/__init__.py +++ b/contrib/python/python-dateutil/py3/dateutil/__init__.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +import sys + try: from ._version import version as __version__ except ImportError: @@ -6,3 +8,17 @@ except ImportError: __all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz', 'utils', 'zoneinfo'] + +def __getattr__(name): + import importlib + + if name in __all__: + return importlib.import_module("." + name, __name__) + raise AttributeError( + "module {!r} has not attribute {!r}".format(__name__, name) + ) + + +def __dir__(): + # __dir__ should include all the lazy-importable modules as well. + return [x for x in globals() if x not in sys.modules] + __all__ diff --git a/contrib/python/python-dateutil/py3/dateutil/_version.py b/contrib/python/python-dateutil/py3/dateutil/_version.py index b723056a756..ddda9809852 100644 --- a/contrib/python/python-dateutil/py3/dateutil/_version.py +++ b/contrib/python/python-dateutil/py3/dateutil/_version.py @@ -1,5 +1,4 @@ -# coding: utf-8 # file generated by setuptools_scm # don't change, don't track in version control -version = '2.8.2' -version_tuple = (2, 8, 2) +__version__ = version = '2.9.0.post0' +__version_tuple__ = version_tuple = (2, 9, 0) diff --git a/contrib/python/python-dateutil/py3/dateutil/parser/isoparser.py b/contrib/python/python-dateutil/py3/dateutil/parser/isoparser.py index 5d7bee38006..7060087df47 100644 --- a/contrib/python/python-dateutil/py3/dateutil/parser/isoparser.py +++ b/contrib/python/python-dateutil/py3/dateutil/parser/isoparser.py @@ -72,7 +72,7 @@ class isoparser(object): Common: - ``YYYY`` - - ``YYYY-MM`` or ``YYYYMM`` + - ``YYYY-MM`` - ``YYYY-MM-DD`` or ``YYYYMMDD`` Uncommon: diff --git a/contrib/python/python-dateutil/py3/dateutil/relativedelta.py b/contrib/python/python-dateutil/py3/dateutil/relativedelta.py index a9e85f7e6cd..cd323a549e0 100644 --- a/contrib/python/python-dateutil/py3/dateutil/relativedelta.py +++ b/contrib/python/python-dateutil/py3/dateutil/relativedelta.py @@ -48,7 +48,7 @@ class relativedelta(object): the corresponding arithmetic operation on the original datetime value with the information in the relativedelta. - weekday: + weekday: One of the weekday instances (MO, TU, etc) available in the relativedelta module. These instances may receive a parameter N, specifying the Nth weekday, which could be positive or negative diff --git a/contrib/python/python-dateutil/py3/dateutil/rrule.py b/contrib/python/python-dateutil/py3/dateutil/rrule.py index b3203393c61..571a0d2bc88 100644 --- a/contrib/python/python-dateutil/py3/dateutil/rrule.py +++ b/contrib/python/python-dateutil/py3/dateutil/rrule.py @@ -182,7 +182,7 @@ class rrulebase(object): # __len__() introduces a large performance penalty. def count(self): """ Returns the number of recurrences in this set. It will have go - trough the whole recurrence, if this hasn't been done before. """ + through the whole recurrence, if this hasn't been done before. """ if self._len is None: for x in self: pass diff --git a/contrib/python/python-dateutil/py3/dateutil/tz/tz.py b/contrib/python/python-dateutil/py3/dateutil/tz/tz.py index 84504cf8eba..617591446bd 100644 --- a/contrib/python/python-dateutil/py3/dateutil/tz/tz.py +++ b/contrib/python/python-dateutil/py3/dateutil/tz/tz.py @@ -34,7 +34,7 @@ except ImportError: from warnings import warn ZERO = datetime.timedelta(0) -EPOCH = datetime.datetime(1970, 1, 1, tzinfo=None) +EPOCH = datetime.datetime(1970, 1, 1, 0, 0) EPOCHORDINAL = EPOCH.toordinal() diff --git a/contrib/python/python-dateutil/py3/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz b/contrib/python/python-dateutil/py3/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz Binary files differindex 631ab17d2d5..1461f8c862d 100644 --- a/contrib/python/python-dateutil/py3/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz +++ b/contrib/python/python-dateutil/py3/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz diff --git a/contrib/python/python-dateutil/py3/dateutil/test/__init__.py b/contrib/python/python-dateutil/py3/tests/__init__.py index e69de29bb2d..e69de29bb2d 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/__init__.py +++ b/contrib/python/python-dateutil/py3/tests/__init__.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/_common.py b/contrib/python/python-dateutil/py3/tests/_common.py index b8d20473743..b8d20473743 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/_common.py +++ b/contrib/python/python-dateutil/py3/tests/_common.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/conftest.py b/contrib/python/python-dateutil/py3/tests/conftest.py index 78ed70acb3c..78ed70acb3c 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/conftest.py +++ b/contrib/python/python-dateutil/py3/tests/conftest.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/property/test_isoparse_prop.py b/contrib/python/python-dateutil/py3/tests/property/test_isoparse_prop.py index f8e288f3d60..f8e288f3d60 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/property/test_isoparse_prop.py +++ b/contrib/python/python-dateutil/py3/tests/property/test_isoparse_prop.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/property/test_parser_prop.py b/contrib/python/python-dateutil/py3/tests/property/test_parser_prop.py index fdfd171e867..fdfd171e867 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/property/test_parser_prop.py +++ b/contrib/python/python-dateutil/py3/tests/property/test_parser_prop.py diff --git a/contrib/python/python-dateutil/py3/tests/property/test_tz_prop.py b/contrib/python/python-dateutil/py3/tests/property/test_tz_prop.py new file mode 100644 index 00000000000..ec6d271dcf1 --- /dev/null +++ b/contrib/python/python-dateutil/py3/tests/property/test_tz_prop.py @@ -0,0 +1,35 @@ +from datetime import datetime, timedelta + +import pytest +import six +from hypothesis import assume, given +from hypothesis import strategies as st + +from dateutil import tz as tz + +EPOCHALYPSE = datetime.fromtimestamp(2147483647) +NEGATIVE_EPOCHALYPSE = datetime.fromtimestamp(0) - timedelta(seconds=2147483648) + + [email protected]("gettz_arg", [None, ""]) +# TODO: Remove bounds when GH #590 is resolved +@given( + dt=st.datetimes( + min_value=NEGATIVE_EPOCHALYPSE, max_value=EPOCHALYPSE, timezones=st.just(tz.UTC), + ) +) +def test_gettz_returns_local(gettz_arg, dt): + act_tz = tz.gettz(gettz_arg) + if isinstance(act_tz, tz.tzlocal): + return + + dt_act = dt.astimezone(tz.gettz(gettz_arg)) + if six.PY2: + dt_exp = dt.astimezone(tz.tzlocal()) + else: + dt_exp = dt.astimezone() + + assert dt_act == dt_exp + assert dt_act.tzname() == dt_exp.tzname() + assert dt_act.utcoffset() == dt_exp.utcoffset() diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_easter.py b/contrib/python/python-dateutil/py3/tests/test_easter.py index cf2ec7f2871..cf2ec7f2871 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_easter.py +++ b/contrib/python/python-dateutil/py3/tests/test_easter.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_import_star.py b/contrib/python/python-dateutil/py3/tests/test_import_star.py index 2fb70981286..2fb70981286 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_import_star.py +++ b/contrib/python/python-dateutil/py3/tests/test_import_star.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_imports.py b/contrib/python/python-dateutil/py3/tests/test_imports.py index 60b86005ca3..7d0749ec544 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_imports.py +++ b/contrib/python/python-dateutil/py3/tests/test_imports.py @@ -1,5 +1,69 @@ import sys +import unittest import pytest +import six + +MODULE_TYPE = type(sys) + + +# Tests live in datetutil/test which cause a RuntimeWarning for Python2 builds. +# But since we expect lazy imports tests to fail for Python < 3.7 we'll ignore those +# warnings with this filter. + +if six.PY2: + filter_import_warning = pytest.mark.filterwarnings("ignore::RuntimeWarning") +else: + + def filter_import_warning(f): + return f + + [email protected](scope="function") +def clean_import(): + """Create a somewhat clean import base for lazy import tests""" + du_modules = { + mod_name: mod + for mod_name, mod in sys.modules.items() + if mod_name.startswith("dateutil") + } + + other_modules = { + mod_name for mod_name in sys.modules if mod_name not in du_modules + } + + for mod_name in du_modules: + del sys.modules[mod_name] + + yield + + # Delete anything that wasn't in the origin sys.modules list + for mod_name in list(sys.modules): + if mod_name not in other_modules: + del sys.modules[mod_name] + + # Restore original modules + for mod_name, mod in du_modules.items(): + sys.modules[mod_name] = mod + + +@filter_import_warning + "module", + ["easter", "parser", "relativedelta", "rrule", "tz", "utils", "zoneinfo"], +) +def test_lazy_import(clean_import, module): + """Test that dateutil.[submodule] works for py version > 3.7""" + + import dateutil, importlib + + if sys.version_info < (3, 7): + pytest.xfail("Lazy loading does not work for Python < 3.7") + + mod_obj = getattr(dateutil, module, None) + assert isinstance(mod_obj, MODULE_TYPE) + + mod_imported = importlib.import_module("dateutil.%s" % module) + assert mod_obj is mod_imported HOST_IS_WINDOWS = sys.platform.startswith('win') diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_internals.py b/contrib/python/python-dateutil/py3/tests/test_internals.py index 530813147d2..b32e6723fc4 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_internals.py +++ b/contrib/python/python-dateutil/py3/tests/test_internals.py @@ -9,6 +9,7 @@ code that may be difficult to reach through the standard API calls. import sys import pytest +import warnings from dateutil.parser._parser import _ymd from dateutil import tz @@ -65,18 +66,17 @@ def test_parser_parser_private_not_warns(): from dateutil.parser._parser import _timelex, _tzparser from dateutil.parser._parser import _parsetz - with pytest.warns(None) as recorder: + with warnings.catch_warnings(): + warnings.simplefilter("error") _tzparser() - assert len(recorder) == 0 - with pytest.warns(None) as recorder: + with warnings.catch_warnings(): + warnings.simplefilter("error") _timelex('2014-03-03') - assert len(recorder) == 0 - - with pytest.warns(None) as recorder: + with warnings.catch_warnings(): + warnings.simplefilter("error") _parsetz('+05:00') - assert len(recorder) == 0 @pytest.mark.tzstr diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_isoparser.py b/contrib/python/python-dateutil/py3/tests/test_isoparser.py index 35899ab9b15..c33881f3b0b 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_isoparser.py +++ b/contrib/python/python-dateutil/py3/tests/test_isoparser.py @@ -80,10 +80,10 @@ def _isoparse_date_and_time(dt, date_fmt, time_fmt, tzoffset, if not fmt.endswith('%f'): # pragma: nocover raise ValueError('Time format has no microseconds!') - if microsecond_precision != 6: - dtstr = dtstr[:-(6 - microsecond_precision)] - elif microsecond_precision > 6: # pragma: nocover - raise ValueError('Precision must be 1-6') + if microsecond_precision != 6: + dtstr = dtstr[: -(6 - microsecond_precision)] + elif microsecond_precision > 6: # pragma: nocover + raise ValueError("Precision must be 1-6") dtstr += offset_str diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_parser.py b/contrib/python/python-dateutil/py3/tests/test_parser.py index 08a34dafbc9..08a34dafbc9 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_parser.py +++ b/contrib/python/python-dateutil/py3/tests/test_parser.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_relativedelta.py b/contrib/python/python-dateutil/py3/tests/test_relativedelta.py index 1e5d170449a..5204c293b7c 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_relativedelta.py +++ b/contrib/python/python-dateutil/py3/tests/test_relativedelta.py @@ -650,6 +650,67 @@ class RelativeDeltaTest(unittest.TestCase): except: self.fail("relativedelta() failed to hash!") + def testDayOfMonthPlus(self): + assert [ + date(2021, 1, 28) + relativedelta(months=1), + date(2021, 2, 27) + relativedelta(months=1), + date(2021, 4, 29) + relativedelta(months=1), + date(2021, 5, 30) + relativedelta(months=1), + ] == [ + date(2021, 2, 28), + date(2021, 3, 27), + date(2021, 5, 29), + date(2021, 6, 30), + ] + + def testLastDayOfMonthPlus(self): + assert [ + date(2021, 1, 31) + relativedelta(months=1), + date(2021, 1, 30) + relativedelta(months=1), + date(2021, 1, 29) + relativedelta(months=1), + date(2021, 1, 28) + relativedelta(months=1), + date(2021, 2, 28) + relativedelta(months=1), + date(2021, 4, 30) + relativedelta(months=1), + date(2021, 5, 31) + relativedelta(months=1), + ] == [ + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 3, 28), + date(2021, 5, 30), + date(2021, 6, 30), + ] + + def testDayOfMonthMinus(self): + assert [ + date(2021, 2, 27) - relativedelta(months=1), + date(2021, 3, 30) - relativedelta(months=1), + date(2021, 3, 29) - relativedelta(months=1), + date(2021, 3, 28) - relativedelta(months=1), + date(2021, 5, 30) - relativedelta(months=1), + date(2021, 6, 29) - relativedelta(months=1), + ] == [ + date(2021, 1, 27), + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 4, 30), + date(2021, 5, 29), + ] + + def testLastDayOfMonthMinus(self): + assert [ + date(2021, 2, 28) - relativedelta(months=1), + date(2021, 3, 31) - relativedelta(months=1), + date(2021, 5, 31) - relativedelta(months=1), + date(2021, 6, 30) - relativedelta(months=1), + ] == [ + date(2021, 1, 28), + date(2021, 2, 28), + date(2021, 4, 30), + date(2021, 5, 30), + ] class RelativeDeltaWeeksPropertyGetterTest(unittest.TestCase): """Test the weeks property getter""" diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_rrule.py b/contrib/python/python-dateutil/py3/tests/test_rrule.py index 52673ecc265..52673ecc265 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_rrule.py +++ b/contrib/python/python-dateutil/py3/tests/test_rrule.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_tz.py b/contrib/python/python-dateutil/py3/tests/test_tz.py index e5e4772d9ad..e5e4772d9ad 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_tz.py +++ b/contrib/python/python-dateutil/py3/tests/test_tz.py diff --git a/contrib/python/python-dateutil/py3/dateutil/test/test_utils.py b/contrib/python/python-dateutil/py3/tests/test_utils.py index fe1bfdcb84f..fe1bfdcb84f 100644 --- a/contrib/python/python-dateutil/py3/dateutil/test/test_utils.py +++ b/contrib/python/python-dateutil/py3/tests/test_utils.py diff --git a/contrib/python/python-dateutil/py3/tests/ya.make b/contrib/python/python-dateutil/py3/tests/ya.make index b6d9599bef1..a4365c02429 100644 --- a/contrib/python/python-dateutil/py3/tests/ya.make +++ b/contrib/python/python-dateutil/py3/tests/ya.make @@ -11,8 +11,6 @@ ENV(LANG=ru_RU.UTF-8) # because we cannot change TZ in arcadia CI ENV(DATEUTIL_MAY_NOT_CHANGE_TZ_VAR=1) -SRCDIR(contrib/python/python-dateutil/py3/dateutil/test) - TEST_SRCS( property/test_isoparse_prop.py property/test_parser_prop.py diff --git a/contrib/python/python-dateutil/py3/ya.make b/contrib/python/python-dateutil/py3/ya.make index 7dbd49b2aeb..bfc2dd5a73b 100644 --- a/contrib/python/python-dateutil/py3/ya.make +++ b/contrib/python/python-dateutil/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(2.8.2) +VERSION(2.9.0.post0) LICENSE(BSD-3-Clause) diff --git a/contrib/python/types-protobuf/.dist-info/METADATA b/contrib/python/types-protobuf/.dist-info/METADATA index da16877bae9..4108d715f65 100644 --- a/contrib/python/types-protobuf/.dist-info/METADATA +++ b/contrib/python/types-protobuf/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: types-protobuf -Version: 4.24.0.20240129 +Version: 4.24.0.20240302 Summary: Typing stubs for protobuf Home-page: https://github.com/python/typeshed License: Apache-2.0 license @@ -38,6 +38,6 @@ If you find that annotations are missing, feel free to contribute and help compl See https://github.com/python/typeshed/blob/main/README.md for more details. -This package was generated from typeshed commit `3dbb2573e68a288ac5ad1b4967a9c5ab994b81be` and was tested -with mypy 1.8.0, pyright 1.1.342, and -pytype 2023.12.18. +This package was generated from typeshed commit `5e4483618a02b4bf182940e3b89e8178855e6f32` and was tested +with mypy 1.8.0, pyright 1.1.350, and +pytype 2024.2.27. diff --git a/contrib/python/types-protobuf/ya.make b/contrib/python/types-protobuf/ya.make index 9ba2128ebd2..60afce42f6a 100644 --- a/contrib/python/types-protobuf/ya.make +++ b/contrib/python/types-protobuf/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(4.24.0.20240129) +VERSION(4.24.0.20240302) LICENSE(Apache-2.0) |
