ThreadRoute.title as url; update scripts about old Diffusion.sounds -> Sound.Diffusion (still need tests); cleanup unused and old code

This commit is contained in:
bkfox 2016-06-21 00:13:10 +02:00
parent 2564ba298a
commit acd0737d5d
10 changed files with 85 additions and 166 deletions

View File

@ -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 '<a href="{url}">{title}</a>'.format(
url = thread.url(),
title = _('%(name)s: %(model)s') % {
'model': model._meta.verbose_name_plural,
'name': thread.title,
}
)
class DateRoute(Route):

View File

@ -14,7 +14,7 @@
<link rel="stylesheet" href="{% static website.styles %}" type="text/css">
{% endif %}
<script src="{% static "aircox/cms/scripts.js" %}"></script>
<title>{% if title %}{{ title }} - {% endif %}{{ website.name }}</title>
<title>{% if title %}{{ title|striptags }} - {% endif %}{{ website.name }}</title>
</head>
<body>
{% block page_header %}
@ -51,7 +51,7 @@
{% endif %}
{% block title %}
{% if title %}
<h1>{{ title }}</h1>
<h1>{{ title|safe }}</h1>
{% endif %}
{% endblock %}

View File

@ -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
)

View File

@ -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:

View File

@ -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()

View File

@ -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

View File

@ -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):

View File

@ -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
"""

View File

@ -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,

View File

@ -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)