forked from rc/aircox
		
	use logging
This commit is contained in:
		@ -15,11 +15,15 @@ planified before the (given) month.
 | 
				
			|||||||
- "check" will remove all diffusions that are unconfirmed and have been planified
 | 
					- "check" will remove all diffusions that are unconfirmed and have been planified
 | 
				
			||||||
from the (given) month and later.
 | 
					from the (given) month and later.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
from argparse import RawTextHelpFormatter
 | 
					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 aircox.programs.models import *
 | 
					from aircox.programs.models import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					logger = logging.getLogger('aircox.programs.' + __name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Actions:
 | 
					class Actions:
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
@ -66,11 +70,11 @@ class Actions:
 | 
				
			|||||||
                    item.save()
 | 
					                    item.save()
 | 
				
			||||||
                    saved_items.add(item)
 | 
					                    saved_items.add(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            print('> {} new diffusions for schedule #{} ({})'.format(
 | 
					            logger.info('[update] {} new diffusions for schedule #{} ({})'.format(
 | 
				
			||||||
                    len(items), schedule.id, str(schedule)
 | 
					                    len(items), schedule.id, str(schedule)
 | 
				
			||||||
                 ))
 | 
					                 ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        print('total of {} diffusions have been created,'.format(count[0]),
 | 
					        logger.info('[update] total of {} diffusions have been created,'.format(count[0]),
 | 
				
			||||||
              'do not forget manual approval' if manual else
 | 
					              'do not forget manual approval' if manual else
 | 
				
			||||||
                '{} conflicts found'.format(count[1]))
 | 
					                '{} conflicts found'.format(count[1]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -78,7 +82,7 @@ class Actions:
 | 
				
			|||||||
    def clean (date):
 | 
					    def clean (date):
 | 
				
			||||||
        qs = Diffusion.objects.filter(type = Diffusion.Type['unconfirmed'],
 | 
					        qs = Diffusion.objects.filter(type = Diffusion.Type['unconfirmed'],
 | 
				
			||||||
                                      date__lt = date)
 | 
					                                      date__lt = date)
 | 
				
			||||||
        print('{} diffusions will be removed'.format(qs.count()))
 | 
					        logger.info('[clean] {} diffusions will be removed'.format(qs.count()))
 | 
				
			||||||
        qs.delete()
 | 
					        qs.delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
@ -92,10 +96,9 @@ class Actions:
 | 
				
			|||||||
                if schedule.match(diffusion.date):
 | 
					                if schedule.match(diffusion.date):
 | 
				
			||||||
                    break
 | 
					                    break
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                print('> #{}: {}'.format(diffusion.pk, str(diffusion)))
 | 
					 | 
				
			||||||
                items.append(diffusion.id)
 | 
					                items.append(diffusion.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        print('{} diffusions will be removed'.format(len(items)))
 | 
					        logger.info('[check] {} diffusions will be removed'.format(len(items)))
 | 
				
			||||||
        if len(items):
 | 
					        if len(items):
 | 
				
			||||||
            Diffusion.objects.filter(id__in = items).delete()
 | 
					            Diffusion.objects.filter(id__in = items).delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@ Sox (and soxi).
 | 
				
			|||||||
"""
 | 
					"""
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
from argparse import RawTextHelpFormatter
 | 
					from argparse import RawTextHelpFormatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -32,15 +33,16 @@ from aircox.programs.models import *
 | 
				
			|||||||
import aircox.programs.settings as settings
 | 
					import aircox.programs.settings as settings
 | 
				
			||||||
import aircox.programs.utils as utils
 | 
					import aircox.programs.utils as utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					logger = logging.getLogger('aircox.programs.' + __name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Command (BaseCommand):
 | 
					class Command (BaseCommand):
 | 
				
			||||||
    help= __doc__
 | 
					    help= __doc__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def report (self, program = None, component = None, *content):
 | 
					    def report (self, program = None, component = None, *content):
 | 
				
			||||||
        if not component:
 | 
					        if not component:
 | 
				
			||||||
            print('{}: '.format(program), *content)
 | 
					            logger.info('{}: '.format(program), *content)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            print('{}, {}: '.format(program, component), *content)
 | 
					            logger.info('{}, {}: '.format(program, component), *content)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_arguments (self, parser):
 | 
					    def add_arguments (self, parser):
 | 
				
			||||||
        parser.formatter_class=RawTextHelpFormatter
 | 
					        parser.formatter_class=RawTextHelpFormatter
 | 
				
			||||||
@ -130,11 +132,11 @@ class Command (BaseCommand):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        For all programs, scan dirs
 | 
					        For all programs, scan dirs
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        print('scan files for all programs...')
 | 
					        logger.info('scan files for all programs...')
 | 
				
			||||||
        programs = Program.objects.filter()
 | 
					        programs = Program.objects.filter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for program in programs:
 | 
					        for program in programs:
 | 
				
			||||||
            print('- program', program.name)
 | 
					            logger.info('program', program.name)
 | 
				
			||||||
            self.scan_for_program(
 | 
					            self.scan_for_program(
 | 
				
			||||||
                program, settings.AIRCOX_SOUND_ARCHIVES_SUBDIR,
 | 
					                program, settings.AIRCOX_SOUND_ARCHIVES_SUBDIR,
 | 
				
			||||||
                type = Sound.Type['archive'],
 | 
					                type = Sound.Type['archive'],
 | 
				
			||||||
@ -149,7 +151,7 @@ class Command (BaseCommand):
 | 
				
			|||||||
        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.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        print(' - scan files in', subdir)
 | 
					        logger.info('scan files in', subdir)
 | 
				
			||||||
        if not program.ensure_dir(subdir):
 | 
					        if not program.ensure_dir(subdir):
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -203,12 +205,12 @@ class Command (BaseCommand):
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            files = [ sound.path for sound in sounds.filter(removed = False) ]
 | 
					            files = [ sound.path for sound in sounds.filter(removed = False) ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        print('start quality check...')
 | 
					        logger.info('start quality check...')
 | 
				
			||||||
        cmd = quality_check.Command()
 | 
					        cmd = quality_check.Command()
 | 
				
			||||||
        cmd.handle( files = files,
 | 
					        cmd.handle( files = files,
 | 
				
			||||||
                    **settings.AIRCOX_SOUND_QUALITY )
 | 
					                    **settings.AIRCOX_SOUND_QUALITY )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        print('- update sounds in database')
 | 
					        logger.info('update sounds in database')
 | 
				
			||||||
        def update_stats(sound_info, sound):
 | 
					        def update_stats(sound_info, sound):
 | 
				
			||||||
            stats = sound_info.get_file_stats()
 | 
					            stats = sound_info.get_file_stats()
 | 
				
			||||||
            if stats:
 | 
					            if stats:
 | 
				
			||||||
 | 
				
			|||||||
@ -2,12 +2,15 @@
 | 
				
			|||||||
Analyse and check files using Sox, prints good and bad files.
 | 
					Analyse and check files using Sox, prints good and bad files.
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
 | 
					 | 
				
			||||||
from argparse import RawTextHelpFormatter
 | 
					from argparse import RawTextHelpFormatter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.core.management.base import BaseCommand, CommandError
 | 
					from django.core.management.base import BaseCommand, CommandError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					logger = logging.getLogger('aircox.programs.' + __name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Stats:
 | 
					class Stats:
 | 
				
			||||||
    attributes = [
 | 
					    attributes = [
 | 
				
			||||||
        'DC offset', 'Min level', 'Max level',
 | 
					        'DC offset', 'Min level', 'Max level',
 | 
				
			||||||
@ -72,7 +75,7 @@ class Sound:
 | 
				
			|||||||
        return self.stats and self.stats[0]
 | 
					        return self.stats and self.stats[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def analyse (self):
 | 
					    def analyse (self):
 | 
				
			||||||
        print('- complete file analysis')
 | 
					        logger.info('complete file analysis')
 | 
				
			||||||
        self.stats = [ Stats(self.path) ]
 | 
					        self.stats = [ Stats(self.path) ]
 | 
				
			||||||
        position = 0
 | 
					        position = 0
 | 
				
			||||||
        length = self.stats[0].get('length')
 | 
					        length = self.stats[0].get('length')
 | 
				
			||||||
@ -80,13 +83,11 @@ class Sound:
 | 
				
			|||||||
        if not self.sample_length:
 | 
					        if not self.sample_length:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        print('- samples analysis: ', end=' ')
 | 
					        logger.info('start samples analysis...')
 | 
				
			||||||
        while position < length:
 | 
					        while position < length:
 | 
				
			||||||
            print(len(self.stats), end=' ')
 | 
					 | 
				
			||||||
            stats = Stats(self.path, at = position, length = self.sample_length)
 | 
					            stats = Stats(self.path, at = position, length = self.sample_length)
 | 
				
			||||||
            self.stats.append(stats)
 | 
					            self.stats.append(stats)
 | 
				
			||||||
            position += self.sample_length
 | 
					            position += self.sample_length
 | 
				
			||||||
        print()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def check (self, name, min_val, max_val):
 | 
					    def check (self, name, min_val, max_val):
 | 
				
			||||||
        self.good = [ index for index, stats in enumerate(self.stats)
 | 
					        self.good = [ index for index, stats in enumerate(self.stats)
 | 
				
			||||||
@ -103,9 +104,11 @@ class Sound:
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.good:
 | 
					        if self.good:
 | 
				
			||||||
            print('- good:\033[92m', ', '.join( view(self.good) ), '\033[0m')
 | 
					            logger.info(self.path, ': good samples:\033[92m',
 | 
				
			||||||
 | 
					                        ', '.join( view(self.good) ), '\033[0m')
 | 
				
			||||||
        if self.bad:
 | 
					        if self.bad:
 | 
				
			||||||
            print('- bad:\033[91m', ', '.join( view(self.bad) ), '\033[0m')
 | 
					            loggeer.info(self.path ': bad samples:\033[91m',
 | 
				
			||||||
 | 
					                         ', '.join( view(self.bad) ), '\033[0m')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Command (BaseCommand):
 | 
					class Command (BaseCommand):
 | 
				
			||||||
    help = __doc__
 | 
					    help = __doc__
 | 
				
			||||||
@ -154,10 +157,9 @@ class Command (BaseCommand):
 | 
				
			|||||||
        self.bad = []
 | 
					        self.bad = []
 | 
				
			||||||
        self.good = []
 | 
					        self.good = []
 | 
				
			||||||
        for sound in self.sounds:
 | 
					        for sound in self.sounds:
 | 
				
			||||||
            print(sound.path)
 | 
					            logger.info('analyse ', sound.path)
 | 
				
			||||||
            sound.analyse()
 | 
					            sound.analyse()
 | 
				
			||||||
            sound.check(attr, minmax[0], minmax[1])
 | 
					            sound.check(attr, minmax[0], minmax[1])
 | 
				
			||||||
            print()
 | 
					 | 
				
			||||||
            if sound.bad:
 | 
					            if sound.bad:
 | 
				
			||||||
                self.bad.append(sound)
 | 
					                self.bad.append(sound)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
@ -166,10 +168,12 @@ class Command (BaseCommand):
 | 
				
			|||||||
        # resume
 | 
					        # resume
 | 
				
			||||||
        if options.get('resume'):
 | 
					        if options.get('resume'):
 | 
				
			||||||
            if self.good:
 | 
					            if self.good:
 | 
				
			||||||
                print('files that did not failed the test:\033[92m\n   ',
 | 
					                logger.info('files that did not failed the test:\033[92m\n   ',
 | 
				
			||||||
                      '\n    '.join([sound.path for sound in self.good]), '\033[0m')
 | 
					                      '\n    '.join([sound.path for sound in self.good]),
 | 
				
			||||||
 | 
					                      '\033[0m')
 | 
				
			||||||
            if self.bad:
 | 
					            if self.bad:
 | 
				
			||||||
                # bad at the end for ergonomy
 | 
					                # bad at the end for ergonomy
 | 
				
			||||||
                print('files that failed the test:\033[91m\n   ',
 | 
					                logger.info('files that failed the test:\033[91m\n   ',
 | 
				
			||||||
                      '\n    '.join([sound.path for sound in self.bad]),'\033[0m')
 | 
					                      '\n    '.join([sound.path for sound in self.bad]),
 | 
				
			||||||
 | 
					                      '\033[0m')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,6 @@
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import shutil
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.template.defaultfilters import slugify
 | 
					from django.template.defaultfilters import slugify
 | 
				
			||||||
@ -14,6 +16,9 @@ import aircox.programs.utils as utils
 | 
				
			|||||||
import aircox.programs.settings as settings
 | 
					import aircox.programs.settings as settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def date_or_default (date, date_only = False):
 | 
					def date_or_default (date, date_only = False):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Return date or default value (now) if not defined, and remove time info
 | 
					    Return date or default value (now) if not defined, and remove time info
 | 
				
			||||||
@ -166,6 +171,7 @@ class Sound (Nameable):
 | 
				
			|||||||
        if not self.file_exists():
 | 
					        if not self.file_exists():
 | 
				
			||||||
            if self.removed:
 | 
					            if self.removed:
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					            logger.info('sound file {} has been removed'.format(self.path))
 | 
				
			||||||
            self.removed = True
 | 
					            self.removed = True
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -176,6 +182,8 @@ class Sound (Nameable):
 | 
				
			|||||||
        if self.mtime != mtime:
 | 
					        if self.mtime != mtime:
 | 
				
			||||||
            self.mtime = mtime
 | 
					            self.mtime = mtime
 | 
				
			||||||
            self.good_quality = False
 | 
					            self.good_quality = False
 | 
				
			||||||
 | 
					            logger.info('sound file {} m_time has changed. Reset quality info'
 | 
				
			||||||
 | 
					                        .format(self.path))
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
        return old_removed != self.removed
 | 
					        return old_removed != self.removed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -433,6 +441,9 @@ class Program (Nameable):
 | 
				
			|||||||
    diffusion informations.
 | 
					    diffusion informations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    A Scheduled program has a schedule and is the one with a normal use case.
 | 
					    A Scheduled program has a schedule and is the one with a normal use case.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Renaming a Program rename the corresponding directory to matches the new
 | 
				
			||||||
 | 
					    name if it does not exists.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    station = models.ForeignKey(
 | 
					    station = models.ForeignKey(
 | 
				
			||||||
        Station,
 | 
					        Station,
 | 
				
			||||||
@ -476,6 +487,17 @@ class Program (Nameable):
 | 
				
			|||||||
            if schedule.match(date, check_time = False):
 | 
					            if schedule.match(date, check_time = False):
 | 
				
			||||||
                return schedule
 | 
					                return schedule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__ (self, *kargs, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(*kargs, **kwargs)
 | 
				
			||||||
 | 
					        self.__original_path = self.path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save (self, *kargs, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(*kargs, **kwargs)
 | 
				
			||||||
 | 
					        if self.__original_path != self.path and \
 | 
				
			||||||
 | 
					                not os.path.exists(self.path):
 | 
				
			||||||
 | 
					            logger.info('program {} name changed to {}. Change dir name' \
 | 
				
			||||||
 | 
					                        .format(self.id, self.name))
 | 
				
			||||||
 | 
					            shutil.move(self.__original_path, self.path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Diffusion (models.Model):
 | 
					class Diffusion (models.Model):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
@ -611,6 +633,7 @@ class Diffusion (models.Model):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def save (self, *args, **kwargs):
 | 
					    def save (self, *args, **kwargs):
 | 
				
			||||||
        if self.initial:
 | 
					        if self.initial:
 | 
				
			||||||
 | 
					            # force link to the top initial diffusion
 | 
				
			||||||
            if self.initial.initial:
 | 
					            if self.initial.initial:
 | 
				
			||||||
                self.initial = self.initial.initial
 | 
					                self.initial = self.initial.initial
 | 
				
			||||||
            self.program = self.initial.program
 | 
					            self.program = self.initial.program
 | 
				
			||||||
@ -668,12 +691,16 @@ class Log (models.Model):
 | 
				
			|||||||
                                    ContentType.objects.get_for_model(model).id)
 | 
					                                    ContentType.objects.get_for_model(model).id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def print (self):
 | 
					    def print (self):
 | 
				
			||||||
        print(str(self), ':', self.comment or '')
 | 
					        logger.info('log #{} ({}): {}{}'.format(
 | 
				
			||||||
        if self.related_object:
 | 
					            str(self),
 | 
				
			||||||
            print(' - {}: #{}'.format(self.related_type,
 | 
					            self.comment or '',
 | 
				
			||||||
                                      self.related_id))
 | 
					            '\n - {}: #{}'.format(self.related_type, self.related_id)
 | 
				
			||||||
 | 
					                if self.related_object else ''
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__ (self):
 | 
					    def __str__ (self):
 | 
				
			||||||
        return self.date.strftime('%Y-%m-%d %H:%M') + ', ' + self.source
 | 
					        return 'log #{} ({}, {})'.format(
 | 
				
			||||||
 | 
					                self.id, self.date.strftime('%Y-%m-%d %H:%M'), self.source
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user