Source code for timing

"""
Simple code performance timer that allows for the execution time to be recorded

**Credit:**

- This is a modified version of Paul's and Nicojo's answers on stackoverflow.
- Reference: http://stackoverflow.com/questions/1557571/how-to-get-time-of-a-python-program-execution

**Usage Case:**

>>> # At the beginning of the chunk of code to be timed.
>>> from blowdrycss.timing import Timer
>>> timer = Timer()
>>> timer.report()
Completed @ 2015-12-14 16:56:08.665080
=======================================
It took: 0.17296 seconds
=======================================

"""
# python 2
from __future__ import absolute_import, print_function, division, unicode_literals
from builtins import str

# builtins
from time import time
from datetime import timedelta, datetime

# custom
import blowdrycss_settings as settings

__author__ = 'chad nelson'
__project__ = 'blowdrycss'


[docs]class Timer(object): """ A performance Timer that reports the amount of time it took to run a block of code. | **Parameters:** | **start** (*time*) -- Time that the program started. | **end** (*time*) -- Time that the program ended. :return: None **Example** >>> from blowdrycss.timing import Timer >>> timer = Timer() >>> timer.report() Completed 2015-12-14 16:56:08.665080 ===================================== It took: 0.17296 seconds ===================================== >>> timer.reset() # Resets start time to now. >>> timer.report() Completed 2015-12-14 17:05:12.164030 ===================================== It took: 1.45249 seconds ===================================== """ def __init__(self): self.start = time() self.end = time()
[docs] @staticmethod def seconds_to_string(seconds_elapsed=0.00): """ Converts the amount of time elapsed to seconds_elapsed, and returns it as a string. :type seconds_elapsed: float :param seconds_elapsed: A time() value in units of seconds_elapsed. :return: (*str*) -- Returns a string version of the total time elapsed in seconds_elapsed. """ return str(timedelta(seconds=seconds_elapsed).total_seconds())
@property def elapsed(self): """ Calculates the amount of time elapsed (delta T) by subtracting start ``time()`` from end ``time()``. **Math:** elapsed = delta T = end - start :return: (*str*) -- Returns delta T in units of seconds as a string. """ seconds_elapsed = self.end - self.start return self.seconds_to_string(seconds_elapsed=seconds_elapsed)
[docs] def print_time(self): """ Prints temporal metadata to the console. Including the completion timestamp and delta T in seconds. :return: None """ completed_at = '\nCompleted ' + str(datetime.now()) border = '=' * len(completed_at) print(str(completed_at)) print(str(border)) print('It took: ' + self.elapsed + 'seconds') print(str(border))
[docs] def report(self): """ Sets ``end`` time and prints the time elapsed (delta T). Calls ``print_time()``, and prints temporal metadata. :return: None """ self.end = time() self.print_time()
[docs]class LimitTimer(object): """ Timer governs when to perform a full and comprehensive run of blowdry.parse(). .. note:: This is independent of file modification watchdog triggers which only scan the file(s) that changed since the last run. ** Why is a LimitTimer needed? ** *Understanding the Truth Table* #. The project only contains two files: File 1 and File 2. #. Each file either contains the CSS class selector 'blue' or not i.e. set(). #. File 2 is modified. Either the class ``blue`` is added or removed i.e. set(). #. X means don't care whether the file contains blue or set(). #. Case #3 is the reason why the LimitTimer is required. The css class selector ``blue`` was only defined in File 2. Then blue was removed from File 2. Since blue existed in the combined class_set before File 2 was modified, it will remain in the combined class_set after the union with set(). This is undesirable in Case #3 since ``blue`` is not used anymore in either of the two files. The LimitTimer runs periodically to clear these unused selectors. +--------+------------------+------------------+--------------------+-----------------+--------------------+ | Case # | File 1 class_set | File 2 class_set | Combined class_set | File 2 modified | Combined class_set | +========+==================+==================+====================+=================+====================+ | 1 | blue | blue | blue | set() | blue | +--------+------------------+------------------+--------------------+-----------------+--------------------+ | 2 | blue | set() | blue | X | blue | +--------+------------------+------------------+--------------------+-----------------+--------------------+ | 3 | set() | blue | blue | set() | blue | +--------+------------------+------------------+--------------------+-----------------+--------------------+ | 4 | set() | set() | set() | blue | blue | +--------+------------------+------------------+--------------------+-----------------+--------------------+ | 5 | set() | set() | set() | set() | set() | +--------+------------------+------------------+--------------------+-----------------+--------------------+ ** Another reason why the LimitTimer is needed. ** On windows and mac watchdog on_modify event gets triggered twice on save. In order to prevent a duplicate run for the same change or set of changes this class is implemented. It can also depend on the IDE being used since some IDEs auto-save. | **Members:** | **time_limit** (*str*) -- Number of seconds that must pass before the limit is exceeded. Default is settings.time_limit. | **start_time** (*str*) -- Time that the timer started. :return: None **Example** >>> from blowdrycss.timing import LimitTimer >>> limit_timer = LimitTimer() >>> if limit_timer.limit_exceeded: >>> print("30 minutes elapses.") >>> limit_timer.reset() """ def __init__(self): self._time_limit = settings.time_limit self.start_time = time() @property def time_limit(self): """ Getter returns ``_time_limit``. :return: (*int*) -- Returns ``_time_limit``. """ return self._time_limit @time_limit.setter def time_limit(self, custom_limit): """ Set time_limit in units of seconds. :type custom_limit: int :param custom_limit: Time limit in units of seconds. :return: None """ self._time_limit = custom_limit @property def limit_exceeded(self): """ Compares the current time to the start time, and returns True if ``self.time_limit`` is exceeded and False otherwise. :return: (*bool*) -- Returns True if ``self.time_limit`` is exceeded and False otherwise. """ return time() - self.start_time >= self.time_limit
[docs] def reset(self): """ Resets ``self.start`` to the current time. :return: None """ self.start_time = time()