#93: reorganise Rerun, Diffusion, Schedule module #95
@ -33,7 +33,7 @@ class ScheduleAdmin(admin.ModelAdmin):
 | 
				
			|||||||
    program_title.short_description = _("Program")
 | 
					    program_title.short_description = _("Program")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def freq(self, obj):
 | 
					    def freq(self, obj):
 | 
				
			||||||
        return obj.get_frequency_verbose()
 | 
					        return obj.get_frequency_display()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    freq.short_description = _("Day")
 | 
					    freq.short_description = _("Day")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
import calendar
 | 
					import calendar
 | 
				
			||||||
from collections import OrderedDict
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytz
 | 
					import pytz
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
@ -28,7 +27,7 @@ class Schedule(Rerun):
 | 
				
			|||||||
    # Important: the first week is always the first week where the weekday of
 | 
					    # Important: the first week is always the first week where the weekday of
 | 
				
			||||||
    # the schedule is present.
 | 
					    # the schedule is present.
 | 
				
			||||||
    # For ponctual programs, there is no need for a schedule, only a diffusion
 | 
					    # For ponctual programs, there is no need for a schedule, only a diffusion
 | 
				
			||||||
    class Frequency(models.IntegerChoice):
 | 
					    class Frequency(models.IntegerChoices):
 | 
				
			||||||
        ponctual = 0b000000, _("ponctual")
 | 
					        ponctual = 0b000000, _("ponctual")
 | 
				
			||||||
        first = 0b000001, _("1st {day} of the month")
 | 
					        first = 0b000001, _("1st {day} of the month")
 | 
				
			||||||
        second = 0b000010, _("2nd {day} of the month")
 | 
					        second = 0b000010, _("2nd {day} of the month")
 | 
				
			||||||
@ -50,7 +49,7 @@ class Schedule(Rerun):
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    timezone = models.CharField(
 | 
					    timezone = models.CharField(
 | 
				
			||||||
        _("timezone"),
 | 
					        _("timezone"),
 | 
				
			||||||
        default=tz.get_current_timezone,
 | 
					        default=lambda: tz.get_current_timezone().zone,
 | 
				
			||||||
        max_length=100,
 | 
					        max_length=100,
 | 
				
			||||||
        choices=[(x, x) for x in pytz.all_timezones],
 | 
					        choices=[(x, x) for x in pytz.all_timezones],
 | 
				
			||||||
        help_text=_("timezone used for the date"),
 | 
					        help_text=_("timezone used for the date"),
 | 
				
			||||||
@ -71,7 +70,7 @@ class Schedule(Rerun):
 | 
				
			|||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "{} - {}, {}".format(
 | 
					        return "{} - {}, {}".format(
 | 
				
			||||||
            self.program.title,
 | 
					            self.program.title,
 | 
				
			||||||
            self.get_frequency_verbose(),
 | 
					            self.get_frequency_display(),
 | 
				
			||||||
            self.time.strftime("%H:%M"),
 | 
					            self.time.strftime("%H:%M"),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -97,12 +96,12 @@ class Schedule(Rerun):
 | 
				
			|||||||
        """Datetime of the end."""
 | 
					        """Datetime of the end."""
 | 
				
			||||||
        return self.start + utils.to_timedelta(self.duration)
 | 
					        return self.start + utils.to_timedelta(self.duration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_frequency_verbose(self):
 | 
					    def get_frequency_display(self):
 | 
				
			||||||
        """Return frequency formated for display."""
 | 
					        """Return frequency formated for display."""
 | 
				
			||||||
        from django.template.defaultfilters import date
 | 
					        from django.template.defaultfilters import date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            self.get_frequency_display()
 | 
					            self._get_FIELD_display(self._meta.get_field("frequency"))
 | 
				
			||||||
            .format(day=date(self.date, "l"))
 | 
					            .format(day=date(self.date, "l"))
 | 
				
			||||||
            .capitalize()
 | 
					            .capitalize()
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
@ -156,16 +155,6 @@ class Schedule(Rerun):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return [self.normalize(date) for date in dates if date.month == month]
 | 
					        return [self.normalize(date) for date in dates if date.month == month]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _exclude_existing_date(self, dates):
 | 
					 | 
				
			||||||
        from .diffusion import Diffusion
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        saved = set(
 | 
					 | 
				
			||||||
            Diffusion.objects.filter(start__in=dates).values_list(
 | 
					 | 
				
			||||||
                "start", flat=True
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        return [date for date in dates if date not in saved]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def diffusions_of_month(self, date):
 | 
					    def diffusions_of_month(self, date):
 | 
				
			||||||
        """Get episodes and diffusions for month of provided date, including
 | 
					        """Get episodes and diffusions for month of provided date, including
 | 
				
			||||||
        reruns.
 | 
					        reruns.
 | 
				
			||||||
@ -186,13 +175,11 @@ class Schedule(Rerun):
 | 
				
			|||||||
            (rerun, rerun.date - self.date) for rerun in self.rerun_set.all()
 | 
					            (rerun, rerun.date - self.date) for rerun in self.rerun_set.all()
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dates = OrderedDict((date, None) for date in self.dates_of_month(date))
 | 
					        dates = {date: None for date in self.dates_of_month(date)}
 | 
				
			||||||
        dates.update(
 | 
					        dates.update(
 | 
				
			||||||
            [
 | 
					            (rerun.normalize(date.date() + delta), date)
 | 
				
			||||||
                (rerun.normalize(date.date() + delta), date)
 | 
					            for date in list(dates.keys())
 | 
				
			||||||
                for date in dates.keys()
 | 
					            for rerun, delta in reruns
 | 
				
			||||||
                for rerun, delta in reruns
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # remove dates corresponding to existing diffusions
 | 
					        # remove dates corresponding to existing diffusions
 | 
				
			||||||
 | 
				
			|||||||
@ -43,7 +43,7 @@
 | 
				
			|||||||
<section>
 | 
					<section>
 | 
				
			||||||
    <h4 class="title is-4">{% translate "Diffusions" %}</h4>
 | 
					    <h4 class="title is-4">{% translate "Diffusions" %}</h4>
 | 
				
			||||||
    {% for schedule in program.schedule_set.all %}
 | 
					    {% for schedule in program.schedule_set.all %}
 | 
				
			||||||
    {{ schedule.get_frequency_verbose }}
 | 
					    {{ schedule.get_frequency_display }}
 | 
				
			||||||
    {% with schedule.start|date:"H:i" as start %}
 | 
					    {% with schedule.start|date:"H:i" as start %}
 | 
				
			||||||
    {% with schedule.end|date:"H:i" as end %}
 | 
					    {% with schedule.end|date:"H:i" as end %}
 | 
				
			||||||
    <time datetime="{{ start }}">{{ start }}</time>
 | 
					    <time datetime="{{ start }}">{{ start }}</time>
 | 
				
			||||||
 | 
				
			|||||||
@ -4,47 +4,60 @@ import itertools
 | 
				
			|||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from model_bakery import baker
 | 
					from model_bakery import baker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from aircox.models import Diffusion
 | 
					from aircox import models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def stations():
 | 
					def stations():
 | 
				
			||||||
    return baker.make("aircox.station", quantity=2)
 | 
					    return baker.make("aircox.station", _quantity=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def programs(stations):
 | 
					def programs(stations):
 | 
				
			||||||
    return list(
 | 
					    items = list(
 | 
				
			||||||
        itertools.chain(
 | 
					        itertools.chain(
 | 
				
			||||||
            *(
 | 
					            *(
 | 
				
			||||||
                baker.make("aircox.program", quantity=3, station=station)
 | 
					                baker.make("aircox.program", station=station, _quantity=3)
 | 
				
			||||||
                for station in stations
 | 
					                for station in stations
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					    for item in items:
 | 
				
			||||||
 | 
					        item.save()
 | 
				
			||||||
 | 
					    return items
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def sched_initials(programs):
 | 
					def sched_initials(programs):
 | 
				
			||||||
    # use concrete class
 | 
					    # use concrete class; timezone is provided in order to ensure DST
 | 
				
			||||||
    return [
 | 
					    items = [
 | 
				
			||||||
        baker.make("aircox.schedule", program=program, time=time(16, 00))
 | 
					        baker.prepare(
 | 
				
			||||||
 | 
					            "aircox.schedule",
 | 
				
			||||||
 | 
					            program=program,
 | 
				
			||||||
 | 
					            time=time(16, 00),
 | 
				
			||||||
 | 
					            timezone="Europe/Brussels",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
        for program in programs
 | 
					        for program in programs
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					    models.Schedule.objects.bulk_create(items)
 | 
				
			||||||
 | 
					    return items
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def sched_reruns(initials):
 | 
					def sched_reruns(sched_initials):
 | 
				
			||||||
    # use concrete class
 | 
					    # use concrete class
 | 
				
			||||||
    return [
 | 
					    items = [
 | 
				
			||||||
        baker.make(
 | 
					        baker.prepare(
 | 
				
			||||||
            "aircox.schedule",
 | 
					            "aircox.schedule",
 | 
				
			||||||
            initial=initial,
 | 
					            initial=initial,
 | 
				
			||||||
 | 
					            program=initial.program,
 | 
				
			||||||
            date=initial.date,
 | 
					            date=initial.date,
 | 
				
			||||||
            time=(initial.start + timedelta(hours=1)).time(),
 | 
					            time=(initial.start + timedelta(hours=1)).time(),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        for initial in initials
 | 
					        for initial in sched_initials
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					    models.Schedule.objects.bulk_create(items)
 | 
				
			||||||
 | 
					    return items
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
@ -54,10 +67,6 @@ def schedules(sched_initials, sched_reruns):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def episodes(programs):
 | 
					def episodes(programs):
 | 
				
			||||||
    items = []
 | 
					    return [
 | 
				
			||||||
    for program in programs:
 | 
					        baker.make("aircox.episode", parent=program) for program in programs
 | 
				
			||||||
        items += [
 | 
					    ]
 | 
				
			||||||
            baker.make("aircox.episode", parent=program, type=type)
 | 
					 | 
				
			||||||
            for type, _ in Diffusion.TYPE_CHOICES
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    return items
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -10,60 +10,60 @@ from aircox.models import Schedule
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class TestRerunQuerySet:
 | 
					class TestRerunQuerySet:
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_station_by_obj(self, stations):
 | 
					    def test_station_by_obj(self, stations, schedules):
 | 
				
			||||||
        for station in stations:
 | 
					        for station in stations:
 | 
				
			||||||
            queryset = (
 | 
					            queryset = (
 | 
				
			||||||
                Schedule.objects.station(station)
 | 
					                Schedule.objects.station(station)
 | 
				
			||||||
                .distinct()
 | 
					                .distinct()
 | 
				
			||||||
                .value_list("station", flat=True)
 | 
					                .values_list("program__station", flat=True)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            assert queryset.count() == 1
 | 
					            assert queryset.count() == 1
 | 
				
			||||||
            assert queryset.first() == station
 | 
					            assert queryset.first() == station.pk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_station_by_id(self, stations):
 | 
					    def test_station_by_id(self, stations, schedules):
 | 
				
			||||||
        for station in stations:
 | 
					        for station in stations:
 | 
				
			||||||
            queryset = (
 | 
					            queryset = (
 | 
				
			||||||
                Schedule.objects.station(id=station.pk)
 | 
					                Schedule.objects.station(id=station.pk)
 | 
				
			||||||
                .distinct()
 | 
					                .distinct()
 | 
				
			||||||
                .value_list("station", flat=True)
 | 
					                .values_list("program__station", flat=True)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            assert queryset.count() == 1
 | 
					            assert queryset.count() == 1
 | 
				
			||||||
            assert queryset.first() == station
 | 
					            assert queryset.first() == station.pk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_program_by_obj(self, programs):
 | 
					    def test_program_by_obj(self, programs, schedules):
 | 
				
			||||||
        for program in programs:
 | 
					        for program in programs:
 | 
				
			||||||
            queryset = (
 | 
					            queryset = (
 | 
				
			||||||
                Schedule.objects.program(program)
 | 
					                Schedule.objects.program(program)
 | 
				
			||||||
                .distinct()
 | 
					                .distinct()
 | 
				
			||||||
                .value_list("program", flat=True)
 | 
					                .values_list("program", flat=True)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            assert queryset.count() == 1
 | 
					            assert queryset.count() == 1
 | 
				
			||||||
            assert queryset.first() == program
 | 
					            assert queryset.first() == program.pk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_program_by_id(self, programs):
 | 
					    def test_program_by_id(self, programs, schedules):
 | 
				
			||||||
        for program in programs:
 | 
					        for program in programs:
 | 
				
			||||||
            queryset = (
 | 
					            queryset = (
 | 
				
			||||||
                Schedule.objects.program(id=program.pk)
 | 
					                Schedule.objects.program(id=program.pk)
 | 
				
			||||||
                .distinct()
 | 
					                .distinct()
 | 
				
			||||||
                .value_list("program", flat=True)
 | 
					                .values_list("program", flat=True)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            assert queryset.count() == 1
 | 
					            assert queryset.count() == 1
 | 
				
			||||||
            assert queryset.first() == program
 | 
					            assert queryset.first() == program.pk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_rerun(self, sched_reruns):
 | 
					    def test_rerun(self, schedules):
 | 
				
			||||||
        queryset = Schedule.objects.rerun().value_list("initial", flat=True)
 | 
					        queryset = Schedule.objects.rerun().values_list("initial", flat=True)
 | 
				
			||||||
        assert None not in queryset
 | 
					        assert None not in queryset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_initial(self, sched_initials):
 | 
					    def test_initial(self, schedules):
 | 
				
			||||||
        queryset = (
 | 
					        queryset = (
 | 
				
			||||||
            Schedule.objects.rerun()
 | 
					            Schedule.objects.initial()
 | 
				
			||||||
            .distinct()
 | 
					            .distinct()
 | 
				
			||||||
            .value_list("initial", flat=True)
 | 
					            .values_list("initial", flat=True)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        assert queryset.count() == 1
 | 
					        assert queryset.count() == 1
 | 
				
			||||||
        assert queryset.first() is None
 | 
					        assert queryset.first() is None
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,13 @@
 | 
				
			|||||||
 | 
					from datetime import date, datetime, time, timedelta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from datetime import datetime
 | 
					from model_bakery import baker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import calendar
 | 
				
			||||||
 | 
					from dateutil.relativedelta import relativedelta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from aircox import utils
 | 
					from aircox import utils
 | 
				
			||||||
 | 
					from aircox.models import Diffusion, Schedule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestSchedule:
 | 
					class TestSchedule:
 | 
				
			||||||
@ -32,43 +38,98 @@ class TestSchedule:
 | 
				
			|||||||
            delta = utils.to_timedelta(schedule.duration)
 | 
					            delta = utils.to_timedelta(schedule.duration)
 | 
				
			||||||
            assert schedule.end - schedule.start == delta
 | 
					            assert schedule.end - schedule.start == delta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # def test_get_frequency_verbose(self):
 | 
					    # def test_get_frequency_display(self):
 | 
				
			||||||
    #    pass
 | 
					    #    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_normalize(self, schedules):
 | 
					    def test_normalize(self, schedules):
 | 
				
			||||||
        for schedule in schedules:
 | 
					        for schedule in schedules:
 | 
				
			||||||
            dt = datetime.combine(schedule.date, schedule.time)
 | 
					            dt = datetime.combine(schedule.date, schedule.time)
 | 
				
			||||||
            assert schedule.normalize(dt).tzinfo.zone == schedule.timezone.zone
 | 
					            assert schedule.normalize(dt).tzinfo.zone == schedule.timezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_dates_of_month_ponctual(self):
 | 
					    def test_dates_of_month_ponctual(self):
 | 
				
			||||||
        pass
 | 
					        schedule = baker.prepare(
 | 
				
			||||||
 | 
					            Schedule, frequency=Schedule.Frequency.ponctual
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        at = schedule.date + relativedelta(months=4)
 | 
				
			||||||
 | 
					        assert schedule.dates_of_month(at) == []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_dates_of_month_n_day_of_month(self):
 | 
					    @pytest.mark.parametrize("months", range(0, 25, 2))
 | 
				
			||||||
        pass
 | 
					    @pytest.mark.parametrize("hour", range(0, 24, 3))
 | 
				
			||||||
 | 
					    def test_dates_of_month_last(self, months, hour):
 | 
				
			||||||
 | 
					        schedule = baker.prepare(
 | 
				
			||||||
 | 
					            Schedule, time=time(hour, 00), frequency=Schedule.Frequency.last
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        at = schedule.date + relativedelta(months=months)
 | 
				
			||||||
 | 
					        datetimes = schedule.dates_of_month(at)
 | 
				
			||||||
 | 
					        assert len(datetimes) == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dt = datetimes[0]
 | 
				
			||||||
 | 
					        self._assert_date(schedule, at, dt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        month_info = calendar.monthrange(at.year, at.month)
 | 
				
			||||||
 | 
					        at = date(at.year, at.month, month_info[1])
 | 
				
			||||||
 | 
					        if at.weekday() < schedule.date.weekday():
 | 
				
			||||||
 | 
					            at -= timedelta(days=7)
 | 
				
			||||||
 | 
					        at += timedelta(days=schedule.date.weekday()) - timedelta(
 | 
				
			||||||
 | 
					            days=at.weekday()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        assert dt.date() == at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # since the same method is used for first, second, etc. frequencies
 | 
				
			||||||
 | 
					    # we assume testing every is sufficient
 | 
				
			||||||
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
 | 
					    @pytest.mark.parametrize("months", range(0, 25, 2))
 | 
				
			||||||
 | 
					    @pytest.mark.parametrize("hour", range(0, 24, 3))
 | 
				
			||||||
 | 
					    def test_dates_of_month_every(self, months, hour):
 | 
				
			||||||
 | 
					        schedule = baker.prepare(
 | 
				
			||||||
 | 
					            Schedule, time=time(hour, 00), frequency=Schedule.Frequency.every
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        at = schedule.date + relativedelta(months=months)
 | 
				
			||||||
 | 
					        datetimes = schedule.dates_of_month(at)
 | 
				
			||||||
 | 
					        last = None
 | 
				
			||||||
 | 
					        for dt in datetimes:
 | 
				
			||||||
 | 
					            self._assert_date(schedule, at, dt)
 | 
				
			||||||
 | 
					            if last:
 | 
				
			||||||
 | 
					                assert (dt - last).days == 7
 | 
				
			||||||
 | 
					            last = dt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_dates_of_month_first_and_third(self):
 | 
					    @pytest.mark.parametrize("months", range(0, 25, 2))
 | 
				
			||||||
        pass
 | 
					    @pytest.mark.parametrize("hour", range(0, 24, 3))
 | 
				
			||||||
 | 
					    def test_dates_of_month_one_on_two(self, months, hour):
 | 
				
			||||||
 | 
					        schedule = baker.prepare(
 | 
				
			||||||
 | 
					            Schedule,
 | 
				
			||||||
 | 
					            time=time(hour, 00),
 | 
				
			||||||
 | 
					            frequency=Schedule.Frequency.one_on_two,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        at = schedule.date + relativedelta(months=months)
 | 
				
			||||||
 | 
					        datetimes = schedule.dates_of_month(at)
 | 
				
			||||||
 | 
					        for dt in datetimes:
 | 
				
			||||||
 | 
					            self._assert_date(schedule, at, dt)
 | 
				
			||||||
 | 
					            delta = dt.date() - schedule.date
 | 
				
			||||||
 | 
					            assert delta.days % 14 == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _assert_date(self, schedule, at, dt):
 | 
				
			||||||
 | 
					        assert dt.year == at.year
 | 
				
			||||||
 | 
					        assert dt.month == at.month
 | 
				
			||||||
 | 
					        assert dt.weekday() == schedule.date.weekday()
 | 
				
			||||||
 | 
					        assert dt.time() == schedule.time
 | 
				
			||||||
 | 
					        assert dt.tzinfo.zone == schedule.timezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_dates_of_month_second_and_fourth(self):
 | 
					    def test_diffusions_of_month(self, sched_initials):
 | 
				
			||||||
        pass
 | 
					        # TODO: test values of initial, rerun
 | 
				
			||||||
 | 
					        for schedule in sched_initials:
 | 
				
			||||||
 | 
					            at = schedule.start + timedelta(days=30)
 | 
				
			||||||
 | 
					            dates = set(schedule.dates_of_month(at))
 | 
				
			||||||
 | 
					            episodes, diffusions = schedule.diffusions_of_month(at)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					            assert all(r.date in dates for r in episodes)
 | 
				
			||||||
    def test_dates_of_month_every(self):
 | 
					            assert all(
 | 
				
			||||||
        pass
 | 
					                (not r.initial or r.date in dates)
 | 
				
			||||||
 | 
					                and r.type == Diffusion.TYPE_ON_AIR
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					                for r in diffusions
 | 
				
			||||||
    def test_dates_of_month_one_on_two(self):
 | 
					            )
 | 
				
			||||||
        pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @pytest.mark.django_db
 | 
					 | 
				
			||||||
    def test__exclude_existing_date(self):
 | 
					 | 
				
			||||||
        pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @pytest.mark.django_db
 | 
					 | 
				
			||||||
    def test_diffusions_of_month(self):
 | 
					 | 
				
			||||||
        pass
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user