Skip to content
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

Add support for optional channels in Select #12

Closed
leandro-lucarella-frequenz opened this issue Sep 13, 2022 · 2 comments
Closed

Add support for optional channels in Select #12

leandro-lucarella-frequenz opened this issue Sep 13, 2022 · 2 comments
Labels
part:synchronization Affects the synchronization of multiple sources (`select`, `merge`) type:enhancement New feature or enhancement visitble to users
Milestone

Comments

@leandro-lucarella-frequenz
Copy link
Contributor

What's needed?

There might be cases when one wants to do a Select loop with some channels that are optional and if they are not present the handling of those channels will just not be used. Right now there is no trivial way to do this.

Proposed solution

Create a Select.with_optional() method like (maybe incomplete and untested):

   def with_optional(self, **optional_receivers: Optional[AsyncIterator[Any]]) -> Select:
       # TODO: check name clashing with self._receivers
       for name, recv in optional_receivers.items():
           self._result[name] = None
           if recv is None:
               continue
           self._receivers[name] = recv
           # can replace __anext__() to anext() (Only Python 3.10>=)
           msg = recv.__anext__()  # pylint: disable=unnecessary-dunder-call
           self._pending.add(asyncio.create_task(msg, name=name))  # type: ignore

       return self

With the intended use:

# chan1 can't be None, chan_none can
select = Select(chan1=chan1).with_optional(chan_none=None)
while await select.ready():
    if select.chan1:
        pass
    elif select.chan_none:  # will always be None if chan_none is None
        pass

Use cases

Yet to be seen

Alternatives and workarounds

  1. Handle the optional channel explicitly:
chan_none = None
optional_channels = {}
if chan_none is not None:
    optional_channels["chan_none"] = chan_none
select = Select(chan1=chan1, **optional_channels)
while await select.ready():
    if select.chan1:  # OK
        pass
    elif chan_none and select.chan_none:  # OK too
        pass
  1. Create a dummy channel, use the receiver in the Select and never call send to the sender of the channel.
chan_none = Broadcast[int]("chan_none").get_receiver()
select = Select(chan1=chan1, chan_none=chan_none)
while await select.ready():
    if select.chan1:  # OK
        pass
    elif select.chan_none:  # OK too, will never be True
        pass

Additional context

No response

@leandro-lucarella-frequenz leandro-lucarella-frequenz added type:enhancement New feature or enhancement visitble to users part:channels Affects channels implementation labels Sep 13, 2022
@leandro-lucarella-frequenz leandro-lucarella-frequenz added part:synchronization Affects the synchronization of multiple sources (`select`, `merge`) and removed part:channels Affects channels implementation labels Nov 3, 2022
@leandro-lucarella-frequenz
Copy link
Contributor Author

This will probably be closed in favor of #29, as we don't want to add new ways to misuse Select, but I will leave it open until the docs are ready just in case.

@llucax llucax added this to the v1.1.0 milestone Aug 7, 2023
@llucax
Copy link
Contributor

llucax commented Nov 9, 2023

Superseded by #116.

@llucax llucax closed this as not planned Won't fix, can't repro, duplicate, stale Nov 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
part:synchronization Affects the synchronization of multiple sources (`select`, `merge`) type:enhancement New feature or enhancement visitble to users
Projects
Development

No branches or pull requests

2 participants