From b79112e2f05db9e64fd877b504f4febe0e247d89 Mon Sep 17 00:00:00 2001 From: Andrew Mahone Date: Wed, 14 Jul 2010 21:18:54 -0400 Subject: [PATCH] Cleanups, fixes, use decorator lib for argspec-preserving decorators. --- audiomangler/cli.py | 10 ++++-- audiomangler/codecs.py | 94 ++++++++++++++++++++++++++------------------------ audiomangler/config.py | 1 + audiomangler/tag.py | 8 ++--- audiomangler/task.py | 46 +++++++++++++----------- 5 files changed, 87 insertions(+), 72 deletions(-) diff --git a/audiomangler/cli.py b/audiomangler/cli.py index ae23260..5d59e29 100644 --- a/audiomangler/cli.py +++ b/audiomangler/cli.py @@ -44,6 +44,8 @@ def parse_options(options = []): try: (opts, args) = getopt.getopt(args, s_opts, l_opts) except getopt.GetoptError: + import traceback + traceback.print_exception(*sys.exc_info()) print_usage(options) sys.exit(0) for k, v in opts: @@ -155,12 +157,16 @@ def replaygain_task_generator(album_list): if len(profiles) != 1: continue profile = profiles.pop() - if profile[1] not in 8000, 11025, 12000, 16000, 22050, 24, 32, 44100, 48000: + dir_ = album[0].meta.flat()['dir'] + if profile[1] not in (8000, 11025, 12000, 16000, 22050, 24, 32, 44100, 48000): + print "invalid bitrate for %s" % dir_ continue codec = get_codec(profile[0]) - if not codec or not codec._replaygain: + if not codec or not codec.has_replaygain: + print "replaygain not supported for %s" % dir_ continue if reduce(lambda x, y: x and y.has_replaygain(), album, True): + print "all tracks have replaygain for %s" % dir_ continue msg(consoleformat=u"Adding replaygain values to %(albumtitle)s", format="rg: %(tracks)r", diff --git a/audiomangler/codecs.py b/audiomangler/codecs.py index 5e5f7f1..c857aab 100644 --- a/audiomangler/codecs.py +++ b/audiomangler/codecs.py @@ -32,14 +32,14 @@ codec_map = {} class Codec(object): __metaclass__ = ClassInitMeta - _from_wav_multi = False - _from_wav_pipe = False - _to_wav_pipe = False - _replaygain = False + has_from_wav_multi = False + has_from_wav_pipe = False + has_to_wav_pipe = False + has_replaygain = False lossless = False @classmethod def __classinit__(cls, name__, bases__, cls_dict): - if cls_dict['type_']: + if 'type_' in cls_dict: codec_map[cls_dict['type_']] = cls @classmethod @@ -48,14 +48,14 @@ class Codec(object): @classmethod def from_wav_multi(cls, indir, infiles, outfiles): - if not getattr(cls, '_from_wav_multi_cmd', None): + if not hasattr('from_wav_multi_cmd'): return None encopts = Config['encopts'] if not encopts: encopts = () else: encopts = tuple(encopts.split()) - args = cls._from_wav_multi_cmd.evaluate({ + args = cls.from_wav_multi_cmd.evaluate({ 'indir':indir, 'infiles':tuple(infiles), 'outfiles':tuple(outfiles), @@ -68,7 +68,7 @@ class Codec(object): @classmethod def from_wav_pipe(cls, infile, outfile): - if not getattr(cls, '_from_wav_pipe_cmd', None): + if not hasattr(cls, 'from_wav_pipe_cmd'): return None encopts = Config['encopts'] if not encopts: @@ -84,7 +84,7 @@ class Codec(object): 'encopts': encopts, 'encoder': cls.encoder } - args = cls._from_wav_pipe_cmd.evaluate(env) + args = cls.from_wav_pipe_cmd.evaluate(env) stdin = '/dev/null' if hasattr(cls, '_from_wav_pipe_stdin'): stdin = cls._from_wav_pipe_stdin.evaluate(env) @@ -92,7 +92,7 @@ class Codec(object): @classmethod def to_wav_pipe(cls, infile, outfile): - if not getattr(cls, '_to_wav_pipe_cmd', None): + if not hasattr(cls, 'to_wav_pipe_cmd'): return None env = { 'infile':infile, @@ -101,10 +101,10 @@ class Codec(object): 'type':cls.type_, 'decoder':cls.decoder } - args = cls._to_wav_pipe_cmd.evaluate(env) + args = cls.to_wav_pipe_cmd.evaluate(env) stdout = '/dev/null' - if hasattr(cls, '_to_wav_pipe_stdout'): - stdout = cls._to_wav_pipe_stdout.evaluate(env) + if hasattr(cls, 'to_wav_pipe_stdout'): + stdout = cls.to_wav_pipe_stdout.evaluate(env) return CLITask(args=args, stdin='/dev/null', stdout=stdout, stderr=sys.stderr, background=False) @classmethod @@ -114,8 +114,8 @@ class Codec(object): 'replaygain':cls.replaygain, 'files':tuple(files) } - if metas and hasattr(cls, '_calc_replaygain_cmd'): - task = CLITask(*cls._calc_replaygain_cmd.evaluate(env)) + if metas and hasattr(cls, 'calc_replaygain_cmd'): + task = CLITask(*cls.calc_replaygain_cmd.evaluate(env)) output = yield task tracks, album = cls.calc_replaygain(output) if tracks: @@ -123,11 +123,11 @@ class Codec(object): meta.update(track) meta.update(album) yield metas - elif hasattr(cls, '_replaygain_cmd'): - task = CLITask(*cls._replaygain_cmd.evaluate(env)) + elif hasattr(cls, 'replaygain_cmd'): + task = CLITask(*cls.replaygain_cmd.evaluate(env)) yield task elif hasattr(cls, 'calc_replaygain'): - task = CLITask(*cls._calc_replaygain_cmd.evaluate(env)) + task = CLITask(*cls.calc_replaygain_cmd.evaluate(env)) output = yield task tracks, album = cls.calc_replaygain(output) for trackfile, trackgain in zip(files, tracks): @@ -142,10 +142,10 @@ class MP3Codec(Codec): type_ = 'mp3' encoder = 'lame' replaygain = 'mp3gain' - _from_wav_multi = True - _replaygain = True - _from_wav_multi_cmd = Expr("(encoder, '--quiet') + encopts + ('--noreplaygain', '--nogapout', indir, '--nogaptags', '--nogap') + infiles") - _calc_replaygain_cmd = Expr("(replaygain, '-q', '-o', '-s', 's')+files") + has_from_wav_multi = True + has_replaygain = True + from_wav_multi_cmd = Expr("(encoder, '--quiet') + encopts + ('--noreplaygain', '--nogapout', indir, '--nogaptags', '--nogap') + infiles") + calc_replaygain_cmd = Expr("(replaygain, '-q', '-o', '-s', 's')+files") @staticmethod def calc_replaygain(out): @@ -167,14 +167,14 @@ class WavPackCodec(Codec): encoder = 'wavpack' decoder = 'wvunpack' replaygain = 'wvgain' - _to_wav_pipe = True - _from_wav_pipe = True - _replaygain = True + has_to_wav_pipe = True + has_from_wav_pipe = True + has_replaygain = True lossless = True - _to_wav_pipe_cmd = Expr("(decoder, '-q', '-w', infile, '-o', '-')") - _to_wav_pipe_stdout = Expr("outfile") - _from_wav_pipe_cmd = Expr("(encoder, '-q')+encopts+(infile, '-o', outfile)") - _replaygain_cmd = Expr("(replaygain, '-a')+files") + to_wav_pipe_cmd = Expr("(decoder, '-q', '-w', infile, '-o', '-')") + to_wav_pipe_stdout = Expr("outfile") + from_wav_pipe_cmd = Expr("(encoder, '-q')+encopts+(infile, '-o', outfile)") + replaygain_cmd = Expr("(replaygain, '-a')+files") class FLACCodec(Codec): ext = 'flac' @@ -182,14 +182,14 @@ class FLACCodec(Codec): encoder = 'flac' decoder = 'flac' replaygain = 'metaflac' - _to_wav_pipe = True - _from_wav_pipe = True - _replaygain = True + has_to_wav_pipe = True + has_from_wav_pipe = True + has_replaygain = True lossless = True - _to_wav_pipe_cmd = Expr("(decoder, '-s', '-c', '-d', infile)") - _to_wav_pipe_stdout = Expr("outfile") - _from_wav_pipe_cmd = Expr("(encoder, '-s')+encopts+(infile, )") - _replaygain_cmd = Expr("(replaygain, '--add-replay-gain')+files") + to_wav_pipe_cmd = Expr("(decoder, '-s', '-c', '-d', infile)") + to_wav_pipe_stdout = Expr("outfile") + from_wav_pipe_cmd = Expr("(encoder, '-s')+encopts+(infile, )") + replaygain_cmd = Expr("(replaygain, '--add-replay-gain')+files") class OggVorbisCodec(Codec): ext = 'ogg' @@ -197,13 +197,14 @@ class OggVorbisCodec(Codec): encoder = 'oggenc' decoder = 'oggdec' replaygain = 'vorbisgain' - _to_wav_pipe = True - _from_wav_pipe = True - _replaygain = True - _to_wav_pipe_cmd = Expr("(decoder, '-Q', '-o', '-', infile)") - _to_wav_pipe_stdout = Expr("outfile") - _from_wav_pipe_cmd = Expr("(encoder, '-Q')+encopts+('-o', outfile, infile)") - _replaygain_cmd = Expr("(replaygain, '-q', '-a')+files") + has_to_wav_pipe = True + has_from_wav_pipe = True + has_replaygain = True + to_wav_pipe_cmd = Expr("(decoder, '-Q', '-o', '-', infile)") + to_wav_pipe_stdout = Expr("outfile") + from_wav_pipe_cmd = Expr("(encoder, '-Q')+encopts+('-o', outfile, infile)") + replaygain_cmd = Expr("(replaygain, '-q', '-a')+files") + calc_replaygain_cmd = Expr("(replaygain, '-a', '-n', '-d')+files") @classmethod def calc_replaygain(cls, files): @@ -314,9 +315,10 @@ def transcode_set(targetcodec, fileset, targetfiles, alsem, trsem, workdirs, wor bgprocs = set() dtask = get_codec(i).to_wav_pipe(i.meta['path'], p) etask = targetcodec.from_wav_pipe(p, o) - ttask = FuncTask(background=True, target=transcode_track, - args=(dtask, etask, trsem) - ) + # FuncTask removed + #ttask = FuncTask(background=True, target=transcode_track, + #args=(dtask, etask, trsem) + #) if trsem: trsem.acquire() bgprocs.add(ttask.run()) diff --git a/audiomangler/config.py b/audiomangler/config.py index fbf2fac..a8783a2 100644 --- a/audiomangler/config.py +++ b/audiomangler/config.py @@ -8,6 +8,7 @@ ########################################################################### import os, os.path import sys +from functools import wraps from ConfigParser import RawConfigParser, NoOptionError, NoSectionError def clear_cache(func): diff --git a/audiomangler/tag.py b/audiomangler/tag.py index 8c0871a..61ed967 100644 --- a/audiomangler/tag.py +++ b/audiomangler/tag.py @@ -23,11 +23,11 @@ def splitnumber(num, label): num = num and num.groups() or [0, 0] try: index = int(num[0]) - except ValueError: + except (ValueError, TypeError): index = 0 try: total = int(num[1]) - except ValueError: + except (ValueError, TypeError): total = 0 ret = [] if index: @@ -42,14 +42,14 @@ def joinnumber(input_, label, outlabel = None): if isinstance(index, (list, tuple)): index = index[0] index = int(index) - except ValueError: + except (ValueError, TypeError): index = 0 try: total = input_.get('total'+label+'s', 0) if isinstance(total, (list, tuple)): total = total[0] total = int(total) - except ValueError: + except (ValueError, TypeError): total = 0 ret = [] if index: diff --git a/audiomangler/task.py b/audiomangler/task.py index 9d5cda7..d273f0e 100644 --- a/audiomangler/task.py +++ b/audiomangler/task.py @@ -18,6 +18,7 @@ from multiprocessing import cpu_count from audiomangler.config import Config from audiomangler.util import ClassInitMeta from audiomangler.logging import err +from decorator import decorator if 'twisted.internet.reactor' not in sys.modules: for reactor in 'kqreactor', 'epollreactor', 'pollreactor', 'selectreactor': @@ -29,19 +30,26 @@ if 'twisted.internet.reactor' not in sys.modules: from twisted.internet import reactor -def background_task(func): - argspec = inspect.getargspec(func) - env = {} - code = """ -def decorate(func): - def proxy%s: - self._register() - reactor.callWhenRunning(%s) - if not reactor.running: - reactor.run() - return proxy""" % (inspect.formatargspec(*argspec), ', '.join(['func', 'self'] + ['%s=%s' % (arg, arg) for arg in argspec.args[1:]])) - exec code in globals(), env - return wraps(func)(env['decorate'](func)) +@decorator +def background_task(func, self, *args, **kwargs): + self._register() + reactor.callWhenRunning(func, self, *args, **kwargs) + if not reactor.running: + reactor.run() + +#def background_task(func): + #argspec = inspect.getargspec(func) + #env = {} + #code = """ +#def decorate(func): + #def proxy%s: + #self._register() + #reactor.callWhenRunning(%s) + #if not reactor.running: + #reactor.run() + #return proxy""" % (inspect.formatargspec(*argspec), ', '.join(['func', 'self'] + ['%s=%s' % (arg, arg) for arg in argspec.args[1:]])) + #exec code in globals(), env + #return wraps(func)(env['decorate'](func)) def chain(f): @@ -62,7 +70,7 @@ class BaseTask(object): run = getattr(cls, 'run', None) if run: cls._run = run - run = background_task(run) + run = background_task(run.im_func) if not run.__doc__: run.__doc__ = "Start the task, returning status via .deferred callbacks when the task completes." cls.run = run @@ -215,13 +223,11 @@ class CLIPipelineTask(BaseSetTask): super(CLIPipelineTask, self).run_sub(sub, *args, **kwargs) self.tasks.append(sub) -def generator_task(f): +@decorator +def generator_task(func, *args, **kwargs): "Decorator function wrapping a generator that yields Tasks in a GeneratorTask." - @wraps(f) - def proxy(*args, **kwargs): - gen = f(*args, **kwargs) - return GeneratorTask(gen) - return proxy + gen = func(*args, **kwargs) + return GeneratorTask(gen) class GeneratorTask(BaseSetTask): "Task that runs subtasks produced by a generator, passing their output back via the generator's send method. If the generator yields a value that is not a Task, that value will be passed to the GeneratorTask's callback." -- 2.11.4.GIT