Get rid of _Clock and move utility time-related functions to _time.py. (#2042)

* Remove _clock.py::sleep.

* Move _clock.py::get_time_no_wait to _time.py.

* Move _clock.py::get_time to _time.py.

* Remove async version of _time.py::get_time.

We started by removing '_time.py::get_time' because that was the async one and then I renamed 'get_time_no_wait' to 'get_time'.

* Make 'get_time' just an alias.
This commit is contained in:
Rodrigo Girão Serrão
2023-03-15 08:56:10 +00:00
committed by GitHub
parent c5f1cbd22c
commit 10a5d171eb
6 changed files with 20 additions and 68 deletions

View File

@@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Any, Callable, TypeVar
from typing_extensions import Protocol, runtime_checkable
from . import _clock
from . import _time
from ._callback import invoke
from ._easing import DEFAULT_EASING, EASING
from ._types import CallbackType
@@ -385,7 +385,7 @@ class Animator:
"""Get the current wall clock time, via the internal Timer."""
# N.B. We could remove this method and always call `self._timer.get_time()` internally,
# but it's handy to have in mocking situations
return _clock.get_time_no_wait()
return _time.get_time()
async def wait_for_idle(self) -> None:
"""Wait for any animations to complete."""

View File

@@ -1,57 +0,0 @@
import asyncio
from ._time import time
"""
A module that serves as the single source of truth for everything time-related in a Textual app.
Having this logic centralised makes it easier to simulate time in integration tests,
by mocking the few functions exposed by this module.
"""
# N.B. This class and its singleton instance have to be hidden APIs because we want to be able to mock time,
# even for Python modules that imported functions such as `get_time` *before* we mocked this internal _Clock.
# (so mocking public APIs such as `get_time` wouldn't affect direct references to then that were done during imports)
class _Clock:
async def get_time(self) -> float:
return time()
def get_time_no_wait(self) -> float:
return time()
async def sleep(self, seconds: float) -> None:
await asyncio.sleep(seconds)
_clock = _Clock()
def get_time_no_wait() -> float:
"""
Get the current wall clock time.
Returns:
The value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards.
"""
return _clock.get_time_no_wait()
async def get_time() -> float:
"""
Asynchronous version of `get_time`. Useful in situations where we want asyncio to be
able to "do things" elsewhere right before we fetch the time.
Returns:
The value (in fractional seconds) of a monotonic clock, i.e. a clock that cannot go backwards.
"""
return await _clock.get_time()
async def sleep(seconds: float) -> None:
"""
Coroutine that completes after a given time (in seconds).
Args:
seconds: The duration we should wait for before unblocking the awaiter
"""
return await _clock.sleep(seconds)

View File

@@ -42,3 +42,12 @@ else:
sleep_for = secs - 0.0005
if sleep_for > 0:
await asyncio_sleep(sleep_for)
get_time = time
"""Get the current wall clock (monotonic) time.
Returns:
The value (in fractional seconds) of a monotonic clock,
i.e. a clock that cannot go backwards.
"""

View File

@@ -4,7 +4,7 @@ import asyncio
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING
from . import _clock, events
from . import _time, events
from ._types import MessageTarget
from .events import MouseUp
@@ -26,7 +26,7 @@ class Driver(ABC):
self._debug = debug
self._size = size
self._loop = asyncio.get_running_loop()
self._mouse_down_time = _clock.get_time_no_wait()
self._mouse_down_time = _time.get_time()
self._down_buttons: list[int] = []
self._last_move_event: events.MouseMove | None = None

View File

@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, ClassVar
import rich.repr
from . import _clock
from . import _time
from ._context import active_message_pump
from ._types import MessageTarget as MessageTarget
from .case import camel_to_snake
@@ -34,7 +34,7 @@ class Message:
def __init__(self) -> None:
self._sender: MessageTarget | None = active_message_pump.get(None)
self.time: float = _clock.get_time_no_wait()
self.time: float = _time.get_time()
self._forwarded = False
self._no_default_action = False
self._stop_propagation = False

View File

@@ -13,7 +13,7 @@ from typing import Awaitable, Callable, Union
from rich.repr import Result, rich_repr
from . import _clock, events
from . import _time, events
from ._asyncio import create_task
from ._callback import invoke
from ._context import active_app
@@ -126,15 +126,15 @@ class Timer:
_repeat = self._repeat
_interval = self._interval
await self._active.wait()
start = _clock.get_time_no_wait()
start = _time.get_time()
while _repeat is None or count <= _repeat:
next_timer = start + ((count + 1) * _interval)
now = await _clock.get_time()
now = _time.get_time()
if self._skip and next_timer < now:
count += 1
continue
now = await _clock.get_time()
now = _time.get_time()
wait_time = max(0, next_timer - now)
if wait_time > 1 / 1000:
await sleep(wait_time)
@@ -142,7 +142,7 @@ class Timer:
count += 1
await self._active.wait()
if self._reset:
start = _clock.get_time_no_wait()
start = _time.get_time()
count = 0
self._reset = False
continue