-
-
Notifications
You must be signed in to change notification settings - Fork 343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
open_memory_channel(): return a named tuple #1771
base: main
Are you sure you want to change the base?
Conversation
trio/_channel.py
Outdated
send_channel: "MemorySendChannel" | ||
receive_channel: "MemoryReceiveChannel" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opted for these qualified names rather than just send
and receive
to avoid the awkwardness of send()
and receive()
also being the primary methods:
channel_pair = open_memory_channel()
await channel_pair.send.send()
Assigning the send and receive channels to separate variables usually | ||
produces the most readable code. However, in situations where the pair | ||
is preserved-- such as a collection of memory channels-- prefer named tuple | ||
access (``pair.send_channel``, ``pair.receive_channel``) over indexed access | ||
(``pair[0]``, ``pair[1]``). | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please note this point
It's why I didn't go crazy converting all the docs and tests to named tuple access-- tuple destructuring is more readable for local code dealing with a single memory channel.
However the named tuple still wins when you're dealing with many channels and keep the pairs intact.
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #1771 +/- ##
==========================================
- Coverage 99.18% 99.12% -0.07%
==========================================
Files 115 115
Lines 17594 17625 +31
Branches 3142 3146 +4
==========================================
+ Hits 17451 17470 +19
- Misses 99 111 +12
Partials 44 44
|
I like this. @njsmith thoughts? I often find myself wanting a single object that includes both ends of the channel, like the old One step further would make the returned object an |
d4a8db0
to
4e7a466
Compare
It seems confusing for API users as it's adding another layer (where a pure named tuple really isn't). Now there are multiple ways to do the same thing ( I'd rather accept the memory channel interface as somewhat low level: it does expose the halves, though in many uses that isn't needed. As far as wrapping that in a simpler API having less features, defer to the application code or a utility library. |
partially addresses python-trio#719
4e7a466
to
9041145
Compare
As a straw man, here are some of the queue-like methods: async def send(self, value):
await self.send_channel.send(value)
def send_nowait(self, value):
self.send_channel.send_nowait(value)
async def receive(self):
return await self.receive_channel.receive()
def receive_nowait(self):
return self.receive_channel.receive_nowait()
async def aclose(self):
await self.send_channel.aclose()
await self.receive_channel.aclose() What's notably missing is receive iteration. But adding that as the default iterator (as Queue once did) would conflict with tuple's iterator. And going down this road, I would just like the class to be named I'm looking at this for our app and/or |
Another vague plan for memory channels is that I feel like they should return a pair of bidirectional channels, so you can send messages both ways. It would dramatically reduce the bookkeeping you need in that case now to juggle 4 different handles, and if you're doing unidirectional communication then it doesn't affect you at all – you can just ignore the extra methods. Also, I feel like it will just be easier to read code where the channels are named based on the endpoint, rather than based on directionality. But, if we make memory channels symmetric like that, then it conflicts with the Another option to throw into the mix: |
So what is |
It would be the equivalent of |
Would it be OK for the instance
What does the construction look like? what are the additional attributes and methods in that case? |
Doesn't |
In the bidirectional channels case, isn't there going to be an object wrapping two memory channels (or one side of the two channels)? That would be a potential place to introduce alternate naming. |
It would be a
Yeah, that's how it works currently, but I'm talking about a potential future where it returns |
attempted in my case I'm needing the |
(Merged master into this branch to get the new Travis check, all checks pass now) |
Hmm that's an issue. The named tuple needs to be generic, but that only works in 3.11+, unless you import |
Can we do the trick we did elsewhere where we only do |
In this case it doesn't really work, because users need to be able to subscript the class for their own type hints. |
partially addresses #719