Skip to content

Commit eca91f8

Browse files
fixing cron conversion (#147)
fixing cron conversion
1 parent 2b6fc78 commit eca91f8

File tree

3 files changed

+58
-30
lines changed

3 files changed

+58
-30
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
------------------
33
* Feature: Allow configuring error email addresses via UI.
44
* Bugfix: . and .. should now be allowed to be used when specifying the templates directory.
5-
5+
* Bugfix: corrected cron schedule incorrectly shifting back one day upon save.
66

77

88
0.5.1 (2023-02-22)

notebooker/web/routes/scheduling.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import json
2-
from typing import Optional, List
2+
from typing import Optional, List, Callable
33
import logging
44

55
from apscheduler.jobstores.base import ConflictingIdError
@@ -125,51 +125,53 @@ def create_schedule(report_name):
125125
return jsonify({"status": "Failed", "content": str(e)})
126126

127127

128-
def convert_day_of_week(day_of_week: str) -> str:
128+
def _convert_day_of_week(day_of_week: str, convert_func: Callable) -> str:
129129
"""
130-
UNIX standard maps days-of-week to ints as:
131-
SUN: 0
132-
MON: 1
133-
TUE: 2....
134-
135-
APScheduler uses:
136-
MON: 0
137-
TUE: 1
138-
WED: 2.....
139-
140-
Given we are providing a UNIX-style crontab, convert ints accordingly. Don't shift char-based descriptors,
141-
ie., 'MON-FRI'.
130+
Given we are providing a crontab converts the int-based day specification according to the function passed.
131+
Does not shift char-based descriptors i.e. 'MON-FRI'.
142132
Parameters
143133
----------
144134
day_of_week - str - "FRI", "MON-FRI", "1"(UNIX Monday)
145-
146-
Returns
147-
-------
148-
day_of_week formatted to APScheduler standard
135+
convert_func - function to use for conversion
149136
"""
150137

151138
def shift(mychar):
152139
if mychar.isnumeric():
153140
myint = int(mychar)
154-
return str((myint + 6) % 7)
141+
return str(convert_func(myint))
155142
else:
156143
return mychar
157144

158145
return "".join([shift(char) for char in day_of_week])
159146

160147

148+
def crontab_to_apscheduler_day_of_week(day_of_week: str) -> str:
149+
"""
150+
Converts UNIX standard days-of-week (SUN=0, MON=1, ...) to APScheduler ones (MON=0, TUE=1, ...)
151+
"""
152+
return _convert_day_of_week(day_of_week, lambda dow: (dow + 6) % 7)
153+
154+
155+
def apscheduler_to_crontab_day_of_week(day_of_week: str) -> str:
156+
"""
157+
Converts APScheduler days-of-week (MON=0, TUE=1, ...) to UNIX standard ones (SUN=0, MON=1, ...)
158+
"""
159+
return _convert_day_of_week(day_of_week, lambda dow: (dow - 6) % 7)
160+
161+
161162
def validate_crontab(crontab: str, issues: List[str]) -> cron.CronTrigger:
162163
parts = crontab.split()
163164
if len(parts) != 5:
164165
issues.append("The crontab key must be passed with a string using 5 crontab parts")
165166
else:
166-
parts[4] = convert_day_of_week(parts[4])
167+
parts[4] = crontab_to_apscheduler_day_of_week(parts[4])
167168
return cron.CronTrigger(minute=parts[0], hour=parts[1], day=parts[2], month=parts[3], day_of_week=parts[4])
168169

169170

170171
def trigger_to_crontab(trigger: cron.CronTrigger) -> str:
171172
fields = {f.name: str(f) for f in trigger.fields}
172-
return f"{fields['minute']} {fields['hour']} {fields['day']} {fields['month']} {fields['day_of_week']}"
173+
day_of_week = apscheduler_to_crontab_day_of_week(fields["day_of_week"])
174+
return f"{fields['minute']} {fields['hour']} {fields['day']} {fields['month']} {day_of_week}"
173175

174176

175177
def _job_to_json(job):
Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,42 @@
1-
from notebooker.web.routes.scheduling import convert_day_of_week
1+
from notebooker.web.routes.scheduling import crontab_to_apscheduler_day_of_week
2+
from notebooker.web.routes.scheduling import apscheduler_to_crontab_day_of_week
23

34

4-
def test_weekdays():
5-
result = convert_day_of_week("1-5")
5+
def test_to_appscheduler_days():
6+
result = crontab_to_apscheduler_day_of_week("0,1,2,3,4,5,6")
7+
assert result == "6,0,1,2,3,4,5"
8+
9+
10+
def test_to_crontab_days():
11+
result = apscheduler_to_crontab_day_of_week("6,0,1,2,3,4,5")
12+
assert result == "0,1,2,3,4,5,6"
13+
14+
15+
def test_to_appscheduler_weekdays():
16+
result = crontab_to_apscheduler_day_of_week("1-5")
617
assert result == "0-4"
718

819

9-
def test_sunday():
10-
result = convert_day_of_week("0")
20+
def test_to_crontab_weekdays():
21+
result = apscheduler_to_crontab_day_of_week("0-4")
22+
assert result == "1-5"
23+
24+
25+
def test_to_appscheduler_sunday():
26+
result = crontab_to_apscheduler_day_of_week("0")
1127
assert result == "6"
1228

1329

14-
def test_string_days():
15-
result = convert_day_of_week("MON-FRI")
16-
assert result == "MON-FRI"
30+
def test_to_crontab_sunday():
31+
result = apscheduler_to_crontab_day_of_week("6")
32+
assert result == "0"
33+
34+
35+
def test_to_appscheduler_string_days():
36+
result = crontab_to_apscheduler_day_of_week("MON-FRI")
37+
assert result == "MON-FRI"
38+
39+
40+
def test_to_crontab_string_days():
41+
result = apscheduler_to_crontab_day_of_week("MON-FRI")
42+
assert result == "MON-FRI"

0 commit comments

Comments
 (0)