Source code for chronometer

# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals

import sys

from monotonic import monotonic


__version__ = '1.0'
__all__ = ['Chronometer',
           'RelaxedStartChronometer',
           'RelaxedStopChronometer',
           'RelaxedChronometer',
           'ChronoRuntimeError',
           'ChronoAlreadyStartedError',
           'ChronoAlreadyStoppedError', ]


PY2 = sys.version_info[0] == 2


[docs]class ChronoRuntimeError(Exception): """Base exceptions for errors which happened inside Chronometer."""
[docs]class ChronoAlreadyStoppedError(ChronoRuntimeError): """Raised when trying to stop a stopped timer."""
[docs]class ChronoAlreadyStartedError(ChronoRuntimeError): """raised when trying to start a started timer."""
[docs]class Chronometer(object): """Simple timer meant to be used for measuring how much time has been spent in a certain code region. """ __slots__ = ('timer', 'since', 'until', ) def __init__(self, timer=monotonic): self.since, self.until, self.timer = None, None, timer def __enter__(self): return self.start() def __exit__(self, exc_type, exc_value, exc_traceback): self.stop() def __repr__(self): state = 'stopped' if self.stopped else 'started' return '<{0} {1} {2}>'.format(type(self).__name__, state, self.elapsed) def __format__(self, format_spec): v = int(self.elapsed) if format_spec[-1] == 'd' else self.elapsed return format(v, format_spec) def __float__(self): return self.elapsed def __bool__(self): return self.started if PY2: __nonzero__ = __bool__ def __str__(self): return '{0:.5f}s'.format(self.elapsed) if PY2: __unicode__ = __str__ __str__ = lambda self: self.__unicode__().encode('utf-8') def _set(self, since=None, until=None): self.since, self.until = since, until
[docs] def start(self): """Starts the timer. :return: Returns the timer itself. :rtype: Chronometer :raises TimerAlreadyStartedError: If the timer is already running. """ if self.started: raise ChronoAlreadyStartedError('Timer already started.') self._set(self.timer()) return self
[docs] def stop(self): """Stops the timer. :return: Time passed since the timer has been started in seconds. :rtype: float :raises TimerAlreadyStoppedError: If the timer is already stopped. """ if self.stopped: raise ChronoAlreadyStoppedError('Timer already stopped.') self.until = self.timer() return self.elapsed
[docs] def reset(self): """Resets the timer. :return: Elapsed time before the timer was reset. :rtype: float """ try: return self.elapsed finally: self._set(None if self.stopped else self.timer())
@property
[docs] def elapsed(self): """Returns time passed in seconds. :return: Time passed since the timer has been started in seconds. :rtype: float """ pit = self.timer() return (self.until or pit) - (self.since or pit)
@property
[docs] def stopped(self): """Returns if the timer is stopped or not. :return: `True` if the timer is stopped and `False` otherwise. :rtype: bool """ return self.since is None or self.until is not None
@property
[docs] def started(self): """Returns if the timer is running or not. :return: `True` if the timer is running and `False` otherwise. :rtype: bool """ return not self.stopped
[docs]class RelaxedStartChronometer(Chronometer): """Relaxed version which won't raise an exception on double starting the timer. """ __slots__ = []
[docs] def start(self): """Starts the timer or just returns if the timer is already running. :return: Returns the timer itself. :rtype: RelaxedStartChronometer """ try: return super(RelaxedStartChronometer, self).start() except ChronoAlreadyStartedError: return self
[docs]class RelaxedStopChronometer(Chronometer): """Relaxed version which won't raise an exception on double stopping the timer. """ __slots__ = []
[docs] def stop(self): """Stops the timer or just returns if the timer is already stopped. :return: Time passed since the timer has been started in seconds. :rtype: float """ try: return super(RelaxedStopChronometer, self).stop() except ChronoAlreadyStoppedError: return self.elapsed
[docs]class RelaxedChronometer(RelaxedStartChronometer, RelaxedStopChronometer): """Ultra relaxed version which won't throw any exceptions on its own. """ __slots__ = []

Related Topics