@@ -484,15 +484,18 @@ async def send_eof(self):
484
484
"""
485
485
486
486
487
+ # A regular invariant generic type
488
+ T = TypeVar ("T" )
489
+
487
490
# The type of object produced by a ReceiveChannel (covariant because
488
491
# ReceiveChannel[Derived] can be passed to someone expecting
489
492
# ReceiveChannel[Base])
490
- T_co = TypeVar ("T_co " , covariant = True )
493
+ ReceiveType = TypeVar ("ReceiveType " , covariant = True )
491
494
492
495
# The type of object accepted by a SendChannel (contravariant because
493
496
# SendChannel[Base] can be passed to someone expecting
494
497
# SendChannel[Derived])
495
- T_contra = TypeVar ("T_contra " , contravariant = True )
498
+ SendType = TypeVar ("SendType " , contravariant = True )
496
499
497
500
# The type of object produced by a Listener (covariant plus must be
498
501
# an AsyncResource)
@@ -537,39 +540,21 @@ async def accept(self):
537
540
"""
538
541
539
542
540
- class SendChannel (AsyncResource , Generic [T_contra ]):
543
+ class SendChannel (AsyncResource , Generic [SendType ]):
541
544
"""A standard interface for sending Python objects to some receiver.
542
545
543
- :class: `SendChannel` objects also implement the :class: `AsyncResource`
544
- interface, so they can be closed by calling :meth: `~AsyncResource.aclose`
545
- or using an ``async with`` block.
546
+ `SendChannel` objects also implement the `AsyncResource` interface, so
547
+ they can be closed by calling `~AsyncResource.aclose` or using an ``async
548
+ with`` block.
546
549
547
550
If you want to send raw bytes rather than Python objects, see
548
- :class: `ReceiveStream`.
551
+ `ReceiveStream`.
549
552
550
553
"""
551
554
__slots__ = ()
552
555
553
556
@abstractmethod
554
- def send_nowait (self , value ):
555
- """Attempt to send an object through the channel, without blocking.
556
-
557
- Args:
558
- value (object): The object to send.
559
-
560
- Raises:
561
- trio.WouldBlock: if the operation cannot be completed immediately
562
- (for example, because the channel's internal buffer is full).
563
- trio.BrokenResourceError: if something has gone wrong, and the
564
- channel is broken. For example, you may get this if the receiver
565
- has already been closed.
566
- trio.ClosedResourceError: if you previously closed this
567
- :class:`SendChannel` object.
568
-
569
- """
570
-
571
- @abstractmethod
572
- async def send (self , value ):
557
+ async def send (self , value : SendType ) -> None :
573
558
"""Attempt to send an object through the channel, blocking if necessary.
574
559
575
560
Args:
@@ -582,36 +567,15 @@ async def send(self, value):
582
567
trio.ClosedResourceError: if you previously closed this
583
568
:class:`SendChannel` object, or if another task closes it while
584
569
:meth:`send` is running.
585
-
586
- """
587
-
588
- @abstractmethod
589
- def clone (self ):
590
- """Clone this send channel object.
591
-
592
- This returns a new :class:`SendChannel` object, which acts as a
593
- duplicate of the original: sending on the new object does exactly the
594
- same thing as sending on the old object.
595
-
596
- However, closing one of the objects does not close the other, and
597
- receivers don't get :exc:`~trio.EndOfChannel` until *all* clones have
598
- been closed.
599
-
600
- This is useful for communication patterns that involve multiple
601
- producers all sending objects to the same destination. If you give
602
- each producer its own clone of the :class:`SendChannel`, and then make
603
- sure to close each :class:`SendChannel` when it's finished, receivers
604
- will automatically get notified when all producers are finished. See
605
- :ref:`channel-mpmc` for examples.
606
-
607
- Raises:
608
- trio.ClosedResourceError: if you already closed this
609
- :class:`SendChannel` object.
570
+ trio.BusyResourceError: some channels allow multiple tasks to call
571
+ `send` at the same time, but others don't. If you try to call
572
+ `send` simultaneously from multiple tasks on a channel that
573
+ doesn't support it, then you can get `~trio.BusyResourceError`.
610
574
611
575
"""
612
576
613
577
614
- class ReceiveChannel (AsyncResource , Generic [T_co ]):
578
+ class ReceiveChannel (AsyncResource , Generic [ReceiveType ]):
615
579
"""A standard interface for receiving Python objects from some sender.
616
580
617
581
You can iterate over a :class:`ReceiveChannel` using an ``async for``
@@ -621,45 +585,22 @@ class ReceiveChannel(AsyncResource, Generic[T_co]):
621
585
...
622
586
623
587
This is equivalent to calling :meth:`receive` repeatedly. The loop exits
624
- without error when :meth: `receive` raises :exc: `~trio.EndOfChannel`.
588
+ without error when `receive` raises `~trio.EndOfChannel`.
625
589
626
- :class: `ReceiveChannel` objects also implement the :class: `AsyncResource`
627
- interface, so they can be closed by calling :meth: `~AsyncResource.aclose`
628
- or using an ``async with`` block.
590
+ `ReceiveChannel` objects also implement the `AsyncResource` interface, so
591
+ they can be closed by calling `~AsyncResource.aclose` or using an ``async
592
+ with`` block.
629
593
630
594
If you want to receive raw bytes rather than Python objects, see
631
- :class: `ReceiveStream`.
595
+ `ReceiveStream`.
632
596
633
597
"""
634
598
__slots__ = ()
635
599
636
600
@abstractmethod
637
- def receive_nowait (self ):
638
- """Attempt to receive an incoming object, without blocking.
639
-
640
- Returns:
641
- object: Whatever object was received.
642
-
643
- Raises:
644
- trio.WouldBlock: if the operation cannot be completed immediately
645
- (for example, because no object has been sent yet).
646
- trio.EndOfChannel: if the sender has been closed cleanly, and no
647
- more objects are coming. This is not an error condition.
648
- trio.ClosedResourceError: if you previously closed this
649
- :class:`ReceiveChannel` object.
650
- trio.BrokenResourceError: if something has gone wrong, and the
651
- channel is broken.
652
-
653
- """
654
-
655
- @abstractmethod
656
- async def receive (self ):
601
+ async def receive (self ) -> ReceiveType :
657
602
"""Attempt to receive an incoming object, blocking if necessary.
658
603
659
- It's legal for multiple tasks to call :meth:`receive` at the same
660
- time. If this happens, then one task receives the first value sent,
661
- another task receives the next value sent, and so on.
662
-
663
604
Returns:
664
605
object: Whatever object was received.
665
606
@@ -670,43 +611,28 @@ async def receive(self):
670
611
:class:`ReceiveChannel` object.
671
612
trio.BrokenResourceError: if something has gone wrong, and the
672
613
channel is broken.
673
-
674
- """
675
-
676
- @abstractmethod
677
- def clone (self ):
678
- """Clone this receive channel object.
679
-
680
- This returns a new :class:`ReceiveChannel` object, which acts as a
681
- duplicate of the original: receiving on the new object does exactly
682
- the same thing as receiving on the old object.
683
-
684
- However, closing one of the objects does not close the other, and the
685
- underlying channel is not closed until all clones are closed.
686
-
687
- This is useful for communication patterns involving multiple consumers
688
- all receiving objects from the same underlying channel. See
689
- :ref:`channel-mpmc` for examples.
690
-
691
- .. warning:: The clones all share the same underlying channel.
692
- Whenever a clone :meth:`receive`\\ s a value, it is removed from the
693
- channel and the other clones do *not* receive that value. If you
694
- want to send multiple copies of the same stream of values to
695
- multiple destinations, like :func:`itertools.tee`, then you need to
696
- find some other solution; this method does *not* do that.
697
-
698
- Raises:
699
- trio.ClosedResourceError: if you already closed this
700
- :class:`SendChannel` object.
614
+ trio.BusyResourceError: some channels allow multiple tasks to call
615
+ `receive` at the same time, but others don't. If you try to call
616
+ `receive` simultaneously from multiple tasks on a channel that
617
+ doesn't support it, then you can get `~trio.BusyResourceError`.
701
618
702
619
"""
703
620
704
621
@aiter_compat
705
622
def __aiter__ (self ):
706
623
return self
707
624
708
- async def __anext__ (self ):
625
+ async def __anext__ (self ) -> ReceiveType :
709
626
try :
710
627
return await self .receive ()
711
628
except trio .EndOfChannel :
712
629
raise StopAsyncIteration
630
+
631
+
632
+ class Channel (SendChannel [T ], ReceiveChannel [T ]):
633
+ """A standard interface for interacting with bidirectional channels.
634
+
635
+ A `Channel` is an object that implements both the `SendChannel` and
636
+ `ReceiveChannel` interfaces, so you can both send and receive objects.
637
+
638
+ """
0 commit comments