Exemple #1
0
 def test_interval_clock_interval_must_be_positive(self):
     with pytest.raises(ValueError, match="greater than 0"):
         clocks.IntervalClock(interval=timedelta(hours=-1))
     with pytest.raises(ValueError, match="greater than 0"):
         clocks.IntervalClock(interval=timedelta(seconds=-1))
     with pytest.raises(ValueError, match="greater than 0"):
         clocks.IntervalClock(interval=timedelta(0))
Exemple #2
0
def test_start_date_and_end_date_none():
    s = schedules.Schedule(clocks=[
        clocks.IntervalClock(timedelta(hours=1)),
        clocks.IntervalClock(timedelta(hours=1)),
    ])
    assert s.start_date is None
    assert s.end_date is None
Exemple #3
0
 def test_interval_clock_interval_must_be_more_than_one_minute(self):
     with pytest.raises(ValueError):
         clocks.IntervalClock(interval=timedelta(seconds=59))
     with pytest.raises(ValueError):
         clocks.IntervalClock(interval=timedelta(microseconds=59999999))
     with pytest.raises(ValueError):
         clocks.IntervalClock(interval=timedelta(0))
Exemple #4
0
def test_interval_clocks_with_exactly_one_minute_intervals_can_be_serialized():
    s = schedules.Schedule(
        clocks=[clocks.IntervalClock(timedelta(seconds=60))])
    t = schedules.Schedule(clocks=[clocks.IntervalClock(timedelta(minutes=1))])
    s2 = serialize_and_deserialize(s)
    t2 = serialize_and_deserialize(t)
    assert s2.next(1, after=pendulum.datetime(
        2019, 1, 1)) == [pendulum.datetime(2019, 1, 1, 0, 1)]
    assert t2.next(1, after=pendulum.datetime(
        2019, 1, 1)) == [pendulum.datetime(2019, 1, 1, 0, 1)]
Exemple #5
0
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)
Exemple #6
0
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),
    ]
Exemple #7
0
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)]
Exemple #8
0
 def test_end_date(self):
     c = clocks.IntervalClock(timedelta(hours=1),
                              end_date=pendulum.datetime(2020, 1, 1))
     assert c.start_date is None
     assert c.interval == timedelta(hours=1)
     assert c.end_date == pendulum.datetime(2020, 1, 1)
     assert c.parameter_defaults == dict()
Exemple #9
0
 def test_create_interval_clock_with_parameters(self):
     c = clocks.IntervalClock(
         start_date=pendulum.now("UTC"),
         interval=timedelta(days=1),
         parameter_defaults=dict(x=42),
     )
     assert c.parameter_defaults == dict(x=42)
Exemple #10
0
def test_interval_clocks_with_sub_minute_intervals_cant_be_deserialized():
    schema = ScheduleSchema()
    s = schedules.Schedule(clocks=[clocks.IntervalClock(timedelta(seconds=100))])
    data = schema.dump(s)
    data["clocks"][0]["interval"] = 59 * 1e6
    with pytest.raises(ValueError, match="can not be less than one minute"):
        schema.load(data)
Exemple #11
0
def test_serialize_complex_schedule():
    dt = pendulum.datetime(2019, 1, 3)
    s = schedules.Schedule(
        # fire every hour
        clocks=[clocks.IntervalClock(timedelta(hours=1))],
        # only on weekdays
        filters=[filters.is_weekday],
        # only at 9am or 3pm
        or_filters=[
            filters.at_time(pendulum.time(9)),
            filters.between_times(pendulum.time(15), pendulum.time(15)),
        ],
        # not on january 8
        not_filters=[filters.between_dates(1, 8, 1, 8)],
        # add three hours
        adjustments=[adjustments.add(timedelta(hours=3))],
    )

    s2 = serialize_and_deserialize(s)

    assert s2.next(8, after=dt) == [
        dt.replace(hour=12),
        dt.replace(hour=18),
        dt.add(days=1).replace(hour=12),
        dt.add(days=1).replace(hour=18),
        # skip weekend
        dt.add(days=4).replace(hour=12),
        dt.add(days=4).replace(hour=18),
        # skip jan 8!
        dt.add(days=6).replace(hour=12),
        dt.add(days=6).replace(hour=18),
    ]
Exemple #12
0
 def test_start_date_can_be_none(self):
     c = clocks.IntervalClock(timedelta(hours=1))
     assert c.start_date is None
     assert c.interval == timedelta(hours=1)
     assert c.end_date is None
     assert c.parameter_defaults == dict()
     assert c.labels is None
Exemple #13
0
def test_create_schedule_multiple_filters():
    # jan 3 was a thursday
    dt = pendulum.datetime(2019, 1, 3)
    s = schedules.Schedule(
        # fire every hour
        clocks=[clocks.IntervalClock(timedelta(hours=1))],
        # only on weekdays
        filters=[filters.is_weekday],
        # only at 9am or 3pm
        or_filters=[
            filters.between_times(pendulum.time(9), pendulum.time(9)),
            filters.between_times(pendulum.time(15), pendulum.time(15)),
        ],
        # not on january 8
        not_filters=[filters.between_dates(1, 8, 1, 8)],
    )

    assert s.next(8, after=dt) == [
        dt.replace(hour=9),
        dt.replace(hour=15),
        dt.add(days=1).replace(hour=9),
        dt.add(days=1).replace(hour=15),
        # skip weekend
        dt.add(days=4).replace(hour=9),
        dt.add(days=4).replace(hour=15),
        # skip jan 8!
        dt.add(days=6).replace(hour=9),
        dt.add(days=6).replace(hour=15),
    ]
Exemple #14
0
 def test_create_interval_clock_with_labels(self):
     c = clocks.IntervalClock(
         start_date=pendulum.now("UTC"),
         interval=timedelta(days=1),
         labels=["foo"],
     )
     assert c.labels == ["foo"]
Exemple #15
0
def test_create_schedule():
    dt = pendulum.datetime(2019, 1, 1)
    s = schedules.Schedule(clocks=[clocks.IntervalClock(timedelta(days=1))])
    output = s.next(3, 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=3)]
Exemple #16
0
 def test_interval_clock_end_date(self):
     start_date = pendulum.datetime(2018, 1, 1)
     end_date = pendulum.datetime(2018, 1, 2)
     c = clocks.IntervalClock(
         start_date=start_date, interval=timedelta(days=1), end_date=end_date
     )
     assert islice(c.events(after=start_date), 3) == [start_date.add(days=1)]
     assert islice(c.events(after=pendulum.datetime(2018, 2, 1)), 3) == []
Exemple #17
0
 def test_interval_clock_doesnt_compute_dates_before_start_date(self):
     start_date = pendulum.datetime(2018, 1, 1)
     c = clocks.IntervalClock(start_date=start_date, interval=timedelta(hours=1))
     assert islice(c.events(after=pendulum.datetime(2000, 1, 1)), 3) == [
         start_date,
         start_date.add(hours=1),
         start_date.add(hours=2),
     ]
Exemple #18
0
 def test_interval_clock_respects_microseconds(self):
     start_date = pendulum.datetime(2018, 1, 1, 0, 0, 0, 1)
     c = clocks.IntervalClock(start_date=start_date, interval=timedelta(hours=1))
     assert islice(c.events(after=pendulum.datetime(2010, 1, 1)), 3) == [
         start_date,
         start_date.add(hours=1),
         start_date.add(hours=2),
     ]
Exemple #19
0
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),
    ]
Exemple #20
0
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_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),
    ]
Exemple #22
0
def test_create_schedule_emits_events_if_asked():
    dt = pendulum.datetime(2019, 1, 1)
    s = schedules.Schedule(clocks=[clocks.IntervalClock(timedelta(days=1))])
    output = s.next(3, 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=3)]
Exemple #23
0
 def test_interval_clock_events_with_after_argument(self):
     start_date = pendulum.datetime(2018, 1, 1)
     after = pendulum.datetime(2025, 1, 5)
     c = clocks.IntervalClock(timedelta(days=1), start_date=start_date)
     assert islice(c.events(after=after.add(hours=1)), 3) == [
         after.add(days=1),
         after.add(days=2),
         after.add(days=3),
     ]
Exemple #24
0
 def test_interval_clock_events(self):
     """Test that default after is *now*"""
     start_date = pendulum.datetime(2018, 1, 1)
     today = pendulum.today("UTC")
     c = clocks.IntervalClock(timedelta(days=1), start_date=start_date)
     assert islice(c.events(), 3) == [
         today.add(days=1),
         today.add(days=2),
         today.add(days=3),
     ]
Exemple #25
0
def test_create_schedule_multiple_exclusive_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)),
            filters.between_times(pendulum.time(15), pendulum.time(16)),
        ],
    )
    assert s.next(6, after=dt) == []
Exemple #26
0
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),
    ]
Exemple #27
0
 def test_interval_clock_respects_after_in_middle_of_interval(self):
     """
     If the "after" date is in the middle of an interval, then the IntervalClock
     should advance to the next interval.
     """
     start_date = pendulum.datetime(2018, 1, 1)
     c = clocks.IntervalClock(start_date=start_date, interval=timedelta(hours=1))
     assert islice(c.events(after=start_date + timedelta(microseconds=1)), 2) == [
         start_date.add(hours=1),
         start_date.add(hours=2),
     ]
Exemple #28
0
 def test_interval_clock_hourly_daylight_savings_time_backward(self, serialize):
     """
     11/4/2018, at 2am, America/New_York switched clocks back an hour.
     """
     dt = pendulum.datetime(2018, 11, 3, 23, tz="America/New_York")
     c = clocks.IntervalClock(timedelta(hours=1), start_date=dt)
     if serialize:
         c = ClockSchema().load(ClockSchema().dump(c))
     next_4 = islice(c.events(after=dt), 4)
     # repeat the 1am run in local time
     assert [t.in_tz("America/New_York").hour for t in next_4] == [0, 1, 1, 2]
     # runs every hour UTC
     assert [t.in_tz("UTC").hour for t in next_4] == [4, 5, 6, 7]
Exemple #29
0
 def test_interval_clock_hourly_daylight_savings_time_forward(self, serialize):
     """
     On 3/11/2018, at 2am, America/New_York switched clocks forward an hour.
     """
     dt = pendulum.datetime(2018, 3, 10, 23, tz="America/New_York")
     c = clocks.IntervalClock(timedelta(hours=1), start_date=dt)
     if serialize:
         c = ClockSchema().load(ClockSchema().dump(c))
     next_4 = islice(c.events(after=dt), 4)
     # skip 2am
     assert [t.in_tz("America/New_York").hour for t in next_4] == [0, 1, 3, 4]
     # constant hourly schedule in utc time
     assert [t.in_tz("UTC").hour for t in next_4] == [5, 6, 7, 8]
Exemple #30
0
 def test_interval_clock_always_has_the_right_offset(self):
     """
     Tests the situation where a long duration has passed since the start date that crosses a DST boundary;
     for very short intervals this occasionally could result in "next" scheduled times that are in the past by one hour.
     """
     start_date = pendulum.from_timestamp(1582002945.964696).astimezone(
         pendulum.timezone("US/Pacific"))
     current_date = pendulum.from_timestamp(1593643144.233938).astimezone(
         pendulum.timezone("UTC"))
     c = clocks.IntervalClock(timedelta(minutes=1, seconds=15),
                              start_date=start_date)
     next_4 = islice(c.events(after=current_date), 4)
     assert all(d > current_date for d in next_4)