2016-08-24 12:12:52 +00:00
|
|
|
import enum
|
|
|
|
from . import daterange
|
|
|
|
|
|
|
|
class Filters(enum.Enum):
|
|
|
|
in_date_range, is_weekday = range(2)
|
|
|
|
|
|
|
|
class Conjunctions(enum.Enum):
|
|
|
|
all, any, none, implies = range(4)
|
|
|
|
|
2016-08-25 20:05:46 +00:00
|
|
|
def to_ir(parsed):
|
2016-08-24 12:12:52 +00:00
|
|
|
assert(len(parsed) >= 1)
|
|
|
|
function, *parameters = parsed
|
|
|
|
|
|
|
|
assert(function in ['date', 'week', 'weekday', 'and', 'or', 'not', 'if'])
|
|
|
|
|
|
|
|
if function == 'date':
|
|
|
|
if len(parameters) == 1:
|
|
|
|
start, = parameters
|
|
|
|
end = start
|
|
|
|
else:
|
|
|
|
assert(len(parameters) == 2)
|
|
|
|
start, end = parameters
|
|
|
|
|
|
|
|
date_range = daterange.between(start, end)
|
|
|
|
return (Filters.in_date_range, date_range)
|
|
|
|
|
|
|
|
elif function == 'week':
|
|
|
|
if len(parameters) > 1:
|
2017-01-25 21:34:33 +00:00
|
|
|
return (Conjunctions.any,) + tuple(to_ir(('week', week)) for week in parameters)
|
2016-08-24 12:12:52 +00:00
|
|
|
else:
|
|
|
|
assert(len(parameters) == 1)
|
|
|
|
week_data, = parameters
|
|
|
|
year, week = week_data
|
|
|
|
|
|
|
|
date_range = daterange.week(year, week)
|
|
|
|
return (Filters.in_date_range, date_range)
|
|
|
|
|
|
|
|
elif function == 'weekday':
|
|
|
|
if len(parameters) > 1:
|
2017-01-25 21:34:33 +00:00
|
|
|
return (Conjunctions.any,) + tuple(to_ir(('weekday', weekday)) for weekday in parameters)
|
2016-08-24 12:12:52 +00:00
|
|
|
else:
|
|
|
|
assert(len(parameters) == 1)
|
|
|
|
weekday, = parameters
|
|
|
|
|
|
|
|
return (Filters.is_weekday, weekday)
|
|
|
|
|
|
|
|
elif function == 'and':
|
2017-01-25 21:34:33 +00:00
|
|
|
return (Conjunctions.all,) + tuple(to_ir(parameter) for parameter in parameters)
|
2016-08-24 12:12:52 +00:00
|
|
|
|
|
|
|
elif function == 'or':
|
2017-01-25 21:34:33 +00:00
|
|
|
return (Conjunctions.any,) + tuple(to_ir(parameter) for parameter in parameters)
|
2016-08-24 12:12:52 +00:00
|
|
|
|
|
|
|
elif function == 'not':
|
2017-01-25 21:34:33 +00:00
|
|
|
return (Conjunctions.none,) + tuple(to_ir(parameter) for parameter in parameters)
|
2016-08-24 12:12:52 +00:00
|
|
|
|
|
|
|
elif function == 'if':
|
|
|
|
assert(len(parameters) == 2)
|
|
|
|
condition, then = parameters
|
2016-08-25 20:05:46 +00:00
|
|
|
return (Conjunctions.implies, to_ir(condition), to_ir(then))
|
2016-08-24 12:12:52 +00:00
|
|
|
|
2016-08-25 20:05:46 +00:00
|
|
|
def to_lambda(date_filter):
|
2016-08-24 12:12:52 +00:00
|
|
|
assert(len(date_filter) >= 1)
|
|
|
|
function, *parameters = date_filter
|
|
|
|
assert(function in Filters or function in Conjunctions)
|
|
|
|
|
|
|
|
if function == Conjunctions.all:
|
2016-08-25 20:05:46 +00:00
|
|
|
compiled = [to_lambda(parameter) for parameter in parameters]
|
|
|
|
return lambda day: all(map(lambda f: f(day), compiled))
|
2016-08-24 12:12:52 +00:00
|
|
|
|
|
|
|
elif function == Conjunctions.any:
|
2016-08-25 20:05:46 +00:00
|
|
|
compiled = [to_lambda(parameter) for parameter in parameters]
|
|
|
|
return lambda day: any(map(lambda f: f(day), compiled))
|
|
|
|
|
2016-08-24 12:12:52 +00:00
|
|
|
elif function == Conjunctions.implies:
|
2016-08-25 20:05:46 +00:00
|
|
|
assert(len(parameters) == 2)
|
|
|
|
left, right = to_lambda(parameters[0], parameters[1])
|
|
|
|
return lambda day: right(day) if left(day) else True
|
|
|
|
|
2016-08-24 12:12:52 +00:00
|
|
|
elif function == Conjunctions.none:
|
2016-08-25 20:05:46 +00:00
|
|
|
compiled = [to_lambda(parameter) for parameter in parameters]
|
|
|
|
return lambda day: not any(map(lambda f: f(day), compiled))
|
|
|
|
|
2016-08-24 12:12:52 +00:00
|
|
|
elif function == Filters.in_date_range:
|
2016-08-25 20:05:46 +00:00
|
|
|
assert(len(parameters) == 1)
|
2016-08-24 12:12:52 +00:00
|
|
|
date_range, = parameters
|
2016-08-25 20:05:46 +00:00
|
|
|
return lambda day: day in date_range
|
|
|
|
|
2016-08-24 12:12:52 +00:00
|
|
|
elif function == Filters.is_weekday:
|
2016-08-25 20:05:46 +00:00
|
|
|
assert(len(parameters) == 1)
|
2016-08-24 12:12:52 +00:00
|
|
|
weekday, = parameters
|
2016-08-25 20:05:46 +00:00
|
|
|
return lambda day: day.isoweekday() == weekday
|
|
|
|
|
|
|
|
def compile(parsed):
|
|
|
|
ir = to_ir(parsed)
|
|
|
|
return to_lambda(ir)
|