aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bachelier <laurent@bachelier.name>2012-12-27 19:45:46 +0100
committerLaurent Bachelier <laurent@bachelier.name>2012-12-27 19:45:46 +0100
commitecbaf4520cbdc814b3a513ca6ecffce3d1e8f789 (patch)
tree4383961fe163e950bd7ace82cbe9e59b15013672
parentOption to ignore lossy files with too high rate/bit (diff)
downloadbrutha-ecbaf4520cbdc814b3a513ca6ecffce3d1e8f789.tar.xz
Refactor output system
-rw-r--r--brutha/__main__.py20
-rw-r--r--brutha/output.py153
2 files changed, 94 insertions, 79 deletions
diff --git a/brutha/__main__.py b/brutha/__main__.py
index f575090..e5c3666 100644
--- a/brutha/__main__.py
+++ b/brutha/__main__.py
@@ -5,8 +5,8 @@ import sys
from StringIO import StringIO
from brutha.tree import Tree
-from brutha.util import uprint, detect_cores, default_output
-from brutha.output import PRINTERS, EXECUTORS
+from brutha.util import detect_cores, default_output
+from brutha.output import OUTPUTS
def main():
@@ -21,7 +21,7 @@ def main():
help='Compute ReplayGain if missing')
parser.add_argument('-d', '--delete', action='store_true',
help='Delete extraneous files in destination')
- parser.add_argument('-o', '--output', default=output, choices=PRINTERS.keys(),
+ parser.add_argument('-o', '--output', default=output, choices=OUTPUTS.keys(),
help='Command list type, default %s' % output)
parser.add_argument('-R', '--maxrate', type=int,
help='Maximum sample rate allowed (e.g. 44100)', metavar='RATE')
@@ -43,18 +43,16 @@ def main():
{'quality': args.quality, 'gain': args.gain, 'delete': args.delete,
'maxrate': args.maxrate, 'maxbits': args.maxbits, 'lossycheck': args.lossycheck})
if args.execute:
- s = StringIO()
- p = uprint(s)
+ stream = StringIO()
else:
- p = uprint(sys.stdout)
- outf = PRINTERS[args.output]
- outf(p, tree.commands(), args.echo, args.jobs)
+ stream = sys.stdout
+ jobs = args.jobs if args.output in ('parallel', 'make') else 1
+ out = OUTPUTS[args.output](args.echo, jobs)
+ out.write(tree.commands(), stream)
if args.execute:
- jobs = args.jobs if args.output in ('parallel', 'make') else 1
print >>sys.stderr, 'Synchronizing %s to %s, using %s concurrent jobs.' % (args.src, args.dest, jobs)
- exef = EXECUTORS[args.output]
- sys.exit(exef(s, args.jobs))
+ sys.exit(out.run(stream))
if __name__ == '__main__':
diff --git a/brutha/output.py b/brutha/output.py
index 8ec8e11..cce5a1b 100644
--- a/brutha/output.py
+++ b/brutha/output.py
@@ -3,7 +3,7 @@ from __future__ import division
import subprocess
-from brutha.util import require_executable
+from brutha.util import require_executable, uprint
def pbar(cur, total, color=True):
@@ -23,73 +23,90 @@ def pbar(cur, total, color=True):
return "echo '%s[%s] (%s%%)%s'" % (BRIGHT, bar, pct, NORMAL)
-# PRINTERS
-
-
-def sh(p, commands, echo=False, jobs=None):
- p('#!%s' % require_executable('sh', ['bash', 'zsh', 'dash', 'sh']))
- p('set -eu')
- if echo:
- p('set -x')
- for i, subcommands in enumerate(commands):
- p("\n".join(subcommands))
- if echo:
- p('( set +x ; %s ) 2>/dev/null' % pbar(i+1, len(commands)))
- else:
- p(pbar(i+1, len(commands)))
+class Output(object):
+ NAME = NotImplemented
+
+ def __init__(self, echo=False, jobs=None):
+ self.echo = echo
+ self.jobs = jobs
+
+ def write(self, commands, stream):
+ raise NotImplementedError()
+
+ def run(self, stream):
+ raise NotImplementedError()
+
+
+class Shebang(object):
+ def run(self, stream):
+ """
+ Extracts the shebang (#!) line and runs it, with the script provided as stdin.
+ This is known to work at least with bash and GNU parallel.
+ """
+ stream.seek(0)
+ line = stream.readline()
+ assert line.startswith('#!')
+ shebang = line[2:].split()
+ p = subprocess.Popen(shebang, shell=False, stdin=subprocess.PIPE)
+ p.communicate(stream.getvalue())
+ return p.returncode
+
+
+class Shell(Shebang, Output):
+ NAME = 'sh'
+
+ def write(self, commands, stream):
+ p = uprint(stream)
+ p('#!%s' % require_executable('sh', ['bash', 'zsh', 'dash', 'sh']))
+ p('set -eu')
+ if self.echo:
+ p('set -x')
+ for i, subcommands in enumerate(commands):
+ p("\n".join(subcommands))
+ if self.echo:
+ p('( set +x ; %s ) 2>/dev/null' % pbar(i+1, len(commands)))
+ else:
+ p(pbar(i+1, len(commands)))
+ p()
+
+
+class Parallel(Shebang, Output):
+ NAME = 'parallel'
+
+ def write(self, commands, stream):
+ p = uprint(stream)
+ verbose = ' --verbose' if self.echo else ''
+ jobs = ' --jobs %s' % self.jobs if self.jobs else ''
+ p('#!%s --shebang --eta%s%s --' % (require_executable('parallel'), jobs, verbose))
+ for i, subcommands in enumerate(commands):
+ p(" && ".join(subcommands + [pbar(i+1, len(commands))]))
+
+
+class Make(Output):
+ NAME = 'make'
+
+ def write(self, commands, stream):
+ p = uprint(stream)
+ prefix = '' if self.echo else '@'
+ targets = ' '.join('d%s' % i for i in xrange(0, len(commands)))
+ p('.PHONY: all %s' % targets)
+ p('all: %s' % targets)
p()
+ for i, subcommands in enumerate(commands):
+ p('d%s:' % i)
+ for subcommand in subcommands:
+ p('\t%s%s' % (prefix, subcommand))
+ p('\t@%s' % pbar(i+1, len(commands)))
+
+ def run(self, stream):
+ if self.jobs:
+ addon = ['-j', str(self.jobs)]
+ else:
+ addon = []
+ p = subprocess.Popen([require_executable('make', ['gmake', 'make']), '-f', '-'] + addon,
+ shell=False, stdin=subprocess.PIPE)
+ p.communicate(stream.getvalue())
+ return p.returncode
-def parallel(p, commands, echo=False, jobs=None):
- verbose = ' --verbose' if echo else ''
- jobs = ' --jobs %s' % jobs if jobs else ''
- p('#!%s --shebang --eta%s%s --' % (require_executable('parallel'), jobs, verbose))
- for i, subcommands in enumerate(commands):
- p(" && ".join(subcommands + [pbar(i+1, len(commands))]))
-
-
-def make(p, commands, echo=False, jobs=None):
- prefix = '' if echo else '@'
- targets = ' '.join('d%s' % i for i in xrange(0, len(commands)))
- p('.PHONY: all %s' % targets)
- p('all: %s' % targets)
- p()
- for i, subcommands in enumerate(commands):
- p('d%s:' % i)
- for subcommand in subcommands:
- p('\t%s%s' % (prefix, subcommand))
- p('\t@%s' % pbar(i+1, len(commands)))
-
-
-PRINTERS = {'sh': sh, 'parallel': parallel, 'make': make}
-
-
-# EXECUTORS
-
-
-def shebang(stream, jobs=None):
- """
- Extracts the shebang (#!) line and runs it, with the script provided as stdin.
- This is known to work at least with bash and GNU parallel.
- """
- stream.seek(0)
- line = stream.readline()
- assert line.startswith('#!')
- shebang = line[2:].split()
- p = subprocess.Popen(shebang, shell=False, stdin=subprocess.PIPE)
- p.communicate(stream.getvalue())
- return p.returncode
-
-
-def emake(stream, jobs=None):
- if jobs:
- addon = ['-j', str(jobs)]
- else:
- addon = []
- p = subprocess.Popen([require_executable('make', ['gmake', 'make']), '-f', '-'] + addon,
- shell=False, stdin=subprocess.PIPE)
- p.communicate(stream.getvalue())
- return p.returncode
-
-
-EXECUTORS = {'sh': shebang, 'parallel': shebang, 'make': emake}
+OUTPUTS = dict((c.NAME, c) for c in (Shell, Parallel, Make))