-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
588e554
commit 449a0c1
Showing
3 changed files
with
96 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
""" Asynchronous timer object """ | ||
import asyncio | ||
from typing import Callable, Optional | ||
|
||
|
||
class Timer: | ||
""" The timer object is used to have an abstraction for handling time | ||
dependend functionality. The timer works non-periodically. | ||
:param callback: an optional callback function called when the time | ||
`timeout` has passed after calling `.start()` or when | ||
calling `.end_early()` | ||
:param loop: optional asyncio event loop | ||
""" | ||
def __init__(self, callback: Optional[Callable[[], None]] = None, | ||
loop: Optional[asyncio.BaseEventLoop] = None): | ||
self._callback = callback | ||
self._handle = None # type: asyncio.Handle | ||
self._loop = loop or asyncio.get_event_loop() | ||
self._args = None | ||
|
||
def start(self, timeout: float, args=()) -> None: | ||
""" start the timer with given timeout. Optional arguments for the | ||
callback can be provided. When the timer is currently running, the timer | ||
will be re-set to the new timeout. | ||
:param timeout: time in seconds to the end of the timer | ||
:param args: optional tuple with arguments for the callback | ||
""" | ||
if self._handle: | ||
self._handle.cancel() | ||
|
||
self._args = args | ||
|
||
if timeout > 0: | ||
self._handle = self._loop.call_later(timeout, self._trigger) | ||
else: | ||
self._trigger() | ||
|
||
def change_arguments(self, args=()): | ||
""" Will chance the arguments for the scheduled callback | ||
:param args: Positional arguments | ||
""" | ||
self._args = args | ||
|
||
def cancel(self) -> None: | ||
""" Cancel the timer. An optional callback will not be called. """ | ||
|
||
if self._handle: | ||
self._handle.cancel() | ||
self._handle = None | ||
|
||
def end_early(self) -> None: | ||
""" immediate stopping the timer and call optional callback """ | ||
self._handle = None | ||
if self._handle and self._callback: | ||
self._callback(*self._args) | ||
|
||
def is_running(self) -> bool: | ||
""" tells if the timer is currently running | ||
:returns: boolean, True when timer is running | ||
""" | ||
return self._handle is not None | ||
|
||
def _trigger(self): | ||
""" internal method called when timer is finished """ | ||
self._handle = None | ||
if self._callback: | ||
self._callback(*self._args) | ||
|