fix stuffs, documentation

This commit is contained in:
bkfox 2015-09-17 14:52:01 +02:00
parent 4b5f908b3d
commit dae9545e27
2 changed files with 102 additions and 85 deletions

View File

@ -1,3 +1,20 @@
"""
Manage diffusions using schedules, to update, clean up or check diffusions.
A diffusion generated using this utility is considered has type "unconfirmed",
and is not considered as ready for diffusion; To do so, users must confirm the
diffusion case by changing it's type to "default".
Different actions are available:
- "update" is the process that is used to generated them using programs
schedules for the (given) month.
- "clean" will remove all diffusions that are still unconfirmed and have been
planified before the (given) month.
- "check" will remove all diffusions that are unconfirmed and have been planified
from the (given) month and later.
"""
from argparse import RawTextHelpFormatter
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone as tz from django.utils import timezone as tz
from programs.models import * from programs.models import *
@ -11,7 +28,7 @@ class Actions:
items += schedule.diffusions_of_month(date, exclude_saved = True) items += schedule.diffusions_of_month(date, exclude_saved = True)
print('> {} new diffusions for schedule #{} ({})'.format( print('> {} new diffusions for schedule #{} ({})'.format(
len(items), schedule.id, str(schedule) len(items), schedule.id, str(schedule)
)) ))
print('total of {} diffusions will be created. To be used, they need ' print('total of {} diffusions will be created. To be used, they need '
'manual approval.'.format(len(items))) 'manual approval.'.format(len(items)))
@ -44,9 +61,11 @@ class Actions:
class Command (BaseCommand): class Command (BaseCommand):
help= 'Monitor diffusions' help= __doc__
def add_arguments (self, parser): def add_arguments (self, parser):
parser.formatter_class=RawTextHelpFormatter
now = tz.datetime.today() now = tz.datetime.today()
group = parser.add_argument_group('action') group = parser.add_argument_group('action')
@ -66,9 +85,7 @@ class Command (BaseCommand):
'schedule') 'schedule')
group = parser.add_argument_group( group = parser.add_argument_group(
'date', 'date')
'this information is used by the action, starting at the first (!) '
'of the given month')
group.add_argument('--year', type=int, default=now.year, group.add_argument('--year', type=int, default=now.year,
help='used by update, default is today\'s year') help='used by update, default is today\'s year')
group.add_argument('--month', type=int, default=now.month, group.add_argument('--month', type=int, default=now.month,

View File

@ -1,5 +1,22 @@
"""
Check over programs' sound files, scan them, and add them to the
database if they are not there yet.
It tries to parse the file name to get the date of the diffusion of an
episode and associate the file with it; We use the following format:
yyyymmdd[_n][_][title]
Where:
'yyyy' is the year of the episode's diffusion;
'mm' is the month of the episode's diffusion;
'dd' is the day of the episode's diffusion;
'n' is the number of the episode (if multiple episodes);
'title' the title of the sound;
"""
import os import os
import re import re
from argparse import RawTextHelpFormatter
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone from django.utils import timezone
@ -8,8 +25,7 @@ import programs.settings as settings
class Command (BaseCommand): class Command (BaseCommand):
help= "Take a look at the programs directory to check on new podcasts" help= __doc__
def report (self, program = None, component = None, *content): def report (self, program = None, component = None, *content):
if not component: if not component:
@ -17,82 +33,71 @@ class Command (BaseCommand):
else: else:
print('{}, {}: '.format(program, component), *content) print('{}, {}: '.format(program, component), *content)
def add_arguments (self, parser):
parser.formatter_class=RawTextHelpFormatter
def handle (self, *args, **options): def handle (self, *args, **options):
programs = Program.objects.filter() programs = Program.objects.filter()
for program in programs: for program in programs:
self.scan_dir(program, program.path + '/public', public = True) self.check(program, program.path + '/public', public = True)
self.scan_dir(program, program.path + '/podcasts', embed = True) self.check(program, program.path + '/podcasts', embed = True)
self.scan_dir(program, program.path + '/private') self.check(program, program.path + '/private')
def get_sound_info (self, path):
def ensure_episode (self, program, sound):
""" """
For a given program, check if there is an episode to associate to. Parse file name to get info on the assumption it has the correct
This makes the assumption that the name of the file has the following format (given in Command.help)
format:
yyyymmdd[_n][_][title]
Where:
yyyy: is the year of the episode's diffusion
mm: is the month of the episode's diffusion
dd: is the day of the episode's diffusion
n: is the number of the episode (if multiple episodes)
We check against the diffusion rather than the episode's date, because
this is the diffusion that defines when the sound will be podcasted for
the first time.
We create the episode if it does not exists only if there is a diffusion
matching the date of the sound, in order to respect the hierarchy of
episode creation.
We dont create episode if it does not exists, because only episodes must
be created through diffusions
TODO: multiple diffusions at the same date
""" """
path = os.path.basename(sound.path)
r = re.search('^(?P<year>[0-9]{4})' r = re.search('^(?P<year>[0-9]{4})'
'(?P<month>[0-9]{2})' '(?P<month>[0-9]{2})'
'(?P<day>[0-9]{2})' '(?P<day>[0-9]{2})'
'(_(?P<n>[0-9]+))?' '(_(?P<n>[0-9]+))?'
'_?(?P<name>.*)\.\w+$' '_?(?P<name>.*)\.\w+$',
, path) os.path.basename(path))
if not r: if not (r and r.groupdict()):
return self.report(program, path, "file path is not correct, use defaults")
r = r.groupdict() r = {
'name': os.path.splitext(path)
}
r['path'] = path
return r
def ensure_sound (self, sound_info):
"""
Return the Sound for the given sound_info; If not found, create it
without saving it.
"""
sound = Sound.objects.filter(path = path)
if sound:
sound = sound[0]
else:
sound = Sound(path = path, title = sound_info['name'])
def find_episode (self, program, sound_info):
"""
For a given program, and sound path check if there is an episode to
associate to, using the diffusion's date.
If there is no matching episode, return None.
"""
# check on episodes # check on episodes
diffusion = Diffusion.objects.filter( program = program diffusion = Diffusion.objects.filter(
, date__year = int(r['year']) program = program,
, date__month = int(r['month']) date__year = int(sound_info['year']),
, date__day = int(r['day']) date__month = int(sound_info['month']),
) date__day = int(sound_info['day'])
)
if not diffusion.count(): if not diffusion.count():
self.report(program, path, 'no diffusion found for the given date') self.report(program, path, 'no diffusion found for the given date')
return return
diffusion = diffusion[0] diffusion = diffusion[0]
if diffusion.episode: return diffusion.episode or None
return diffusion.episode
episode = Episode( parent = program
, title = r.get('name') \
.replace('_', ' ') \
.capitalize()
, date = diffusion.date
)
episode.save()
if program.tags.all():
episode.tags.add(program.tags.all())
self.report(program, path, 'episode does not exist, create')
return episode
def scan_dir (self, program, dir_path, public = False, embed = False): def check (self, program, dir_path, public = False, embed = False):
""" """
Scan a given directory that is associated to the given program, and Scan a given directory that is associated to the given program, and
update sounds information update sounds information
@ -110,27 +115,22 @@ class Command (BaseCommand):
paths.append(path) paths.append(path)
# check for new sound files or update sound_info = self.get_sound_info(path)
sound = Sound.objects.filter(path = path) sound = self.ensure_sound(sound_info)
if sound.count():
sound = sound[0]
else:
sound = Sound(path = path)
# check for the corresponding episode: sound.public = public
episode = self.ensure_episode(program, sound)
if not episode:
continue
sound.save()
for sound_ in episode.sounds.get_queryset():
if sound_.path == sound.path:
continue
self.report(program, path, 'associate sound to episode '
, episode.id)
episode.sounds.add(sound)
# episode and relation
if 'year' in sound_info:
episode = self.find_episode(program, sound_info)
if episode:
for sound_ in episode.sounds.get_queryset():
if sound_.path == sound.path:
break
else:
self.report(program, path, 'associate sound to episode ',
episode.id)
episode.sounds.add(sound)
return paths return paths