From acd0737d5dad996cd4510938c4b26aef3da712c8 Mon Sep 17 00:00:00 2001 From: bkfox Date: Tue, 21 Jun 2016 00:13:10 +0200 Subject: [PATCH] ThreadRoute.title as url; update scripts about old Diffusion.sounds -> Sound.Diffusion (still need tests); cleanup unused and old code --- cms/routes.py | 12 ++- cms/templates/aircox/cms/website.html | 4 +- cms/views.py | 2 +- liquidsoap/management/commands/liquidsoap.py | 19 +++-- .../management/commands/liquidsoap_log.py | 62 -------------- notes.md | 9 +- programs/admin.py | 22 ++--- .../management/commands/sounds_monitor.py | 85 +++++++++---------- programs/models.py | 27 ++---- programs/utils.py | 9 -- 10 files changed, 85 insertions(+), 166 deletions(-) delete mode 100644 liquidsoap/management/commands/liquidsoap_log.py diff --git a/cms/routes.py b/cms/routes.py index f76a02c..b213241 100644 --- a/cms/routes.py +++ b/cms/routes.py @@ -127,10 +127,14 @@ class ThreadRoute(Route): @classmethod def get_title(cl, model, request, thread_model, pk, **kwargs): - return _('%(name)s: %(model)s') % { - 'model': model._meta.verbose_name_plural, - 'name': cl.get_thread(model, thread_model, pk).title, - } + thread = cl.get_thread(model, thread_model, pk) + return '{title}'.format( + url = thread.url(), + title = _('%(name)s: %(model)s') % { + 'model': model._meta.verbose_name_plural, + 'name': thread.title, + } + ) class DateRoute(Route): diff --git a/cms/templates/aircox/cms/website.html b/cms/templates/aircox/cms/website.html index f8e6470..83fae0a 100644 --- a/cms/templates/aircox/cms/website.html +++ b/cms/templates/aircox/cms/website.html @@ -14,7 +14,7 @@ {% endif %} - {% if title %}{{ title }} - {% endif %}{{ website.name }} + {% if title %}{{ title|striptags }} - {% endif %}{{ website.name }} {% block page_header %} @@ -51,7 +51,7 @@ {% endif %} {% block title %} {% if title %} -

{{ title }}

+

{{ title|safe }}

{% endif %} {% endblock %} diff --git a/cms/views.py b/cms/views.py index 542e2f6..b52b386 100644 --- a/cms/views.py +++ b/cms/views.py @@ -187,7 +187,7 @@ class PostListView(BaseView, ListView): context = super().get_context_data(**kwargs) - if not context.get('title') and self.route: + if self.route and not context.get('title'): context['title'] = self.route.get_title( self.model, self.request, **self.kwargs ) diff --git a/liquidsoap/management/commands/liquidsoap.py b/liquidsoap/management/commands/liquidsoap.py index add2512..2773d08 100644 --- a/liquidsoap/management/commands/liquidsoap.py +++ b/liquidsoap/management/commands/liquidsoap.py @@ -95,15 +95,18 @@ class Monitor: # - preload next diffusion's tracks args = {'start__gt': prev_diff.start } if prev_diff else {} - next_diff = programs.Diffusion \ - .get(now, now = True, - type = programs.Diffusion.Type.normal, - sounds__isnull = False, - **args) \ - .prefetch_related('sounds') + next_diff = programs.Diffusion.get( + now, now = True, + type = programs.Diffusion.Type.normal, + **args + ) if next_diff: - next_diff = next_diff[0] - playlist += next_diff.playlist + for diff in next_diffs: + if not diff.playlist: + continue + next_diff = diff + playlist += next_diff.playlist + break # playlist update if dealer.playlist != playlist: diff --git a/liquidsoap/management/commands/liquidsoap_log.py b/liquidsoap/management/commands/liquidsoap_log.py deleted file mode 100644 index 8d36e50..0000000 --- a/liquidsoap/management/commands/liquidsoap_log.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -This script is used by liquidsoap in order to log a file change. It should not -be used for other purposes. -""" -import os -from argparse import RawTextHelpFormatter - -from django.utils import timezone as tz -from django.core.management.base import BaseCommand, CommandError - -import aircox.programs.models as programs - - -class Command (BaseCommand): - help= __doc__ - - @staticmethod - def date(s): - try: - return tz.make_aware(tz.datetime.strptime(s, '%Y/%m/%d %H:%M:%S')) - except ValueError: - raise argparse.ArgumentTypeError('Invalid date format') - - - def add_arguments (self, parser): - parser.formatter_class=RawTextHelpFormatter - parser.add_argument( - '-c', '--comment', type=str, - help='log comment' - ) - parser.add_argument( - '-s', '--source', type=str, - required=True, - help='source path' - ) - parser.add_argument( - '-p', '--path', type=str, - required=True, - help='sound path to log' - ) - parser.add_argument( - '-d', '--date', type=Command.date, - help='set date instead of now (using format "%Y/%m/%d %H:%M:%S")' - ) - - - def handle (self, *args, **options): - comment = options.get('comment') or '' - path = os.path.realpath(options.get('path')) - - sound = programs.Sound.objects.filter(path = path) - if sound: - sound = sound[0] - else: - sound = None - comment += '\nunregistered sound: {}'.format(path) - - programs.Log(source = options.get('source'), - comment = comment, - related_object = sound).save() - - diff --git a/notes.md b/notes.md index 83d374b..eb808a5 100644 --- a/notes.md +++ b/notes.md @@ -13,9 +13,9 @@ - sounds: - check that a sound is available when uploading too - one sound, one diffusion - -> update admin & inlining -> sound_monitor -> liquidsoap + -> tests: sound_monitor, liquidsoap (monitor) - liquidsoap: - update rc's supervisor scripts @@ -29,15 +29,15 @@ - cms.script - cms.qcombine - routes - - customized header depending on the list (e.g. thread -> link to thread parent) - integrate QCombine - admin cms - content management -> do we use a markup language? - sections: - - article list with the focus - similar articles (using tags) - calendar - - tags: allow tags_url on all publications + - article list with the focus + -> set html attribute based on values that are public + - tags: allow tags_url route QCombine - website: - diffusions: @@ -51,6 +51,7 @@ - load complete week for a schedule? - finish that fucking website - list of played diffusions and tracks when non-stop; + - search field -- section diff --git a/programs/admin.py b/programs/admin.py index b85d193..f8c52e0 100755 --- a/programs/admin.py +++ b/programs/admin.py @@ -24,8 +24,17 @@ class StreamInline(admin.TabularInline): model = Stream extra = 1 -class SoundDiffInline(admin.TabularInline): +class SoundInline(admin.TabularInline): + fields = ['type', 'path', 'duration'] + readonly_fields = fields model = Sound + extra = 0 + + +class DiffusionInline(admin.StackedInline): + model = Diffusion + extra = 0 + fields = ['type', 'start', 'end'] # from suit.admin import SortableTabularInline, SortableModelAdmin #class TrackInline(SortableTabularInline): @@ -83,11 +92,6 @@ class ProgramAdmin(NameableAdmin): #return super().get_form(request, obj, **kwargs) -class DiffusionInline(admin.StackedInline): - model = Diffusion - extra = 0 - fields = ['type', 'start', 'end'] - @admin.register(Diffusion) class DiffusionAdmin(admin.ModelAdmin): def archives(self, obj): @@ -112,8 +116,7 @@ class DiffusionAdmin(admin.ModelAdmin): ordering = ('-start', 'id') fields = ['type', 'start', 'end', 'initial', 'program'] - inlines = [ DiffusionInline, SoundDiffInline ] - exclude = ('sounds',) + inlines = [ DiffusionInline, SoundInline ] def get_form(self, request, obj=None, **kwargs): @@ -121,9 +124,6 @@ class DiffusionAdmin(admin.ModelAdmin): self.readonly_fields = [] else: self.readonly_fields = ['program', 'start', 'end'] - - if obj and obj.initial: - self.readonly_fields += ['program', 'sounds'] return super().get_form(request, obj, **kwargs) def get_object(self, *args, **kwargs): diff --git a/programs/management/commands/sounds_monitor.py b/programs/management/commands/sounds_monitor.py index b84bff7..57b92ed 100644 --- a/programs/management/commands/sounds_monitor.py +++ b/programs/management/commands/sounds_monitor.py @@ -51,11 +51,11 @@ class SoundInfo: duration = None @property - def path (self): + def path(self): return self._path @path.setter - def path (self, value): + def path(self, value): """ Parse file name to get info on the assumption it has the correct format (given in Command.help) @@ -83,10 +83,10 @@ class SoundInfo: self.n = r.get('n') return r - def __init__ (self, path = ''): + def __init__(self, path = ''): self.path = path - def get_duration (self): + def get_duration(self): p = subprocess.Popen(['soxi', '-D', self.path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -96,7 +96,7 @@ class SoundInfo: self.duration = duration return duration - def get_sound (self, kwargs = None, save = True): + def get_sound(self, kwargs = None, save = True): """ Get or create a sound using self info. @@ -116,47 +116,42 @@ class SoundInfo: self.sound = sound return sound - def find_diffusion (self, program, attach = False): + def find_diffusion(self, program, save = True): """ For a given program, check if there is an initial diffusion - to associate to, using the date info we have. + to associate to, using the date info we have. Update self.sound + and save it consequently. We only allow initial diffusion since there should be no rerun. - - If attach is True and we have self.sound, we add self.sound to - the diffusion and update the DB. """ - if self.year == None: + if self.year == None or not self.sound or self.sound.diffusion: return; - # check on episodes diffusion = Diffusion.objects.filter( program = program, + initial__isnull = True, start__year = self.year, start__month = self.month, start__day = self.day, - initial = None, ) if not diffusion: return - diffusion = diffusion[0] - if attach and self.sound: - qs = diffusion.sounds.get_queryset().filter(path = sound.path) - if not qs: - logger.info('diffusion %s mathes to sound -> %s', str(diffusion), - sound.path) - diffusion.sounds.add(sound.pk) - diffusion.save() + + logger.info('diffusion %s mathes to sound -> %s', str(diffusion), + sound.path) + self.sound.diffusion = diffusion + if save: + self.sound.save() return diffusion -class MonitorHandler (PatternMatchingEventHandler): +class MonitorHandler(PatternMatchingEventHandler): """ Event handler for watchdog, in order to be used in monitoring. """ - def __init__ (self, subdir): + def __init__(self, subdir): """ subdir: AIRCOX_SOUND_ARCHIVES_SUBDIR or AIRCOX_SOUND_EXCERPTS_SUBDIR """ @@ -170,10 +165,10 @@ class MonitorHandler (PatternMatchingEventHandler): for ext in settings.AIRCOX_SOUND_FILE_EXT ] super().__init__(patterns=patterns, ignore_directories=True) - def on_created (self, event): + def on_created(self, event): self.on_modified(event) - def on_modified (self, event): + def on_modified(self, event): logger.info('sound modified: %s', event.src_path) program = Program.get_from_path(event.src_path) if not program: @@ -182,9 +177,9 @@ class MonitorHandler (PatternMatchingEventHandler): si = SoundInfo(event.src_path) si.get_sound(self.sound_kwargs, True) if si.year != None: - si.find_diffusion(program, True) + si.find_diffusion(program) - def on_deleted (self, event): + def on_deleted(self, event): logger.info('sound deleted: %s', event.src_path) sound = Sound.objects.filter(path = event.src_path) if sound: @@ -192,7 +187,7 @@ class MonitorHandler (PatternMatchingEventHandler): sound.removed = True sound.save() - def on_moved (self, event): + def on_moved(self, event): logger.info('sound moved: %s -> %s', event.src_path, event.dest_path) sound = Sound.objects.filter(path = event.src_path) if not sound: @@ -206,17 +201,17 @@ class MonitorHandler (PatternMatchingEventHandler): sound.save() -class Command (BaseCommand): +class Command(BaseCommand): help= __doc__ - def report (self, program = None, component = None, *content): + def report(self, program = None, component = None, *content): if not component: logger.info('%s: %s', str(program), ' '.join([str(c) for c in content])) else: logger.info('%s, %s: %s', str(program), str(component), ' '.join([str(c) for c in content])) - def add_arguments (self, parser): + def add_arguments(self, parser): parser.formatter_class=RawTextHelpFormatter parser.add_argument( '-q', '--quality_check', action='store_true', @@ -226,7 +221,7 @@ class Command (BaseCommand): parser.add_argument( '-s', '--scan', action='store_true', help='Scan programs directories for changes, plus check for a ' - ' matching episode on sounds that have not been yet assigned' + ' matching diffusion on sounds that have not been yet assigned' ) parser.add_argument( '-m', '--monitor', action='store_true', @@ -235,7 +230,7 @@ class Command (BaseCommand): ) - def handle (self, *args, **options): + def handle(self, *args, **options): if options.get('scan'): self.scan() if options.get('quality_check'): @@ -244,7 +239,7 @@ class Command (BaseCommand): self.monitor() @staticmethod - def check_sounds (qs): + def check_sounds(qs): """ Only check for the sound existence or update """ @@ -253,7 +248,7 @@ class Command (BaseCommand): if sound.check_on_file(): sound.save(check = False) - def scan (self): + def scan(self): """ For all programs, scan dirs """ @@ -271,7 +266,7 @@ class Command (BaseCommand): type = Sound.Type.excerpt, ) - def scan_for_program (self, program, subdir, **sound_kwargs): + def scan_for_program(self, program, subdir, **sound_kwargs): """ Scan a given directory that is associated to the given program, and update sounds information. @@ -281,7 +276,7 @@ class Command (BaseCommand): return subdir = os.path.join(program.path, subdir) - new_sounds = [] + sounds = [] # sounds in directory for path in os.listdir(subdir): @@ -291,15 +286,15 @@ class Command (BaseCommand): si = SoundInfo(path) si.get_sound(sound_kwargs, True) - if si.year != None: - si.find_diffusion(program, True) - new_sounds = [si.sound.pk] + si.find_diffusion(program) + sounds.append(si.sound.pk) - # sounds in db - self.check_sounds(Sound.objects.filter(path__startswith = subdir) \ - .exclude(pk__in = new_sounds )) + # sounds in db & unchecked + sounds = Sound.objects.filter(path__startswith = subdir). \ + exclude(pk__in = sounds) + self.check_sounds(sounds) - def check_quality (self, check = False): + def check_quality(self, check = False): """ Check all files where quality has been set to bad """ @@ -338,7 +333,7 @@ class Command (BaseCommand): update_stats(sound_info, sound) sound.save(check = False) - def monitor (self): + def monitor(self): """ Run in monitor mode """ diff --git a/programs/models.py b/programs/models.py index a967fc7..b3f1a36 100755 --- a/programs/models.py +++ b/programs/models.py @@ -577,31 +577,18 @@ class Diffusion(models.Model): @property def playlist(self): """ - List of sounds as playlist + List of archives' path; uses get_archives """ - playlist = [ sound.path for sound in self.sounds.all() ] - playlist.sort() - return playlist - - def archives_duration(self): - """ - Get total duration of the archives. May differ from the schedule - duration. - """ - sounds = self.initial.sounds if self.initial else self.sounds - r = [ sound.duration - for sound in sounds.filter(type = Sound.Type.archive) - if sound.duration ] - return utils.time_sum(r) + return [ sound.path for sound in self.get_archives() ] def get_archives(self): """ - Return an ordered list of archives sounds for the given episode. + Return a list of available archives sounds for the given episode, + ordered by path. """ - sounds = self.initial.sounds if self.initial else self.sounds - r = [ sound for sound in sounds.all().order_by('path') - if sound.type == Sound.Type.archive ] - return r + sounds = self.initial.sound_set if self.initial else self.sound_set + return sounds.filter(type = Sound.Type.archive, removed = False). \ + order_by('path') @classmethod def get(cl, date = None, diff --git a/programs/utils.py b/programs/utils.py index 9e46ea5..5f3f1aa 100644 --- a/programs/utils.py +++ b/programs/utils.py @@ -19,12 +19,3 @@ def seconds_to_time (seconds): hours, minutes = divmod(minutes, 60) return datetime.time(hour = hours, minute = minutes, second = seconds) -def time_sum (times): - """ - Sum up a list of time elements - """ - seconds = sum([ time.hour * 3600 + time.minute * 60 + time.second - for time in times ]) - return seconds_to_time(seconds) - -