code quality

This commit is contained in:
bkfox
2023-03-13 17:47:00 +01:00
parent 934817da8a
commit 112770eddf
162 changed files with 4798 additions and 4069 deletions

View File

@ -1,7 +1,5 @@
#! /usr/bin/env python3
"""
Provide SoundFile which is used to link between database and file system.
"""Provide SoundFile which is used to link between database and file system.
File name
=========
@ -22,28 +20,27 @@ To check quality of files, call the command sound_quality_check using the
parameters given by the setting AIRCOX_SOUND_QUALITY. This script requires
Sox (and soxi).
"""
from datetime import date
import logging
import os
import re
from datetime import date
import mutagen
from django.conf import settings as conf
from django.utils import timezone as tz
from django.utils.translation import gettext as _
from aircox import utils
from aircox.models import Program, Sound, Track
from .commands.import_playlist import PlaylistImport
logger = logging.getLogger('aircox.commands')
logger = logging.getLogger("aircox.commands")
class SoundFile:
"""
Handle synchronisation between sounds on files and database.
"""
"""Handle synchronisation between sounds on files and database."""
path = None
info = None
path_info = None
@ -54,18 +51,22 @@ class SoundFile:
@property
def sound_path(self):
""" Relative path name """
return self.path.replace(conf.MEDIA_ROOT + '/', '')
"""Relative path name."""
return self.path.replace(conf.MEDIA_ROOT + "/", "")
@property
def episode(self):
return self.sound and self.sound.episode
def sync(self, sound=None, program=None, deleted=False, keep_deleted=False,
**kwargs):
"""
Update related sound model and save it.
"""
def sync(
self,
sound=None,
program=None,
deleted=False,
keep_deleted=False,
**kwargs
):
"""Update related sound model and save it."""
if deleted:
return self._on_delete(self.path, keep_deleted)
@ -73,26 +74,27 @@ class SoundFile:
if not program:
program = Program.get_from_path(self.path)
logger.debug('program from path "%s" -> %s', self.path, program)
kwargs['program_id'] = program.pk
kwargs["program_id"] = program.pk
if sound:
created = False
else:
sound, created = Sound.objects.get_or_create(
file=self.sound_path, defaults=kwargs)
file=self.sound_path, defaults=kwargs
)
self.sound = sound
self.path_info = self.read_path(self.path)
sound.program = program
if created or sound.check_on_file():
sound.name = self.path_info.get('name')
sound.name = self.path_info.get("name")
self.info = self.read_file_info()
if self.info is not None:
sound.duration = utils.seconds_to_time(self.info.info.length)
# check for episode
if sound.episode is None and 'year' in self.path_info:
if sound.episode is None and "year" in self.path_info:
sound.episode = self.find_episode(sound, self.path_info)
sound.save()
@ -114,8 +116,9 @@ class SoundFile:
Sound.objects.path(self.path).delete()
def read_path(self, path):
"""
Parse path name returning dictionary of extracted info. It can contain:
"""Parse path name returning dictionary of extracted info. It can
contain:
- `year`, `month`, `day`: diffusion date
- `hour`, `minute`: diffusion time
- `n`: sound arbitrary number (used for sound ordering)
@ -126,29 +129,29 @@ class SoundFile:
reg_match = self._path_re.search(basename)
if reg_match:
info = reg_match.groupdict()
for k in ('year', 'month', 'day', 'hour', 'minute', 'n'):
for k in ("year", "month", "day", "hour", "minute", "n"):
if info.get(k) is not None:
info[k] = int(info[k])
name = info.get('name')
info['name'] = name and self._into_name(name) or basename
name = info.get("name")
info["name"] = name and self._into_name(name) or basename
else:
info = {'name': basename}
info = {"name": basename}
return info
_path_re = re.compile(
'^(?P<year>[0-9]{4})(?P<month>[0-9]{2})(?P<day>[0-9]{2})'
'(_(?P<hour>[0-9]{2})h(?P<minute>[0-9]{2}))?'
'(_(?P<n>[0-9]+))?'
'_?[ -]*(?P<name>.*)$'
"^(?P<year>[0-9]{4})(?P<month>[0-9]{2})(?P<day>[0-9]{2})"
"(_(?P<hour>[0-9]{2})h(?P<minute>[0-9]{2}))?"
"(_(?P<n>[0-9]+))?"
"_?[ -]*(?P<name>.*)$"
)
def _into_name(self, name):
name = name.replace('_', ' ')
return ' '.join(r.capitalize() for r in name.split(' '))
name = name.replace("_", " ")
return " ".join(r.capitalize() for r in name.split(" "))
def read_file_info(self):
""" Read file information and metadata. """
"""Read file information and metadata."""
try:
if os.path.exists(self.path):
return mutagen.File(self.path)
@ -157,22 +160,21 @@ class SoundFile:
return None
def find_episode(self, sound, path_info):
"""
For a given program, check if there is an initial diffusion
to associate to, using the date info we have. Update self.sound
and save it consequently.
"""For a given program, check if there is an initial diffusion 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.
We only allow initial diffusion since there should be no rerun.
"""
program, pi = sound.program, path_info
if 'year' not in pi or not sound or sound.episode:
if "year" not in pi or not sound or sound.episode:
return None
year, month, day = pi.get('year'), pi.get('month'), pi.get('day')
if pi.get('hour') is not None:
at = tz.datetime(year, month, day, pi.get('hour', 0),
pi.get('minute', 0))
year, month, day = pi.get("year"), pi.get("month"), pi.get("day")
if pi.get("hour") is not None:
at = tz.datetime(
year, month, day, pi.get("hour", 0), pi.get("minute", 0)
)
at = tz.get_current_timezone().localize(at)
else:
at = date(year, month, day)
@ -181,13 +183,12 @@ class SoundFile:
if not diffusion:
return None
logger.debug('%s <--> %s', sound.file.name, str(diffusion.episode))
logger.debug("%s <--> %s", sound.file.name, str(diffusion.episode))
return diffusion.episode
def find_playlist(self, sound=None, use_meta=True):
"""
Find a playlist file corresponding to the sound path, such as:
my_sound.ogg => my_sound.csv
"""Find a playlist file corresponding to the sound path, such as:
my_sound.ogg => my_sound.csv.
Use sound's file metadata if no corresponding playlist has been
found and `use_meta` is True.
@ -199,7 +200,7 @@ class SoundFile:
# import playlist
path_noext, ext = os.path.splitext(self.sound.file.path)
path = path_noext + '.csv'
path = path_noext + ".csv"
if os.path.exists(path):
PlaylistImport(path, sound=sound).run()
# use metadata
@ -209,18 +210,27 @@ class SoundFile:
if self.info and self.info.tags:
tags = self.info.tags
title, artist, album, year = tuple(
t and ', '.join(t) for t in (
tags.get(k) for k in ('title', 'artist', 'album',
'year'))
t and ", ".join(t)
for t in (
tags.get(k)
for k in ("title", "artist", "album", "year")
)
)
title = (
title
or (self.path_info and self.path_info.get("name"))
or os.path.basename(path_noext)
)
info = (
"{} ({})".format(album, year)
if album and year
else album or year or ""
)
track = Track(
sound=sound,
position=int(tags.get("tracknumber", 0)),
title=title,
artist=artist or _("unknown"),
info=info,
)
title = title or (self.path_info and
self.path_info.get('name')) or \
os.path.basename(path_noext)
info = '{} ({})'.format(album, year) if album and year else \
album or year or ''
track = Track(sound=sound,
position=int(tags.get('tracknumber', 0)),
title=title,
artist=artist or _('unknown'),
info=info)
track.save()