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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
"""
Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard python 2.3+
datetime module.
"""
__author__ = "Gustavo Niemeyer <gustavo@niemeyer.net>"
__license__ = "PSF License"
import datetime
import thread
import signal
import time
class sched:
def __init__(self, rrule,
tolerance=None, last=None,
execute=None, args=None, kwargs=None):
self._rrule = rrule
if tolerance:
self._tolerance = datetime.timedelta(seconds=tolerance)
else:
self._tolerance = None
self._last = last
self._execute = execute
self._args = args or ()
self._kwargs = kwargs or {}
def last(self):
return self._last
def next(self, now=None):
if not now:
now = datetime.datetime.now()
return self._rrule.after(now)
def check(self, now=None, readonly=False):
if not now:
now = datetime.datetime.now()
item = self._rrule.before(now, inc=True)
if (item is None or item == self._last or
(self._tolerance and item+self._tolerance < now)):
return None
if not readonly:
self._last = item
if self._execute:
self._execute(*self._args, **self._kwargs)
return item
class schedset:
def __init__(self):
self._scheds = []
def add(self, sched):
self._scheds.append(sched)
def next(self, now=None):
if not now:
now = datetime.datetime.now()
res = None
for sched in self._scheds:
next = sched.next(now)
if next and (not res or next < res):
res = next
return res
def check(self, now=None, readonly=False):
if not now:
now = datetime.datetime.now()
res = False
for sched in self._scheds:
if sched.check(now, readonly):
res = True
return res
class schedthread:
def __init__(self, sched, lock=None):
self._sched = sched
self._lock = lock
self._running = False
def running(self):
return self._running
def run(self):
self._running = True
thread.start_new_thread(self._loop, ())
def stop(self):
self._running = False
def _loop(self):
while self._running:
if self._lock:
self._lock.acquire()
now = datetime.datetime.now()
self._sched.check(now)
if self._lock:
self._lock.release()
seconds = _seconds_left(self._sched.next(now))
if seconds is None:
self._running = False
break
if self._running:
time.sleep(seconds)
class schedalarm:
def __init__(self, sched, lock=None):
self._sched = sched
self._lock = lock
self._running = False
def running(self):
return self._running
def run(self):
self._running = True
signal.signal(signal.SIGALRM, self._handler)
self._handler(None, None)
def stop(self):
self._running = False
def _handler(self, sig, frame):
while self._running:
if self._lock:
self._lock.acquire()
now = datetime.datetime.now()
self._sched.check(now)
if self._lock:
self._lock.release()
if self._running:
seconds = _seconds_left(self._sched.next(now))
if seconds:
signal.alarm(seconds)
break
elif seconds is None:
self._running = False
break
def _seconds_left(next):
if not next:
return None
now = datetime.datetime.now()
delta = next-now
seconds = delta.days*86400+delta.seconds
if seconds < 0:
seconds = 0
return seconds
|