From 3051a93f0125ff0f7db27a1d49b1fabcf7b7bb90 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 10 May 2020 11:21:33 +0300 Subject: refactor: format with black --- contractor | 366 ++++++++++++++++++++++++++++++------------------------------- funcs.py | 30 ++--- 2 files changed, 197 insertions(+), 199 deletions(-) diff --git a/contractor b/contractor index 7929e7c..8fe1e37 100755 --- a/contractor +++ b/contractor @@ -14,15 +14,15 @@ import yaml # The device in the manager VM for the workspace disk. -WS_DEV = '/dev/vdb' +WS_DEV = "/dev/vdb" # The worker VM image file on manager VM. -WORKER_IMG = 'worker.img' +WORKER_IMG = "worker.img" # The temporary worker VM image file, used while worker VM is running. -TEMP_IMG = 'temp.img' +TEMP_IMG = "temp.img" # The UID of the worker account, on the worker VM. @@ -34,27 +34,24 @@ WORKER_GID = 1000 class ExecResult: - def __init__(self, stdout, stderr, exit_code): self.stdout = stdout self.stderr = stderr self.exit_code = exit_code - logging.debug('RESULT: {} {!r} {!r}'.format(stdout, stderr, exit_code)) + logging.debug("RESULT: {} {!r} {!r}".format(stdout, stderr, exit_code)) def failed(self): return self.exit_code != 0 def ssh(target, port, argv, quiet=False): - ssh_argv = ['ssh', '-p', str(port), '--', target] + ssh_argv = ["ssh", "-p", str(port), "--", target] argv = ssh_argv + [shlex.quote(arg) for arg in argv] - logging.info('SSH: {!r}'.format(argv)) + logging.info("SSH: {!r}".format(argv)) stdout = None if quiet: stdout = PIPE - logging.debug( - 'EXEC: {!r} stdout={!r} stderr={!r}'.format( - argv, stdout, STDOUT)) + logging.debug("EXEC: {!r} stdout={!r} stderr={!r}".format(argv, stdout, STDOUT)) p = subprocess.Popen(argv, stderr=STDOUT, stdout=stdout) out, err = p.communicate() return ExecResult(out, err, p.returncode) @@ -62,21 +59,26 @@ def ssh(target, port, argv, quiet=False): def rsync(filename, target, port): argv = [ - 'rsync', '-essh -p{}'.format(port), '-aHSs', '--delete', '--exclude=lost+found', '--', - filename, target, + "rsync", + "-essh -p{}".format(port), + "-aHSs", + "--delete", + "--exclude=lost+found", + "--", + filename, + target, ] - logging.info('RSYNC: {!r}'.format(argv)) + logging.info("RSYNC: {!r}".format(argv)) p = subprocess.Popen(argv, stderr=STDOUT, stdout=None) out, err = p.communicate() return ExecResult(out, err, p.returncode) class RemoteServer: - def __init__(self, ssh_destination, ssh_port, verbose=None): self._dest = ssh_destination self._port = ssh_port - self._where = 'manager: {}'.format(ssh_destination) + self._where = "manager: {}".format(ssh_destination) self._verbose = verbose def quietly(self, *execs): @@ -87,15 +89,15 @@ class RemoteServer: def _msg(self, execs): if self._verbose is not None: - self._verbose('Executing steps on {}'.format(self._where)) + self._verbose("Executing steps on {}".format(self._where)) for e in execs: m = e.msg() or e.__class__.__name__ - self._verbose(' - ' + m) + self._verbose(" - " + m) def _argv(self, execs): self._msg(execs) snippets = [e.as_shell() for e in execs] - return ['sh', '-euc', '; '.join(snippets)] + return ["sh", "-euc", "; ".join(snippets)] def _execute(self, *execs, quiet=None): assert quiet is not None @@ -103,12 +105,11 @@ class RemoteServer: class OnWorker(RemoteServer): - def __init__(self, manager, ssh_port, worker, verbose=None): self._dest = manager self._port = ssh_port - self._where = 'worker: {}'.format(worker) - self._prefix = ['ssh', worker, '--'] + self._where = "worker: {}".format(worker) + self._prefix = ["ssh", worker, "--"] self._verbose = verbose def _execute(self, *execs, quiet=None): @@ -118,7 +119,6 @@ class OnWorker(RemoteServer): class RemoteExecution: - def msg(self): return None @@ -126,35 +126,35 @@ class RemoteExecution: raise NotImplementedError() def as_shell(self): - return ' '.join(shlex.quote(arg) for arg in self.argv()) + return " ".join(shlex.quote(arg) for arg in self.argv()) class MayFail(RemoteExecution): - def as_shell(self): - return super().as_shell() + '|| true' + return super().as_shell() + "|| true" class TrueCmd(RemoteExecution): - def msg(self): - return 'can we run true?' + return "can we run true?" def argv(self): - return ['true'] + return ["true"] class Ansible(RemoteExecution): - def __init__(self, playbook, worker_ip): self._playbook = playbook self._worker_ip = worker_ip def msg(self): - return 'running Ansible playbook on worker' + return "running Ansible playbook on worker" def argv(self): - x = ['sh', '-c', ''' + x = [ + "sh", + "-c", + """ cat > hosts << EOF [all] worker ansible_ssh_host={ip} @@ -165,165 +165,164 @@ cat > worker.yaml << EOF EOF ansible-playbook -i hosts worker.yaml -'''.format(ip=self._worker_ip, playbook=yaml.safe_dump(self._playbook))] - logging.debug('Ansible: {!r}'.format(x)) +""".format( + ip=self._worker_ip, playbook=yaml.safe_dump(self._playbook) + ), + ] + logging.debug("Ansible: {!r}".format(x)) return x class Chdir(RemoteExecution): - def __init__(self, pathname): self._pathname = pathname def msg(self): - return 'cd {}'.format(self._pathname) + return "cd {}".format(self._pathname) def argv(self): - return ['cd', self._pathname] + return ["cd", self._pathname] class Build(RemoteExecution): - def __init__(self, shell): self._shell = shell def msg(self): - return 'building' + return "building" def argv(self): - return ['sh', '-euxc', self._shell] + return ["sh", "-euxc", self._shell] def virsh(*args): - return ['virsh', '-c', 'qemu:///system'] + list(args) + return ["virsh", "-c", "qemu:///system"] + list(args) class DestroyWorkerVM(MayFail): - def msg(self): - return 'destroying worker VM' + return "destroying worker VM" def argv(self): - return virsh('destroy', 'worker') + return virsh("destroy", "worker") class UndefineWorkerVM(MayFail): - def msg(self): - return 'undefining worker VM' + return "undefining worker VM" def argv(self): - return virsh('undefine', 'worker') + return virsh("undefine", "worker") class ShutdownWorkerVM(RemoteExecution): - def msg(self): - return 'shutting down worker VM cleanly' + return "shutting down worker VM cleanly" def argv(self): - return ['sh', '-c', ''' + return [ + "sh", + "-c", + """ virsh -c qemu:///system shutdown worker while virsh -c qemu:///system list --name | grep do sleep 0 done -'''] +""", + ] class CopyWorkerImage(RemoteExecution): - def msg(self): - return 'copying image file for new worker VM' + return "copying image file for new worker VM" def argv(self): - return ['sh', '-c', 'rm -f temp.img; cp worker.img temp.img'] - self.ssh(['rm', '-f', TEMP_IMG]) - ret = self.ssh(['cp', WORKER_IMG, TEMP_IMG]) + return ["sh", "-c", "rm -f temp.img; cp worker.img temp.img"] + self.ssh(["rm", "-f", TEMP_IMG]) + ret = self.ssh(["cp", WORKER_IMG, TEMP_IMG]) class StartGuestNetworking(MayFail): - def msg(self): - return 'starting guest network' + return "starting guest network" def argv(self): - return virsh('net-start', 'default') + return virsh("net-start", "default") class MountWS(RemoteExecution): - def msg(self): - return 'mounting workspace on manager' + return "mounting workspace on manager" def argv(self): - return ['sudo', 'mount', WS_DEV, '/mnt'] + return ["sudo", "mount", WS_DEV, "/mnt"] class MountWSonWorker(RemoteExecution): - def msg(self): - return 'mounting workspace on worker' + return "mounting workspace on worker" def argv(self): - return ['sudo', 'mount', '/dev/vdb', '/workspace'] + return ["sudo", "mount", "/dev/vdb", "/workspace"] class TryUnmountWS(MayFail): - def msg(self): - return 'trying to unmount workspace on manager' + return "trying to unmount workspace on manager" def argv(self): - return ['sudo', 'umount', '--quiet', WS_DEV] + return ["sudo", "umount", "--quiet", WS_DEV] class UnmountWS(RemoteExecution): - def msg(self): - return 'unmounting workspace on manager' + return "unmounting workspace on manager" def argv(self): - return ['sudo', 'umount', '--quiet', WS_DEV] + return ["sudo", "umount", "--quiet", WS_DEV] class ChownWS(RemoteExecution): - def msg(self): - return 'set ownerships on workspace' + return "set ownerships on workspace" def argv(self): - return ['sudo', 'chown', '-R', - '{}:{}'.format(WORKER_UID, WORKER_GID), '/mnt'] + return ["sudo", "chown", "-R", "{}:{}".format(WORKER_UID, WORKER_GID), "/mnt"] class Mkdir(RemoteExecution): - - def __init__(self, pathname, owner='root', group='root', mode=0o755): + def __init__(self, pathname, owner="root", group="root", mode=0o755): self._argv = [ - 'sudo', - 'install', '-d', - '-o', str(owner), - '-g', str(group), - '-m', '{:o}'.format(mode), + "sudo", + "install", + "-d", + "-o", + str(owner), + "-g", + str(group), + "-m", + "{:o}".format(mode), pathname, ] self._pathname = pathname def msg(self): - return 'create {}'.format(self._pathname) + return "create {}".format(self._pathname) def argv(self): return self._argv class CreateWorkerVM(RemoteExecution): - def msg(self): - return 'creating worker VM' + return "creating worker VM" def argv(self): - return ['sh', '-euxc', ''' + return [ + "sh", + "-euxc", + """ n="$(grep -c '^processor' /proc/cpuinfo)" n="$(expr "$n" - 1)" virt-install \ @@ -339,26 +338,38 @@ virt-install \ --network=network=default \ --graphics=spice \ --noautoconsole \ -'''.format(img=TEMP_IMG)] +""".format( + img=TEMP_IMG + ), + ] class AttachWS(RemoteExecution): - def msg(self): - return 'attach workspace disk to worker' + return "attach workspace disk to worker" def argv(self): - return virsh('--quiet', 'attach-disk', 'worker', WS_DEV, 'vdb', - '--targetbus', 'virtio', '--live') + return virsh( + "--quiet", + "attach-disk", + "worker", + WS_DEV, + "vdb", + "--targetbus", + "virtio", + "--live", + ) class WorkerIP(RemoteExecution): - def msg(self): - return 'get worker IP' + return "get worker IP" def argv(self): - return ['sh', '-euc', ''' + return [ + "sh", + "-euc", + """ status=/var/lib/libvirt/dnsmasq/virbr0.status while true do @@ -370,27 +381,26 @@ do fi done echo "$ip" -'''] +""", + ] class Find(RemoteExecution): - def __init__(self, dirname): self._dirname = dirname def argv(self): - return ['sudo', 'find', self._dirname, '-ls'] + return ["sudo", "find", self._dirname, "-ls"] class BuildSpec: - def __init__(self, yaml_text): spec = yaml.safe_load(yaml_text) - self._image = os.path.expanduser(self._get(spec, 'worker-image')) - self._source = os.path.expanduser(self._get(spec, 'source')) - self._workspace = os.path.expanduser(self._get(spec, 'workspace', '')) - self._ansible = self._get(spec, 'ansible', []) - self._build = self._get(spec, 'build') + self._image = os.path.expanduser(self._get(spec, "worker-image")) + self._source = os.path.expanduser(self._get(spec, "source")) + self._workspace = os.path.expanduser(self._get(spec, "workspace", "")) + self._ansible = self._get(spec, "ansible", []) + self._build = self._get(spec, "build") def worker_image(self): return self._image @@ -409,11 +419,11 @@ class BuildSpec: def as_dict(self): return { - 'worker-image': self.worker_image(), - 'ansible': self.ansible(), - 'source': self.source(), - 'workspace': self.workspace(), - 'build': self.build(), + "worker-image": self.worker_image(), + "ansible": self.ansible(), + "source": self.source(), + "workspace": self.workspace(), + "build": self.build(), } def _get(self, spec, key, default=None): @@ -424,14 +434,11 @@ class BuildSpec: class SpecMissingKey(Exception): - def __init__(self, key): - super().__init__( - 'Build specification is missing required key {!r}'.format(key)) + super().__init__("Build specification is missing required key {!r}".format(key)) class Timer: - def __init__(self, report, title): self._report = report self._title = title @@ -444,7 +451,7 @@ class Timer: now = time.time() duration = now - self._prev self._prev = now - self._report('time: {:.1f} s {}\n'.format(duration, self._title)) + self._report("time: {:.1f} s {}\n".format(duration, self._title)) return False @@ -454,8 +461,8 @@ def load_build_spec(filename): def error(msg): - sys.stderr.write('ERROR: {}\n'.format(msg)) - logging.error('ERROR: {}'.format(msg)) + sys.stderr.write("ERROR: {}\n".format(msg)) + logging.error("ERROR: {}".format(msg)) def verbose(args, msg): @@ -463,44 +470,45 @@ def verbose(args, msg): if args.verbose: print(msg) + def manager_destination(args): user = args.manager_user addr = args.manager_address port = args.manager_port - return '{}@{}'.format(user, addr), port + return "{}@{}".format(user, addr), port def upload_worker_image(vrb, filename, dest, port): - vrb('uploading to manager local worker image {}'.format(filename)) - target = '{}:{}'.format(dest, WORKER_IMG) + vrb("uploading to manager local worker image {}".format(filename)) + target = "{}:{}".format(dest, WORKER_IMG) if rsync(filename, target, port).failed(): - error('could not upload image to worker') + error("could not upload image to worker") sys.exit(1) def sync_to_workspace(vrb, frm, dest, port, subdir): - destdir = '/mnt/{}'.format(subdir) - vrb('syncing local {} to manager {}'.format(frm, destdir)) - er = rsync('{}/.'.format(frm), '{}:{}/.'.format(dest, destdir), port) + destdir = "/mnt/{}".format(subdir) + vrb("syncing local {} to manager {}".format(frm, destdir)) + er = rsync("{}/.".format(frm), "{}:{}/.".format(dest, destdir), port) if er.failed(): - error('Failed to rsync saved workspace to worker') + error("Failed to rsync saved workspace to worker") sys.exit(1) def sync_from_workspace(vrb, dest, port, ws): - vrb('syncing manager /mnt to local {}'.format(ws)) + vrb("syncing manager /mnt to local {}".format(ws)) if not os.path.exists(ws): os.makedirs(ws) - er = rsync('{}:/mnt/.'.format(dest), '{}/.'.format(ws), port) + er = rsync("{}:/mnt/.".format(dest), "{}/.".format(ws), port) if er.failed(): - error('Failed to rsync workspace from worker') + error("Failed to rsync workspace from worker") sys.exit(1) def exec_sequence(how, *execs): er = how(*execs) if er.failed(): - error('Failed to do that, giving up') + error("Failed to do that, giving up") sys.exit(1) return er @@ -515,36 +523,36 @@ def exec_verbosely(manager, *execs): def cmd_dump(args): bs = load_build_spec(args.spec) - sys.stdout.write('{}\n'.format(json.dumps(bs.as_dict(), indent=4))) + sys.stdout.write("{}\n".format(json.dumps(bs.as_dict(), indent=4))) def cmd_status(args): dest, port = manager_destination(args) - verbose(args, 'manager VM is {}:{}'.format(dest, port)) + verbose(args, "manager VM is {}:{}".format(dest, port)) manager = RemoteServer(dest, port) if manager.quietly(TrueCmd()).failed(): - error('Manager VM is NOT available') + error("Manager VM is NOT available") sys.exit(1) - verbose(args, 'manager VM is available') + verbose(args, "manager VM is available") def cmd_build(args): vrb = lambda msg: verbose(args, msg) - vrb('building according to {}'.format(args.spec)) + vrb("building according to {}".format(args.spec)) bs = load_build_spec(args.spec) dest, port = manager_destination(args) - vrb('manager is at {} (port {})'.format(dest, port)) + vrb("manager is at {} (port {})".format(dest, port)) manager = RemoteServer(dest, port, verbose=vrb) - with Timer(vrb, 'complete-run'): - with Timer(vrb, 'upload-worker-image'): + with Timer(vrb, "complete-run"): + with Timer(vrb, "upload-worker-image"): upload_worker_image(vrb, bs.worker_image(), dest, port) # Do the minimum needed to start worker VM. The VM takes a # while to boot and we can do other things while that # happens. - with Timer(vrb, 'start-worker'): + with Timer(vrb, "start-worker"): execs = [ DestroyWorkerVM(), UndefineWorkerVM(), @@ -557,66 +565,56 @@ def cmd_build(args): ] exec_quietly(manager, *execs) - with Timer(vrb, 'upload-saved-workspace'): + with Timer(vrb, "upload-saved-workspace"): ws = bs.workspace() if os.path.exists(ws): - sync_to_workspace(vrb, ws, dest, port, '.') + sync_to_workspace(vrb, ws, dest, port, ".") - with Timer(vrb, 'upload-source'): - exec_quietly(manager, Mkdir('/mnt/src', owner=WORKER_UID, group=WORKER_GID)) + with Timer(vrb, "upload-source"): + exec_quietly(manager, Mkdir("/mnt/src", owner=WORKER_UID, group=WORKER_GID)) src = bs.source() - sync_to_workspace(vrb, src, dest, port, 'src') + sync_to_workspace(vrb, src, dest, port, "src") - with Timer(vrb, 'wait-for-worker-to-be-available'): - execs = [ - UnmountWS(), - WorkerIP(), - AttachWS(), - ] + with Timer(vrb, "wait-for-worker-to-be-available"): + execs = [UnmountWS(), WorkerIP(), AttachWS()] er = exec_quietly(manager, *execs) - worker_ip = er.stdout.decode('UTF8').strip() + worker_ip = er.stdout.decode("UTF8").strip() - with Timer(vrb, 'prepare-workspace-worker'): - worker_dest = 'worker@{}'.format(worker_ip) - vrb('worker is at {} (via manager)'.format(worker_dest)) + with Timer(vrb, "prepare-workspace-worker"): + worker_dest = "worker@{}".format(worker_ip) + vrb("worker is at {} (via manager)".format(worker_dest)) worker = OnWorker(dest, port, worker_dest, verbose=vrb) - exec_quietly(worker, Mkdir('/workspace'), MountWSonWorker()) + exec_quietly(worker, Mkdir("/workspace"), MountWSonWorker()) - with Timer(vrb, 'prepare-worker-with-ansible'): + with Timer(vrb, "prepare-worker-with-ansible"): ansible = bs.ansible() if ansible: exec_verbosely(manager, Ansible(ansible, worker_ip)) - with Timer(vrb, 'build'): - execs = [ - Chdir('/workspace/src'), - Build(bs.build()), - ] + with Timer(vrb, "build"): + execs = [Chdir("/workspace/src"), Build(bs.build())] build_failed = worker.verbosely(*execs).failed() - with Timer(vrb, 'shutdown-worker'): - execs = [ - ShutdownWorkerVM(), - MountWS(), - ] + with Timer(vrb, "shutdown-worker"): + execs = [ShutdownWorkerVM(), MountWS()] exec_quietly(manager, *execs) - with Timer(vrb, 'save-workspace'): + with Timer(vrb, "save-workspace"): if ws: - vrb('saving workspace to {}'.format(ws)) + vrb("saving workspace to {}".format(ws)) sync_from_workspace(vrb, dest, port, ws) if build_failed: - error('build FAILED') + error("build FAILED") sys.exit(1) - vrb('build finished OK') + vrb("build finished OK") def setup_logging(args): if args.log: - fmt = '%(asctime)s %(levelname)s %(message)s' - datefmt = '%Y-%m-%d %H:%M:%S' + fmt = "%(asctime)s %(levelname)s %(message)s" + datefmt = "%Y-%m-%d %H:%M:%S" formatter = logging.Formatter(fmt, datefmt) handler = logging.FileHandler(args.log) @@ -631,31 +629,31 @@ def setup_logging(args): def main(): p = argparse.ArgumentParser() - p.add_argument('-v', '--verbose', action='store_true') - p.add_argument('--log', help='log to a file') + p.add_argument("-v", "--verbose", action="store_true") + p.add_argument("--log", help="log to a file") sub = p.add_subparsers() manager_defaults = { - 'manager_address': None, - 'manager_port': 22, - 'manager_user': 'manager', + "manager_address": None, + "manager_port": 22, + "manager_user": "manager", } - dump = sub.add_parser('dump', help='dump parsed build spec as JSON') - dump.add_argument('spec') + dump = sub.add_parser("dump", help="dump parsed build spec as JSON") + dump.add_argument("spec") dump.set_defaults(func=cmd_dump) - status = sub.add_parser('status', help='check status of manager VM') - status.add_argument('-m', '--manager-address', help='address of manager VM') - status.add_argument('-p', '--manager-port', help='SSH port of manager VM') - status.add_argument('-u', '--manager-usr', help='user on manager VM') + status = sub.add_parser("status", help="check status of manager VM") + status.add_argument("-m", "--manager-address", help="address of manager VM") + status.add_argument("-p", "--manager-port", help="SSH port of manager VM") + status.add_argument("-u", "--manager-usr", help="user on manager VM") status.set_defaults(func=cmd_status, **manager_defaults) - build = sub.add_parser('build', help='build according to spec') - build.add_argument('spec') - build.add_argument('-m', '--manager-address', help='address of manager VM') - build.add_argument('-p', '--manager-port', help='SSH port of manager VM') + build = sub.add_parser("build", help="build according to spec") + build.add_argument("spec") + build.add_argument("-m", "--manager-address", help="address of manager VM") + build.add_argument("-p", "--manager-port", help="SSH port of manager VM") build.set_defaults(func=cmd_build, **manager_defaults) args = p.parse_args() @@ -663,5 +661,5 @@ def main(): args.func(args) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/funcs.py b/funcs.py index 2172cc2..f028730 100644 --- a/funcs.py +++ b/funcs.py @@ -14,10 +14,10 @@ import yaml def _run(ctx, argv): p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate("") - ctx['argv'] = argv - ctx['stdout'] = stdout.decode('utf-8') - ctx['stderr'] = stderr.decode('utf-8') - ctx['exit'] = p.returncode + ctx["argv"] = argv + ctx["stdout"] = stdout.decode("utf-8") + ctx["stderr"] = stderr.decode("utf-8") + ctx["exit"] = p.returncode # Return argv prefix to run contractor from source directory. This @@ -25,13 +25,12 @@ def _run(ctx, argv): # the address of the manager VM from CONTRACTOR_ADDRESS in the # environment. def _contractor(): - return [os.path.join(srcdir, 'contractor')] + return [os.path.join(srcdir, "contractor")] # Return manager address. def _manager_address(): - return os.environ['CONTRACTOR_ADDRESS'] - + return os.environ["CONTRACTOR_ADDRESS"] ############################################################################# @@ -42,17 +41,18 @@ def _manager_address(): def nop(ctx, **kwargs): pass + # Check that we can access the contractor VM. # FIXME: this hardcodes some things. def contractor_is_working(ctx): - argv = _contractor() + ['status', '-m', _manager_address()] + argv = _contractor() + ["status", "-m", _manager_address()] _run(ctx, argv) - assert_eq(ctx['exit'], 0) + assert_eq(ctx["exit"], 0) # Create a file from the files embedded in the input document. def create_file(ctx, filename=None): - with open(filename, 'wb') as f: + with open(filename, "wb") as f: f.write(get_file(filename)) @@ -63,31 +63,31 @@ def file_exists(ctx, filename=None): # Copy a file from srcdir. def copy_file_from_srcdir(ctx, filename=None): - shutil.copy(os.path.join(srcdir, './' + filename), '.') + shutil.copy(os.path.join(srcdir, "./" + filename), ".") # Check that the subprocess we last ran ended with the expected exit # code. def exit_code_is(ctx, exit_code=None): - assert_eq(ctx['exit'], int(exit_code)) + assert_eq(ctx["exit"], int(exit_code)) # Run contractor dump def run_contractor_dump(ctx, filename=None): - argv = _contractor() + ['dump', filename] + argv = _contractor() + ["dump", filename] _run(ctx, argv) # Run the contractor to do a build. def run_contractor_build(ctx, filename=None): - argv = _contractor() + ['build', filename, '-m', _manager_address()] + argv = _contractor() + ["build", filename, "-m", _manager_address()] _run(ctx, argv) # Parse stdout from latest subprocess as JSON into a dict. Read the # named YAML file, parse as a dict. Do the two dicts match? def stdout_json_matches_yaml_file(ctx, filename=None): - dict1 = json.loads(ctx['stdout']) + dict1 = json.loads(ctx["stdout"]) with open(filename) as f: dict2 = yaml.safe_load(f) assert_eq(dict1, dict2) -- cgit v1.2.1