Repository navigation
Expand file tree
/
Copy pathschedulee.py
More file actions
111 lines (83 loc) · 2.79 KB
/
Copy pathschedulee.py
File metadata and controls
111 lines (83 loc) · 2.79 KB
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
import logging
import functools
import datetime
logger = logging.getLogger('schedule')
class ScheduleError(Exception):
'''base schedule error'''
class ScheduleValueError(ScheduleError):
'''base schedule value error'''
class IntervalError(ScheduleError):
'''an improper interval was used'''
class Scheduler():
def __init__(self):
self.jobs = []
def every(self,interval):
job = Job(interval,self)
return job
def run_pending(self):
runnable_jobs = (job for job in self.jobs if job.should_run)
for job in sorted(runnable_jobs):
self._run_job(job)
def _run_job(self,job):
job.run()
class Job():
def __init__(self,interval,scheduler):
self.interval = interval
self.scheduler = scheduler
self.period = None
self.last_run =None
self.next_run = None
self.job_func = None
self.unit = None
def __lt__ (self,other):
return self.next_run < other.next_run
@property
def second(self):
if self.interval != 1 :
raise IntervalError("use seconds instead of second")
return self.seconds
@property
def seconds(self):
self.unit = 'seconds'
return self
@property
def minute(self):
if self.interval != 1 :
raise IntervalError("use minutes instead of second")
return self.seconds
@property
def minutes(self):
self.unit = 'minutes'
return self
def do(self, job_func, *args, **kwargs):
self.job_func = functools.partial(job_func, *args, **kwargs)
functools.update_wrapper(self.job_func, job_func)
self._schedule_next_run()
if self.scheduler is None:
raise ScheduleError(
"unable to add job to schedule,"
"job is not associated with an scheduler"
)
self.scheduler.jobs.append(self)
return self
def _schedule_next_run(self):
if self.unit not in ('seconds', 'minutes', 'hours', 'days', 'weeks'):
raise ScheduleValueError("invalid unit")
interval = self.interval
self.period = datetime.timedelta(**{self.unit:interval})
self.next_run = datetime.datetime.now() + self.period
@property
def should_run(self):
assert self.next_run is not None, "must run _schedule_next_run first"
return datetime.datetime.now() >= self.next_run
def run(self):
logger.debug(f'running job {self}')
ret = self.job_func()
self.last_run = datetime.datetime.now()
self._schedule_next_run()
return ret
default_schedular = Scheduler()
def every(interval=1):
return default_schedular.every(interval)
def run_pending():
default_schedular.run_pending()