django-orchestra/orchestra/contrib/tasks/schedules.py

120 lines
4.1 KiB
Python

#import re
#class CronTab(object):
# pass
#class ParseException(Exception):
# """Raised by crontab_parser when the input can't be parsed."""
## https://github.com/celery/celery/blob/master/celery/schedules.py
#class CrontabParser(object):
# """Parser for crontab expressions. Any expression of the form 'groups'
# (see BNF grammar below) is accepted and expanded to a set of numbers.
# These numbers represent the units of time that the crontab needs to
# run on::
# digit :: '0'..'9'
# dow :: 'a'..'z'
# number :: digit+ | dow+
# steps :: number
# range :: number ( '-' number ) ?
# numspec :: '*' | range
# expr :: numspec ( '/' steps ) ?
# groups :: expr ( ',' expr ) *
# The parser is a general purpose one, useful for parsing hours, minutes and
# day_of_week expressions. Example usage::
# >>> minutes = crontab_parser(60).parse('*/15')
# [0, 15, 30, 45]
# >>> hours = crontab_parser(24).parse('*/4')
# [0, 4, 8, 12, 16, 20]
# >>> day_of_week = crontab_parser(7).parse('*')
# [0, 1, 2, 3, 4, 5, 6]
# It can also parse day_of_month and month_of_year expressions if initialized
# with an minimum of 1. Example usage::
# >>> days_of_month = crontab_parser(31, 1).parse('*/3')
# [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31]
# >>> months_of_year = crontab_parser(12, 1).parse('*/2')
# [1, 3, 5, 7, 9, 11]
# >>> months_of_year = crontab_parser(12, 1).parse('2-12/2')
# [2, 4, 6, 8, 10, 12]
# The maximum possible expanded value returned is found by the formula::
# max_ + min_ - 1
# """
# ParseException = ParseException
# _range = r'(\w+?)-(\w+)'
# _steps = r'/(\w+)?'
# _star = r'\*'
# def __init__(self, max_=60, min_=0):
# self.max_ = max_
# self.min_ = min_
# self.pats = (
# (re.compile(self._range + self._steps), self._range_steps),
# (re.compile(self._range), self._expand_range),
# (re.compile(self._star + self._steps), self._star_steps),
# (re.compile('^' + self._star + '$'), self._expand_star),
# )
# def parse(self, spec):
# acc = set()
# for part in spec.split(','):
# if not part:
# raise self.ParseException('empty part')
# acc |= set(self._parse_part(part))
# return acc
# def _parse_part(self, part):
# for regex, handler in self.pats:
# m = regex.match(part)
# if m:
# return handler(m.groups())
# return self._expand_range((part, ))
# def _expand_range(self, toks):
# fr = self._expand_number(toks[0])
# if len(toks) > 1:
# to = self._expand_number(toks[1])
# if to < fr: # Wrap around max_ if necessary
# return (list(range(fr, self.min_ + self.max_)) +
# list(range(self.min_, to + 1)))
# return list(range(fr, to + 1))
# return [fr]
# def _range_steps(self, toks):
# if len(toks) != 3 or not toks[2]:
# raise self.ParseException('empty filter')
# return self._expand_range(toks[:2])[::int(toks[2])]
# def _star_steps(self, toks):
# if not toks or not toks[0]:
# raise self.ParseException('empty filter')
# return self._expand_star()[::int(toks[0])]
# def _expand_star(self, *args):
# return list(range(self.min_, self.max_ + self.min_))
# def _expand_number(self, s):
# if isinstance(s, str) and s[0] == '-':
# raise self.ParseException('negative numbers not supported')
# try:
# i = int(s)
# except ValueError:
# try:
# i = weekday(s)
# except KeyError:
# raise ValueError('Invalid weekday literal {0!r}.'.format(s))
# max_val = self.min_ + self.max_ - 1
# if i > max_val:
# raise ValueError(
# 'Invalid end range: {0} > {1}.'.format(i, max_val))
# if i < self.min_:
# raise ValueError(
# 'Invalid beginning range: {0} < {1}.'.format(i, self.min_))
# return i