def test_capsys_err(capsys): try: fatal('goodbye world') except SystemExit: pass cap = capsys.readouterr() assert 'goodbye world' in cap.err
def main(): with Inform(notify_if_no_tty=True, version=version) as inform: try: # assure config and log directories exist to_path(CONFIG_DIR).mkdir(parents=True, exist_ok=True) to_path(DATA_DIR).mkdir(parents=True, exist_ok=True) inform.set_logfile(to_path(DATA_DIR, LOG_FILE)) # read command line cmdline = docopt(synopsis, options_first=True, version=version) command = cmdline["<command>"] args = cmdline["<args>"] if cmdline["--quiet"]: inform.quiet = True # find and run command settings = Settings(cmdline) cmd, cmd_name = Command.find(command) cmd.execute(cmd_name, args, settings, cmdline) except KeyboardInterrupt: display("Terminated by user.") except Error as e: e.terminate() except OSError as e: fatal(os_error(e)) done()
def initialize(cls, gpg_path=None, gpg_home=None, armor=None): cls.gpg_path = to_path( gpg_path if gpg_path else get_setting('gpg_executable')) override_setting('gpg_executable', cls.gpg_path) cls.gpg_home = to_path( gpg_home if gpg_home else get_setting('gpg_home')) override_setting('gpg_home', cls.gpg_home) armor = armor if armor is not None else get_setting('gpg_armor') if armor not in ARMOR_CHOICES: warn("'%s' is not valid, choose from %s." % (armor, conjoin(ARMOR_CHOICES)), culprit=setting_path('gpg_armor')) armor = 'extension' cls.armor = armor override_setting('gpg_armor', armor) gpg_args = {} if cls.gpg_path: gpg_args.update({'gpgbinary': str(cls.gpg_path)}) if cls.gpg_home: gpg_args.update({'gnupghome': str(cls.gpg_home)}) try: cls.gpg = gnupg.GPG(**gpg_args) except ValueError as e: fatal(e)
def main(): try: # read config file read_config() # read command line cmdline = docopt( __doc__.format(commands=Command.summarize()), version='avendesora {} ({})'.format(__version__, __released__), options_first=True, ) # start logging logfile = BufferedFile(get_setting('log_file'), True) Inform(logfile=logfile, hanging_indent=False, stream_policy='header', notify_if_no_tty=True) shlib.set_prefs(use_inform=True, log_cmd=True) # run the requested command Command.execute(cmdline['<command>'], cmdline['<args>']) done() except KeyboardInterrupt: output('\nTerminated by user.') terminate() except (PasswordError, Error) as e: e.terminate() except OSError as e: fatal(os_error(e)) done()
def main(): with Inform() as inform: # read command line cmdline = docopt( __doc__.format(commands=Command.summarize()), options_first=True ) config = cmdline['--config'] command = cmdline['<command>'] args = cmdline['<args>'] options = cull([ 'verbose' if cmdline['--verbose'] else '', 'narrate' if cmdline['--narrate'] else '', 'trial-run' if cmdline['--trial-run'] else '', ]) if cmdline['--narrate']: inform.narrate = True try: cmd, name = Command.find(command) with Settings(config, cmd.REQUIRES_EXCLUSIVITY) as settings: cmd.execute(name, args, settings, options) except KeyboardInterrupt: display('Terminated by user.') except Error as err: err.terminate() except OSError as err: fatal(os_error(err)) terminate()
def main(): with Inform(error_status=2, flush=True, version=version) as inform: # read command line cmdline = docopt(expanded_synopsis, options_first=True, version=version) config = cmdline["--config"] command = cmdline["<command>"] args = cmdline["<args>"] if cmdline["--mute"]: inform.mute = True if cmdline["--quiet"]: inform.quiet = True emborg_opts = cull( [ "verbose" if cmdline["--verbose"] else "", "narrate" if cmdline["--narrate"] else "", "dry-run" if cmdline["--dry-run"] else "", "no-log" if cmdline["--no-log"] else "", ] ) if cmdline["--narrate"]: inform.narrate = True try: # find the command cmd, cmd_name = Command.find(command) # execute the command initialization exit_status = cmd.execute_early(cmd_name, args, None, emborg_opts) if exit_status is not None: terminate(exit_status) worst_exit_status = 0 try: while True: with Settings(config, cmd, emborg_opts) as settings: try: exit_status = cmd.execute( cmd_name, args, settings, emborg_opts ) except Error as e: settings.fail(e, cmd=' '.join(sys.argv)) e.terminate() if exit_status and exit_status > worst_exit_status: worst_exit_status = exit_status except NoMoreConfigs: pass # execute the command termination exit_status = cmd.execute_late(cmd_name, args, None, emborg_opts) if exit_status and exit_status > worst_exit_status: worst_exit_status = exit_status except KeyboardInterrupt: display("Terminated by user.") except Error as e: e.terminate() except OSError as e: fatal(os_error(e)) terminate(worst_exit_status)
def main(): with Inform(error_status=2, flush=True, version=version) as inform: # read command line cmdline = docopt(expanded_synopsis, options_first=True, version=version) config = cmdline['--config'] command = cmdline['<command>'] args = cmdline['<args>'] if cmdline['--mute']: inform.mute = True if cmdline['--quiet']: inform.quiet = True options = cull([ 'verbose' if cmdline['--verbose'] else '', 'narrate' if cmdline['--narrate'] else '', 'trial-run' if cmdline['--trial-run'] else '', 'no-log' if cmdline['--no-log'] else '', ]) if cmdline['--narrate']: inform.narrate = True try: # find the command cmd, cmd_name = Command.find(command) # execute the command initialization exit_status = cmd.execute_early(cmd_name, args, None, options) if exit_status is not None: terminate(exit_status) worst_exit_status = 0 try: while True: with Settings(config, cmd, options) as settings: try: exit_status = cmd.execute(cmd_name, args, settings, options) except Error as e: settings.fail(e) e.terminate() if exit_status and exit_status > worst_exit_status: worst_exit_status = exit_status except NoMoreConfigs: pass # execute the command termination exit_status = cmd.execute_late(cmd_name, args, None, options) if exit_status and exit_status > worst_exit_status: worst_exit_status = exit_status except KeyboardInterrupt: display('Terminated by user.') except Error as e: e.terminate() except OSError as e: fatal(os_error(e)) terminate(worst_exit_status)
def update_params(self, **params): prev_params = self.metadata['parameters'] curr_params = params if prev_params and prev_params != curr_params: error(f"{self.repr} parameters differ from those used previously!") for key in params: prev = prev_params.get(key, '') curr = curr_params.get(key, '') if prev != curr: codicil(f" {key!r} was {prev!r}, now {curr!r}") fatal("Use the -f flag to overwrite. Aborting.") self.metadata['parameters'] = curr_params
def get_psf_filename(psf_file): if not psf_file: try: with open(saved_psf_file_filename) as f: psf_file = f.read().strip() display('Using PSF file:', psf_file) except OSError: fatal('missing PSF file name.') try: with open(saved_psf_file_filename, 'w') as f: f.write(psf_file) except OSError as e: warn(os_error(e)) return psf_file
def main(): """ Construct, encrypt, and publish backup keys. As the primary entry point for the end user, this function is also responsible for integrating information from command-line arguments, configuration files, and `setuptools` plugins. """ set_shlib_prefs(use_inform=True, log_cmd=True) args = docopt.docopt(__doc__) if args['--verbose']: set_output_prefs(verbose=True, narrate=True) elif args['--quiet']: set_output_prefs(quiet=True) try: config_path, config = load_config() try: if args['plugins']: list_plugins(config) sys.exit() # Get the passcode before building the archive, so if something # goes wrong with the passcode, we don't need to worry about # cleaning up the unencrypted archive. passcode = query_passcode(config) batch = args['--yes'] or args['--quiet'] archive = build_archive(config, not batch) encrypt_archive(config, archive, passcode) publish_archive(config, archive) except ConfigError as e: e.reraise(culprit=config_path) finally: if 'archive' in locals(): delete_archive(config, archive) except KeyboardInterrupt: print() except Error as e: if args['--verbose']: raise else: e.report() except OSError as e: fatal(os_error(e)) terminate()
def generate(self): comment(' creating key') keyname = self.keyname data = self.data servers = self.data.get('servers', []) opts = data['keygen-options'] account_name = data['abraxas-account'] if account_name: pw.get_account(account_name) passcode = pw.generate_password() description = fmt("{keyname} (created {date})") else: passcode = '' self.warning = 'This key is not protected with a passcode!' description = fmt("{keyname} (created {date} -- no passcode!)") # warn user if they have a key with no passcode and no restrictions for server in servers: server_data = servers[server] restrictions = server_data.get('restrictions') if not restrictions: warn( 'unprotected key being sent to', server, 'without restrictions.' ) args = ['-C', description, '-f', keyname] + opts.split() try: comment(' running:', 'ssh-keygen', *args) keygen = pexpect.spawn('ssh-keygen', args, timeout=None) keygen.expect('Enter passphrase.*: ') keygen.sendline(passcode) keygen.expect('Enter same passphrase again: ') keygen.sendline(passcode) keygen.expect(pexpect.EOF) keygen.close() except pexpect.ExceptionPexpect as err: fatal(err) # remove group/other permissions from keyfiles to_path(keyname).chmod(0o600) to_path(keyname + '.pub').chmod(0o600)
def main(): import docopt args = docopt.docopt(__doc__) # Create the workspace directory: work = SharedWorkspace(args['<workspace>']) if args['--force']: work.rmdir() if work.exists(): error(f"Workspace '{args['<workspace>']}' already exists.") fatal("Use the -f flag to overwrite. Aborting.") work.mkdir() # Fill in the workspace: copyfile(args['<fasta>'], work.target_fasta) copyfile(args['<pdb>'], work.get_target_pdb(args['<pdb>'])) work.loophash_db.symlink_to( os.path.relpath( Path(args['<loophash_db>']).resolve(), work.root, ), target_is_directory=True, ) work.params['target'] = { 'pdb_chain': args['<pdb_chain>'], } work.params['user'] = { 'email': args['--user-email'], } work.write_params() display("Workspace successfully initialized.")
def find_matching_command(given_cmd, known_cmds): matching_cmds = find_matching_commands(given_cmd, known_cmds) pseudo_cmd = shlex.join([Path(sys.argv[0]).name] + sys.argv[1:]) if len(matching_cmds) == 0: guessed_cmd = did_you_mean(given_cmd, known_cmds) fatal(f"""\ Unknown command '{given_cmd}'. Did you mean: $ {pseudo_cmd.replace(given_cmd, guessed_cmd)} """) elif len(matching_cmds) > 1: err = f"Command '{given_cmd}' is ambiguous. Did you mean:\n\n" for cmd, main in matching_cmds: err += f" $ {pseudo_cmd.replace(given_cmd, cmd)}\n" err += '\n' fatal(err) else: return matching_cmds[0]
def main(): # read config file read_config() # read command line cmdline = docopt( __doc__.format(commands=Command.summarize()), options_first=True ) # start logging logfile = BufferedFile(get_setting('log_file'), True) with Inform(logfile=logfile, hanging_indent=False): try: Command.execute(cmdline['<command>'], cmdline['<args>']) except KeyboardInterrupt: output('Terminated by user.') except Error as err: err.terminate() except OSError as err: fatal(os_error(err)) terminate()
def main(): with Inform(error_status=2, flush=True, version=version) as inform: # read command line cmdline = docopt(expanded_synopsis, options_first=True, version=version) config = cmdline['--config'] command = cmdline['<command>'] args = cmdline['<args>'] if cmdline['--mute']: inform.mute = True options = cull([ 'verbose' if cmdline['--verbose'] else '', 'narrate' if cmdline['--narrate'] else '', 'trial-run' if cmdline['--trial-run'] else '', 'no-log' if cmdline['--no-log'] else '', ]) if cmdline['--narrate']: inform.narrate = True try: cmd, cmd_name = Command.find(command) with Settings(config, cmd.REQUIRES_EXCLUSIVITY, options) as settings: try: exit_status = cmd.execute(cmd_name, args, settings, options) except Error as e: settings.fail(e) e.terminate(True) except KeyboardInterrupt: display('Terminated by user.') exit_status = 0 except Error as e: e.terminate() except OSError as e: fatal(os_error(e)) terminate(exit_status)
def main(self): appcli.load(self) io = ProtocolIO.from_stdin() if io.errors: fatal("protocol has errors, not adding footnote.") if not io.protocol: fatal("no protocol specified.") p = io.protocol footnote = self.text if self.wrap else pre(self.text) pattern = re.compile(self.where or '(?=[.:])') try: p.insert_footnotes(footnote, pattern=pattern) except ValueError: fatal(f"pattern {pattern!r} not found in protocol.") p.merge_footnotes() io.to_stdout(self.force_text)
def protocol_from_stdin(): io = ProtocolIO.from_stdin() if io.errors: fatal("protocol has errors, not stashing.") return io.protocol
def main(): import docopt args = docopt.docopt(__doc__) plots = [] for path in args['<dels_workspace>']: work_dels = DeletionsWorkspace.from_path(path) msa = load_weighted_msa(work_dels.msa) dels = pd.read_hdf(work_dels.deletions_hdf5) plot = Plot() plot.y = count_deletions(msa, dels) plot.x = np.arange(len(plot.y)) plot.label = f'{work_dels.relpath} (N={len(dels)})' plot.seq = msa.ref_ungapped plots.append(plot) if args['--align']: if len(plots) != 2: fatal("Must specify 2 worksapces to use the --align option.") # I decided to use BLOSUM62 because the two sequences in this case may # not be particularly similar. I used the corresponding gap penalties # from BLAST 2.2.27, which I found in the reference below: # # https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3848038/ alignments = align.globalds( plots[0].seq, plots[1].seq, blosum62, -11, -1, ) aligned_seq1, aligned_seq2, score, start, end = alignments[0] aligned_x1 = [] aligned_x2 = [] for i, (aa1, aa2) in enumerate(zip(aligned_seq1, aligned_seq2)): if aa1 not in '-': aligned_x1.append(i) if aa2 not in '-': aligned_x2.append(i) plots[0].x = np.array(aligned_x1) plots[1].x = np.array(aligned_x2) percent_id = sum(x[0] == x[1] and '-' not in x for x in zip(aligned_seq1, aligned_seq2)) percent_id /= max(len(p.seq) for p in plots) print(f"Scaffolds aligned with {100*percent_id:.2f}% identity.") if os.fork(): sys.exit() for p in plots: plt.plot(p.x, p.y, label=p.label) plt.xlabel("aligned residue index" if args['--align'] else "residue index") plt.ylabel("relative deletions" if args['--normalize'] else "deletions") plt.xlim((0, max(p.x[-1] for x in plots))) plt.legend(loc='best') plt.show()
def format_text(self, *args, **kwargs): fatal( f"failed to unpickle stashed protocol:\n{self.err.__class__.__name__}: {self.err}" )
def main(): try: # Read command line {{{1 cmdline = docopt(__doc__) keys = cmdline["--keys"].split(",") if cmdline["--keys"] else [] update = cmdline["--update"].split(",") if cmdline["--update"] else [] skip = cmdline["--skip"].split(",") if cmdline["--skip"] else [] Inform( narrate=cmdline["--narrate"] or cmdline["--verbose"], verbose=cmdline["--verbose"], logfile=".sshdeploy.log", prog_name=False, flush=True, version=__version__, ) if keys and not cmdline["--trial-run"]: fatal( "Using the --keys option results in incomplete authorized_keys files.", "It may only be used for testing purposes.", "As such, --trial-run must also be specified when using --keys.", sep="\n", ) # Generated detailed help {{{1 if cmdline["manual"]: from pkg_resources import resource_string try: Run(cmd=["less"], modes="soeW0", stdin=resource_string("src", "manual.rst").decode("utf8")) except OSError as err: error(os_error(err)) terminate() # Read config file {{{1 try: config_file = cmdline.get("--config-file") config_file = config_file if config_file else "sshdeploy.conf" contents = to_path(config_file).read_text() except OSError as err: fatal(os_error(err)) code = compile(contents, config_file, "exec") config = {} try: exec(code, config) except Exception as err: fatal(err) # Move into keydir {{{1 keydir = cmdline["--keydir"] keydir = to_path(keydir if keydir else "keys-" + date) if cmdline["generate"]: comment("creating key directory:", keydir) rm(keydir) mkdir(keydir) cd(keydir) elif cmdline["distribute"]: cd(keydir) # determine default values for key options defaults = {} for name, default in [ ("keygen-options", DefaultKeygenOpts), ("abraxas-account", DefaultAbraxasAccount), ("remote-include-filename", DefaultRemoteIncludeFilename), ]: defaults[name] = config.get(name, default) # Generate keys {{{1 if cmdline["generate"]: for keyname in sorted(config["keys"].keys()): data = config["keys"][keyname] if keys and keyname not in keys: # user did not request this key continue # get default values for missing key options for option in defaults: data[option] = data.get(option, defaults[option]) # generate the key key = Key(keyname, data, update, skip, cmdline["--trial-run"]) key.generate() # Publish keys {{{1 elif cmdline["distribute"]: for keyname in sorted(config["keys"].keys()): data = config["keys"][keyname] if keys and keyname not in keys: continue # user did not request this key # get default values for missing key options for option in defaults: data[option] = data.get(option, defaults[option]) # publish the key pair to clients key = Key(keyname, data, update, skip, cmdline["--trial-run"]) key.publish_private_key() key.gather_public_keys() # publish authorized_keys files to servers {{{1 if cmdline["distribute"]: for each in sorted(AuthKeys.known): authkey = AuthKeys.known[each] authkey.publish() authkey.verify() # Process hosts {{{1 elif cmdline["test"] or cmdline["clean"] or cmdline["hosts"]: hosts = set() for keyname, data in config["keys"].items(): if keys and keyname not in keys: continue # user did not request this key # add servers to list of hosts for server, options in data["servers"].items(): if update and server not in update or server in skip: continue if "bypass" not in options: hosts.add(server) # add clients to list of hosts for client in data["clients"].keys(): if update and client not in update or client in skip: continue hosts.add(client) # process the hosts if cmdline["test"]: # test host for host in sorted(hosts): test_access(host) elif cmdline["clean"]: # clean host for host in sorted(hosts): clean(host) else: # list hosts for host in sorted(hosts): display(host) except OSError as err: error(os_error(err)) except KeyboardInterrupt: display("Killed by user") done()
def show_list_dialog(options): msg = 'selection dialog not available, you must install python3-gobject.' notify(msg) fatal(msg)
if path.is_symlink(): notes = f" (symlink to {path.resolve().name})" doc += f" {path.name}{notes}\n" return doc.strip() if __name__ == '__main__': template_docs = document_templates() args = docopt.docopt(__doc__.format(indent(template_docs, 8*' '))) case = name_test_dir(args['<family>'], args['--num']) template = TEMPLATE_DIR / args['<template>'] if not template.is_dir(): fatal("template not found", culprit=template.name) shutil.copytree(template, case, symlinks=True) print(case) if args['--readme']: readme = case / 'README' readme.touch() editor = args['--editor'] or os.environ.get('EDITOR', 'vim') editor_args = [ str(p) for p in sorted( case.iterdir(), key=lambda p: FILE_ORDER.get(p.name, len(FILE_ORDER)), )
import nestedtext as nt from voluptuous import Schema, Coerce, Invalid from inform import fatal, full_stop from pprint import pprint schema = Schema({ 'debug': Coerce(bool), 'secret_key': str, 'allowed_hosts': [str], 'database': { 'engine': str, 'host': str, 'port': Coerce(int), 'user': str, }, 'webmaster_email': str, }) try: keymap = {} raw = nt.load('deploy.nt', keymap=keymap) config = schema(raw) except nt.NestedTextError as e: e.terminate() except Invalid as e: kind = 'key' if 'key' in e.msg else 'value' loc = keymap[tuple(e.path)] fatal(full_stop(e.msg), culprit=e.path, codicil=loc.as_line(kind)) pprint(config)
def run_script(self, account, script): def run_xdotool(args): try: #[get_setting('xdotool_executable'), 'getactivewindow'] + Run(get_setting('xdotool_executable').split() + args, 'soeW') except OSError as err: fatal(os_error(err)) def autotype(text): # Split the text into individual key strokes and convert the special # characters to their xkeysym names keysyms = [] for char in text: if char in string.ascii_letters + string.digits: keysym = char else: keysym = KEYSYMS.get(char) if not keysym: error('cannot map to keysym, unknown', culprit=char) else: keysyms.append(keysym) run_xdotool('key --clearmodifiers'.split() + keysyms) # Create the default script if a script was not given if script is True: # this bit of trickery gets the name of the default field name, key = account.split_name(None) name = account.combine_name(name, key) script = "{%s}{return}" % name # Run the script regex = re.compile(r'({\w+})') out = [] scrubbed = [] sleep(INITIAL_AUTOTYPE_DELAY) for term in regex.split(script): if term and term[0] == '{' and term[-1] == '}': # we have found a command cmd = term[1:-1].lower() if cmd == 'tab': out.append('\t') scrubbed.append('\t') elif cmd == 'return': out.append('\n') scrubbed.append('\n') elif cmd.startswith('sleep '): cmd = cmd.split() try: assert cmd[0] == 'sleep' assert len(cmd) == 2 if out: autotype(''.join(out)) out = [] sleep(float(cmd[1])) scrubbed.append('<sleep %s>' % cmd[1]) except (AssertionError, TypeError): raise fatal('syntax error in keyboard script.', culprit=term) else: name, key = account.split_name(cmd) try: value = dedent(str(account.get_field(name, key))).strip() out.append(value) if account.is_secret(name, key): scrubbed.append('<%s>' % cmd) else: scrubbed.append('%s' % value) except Error as err: err.terminate() else: out.append(term) log('Autotyping "%s".' % ''.join(scrubbed).replace('\t', '→').replace('\n', '↲')) autotype(''.join(out))
def run_xdotool(args): try: #[get_setting('xdotool_executable'), 'getactivewindow'] + Run(get_setting('xdotool_executable').split() + args, 'soeW') except OSError as err: fatal(os_error(err))
def template_stock_nM(self, x): if x is not None: return x fatal("Must specify a template stock concentration")
def show_error_dialog(message): msg = 'error dialog not available, you must install python3-gobject.' notify(msg) fatal(msg)
path = Path(args['<table>']) keys = args['--key'] loaders = { '.xlsx': lambda p: pd.read_excel(p, header=None, dtype=str), '.csv': lambda p: pd.read_csv(p, header=None, dtype=str), '.tsv': lambda p: pd.read_csv(p, sep='\t', header=None, dtype=str), } try: df = loaders[path.suffix](path) except KeyError: err = f"""\ Unsupported file extension: *{path.suffix} Expected one of the following: *.xlsx *.csv *.tsv""" fatal(err, culprit=path) except FileNotFoundError: fatal("no such file", culprit=path) # Add colons to the condition names: df[0] = df[0].map(lambda x: x.rstrip(':') + ':') # Replace hyphens with true minus-signs: for c in df.columns[1:]: df[c] = df[c].str.replace(r'^-$', '−') rows = df.values.tolist() align = ['<'] + (len(df.columns) - 1) * ['^'] br = '\n' p = Protocol()
def main(self): appcli.load(self) # Defer importing `sqlalchemy`. from . import model with model.open_db() as db: if self.ls: model.list_protocols( db, categories=self.categories, dependencies=self.dependencies, include_dependents=self.show_dependents, include_complete=self.show_all, ) elif self.edit: model.edit_protocol( db, self.id, protocol=protocol_from_stdin(), message=self.message, categories=self.categories, dependencies=self.dependencies, explicit=self.explicit, ) elif self.peek: model.peek_protocol( db, self.id, quiet=self.quiet, force_text=self.force_text, ) elif self.pop: model.pop_protocol( db, self.id, quiet=self.quiet, force_text=self.force_text, ) elif self.drop: model.drop_protocols(db, self.ids) elif self.restore: model.restore_protocols(db, self.ids) elif self.clear: model.clear_protocols(db) elif self.reset: model.reset_protocols(db) else: protocol = protocol_from_stdin() if not protocol: if self.add: fatal("no protocol specified.") model.list_protocols( db, categories=self.categories, dependencies=self.dependencies, include_dependents=self.show_dependents, include_complete=self.show_all, ) else: model.add_protocol( db, protocol, message=self.message, categories=self.categories, dependencies=self.dependencies, )