55
66from __future__ import annotations
77
8- from typing import Generic
8+ from typing import Generic , TypeVar
99
1010from ._base_classes import Receiver , Sender , T , U
1111from ._broadcast import Broadcast
1212
13+ V = TypeVar ("V" )
14+ W = TypeVar ("W" )
15+
1316
1417class Bidirectional (Generic [T , U ]):
1518 """A wrapper class for simulating bidirectional channels."""
1619
20+ class Handle (Sender [V ], Receiver [W ]):
21+ """A handle to a [Bidirectional][frequenz.channels.Bidirectional] instance.
22+
23+ It can be used to send/receive values between the client and service.
24+ """
25+
26+ def __init__ (self , sender : Sender [V ], receiver : Receiver [W ]) -> None :
27+ """Create a `Bidirectional.Handle` instance.
28+
29+ Args:
30+ sender: A sender to send values with.
31+ receiver: A receiver to receive values from.
32+ """
33+ self ._sender = sender
34+ self ._receiver = receiver
35+
36+ async def send (self , msg : V ) -> bool :
37+ """Send a value to the other side.
38+
39+ Args:
40+ msg: The value to send.
41+
42+ Returns:
43+ Whether the send was successful or not.
44+ """
45+ return await self ._sender .send (msg )
46+
47+ async def ready (self ) -> None :
48+ """Wait until the receiver is ready with a value."""
49+ await self ._receiver .ready () # pylint: disable=protected-access
50+
51+ def consume (self ) -> W :
52+ """Return the latest value once `_ready` is complete.
53+
54+ Returns:
55+ The next value that was received.
56+ """
57+ return self ._receiver .consume () # pylint: disable=protected-access
58+
1759 def __init__ (self , client_id : str , service_id : str ) -> None :
1860 """Create a `Bidirectional` instance.
1961
@@ -27,69 +69,29 @@ def __init__(self, client_id: str, service_id: str) -> None:
2769 f"resp_{ service_id } _{ client_id } "
2870 )
2971
30- self ._client_handle = BidirectionalHandle (
72+ self ._client_handle = Bidirectional . Handle (
3173 self ._request_channel .new_sender (),
3274 self ._response_channel .new_receiver (),
3375 )
34- self ._service_handle = BidirectionalHandle (
76+ self ._service_handle = Bidirectional . Handle (
3577 self ._response_channel .new_sender (),
3678 self ._request_channel .new_receiver (),
3779 )
3880
3981 @property
40- def client_handle (self ) -> BidirectionalHandle [T , U ]:
41- """Get a BidirectionalHandle for the client to use.
82+ def client_handle (self ) -> Bidirectional . Handle [T , U ]:
83+ """Get a `Handle` for the client side to use.
4284
4385 Returns:
4486 Object to send/receive messages with.
4587 """
4688 return self ._client_handle
4789
4890 @property
49- def service_handle (self ) -> BidirectionalHandle [U , T ]:
50- """Get a `BidirectionalHandle ` for the service to use.
91+ def service_handle (self ) -> Bidirectional . Handle [U , T ]:
92+ """Get a `Handle ` for the service side to use.
5193
5294 Returns:
5395 Object to send/receive messages with.
5496 """
5597 return self ._service_handle
56-
57-
58- class BidirectionalHandle (Sender [T ], Receiver [U ]):
59- """A handle to a [Bidirectional][frequenz.channels.Bidirectional] instance.
60-
61- It can be used to send/receive values between the client and service.
62- """
63-
64- def __init__ (self , sender : Sender [T ], receiver : Receiver [U ]) -> None :
65- """Create a `BidirectionalHandle` instance.
66-
67- Args:
68- sender: A sender to send values with.
69- receiver: A receiver to receive values from.
70- """
71- self ._sender = sender
72- self ._receiver = receiver
73-
74- async def send (self , msg : T ) -> bool :
75- """Send a value to the other side.
76-
77- Args:
78- msg: The value to send.
79-
80- Returns:
81- Whether the send was successful or not.
82- """
83- return await self ._sender .send (msg )
84-
85- async def ready (self ) -> None :
86- """Wait until the receiver is ready with a value."""
87- await self ._receiver .ready () # pylint: disable=protected-access
88-
89- def consume (self ) -> U :
90- """Return the latest value once `_ready` is complete.
91-
92- Returns:
93- The next value that was received.
94- """
95- return self ._receiver .consume () # pylint: disable=protected-access
0 commit comments