Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
devtools / timer.py
Size: Mime:
from time import time

__all__ = ('Timer',)


class TimerResult:
    def __init__(self, name=None, verbose=True):
        self._name = name
        self.verbose = verbose
        self.finish = None
        self.start = time()

    def capture(self):
        self.finish = time()

    def elapsed(self):
        if self.finish:
            return self.finish - self.start
        else:
            return -1

    def str(self, dp=3):
        if self._name:
            return f'{self._name}: {self.elapsed():0.{dp}f}s elapsed'
        else:
            return f'{self.elapsed():0.{dp}f}s elapsed'

    def __str__(self):
        return self.str()


_SUMMARY_TEMPLATE = '{count} times: mean={mean:0.{dp}f}s stdev={stddev:0.{dp}f}s min={min:0.{dp}f}s max={max:0.{dp}f}s'


class Timer:
    def __init__(self, name=None, verbose=True, file=None, dp=3):
        self.file = file
        self.dp = dp
        self._name = name
        self._verbose = verbose
        self.results = []

    def __call__(self, name=None, verbose=None):
        if name:
            self._name = name
        if verbose is not None:
            self._verbose = verbose
        return self

    def start(self, name=None, verbose=None):
        self.results.append(TimerResult(name or self._name, self._verbose if verbose is None else verbose))
        return self

    def capture(self, verbose=None):
        r = self.results[-1]
        r.capture()
        print_ = r.verbose if verbose is None else verbose
        if print_:
            print(r.str(self.dp), file=self.file, flush=True)
        return r

    def summary(self, verbose=False):
        times = set()
        for r in self.results:
            if not r.finish:
                r.capture()
            if verbose:
                print(f'    {r.str(self.dp)}', file=self.file)
            times.add(r.elapsed())

        if times:
            from statistics import mean, stdev

            print(
                f'{len(times)} times: '
                f'mean={mean(times):0.{self.dp}f}s '
                f'stdev={stdev(times) if len(times) > 1 else 0:0.{self.dp}f}s '
                f'min={min(times):0.{self.dp}f}s '
                f'max={max(times):0.{self.dp}f}s',
                file=self.file,
                flush=True,
            )
        else:
            raise RuntimeError('timer not started')
        return times

    def __enter__(self):
        self.start()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.capture()