Welcome, guest | Sign In | My Account | Store | Cart

Sometimes it's desirable to run a function not often than some time interval. The timeguard decorator below lets do exactly that. See the doctest for details.

Python, 56 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from datetime import datetime


def timeguard(time_interval, default=None):
    """Run decorated function not often than time_interval.

    If the function is called more often than time_interval
    run the default function instead if it's not None.

    >>> import time
    >>> from datetime import timedelta

    Let's define a test class first:

    >>> class TimeGuardTest(object):
    ...
    ...     def dot(self):
    ...         print ".",
    ...
    ...     @timeguard(timedelta(seconds=3), default=dot)
    ...     def plus(self):
    ...         print "+",
    ...
    ...     @timeguard(timedelta(seconds=2))
    ...     def minus(self):
    ...         print "-",
    ...
    ...     def run(self):
    ...         for i in range(6):
    ...             self.plus()
    ...             self.minus()
    ...             time.sleep(1.1)

    Now run the test and see results:

    >>> test = TimeGuardTest()
    >>> test.run()
    + - . . - + . - .
    """
    def decorator(function):
        # For first time always run the function
        function.__last_run = datetime.min
        def guard(*args, **kwargs):
            now = datetime.now()
            if now - function.__last_run >= time_interval:
                function.__last_run = now
                return function(*args, **kwargs)
            elif default is not None:
                return default(*args, **kwargs)
        return guard
    return decorator


if __name__ == "__main__":
    import doctest
    doctest.testmod()