#93: reorganise Rerun, Diffusion, Schedule module #95
|
@ -165,7 +165,7 @@ class Diffusion(Rerun):
|
||||||
|
|
||||||
def save_rerun(self):
|
def save_rerun(self):
|
||||||
self.episode = self.initial.episode
|
self.episode = self.initial.episode
|
||||||
self.program = self.episode.program
|
super().save_rerun()
|
||||||
|
|
||||||
def save_initial(self):
|
def save_initial(self):
|
||||||
self.program = self.episode.program
|
self.program = self.episode.program
|
||||||
|
|
|
@ -64,24 +64,6 @@ class Rerun(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
if self.initial is not None:
|
|
||||||
self.initial = self.initial.get_initial()
|
|
||||||
if self.initial == self:
|
|
||||||
self.initial = None
|
|
||||||
|
|
||||||
if self.is_rerun:
|
|
||||||
self.save_rerun()
|
|
||||||
else:
|
|
||||||
self.save_initial()
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
|
|
||||||
def save_rerun(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def save_initial(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_initial(self):
|
def is_initial(self):
|
||||||
return self.initial is None
|
return self.initial is None
|
||||||
|
@ -96,7 +78,29 @@ class Rerun(models.Model):
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super().clean()
|
super().clean()
|
||||||
if self.initial is not None and self.initial.start >= self.start:
|
if (
|
||||||
|
hasattr(self, "start")
|
||||||
|
and self.initial is not None
|
||||||
|
and self.initial.start >= self.start
|
||||||
|
):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"initial": _("rerun must happen after original")}
|
{"initial": _("rerun must happen after original")}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def save_rerun(self):
|
||||||
|
self.program = self.initial.program
|
||||||
|
|
||||||
|
def save_initial(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.initial is not None:
|
||||||
|
self.initial = self.initial.get_initial()
|
||||||
|
if self.initial == self:
|
||||||
|
self.initial = None
|
||||||
|
|
||||||
|
if self.is_rerun:
|
||||||
|
self.save_rerun()
|
||||||
|
else:
|
||||||
|
self.save_initial()
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
|
@ -75,8 +75,8 @@ class Schedule(Rerun):
|
||||||
self.time.strftime("%H:%M"),
|
self.time.strftime("%H:%M"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def save_rerun(self, *args, **kwargs):
|
def save_rerun(self):
|
||||||
self.program = self.initial.program
|
super().save_rerun()
|
||||||
self.duration = self.initial.duration
|
self.duration = self.initial.duration
|
||||||
self.frequency = self.initial.frequency
|
self.frequency = self.initial.frequency
|
||||||
|
|
||||||
|
@ -107,23 +107,6 @@ class Schedule(Rerun):
|
||||||
.capitalize()
|
.capitalize()
|
||||||
)
|
)
|
||||||
|
|
||||||
# initial cached data
|
|
||||||
__initial = None
|
|
||||||
|
|
||||||
def changed(self, fields=["date", "duration", "frequency", "timezone"]):
|
|
||||||
initial = self._Schedule__initial
|
|
||||||
|
|
||||||
if not initial:
|
|
||||||
return
|
|
||||||
|
|
||||||
this = self.__dict__
|
|
||||||
|
|
||||||
for field in fields:
|
|
||||||
if initial.get(field) != this.get(field):
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def normalize(self, date):
|
def normalize(self, date):
|
||||||
"""Return a datetime set to schedule's time for the provided date,
|
"""Return a datetime set to schedule's time for the provided date,
|
||||||
handling timezone (based on schedule's timezone)."""
|
handling timezone (based on schedule's timezone)."""
|
||||||
|
@ -245,10 +228,3 @@ class Schedule(Rerun):
|
||||||
end=date + duration,
|
end=date + duration,
|
||||||
)
|
)
|
||||||
return episodes.values(), diffusions.values()
|
return episodes.values(), diffusions.values()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
# TODO/FIXME: use validators?
|
|
||||||
if self.initial is not None and self.date > self.date:
|
|
||||||
raise ValueError("initial must be later")
|
|
||||||
|
|
63
aircox/tests/conftest.py
Normal file
63
aircox/tests/conftest.py
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
from datetime import time, timedelta
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from model_bakery import baker
|
||||||
|
|
||||||
|
from aircox.models import Diffusion
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def stations():
|
||||||
|
return baker.make("aircox.station", quantity=2)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def programs(stations):
|
||||||
|
return list(
|
||||||
|
itertools.chain(
|
||||||
|
*(
|
||||||
|
baker.make("aircox.program", quantity=3, station=station)
|
||||||
|
for station in stations
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def sched_initials(programs):
|
||||||
|
# use concrete class
|
||||||
|
return [
|
||||||
|
baker.make("aircox.schedule", program=program, time=time(16, 00))
|
||||||
|
for program in programs
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def sched_reruns(initials):
|
||||||
|
# use concrete class
|
||||||
|
return [
|
||||||
|
baker.make(
|
||||||
|
"aircox.schedule",
|
||||||
|
initial=initial,
|
||||||
|
date=initial.date,
|
||||||
|
time=(initial.start + timedelta(hours=1)).time(),
|
||||||
|
)
|
||||||
|
for initial in initials
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def schedules(sched_initials, sched_reruns):
|
||||||
|
return sched_initials + sched_reruns
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def episodes(programs):
|
||||||
|
items = []
|
||||||
|
for program in programs:
|
||||||
|
items += [
|
||||||
|
baker.make("aircox.episode", parent=program, type=type)
|
||||||
|
for type, _ in Diffusion.TYPE_CHOICES
|
||||||
|
]
|
||||||
|
return items
|
19
aircox/tests/models/test_diffusion.py
Normal file
19
aircox/tests/models/test_diffusion.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
class TestDiffusionQuerySet:
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_episode_by_obj(self, episodes):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_episode_by_id(self, episodes):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_on_air(self, episodes):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_now(self, episodes):
|
||||||
|
pass
|
117
aircox/tests/models/test_rerun.py
Normal file
117
aircox/tests/models/test_rerun.py
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
|
# we use Schedule as concrete class (Rerun is abstract)
|
||||||
|
from aircox.models import Schedule
|
||||||
|
|
||||||
|
|
||||||
|
class TestRerunQuerySet:
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_station_by_obj(self, stations):
|
||||||
|
for station in stations:
|
||||||
|
queryset = (
|
||||||
|
Schedule.objects.station(station)
|
||||||
|
.distinct()
|
||||||
|
.value_list("station", flat=True)
|
||||||
|
)
|
||||||
|
assert queryset.count() == 1
|
||||||
|
assert queryset.first() == station
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_station_by_id(self, stations):
|
||||||
|
for station in stations:
|
||||||
|
queryset = (
|
||||||
|
Schedule.objects.station(id=station.pk)
|
||||||
|
.distinct()
|
||||||
|
.value_list("station", flat=True)
|
||||||
|
)
|
||||||
|
assert queryset.count() == 1
|
||||||
|
assert queryset.first() == station
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_program_by_obj(self, programs):
|
||||||
|
for program in programs:
|
||||||
|
queryset = (
|
||||||
|
Schedule.objects.program(program)
|
||||||
|
.distinct()
|
||||||
|
.value_list("program", flat=True)
|
||||||
|
)
|
||||||
|
assert queryset.count() == 1
|
||||||
|
assert queryset.first() == program
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_program_by_id(self, programs):
|
||||||
|
for program in programs:
|
||||||
|
queryset = (
|
||||||
|
Schedule.objects.program(id=program.pk)
|
||||||
|
.distinct()
|
||||||
|
.value_list("program", flat=True)
|
||||||
|
)
|
||||||
|
assert queryset.count() == 1
|
||||||
|
assert queryset.first() == program
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_rerun(self, sched_reruns):
|
||||||
|
queryset = Schedule.objects.rerun().value_list("initial", flat=True)
|
||||||
|
assert None not in queryset
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_initial(self, sched_initials):
|
||||||
|
queryset = (
|
||||||
|
Schedule.objects.rerun()
|
||||||
|
.distinct()
|
||||||
|
.value_list("initial", flat=True)
|
||||||
|
)
|
||||||
|
assert queryset.count() == 1
|
||||||
|
assert queryset.first() is None
|
||||||
|
|
||||||
|
|
||||||
|
class TestRerun:
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_is_initial_true(self, sched_initials):
|
||||||
|
assert all(r.is_initial for r in sched_initials)
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_is_initial_false(self, sched_reruns):
|
||||||
|
assert all(not r.is_initial for r in sched_reruns)
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_is_rerun_true(self, sched_reruns):
|
||||||
|
assert all(r.is_rerun for r in sched_reruns)
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_is_rerun_false(self, sched_initials):
|
||||||
|
assert all(not r.is_rerun for r in sched_initials)
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_get_initial_of_initials(self, sched_initials):
|
||||||
|
assert all(r.get_initial() is r for r in sched_initials)
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_get_initial_of_reruns(self, sched_reruns):
|
||||||
|
assert all(r.get_initial() is r.initial for r in sched_reruns)
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_clean_success(self, sched_reruns):
|
||||||
|
for rerun in sched_reruns:
|
||||||
|
rerun.clean()
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_clean_fails(self, sched_reruns):
|
||||||
|
for rerun in sched_reruns:
|
||||||
|
rerun.time = (rerun.initial.start - timedelta(hours=2)).time()
|
||||||
|
with pytest.raises(ValidationError):
|
||||||
|
rerun.clean()
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_save_rerun(self, sched_reruns):
|
||||||
|
for rerun in sched_reruns:
|
||||||
|
rerun.program = None
|
||||||
|
rerun.save_rerun()
|
||||||
|
assert rerun.program == rerun.initial.program
|
||||||
|
|
||||||
|
# TODO: save()
|
||||||
|
# save_initial is empty, thus not tested
|
74
aircox/tests/models/test_schedule.py
Normal file
74
aircox/tests/models/test_schedule.py
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import pytest
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from aircox import utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestSchedule:
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_save_rerun(self, sched_reruns):
|
||||||
|
for schedule in sched_reruns:
|
||||||
|
schedule.duration = None
|
||||||
|
schedule.frequency = None
|
||||||
|
schedule.save_rerun()
|
||||||
|
assert schedule.program == schedule.initial.program
|
||||||
|
assert schedule.duration == schedule.initial.duration
|
||||||
|
assert schedule.frequency == schedule.initial.frequency
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_tz(self, schedules):
|
||||||
|
for schedule in schedules:
|
||||||
|
assert schedule.timezone == schedule.tz.zone
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_start(self, schedules):
|
||||||
|
for schedule in schedules:
|
||||||
|
assert schedule.start.date() == schedule.date
|
||||||
|
assert schedule.start.time() == schedule.time
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_end(self, schedules):
|
||||||
|
for schedule in schedules:
|
||||||
|
delta = utils.to_timedelta(schedule.duration)
|
||||||
|
assert schedule.end - schedule.start == delta
|
||||||
|
|
||||||
|
# def test_get_frequency_verbose(self):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_normalize(self, schedules):
|
||||||
|
for schedule in schedules:
|
||||||
|
dt = datetime.combine(schedule.date, schedule.time)
|
||||||
|
assert schedule.normalize(dt).tzinfo.zone == schedule.timezone.zone
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_dates_of_month_ponctual(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_dates_of_month_n_day_of_month(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_dates_of_month_first_and_third(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_dates_of_month_second_and_fourth(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_dates_of_month_every(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
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
|
|
@ -1,2 +1,3 @@
|
||||||
pytest~=7.2
|
pytest~=7.2
|
||||||
pytest-django~=4.5
|
pytest-django~=4.5
|
||||||
|
model_bakery~=1.10
|
||||||
|
|
Loading…
Reference in New Issue
Block a user