Загрузить файлы в «venv/Lib/site-packages/anyio/abc»
This commit is contained in:
58
venv/Lib/site-packages/anyio/abc/__init__.py
Normal file
58
venv/Lib/site-packages/anyio/abc/__init__.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from ._eventloop import AsyncBackend as AsyncBackend
|
||||||
|
from ._resources import AsyncResource as AsyncResource
|
||||||
|
from ._sockets import ConnectedUDPSocket as ConnectedUDPSocket
|
||||||
|
from ._sockets import ConnectedUNIXDatagramSocket as ConnectedUNIXDatagramSocket
|
||||||
|
from ._sockets import IPAddressType as IPAddressType
|
||||||
|
from ._sockets import IPSockAddrType as IPSockAddrType
|
||||||
|
from ._sockets import SocketAttribute as SocketAttribute
|
||||||
|
from ._sockets import SocketListener as SocketListener
|
||||||
|
from ._sockets import SocketStream as SocketStream
|
||||||
|
from ._sockets import UDPPacketType as UDPPacketType
|
||||||
|
from ._sockets import UDPSocket as UDPSocket
|
||||||
|
from ._sockets import UNIXDatagramPacketType as UNIXDatagramPacketType
|
||||||
|
from ._sockets import UNIXDatagramSocket as UNIXDatagramSocket
|
||||||
|
from ._sockets import UNIXSocketStream as UNIXSocketStream
|
||||||
|
from ._streams import AnyByteReceiveStream as AnyByteReceiveStream
|
||||||
|
from ._streams import AnyByteSendStream as AnyByteSendStream
|
||||||
|
from ._streams import AnyByteStream as AnyByteStream
|
||||||
|
from ._streams import AnyByteStreamConnectable as AnyByteStreamConnectable
|
||||||
|
from ._streams import AnyUnreliableByteReceiveStream as AnyUnreliableByteReceiveStream
|
||||||
|
from ._streams import AnyUnreliableByteSendStream as AnyUnreliableByteSendStream
|
||||||
|
from ._streams import AnyUnreliableByteStream as AnyUnreliableByteStream
|
||||||
|
from ._streams import ByteReceiveStream as ByteReceiveStream
|
||||||
|
from ._streams import ByteSendStream as ByteSendStream
|
||||||
|
from ._streams import ByteStream as ByteStream
|
||||||
|
from ._streams import ByteStreamConnectable as ByteStreamConnectable
|
||||||
|
from ._streams import Listener as Listener
|
||||||
|
from ._streams import ObjectReceiveStream as ObjectReceiveStream
|
||||||
|
from ._streams import ObjectSendStream as ObjectSendStream
|
||||||
|
from ._streams import ObjectStream as ObjectStream
|
||||||
|
from ._streams import ObjectStreamConnectable as ObjectStreamConnectable
|
||||||
|
from ._streams import UnreliableObjectReceiveStream as UnreliableObjectReceiveStream
|
||||||
|
from ._streams import UnreliableObjectSendStream as UnreliableObjectSendStream
|
||||||
|
from ._streams import UnreliableObjectStream as UnreliableObjectStream
|
||||||
|
from ._subprocesses import Process as Process
|
||||||
|
from ._tasks import TaskGroup as TaskGroup
|
||||||
|
from ._tasks import TaskStatus as TaskStatus
|
||||||
|
from ._testing import TestRunner as TestRunner
|
||||||
|
|
||||||
|
# Re-exported here, for backwards compatibility
|
||||||
|
# isort: off
|
||||||
|
from .._core._synchronization import (
|
||||||
|
CapacityLimiter as CapacityLimiter,
|
||||||
|
Condition as Condition,
|
||||||
|
Event as Event,
|
||||||
|
Lock as Lock,
|
||||||
|
Semaphore as Semaphore,
|
||||||
|
)
|
||||||
|
from .._core._tasks import CancelScope as CancelScope
|
||||||
|
from ..from_thread import BlockingPortal as BlockingPortal
|
||||||
|
|
||||||
|
# Re-export imports so they look like they live directly in this package
|
||||||
|
for __value in list(locals().values()):
|
||||||
|
if getattr(__value, "__module__", "").startswith("anyio.abc."):
|
||||||
|
__value.__module__ = __name__
|
||||||
|
|
||||||
|
del __value
|
||||||
410
venv/Lib/site-packages/anyio/abc/_eventloop.py
Normal file
410
venv/Lib/site-packages/anyio/abc/_eventloop.py
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
from collections.abc import AsyncIterator, Awaitable, Callable, Coroutine, Sequence
|
||||||
|
from contextlib import AbstractContextManager
|
||||||
|
from os import PathLike
|
||||||
|
from signal import Signals
|
||||||
|
from socket import AddressFamily, SocketKind, socket
|
||||||
|
from typing import (
|
||||||
|
IO,
|
||||||
|
TYPE_CHECKING,
|
||||||
|
Any,
|
||||||
|
TypeAlias,
|
||||||
|
TypeVar,
|
||||||
|
overload,
|
||||||
|
)
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 11):
|
||||||
|
from typing import TypeVarTuple, Unpack
|
||||||
|
else:
|
||||||
|
from typing_extensions import TypeVarTuple, Unpack
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from _typeshed import FileDescriptorLike
|
||||||
|
|
||||||
|
from .._core._synchronization import CapacityLimiter, Event, Lock, Semaphore
|
||||||
|
from .._core._tasks import CancelScope
|
||||||
|
from .._core._testing import TaskInfo
|
||||||
|
from ._sockets import (
|
||||||
|
ConnectedUDPSocket,
|
||||||
|
ConnectedUNIXDatagramSocket,
|
||||||
|
IPSockAddrType,
|
||||||
|
SocketListener,
|
||||||
|
SocketStream,
|
||||||
|
UDPSocket,
|
||||||
|
UNIXDatagramSocket,
|
||||||
|
UNIXSocketStream,
|
||||||
|
)
|
||||||
|
from ._subprocesses import Process
|
||||||
|
from ._tasks import TaskGroup
|
||||||
|
from ._testing import TestRunner
|
||||||
|
|
||||||
|
T_Retval = TypeVar("T_Retval")
|
||||||
|
T_co = TypeVar("T_co", covariant=True)
|
||||||
|
PosArgsT = TypeVarTuple("PosArgsT")
|
||||||
|
StrOrBytesPath: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes]
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncBackend(metaclass=ABCMeta):
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def run(
|
||||||
|
cls,
|
||||||
|
func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]],
|
||||||
|
args: tuple[Unpack[PosArgsT]],
|
||||||
|
kwargs: dict[str, Any],
|
||||||
|
options: dict[str, Any],
|
||||||
|
) -> T_Retval:
|
||||||
|
"""
|
||||||
|
Run the given coroutine function in an asynchronous event loop.
|
||||||
|
|
||||||
|
The current thread must not be already running an event loop.
|
||||||
|
|
||||||
|
:param func: a coroutine function
|
||||||
|
:param args: positional arguments to ``func``
|
||||||
|
:param kwargs: positional arguments to ``func``
|
||||||
|
:param options: keyword arguments to call the backend ``run()`` implementation
|
||||||
|
with
|
||||||
|
:return: the return value of the coroutine function
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def current_token(cls) -> object:
|
||||||
|
"""
|
||||||
|
Return an object that allows other threads to run code inside the event loop.
|
||||||
|
|
||||||
|
:return: a token object, specific to the event loop running in the current
|
||||||
|
thread
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def current_time(cls) -> float:
|
||||||
|
"""
|
||||||
|
Return the current value of the event loop's internal clock.
|
||||||
|
|
||||||
|
:return: the clock value (seconds)
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def cancelled_exception_class(cls) -> type[BaseException]:
|
||||||
|
"""Return the exception class that is raised in a task if it's cancelled."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def checkpoint(cls) -> None:
|
||||||
|
"""
|
||||||
|
Check if the task has been cancelled, and allow rescheduling of other tasks.
|
||||||
|
|
||||||
|
This is effectively the same as running :meth:`checkpoint_if_cancelled` and then
|
||||||
|
:meth:`cancel_shielded_checkpoint`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def checkpoint_if_cancelled(cls) -> None:
|
||||||
|
"""
|
||||||
|
Check if the current task group has been cancelled.
|
||||||
|
|
||||||
|
This will check if the task has been cancelled, but will not allow other tasks
|
||||||
|
to be scheduled if not.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if cls.current_effective_deadline() == -math.inf:
|
||||||
|
await cls.checkpoint()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def cancel_shielded_checkpoint(cls) -> None:
|
||||||
|
"""
|
||||||
|
Allow the rescheduling of other tasks.
|
||||||
|
|
||||||
|
This will give other tasks the opportunity to run, but without checking if the
|
||||||
|
current task group has been cancelled, unlike with :meth:`checkpoint`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
with cls.create_cancel_scope(shield=True):
|
||||||
|
await cls.sleep(0)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def sleep(cls, delay: float) -> None:
|
||||||
|
"""
|
||||||
|
Pause the current task for the specified duration.
|
||||||
|
|
||||||
|
:param delay: the duration, in seconds
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_cancel_scope(
|
||||||
|
cls, *, deadline: float = math.inf, shield: bool = False
|
||||||
|
) -> CancelScope:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def current_effective_deadline(cls) -> float:
|
||||||
|
"""
|
||||||
|
Return the nearest deadline among all the cancel scopes effective for the
|
||||||
|
current task.
|
||||||
|
|
||||||
|
:return:
|
||||||
|
- a clock value from the event loop's internal clock
|
||||||
|
- ``inf`` if there is no deadline in effect
|
||||||
|
- ``-inf`` if the current scope has been cancelled
|
||||||
|
:rtype: float
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_task_group(cls) -> TaskGroup:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_event(cls) -> Event:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_lock(cls, *, fast_acquire: bool) -> Lock:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_semaphore(
|
||||||
|
cls,
|
||||||
|
initial_value: int,
|
||||||
|
*,
|
||||||
|
max_value: int | None = None,
|
||||||
|
fast_acquire: bool = False,
|
||||||
|
) -> Semaphore:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def run_sync_in_worker_thread(
|
||||||
|
cls,
|
||||||
|
func: Callable[[Unpack[PosArgsT]], T_Retval],
|
||||||
|
args: tuple[Unpack[PosArgsT]],
|
||||||
|
abandon_on_cancel: bool = False,
|
||||||
|
limiter: CapacityLimiter | None = None,
|
||||||
|
) -> T_Retval:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def check_cancelled(cls) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def run_async_from_thread(
|
||||||
|
cls,
|
||||||
|
func: Callable[[Unpack[PosArgsT]], Coroutine[Any, Any, T_co]],
|
||||||
|
args: tuple[Unpack[PosArgsT]],
|
||||||
|
token: object,
|
||||||
|
) -> T_co:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def run_sync_from_thread(
|
||||||
|
cls,
|
||||||
|
func: Callable[[Unpack[PosArgsT]], T_Retval],
|
||||||
|
args: tuple[Unpack[PosArgsT]],
|
||||||
|
token: object,
|
||||||
|
) -> T_Retval:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def open_process(
|
||||||
|
cls,
|
||||||
|
command: StrOrBytesPath | Sequence[StrOrBytesPath],
|
||||||
|
*,
|
||||||
|
stdin: int | IO[Any] | None,
|
||||||
|
stdout: int | IO[Any] | None,
|
||||||
|
stderr: int | IO[Any] | None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> Process:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def setup_process_pool_exit_at_shutdown(cls, workers: set[Process]) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def connect_tcp(
|
||||||
|
cls, host: str, port: int, local_address: IPSockAddrType | None = None
|
||||||
|
) -> SocketStream:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def connect_unix(cls, path: str | bytes) -> UNIXSocketStream:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_tcp_listener(cls, sock: socket) -> SocketListener:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_unix_listener(cls, sock: socket) -> SocketListener:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def create_udp_socket(
|
||||||
|
cls,
|
||||||
|
family: AddressFamily,
|
||||||
|
local_address: IPSockAddrType | None,
|
||||||
|
remote_address: IPSockAddrType | None,
|
||||||
|
reuse_port: bool,
|
||||||
|
) -> UDPSocket | ConnectedUDPSocket:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@overload
|
||||||
|
async def create_unix_datagram_socket(
|
||||||
|
cls, raw_socket: socket, remote_path: None
|
||||||
|
) -> UNIXDatagramSocket: ...
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@overload
|
||||||
|
async def create_unix_datagram_socket(
|
||||||
|
cls, raw_socket: socket, remote_path: str | bytes
|
||||||
|
) -> ConnectedUNIXDatagramSocket: ...
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def create_unix_datagram_socket(
|
||||||
|
cls, raw_socket: socket, remote_path: str | bytes | None
|
||||||
|
) -> UNIXDatagramSocket | ConnectedUNIXDatagramSocket:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def getaddrinfo(
|
||||||
|
cls,
|
||||||
|
host: bytes | str | None,
|
||||||
|
port: str | int | None,
|
||||||
|
*,
|
||||||
|
family: int | AddressFamily = 0,
|
||||||
|
type: int | SocketKind = 0,
|
||||||
|
proto: int = 0,
|
||||||
|
flags: int = 0,
|
||||||
|
) -> Sequence[
|
||||||
|
tuple[
|
||||||
|
AddressFamily,
|
||||||
|
SocketKind,
|
||||||
|
int,
|
||||||
|
str,
|
||||||
|
tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
|
||||||
|
]
|
||||||
|
]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def getnameinfo(
|
||||||
|
cls, sockaddr: IPSockAddrType, flags: int = 0
|
||||||
|
) -> tuple[str, str]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wait_readable(cls, obj: FileDescriptorLike) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wait_writable(cls, obj: FileDescriptorLike) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def notify_closing(cls, obj: FileDescriptorLike) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wrap_listener_socket(cls, sock: socket) -> SocketListener:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wrap_stream_socket(cls, sock: socket) -> SocketStream:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wrap_unix_stream_socket(cls, sock: socket) -> UNIXSocketStream:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wrap_udp_socket(cls, sock: socket) -> UDPSocket:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wrap_connected_udp_socket(cls, sock: socket) -> ConnectedUDPSocket:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wrap_unix_datagram_socket(cls, sock: socket) -> UNIXDatagramSocket:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wrap_connected_unix_datagram_socket(
|
||||||
|
cls, sock: socket
|
||||||
|
) -> ConnectedUNIXDatagramSocket:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def current_default_thread_limiter(cls) -> CapacityLimiter:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def open_signal_receiver(
|
||||||
|
cls, *signals: Signals
|
||||||
|
) -> AbstractContextManager[AsyncIterator[Signals]]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def get_current_task(cls) -> TaskInfo:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def get_running_tasks(cls) -> Sequence[TaskInfo]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
async def wait_all_tasks_blocked(cls) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def create_test_runner(cls, options: dict[str, Any]) -> TestRunner:
|
||||||
|
pass
|
||||||
33
venv/Lib/site-packages/anyio/abc/_resources.py
Normal file
33
venv/Lib/site-packages/anyio/abc/_resources.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
from types import TracebackType
|
||||||
|
from typing import TypeVar
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncResource(metaclass=ABCMeta):
|
||||||
|
"""
|
||||||
|
Abstract base class for all closeable asynchronous resources.
|
||||||
|
|
||||||
|
Works as an asynchronous context manager which returns the instance itself on enter,
|
||||||
|
and calls :meth:`aclose` on exit.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
async def __aenter__(self: T) -> T:
|
||||||
|
return self
|
||||||
|
|
||||||
|
async def __aexit__(
|
||||||
|
self,
|
||||||
|
exc_type: type[BaseException] | None,
|
||||||
|
exc_val: BaseException | None,
|
||||||
|
exc_tb: TracebackType | None,
|
||||||
|
) -> None:
|
||||||
|
await self.aclose()
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def aclose(self) -> None:
|
||||||
|
"""Close the resource."""
|
||||||
399
venv/Lib/site-packages/anyio/abc/_sockets.py
Normal file
399
venv/Lib/site-packages/anyio/abc/_sockets.py
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import errno
|
||||||
|
import socket
|
||||||
|
from abc import abstractmethod
|
||||||
|
from collections.abc import Callable, Collection, Mapping
|
||||||
|
from contextlib import AsyncExitStack
|
||||||
|
from io import IOBase
|
||||||
|
from ipaddress import IPv4Address, IPv6Address
|
||||||
|
from socket import AddressFamily
|
||||||
|
from typing import Any, TypeAlias, TypeVar
|
||||||
|
|
||||||
|
from .._core._eventloop import get_async_backend
|
||||||
|
from .._core._typedattr import (
|
||||||
|
TypedAttributeProvider,
|
||||||
|
TypedAttributeSet,
|
||||||
|
typed_attribute,
|
||||||
|
)
|
||||||
|
from ._streams import ByteStream, Listener, UnreliableObjectStream
|
||||||
|
from ._tasks import TaskGroup
|
||||||
|
|
||||||
|
IPAddressType: TypeAlias = str | IPv4Address | IPv6Address
|
||||||
|
IPSockAddrType: TypeAlias = tuple[str, int]
|
||||||
|
SockAddrType: TypeAlias = IPSockAddrType | str
|
||||||
|
UDPPacketType: TypeAlias = tuple[bytes, IPSockAddrType]
|
||||||
|
UNIXDatagramPacketType: TypeAlias = tuple[bytes, str]
|
||||||
|
T_Retval = TypeVar("T_Retval")
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_socket(
|
||||||
|
sock_or_fd: socket.socket | int,
|
||||||
|
sock_type: socket.SocketKind,
|
||||||
|
addr_family: socket.AddressFamily = socket.AF_UNSPEC,
|
||||||
|
*,
|
||||||
|
require_connected: bool = False,
|
||||||
|
require_bound: bool = False,
|
||||||
|
) -> socket.socket:
|
||||||
|
if isinstance(sock_or_fd, int):
|
||||||
|
try:
|
||||||
|
sock = socket.socket(fileno=sock_or_fd)
|
||||||
|
except OSError as exc:
|
||||||
|
if exc.errno == errno.ENOTSOCK:
|
||||||
|
raise ValueError(
|
||||||
|
"the file descriptor does not refer to a socket"
|
||||||
|
) from exc
|
||||||
|
elif require_connected:
|
||||||
|
raise ValueError("the socket must be connected") from exc
|
||||||
|
elif require_bound:
|
||||||
|
raise ValueError("the socket must be bound to a local address") from exc
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
elif isinstance(sock_or_fd, socket.socket):
|
||||||
|
sock = sock_or_fd
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
f"expected an int or socket, got {type(sock_or_fd).__qualname__} instead"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if require_connected:
|
||||||
|
try:
|
||||||
|
sock.getpeername()
|
||||||
|
except OSError as exc:
|
||||||
|
raise ValueError("the socket must be connected") from exc
|
||||||
|
|
||||||
|
if require_bound:
|
||||||
|
try:
|
||||||
|
if sock.family in (socket.AF_INET, socket.AF_INET6):
|
||||||
|
bound_addr = sock.getsockname()[1]
|
||||||
|
else:
|
||||||
|
bound_addr = sock.getsockname()
|
||||||
|
except OSError:
|
||||||
|
bound_addr = None
|
||||||
|
|
||||||
|
if not bound_addr:
|
||||||
|
raise ValueError("the socket must be bound to a local address")
|
||||||
|
|
||||||
|
if addr_family != socket.AF_UNSPEC and sock.family != addr_family:
|
||||||
|
raise ValueError(
|
||||||
|
f"address family mismatch: expected {addr_family.name}, got "
|
||||||
|
f"{sock.family.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if sock.type != sock_type:
|
||||||
|
raise ValueError(
|
||||||
|
f"socket type mismatch: expected {sock_type.name}, got {sock.type.name}"
|
||||||
|
)
|
||||||
|
except BaseException:
|
||||||
|
# Avoid ResourceWarning from the locally constructed socket object
|
||||||
|
if isinstance(sock_or_fd, int):
|
||||||
|
sock.detach()
|
||||||
|
|
||||||
|
raise
|
||||||
|
|
||||||
|
sock.setblocking(False)
|
||||||
|
return sock
|
||||||
|
|
||||||
|
|
||||||
|
class SocketAttribute(TypedAttributeSet):
|
||||||
|
"""
|
||||||
|
.. attribute:: family
|
||||||
|
:type: socket.AddressFamily
|
||||||
|
|
||||||
|
the address family of the underlying socket
|
||||||
|
|
||||||
|
.. attribute:: local_address
|
||||||
|
:type: tuple[str, int] | str
|
||||||
|
|
||||||
|
the local address the underlying socket is connected to
|
||||||
|
|
||||||
|
.. attribute:: local_port
|
||||||
|
:type: int
|
||||||
|
|
||||||
|
for IP based sockets, the local port the underlying socket is bound to
|
||||||
|
|
||||||
|
.. attribute:: raw_socket
|
||||||
|
:type: socket.socket
|
||||||
|
|
||||||
|
the underlying stdlib socket object
|
||||||
|
|
||||||
|
.. attribute:: remote_address
|
||||||
|
:type: tuple[str, int] | str
|
||||||
|
|
||||||
|
the remote address the underlying socket is connected to
|
||||||
|
|
||||||
|
.. attribute:: remote_port
|
||||||
|
:type: int
|
||||||
|
|
||||||
|
for IP based sockets, the remote port the underlying socket is connected to
|
||||||
|
"""
|
||||||
|
|
||||||
|
family: AddressFamily = typed_attribute()
|
||||||
|
local_address: SockAddrType = typed_attribute()
|
||||||
|
local_port: int = typed_attribute()
|
||||||
|
raw_socket: socket.socket = typed_attribute()
|
||||||
|
remote_address: SockAddrType = typed_attribute()
|
||||||
|
remote_port: int = typed_attribute()
|
||||||
|
|
||||||
|
|
||||||
|
class _SocketProvider(TypedAttributeProvider):
|
||||||
|
@property
|
||||||
|
def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]:
|
||||||
|
from .._core._sockets import convert_ipv6_sockaddr as convert
|
||||||
|
|
||||||
|
attributes: dict[Any, Callable[[], Any]] = {
|
||||||
|
SocketAttribute.family: lambda: self._raw_socket.family,
|
||||||
|
SocketAttribute.local_address: lambda: convert(
|
||||||
|
self._raw_socket.getsockname()
|
||||||
|
),
|
||||||
|
SocketAttribute.raw_socket: lambda: self._raw_socket,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
peername: tuple[str, int] | None = convert(self._raw_socket.getpeername())
|
||||||
|
except OSError:
|
||||||
|
peername = None
|
||||||
|
|
||||||
|
# Provide the remote address for connected sockets
|
||||||
|
if peername is not None:
|
||||||
|
attributes[SocketAttribute.remote_address] = lambda: peername
|
||||||
|
|
||||||
|
# Provide local and remote ports for IP based sockets
|
||||||
|
if self._raw_socket.family in (AddressFamily.AF_INET, AddressFamily.AF_INET6):
|
||||||
|
attributes[SocketAttribute.local_port] = lambda: (
|
||||||
|
self._raw_socket.getsockname()[1]
|
||||||
|
)
|
||||||
|
if peername is not None:
|
||||||
|
remote_port = peername[1]
|
||||||
|
attributes[SocketAttribute.remote_port] = lambda: remote_port
|
||||||
|
|
||||||
|
return attributes
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def _raw_socket(self) -> socket.socket:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SocketStream(ByteStream, _SocketProvider):
|
||||||
|
"""
|
||||||
|
Transports bytes over a socket.
|
||||||
|
|
||||||
|
Supports all relevant extra attributes from :class:`~SocketAttribute`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def from_socket(cls, sock_or_fd: socket.socket | int) -> SocketStream:
|
||||||
|
"""
|
||||||
|
Wrap an existing socket object or file descriptor as a socket stream.
|
||||||
|
|
||||||
|
The newly created socket wrapper takes ownership of the socket being passed in.
|
||||||
|
The existing socket must already be connected.
|
||||||
|
|
||||||
|
:param sock_or_fd: a socket object or file descriptor
|
||||||
|
:return: a socket stream
|
||||||
|
|
||||||
|
"""
|
||||||
|
sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_connected=True)
|
||||||
|
return await get_async_backend().wrap_stream_socket(sock)
|
||||||
|
|
||||||
|
|
||||||
|
class UNIXSocketStream(SocketStream):
|
||||||
|
@classmethod
|
||||||
|
async def from_socket(cls, sock_or_fd: socket.socket | int) -> UNIXSocketStream:
|
||||||
|
"""
|
||||||
|
Wrap an existing socket object or file descriptor as a UNIX socket stream.
|
||||||
|
|
||||||
|
The newly created socket wrapper takes ownership of the socket being passed in.
|
||||||
|
The existing socket must already be connected.
|
||||||
|
|
||||||
|
:param sock_or_fd: a socket object or file descriptor
|
||||||
|
:return: a UNIX socket stream
|
||||||
|
|
||||||
|
"""
|
||||||
|
sock = _validate_socket(
|
||||||
|
sock_or_fd, socket.SOCK_STREAM, socket.AF_UNIX, require_connected=True
|
||||||
|
)
|
||||||
|
return await get_async_backend().wrap_unix_stream_socket(sock)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None:
|
||||||
|
"""
|
||||||
|
Send file descriptors along with a message to the peer.
|
||||||
|
|
||||||
|
:param message: a non-empty bytestring
|
||||||
|
:param fds: a collection of files (either numeric file descriptors or open file
|
||||||
|
or socket objects)
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]:
|
||||||
|
"""
|
||||||
|
Receive file descriptors along with a message from the peer.
|
||||||
|
|
||||||
|
:param msglen: length of the message to expect from the peer
|
||||||
|
:param maxfds: maximum number of file descriptors to expect from the peer
|
||||||
|
:return: a tuple of (message, file descriptors)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class SocketListener(Listener[SocketStream], _SocketProvider):
|
||||||
|
"""
|
||||||
|
Listens to incoming socket connections.
|
||||||
|
|
||||||
|
Supports all relevant extra attributes from :class:`~SocketAttribute`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def from_socket(
|
||||||
|
cls,
|
||||||
|
sock_or_fd: socket.socket | int,
|
||||||
|
) -> SocketListener:
|
||||||
|
"""
|
||||||
|
Wrap an existing socket object or file descriptor as a socket listener.
|
||||||
|
|
||||||
|
The newly created listener takes ownership of the socket being passed in.
|
||||||
|
|
||||||
|
:param sock_or_fd: a socket object or file descriptor
|
||||||
|
:return: a socket listener
|
||||||
|
|
||||||
|
"""
|
||||||
|
sock = _validate_socket(sock_or_fd, socket.SOCK_STREAM, require_bound=True)
|
||||||
|
return await get_async_backend().wrap_listener_socket(sock)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def accept(self) -> SocketStream:
|
||||||
|
"""Accept an incoming connection."""
|
||||||
|
|
||||||
|
async def serve(
|
||||||
|
self,
|
||||||
|
handler: Callable[[SocketStream], Any],
|
||||||
|
task_group: TaskGroup | None = None,
|
||||||
|
) -> None:
|
||||||
|
from .. import create_task_group
|
||||||
|
|
||||||
|
async with AsyncExitStack() as stack:
|
||||||
|
if task_group is None:
|
||||||
|
task_group = await stack.enter_async_context(create_task_group())
|
||||||
|
|
||||||
|
while True:
|
||||||
|
stream = await self.accept()
|
||||||
|
task_group.start_soon(handler, stream)
|
||||||
|
|
||||||
|
|
||||||
|
class UDPSocket(UnreliableObjectStream[UDPPacketType], _SocketProvider):
|
||||||
|
"""
|
||||||
|
Represents an unconnected UDP socket.
|
||||||
|
|
||||||
|
Supports all relevant extra attributes from :class:`~SocketAttribute`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def from_socket(cls, sock_or_fd: socket.socket | int) -> UDPSocket:
|
||||||
|
"""
|
||||||
|
Wrap an existing socket object or file descriptor as a UDP socket.
|
||||||
|
|
||||||
|
The newly created socket wrapper takes ownership of the socket being passed in.
|
||||||
|
The existing socket must be bound to a local address.
|
||||||
|
|
||||||
|
:param sock_or_fd: a socket object or file descriptor
|
||||||
|
:return: a UDP socket
|
||||||
|
|
||||||
|
"""
|
||||||
|
sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, require_bound=True)
|
||||||
|
return await get_async_backend().wrap_udp_socket(sock)
|
||||||
|
|
||||||
|
async def sendto(self, data: bytes, host: str, port: int) -> None:
|
||||||
|
"""
|
||||||
|
Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, (host, port))).
|
||||||
|
|
||||||
|
"""
|
||||||
|
return await self.send((data, (host, port)))
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectedUDPSocket(UnreliableObjectStream[bytes], _SocketProvider):
|
||||||
|
"""
|
||||||
|
Represents an connected UDP socket.
|
||||||
|
|
||||||
|
Supports all relevant extra attributes from :class:`~SocketAttribute`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def from_socket(cls, sock_or_fd: socket.socket | int) -> ConnectedUDPSocket:
|
||||||
|
"""
|
||||||
|
Wrap an existing socket object or file descriptor as a connected UDP socket.
|
||||||
|
|
||||||
|
The newly created socket wrapper takes ownership of the socket being passed in.
|
||||||
|
The existing socket must already be connected.
|
||||||
|
|
||||||
|
:param sock_or_fd: a socket object or file descriptor
|
||||||
|
:return: a connected UDP socket
|
||||||
|
|
||||||
|
"""
|
||||||
|
sock = _validate_socket(
|
||||||
|
sock_or_fd,
|
||||||
|
socket.SOCK_DGRAM,
|
||||||
|
require_connected=True,
|
||||||
|
)
|
||||||
|
return await get_async_backend().wrap_connected_udp_socket(sock)
|
||||||
|
|
||||||
|
|
||||||
|
class UNIXDatagramSocket(
|
||||||
|
UnreliableObjectStream[UNIXDatagramPacketType], _SocketProvider
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Represents an unconnected Unix datagram socket.
|
||||||
|
|
||||||
|
Supports all relevant extra attributes from :class:`~SocketAttribute`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def from_socket(
|
||||||
|
cls,
|
||||||
|
sock_or_fd: socket.socket | int,
|
||||||
|
) -> UNIXDatagramSocket:
|
||||||
|
"""
|
||||||
|
Wrap an existing socket object or file descriptor as a UNIX datagram
|
||||||
|
socket.
|
||||||
|
|
||||||
|
The newly created socket wrapper takes ownership of the socket being passed in.
|
||||||
|
|
||||||
|
:param sock_or_fd: a socket object or file descriptor
|
||||||
|
:return: a UNIX datagram socket
|
||||||
|
|
||||||
|
"""
|
||||||
|
sock = _validate_socket(sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX)
|
||||||
|
return await get_async_backend().wrap_unix_datagram_socket(sock)
|
||||||
|
|
||||||
|
async def sendto(self, data: bytes, path: str) -> None:
|
||||||
|
"""Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, path))."""
|
||||||
|
return await self.send((data, path))
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectedUNIXDatagramSocket(UnreliableObjectStream[bytes], _SocketProvider):
|
||||||
|
"""
|
||||||
|
Represents a connected Unix datagram socket.
|
||||||
|
|
||||||
|
Supports all relevant extra attributes from :class:`~SocketAttribute`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def from_socket(
|
||||||
|
cls,
|
||||||
|
sock_or_fd: socket.socket | int,
|
||||||
|
) -> ConnectedUNIXDatagramSocket:
|
||||||
|
"""
|
||||||
|
Wrap an existing socket object or file descriptor as a connected UNIX datagram
|
||||||
|
socket.
|
||||||
|
|
||||||
|
The newly created socket wrapper takes ownership of the socket being passed in.
|
||||||
|
The existing socket must already be connected.
|
||||||
|
|
||||||
|
:param sock_or_fd: a socket object or file descriptor
|
||||||
|
:return: a connected UNIX datagram socket
|
||||||
|
|
||||||
|
"""
|
||||||
|
sock = _validate_socket(
|
||||||
|
sock_or_fd, socket.SOCK_DGRAM, socket.AF_UNIX, require_connected=True
|
||||||
|
)
|
||||||
|
return await get_async_backend().wrap_connected_unix_datagram_socket(sock)
|
||||||
233
venv/Lib/site-packages/anyio/abc/_streams.py
Normal file
233
venv/Lib/site-packages/anyio/abc/_streams.py
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
from collections.abc import Callable
|
||||||
|
from typing import Any, Generic, TypeAlias, TypeVar
|
||||||
|
|
||||||
|
from .._core._exceptions import EndOfStream
|
||||||
|
from .._core._typedattr import TypedAttributeProvider
|
||||||
|
from ._resources import AsyncResource
|
||||||
|
from ._tasks import TaskGroup
|
||||||
|
|
||||||
|
T_Item = TypeVar("T_Item")
|
||||||
|
T_co = TypeVar("T_co", covariant=True)
|
||||||
|
T_contra = TypeVar("T_contra", contravariant=True)
|
||||||
|
|
||||||
|
|
||||||
|
class UnreliableObjectReceiveStream(
|
||||||
|
Generic[T_co], AsyncResource, TypedAttributeProvider
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
An interface for receiving objects.
|
||||||
|
|
||||||
|
This interface makes no guarantees that the received messages arrive in the order in
|
||||||
|
which they were sent, or that no messages are missed.
|
||||||
|
|
||||||
|
Asynchronously iterating over objects of this type will yield objects matching the
|
||||||
|
given type parameter.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __aiter__(self) -> UnreliableObjectReceiveStream[T_co]:
|
||||||
|
return self
|
||||||
|
|
||||||
|
async def __anext__(self) -> T_co:
|
||||||
|
try:
|
||||||
|
return await self.receive()
|
||||||
|
except EndOfStream:
|
||||||
|
raise StopAsyncIteration from None
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def receive(self) -> T_co:
|
||||||
|
"""
|
||||||
|
Receive the next item.
|
||||||
|
|
||||||
|
:raises ~anyio.ClosedResourceError: if the receive stream has been explicitly
|
||||||
|
closed
|
||||||
|
:raises ~anyio.EndOfStream: if this stream has been closed from the other end
|
||||||
|
:raises ~anyio.BrokenResourceError: if this stream has been rendered unusable
|
||||||
|
due to external causes
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class UnreliableObjectSendStream(
|
||||||
|
Generic[T_contra], AsyncResource, TypedAttributeProvider
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
An interface for sending objects.
|
||||||
|
|
||||||
|
This interface makes no guarantees that the messages sent will reach the
|
||||||
|
recipient(s) in the same order in which they were sent, or at all.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def send(self, item: T_contra) -> None:
|
||||||
|
"""
|
||||||
|
Send an item to the peer(s).
|
||||||
|
|
||||||
|
:param item: the item to send
|
||||||
|
:raises ~anyio.ClosedResourceError: if the send stream has been explicitly
|
||||||
|
closed
|
||||||
|
:raises ~anyio.BrokenResourceError: if this stream has been rendered unusable
|
||||||
|
due to external causes
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class UnreliableObjectStream(
|
||||||
|
UnreliableObjectReceiveStream[T_Item], UnreliableObjectSendStream[T_Item]
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
A bidirectional message stream which does not guarantee the order or reliability of
|
||||||
|
message delivery.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectReceiveStream(UnreliableObjectReceiveStream[T_co]):
|
||||||
|
"""
|
||||||
|
A receive message stream which guarantees that messages are received in the same
|
||||||
|
order in which they were sent, and that no messages are missed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectSendStream(UnreliableObjectSendStream[T_contra]):
|
||||||
|
"""
|
||||||
|
A send message stream which guarantees that messages are delivered in the same order
|
||||||
|
in which they were sent, without missing any messages in the middle.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectStream(
|
||||||
|
ObjectReceiveStream[T_Item],
|
||||||
|
ObjectSendStream[T_Item],
|
||||||
|
UnreliableObjectStream[T_Item],
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
A bidirectional message stream which guarantees the order and reliability of message
|
||||||
|
delivery.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def send_eof(self) -> None:
|
||||||
|
"""
|
||||||
|
Send an end-of-file indication to the peer.
|
||||||
|
|
||||||
|
You should not try to send any further data to this stream after calling this
|
||||||
|
method. This method is idempotent (does nothing on successive calls).
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ByteReceiveStream(AsyncResource, TypedAttributeProvider):
|
||||||
|
"""
|
||||||
|
An interface for receiving bytes from a single peer.
|
||||||
|
|
||||||
|
Iterating this byte stream will yield a byte string of arbitrary length, but no more
|
||||||
|
than 65536 bytes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __aiter__(self) -> ByteReceiveStream:
|
||||||
|
return self
|
||||||
|
|
||||||
|
async def __anext__(self) -> bytes:
|
||||||
|
try:
|
||||||
|
return await self.receive()
|
||||||
|
except EndOfStream:
|
||||||
|
raise StopAsyncIteration from None
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def receive(self, max_bytes: int = 65536) -> bytes:
|
||||||
|
"""
|
||||||
|
Receive at most ``max_bytes`` bytes from the peer.
|
||||||
|
|
||||||
|
.. note:: Implementers of this interface should not return an empty
|
||||||
|
:class:`bytes` object, and users should ignore them.
|
||||||
|
|
||||||
|
:param max_bytes: maximum number of bytes to receive
|
||||||
|
:return: the received bytes
|
||||||
|
:raises ~anyio.EndOfStream: if this stream has been closed from the other end
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ByteSendStream(AsyncResource, TypedAttributeProvider):
|
||||||
|
"""An interface for sending bytes to a single peer."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def send(self, item: bytes) -> None:
|
||||||
|
"""
|
||||||
|
Send the given bytes to the peer.
|
||||||
|
|
||||||
|
:param item: the bytes to send
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ByteStream(ByteReceiveStream, ByteSendStream):
|
||||||
|
"""A bidirectional byte stream."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def send_eof(self) -> None:
|
||||||
|
"""
|
||||||
|
Send an end-of-file indication to the peer.
|
||||||
|
|
||||||
|
You should not try to send any further data to this stream after calling this
|
||||||
|
method. This method is idempotent (does nothing on successive calls).
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
#: Type alias for all unreliable bytes-oriented receive streams.
|
||||||
|
AnyUnreliableByteReceiveStream: TypeAlias = (
|
||||||
|
UnreliableObjectReceiveStream[bytes] | ByteReceiveStream
|
||||||
|
)
|
||||||
|
#: Type alias for all unreliable bytes-oriented send streams.
|
||||||
|
AnyUnreliableByteSendStream: TypeAlias = (
|
||||||
|
UnreliableObjectSendStream[bytes] | ByteSendStream
|
||||||
|
)
|
||||||
|
#: Type alias for all unreliable bytes-oriented streams.
|
||||||
|
AnyUnreliableByteStream: TypeAlias = UnreliableObjectStream[bytes] | ByteStream
|
||||||
|
#: Type alias for all bytes-oriented receive streams.
|
||||||
|
AnyByteReceiveStream: TypeAlias = ObjectReceiveStream[bytes] | ByteReceiveStream
|
||||||
|
#: Type alias for all bytes-oriented send streams.
|
||||||
|
AnyByteSendStream: TypeAlias = ObjectSendStream[bytes] | ByteSendStream
|
||||||
|
#: Type alias for all bytes-oriented streams.
|
||||||
|
AnyByteStream: TypeAlias = ObjectStream[bytes] | ByteStream
|
||||||
|
|
||||||
|
|
||||||
|
class Listener(Generic[T_co], AsyncResource, TypedAttributeProvider):
|
||||||
|
"""An interface for objects that let you accept incoming connections."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def serve(
|
||||||
|
self, handler: Callable[[T_co], Any], task_group: TaskGroup | None = None
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Accept incoming connections as they come in and start tasks to handle them.
|
||||||
|
|
||||||
|
:param handler: a callable that will be used to handle each accepted connection
|
||||||
|
:param task_group: the task group that will be used to start tasks for handling
|
||||||
|
each accepted connection (if omitted, an ad-hoc task group will be created)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ObjectStreamConnectable(Generic[T_co], metaclass=ABCMeta):
|
||||||
|
@abstractmethod
|
||||||
|
async def connect(self) -> ObjectStream[T_co]:
|
||||||
|
"""
|
||||||
|
Connect to the remote endpoint.
|
||||||
|
|
||||||
|
:return: an object stream connected to the remote end
|
||||||
|
:raises ConnectionFailed: if the connection fails
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ByteStreamConnectable(metaclass=ABCMeta):
|
||||||
|
@abstractmethod
|
||||||
|
async def connect(self) -> ByteStream:
|
||||||
|
"""
|
||||||
|
Connect to the remote endpoint.
|
||||||
|
|
||||||
|
:return: a bytestream connected to the remote end
|
||||||
|
:raises ConnectionFailed: if the connection fails
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
#: Type alias for all connectables returning bytestreams or bytes-oriented object streams
|
||||||
|
AnyByteStreamConnectable: TypeAlias = (
|
||||||
|
ObjectStreamConnectable[bytes] | ByteStreamConnectable
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user