Skip to content

Commit

Permalink
uselect: Rewrite the docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
laurensvalk committed Dec 1, 2022
1 parent 6f55e90 commit 236ce41
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 62 deletions.
35 changes: 35 additions & 0 deletions doc/main/micropython/uselect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,38 @@
=================================

.. automodule:: uselect
:no-members:

.. rubric:: Poll instance and class

.. autofunction:: poll

.. autoclass:: Poll
:no-members:

.. automethod:: register

.. automethod:: unregister

.. automethod:: modify

.. automethod:: poll

.. automethod:: ipoll

.. rubric:: Event mask flags

.. autodata:: POLLIN

.. autodata:: POLLOUT

.. autodata:: POLLERR

.. autodata:: POLLHUP

Examples
---------------

See the `projects website`_ for a demo that uses this module.

.. _projects website: https://pybricks.com/projects/tutorials/wireless/hub-to-device/pc-keyboard/
8 changes: 8 additions & 0 deletions doc/main/micropython/usys.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ This MicroPython module is a subset of the `sys module`_ in Python.
.. autodata:: usys.stderr
:annotation:



Examples
---------------

See the `projects website`_ for a demo that uses this module.

.. _projects website: https://pybricks.com/projects/tutorials/wireless/hub-to-device/pc-keyboard/
.. _sys module: https://docs.python.org/3.5/library/sys.html
138 changes: 76 additions & 62 deletions src/uselect/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

"""
This module provides functions to efficiently wait for events on multiple streams.
.. note:: This module is not available on the BOOST Move hub.
"""

from typing import IO, Iterator, List, Tuple, overload
Expand All @@ -25,61 +23,58 @@

POLLERR: int
"""
Error condition happened on the associated stream.
Error condition happened on the associated stream. Should be handled explicitly
or else further invocations of :meth:`poll` may return right away.
"""

POLLHUP: int
"""
Hang up happened on the associated stream.
Hang up happened on the associated stream. Should be handled explicitly
or else further invocations of :meth:`poll` may return right away.
"""


def poll() -> "Poll":
"""
Creates an instance of the Poll class.
"""


# skipping def select(...)


class Poll:
@overload
def register(self, obj: IO) -> None:
...

@overload
def register(self, obj: IO, eventmask: int) -> None:
...

def register(self, obj: IO, eventmask: int) -> None:
def register(self, object: IO, eventmask: int) -> None:
"""
Register `stream` ``obj`` for polling. ``eventmask`` is logical OR of:
* :data:`POLLIN`
* :data:`POLLOUT`
register(object, eventmask=POLLOUT | POLLOUT)
Note that flags like :data:`POLLHUP` and :data:`POLLERR` are
*not* valid as input eventmask (these are unsolicited events which
will be returned from :meth:`poll` regardless of whether they are asked
for). This semantics is per POSIX.
Register a stream object for polling. The stream object will now be
monitored for events. If an event happens, it becomes part of the
return value of :meth:`poll`.
``eventmask`` defaults to ``POLLIN | POLLOUT``.
If this method is called again for the same stream object, the object
will not be registered again, but the ``eventmask`` flags will be
updated, as if calling :meth:`modify()`.
It is OK to call this function multiple times for the same ``obj``.
Successive calls will update ``obj``'s eventmask to the value of
``eventmask`` (i.e. will behave as :meth:`modify()`).
Arguments:
object (FileIO): Stream to be registered for polling.
eventmask (int): Which events to use. Should be ``POLLIN``,
``POLLOUT``, or their logical disjunction: ``POLLIN | POLLOUT``.
"""

def unregister(self, obj: IO) -> None:
def unregister(self, object: IO) -> None:
"""
Unregister ``obj`` from polling.
unregister(poll)
Unregister an object from polling.
Arguments:
object (FileIO): Stream to be unregistered from polling.
"""

def modify(self, obj: IO, eventmask: int) -> None:
"""
Modify the ``eventmask`` for ``obj``. If ``obj`` is not registered, ``OSError``
is raised with error of ``ENOENT``.
modify(object, eventmask)
Modifies the event mask for the stream object.
Arguments:
object (FileIO): Stream to be registered for polling.
eventmask (int): Which events to use.
Raises:
``OSError``: If the object is not registered. The error is ``ENOENT``.
"""

@overload
Expand All @@ -92,21 +87,21 @@ def poll(self, timeout: int) -> List[Tuple[IO, int]]:

def poll(self, timeout: int = -1, /) -> List[Tuple[IO, int]]:
"""
Wait for at least one of the registered objects to become ready or have an
exceptional condition, with optional timeout in milliseconds (if ``timeout``
arg is not specified or -1, there is no timeout).
Returns list of (``obj``, ``event``, ...) tuples. There may be other elements in
tuple, depending on a platform and version, so don't assume that its size is 2.
The ``event`` element specifies which events happened with a stream and
is a combination of ``POLL*`` constants described above. Note that
flags :data:`POLLHUP` and :data:`POLLERR` can be returned at any time
(even if were not asked for), and must be acted on accordingly (the
corresponding stream unregistered from poll and likely closed), because
otherwise all further invocations of :meth:`poll` may return immediately with
these flags set for this stream again.
In case of timeout, an empty list is returned.
poll(timeout=-1) -> List[Tuple[FileIO, int]]
Wait until at least one of the registered objects has a new event or
exceptional condition ready to be handled.
Arguments:
timeout (int): Timeout in milliseconds. Choose ``0`` to return
immediately or choose ``-1`` to wait indefinitely.
Returns:
A list of tuples. There is one (``object``, ``eventmask``, ...)
tuple for each object with an event, or no tuples if there are no
events to be handled. The ``eventmask`` value
is a combination of poll flags to indicate what happened. This may
include ``POLLERR`` and ``POLLHUP`` even if they were not registered.
"""

@overload
Expand All @@ -123,13 +118,32 @@ def ipoll(self, timeout: int, flags: int) -> Iterator[Tuple[IO, int]]:

def ipoll(self, timeout: int = -1, flags: int = 0, /) -> Iterator[Tuple[IO, int]]:
"""
Like :meth:`poll`, but instead returns an iterator which yields a
`callee-owned tuple`. This function provides an efficient, allocation-free
way to poll on streams.
If ``flags`` is 1, one-shot behavior for events is employed: streams for
which events happened will have their event masks automatically reset
(equivalent to ``poll.modify(obj, 0)``), so new events for such a stream
won't be processed until new mask is set with :meth:`modify`. This
behavior is useful for asynchronous I/O schedulers.
ipoll(timeout=-1, flags=1) -> Iterator[Tuple[FileIO, int]]
First, just like :meth:`poll`, wait until at least one of the registered
objects has a new event or exceptional condition ready to be handled.
But instead of a list, this method returns an iterator for improved
efficiency. The iterator yields one (``object``, ``eventmask``, ...)
tuple at a time, and overwrites it when yielding the next value. If you
need the values later, make sure to copy them explicitly.
Arguments:
timeout (int): Timeout in milliseconds. Choose ``0`` to return
immediately or choose ``-1`` to wait indefinitely.
flags (int): If set to ``1``, one-shot behavior for events is
employed. This means that streams for which events happened
will have their event masks automatically reset using
``poll.modify(obj, 0)``. This way, new events for such a stream
won't be processed until a new mask is set with :meth:`modify`,
which is useful for asynchronous I/O schedulers.
"""


def poll() -> Poll:
"""
Creates an instance of the :class:`Poll` class.
Returns:
The :class:`Poll` instance.
"""

0 comments on commit 236ce41

Please sign in to comment.