aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-12-17 12:07:28 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-12-17 12:18:43 +0300
commit48bd5f88777f4dc94fd41a7dd22808ed639b985d (patch)
tree6a899d7cc8bd632073408198260a93d76f99ef32 /contrib/python
parent3e05dc5f5c47aa8d220db7b5508cfbd4a0d8919f (diff)
downloadydb-48bd5f88777f4dc94fd41a7dd22808ed639b985d.tar.gz
Intermediate changes
commit_hash:3786c4fc65af12274eea45a3ef9de6050e262ac0
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/Twisted/py3/.dist-info/METADATA6
-rw-r--r--contrib/python/Twisted/py3/README.rst2
-rw-r--r--contrib/python/Twisted/py3/twisted/_version.py2
-rw-r--r--contrib/python/Twisted/py3/twisted/conch/ssh/keys.py6
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/_multicast.py161
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/abstract.py34
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/endpoints.py255
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/interfaces.py89
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/iocpreactor/reactor.py4
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/iocpreactor/udp.py101
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/posixbase.py12
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/protocol.py13
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/tcp.py33
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/udp.py88
-rw-r--r--contrib/python/Twisted/py3/twisted/internet/unix.py30
-rw-r--r--contrib/python/Twisted/py3/twisted/mail/imap4.py25
-rw-r--r--contrib/python/Twisted/py3/twisted/python/__init__.py10
-rw-r--r--contrib/python/Twisted/py3/twisted/python/compat.py12
-rw-r--r--contrib/python/Twisted/py3/twisted/python/constants.py14
-rw-r--r--contrib/python/Twisted/py3/twisted/words/xish/xpathparser.g1
-rw-r--r--contrib/python/Twisted/py3/twisted/words/xish/xpathparser.py1
-rw-r--r--contrib/python/Twisted/py3/ya.make4
-rw-r--r--contrib/python/clickhouse-connect/.dist-info/METADATA2
-rw-r--r--contrib/python/clickhouse-connect/clickhouse_connect/__version__.py2
-rw-r--r--contrib/python/clickhouse-connect/clickhouse_connect/datatypes/temporal.py5
-rw-r--r--contrib/python/clickhouse-connect/clickhouse_connect/driver/dataconv.py3
-rw-r--r--contrib/python/clickhouse-connect/clickhouse_connect/tools/datagen.py7
-rw-r--r--contrib/python/clickhouse-connect/ya.make2
28 files changed, 571 insertions, 353 deletions
diff --git a/contrib/python/Twisted/py3/.dist-info/METADATA b/contrib/python/Twisted/py3/.dist-info/METADATA
index 838ec650c5..6c1a7ea42c 100644
--- a/contrib/python/Twisted/py3/.dist-info/METADATA
+++ b/contrib/python/Twisted/py3/.dist-info/METADATA
@@ -1,18 +1,16 @@
Metadata-Version: 2.3
Name: Twisted
-Version: 24.10.0
+Version: 24.11.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.twisted.org/
Project-URL: Homepage, https://twisted.org/
Project-URL: Issues, https://github.com/twisted/twisted/issues
Project-URL: Source, https://github.com/twisted/twisted
-Project-URL: Twitter, https://twitter.com/twistedmatrix
Project-URL: Funding-PSF, https://psfmember.org/civicrm/contribute/transact/?reset=1&id=44
Project-URL: Funding-GitHub, https://github.com/sponsors/twisted
Author-email: Twisted Matrix Community <twisted@python.org>
License: MIT License
-License-File: LICENSE
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
@@ -293,7 +291,7 @@ If you'd like to join them, please consider `sponsoring Twisted's <https://docs.
What is this?
-------------
-Twisted is an event-based framework for internet applications, supporting Python 3.6+.
+Twisted is a Python event-based framework for internet applications.
It includes modules for many different purposes, including the following:
- ``twisted.web``: HTTP clients and servers, HTML templating, and a WSGI server
diff --git a/contrib/python/Twisted/py3/README.rst b/contrib/python/Twisted/py3/README.rst
index a30c266eb3..bc2e901c67 100644
--- a/contrib/python/Twisted/py3/README.rst
+++ b/contrib/python/Twisted/py3/README.rst
@@ -23,7 +23,7 @@ If you'd like to join them, please consider `sponsoring Twisted's <https://docs.
What is this?
-------------
-Twisted is an event-based framework for internet applications, supporting Python 3.6+.
+Twisted is a Python event-based framework for internet applications.
It includes modules for many different purposes, including the following:
- ``twisted.web``: HTTP clients and servers, HTML templating, and a WSGI server
diff --git a/contrib/python/Twisted/py3/twisted/_version.py b/contrib/python/Twisted/py3/twisted/_version.py
index b43dec8e33..43da56319b 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", 24, 10, 0)
+__version__ = Version("Twisted", 24, 11, 0)
__all__ = ["__version__"]
diff --git a/contrib/python/Twisted/py3/twisted/conch/ssh/keys.py b/contrib/python/Twisted/py3/twisted/conch/ssh/keys.py
index 7d2f1072f4..e0e4a4b2c5 100644
--- a/contrib/python/Twisted/py3/twisted/conch/ssh/keys.py
+++ b/contrib/python/Twisted/py3/twisted/conch/ssh/keys.py
@@ -16,6 +16,7 @@ from hashlib import md5, sha256
from typing import Any
import bcrypt
+from constantly import NamedConstant, Names
from cryptography import utils
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
@@ -32,7 +33,6 @@ from twisted.conch.ssh import common, sexpy
from twisted.conch.ssh.common import int_to_bytes
from twisted.python import randbytes
from twisted.python.compat import iterbytes, nativeString
-from twisted.python.constants import NamedConstant, Names
from twisted.python.deprecate import _mutuallyExclusiveArguments
try:
@@ -99,11 +99,11 @@ class FingerprintFormats(Names):
@cvar MD5_HEX: Named constant representing fingerprint format generated
using md5[RFC1321] algorithm in hexadecimal encoding.
- @type MD5_HEX: L{twisted.python.constants.NamedConstant}
+ @type MD5_HEX: L{constantly.NamedConstant}
@cvar SHA256_BASE64: Named constant representing fingerprint format
generated using sha256[RFC4634] algorithm in base64 encoding
- @type SHA256_BASE64: L{twisted.python.constants.NamedConstant}
+ @type SHA256_BASE64: L{constantly.NamedConstant}
"""
MD5_HEX = NamedConstant()
diff --git a/contrib/python/Twisted/py3/twisted/internet/_multicast.py b/contrib/python/Twisted/py3/twisted/internet/_multicast.py
new file mode 100644
index 0000000000..99b1c937f2
--- /dev/null
+++ b/contrib/python/Twisted/py3/twisted/internet/_multicast.py
@@ -0,0 +1,161 @@
+# -*- test-case-name: twisted.test.test_udp -*-
+# Copyright (c) Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+from __future__ import annotations
+
+import socket
+import struct
+from typing import Any
+
+from twisted.internet.abstract import isIPAddress, isIPv6Address
+from twisted.internet.defer import Deferred, succeed
+from twisted.internet.error import MulticastJoinError
+from twisted.internet.interfaces import IReactorCore
+
+
+def _maybeResolve(reactor: IReactorCore, addr: str) -> Deferred[str]:
+ if isIPv6Address(addr) or isIPAddress(addr):
+ return succeed(addr)
+ return reactor.resolve(addr)
+
+
+class MulticastMixin:
+ """
+ Implement multicast functionality.
+ """
+
+ addressFamily: socket.AddressFamily
+ reactor: Any
+ socket: socket.socket
+
+ def _addrpack(self, addr: str) -> bytes:
+ """
+ Pack an IP address literal into bytes, according to the address family
+ of this transport.
+ """
+ try:
+ return socket.inet_pton(self.addressFamily, addr)
+ except OSError:
+ raise MulticastJoinError(
+ f"invalid address literal for {socket.AddressFamily(self.addressFamily).name}: {addr!r}"
+ )
+
+ @property
+ def _ipproto(self) -> int:
+ return (
+ socket.IPPROTO_IP
+ if self.addressFamily == socket.AF_INET
+ else socket.IPPROTO_IPV6
+ )
+
+ @property
+ def _multiloop(self) -> int:
+ return (
+ socket.IP_MULTICAST_LOOP
+ if self.addressFamily == socket.AF_INET
+ else socket.IPV6_MULTICAST_LOOP
+ )
+
+ @property
+ def _multiif(self) -> int:
+ return (
+ socket.IP_MULTICAST_IF
+ if self.addressFamily == socket.AF_INET
+ else socket.IPV6_MULTICAST_IF
+ )
+
+ @property
+ def _joingroup(self) -> int:
+ return (
+ socket.IP_ADD_MEMBERSHIP
+ if self.addressFamily == socket.AF_INET
+ else socket.IPV6_JOIN_GROUP
+ )
+
+ @property
+ def _leavegroup(self) -> int:
+ return (
+ socket.IP_DROP_MEMBERSHIP
+ if self.addressFamily == socket.AF_INET
+ else socket.IPV6_LEAVE_GROUP
+ )
+
+ def getOutgoingInterface(self) -> str | int:
+ blen = 0x4 if self.addressFamily == socket.AF_INET else 0x10
+ ipproto = self._ipproto
+ multiif = self._multiif
+ i = self.socket.getsockopt(ipproto, multiif, blen)
+ from sys import byteorder
+
+ if self.addressFamily == socket.AF_INET6:
+ return int.from_bytes(i, byteorder)
+ return socket.inet_ntop(self.addressFamily, i)
+
+ def setOutgoingInterface(self, addr: str | int) -> Deferred[int]:
+ """
+ @see: L{IMulticastTransport.setOutgoingInterface}
+ """
+
+ async def asynchronously() -> int:
+ i: bytes | int
+ if self.addressFamily == socket.AF_INET:
+ assert isinstance(
+ addr, str
+ ), "IPv4 interfaces are specified as addresses"
+ i = self._addrpack(await _maybeResolve(self.reactor, addr))
+ else:
+ assert isinstance(
+ addr, int
+ ), "IPv6 interfaces are specified as integers"
+ i = addr
+ self.socket.setsockopt(self._ipproto, self._multiif, i)
+ return 1
+
+ return Deferred.fromCoroutine(asynchronously())
+
+ def getLoopbackMode(self) -> bool:
+ return bool(self.socket.getsockopt(self._ipproto, self._multiloop))
+
+ def setLoopbackMode(self, mode: int) -> None:
+ # mode = struct.pack("b", bool(mode))
+ a = self._ipproto
+ b = self._multiloop
+ self.socket.setsockopt(a, b, int(bool(mode)))
+
+ def getTTL(self) -> int:
+ return self.socket.getsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL)
+
+ def setTTL(self, ttl: int) -> None:
+ bttl = struct.pack("B", ttl)
+ self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, bttl)
+
+ def _joinleave(self, addr: str, interface: str, join: bool) -> Deferred[None]:
+ cmd = self._joingroup if join else self._leavegroup
+ if not interface:
+ interface = "0.0.0.0" if self.addressFamily == socket.AF_INET else "::"
+
+ async def impl() -> None:
+ resaddr = await _maybeResolve(self.reactor, addr)
+ resif = await _maybeResolve(self.reactor, interface)
+
+ packaddr = self._addrpack(resaddr)
+ packif = self._addrpack(resif)
+ try:
+ self.socket.setsockopt(self._ipproto, cmd, packaddr + packif)
+ except OSError as e:
+ raise MulticastJoinError(addr, interface, *e.args) from e
+
+ return Deferred.fromCoroutine(impl())
+
+ def joinGroup(self, addr: str, interface: str = "") -> Deferred[None]:
+ """
+ @see: L{IMulticastTransport.joinGroup}
+ """
+ return self._joinleave(addr, interface, True)
+
+ def leaveGroup(self, addr: str, interface: str = "") -> Deferred[None]:
+ """
+ @see: L{IMulticastTransport.leaveGroup}
+ """
+ return self._joinleave(addr, interface, False)
diff --git a/contrib/python/Twisted/py3/twisted/internet/abstract.py b/contrib/python/Twisted/py3/twisted/internet/abstract.py
index 45a80383c2..09bd751199 100644
--- a/contrib/python/Twisted/py3/twisted/internet/abstract.py
+++ b/contrib/python/Twisted/py3/twisted/internet/abstract.py
@@ -6,9 +6,10 @@
Support for generic select()able objects.
"""
+from __future__ import annotations
from socket import AF_INET, AF_INET6, inet_pton
-from typing import Iterable, List, Optional
+from typing import Iterable, List, Optional, Union
from zope.interface import implementer
@@ -165,6 +166,12 @@ class FileDescriptor(_ConsumerMixin, _LogOwner):
valid to be passed to select(2).
"""
+ # We have two buffers: a list (_tempDataBuffer), and a byte string
+ # (self.dataBuffer). A given write may not be able to write everything, and
+ # we also limit to sending at most SEND_LIMIT bytes at a time. Thus, we
+ # also have self.offset tracks where in self.dataBuffer we are in the
+ # writing process, to reduce unnecessary copying if we failed to write all
+ # the data.
connected = 0
disconnected = 0
disconnecting = 0
@@ -208,7 +215,7 @@ class FileDescriptor(_ConsumerMixin, _LogOwner):
self.stopReading()
self.stopWriting()
- def writeSomeData(self, data: bytes) -> None:
+ def writeSomeData(self, data: bytes) -> Union[int, BaseException]:
"""
Write as much as possible of the given data, immediately.
@@ -242,12 +249,22 @@ class FileDescriptor(_ConsumerMixin, _LogOwner):
@see: L{twisted.internet.interfaces.IWriteDescriptor.doWrite}.
"""
- if len(self.dataBuffer) - self.offset < self.SEND_LIMIT:
- # If there is currently less than SEND_LIMIT bytes left to send
- # in the string, extend it with the array data.
- self.dataBuffer = _concatenate(
- self.dataBuffer, self.offset, self._tempDataBuffer
- )
+ # We only send at most SEND_LIMIT bytes at a time. If the amount of
+ # bytes in our send-immediately buffer is smaller than that limit,
+ # probably a good time to add the bytes from our secondary, list-based
+ # buffer (self._tempDataBuffer.)
+ remaining = len(self.dataBuffer) - self.offset
+ if remaining < self.SEND_LIMIT:
+ if remaining > 0:
+ # There is currently some data to write, extend it with the
+ # list data.
+ self.dataBuffer = _concatenate(
+ self.dataBuffer, self.offset, self._tempDataBuffer
+ )
+ else:
+ # self.dataBuffer has nothing left to write, so just convert
+ # the list buffer to bytes buffer in a cheaper way:
+ self.dataBuffer = b"".join(self._tempDataBuffer)
self.offset = 0
self._tempDataBuffer = []
self._tempDataLen = 0
@@ -256,6 +273,7 @@ class FileDescriptor(_ConsumerMixin, _LogOwner):
if self.offset:
l = self.writeSomeData(lazyByteSlice(self.dataBuffer, self.offset))
else:
+ # Optimization: skip lazyByteSlice() when it's unnecessary.
l = self.writeSomeData(self.dataBuffer)
# There is no writeSomeData implementation in Twisted which returns
diff --git a/contrib/python/Twisted/py3/twisted/internet/endpoints.py b/contrib/python/Twisted/py3/twisted/internet/endpoints.py
index a98fd2ba43..dfa0cc43ce 100644
--- a/contrib/python/Twisted/py3/twisted/internet/endpoints.py
+++ b/contrib/python/Twisted/py3/twisted/internet/endpoints.py
@@ -12,21 +12,22 @@ parsed by the L{clientFromString} and L{serverFromString} functions.
@since: 10.1
"""
+from __future__ import annotations
import os
import re
import socket
import warnings
-from typing import Optional, Sequence, Type
+from typing import Any, Iterable, Optional, Sequence, Type
from unicodedata import normalize
-from zope.interface import directlyProvides, implementer, provider
+from zope.interface import directlyProvides, implementer
from constantly import NamedConstant, Names
from incremental import Version
from twisted.internet import defer, error, fdesc, interfaces, threads
-from twisted.internet.abstract import isIPAddress, isIPv6Address
+from twisted.internet.abstract import isIPv6Address
from twisted.internet.address import (
HostnameAddress,
IPv4Address,
@@ -37,9 +38,13 @@ from twisted.internet.interfaces import (
IAddress,
IHostnameResolver,
IHostResolution,
+ IOpenSSLClientConnectionCreator,
+ IProtocol,
+ IProtocolFactory,
IReactorPluggableNameResolver,
IReactorSocket,
IResolutionReceiver,
+ IStreamClientEndpoint,
IStreamClientEndpointStringParserWithReactor,
IStreamServerEndpointStringParser,
)
@@ -201,14 +206,16 @@ class _WrappingFactory(ClientFactory):
# Type is wrong. See https://twistedmatrix.com/trac/ticket/10005#ticket
protocol = _WrappingProtocol # type: ignore[assignment]
- def __init__(self, wrappedFactory):
+ def __init__(self, wrappedFactory: IProtocolFactory) -> None:
"""
@param wrappedFactory: A provider of I{IProtocolFactory} whose
buildProtocol method will be called and whose resulting protocol
will be wrapped.
"""
self._wrappedFactory = wrappedFactory
- self._onConnection = defer.Deferred(canceller=self._canceller)
+ self._onConnection: defer.Deferred[IProtocol] = defer.Deferred(
+ canceller=self._canceller
+ )
def startedConnecting(self, connector):
"""
@@ -567,7 +574,14 @@ class TCP4ClientEndpoint:
TCP client endpoint with an IPv4 configuration.
"""
- def __init__(self, reactor, host, port, timeout=30, bindAddress=None):
+ def __init__(
+ self,
+ reactor: Any,
+ host: str,
+ port: int,
+ timeout: float = 30,
+ bindAddress: str | tuple[bytes | str, int] | None = None,
+ ) -> None:
"""
@param reactor: An L{IReactorTCP} provider
@@ -591,7 +605,7 @@ class TCP4ClientEndpoint:
self._timeout = timeout
self._bindAddress = bindAddress
- def connect(self, protocolFactory):
+ def connect(self, protocolFactory: IProtocolFactory) -> Deferred[IProtocol]:
"""
Implement L{IStreamClientEndpoint.connect} to connect via TCP.
"""
@@ -665,7 +679,9 @@ class TCP6ClientEndpoint:
"""
return self._deferToThread(self._getaddrinfo, host, 0, socket.AF_INET6)
- def _resolvedHostConnect(self, resolvedHost, protocolFactory):
+ def _resolvedHostConnect(
+ self, resolvedHost: str, protocolFactory: IProtocolFactory
+ ) -> Deferred[IProtocol]:
"""
Connect to the server using the resolved hostname.
"""
@@ -774,10 +790,6 @@ class HostnameEndpoint:
associated with this endpoint.
@type _hostBytes: L{bytes}
- @ivar _hostStr: the native-string representation of the hostname passed to
- the constructor, used for exception construction
- @type _hostStr: native L{str}
-
@ivar _badHostname: a flag - hopefully false! - indicating that an invalid
hostname was passed to the constructor. This might be a textual
hostname that isn't valid IDNA, or non-ASCII bytes.
@@ -789,8 +801,14 @@ class HostnameEndpoint:
_DEFAULT_ATTEMPT_DELAY = 0.3
def __init__(
- self, reactor, host, port, timeout=30, bindAddress=None, attemptDelay=None
- ):
+ self,
+ reactor: Any,
+ host: str | bytes,
+ port: int,
+ timeout: float = 30,
+ bindAddress: bytes | str | tuple[bytes | str, int] | None = None,
+ attemptDelay: float | None = None,
+ ) -> None:
"""
Create a L{HostnameEndpoint}.
@@ -799,7 +817,7 @@ class HostnameEndpoint:
L{IReactorPluggableNameResolver} or L{IReactorPluggableResolver}.
@param host: A hostname to connect to.
- @type host: L{bytes} or L{unicode}
+ @type host: L{bytes} or L{str}
@param port: The port number to connect to.
@type port: L{int}
@@ -833,9 +851,9 @@ class HostnameEndpoint:
[self._badHostname, self._hostBytes, self._hostText] = self._hostAsBytesAndText(
host
)
- self._hostStr = self._hostBytes if bytes is str else self._hostText
self._port = port
self._timeout = timeout
+
if bindAddress is not None:
if isinstance(bindAddress, (bytes, str)):
bindAddress = (bindAddress, 0)
@@ -852,21 +870,25 @@ class HostnameEndpoint:
@return: A L{str}
"""
- if self._badHostname:
- # Use the backslash-encoded version of the string passed to the
- # constructor, which is already a native string.
- host = self._hostStr
- elif isIPv6Address(self._hostStr):
- host = f"[{self._hostStr}]"
- else:
- # Convert the bytes representation to a native string to ensure
- # that we display the punycoded version of the hostname, which is
- # more useful than any IDN version as it can be easily copy-pasted
- # into debugging tools.
- host = nativeString(self._hostBytes)
- return "".join(["<HostnameEndpoint ", host, ":", str(self._port), ">"])
+ host = (
+ # It the hostname is bad, use the backslash-encoded version of the
+ # string passed to the constructor, which is already a string.
+ self._hostText
+ if self._badHostname
+ else (
+ # Add some square brackets if it's an IPv6 address.
+ f"[{self._hostText}]"
+ if isIPv6Address(self._hostText)
+ # Convert the bytes representation to a native string to ensure
+ # that we display the punycoded version of the hostname, which is
+ # more useful than any IDN version as it can be easily copy-pasted
+ # into debugging tools.
+ else self._hostBytes.decode("ascii")
+ )
+ )
+ return f"<HostnameEndpoint {host}:{self._port}>"
- def _getNameResolverAndMaybeWarn(self, reactor):
+ def _getNameResolverAndMaybeWarn(self, reactor: object) -> IHostnameResolver:
"""
Retrieve a C{nameResolver} callable and warn the caller's
caller that using a reactor which doesn't provide
@@ -894,7 +916,7 @@ class HostnameEndpoint:
return reactor.nameResolver
@staticmethod
- def _hostAsBytesAndText(host):
+ def _hostAsBytesAndText(host: bytes | str) -> tuple[bool, bytes, str]:
"""
For various reasons (documented in the C{@ivar}'s in the class
docstring) we need both a textual and a binary representation of the
@@ -906,39 +928,36 @@ class HostnameEndpoint:
this up in the future and just operate in terms of text internally.
@param host: A hostname to convert.
- @type host: L{bytes} or C{str}
@return: a 3-tuple of C{(invalid, bytes, text)} where C{invalid} is a
boolean indicating the validity of the hostname, C{bytes} is a
binary representation of C{host}, and C{text} is a textual
representation of C{host}.
"""
+ invalid = False
if isinstance(host, bytes):
- if isIPAddress(host) or isIPv6Address(host):
- return False, host, host.decode("ascii")
- else:
- try:
- return False, host, _idnaText(host)
- except UnicodeError:
- # Convert the host to _some_ kind of text, to handle below.
- host = host.decode("charmap")
+ hostBytes = host
+ try:
+ hostText = _idnaText(hostBytes)
+ except UnicodeError:
+ hostText = hostBytes.decode("charmap")
+ if not isIPv6Address(hostText):
+ invalid = True
else:
- host = normalize("NFC", host)
- if isIPAddress(host) or isIPv6Address(host):
- return False, host.encode("ascii"), host
+ hostText = normalize("NFC", host)
+ if isIPv6Address(hostText):
+ hostBytes = hostText.encode("ascii")
else:
try:
- return False, _idnaBytes(host), host
+ hostBytes = _idnaBytes(hostText)
except UnicodeError:
- pass
- # `host` has been converted to text by this point either way; it's
- # invalid as a hostname, and so may contain unprintable characters and
- # such. escape it with backslashes so the user can get _some_ guess as
- # to what went wrong.
- asciibytes = host.encode("ascii", "backslashreplace")
- return True, asciibytes, asciibytes.decode("ascii")
+ invalid = True
+ if invalid:
+ hostBytes = hostText.encode("ascii", "backslashreplace")
+ hostText = hostBytes.decode("ascii")
+ return invalid, hostBytes, hostText
- def connect(self, protocolFactory):
+ def connect(self, protocolFactory: IProtocolFactory) -> Deferred[IProtocol]:
"""
Attempts a connection to each resolved address, and returns a
connection which is established first.
@@ -952,37 +971,38 @@ class HostnameEndpoint:
or fails a connection-related error.
"""
if self._badHostname:
- return defer.fail(ValueError(f"invalid hostname: {self._hostStr}"))
+ return defer.fail(ValueError(f"invalid hostname: {self._hostText}"))
- d = Deferred()
- addresses = []
+ resolved: Deferred[list[IAddress]] = Deferred()
+ addresses: list[IAddress] = []
- @provider(IResolutionReceiver)
+ @implementer(IResolutionReceiver)
class EndpointReceiver:
@staticmethod
- def resolutionBegan(resolutionInProgress):
+ def resolutionBegan(resolutionInProgress: IHostResolution) -> None:
pass
@staticmethod
- def addressResolved(address):
+ def addressResolved(address: IAddress) -> None:
addresses.append(address)
@staticmethod
- def resolutionComplete():
- d.callback(addresses)
+ def resolutionComplete() -> None:
+ resolved.callback(addresses)
self._nameResolver.resolveHostName(
- EndpointReceiver, self._hostText, portNumber=self._port
+ EndpointReceiver(), self._hostText, portNumber=self._port
)
- d.addErrback(
+ resolved.addErrback(
lambda ignored: defer.fail(
- error.DNSLookupError(f"Couldn't find the hostname '{self._hostStr}'")
+ error.DNSLookupError(f"Couldn't find the hostname '{self._hostText}'")
)
)
- @d.addCallback
- def resolvedAddressesToEndpoints(addresses):
+ def resolvedAddressesToEndpoints(
+ addresses: Iterable[IAddress],
+ ) -> Iterable[TCP6ClientEndpoint | TCP4ClientEndpoint]:
# Yield an endpoint for every address resolved from the name.
for eachAddress in addresses:
if isinstance(eachAddress, IPv6Address):
@@ -1002,22 +1022,24 @@ class HostnameEndpoint:
self._bindAddress,
)
- d.addCallback(list)
+ iterd = resolved.addCallback(resolvedAddressesToEndpoints)
+ listd = iterd.addCallback(list)
- def _canceller(d):
+ def _canceller(cancelled: Deferred[IProtocol]) -> None:
# This canceller must remain defined outside of
# `startConnectionAttempts`, because Deferred should not
# participate in cycles with their cancellers; that would create a
# potentially problematic circular reference and possibly
# gc.garbage.
- d.errback(
+ cancelled.errback(
error.ConnectingCancelledError(
HostnameAddress(self._hostBytes, self._port)
)
)
- @d.addCallback
- def startConnectionAttempts(endpoints):
+ def startConnectionAttempts(
+ endpoints: list[TCP6ClientEndpoint | TCP4ClientEndpoint],
+ ) -> Deferred[IProtocol]:
"""
Given a sequence of endpoints obtained via name resolution, start
connecting to a new one every C{self._attemptDelay} seconds until
@@ -1037,62 +1059,68 @@ class HostnameEndpoint:
"""
if not endpoints:
raise error.DNSLookupError(
- f"no results for hostname lookup: {self._hostStr}"
+ f"no results for hostname lookup: {self._hostText}"
)
iterEndpoints = iter(endpoints)
- pending = []
- failures = []
- winner = defer.Deferred(canceller=_canceller)
+ pending: list[defer.Deferred[IProtocol]] = []
+ failures: list[Failure] = []
+ winner: defer.Deferred[IProtocol] = defer.Deferred(canceller=_canceller)
- def checkDone():
- if pending or checkDone.completed or checkDone.endpointsLeft:
+ checkDoneCompleted = False
+ checkDoneEndpointsLeft = True
+
+ def checkDone() -> None:
+ if pending or checkDoneCompleted or checkDoneEndpointsLeft:
return
winner.errback(failures.pop())
- checkDone.completed = False
- checkDone.endpointsLeft = True
-
@LoopingCall
- def iterateEndpoint():
+ def iterateEndpoint() -> None:
+ nonlocal checkDoneEndpointsLeft
endpoint = next(iterEndpoints, None)
if endpoint is None:
# The list of endpoints ends.
- checkDone.endpointsLeft = False
+ checkDoneEndpointsLeft = False
checkDone()
return
eachAttempt = endpoint.connect(protocolFactory)
pending.append(eachAttempt)
- @eachAttempt.addBoth
- def noLongerPending(result):
+ def noLongerPending(result: IProtocol | Failure) -> IProtocol | Failure:
pending.remove(eachAttempt)
return result
- @eachAttempt.addCallback
- def succeeded(result):
+ successState = eachAttempt.addBoth(noLongerPending)
+
+ def succeeded(result: IProtocol) -> None:
winner.callback(result)
- @eachAttempt.addErrback
+ successState.addCallback(succeeded)
+
def failed(reason):
failures.append(reason)
checkDone()
+ successState.addErrback(failed)
+
iterateEndpoint.clock = self._reactor
iterateEndpoint.start(self._attemptDelay)
- @winner.addBoth
- def cancelRemainingPending(result):
- checkDone.completed = True
+ def cancelRemainingPending(
+ result: IProtocol | Failure,
+ ) -> IProtocol | Failure:
+ nonlocal checkDoneCompleted
+ checkDoneCompleted = True
for remaining in pending[:]:
remaining.cancel()
if iterateEndpoint.running:
iterateEndpoint.stop()
return result
- return winner
+ return winner.addBoth(cancelRemainingPending)
- return d
+ return listd.addCallback(startConnectionAttempts)
def _fallbackNameResolution(self, host, port):
"""
@@ -2218,7 +2246,10 @@ class _WrapperServerEndpoint:
return self._wrappedEndpoint.listen(self._wrapperFactory(protocolFactory))
-def wrapClientTLS(connectionCreator, wrappedEndpoint):
+def wrapClientTLS(
+ connectionCreator: IOpenSSLClientConnectionCreator,
+ wrappedEndpoint: IStreamClientEndpoint,
+) -> _WrapperEndpoint:
"""
Wrap an endpoint which upgrades to TLS as soon as the connection is
established.
@@ -2250,17 +2281,17 @@ def wrapClientTLS(connectionCreator, wrappedEndpoint):
def _parseClientTLS(
- reactor,
- host,
- port,
- timeout=b"30",
- bindAddress=None,
- certificate=None,
- privateKey=None,
- trustRoots=None,
- endpoint=None,
- **kwargs,
-):
+ reactor: Any,
+ host: bytes | str,
+ port: bytes | str,
+ timeout: bytes | str = b"30",
+ bindAddress: bytes | str | None = None,
+ certificate: bytes | str | None = None,
+ privateKey: bytes | str | None = None,
+ trustRoots: bytes | str | None = None,
+ endpoint: bytes | str | None = None,
+ **kwargs: object,
+) -> IStreamClientEndpoint:
"""
Internal method to construct an endpoint from string parameters.
@@ -2303,18 +2334,24 @@ def _parseClientTLS(
if isinstance(bindAddress, str) or bindAddress is None
else bindAddress.decode("utf-8")
)
- port = int(port)
- timeout = int(timeout)
+ portint = int(port)
+ timeoutint = int(timeout)
return wrapClientTLS(
optionsForClientTLS(
host,
trustRoot=_parseTrustRootPath(trustRoots),
clientCertificate=_privateCertFromPaths(certificate, privateKey),
),
- clientFromString(reactor, endpoint)
- if endpoint is not None
- else HostnameEndpoint(
- reactor, _idnaBytes(host), port, timeout, (bindAddress, 0)
+ (
+ clientFromString(reactor, endpoint)
+ if endpoint is not None
+ else HostnameEndpoint(
+ reactor,
+ _idnaBytes(host),
+ portint,
+ timeoutint,
+ None if bindAddress is None else (bindAddress, 0),
+ )
),
)
diff --git a/contrib/python/Twisted/py3/twisted/internet/interfaces.py b/contrib/python/Twisted/py3/twisted/internet/interfaces.py
index 78380ccc39..28ab9bffbd 100644
--- a/contrib/python/Twisted/py3/twisted/internet/interfaces.py
+++ b/contrib/python/Twisted/py3/twisted/internet/interfaces.py
@@ -688,7 +688,10 @@ class IResolver(IResolverSimple):
class IReactorTCP(Interface):
def listenTCP(
- port: int, factory: "ServerFactory", backlog: int, interface: str
+ port: int,
+ factory: "ServerFactory",
+ backlog: int = 50,
+ interface: str = "",
) -> "IListeningPort":
"""
Connects a given protocol factory to the given numeric TCP/IP port.
@@ -712,8 +715,8 @@ class IReactorTCP(Interface):
host: str,
port: int,
factory: "ClientFactory",
- timeout: float,
- bindAddress: Optional[Tuple[str, int]],
+ timeout: float = 30.0,
+ bindAddress: Optional[Tuple[str, int]] = None,
) -> IConnector:
"""
Connect a TCP client.
@@ -784,7 +787,10 @@ class IReactorUNIX(Interface):
"""
def connectUNIX(
- address: str, factory: "ClientFactory", timeout: float, checkPID: bool
+ address: str,
+ factory: "ClientFactory",
+ timeout: float = 30,
+ checkPID: bool = False,
) -> IConnector:
"""
Connect a client protocol to a UNIX socket.
@@ -801,7 +807,11 @@ class IReactorUNIX(Interface):
"""
def listenUNIX(
- address: str, factory: "Factory", backlog: int, mode: int, wantPID: bool
+ address: str,
+ factory: "Factory",
+ backlog: int = 50,
+ mode: int = 0o666,
+ wantPID: bool = False,
) -> "IListeningPort":
"""
Listen on a UNIX socket.
@@ -923,21 +933,35 @@ class IReactorMulticast(Interface):
def listenMulticast(
port: int,
protocol: "DatagramProtocol",
- interface: str,
- maxPacketSize: int,
- listenMultiple: bool,
- ) -> "IListeningPort":
+ interface: str = "",
+ maxPacketSize: int = 8192,
+ listenMultiple: bool = False,
+ ) -> IMulticastTransport:
"""
Connects a given
L{DatagramProtocol<twisted.internet.protocol.DatagramProtocol>} to the
given numeric UDP port.
- @param listenMultiple: If set to True, allows multiple sockets to
- bind to the same address and port number at the same time.
+ @param port: The port number to bind to.
- @returns: An object which provides L{IListeningPort}.
+ @param protocol: the datagram receiver that will receive multicast
+ packets sent to the given interface and port.
+
+ @param interface: The IP address literal of the network interface to
+ bind to. By default, this will be C{"0.0.0.0"}, i.e. all IPv4
+ interfaces. Note that the format of this literal determines the
+ address family of the resulting multicast transport: passing an
+ IPv6 literal, such as C{"::"}, will result in an IPv6 multicast
+ transport.
+
+ @param maxPacketSize: The maximum packet size to accept.
+
+ @param listenMultiple: If set to True, allows multiple sockets to bind
+ to the same address and port number at the same time.
+
+ @returns: An L{IMulticastTransport} that can send multicast traffic to
+ C{interface}.
- @see: L{twisted.internet.interfaces.IMulticastTransport}
@see: U{http://twistedmatrix.com/documents/current/core/howto/udp.html}
"""
@@ -1330,10 +1354,25 @@ class IReactorCore(Interface):
"I{during shutdown} and C{False} the rest of the time."
)
- def resolve(name: str, timeout: Sequence[int]) -> "Deferred[str]":
+ def resolve(name: str, timeout: Sequence[int] = (1, 3, 11, 45)) -> "Deferred[str]":
"""
- Return a L{twisted.internet.defer.Deferred} that will resolve
- a hostname.
+ Asynchronously resolve a hostname to a single IPv4 address.
+
+ @note: Rather than calling this API directly, you probably want to use
+ L{twisted.internet.endpoints.HostnameEndpoint} to connect to a
+ hostname. If you do want to resolve a hostname without connecting
+ to it, see L{IReactorPluggableNameResolver} and
+ L{IHostnameResolver} so that you can receive multiple results and
+ IPv6 addresses.
+
+ @param name: The hostname to resolve.
+
+ @param timeout: A sequence of timeouts, meant to mirror the sequence of
+ timeouts used for each hop in recursive queries. Note that
+ different implementations of the resolver backend may not honor
+ this timeout as such, or at all; if the underlying platform API
+ supports it, implementations make a best-effort attempt to cancel
+ the underlying resolution if the sum of these timeouts elapses.
"""
def run() -> None:
@@ -1477,7 +1516,7 @@ class IReactorPluggableNameResolver(Interface):
set to a user-supplied object.
"""
- nameResolver = Attribute(
+ nameResolver: IHostnameResolver = Attribute(
"""
Read-only attribute; the resolver installed with L{installResolver}.
An L{IHostnameResolver}.
@@ -2569,21 +2608,25 @@ class IUNIXDatagramConnectedTransport(Interface):
"""
-class IMulticastTransport(Interface):
+class IMulticastTransport(IUDPTransport):
"""
Additional functionality for multicast UDP.
"""
- def getOutgoingInterface() -> str:
+ def getOutgoingInterface() -> str | int:
"""
Return interface of outgoing multicast packets.
"""
- def setOutgoingInterface(addr: str) -> None:
+ def setOutgoingInterface(addr: str | int) -> Deferred[int]:
"""
Set interface for outgoing multicast packets.
- Returns Deferred of success.
+ @note: For IPv4 multicast sockets, the address must be a hostname or IP
+ address. For IPv6 multicast sockets, the address must be an
+ interface index, as described in L{socket.if_nameindex}.
+
+ @returns: Deferred of (1: success, 0: failure).
"""
def getLoopbackMode() -> bool:
@@ -2606,7 +2649,7 @@ class IMulticastTransport(Interface):
Set time to live on multicast packets.
"""
- def joinGroup(addr: str, interface: str) -> "Deferred[None]":
+ def joinGroup(addr: str, interface: str = "") -> "Deferred[None]":
"""
Join a multicast group. Returns L{Deferred} of success or failure.
@@ -2614,7 +2657,7 @@ class IMulticastTransport(Interface):
L{error.MulticastJoinError}.
"""
- def leaveGroup(addr: str, interface: str) -> "Deferred[None]":
+ def leaveGroup(addr: str, interface: str = "") -> "Deferred[None]":
"""
Leave multicast group, return L{Deferred} of success.
"""
diff --git a/contrib/python/Twisted/py3/twisted/internet/iocpreactor/reactor.py b/contrib/python/Twisted/py3/twisted/internet/iocpreactor/reactor.py
index e9c3716219..976d1096e7 100644
--- a/contrib/python/Twisted/py3/twisted/internet/iocpreactor/reactor.py
+++ b/contrib/python/Twisted/py3/twisted/internet/iocpreactor/reactor.py
@@ -139,7 +139,9 @@ class IOCPReactor(base.ReactorBase, _ThreadedWin32EventsMixin):
def registerHandle(self, handle):
self.port.addHandle(handle, KEY_NORMAL)
- def createSocket(self, af, stype):
+ def createSocket(
+ self, af: socket.AddressFamily, stype: socket.SocketKind
+ ) -> socket.socket:
skt = socket.socket(af, stype)
self.registerHandle(skt.fileno())
return skt
diff --git a/contrib/python/Twisted/py3/twisted/internet/iocpreactor/udp.py b/contrib/python/Twisted/py3/twisted/internet/iocpreactor/udp.py
index 59c5fefb4b..744efa03e1 100644
--- a/contrib/python/Twisted/py3/twisted/internet/iocpreactor/udp.py
+++ b/contrib/python/Twisted/py3/twisted/internet/iocpreactor/udp.py
@@ -5,15 +5,18 @@
UDP support for IOCP reactor
"""
+from __future__ import annotations
+
import errno
import socket
import struct
import warnings
-from typing import Optional
+from typing import TYPE_CHECKING, Optional
from zope.interface import implementer
from twisted.internet import address, defer, error, interfaces
+from twisted.internet._multicast import MulticastMixin
from twisted.internet.abstract import isIPAddress, isIPv6Address
from twisted.internet.iocpreactor import abstract, iocpsupport as _iocp
from twisted.internet.iocpreactor.const import (
@@ -22,7 +25,11 @@ from twisted.internet.iocpreactor.const import (
ERROR_PORT_UNREACHABLE,
)
from twisted.internet.iocpreactor.interfaces import IReadWriteHandle
-from twisted.python import failure, log
+from twisted.internet.protocol import AbstractDatagramProtocol
+from twisted.python import log
+
+if TYPE_CHECKING:
+ from twisted.internet.iocpreactor.reactor import IOCPReactor
@implementer(
@@ -39,6 +46,7 @@ class Port(abstract.FileHandle):
whether this port is listening on an IPv4 address or an IPv6 address.
"""
+ reactor: IOCPReactor
addressFamily = socket.AF_INET
socketType = socket.SOCK_DGRAM
dynamicReadBuffers = False
@@ -47,7 +55,14 @@ class Port(abstract.FileHandle):
# value when we are actually listening.
_realPortNumber: Optional[int] = None
- def __init__(self, port, proto, interface="", maxPacketSize=8192, reactor=None):
+ def __init__(
+ self,
+ port: int,
+ proto: AbstractDatagramProtocol,
+ interface: str = "",
+ maxPacketSize: int = 8192,
+ reactor: IOCPReactor | None = None,
+ ) -> None:
"""
Initialize with a numeric port to listen on.
"""
@@ -102,7 +117,7 @@ class Port(abstract.FileHandle):
self._bindSocket()
self._connectToProtocol()
- def createSocket(self):
+ def createSocket(self) -> socket.socket:
return self.reactor.createSocket(self.addressFamily, self.socketType)
def _bindSocket(self):
@@ -339,68 +354,6 @@ class Port(abstract.FileHandle):
return bool(self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST))
-class MulticastMixin:
- """
- Implement multicast functionality.
- """
-
- def getOutgoingInterface(self):
- i = self.socket.getsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF)
- return socket.inet_ntoa(struct.pack("@i", i))
-
- def setOutgoingInterface(self, addr):
- """
- Returns Deferred of success.
- """
- return self.reactor.resolve(addr).addCallback(self._setInterface)
-
- def _setInterface(self, addr):
- i = socket.inet_aton(addr)
- self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, i)
- return 1
-
- def getLoopbackMode(self):
- return self.socket.getsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP)
-
- def setLoopbackMode(self, mode):
- mode = struct.pack("b", bool(mode))
- self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, mode)
-
- def getTTL(self):
- return self.socket.getsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL)
-
- def setTTL(self, ttl):
- ttl = struct.pack("B", ttl)
- self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
-
- def joinGroup(self, addr, interface=""):
- """
- Join a multicast group. Returns Deferred of success.
- """
- return self.reactor.resolve(addr).addCallback(self._joinAddr1, interface, 1)
-
- def _joinAddr1(self, addr, interface, join):
- return self.reactor.resolve(interface).addCallback(self._joinAddr2, addr, join)
-
- def _joinAddr2(self, interface, addr, join):
- addr = socket.inet_aton(addr)
- interface = socket.inet_aton(interface)
- if join:
- cmd = socket.IP_ADD_MEMBERSHIP
- else:
- cmd = socket.IP_DROP_MEMBERSHIP
- try:
- self.socket.setsockopt(socket.IPPROTO_IP, cmd, addr + interface)
- except OSError as e:
- return failure.Failure(error.MulticastJoinError(addr, interface, *e.args))
-
- def leaveGroup(self, addr, interface=""):
- """
- Leave multicast group, return Deferred of success.
- """
- return self.reactor.resolve(addr).addCallback(self._joinAddr1, interface, 0)
-
-
@implementer(interfaces.IMulticastTransport)
class MulticastPort(MulticastMixin, Port):
"""
@@ -409,17 +362,17 @@ class MulticastPort(MulticastMixin, Port):
def __init__(
self,
- port,
- proto,
- interface="",
- maxPacketSize=8192,
- reactor=None,
- listenMultiple=False,
- ):
+ port: int,
+ proto: AbstractDatagramProtocol,
+ interface: str = "",
+ maxPacketSize: int = 8192,
+ reactor: IOCPReactor | None = None,
+ listenMultiple: bool = False,
+ ) -> None:
Port.__init__(self, port, proto, interface, maxPacketSize, reactor)
self.listenMultiple = listenMultiple
- def createSocket(self):
+ def createSocket(self) -> socket.socket:
skt = Port.createSocket(self)
if self.listenMultiple:
skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
diff --git a/contrib/python/Twisted/py3/twisted/internet/posixbase.py b/contrib/python/Twisted/py3/twisted/internet/posixbase.py
index 3be65752a2..d9fa8a9a55 100644
--- a/contrib/python/Twisted/py3/twisted/internet/posixbase.py
+++ b/contrib/python/Twisted/py3/twisted/internet/posixbase.py
@@ -6,6 +6,7 @@
Posix reactor base class
"""
+from __future__ import annotations
import socket
import sys
@@ -16,6 +17,7 @@ from zope.interface import classImplements, implementer
from twisted.internet import error, tcp, udp
from twisted.internet.base import ReactorBase
from twisted.internet.interfaces import (
+ IConnector,
IHalfCloseableDescriptor,
IReactorFDSet,
IReactorMulticast,
@@ -28,6 +30,7 @@ from twisted.internet.interfaces import (
IReactorUNIXDatagram,
)
from twisted.internet.main import CONNECTION_DONE, CONNECTION_LOST
+from twisted.internet.protocol import ClientFactory
from twisted.python import failure, log
from twisted.python.runtime import platform, platformType
from ._signals import (
@@ -363,7 +366,14 @@ class PosixReactorBase(_DisconnectSelectableMixin, ReactorBase):
p.startListening()
return p
- def connectTCP(self, host, port, factory, timeout=30, bindAddress=None):
+ def connectTCP(
+ self,
+ host: str,
+ port: int,
+ factory: "ClientFactory",
+ timeout: float = 30.0,
+ bindAddress: tuple[str, int] | None = None,
+ ) -> IConnector:
c = tcp.Connector(host, port, factory, timeout, bindAddress, self)
c.connect()
return c
diff --git a/contrib/python/Twisted/py3/twisted/internet/protocol.py b/contrib/python/Twisted/py3/twisted/internet/protocol.py
index 4fcf0e1038..bd1e647302 100644
--- a/contrib/python/Twisted/py3/twisted/internet/protocol.py
+++ b/contrib/python/Twisted/py3/twisted/internet/protocol.py
@@ -8,7 +8,7 @@ Standard implementations of Twisted protocol-related interfaces.
Start here if you are looking to write a new protocol implementation for
Twisted. The Protocol class contains some introductory material.
"""
-
+from __future__ import annotations
import random
from typing import Any, Callable, Optional
@@ -16,7 +16,12 @@ from typing import Any, Callable, Optional
from zope.interface import implementer
from twisted.internet import defer, error, interfaces
-from twisted.internet.interfaces import IAddress, ITransport
+from twisted.internet.interfaces import (
+ IAddress,
+ IMulticastTransport,
+ ITransport,
+ IUDPTransport,
+)
from twisted.logger import _loggerFor
from twisted.python import components, failure, log
@@ -686,7 +691,7 @@ class AbstractDatagramProtocol:
UDP.
"""
- transport = None
+ transport: IUDPTransport | IMulticastTransport | None = None
numPorts = 0
noisy = True
@@ -735,7 +740,7 @@ class AbstractDatagramProtocol:
Will only be called once, after all ports are disconnected.
"""
- def makeConnection(self, transport):
+ def makeConnection(self, transport: IUDPTransport) -> None:
"""
Make a connection to a transport and a server.
diff --git a/contrib/python/Twisted/py3/twisted/internet/tcp.py b/contrib/python/Twisted/py3/twisted/internet/tcp.py
index 018d1912d2..7bc4d1eaac 100644
--- a/contrib/python/Twisted/py3/twisted/internet/tcp.py
+++ b/contrib/python/Twisted/py3/twisted/internet/tcp.py
@@ -14,7 +14,7 @@ import os
import socket
import struct
import sys
-from typing import Callable, ClassVar, List, Optional, Union
+from typing import Any, Callable, ClassVar, List, Optional, Union
from zope.interface import Interface, implementer
@@ -29,9 +29,9 @@ from twisted.internet.interfaces import (
ISystemHandle,
ITCPTransport,
)
+from twisted.internet.protocol import ClientFactory
from twisted.logger import ILogObserver, LogEvent, Logger
from twisted.python import deprecate, versions
-from twisted.python.compat import lazyByteSlice
from twisted.python.runtime import platformType
try:
@@ -275,7 +275,7 @@ class Connection(
"""
# Limit length of buffer to try to send, because some OSes are too
# stupid to do so themselves (ahem windows)
- limitedData = lazyByteSlice(data, 0, self.SEND_LIMIT)
+ limitedData = memoryview(data)[: self.SEND_LIMIT]
try:
return untilConcludes(self.socket.send, limitedData)
@@ -337,7 +337,18 @@ class Connection(
return bool(self.socket.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY))
def setTcpNoDelay(self, enabled):
- self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, enabled)
+ try:
+ # There are bug reports about failures when setting TCP_NODELAY under certain conditions
+ # on macOS: https://github.com/thespianpy/Thespian/issues/70,
+ # https://github.com/envoyproxy/envoy/issues/1446.
+ #
+ # It is reasonable to simply eat errors coming from setting TCP_NODELAY because
+ # TCP_NODELAY is relatively small performance optimization. In almost all cases the
+ # caller will not be able to do anything to remedy the situation and will simply
+ # continue.
+ self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, enabled)
+ except OSError as e: # pragma: no cover
+ log.err(e, "got error when setting TCP_NODELAY on TCP socket")
def getTcpKeepAlive(self):
return bool(self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE))
@@ -1506,9 +1517,17 @@ class Connector(base.BaseConnector):
@type _addressType: C{type}
"""
- _addressType = address.IPv4Address
+ _addressType: type[address.IPv4Address | address.IPv6Address] = address.IPv4Address
- def __init__(self, host, port, factory, timeout, bindAddress, reactor=None):
+ def __init__(
+ self,
+ host: str,
+ port: int | str,
+ factory: ClientFactory,
+ timeout: float,
+ bindAddress: str | tuple[str, int] | None,
+ reactor: Any = None,
+ ) -> None:
if isinstance(port, str):
try:
port = socket.getservbyname(port, "tcp")
@@ -1520,7 +1539,7 @@ class Connector(base.BaseConnector):
self.bindAddress = bindAddress
base.BaseConnector.__init__(self, factory, timeout, reactor)
- def _makeTransport(self):
+ def _makeTransport(self) -> Client:
"""
Create a L{Client} bound to this L{Connector}.
diff --git a/contrib/python/Twisted/py3/twisted/internet/udp.py b/contrib/python/Twisted/py3/twisted/internet/udp.py
index 7601f2dc84..6ef67f323c 100644
--- a/contrib/python/Twisted/py3/twisted/internet/udp.py
+++ b/contrib/python/Twisted/py3/twisted/internet/udp.py
@@ -14,16 +14,18 @@ Please do not use this module directly.
@var _sockErrReadRefuse: list of symbolic error constants (from the C{errno}
module) representing socket errors that indicate connection refused.
"""
-
+from __future__ import annotations
# System Imports
import socket
-import struct
import warnings
from typing import Optional
from zope.interface import implementer
+from twisted.internet._multicast import MulticastMixin
+from twisted.internet.interfaces import IReactorMulticast
+from twisted.internet.protocol import AbstractDatagramProtocol
from twisted.python.runtime import platformType
if platformType == "win32":
@@ -56,7 +58,7 @@ else:
# Twisted Imports
from twisted.internet import abstract, address, base, defer, error, interfaces
-from twisted.python import failure, log
+from twisted.python import log
@implementer(
@@ -81,8 +83,8 @@ class Port(base.BasePort):
L{Port}).
"""
- addressFamily = socket.AF_INET
- socketType = socket.SOCK_DGRAM
+ addressFamily: socket.AddressFamily = socket.AF_INET
+ socketType: socket.SocketKind = socket.SOCK_DGRAM
maxThroughput = 256 * 1024
_realPortNumber: Optional[int] = None
@@ -440,62 +442,6 @@ class Port(base.BasePort):
return bool(self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST))
-class MulticastMixin:
- """
- Implement multicast functionality.
- """
-
- def getOutgoingInterface(self):
- i = self.socket.getsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF)
- return socket.inet_ntoa(struct.pack("@i", i))
-
- def setOutgoingInterface(self, addr):
- """Returns Deferred of success."""
- return self.reactor.resolve(addr).addCallback(self._setInterface)
-
- def _setInterface(self, addr):
- i = socket.inet_aton(addr)
- self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, i)
- return 1
-
- def getLoopbackMode(self):
- return self.socket.getsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP)
-
- def setLoopbackMode(self, mode):
- mode = struct.pack("b", bool(mode))
- self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, mode)
-
- def getTTL(self):
- return self.socket.getsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL)
-
- def setTTL(self, ttl):
- ttl = struct.pack("B", ttl)
- self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
-
- def joinGroup(self, addr, interface=""):
- """Join a multicast group. Returns Deferred of success."""
- return self.reactor.resolve(addr).addCallback(self._joinAddr1, interface, 1)
-
- def _joinAddr1(self, addr, interface, join):
- return self.reactor.resolve(interface).addCallback(self._joinAddr2, addr, join)
-
- def _joinAddr2(self, interface, addr, join):
- addr = socket.inet_aton(addr)
- interface = socket.inet_aton(interface)
- if join:
- cmd = socket.IP_ADD_MEMBERSHIP
- else:
- cmd = socket.IP_DROP_MEMBERSHIP
- try:
- self.socket.setsockopt(socket.IPPROTO_IP, cmd, addr + interface)
- except OSError as e:
- return failure.Failure(error.MulticastJoinError(addr, interface, *e.args))
-
- def leaveGroup(self, addr, interface=""):
- """Leave multicast group, return Deferred of success."""
- return self.reactor.resolve(addr).addCallback(self._joinAddr1, interface, 0)
-
-
@implementer(interfaces.IMulticastTransport)
class MulticastPort(MulticastMixin, Port):
"""
@@ -504,20 +450,24 @@ class MulticastPort(MulticastMixin, Port):
def __init__(
self,
- port,
- proto,
- interface="",
- maxPacketSize=8192,
- reactor=None,
- listenMultiple=False,
- ):
+ port: int,
+ proto: AbstractDatagramProtocol,
+ interface: str = "",
+ maxPacketSize: int = 8192,
+ reactor: IReactorMulticast | None = None,
+ listenMultiple: bool = False,
+ ) -> None:
"""
@see: L{twisted.internet.interfaces.IReactorMulticast.listenMulticast}
"""
Port.__init__(self, port, proto, interface, maxPacketSize, reactor)
self.listenMultiple = listenMultiple
- def createInternetSocket(self):
+ def createInternetSocket(self) -> socket.socket:
+ """
+ Override L{Port.createInternetSocket} to configure the socket to honor
+ the C{listenMultiple} argument to L{IReactorMulticast.listenMultiple}.
+ """
skt = Port.createInternetSocket(self)
if self.listenMultiple:
skt.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
diff --git a/contrib/python/Twisted/py3/twisted/internet/unix.py b/contrib/python/Twisted/py3/twisted/internet/unix.py
index c3fe62b22d..b33ef29974 100644
--- a/contrib/python/Twisted/py3/twisted/internet/unix.py
+++ b/contrib/python/Twisted/py3/twisted/internet/unix.py
@@ -294,6 +294,21 @@ class Server(_SendmsgMixin, tcp.Server):
def getPeer(self):
return address.UNIXAddress(self.hostname or None)
+ def getTcpNoDelay(self):
+ """
+ FIXME:https://github.com/twisted/twisted/issues/12369
+
+ L{twisted.internet.unix.Server} inherits from L{twisted.internet.tcp.Server} which has
+ this method implemented for TCP. For Unix socket, this is just a NOOP to avoid
+ errors for the code that calls TCP specicific methods thinking that the Unix transport
+ is a TCP transport.
+ """
+ return False
+
+ def setTcpNoDelay(self, enabled):
+ # This is not supported on UNIX sockets and therefore silently ignored.
+ pass
+
def _inFilesystemNamespace(path):
"""
@@ -467,6 +482,21 @@ class Client(_SendmsgMixin, tcp.BaseClient):
def getHost(self):
return address.UNIXAddress(None)
+ def getTcpNoDelay(self):
+ """
+ FIXME:https://github.com/twisted/twisted/issues/12369
+
+ L{twisted.internet.unix.Client} inherits from L{twisted.internet.tcp.Client} which has
+ this method implemented for TCP. For Unix socket, this is just a NOOP to avoid
+ errors for the code that calls TCP specicific methods thinking that the Unix transport
+ is a TCP transport.
+ """
+ return False
+
+ def setTcpNoDelay(self, enabled):
+ # This is not supported on UNIX sockets and therefore silently ignored.
+ pass
+
class Connector(base.BaseConnector):
def __init__(self, address, factory, timeout, reactor, checkPID):
diff --git a/contrib/python/Twisted/py3/twisted/mail/imap4.py b/contrib/python/Twisted/py3/twisted/mail/imap4.py
index 9a9f140795..f38d094f89 100644
--- a/contrib/python/Twisted/py3/twisted/mail/imap4.py
+++ b/contrib/python/Twisted/py3/twisted/mail/imap4.py
@@ -28,7 +28,7 @@ import uuid
from base64 import decodebytes, encodebytes
from io import BytesIO
from itertools import chain
-from typing import Any, List, cast
+from typing import Any, List, Optional, cast
from zope.interface import implementer
@@ -2205,7 +2205,7 @@ class IMAP4Server(basic.LineReceiver, policies.TimeoutMixin):
hdrs = _formatHeaders(msg.getHeaders(True))
_w(part.__bytes__() + b" " + _literal(hdrs))
elif part.empty:
- _w(part.__bytes__() + b" ")
+ _w(part.getBytes(length=msg.getSize()) + b" ")
_f()
if part.part:
return FileProducer(msg.getBodyFile()).beginProducing(self.transport)
@@ -5691,7 +5691,14 @@ class _FetchParser:
def __str__(self) -> str:
return self.__bytes__().decode("ascii")
- def __bytes__(self) -> bytes:
+ def getBytes(self, length: Optional[int] = None) -> bytes:
+ """
+ Prepare the initial command response for a Fetch BODY request.
+ Interpret the Fetch request from the client and return the
+ appropriate response based on RFC 3501.
+ This is not the body itself of the response, merely the section
+ of the first response line that describes the body part.
+ """
base = b"BODY"
part = b""
separator = b""
@@ -5711,9 +5718,19 @@ class _FetchParser:
elif self.empty:
base += b"[" + part + b"]"
if self.partialBegin is not None:
- base += b"<%d.%d>" % (self.partialBegin, self.partialLength) # type: ignore[unreachable]
+ if length is None or length > self.partialLength: # type: ignore[unreachable]
+ base += b"<%d.%d>" % (self.partialBegin, self.partialLength)
+ else:
+ # IMAP4rev1 says that if the partial length is greater than
+ # the length of the data, the server should send the entire
+ # data., with a "0" as the partial length
+ # https://datatracker.ietf.org/doc/html/rfc3501#section-6.4.5
+ base += b"<0>"
return base
+ def __bytes__(self) -> bytes:
+ return self.getBytes()
+
class BodyStructure:
type = "bodystructure"
__str__ = lambda self: "bodystructure"
diff --git a/contrib/python/Twisted/py3/twisted/python/__init__.py b/contrib/python/Twisted/py3/twisted/python/__init__.py
index 3dc5524f01..722430edb2 100644
--- a/contrib/python/Twisted/py3/twisted/python/__init__.py
+++ b/contrib/python/Twisted/py3/twisted/python/__init__.py
@@ -7,19 +7,9 @@ Twisted Python: Utilities and Enhancements for Python.
from .deprecate import deprecatedModuleAttribute
-
-# Deprecating twisted.python.constants.
from .versions import Version
deprecatedModuleAttribute(
- Version("Twisted", 16, 5, 0),
- "Please use constantly from PyPI instead.",
- "twisted.python",
- "constants",
-)
-
-
-deprecatedModuleAttribute(
Version("Twisted", 17, 5, 0),
"Please use hyperlink from PyPI instead.",
"twisted.python",
diff --git a/contrib/python/Twisted/py3/twisted/python/compat.py b/contrib/python/Twisted/py3/twisted/python/compat.py
index fc1e5752f3..672d9ee0b7 100644
--- a/contrib/python/Twisted/py3/twisted/python/compat.py
+++ b/contrib/python/Twisted/py3/twisted/python/compat.py
@@ -420,16 +420,16 @@ def intToBytes(i: int) -> bytes:
def lazyByteSlice(object, offset=0, size=None):
"""
- Return a copy of the given bytes-like object.
+ Return a memory view of the given bytes-like object.
- If an offset is given, the copy starts at that offset. If a size is
- given, the copy will only be of that length.
+ If an offset is given, the view starts at that offset. If a size is
+ given, the view will only be of that length.
- @param object: C{bytes} to be copied.
+ @param object: C{bytes} to be sliced.
- @param offset: C{int}, starting index of copy.
+ @param offset: C{int}, starting index of view.
- @param size: Optional, if an C{int} is given limit the length of copy
+ @param size: Optional, if an C{int} is given limit the length of the view
to this size.
"""
view = memoryview(object)
diff --git a/contrib/python/Twisted/py3/twisted/python/constants.py b/contrib/python/Twisted/py3/twisted/python/constants.py
deleted file mode 100644
index df970363c6..0000000000
--- a/contrib/python/Twisted/py3/twisted/python/constants.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- test-case-name: twisted.python.test.test_constants -*-
-# Copyright (c) Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Symbolic constant support, including collections and constants with text,
-numeric, and bit flag values.
-"""
-
-
-# Import and re-export Constantly
-from constantly import FlagConstant, Flags, NamedConstant, Names, ValueConstant, Values
-
-__all__ = ["NamedConstant", "ValueConstant", "FlagConstant", "Names", "Values", "Flags"]
diff --git a/contrib/python/Twisted/py3/twisted/words/xish/xpathparser.g b/contrib/python/Twisted/py3/twisted/words/xish/xpathparser.g
index 4c78352381..cddf0d4045 100644
--- a/contrib/python/Twisted/py3/twisted/words/xish/xpathparser.g
+++ b/contrib/python/Twisted/py3/twisted/words/xish/xpathparser.g
@@ -41,7 +41,6 @@ produced by Yapps, and a context class that keeps track of the parse stack.
These have been copied from the Yapps runtime module.
"""
-from __future__ import print_function
import sys, re
MIN_WINDOW=4096
diff --git a/contrib/python/Twisted/py3/twisted/words/xish/xpathparser.py b/contrib/python/Twisted/py3/twisted/words/xish/xpathparser.py
index 8df0d54369..182d900fb9 100644
--- a/contrib/python/Twisted/py3/twisted/words/xish/xpathparser.py
+++ b/contrib/python/Twisted/py3/twisted/words/xish/xpathparser.py
@@ -43,7 +43,6 @@ These have been copied from the Yapps runtime module.
exec(
r'''
-from __future__ import print_function
import sys, re
MIN_WINDOW=4096
diff --git a/contrib/python/Twisted/py3/ya.make b/contrib/python/Twisted/py3/ya.make
index 0ad4221796..93a5caf110 100644
--- a/contrib/python/Twisted/py3/ya.make
+++ b/contrib/python/Twisted/py3/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(24.10.0)
+VERSION(24.11.0)
LICENSE(MIT)
@@ -120,6 +120,7 @@ PY_SRCS(
twisted/internet/_dumbwin32proc.py
twisted/internet/_glibbase.py
twisted/internet/_idna.py
+ twisted/internet/_multicast.py
twisted/internet/_newtls.py
twisted/internet/_pollingfile.py
twisted/internet/_posixserialport.py
@@ -308,7 +309,6 @@ PY_SRCS(
twisted/python/_url.py
twisted/python/compat.py
twisted/python/components.py
- twisted/python/constants.py
twisted/python/context.py
twisted/python/deprecate.py
twisted/python/failure.py
diff --git a/contrib/python/clickhouse-connect/.dist-info/METADATA b/contrib/python/clickhouse-connect/.dist-info/METADATA
index 3d5428f0c5..774b5caa2e 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.8.8
+Version: 0.8.9
Summary: ClickHouse Database Core Driver for Python, Pandas, and Superset
Home-page: https://github.com/ClickHouse/clickhouse-connect
Author: ClickHouse Inc.
diff --git a/contrib/python/clickhouse-connect/clickhouse_connect/__version__.py b/contrib/python/clickhouse-connect/clickhouse_connect/__version__.py
index 0c10f92064..eed7e58e36 100644
--- a/contrib/python/clickhouse-connect/clickhouse_connect/__version__.py
+++ b/contrib/python/clickhouse-connect/clickhouse_connect/__version__.py
@@ -1 +1 @@
-version = '0.8.8'
+version = '0.8.9'
diff --git a/contrib/python/clickhouse-connect/clickhouse_connect/datatypes/temporal.py b/contrib/python/clickhouse-connect/clickhouse_connect/datatypes/temporal.py
index 49899fb7c1..39bf0c070d 100644
--- a/contrib/python/clickhouse-connect/clickhouse_connect/datatypes/temporal.py
+++ b/contrib/python/clickhouse-connect/clickhouse_connect/datatypes/temporal.py
@@ -79,9 +79,6 @@ class Date32(Date):
return data_conv.read_date32_col(source, num_rows)
-from_ts_tz = datetime.fromtimestamp
-
-
class DateTimeBase(ClickHouseType, registered=False):
__slots__ = ('tzinfo',)
valid_formats = 'native', 'int'
@@ -192,7 +189,7 @@ class DateTime64(DateTimeBase):
def _read_binary_naive(self, column: Sequence):
new_col = []
app = new_col.append
- dt_from = datetime.fromtimestamp
+ dt_from = datetime.utcfromtimestamp
prec = self.prec
for ticks in column:
seconds = ticks // prec
diff --git a/contrib/python/clickhouse-connect/clickhouse_connect/driver/dataconv.py b/contrib/python/clickhouse-connect/clickhouse_connect/driver/dataconv.py
index fc2720128d..5acc49830e 100644
--- a/contrib/python/clickhouse-connect/clickhouse_connect/driver/dataconv.py
+++ b/contrib/python/clickhouse-connect/clickhouse_connect/driver/dataconv.py
@@ -28,6 +28,9 @@ def read_ipv4_col(source: ByteSource, num_rows: int):
def read_datetime_col(source: ByteSource, num_rows: int, tz_info: Optional[tzinfo]):
src_array = source.read_array('I', num_rows)
+ if tz_info is None:
+ fts = datetime.utcfromtimestamp
+ return [fts(ts) for ts in src_array]
fts = datetime.fromtimestamp
return [fts(ts, tz_info) for ts in src_array]
diff --git a/contrib/python/clickhouse-connect/clickhouse_connect/tools/datagen.py b/contrib/python/clickhouse-connect/clickhouse_connect/tools/datagen.py
index 755f3df98e..490d852916 100644
--- a/contrib/python/clickhouse-connect/clickhouse_connect/tools/datagen.py
+++ b/contrib/python/clickhouse-connect/clickhouse_connect/tools/datagen.py
@@ -18,7 +18,8 @@ from clickhouse_connect.datatypes.string import String, FixedString
from clickhouse_connect.datatypes.temporal import Date, Date32, DateTime, DateTime64
from clickhouse_connect.driver.common import array_sizes
-dt_from_ts = datetime.fromtimestamp
+dt_from_ts = datetime.utcfromtimestamp
+dt_from_ts_tz = datetime.fromtimestamp
epoch_date = date(1970, 1, 1)
date32_start_date = date(1925, 1, 1)
@@ -137,7 +138,7 @@ def random_datetime():
def random_datetime_tz(timezone: tzinfo):
- return dt_from_ts(int(random() * 2 ** 32), timezone).replace(microsecond=0)
+ return dt_from_ts_tz(int(random() * 2 ** 32), timezone).replace(microsecond=0)
def random_ascii_str(max_len: int = 200, min_len: int = 0):
@@ -171,7 +172,7 @@ def random_datetime64_tz(prec: int, timezone: tzinfo):
u_sec = int(random() * 1000) * 1000
else:
u_sec = int(random() * 1000000)
- return dt_from_ts(int(random() * 4294967296), timezone).replace(microsecond=u_sec)
+ return dt_from_ts_tz(int(random() * 4294967296), timezone).replace(microsecond=u_sec)
def random_ipv6():
diff --git a/contrib/python/clickhouse-connect/ya.make b/contrib/python/clickhouse-connect/ya.make
index ab287865bd..f2bef2bd2a 100644
--- a/contrib/python/clickhouse-connect/ya.make
+++ b/contrib/python/clickhouse-connect/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(0.8.8)
+VERSION(0.8.9)
LICENSE(Apache-2.0)