def test_create_schedule_filters_2(): dt = pendulum.datetime(2019, 1, 1) s = schedules.Schedule( clocks=[clocks.IntervalClock(timedelta(minutes=15))], filters=[filters.at_time(pendulum.time(2, 45))], ) assert s.next(6, after=dt) == [ dt.add(days=0, hours=2, minutes=45), dt.add(days=1, hours=2, minutes=45), dt.add(days=2, hours=2, minutes=45), dt.add(days=3, hours=2, minutes=45), dt.add(days=4, hours=2, minutes=45), dt.add(days=5, hours=2, minutes=45), ]
def test_create_schedule_filters(): dt = pendulum.datetime(2019, 1, 1) s = schedules.Schedule( clocks=[clocks.IntervalClock(timedelta(hours=1))], filters=[filters.between_times(pendulum.time(9), pendulum.time(10))], ) assert s.next(6, after=dt) == [ dt.add(days=0).replace(hour=9), dt.add(days=0).replace(hour=10), dt.add(days=1).replace(hour=9), dt.add(days=1).replace(hour=10), dt.add(days=2).replace(hour=9), dt.add(days=2).replace(hour=10), ]
def test_serialize_schedule_with_parameters(): dt = pendulum.datetime(2099, 1, 1) s = schedules.Schedule(clocks=[ clocks.IntervalClock(timedelta(hours=1), parameter_defaults=dict( x=42)), clocks.CronClock("0 8 * * *", parameter_defaults=dict(y=99)), ]) s2 = serialize_and_deserialize(s) assert s2.clocks[0].parameter_defaults == dict(x=42) assert s2.clocks[1].parameter_defaults == dict(y=99) output = s2.next(3, after=dt, return_events=True) assert all([isinstance(e, clocks.ClockEvent) for e in output])
def test_start_date_and_end_date(): s = schedules.Schedule(clocks=[ clocks.IntervalClock( timedelta(hours=1), start_date=pendulum.datetime(2018, 1, 1), end_date=pendulum.datetime(2019, 1, 1), ), clocks.IntervalClock( timedelta(hours=1), start_date=pendulum.datetime(2019, 1, 1), end_date=pendulum.datetime(2020, 1, 1), ), ]) assert s.start_date == pendulum.datetime(2018, 1, 1) assert s.end_date == pendulum.datetime(2020, 1, 1)
def test_create_schedule_multiple_overlapping_clocks(): dt = pendulum.datetime(2019, 1, 1) s = schedules.Schedule(clocks=[ clocks.IntervalClock(timedelta(days=1)), clocks.IntervalClock(timedelta(hours=12), start_date=pendulum.datetime(2019, 1, 3)), ]) assert s.next(6, after=dt) == [ dt.add(days=1), dt.add(days=2), dt.add(days=2, hours=12), dt.add(days=3), dt.add(days=3, hours=12), dt.add(days=4), ]
def test_serialize_multiple_clocks(): dt = pendulum.datetime(2019, 1, 1) s = schedules.Schedule(clocks=[ clocks.IntervalClock(timedelta(days=1)), clocks.IntervalClock(timedelta(hours=12), start_date=pendulum.datetime(2019, 1, 3)), ]) s2 = serialize_and_deserialize(s) assert s2.next(6, after=dt) == [ dt.add(days=1), dt.add(days=2), dt.add(days=2, hours=12), dt.add(days=3), dt.add(days=3, hours=12), dt.add(days=4), ]
def test_create_schedule_multiple_overlapping_clocks_emit_events_if_asked(): dt = pendulum.datetime(2019, 1, 1) s = schedules.Schedule(clocks=[ clocks.IntervalClock(timedelta(days=1)), clocks.IntervalClock(timedelta(hours=12), start_date=pendulum.datetime(2019, 1, 3)), ]) output = s.next(6, after=dt, return_events=True) assert all(isinstance(e, clocks.ClockEvent) for e in output) assert all(e.parameter_defaults == dict() for e in output) assert output == [ dt.add(days=1), dt.add(days=2), dt.add(days=2, hours=12), dt.add(days=3), dt.add(days=3, hours=12), dt.add(days=4), ]
def test_create_schedule_multiple_overlapping_clocks(): dt = pendulum.datetime(2019, 1, 1) s = schedules.Schedule(clocks=[ clocks.IntervalClock(timedelta(days=1)), clocks.IntervalClock(timedelta(hours=12), start_date=pendulum.datetime(2019, 1, 3)), ]) output = s.next(6, after=dt) assert all(not isinstance(e, clocks.ClockEvent) for e in output) assert output == [ dt.add(days=1), dt.add(days=2), dt.add(days=2, hours=12), dt.add(days=3), dt.add(days=3, hours=12), dt.add(days=4), ]
def test_create_schedule_multiple_overlapping_clocks_emit_events_with_correct_parameters(): s = schedules.Schedule( clocks=[ clocks.IntervalClock(timedelta(days=1), parameter_defaults=dict(x=0)), clocks.IntervalClock(timedelta(hours=12), parameter_defaults=dict(x=1)), ] ) dt = pendulum.datetime(2019, 1, 1) output = s.next(6, after=dt, return_events=True) assert all([isinstance(e, clocks.ClockEvent) for e in output]) assert [e.parameter_defaults["x"] for e in output] == [1, 0, 1, 1, 0, 1] assert [e.start_time for e in output] == [ dt.add(hours=12), dt.add(days=1), dt.add(days=1), dt.add(days=1, hours=12), dt.add(days=2), dt.add(days=2), ]
def test_with_clocks_with_different_timezones(): east = clocks.CronClock( "0 9 * * 1-5", start_date=pendulum.parse("2019-03-14", tz="US/Eastern") ) west = clocks.CronClock( "30 6 * * 1-5", start_date=pendulum.parse("2019-03-14", tz="US/Pacific") ) s = schedules.Schedule(clocks=[east, west]) after = pendulum.datetime(2019, 5, 1) next_east = list(itertools.islice(east.events(after=after), 3)) next_west = list(itertools.islice(west.events(after=after), 3)) expected = [ next_east[0], next_west[0], next_east[1], next_west[1], next_east[2], next_west[2], ] assert s.next(6, after) == expected
def test_start_date_and_end_date_missing(): s = schedules.Schedule(clocks=[]) assert s.start_date is None assert s.end_date is None
def test_schedule_with_empty_clocks(): s = schedules.Schedule(clocks=[]) assert s.next(3) == []
def test_create_schedule_requires_list_of_clocks(): with pytest.raises(TypeError): schedules.Schedule(clocks=clocks.IntervalClock(timedelta(days=1)))
def test_serialize_rrule_clocks(): start = pendulum.datetime(2020, 1, 1, 0, 0) rr = rrule.rrule(rrule.MINUTELY, start) t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) assert t.next(1, after=start) == [pendulum.datetime(2020, 1, 1, 0, 1)] t2 = serialize_and_deserialize(t) assert t2.next(1, after=start) == [pendulum.datetime(2020, 1, 1, 0, 1)] weekdays = (rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR) rr = rrule.rrule(rrule.MONTHLY, start, byweekday=weekdays, bysetpos=-1) t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) assert t.next(1, after=start) == [pendulum.datetime(2020, 1, 31, 0, 0)] t2 = serialize_and_deserialize(t) assert t2.next(1, after=start) == [pendulum.datetime(2020, 1, 31, 0, 0)] # Every weekday (BYDAY) for the next 8 weekdays (COUNT). rr = rrule.rrule(rrule.DAILY, start, byweekday=weekdays, count=8) t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) assert t.next(1, after=start) == [pendulum.datetime(2020, 1, 2, 0, 0)] assert len(t.next(10, after=start)) == 7 t2 = serialize_and_deserialize(t) assert t2.next(1, after=start) == [pendulum.datetime(2020, 1, 2, 0, 0)] assert len(t2.next(10, after=start)) == 7 # Every third year (INTERVAL) on the first Tuesday (BYDAY) after a Monday (BYMONTHDAY) in October. month_day = (2, 3, 4, 5, 6, 7, 8) rr = rrule.rrule( rrule.YEARLY, start, interval=3, bymonth=10, byweekday=rrule.TU, bymonthday=month_day, ) t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) first = pendulum.datetime(2020, 10, 6, 0, 0) second = pendulum.datetime(2023, 10, 3, 0, 0) assert t.next(2, after=start) == [first, second] t2 = serialize_and_deserialize(t) assert t2.next(2, after=start) == [first, second] # Every three weeks on Sunday until 9/23/2021 until = pendulum.datetime(2021, 9, 23) days = [pendulum.datetime(2020, 1, 5), pendulum.datetime(2020, 1, 26)] after_days = [pendulum.datetime(2021, 9, 1), pendulum.datetime(2021, 9, 5)] rr = rrule.rrule(rrule.WEEKLY, start, byweekday=rrule.SU, interval=3, until=until) t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) assert t.next(2, after=start) == days assert t.next(3, after=after_days[0]) == [after_days[1]] t2 = serialize_and_deserialize(t) assert t2.next(2, after=start) == days assert t2.next(3, after=after_days[0]) == [after_days[1]] rr = rrule.rrule(rrule.YEARLY, start, byyearday=200) days = [pendulum.datetime(2020, 7, 18), pendulum.datetime(2021, 7, 19)] t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) assert t.next(2, after=start) == days t2 = serialize_and_deserialize(t) assert t2.next(2, after=start) == days # Three days after easter annually rr = rrule.rrule(rrule.YEARLY, start, byeaster=3) days = [pendulum.datetime(2020, 4, 15), pendulum.datetime(2021, 4, 7)] t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) assert t.next(2, after=start) == days t2 = serialize_and_deserialize(t) assert t2.next(2, after=start) == days rr = rrule.rrule(rrule.WEEKLY, start, byhour=9, byminute=13, bysecond=54) t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) assert t.next(1, after=start) == [pendulum.datetime(2020, 1, 1, 9, 13, 54)] t2 = serialize_and_deserialize(t) assert t2.next(1, after=start) == [pendulum.datetime(2020, 1, 1, 9, 13, 54)] rr = rrule.rrule(rrule.YEARLY, start, byweekno=(7, 16), byweekday=rrule.WE) days = [pendulum.datetime(2020, 2, 12), pendulum.datetime(2020, 4, 15)] t = schedules.Schedule(clocks=[clocks.RRuleClock(rrule_obj=rr)]) assert t.next(2, after=start) == days t2 = serialize_and_deserialize(t) assert t2.next(2, after=start) == days
def test_create_schedule(): dt = pendulum.datetime(2019, 1, 1) s = schedules.Schedule(clocks=[clocks.IntervalClock(timedelta(days=1))]) assert s.next(3, after=dt) == [dt.add(days=1), dt.add(days=2), dt.add(days=3)]
def test_serialize_schedule_with_dateclock(): dt = pendulum.datetime(2099, 1, 1) s = schedules.Schedule(clocks=[clocks.DatesClock(dates=[dt, dt.add(days=1)])]) s2 = serialize_and_deserialize(s) assert s2.next(2) == [dt, dt.add(days=1)]
def test_interval_clocks_with_sub_minute_intervals_cant_be_serialized(): schema = ScheduleSchema() s = schedules.Schedule(clocks=[clocks.IntervalClock(timedelta(seconds=59))]) with pytest.raises(ValueError, match="can not be less than one minute"): schema.dump(s)
def test_create_schedule_requires_clock(): with pytest.raises(TypeError): schedules.Schedule()