-
Notifications
You must be signed in to change notification settings - Fork 9
Improve documentation of the frequenz.channels.experimental.Pipe
#407
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
Improve documentation of the frequenz.channels.experimental.Pipe
#407
Conversation
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.
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
Comments suppressed due to low confidence (1)
src/frequenz/channels/experimental/_pipe.py:33
- The code snippet references 'Receiver[int]' without importing 'Receiver'. Consider adding the appropriate import (e.g., from frequenz.channels import Receiver) to avoid confusion.
async def create_forwarding_pipe(receiver: Receiver[int]) -> AsyncIterator[Broadcast[int]]:
66559d7 to
aca4789
Compare
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.
All comments are minor, I think the example is good enough to go as it is, just ideas of possible improvements.
| from frequenz.channels import Broadcast, Pipe, Receiver | ||
| @asynccontextmanager | ||
| async def create_forwarding_pipe( |
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.
Nitpick: I would try to use the pattern used by the Python library, like closing. Maybe call this forwarding_channel (as you are also returning the channel, not the pipe)?
Then:
async with forwarding_channel(
source_channel.new_receiver()
) as destination_channel:
receiver = destination_channel.new_receiver()
await source_sender.send(10)
assert await receiver.receive() == 10| async with create_forwarding_pipe( | ||
| source_channel.new_receiver() | ||
| ) as forwarding_channel: | ||
| receiver = forwarding_channel.new_receiver() |
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 guess here you don't close the receiver because you are closing the channel? Maybe this needs a note because it might not be obvious? I also wonder if, at least for this example, it wouldn't make more sense to return a new receiver instead of the whole channel, and explicitly close the receiver in the async context manager, to make it more clear/explicit.
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 didn't close it because it goes with with not async with and I simply forgot...
RELEASE_NOTES.md
Outdated
| ## Upgrading | ||
|
|
||
| - Some minimal dependencies have been bumped, so you might need to adjust your dependencies accordingly. | ||
| - Improve documentation of the frequenz.channels.experimental.Pipe |
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.
This is not really an upgrade step, so I would put it into New Features (even if it is not a new feature either :D, sometimes I create a new section # Enhancements in these cases, but I think it can also be left out of the release notes, as I don't think anyone will go check out the Pipe docs just because it is in the changelog).
|
If we merge this, we can even simplify the example further and only use |
|
Ok prepared 2 examples:
from contextlib import asynccontextmanager, closing, aclosing
from typing import AsyncIterator
from frequenz.channels import Broadcast, Pipe, Receiver
@asynccontextmanager
async def new_forwarding_channel(
receiver: Receiver[int],
) -> AsyncIterator[Broadcast[int]]:
forwarding_channel: Broadcast[int] = Broadcast(name="forwarded channel")
forwarding_sender = forwarding_channel.new_sender()
try:
async with Pipe(receiver, forwarding_sender):
yield forwarding_channel
finally:
receiver.close()
await forwarding_channel.aclose()
async with (
aclosing(Broadcast(name="source channel")) as source_channel,
new_forwarding_channel(source_channel.new_receiver()) as forwarding_channel,
):
with closing(forwarding_channel.new_receiver()) as receiver:
source_sender = source_channel.new_sender()
await source_sender.send(10)
assert await receiver.receive() == 10
from contextlib import closing, aclosing
from frequenz.channels import Broadcast, Pipe, Receiver
async with aclosing(Broadcast(name="source channel")) as source_channel:
with closing(source_channel.new_receiver()) as source_receiver:
async with (
aclosing(Broadcast(name="forwarded channel")) as forwarding_channel,
Pipe(source_receiver, forwarding_channel.new_sender())
):
with closing(forwarding_channel.new_receiver()) as receiver:
source_sender = source_channel.new_sender()
await source_sender.send(10)
assert await receiver.receive() == 10The first one has more lines, but took me much less time to write and understand |
aca4789 to
e7069da
Compare
|
It is a new version with AsyncExitStack :) |
e7069da to
8398261
Compare
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.
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/frequenz/channels/experimental/_pipe.py:38
- Consider using 'aclosing' instead of 'closing' when entering the async context for 'new_receiver()' (if it is an asynchronous context manager) to ensure proper async cleanup.
source_receiver = await stack.enter_async_context(closing(source_channel.new_receiver()))
| source_receiver = await stack.enter_async_context( | ||
| closing(source_channel.new_receiver())) |
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.
Does this really works? AsycnExitStack() also provides the methods provided by ExitStack, so you should probably use enter_context() here that the context manager is sync.
| source_receiver = await stack.enter_async_context( | |
| closing(source_channel.new_receiver())) | |
| source_receiver = await stack.enter_context( | |
| closing(source_channel.new_receiver())) |
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.
Yea sorry I assumed the code in Example is executed. (because they are showed in the pytest summary as tests.
I just found out only imports are checked. Fixed
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.
pylint is also ran, but the code itself isn't, nor mypy or other lint tools.
| aclosing(Broadcast(name="forwarding channel"))) | ||
| await stack.enter_async_context(Pipe(source_receiver, forwarding_channel.new_sender())) | ||
| receiver = await stack.enter_async_context(closing(forwarding_channel.new_receiver())) |
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.
And here.
| receiver = await stack.enter_async_context(closing(forwarding_channel.new_receiver())) | |
| receiver = await stack.enter_context(closing(forwarding_channel.new_receiver())) |
8398261 to
b2e2f66
Compare
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.
Thanks for taking care of this!
Documentation shows how to create Pipe inside context manager to cleanup the resources when context is exited. Signed-off-by: Elzbieta Kotulska <[email protected]>
b2e2f66 to
9b4b7d7
Compare
Documentation shows how to create Pipe inside context manager to cleanup the resources when context is exited.