@ -80,7 +80,7 @@ class LogArchiver:
 | 
				
			|||||||
    def load_file(self, path):
 | 
					    def load_file(self, path):
 | 
				
			||||||
        with gzip.open(path, "rb") as archive:
 | 
					        with gzip.open(path, "rb") as archive:
 | 
				
			||||||
            data = archive.read()
 | 
					            data = archive.read()
 | 
				
			||||||
            logs = yaml.load(data)
 | 
					            logs = yaml.safe_load(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # we need to preload diffusions, sounds and tracks
 | 
					            # we need to preload diffusions, sounds and tracks
 | 
				
			||||||
            rels = {
 | 
					            rels = {
 | 
				
			||||||
 | 
				
			|||||||
@ -84,7 +84,6 @@ class SoundStats:
 | 
				
			|||||||
        self.stats = [SoxStats(self.path)]
 | 
					        self.stats = [SoxStats(self.path)]
 | 
				
			||||||
        position = 0
 | 
					        position = 0
 | 
				
			||||||
        length = self.stats[0].get("length")
 | 
					        length = self.stats[0].get("length")
 | 
				
			||||||
        print(self.stats, "-----")
 | 
					 | 
				
			||||||
        if not self.sample_length:
 | 
					        if not self.sample_length:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
import pytz
 | 
					from zoneinfo import ZoneInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.db.models import Q
 | 
					from django.db.models import Q
 | 
				
			||||||
from django.utils import timezone as tz
 | 
					from django.utils import timezone as tz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -11,38 +12,36 @@ __all__ = ("AircoxMiddleware",)
 | 
				
			|||||||
class AircoxMiddleware(object):
 | 
					class AircoxMiddleware(object):
 | 
				
			||||||
    """Middleware used to get default info for the given website.
 | 
					    """Middleware used to get default info for the given website.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Theses
 | 
					    It provide following request attributes:
 | 
				
			||||||
 | 
					    - ``station``: current Station
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    This middleware must be set after the middleware
 | 
					    This middleware must be set after the middleware
 | 
				
			||||||
        'django.contrib.auth.middleware.AuthenticationMiddleware',
 | 
					        'django.contrib.auth.middleware.AuthenticationMiddleware',
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    timezone_session_key = "aircox.timezone"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, get_response):
 | 
					    def __init__(self, get_response):
 | 
				
			||||||
        self.get_response = get_response
 | 
					        self.get_response = get_response
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_station(self, request):
 | 
					    def get_station(self, request):
 | 
				
			||||||
        """Return station for the provided request."""
 | 
					        """Return station for the provided request."""
 | 
				
			||||||
        expr = Q(default=True) | Q(hosts__contains=request.get_host())
 | 
					        host = request.get_host()
 | 
				
			||||||
        # case = Case(When(hosts__contains=request.get_host(), then=Value(0)),
 | 
					        expr = Q(default=True) | Q(hosts=host) | Q(hosts__contains=host + "\n")
 | 
				
			||||||
        #            When(default=True, then=Value(32)))
 | 
					 | 
				
			||||||
        return Station.objects.filter(expr).order_by("default").first()
 | 
					        return Station.objects.filter(expr).order_by("default").first()
 | 
				
			||||||
        #              .annotate(resolve_priority=case) \
 | 
					 | 
				
			||||||
        # .order_by('resolve_priority').first()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def init_timezone(self, request):
 | 
					    def init_timezone(self, request):
 | 
				
			||||||
        # note: later we can use http://freegeoip.net/ on user side if
 | 
					        # note: later we can use http://freegeoip.net/ on user side if
 | 
				
			||||||
        # required
 | 
					        # required
 | 
				
			||||||
        timezone = None
 | 
					        timezone = None
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            timezone = request.session.get("aircox.timezone")
 | 
					            timezone = request.session.get(self.timezone_session_key)
 | 
				
			||||||
            if timezone:
 | 
					            if timezone:
 | 
				
			||||||
                timezone = pytz.timezone(timezone)
 | 
					                timezone = ZoneInfo(timezone)
 | 
				
			||||||
 | 
					                tz.activate(timezone)
 | 
				
			||||||
        except Exception:
 | 
					        except Exception:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not timezone:
 | 
					 | 
				
			||||||
            timezone = tz.get_current_timezone()
 | 
					 | 
				
			||||||
            tz.activate(timezone)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __call__(self, request):
 | 
					    def __call__(self, request):
 | 
				
			||||||
        self.init_timezone(request)
 | 
					        self.init_timezone(request)
 | 
				
			||||||
        request.station = self.get_station(request)
 | 
					        request.station = self.get_station(request)
 | 
				
			||||||
 | 
				
			|||||||
@ -39,8 +39,10 @@ class DiffusionQuerySet(RerunQuerySet):
 | 
				
			|||||||
    def date(self, date=None, order=True):
 | 
					    def date(self, date=None, order=True):
 | 
				
			||||||
        """Diffusions occuring date."""
 | 
					        """Diffusions occuring date."""
 | 
				
			||||||
        date = date or datetime.date.today()
 | 
					        date = date or datetime.date.today()
 | 
				
			||||||
        start = tz.datetime.combine(date, datetime.time())
 | 
					        start = tz.make_aware(tz.datetime.combine(date, datetime.time()))
 | 
				
			||||||
        end = tz.datetime.combine(date, datetime.time(23, 59, 59, 999))
 | 
					        end = tz.make_aware(
 | 
				
			||||||
 | 
					            tz.datetime.combine(date, datetime.time(23, 59, 59, 999))
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
        # start = tz.get_current_timezone().localize(start)
 | 
					        # start = tz.get_current_timezone().localize(start)
 | 
				
			||||||
        # end = tz.get_current_timezone().localize(end)
 | 
					        # end = tz.get_current_timezone().localize(end)
 | 
				
			||||||
        qs = self.filter(start__range=(start, end))
 | 
					        qs = self.filter(start__range=(start, end))
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import calendar
 | 
					import calendar
 | 
				
			||||||
 | 
					import zoneinfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytz
 | 
					 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.utils import timezone as tz
 | 
					from django.utils import timezone as tz
 | 
				
			||||||
from django.utils.functional import cached_property
 | 
					from django.utils.functional import cached_property
 | 
				
			||||||
@ -49,9 +49,9 @@ class Schedule(Rerun):
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    timezone = models.CharField(
 | 
					    timezone = models.CharField(
 | 
				
			||||||
        _("timezone"),
 | 
					        _("timezone"),
 | 
				
			||||||
        default=lambda: tz.get_current_timezone().zone,
 | 
					        default=lambda: tz.get_current_timezone().key,
 | 
				
			||||||
        max_length=100,
 | 
					        max_length=100,
 | 
				
			||||||
        choices=[(x, x) for x in pytz.all_timezones],
 | 
					        choices=[(x, x) for x in zoneinfo.available_timezones()],
 | 
				
			||||||
        help_text=_("timezone used for the date"),
 | 
					        help_text=_("timezone used for the date"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    duration = models.TimeField(
 | 
					    duration = models.TimeField(
 | 
				
			||||||
@ -82,9 +82,7 @@ class Schedule(Rerun):
 | 
				
			|||||||
    @cached_property
 | 
					    @cached_property
 | 
				
			||||||
    def tz(self):
 | 
					    def tz(self):
 | 
				
			||||||
        """Pytz timezone of the schedule."""
 | 
					        """Pytz timezone of the schedule."""
 | 
				
			||||||
        import pytz
 | 
					        return zoneinfo.ZoneInfo(self.timezone)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return pytz.timezone(self.timezone)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @cached_property
 | 
					    @cached_property
 | 
				
			||||||
    def start(self):
 | 
					    def start(self):
 | 
				
			||||||
@ -110,7 +108,7 @@ class Schedule(Rerun):
 | 
				
			|||||||
        """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)."""
 | 
				
			||||||
        date = tz.datetime.combine(date, self.time)
 | 
					        date = tz.datetime.combine(date, self.time)
 | 
				
			||||||
        return self.tz.normalize(self.tz.localize(date))
 | 
					        return date.replace(tzinfo=self.tz)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def dates_of_month(self, date):
 | 
					    def dates_of_month(self, date):
 | 
				
			||||||
        """Return normalized diffusion dates of provided date's month."""
 | 
					        """Return normalized diffusion dates of provided date's month."""
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@ class Station(models.Model):
 | 
				
			|||||||
        max_length=512,
 | 
					        max_length=512,
 | 
				
			||||||
        null=True,
 | 
					        null=True,
 | 
				
			||||||
        blank=True,
 | 
					        blank=True,
 | 
				
			||||||
        help_text=_("specify one url per line"),
 | 
					        help_text=_("specify one domain per line, without 'http://' prefix"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    audio_streams = models.TextField(
 | 
					    audio_streams = models.TextField(
 | 
				
			||||||
        _("audio streams"),
 | 
					        _("audio streams"),
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ from datetime import time, timedelta
 | 
				
			|||||||
import itertools
 | 
					import itertools
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.conf import settings
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
from django.test import RequestFactory
 | 
					from django.test import RequestFactory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -16,6 +17,12 @@ req_factory = RequestFactory()
 | 
				
			|||||||
"""Request Factory used among different tests."""
 | 
					"""Request Factory used among different tests."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					settings.ALLOWED_HOSTS = list(settings.ALLOWED_HOSTS) + [
 | 
				
			||||||
 | 
					    "sub.server.org",
 | 
				
			||||||
 | 
					    "server.org",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def staff_user():
 | 
					def staff_user():
 | 
				
			||||||
    return baker.make(User, is_active=True, is_staff=True)
 | 
					    return baker.make(User, is_active=True, is_staff=True)
 | 
				
			||||||
@ -31,12 +38,23 @@ def logger():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def station():
 | 
					def station():
 | 
				
			||||||
    return baker.make(models.Station, audio_streams="stream 1\nstream 2")
 | 
					    return baker.make(
 | 
				
			||||||
 | 
					        models.Station,
 | 
				
			||||||
 | 
					        hosts="server.org",
 | 
				
			||||||
 | 
					        audio_streams="stream 1\nstream 2",
 | 
				
			||||||
 | 
					        default=True,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
def stations(station):
 | 
					def sub_station():
 | 
				
			||||||
    return [station, baker.make(models.Station)]
 | 
					    """Non-default station."""
 | 
				
			||||||
 | 
					    return baker.make(models.Station, hosts="sub.server.org", default=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
					def stations(station, sub_station):
 | 
				
			||||||
 | 
					    return [station, sub_station]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.fixture
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ class TestSchedule:
 | 
				
			|||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_tz(self, schedules):
 | 
					    def test_tz(self, schedules):
 | 
				
			||||||
        for schedule in schedules:
 | 
					        for schedule in schedules:
 | 
				
			||||||
            assert schedule.timezone == schedule.tz.zone
 | 
					            assert schedule.timezone == schedule.tz.key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_start(self, schedules):
 | 
					    def test_start(self, schedules):
 | 
				
			||||||
@ -45,7 +45,7 @@ class TestSchedule:
 | 
				
			|||||||
    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
 | 
					            assert schedule.normalize(dt).tzinfo.key == schedule.timezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_dates_of_month_ponctual(self):
 | 
					    def test_dates_of_month_ponctual(self):
 | 
				
			||||||
@ -117,7 +117,7 @@ class TestSchedule:
 | 
				
			|||||||
        assert dt.month == at.month
 | 
					        assert dt.month == at.month
 | 
				
			||||||
        assert dt.weekday() == schedule.date.weekday()
 | 
					        assert dt.weekday() == schedule.date.weekday()
 | 
				
			||||||
        assert dt.time() == schedule.time
 | 
					        assert dt.time() == schedule.time
 | 
				
			||||||
        assert dt.tzinfo.zone == schedule.timezone
 | 
					        assert dt.tzinfo.key == schedule.timezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.django_db
 | 
					    @pytest.mark.django_db
 | 
				
			||||||
    def test_diffusions_of_month(self, sched_initials):
 | 
					    def test_diffusions_of_month(self, sched_initials):
 | 
				
			||||||
 | 
				
			|||||||
@ -6,11 +6,11 @@ to:
 | 
				
			|||||||
- cancels Diffusions that have an archive but could not have been played;
 | 
					- cancels Diffusions that have an archive but could not have been played;
 | 
				
			||||||
- run Liquidsoap
 | 
					- run Liquidsoap
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from datetime import timezone
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from argparse import RawTextHelpFormatter
 | 
					from argparse import RawTextHelpFormatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytz
 | 
					 | 
				
			||||||
from django.core.management.base import BaseCommand
 | 
					from django.core.management.base import BaseCommand
 | 
				
			||||||
from django.utils import timezone as tz
 | 
					from django.utils import timezone as tz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -19,7 +19,7 @@ from aircox_streamer.controllers import Monitor, Streamer
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# force using UTC
 | 
					# force using UTC
 | 
				
			||||||
tz.activate(pytz.UTC)
 | 
					tz.activate(timezone.UTC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Command(BaseCommand):
 | 
					class Command(BaseCommand):
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					from zoneinfo import ZoneInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytz
 | 
					 | 
				
			||||||
from django.utils import timezone
 | 
					from django.utils import timezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sys.path.insert(1, os.path.dirname(os.path.realpath(__file__)))
 | 
					sys.path.insert(1, os.path.dirname(os.path.realpath(__file__)))
 | 
				
			||||||
@ -65,7 +65,7 @@ USE_I18N = True
 | 
				
			|||||||
USE_L10N = True
 | 
					USE_L10N = True
 | 
				
			||||||
USE_TZ = True
 | 
					USE_TZ = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
timezone.activate(pytz.timezone(TIME_ZONE))
 | 
					timezone.activate(ZoneInfo(TIME_ZONE))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
    import locale
 | 
					    import locale
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ For Django settings see:
 | 
				
			|||||||
    https://docs.djangoproject.com/en/3.1/topics/settings/
 | 
					    https://docs.djangoproject.com/en/3.1/topics/settings/
 | 
				
			||||||
    https://docs.djangoproject.com/en/3.1/ref/settings/
 | 
					    https://docs.djangoproject.com/en/3.1/ref/settings/
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					from zoneinfo import ZoneInfo
 | 
				
			||||||
from .prod import *
 | 
					from .prod import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# FOR dev: from .dev import *
 | 
					# FOR dev: from .dev import *
 | 
				
			||||||
@ -20,7 +21,7 @@ LANGUAGE_CODE = "fr-BE"
 | 
				
			|||||||
LC_LOCALE = "fr_BE.UTF-8"
 | 
					LC_LOCALE = "fr_BE.UTF-8"
 | 
				
			||||||
TIME_ZONE = "Europe/Brussels"
 | 
					TIME_ZONE = "Europe/Brussels"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
timezone.activate(pytz.timezone(TIME_ZONE))
 | 
					timezone.activate(ZoneInfo(TIME_ZONE))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Secret key: you MUST put a consistent secret key. You can generate one
 | 
					# Secret key: you MUST put a consistent secret key. You can generate one
 | 
				
			||||||
# at https://djecrety.ir/
 | 
					# at https://djecrety.ir/
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user