diff options
author | Lowell Alleman <lowell@kintyre.co> | 2021-03-25 14:05:18 -0400 |
---|---|---|
committer | kiorky <kiorky@cryptelium.net> | 2021-04-07 17:01:14 +0200 |
commit | ecda34051261bb9ccd3c57411a5885851baa4d20 (patch) | |
tree | 1780c096739abbaa33be240f830a077b5fb3c161 | |
parent | 95ea75d1352d648fa99a834faada1bde68255745 (diff) | |
download | croniter-ecda34051261bb9ccd3c57411a5885851baa4d20.tar.gz |
Integrate parsing logic into _expand()
- Commented out the dow_types checking (L + non-L) detection and explicit
blocking due to mishandled corner cases.
-rw-r--r-- | src/croniter/croniter.py | 72 |
1 files changed, 35 insertions, 37 deletions
diff --git a/src/croniter/croniter.py b/src/croniter/croniter.py index 74e4eb8..3c923fd 100644 --- a/src/croniter/croniter.py +++ b/src/croniter/croniter.py @@ -17,6 +17,7 @@ import calendar step_search_re = re.compile(r'^([^-]+)-([^-/]+)(/(\d+))?$') only_int_re = re.compile(r'^\d+$') star_or_int_re = re.compile(r'^(\d+|\*)$') +last_weekday_re = re.compile(r'^l([0-7])$') VALID_LEN_EXPRESSION = [5, 6] @@ -120,43 +121,10 @@ class croniter(object): self.dst_start_time = None self.cur = None self.set_current(start_time) - self.last_weekday_of_month = set() - try: - expr_format = self.prep_expr(expr_format) - except IndexError as e: - raise ValueError(e) - self.expanded, self.nth_weekday_of_month = self.expand(expr_format) + self.expanded, self.nth_weekday_of_month, self.last_weekday_of_month = \ + self.expand(expr_format) self._is_prev = is_prev - def prep_expr(self, expr_format): - """ Intercept "<dow>L" entries in day-of-week and handle them specially. - Everything else is passed along as-is. Unpack / repack. """ - def handle_dow(day_of_week): - mo = re.match(r"^L([0-7])$", day_of_week, re.IGNORECASE) - if mo: - dow = int(mo.group(1)) % 7 - self.last_weekday_of_month.add(dow) - # Last dow should always be either the 4 or 5th occurrence of that dow - return "L", "{dow}#4,{dow}#5".format(dow=dow) - return "other", day_of_week - - expressions = expr_format.split() - # day of week field manipulations - found_types = set() - items = [] - for dow in expressions[4].split(","): - type_, dow = handle_dow(dow) - found_types.add(type_) - items.append(dow) - if len(found_types) > 1: - raise CroniterBadCronError( - "Mixing 'L' and non-'L' syntax in day of week field is not " - "supported in the cron expression: {}".format(expr_format)) - - expressions[4] = ",".join(items) - expr_format = " ".join(expressions) - return expr_format - @classmethod def _alphaconv(cls, index, key, expressions): try: @@ -474,7 +442,6 @@ class croniter(object): else: # NEED HELP here!! # XXX How do we know how much/little to bump forward/backwards? - # This seems to work, even if the next match is less than 1 day away, making me even *more* confused! if is_prev: d -= relativedelta(days=1) else: @@ -633,6 +600,8 @@ class croniter(object): expanded = [] nth_weekday_of_month = {} + last_weekday_of_month = set() + # dow_types = set() for i, expr in enumerate(expressions): e_list = expr.split(',') @@ -642,6 +611,21 @@ class croniter(object): e = e_list.pop() if i == 4: + # Handle special case in the day-of-week expression + m = last_weekday_re.match(str(e)) + if m: + dow = int(m.group(1)) % 7 + last_weekday_of_month.add(dow) + # Last dow should always be either the 4 or 5th occurrence of that dow + e = "{}#4".format(dow) + e_list.insert(0, "{}#5".format(dow)) + # dow_types.add("last-weekday-of-month") + del dow + ''' + else: + dow_types.add("other") + ''' + e, sep, nth = str(e).partition('#') if nth and not re.match(r'[1-5]', nth): raise CroniterBadCronError( @@ -743,7 +727,21 @@ class croniter(object): and res[0] == '*') else res) - return expanded, nth_weekday_of_month + ''' + if len(dow_types) > 1: + # This is more of a current implementation limit, not something that's impossible + + # For example `fri#1,L5` first and last friday of the month could be pretty easily + # supported, but `fri#4,L5` should really be translated to just `5#4,5#5` with + # last_weekday_of_month.discard(5). It gets complicated, so starting with a simple + # implementation that can be expanded overtime. + raise CroniterBadCronError( + "Mixing 'L' and non-'L' syntax in day of week field is not " + "currently supported. " + "Failed expression: {}".format(expr_format)) + ''' + + return expanded, nth_weekday_of_month, last_weekday_of_month @classmethod def expand(cls, expr_format): |