diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-03-16 14:04:41 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-03-16 14:15:11 +0300 |
commit | d83e7ea91cbc5e5d4ea49195eeab84c364dba4bb (patch) | |
tree | 5ffdbed1c2a932a8d41089a6ac2766dd783ad15b | |
parent | f7d1b63f8a2e18da4372628a2917fa0c508ba43a (diff) | |
download | ydb-d83e7ea91cbc5e5d4ea49195eeab84c364dba4bb.tar.gz |
Intermediate changes
67 files changed, 469 insertions, 314 deletions
diff --git a/contrib/python/Twisted/py3/.dist-info/METADATA b/contrib/python/Twisted/py3/.dist-info/METADATA index 6f2beda880..2f5a63dbb8 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 f3811313cd..46747386e3 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 73783ca21a..ba458874ce 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 e69de29bb2..0000000000 --- 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 3f2476fe9c..1d58c477de 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 194a4dd8a7..9e702f7e84 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 17b21962ae..01bbaeba1b 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 e314e3cd72..0696aeb1ac 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 9aed452d3b..848c7c2fb2 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 678f54e59b..22eb26b1a4 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 4a6d1323ab..587ec1bd05 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 758a4cecb7..389182a69a 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 636aefa170..7858362dda 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 fa878f6cba..18793bfbba 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 552c30bbf0..abb6bddf7c 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 2dda4b9816..59874ed2f6 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 f1ac920f60..104d65f348 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 142c0472ef..f686092e69 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 17e717cad2..caafb52210 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 4a4cf55e8e..7ab1d81731 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 e9c072f41a..4a193a79ec 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 b4e0c4c4e1..d0fc744083 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 826c976487..9cb9f16da2 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 aadd685269..ef72b7ed7e 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 bd160ec865..ed218b37f3 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 ef3b88d9f1..ff7684e358 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 bfbffb9cb4..265fea2405 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 d63d4ce435..4fda3b9115 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 1ad02b3c09..902268bab4 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 c87b5b7333..8f85025556 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 - - def __init__(self, sock, protocol, client, server, sessionno, reactor): + _addressType: Union[ + type[address.IPv4Address], type[address.IPv6Address] + ] = address.IPv4Address + + 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 0e96012ea5..8fbef7d554 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 b988724dfa..257c5259ce 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 fa4220ea3e..07e443849a 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 4bc06ec40c..59b44c7f72 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 7a49718db7..9663421220 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 2ecdd43045..0cc05ce501 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 800a549f88..39fab342de 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 030b643883..abc707e4a8 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 a5f6dbef3b..2564257966 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 7ac5398cd9..460f5b4ff2 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 128c1b7938..b1f761f598 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 a8c35754a9..ac28a92bfa 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 5b8e587401..cfcf7c99bc 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 d2ac2d2cf8..be7a58ce4d 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 8ceb111676..90f5858c96 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 fbad78e408..df970363c6 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 c85b98d627..c5df556f70 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 ca893ca4c9..c006d555e5 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 c285d4ad10..bea04ee560 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 aea6a6ed82..d2294a593a 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 7d08424bdd..a735cd6737 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 058f1044b3..6047f7eda5 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 df1b22fa1e..f86c1ec90e 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 ef98fee272..4e8d11d778 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 3db4dca5de..8bb5ecf7a4 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 2cffc2c79e..6b1f43dc89 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 2664b2fe0d..4ee67ebcf6 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 57762e1805..24c24fc0ff 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 4a9f7f2100..230c33f3e8 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 9a0d5e9e10..e66b0cf317 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 + response: IResponse - def info(self): - class _Meta: - def getheaders(zelf, name): - # PY2 - headers = self.response.headers.getRawHeaders(name, []) - return headers - - 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 2bad1471dc..1c598380ac 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}. - Not used in any other state. + @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} + + @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 54ea1c431b..f94f8655b9 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 33b172cdbf..456db72d12 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 bc4a90f748..794eef8f63 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 e8e01ec781..6392a3168a 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 c60bc92b91..cc44b41e2a 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 4a28d8ff16..47590a4139 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 |