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
158
|
# -*- coding: utf-8 -*-
"""
Copyright (c) 2003-2005 Gustavo Niemeyer <gustavo@niemeyer.net>
This module offers extensions to the standard Python
datetime module.
"""
__author__ = "Tomi Pieviläinen <tomi.pievilainen@iki.fi>"
__license__ = "Simplified BSD"
import datetime
import _thread
import signal
import time
class sched(object):
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(object):
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(object):
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(object):
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
|