75 lines
2.0 KiB
Python
75 lines
2.0 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from time import monotonic
|
||
|
|
from typing import Callable
|
||
|
|
|
||
|
|
import rich.repr
|
||
|
|
|
||
|
|
|
||
|
|
@rich.repr.auto(angular=True)
|
||
|
|
class Clock:
|
||
|
|
"""An object to get relative time.
|
||
|
|
|
||
|
|
The `time` attribute of clock will return the time in seconds since the
|
||
|
|
Clock was created or reset.
|
||
|
|
|
||
|
|
"""
|
||
|
|
|
||
|
|
def __init__(self, *, get_time: Callable[[], float] = monotonic) -> None:
|
||
|
|
"""Create a clock.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
get_time: A callable to get time in seconds.
|
||
|
|
start: Start the clock (time is 0 unless clock has been started).
|
||
|
|
"""
|
||
|
|
self._get_time = get_time
|
||
|
|
self._start_time = self._get_time()
|
||
|
|
|
||
|
|
def __rich_repr__(self) -> rich.repr.Result:
|
||
|
|
yield self.time
|
||
|
|
|
||
|
|
def clone(self) -> Clock:
|
||
|
|
"""Clone the Clock with an independent time."""
|
||
|
|
return Clock(get_time=self._get_time)
|
||
|
|
|
||
|
|
def reset(self) -> None:
|
||
|
|
"""Reset the clock."""
|
||
|
|
self._start_time = self._get_time()
|
||
|
|
|
||
|
|
@property
|
||
|
|
def time(self) -> float:
|
||
|
|
"""Time since creation or reset."""
|
||
|
|
return self._get_time() - self._start_time
|
||
|
|
|
||
|
|
|
||
|
|
class MockClock(Clock):
|
||
|
|
"""A mock clock object where the time may be explicitly set."""
|
||
|
|
|
||
|
|
def __init__(self, time: float = 0.0) -> None:
|
||
|
|
"""Construct a mock clock."""
|
||
|
|
self._time = time
|
||
|
|
super().__init__(get_time=lambda: self._time)
|
||
|
|
|
||
|
|
def clone(self) -> MockClock:
|
||
|
|
"""Clone the mocked clock (clone will return the same time as original)."""
|
||
|
|
clock = MockClock(self._time)
|
||
|
|
clock._get_time = self._get_time
|
||
|
|
clock._time = self._time
|
||
|
|
return clock
|
||
|
|
|
||
|
|
def reset(self) -> None:
|
||
|
|
"""A null-op because it doesn't make sense to reset a mocked clock."""
|
||
|
|
|
||
|
|
def set_time(self, time: float) -> None:
|
||
|
|
"""Set the time for the clock.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
time: Time to set.
|
||
|
|
"""
|
||
|
|
self._time = time
|
||
|
|
|
||
|
|
@property
|
||
|
|
def time(self) -> float:
|
||
|
|
"""Time since creation or reset."""
|
||
|
|
return self._get_time()
|