Format: text/x-python
⬇ Download File (6.4 KB)
   1  from __future__ import annotations
   2  
   3  from abc import abstractmethod
   4  from collections.abc import Callable
   5  from typing import Any, Generic, TypeVar, Union
   6  
   7  from .._core._exceptions import EndOfStream
   8  from .._core._typedattr import TypedAttributeProvider
   9  from ._resources import AsyncResource
  10  from ._tasks import TaskGroup
  11  
  12  T_Item = TypeVar("T_Item")
  13  T_co = TypeVar("T_co", covariant=True)
  14  T_contra = TypeVar("T_contra", contravariant=True)
  15  
  16  
  17  class UnreliableObjectReceiveStream(
  18      Generic[T_co], AsyncResource, TypedAttributeProvider
  19  ):
  20      """
  21      An interface for receiving objects.
  22  
  23      This interface makes no guarantees that the received messages arrive in the order in
  24      which they were sent, or that no messages are missed.
  25  
  26      Asynchronously iterating over objects of this type will yield objects matching the
  27      given type parameter.
  28      """
  29  
  30      def __aiter__(self) -> UnreliableObjectReceiveStream[T_co]:
  31          return self
  32  
  33      async def __anext__(self) -> T_co:
  34          try:
  35              return await self.receive()
  36          except EndOfStream:
  37              raise StopAsyncIteration
  38  
  39      @abstractmethod
  40      async def receive(self) -> T_co:
  41          """
  42          Receive the next item.
  43  
  44          :raises ~anyio.ClosedResourceError: if the receive stream has been explicitly
  45              closed
  46          :raises ~anyio.EndOfStream: if this stream has been closed from the other end
  47          :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable
  48              due to external causes
  49          """
  50  
  51  
  52  class UnreliableObjectSendStream(
  53      Generic[T_contra], AsyncResource, TypedAttributeProvider
  54  ):
  55      """
  56      An interface for sending objects.
  57  
  58      This interface makes no guarantees that the messages sent will reach the
  59      recipient(s) in the same order in which they were sent, or at all.
  60      """
  61  
  62      @abstractmethod
  63      async def send(self, item: T_contra) -> None:
  64          """
  65          Send an item to the peer(s).
  66  
  67          :param item: the item to send
  68          :raises ~anyio.ClosedResourceError: if the send stream has been explicitly
  69              closed
  70          :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable
  71              due to external causes
  72          """
  73  
  74  
  75  class UnreliableObjectStream(
  76      UnreliableObjectReceiveStream[T_Item], UnreliableObjectSendStream[T_Item]
  77  ):
  78      """
  79      A bidirectional message stream which does not guarantee the order or reliability of
  80      message delivery.
  81      """
  82  
  83  
  84  class ObjectReceiveStream(UnreliableObjectReceiveStream[T_co]):
  85      """
  86      A receive message stream which guarantees that messages are received in the same
  87      order in which they were sent, and that no messages are missed.
  88      """
  89  
  90  
  91  class ObjectSendStream(UnreliableObjectSendStream[T_contra]):
  92      """
  93      A send message stream which guarantees that messages are delivered in the same order
  94      in which they were sent, without missing any messages in the middle.
  95      """
  96  
  97  
  98  class ObjectStream(
  99      ObjectReceiveStream[T_Item],
 100      ObjectSendStream[T_Item],
 101      UnreliableObjectStream[T_Item],
 102  ):
 103      """
 104      A bidirectional message stream which guarantees the order and reliability of message
 105      delivery.
 106      """
 107  
 108      @abstractmethod
 109      async def send_eof(self) -> None:
 110          """
 111          Send an end-of-file indication to the peer.
 112  
 113          You should not try to send any further data to this stream after calling this
 114          method. This method is idempotent (does nothing on successive calls).
 115          """
 116  
 117  
 118  class ByteReceiveStream(AsyncResource, TypedAttributeProvider):
 119      """
 120      An interface for receiving bytes from a single peer.
 121  
 122      Iterating this byte stream will yield a byte string of arbitrary length, but no more
 123      than 65536 bytes.
 124      """
 125  
 126      def __aiter__(self) -> ByteReceiveStream:
 127          return self
 128  
 129      async def __anext__(self) -> bytes:
 130          try:
 131              return await self.receive()
 132          except EndOfStream:
 133              raise StopAsyncIteration
 134  
 135      @abstractmethod
 136      async def receive(self, max_bytes: int = 65536) -> bytes:
 137          """
 138          Receive at most ``max_bytes`` bytes from the peer.
 139  
 140          .. note:: Implementers of this interface should not return an empty
 141              :class:`bytes` object, and users should ignore them.
 142  
 143          :param max_bytes: maximum number of bytes to receive
 144          :return: the received bytes
 145          :raises ~anyio.EndOfStream: if this stream has been closed from the other end
 146          """
 147  
 148  
 149  class ByteSendStream(AsyncResource, TypedAttributeProvider):
 150      """An interface for sending bytes to a single peer."""
 151  
 152      @abstractmethod
 153      async def send(self, item: bytes) -> None:
 154          """
 155          Send the given bytes to the peer.
 156  
 157          :param item: the bytes to send
 158          """
 159  
 160  
 161  class ByteStream(ByteReceiveStream, ByteSendStream):
 162      """A bidirectional byte stream."""
 163  
 164      @abstractmethod
 165      async def send_eof(self) -> None:
 166          """
 167          Send an end-of-file indication to the peer.
 168  
 169          You should not try to send any further data to this stream after calling this
 170          method. This method is idempotent (does nothing on successive calls).
 171          """
 172  
 173  
 174  #: Type alias for all unreliable bytes-oriented receive streams.
 175  AnyUnreliableByteReceiveStream = Union[
 176      UnreliableObjectReceiveStream[bytes], ByteReceiveStream
 177  ]
 178  #: Type alias for all unreliable bytes-oriented send streams.
 179  AnyUnreliableByteSendStream = Union[UnreliableObjectSendStream[bytes], ByteSendStream]
 180  #: Type alias for all unreliable bytes-oriented streams.
 181  AnyUnreliableByteStream = Union[UnreliableObjectStream[bytes], ByteStream]
 182  #: Type alias for all bytes-oriented receive streams.
 183  AnyByteReceiveStream = Union[ObjectReceiveStream[bytes], ByteReceiveStream]
 184  #: Type alias for all bytes-oriented send streams.
 185  AnyByteSendStream = Union[ObjectSendStream[bytes], ByteSendStream]
 186  #: Type alias for all bytes-oriented streams.
 187  AnyByteStream = Union[ObjectStream[bytes], ByteStream]
 188  
 189  
 190  class Listener(Generic[T_co], AsyncResource, TypedAttributeProvider):
 191      """An interface for objects that let you accept incoming connections."""
 192  
 193      @abstractmethod
 194      async def serve(
 195          self, handler: Callable[[T_co], Any], task_group: TaskGroup | None = None
 196      ) -> None:
 197          """
 198          Accept incoming connections as they come in and start tasks to handle them.
 199  
 200          :param handler: a callable that will be used to handle each accepted connection
 201          :param task_group: the task group that will be used to start tasks for handling
 202              each accepted connection (if omitted, an ad-hoc task group will be created)
 203          """
 204