def get_contigs_to_keep(args): ''' Return contigs matching criteria: - novel block size >= MIN_CLIP - novel blocks are spliced in some way - novel exons have corresponding novel splice sites and novel splice donor/acceptor motifs - TSVs occur in exonic regions ''' try: cinfo_file = args.contig_info_file contigs = pd.read_csv(cinfo_file, sep='\t') except IOError as exception: exit_with_error(str(exception), constants.EXIT_FILE_IO_ERROR) gene_tree, ex_trees, ex_ref = ac.get_gene_lookup(args.tx_ref_file) contigs['large_varsize'] = contigs.contig_varsize >= MIN_CLIP contigs['is_contig_spliced'] = contigs.contig_cigar.apply( lambda x: bool(re.search('N', x))) contigs['spliced_exon'] = match_splice_juncs(contigs) contigs['overlaps_exon'] = vars_overlap_exon(contigs, ex_trees) contigs['overlaps_gene'] = contigs.apply(overlaps_gene, axis=1, args=(gene_tree, )) # keep exons falling outside the gene is_intergenic_exon = np.logical_and.reduce( (contigs.spliced_exon, contigs.variant_type == 'NE', contigs.large_varsize, np.invert(contigs.overlaps_gene))) # novel exon contigs (spliced, valid motif and large variant size) is_novel_exon = np.logical_and(contigs.spliced_exon, contigs.large_varsize) if args.mismatches < 4: contigs = check_for_valid_motifs(contigs, is_novel_exon, args) is_novel_exon = np.logical_and(is_novel_exon, contigs.valid_motif) ne_vars = contigs[np.logical_or(is_novel_exon, is_intergenic_exon)].variant_id.values # keep all splice vars as_vars = contigs.variant_id.values[contigs.variant_type.isin(SPLICE_VARS)] # get junc vars junc_vars = get_junc_vars(contigs, ex_trees, args) # check size of retained introns ri_vars = contigs[np.logical_and(contigs.variant_type == 'RI', contigs.large_varsize)].variant_id.values # get fusions and TSVs fus_vars = get_fusion_vars(contigs) sv_vars = get_tsv_vars(contigs) # collate contigs to keep keep_vars = np.unique( np.concatenate( [ri_vars, as_vars, ne_vars, sv_vars, fus_vars, junc_vars])) contigs['variant_of_interest'] = contigs.variant_id.isin(keep_vars) contigs.to_csv('%s_info.tsv' % args.out_prefix, sep='\t', index=None) keep_contigs = contigs[contigs.variant_of_interest].contig_id.values return (keep_contigs)
def main(): args = parse_args(sys.argv[1:]) init_logging(args.log) try: contigs = pd.read_csv(args.contig_info, sep='\t', low_memory=False).fillna('') de_results = pd.read_csv(args.de_results, sep='\t', low_memory=False) vafs = pd.read_csv(args.vaf_estimates, sep='\t', low_memory=False) vafs = vafs[['contig_id', 'TPM', 'mean_WT_TPM', 'VAF']].drop_duplicates() gene_filter = pd.read_csv(args.gene_filter, header=None, low_memory=False) if args.gene_filter != '' \ else pd.DataFrame() except IOError as exception: exit_with_error(str(exception), EXIT_FILE_IO_ERROR) # count the number of variants per contig (count uninteresting vars) vars_per_contig = contigs.groupby('contig_id', as_index=False) vars_per_contig = vars_per_contig.agg( {'variant_id': lambda x: len(np.unique(x))}) vars_per_contig = vars_per_contig.rename({'variant_id': 'vars_in_contig'}, axis=1) contigs = contigs.merge(vars_per_contig) # consider only variants of interest contigs = contigs[contigs.variant_of_interest] contigs['sample'] = args.sample if args.var_filter: contigs = contigs[contigs.variant_type.apply( lambda v: v in args.var_filter).values] if len(gene_filter) > 0: contigs = filter_by_gene(contigs, gene_filter) if len(contigs) == 0: logging.info('WARNING: no variants present after filtering. Exiting.') contigs.to_csv(sys.stdout, index=False, sep='\t', na_rep='NA') sys.exit() logging.info('Adding DE and VAF info...') contigs = add_de_info(contigs, de_results) contigs = pd.merge(contigs, vafs, on='contig_id', how='left') short_gnames = contigs.overlapping_genes.map(str).apply( get_short_gene_name) contig_ids, samples = contigs.contig_id, contigs['sample'] con_names = [ '|'.join([s, cid, sg]) for cid, s, sg in zip(contig_ids, samples, short_gnames) ] contigs[ 'unique_contig_ID'] = con_names # TODO: fix this field (it is not really unique) contigs = get_variant_seq(contigs, args.contig_fasta) logging.info('Outputting to CSV') contigs = reformat_fields(contigs) contigs.to_csv(sys.stdout, index=False, sep='\t', na_rep='NA')
def main(): args = parse_args() init_logging(args.log) set_globals(args) keep_contigs = get_contigs_to_keep(args) if len(keep_contigs) > 0: write_output(args, keep_contigs) write_bam(args, keep_contigs) else: exit_with_error('ERROR: no variants to output.', constants.EXIT_OUTPUT_ERROR)
def write_output(args, keep_contigs): cvars_file = args.vcf_file try: vcf = pd.read_csv(cvars_file, sep='\t', header=None, comment='#') cvf = open(cvars_file, 'r') for line in cvf: if not line.startswith('#'): break print(line.strip()) cvf.close() except IOError as exception: exit_with_error(str(exception), constants.EXIT_FILE_IO_ERROR) vcf = vcf[vcf[7].apply( lambda x: x.split(';')[0].split('=')[1] in keep_contigs)] vcf.to_csv(sys.stdout, sep='\t', index=False, header=False)
def main(): args = parse_args(sys.argv[1:]) init_logging(args.log) try: contigs = pd.read_csv(args.contig_info, sep='\t', low_memory=False) st_bed = pd.read_csv(args.st_bed, sep='\t', header=None, names=BED_COLS, low_memory=False) except IOError as exception: exit_with_error(str(exception), EXIT_FILE_IO_ERROR) logging.info('Matching contigs to ST alignments...') contigs = get_st_alignments(contigs, args.cont_align) logging.info('Counting reads crossing variant boundaries...') bamf = pysam.AlignmentFile(args.read_align, "rb") contigs = get_read_support(contigs, bamf, st_bed) logging.info('Outputting to CSV') contigs = contigs.sort_values(by='PValue', ascending=True) contigs.to_csv(sys.stdout, index=False, sep='\t', na_rep='NA')
def main(): args = parse_args() init_logging(args.log) genome_bed, st_block_bed, st_gene_bed, st_fasta = get_output_files(args.sample, args.outdir) if os.path.exists(genome_bed): os.remove(genome_bed) if os.path.exists(st_block_bed): os.remove(st_block_bed) if os.path.exists(st_gene_bed): os.remove(st_gene_bed) if os.path.exists(st_fasta): os.remove(st_fasta) try: gtf = load_gtf_file(args.gtf_file) cvcf = load_vcf_file(args.contig_vcf) contigs = pd.read_csv(args.contig_info, sep='\t', low_memory=False).fillna('') except IOError as exception: exit_with_error(str(exception), EXIT_FILE_IO_ERROR) make_supertranscripts(args, contigs, cvcf, gtf) write_canonical_genes(args, contigs, gtf)
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv global_cli_args = { 'debug': { 'short': '-d', 'long': '--debug', 'has_arg': False, 're-exec': True, 'env': 'BLOCKSTACK_DEBUG', 'help': 'Enable global debugging messages', 'similar': ['--dbg', '-dd', '-ddd', '-dddd', '--verbose'], 'secret': False, }, 'config': { 'short': '-c', 'long': '--config', 'has_arg': True, 're-exec': True, 'env': 'BLOCKSTACK_CLIENT_CONFIG', 'help': 'Path to alternative configuration file and associated state', 'similar': ['--conf'], 'secret': False, }, 'default_yes': { 'short': '-y', 'long': '--yes', 'has_arg': False, 're-exec': False, 'env': 'BLOCKSTACK_CLIENT_INTERACTIVE_YES', 'help': 'Assume default/yes response to all queries', 'similar': [], 'secret': False, }, 'api_pass': { 'short': '-a', 'long': '--api_password', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_PASSWORD', 'help': 'API password to use', 'similar': ['--api-password', '--api-pass', '--api_pass'], 'secret': True, }, 'api_session': { 'short': '-A', 'long': '--api_session', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_SESSION', 'help': 'API session token to use', 'similar': ['--api-session', '--session', '--ses'], 'secret': True, }, 'api_bind': { 'short': '-b', 'long': '--bind', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_BIND', 'help': 'Address or hostname to bind the API server', 'similar': [], 'secret': False, }, 'dry_run': { 'short': '-n', 'long': '--dry_run', 'has_arg': False, 're-exec': True, 'env': 'BLOCKSTACK_DRY_RUN', 'help': 'Do not send transactions. Return the signed transaction instead.', 'similar': ['--dry-run', '--dryrun'], 'secret': False, }, 'wallet_password': { 'short': '-p', 'long': '--password', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLIENT_WALLET_PASSWORD', 'help': 'Wallet decryption password', 'similar': ['--pass', '--passwd'], 'secret': True, }, 'indexer_host': { 'short': '-H', 'long': '--host', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLI_SERVER_HOST', 'help': 'Hostname or IP address of the Blockstack blockchain indexer', 'similar': ['--ip', '--ipv4'], 'secret': False, }, 'indexer_port': { 'short': '-P', 'long': '--port', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLI_SERVER_PORT', 'help': 'Port number of the Blockstack blockchain indexer', 'similar': [], 'secret': False, }, 'secret_fd': { 'short': '-f', 'long': '--secrets', 'has_arg': True, 're-exec': False, 'help': 'Used internally; file descriptor number to serialized secrets preserved across execv(2).', 'similar': [], 'secret': False, }, } if '-v' in argv or '--version' in argv: print(VERSION) sys.exit(0) arg_info = parse_args(global_cli_args, argv, config_path=config_path) if 'error' in arg_info: print("Failed to parse global CLI arguments: {}".format( arg_info['error']), file=sys.stderr) print("Global CLI arguments:\n{}\n".format("\n".join([ "\t{}/{}\n\t\t{}".format(cliarg['short'], cliarg['long'], cliarg['help']) for argname, cliarg in global_cli_args.items() ])), file=sys.stderr) if 'similar' in arg_info: siminfo = arg_info['similar'] assert len(siminfo.keys()) == 1 opt = siminfo.keys()[0] arg = siminfo[opt] print("Suggestion: Use '{}' instead of '{}'".format(opt, arg), file=sys.stderr) sys.exit(1) cli_debug = arg_info['args'].get('debug') cli_config_argv = (arg_info['args'].has_key('config')) # set (non-secret) environment variables for envar, enval in arg_info['envs'].items(): if os.environ.get(envar) is None: if cli_debug: print("Set {} to {}".format(envar, enval), file=sys.stderr) os.environ[envar] = enval # set secrets... for secvar, secval in arg_info['secrets'].items(): set_secret(secvar, secval) # re-exec? if arg_info['re-exec']: new_argv = arg_info['new_argv'] if len(arg_info['secrets']) > 0: secbuf = serialize_secrets() fd = write_secrets(secbuf) new_argv += ['--secrets', str(fd)] new_argv = [sys.executable] + new_argv if cli_debug: print("Re-exec as `{}`".format(", ".join( ['"{}"'.format(i) for i in new_argv])), file=sys.stderr) try: os.execv(new_argv[0], new_argv) except: import traceback as tb tb.print_exc() sys.exit(1) # load secrets if arg_info['args'].has_key('secret_fd'): fd_str = arg_info['args']['secret_fd'] if fd_str: try: fd = int(fd_str) except: print('Invalid secret fd {}'.format(fd_str), file=sys.stderr) sys.exit(1) log.debug("Load secrets from {}".format(fd)) try: os.lseek(fd, 0, os.SEEK_SET) secbuf = os.read(fd, 65536) os.close(fd) load_secrets(secbuf) except Exception as e: traceback.print_exc() sys.exit(1) # do one-time opt-in request uuid_path = client_uuid_path(config_dir=os.path.dirname(config_path)) first_time = False client_uuid = None if not os.path.exists(uuid_path): first_time = True client_uuid = get_or_set_uuid(config_dir=os.path.dirname(config_path)) res = config.setup_config( config_path=config_path, interactive=(os.environ.get("BLOCKSTACK_CLIENT_INTERACTIVE_YES") != '1')) if 'error' in res: exit_with_error("Failed to load and verify config file: {}".format( res['error'])) conf = res['config'] # if the wallet exists, make sure that it's the latest version wallet_path = os.path.join(os.path.dirname(config_path), WALLET_FILENAME) if os.path.exists(wallet_path): res = inspect_wallet(wallet_path=wallet_path) if 'error' in res: exit_with_error( "Failed to inspect wallet at {}".format(wallet_path)) if res['migrate'] or res['format'] != 'current': if len(sys.argv) <= 1 or sys.argv[1] != 'setup_wallet': exit_with_error( "Wallet is in legacy format. Please unlock and migrate it with `ysi setup_wallet`." ) parser = BlockstackArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods all_method_names = get_cli_methods() all_methods = parse_methods(all_method_names) build_method_subparsers(subparsers, all_methods) # Print default help message, if no argument is given if len(argv) == 1 or '-h' in argv or '--help' in argv: parser.print_help() sys.exit(0) interactive, args, directive = False, None, None try: # capture stderr so we don't repeat ourselves args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = BlockstackArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) directive_subparsers = directive_parser.add_subparsers( dest='action') # only parse the directive build_method_subparsers(directive_subparsers, all_methods, include_args=False, include_opts=False) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:]) # want interactive prompting interactive, directive = True, directive_args.action except SystemExit: # still invalid return {'error': 'Invalid arguments. Try passing "-h".'} result = {} ysi_server, ysi_port = conf['ysi-client']['server'], conf['ysi-client'][ 'port'] # initialize ysi connection session(server_host=ysi_server, server_port=ysi_port, set_global=True) prompt_func_arg = lambda help, name: raw_input('required: {} ("{}"): '. format(help, name)) prompt_func_opt = lambda help, name: raw_input('optional: {} ("{}"): '. format(help, name)) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] pragmas = method_info['pragmas'] # interactive? if interactive: arg_names = [mi['name'] for mi in method_info['args']] opt_names = [mi['name'] for mi in method_info['opts']] arg_usage = ' '.join(arg_names) opt_usage = ' '.join(['[{}]'.format(opt) for opt in opt_names]) print('') print('Interactive prompt engaged. Press Ctrl+C to quit') print('Help for "{}": {}'.format(method_info['command'], method_info['help'])) print('Arguments: {} {} {}'.format(method_info['command'], arg_usage, opt_usage)) print('') required_args = prompt_args(method_info['args'], prompt_func_arg) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args(method_info['opts'], prompt_func_opt) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command'] ] + required_args + optional_args try: args, unknown_args = parser.parse_known_args(args=full_args) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method(args, config_path=config_path) return {'status': True, 'result': result, 'pragmas': pragmas} # not found return {'error': 'No such command "{}"'.format(args.action)}
if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command'] ] + required_args + optional_args try: args, unknown_args = parser.parse_known_args(args=full_args) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method(args, config_path=config_path) return {'status': True, 'result': result, 'pragmas': pragmas} # not found return {'error': 'No such command "{}"'.format(args.action)} if __name__ == '__main__': result = run_cli() if 'error' in result: exit_with_error(result['error']) else: if 'raw' in result['pragmas']: print(result['result']) else: print_result(result['result']) sys.exit(0)
def load_params(): if not os.path.exists('tool.cfg'): utils.exit_with_error("tool.cfg not found") global params params = Params.load(fsutils.read_file('tool.cfg')) print(params)
import utils as u import vk import os import sys from functools import lru_cache WAIT_TIME = u.WAIT_TIME # Intialize constants # Initialize vk api if not os.path.exists('params.json'): u.exit_with_error( "Файл params.json не найден; Создайте файл и повторите попытку") sys.exit(1) params = u.json_read('params.json') session = vk.AuthSession(**params) api = vk.API(session, v='4.104') _fwd_id = 0 # Initialize functions # Returns FN LN by user object def gen_name(user): return user['first_name'] + ' ' + user['last_name'] def gen_dir_name(user): return u.transliterate(user['first_name']) + '_' + u.transliterate(
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv # only version? if '-v' in argv or '--version' in argv: print config.VERSION sys.exit(0) # alternative config path? if '-c' in argv or '--config' in argv: i = 1 while i < len(argv): if argv[i] == '-c' or argv[i] == '--config': if i + 1 >= len(argv): print >> sys.stderr, "%s: missing path" % argv[i] sys.exit(1) config_path = argv[i+1] argv.pop(i) argv.pop(i) else: i+=1 conf = config.get_config(path=config_path) if conf is None: return {'error': 'Failed to load config'} conf_version = conf.get('client_version', '') if not semver_match( conf_version, VERSION ): exit_with_error("Invalid configuration file: %s != %s" % (conf_version, VERSION), \ "Your configuration file (%s) is out of date. Please move it and try again in order to automatically generate a new config file." % config_path) advanced_mode = conf.get('advanced_mode', False) parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods basic_methods = get_cli_basic_methods() basic_method_info = parse_methods( basic_methods ) build_method_subparsers( subparsers, basic_method_info ) all_methods = basic_method_info if advanced_mode: # add advanced methods log.debug("Enabling advanced methods") advanced_methods = get_cli_advanced_methods() advanced_method_info = parse_methods( advanced_methods ) build_method_subparsers( subparsers, advanced_method_info ) all_methods += advanced_method_info # Print default help message, if no argument is given if len(argv) == 1 or '-h' in argv: parser.print_help() return {} interactive = False args = None directive = None try: args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = argparse.ArgumentParser(description='Blockstack cli version {}'.format(config.VERSION)) directive_subparsers = directive_parser.add_subparsers(dest='action') # only parse the directive build_method_subparsers( directive_subparsers, all_methods, include_args=False, include_opts=False ) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:] ) # want interactive prompting interactive = True directive = directive_args.action except SystemExit: # still invalid parser.print_help() return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server = conf['server'] blockstack_port = conf['port'] # initialize blockstack connection session(conf=conf, server_host=blockstack_server, server_port=blockstack_port, set_global=True) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] # interactive? if interactive: print "" print "Interactive prompt engaged. Press Ctrl+C to quit" print "Help for '%s': %s" % (method_info['command'], method_info['help']) print "" required_args = prompt_args( method_info['args'], lambda arghelp, argname: raw_input("%s ('%s'): " % (arghelp, argname)) ) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args( method_info['opts'], lambda arghelp, argname: raw_input("optional: %s ('%s'): " % (arghelp, argname) )) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command']] + required_args + optional_args try: args, unknown_args = parser.parse_known_args( args=full_args ) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method( args, config_path=config_path ) return result # not found return {'error': "No such command '%s'" % args.action}
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv # alternative config path? if '-c' in argv or '--config' in argv: i = 1 while i < len(argv): if argv[i] == '-c' or argv[i] == '--config': if i + 1 >= len(argv): print >> sys.stderr, "%s: missing path" % argv[i] sys.exit(1) config_path = argv[i+1] argv.pop(i) argv.pop(i) else: i+=1 conf = config.get_config(path=config_path) if conf is None: return {'error': 'Failed to load config'} conf_version = conf.get('client_version', '') if not semver_match( conf_version, VERSION ): exit_with_error("Invalid configuration file: %s != %s" % (conf_version, VERSION), \ "Your configuration file (%s) is out of date. Please move it and try again in order to automatically generate a new config file." % config_path) advanced_mode = conf.get('advanced_mode', False) parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods basic_methods = get_cli_basic_methods() basic_method_info = parse_methods( basic_methods ) build_method_subparsers( subparsers, basic_method_info ) all_methods = basic_method_info if advanced_mode: # add advanced methods log.debug("Enabling advanced methods") advanced_methods = get_cli_advanced_methods() advanced_method_info = parse_methods( advanced_methods ) build_method_subparsers( subparsers, advanced_method_info ) all_methods += advanced_method_info # Print default help message, if no argument is given if len(argv) == 1: parser.print_help() return {} interactive = False args = None directive = None try: args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = argparse.ArgumentParser(description='Blockstack cli version {}'.format(config.VERSION)) directive_subparsers = directive_parser.add_subparsers(dest='action') # only parse the directive build_method_subparsers( directive_subparsers, all_methods, include_args=False, include_opts=False ) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:] ) # want interactive prompting interactive = True directive = directive_args.action except SystemExit: # still invalid parser.print_help() return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server = conf['server'] blockstack_port = conf['port'] # initialize blockstack connection session(conf=conf, server_host=blockstack_server, server_port=blockstack_port, set_global=True) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] # interactive? if interactive: print "" print "Interactive prompt engaged. Press Ctrl+C to quit" print "Help for '%s': %s" % (method_info['command'], method_info['help']) print "" required_args = prompt_args( method_info['args'], lambda arghelp, argname: raw_input("%s ('%s'): " % (arghelp, argname)) ) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args( method_info['opts'], lambda arghelp, argname: raw_input("optional: %s ('%s'): " % (arghelp, argname) )) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command']] + required_args + optional_args try: args, unknown_args = parser.parse_known_args( args=full_args ) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method( args, config_path=config_path ) return result # not found return {'error': "No such command '%s'" % args.action}
if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args( method_info['opts'], lambda arghelp, argname: raw_input("optional: %s ('%s'): " % (arghelp, argname) )) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command']] + required_args + optional_args try: args, unknown_args = parser.parse_known_args( args=full_args ) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method( args, config_path=config_path ) return result # not found return {'error': "No such command '%s'" % args.action} if __name__ == '__main__': result = run_cli() if 'error' in result: exit_with_error(result['error']) else: print_result(result) sys.exit(0)
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv global_cli_args = { 'debug': { 'short': '-d', 'long': '--debug', 'has_arg': False, 're-exec': True, 'env': 'BLOCKSTACK_DEBUG', 'help': 'Enable global debugging messages', 'similar': ['--dbg', '-dd', '-ddd', '-dddd', '--verbose'], 'secret': False, }, 'config': { 'short': '-c', 'long': '--config', 'has_arg': True, 're-exec': True, 'env': 'BLOCKSTACK_CLIENT_CONFIG', 'help': 'Path to alternative configuration file and associated state', 'similar': ['--conf'], 'secret': False, }, 'default_yes': { 'short': '-y', 'long': '--yes', 'has_arg': False, 're-exec': False, 'env': 'BLOCKSTACK_CLIENT_INTERACTIVE_YES', 'help': 'Assume default/yes response to all queries', 'similar': [], 'secret': False, }, 'api_pass': { 'short': '-a', 'long': '--api_password', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_PASSWORD', 'help': 'API password to use', 'similar': ['--api-password', '--api-pass', '--api_pass'], 'secret': True, }, 'api_session': { 'short': '-A', 'long': '--api_session', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_SESSION', 'help': 'API session token to use', 'similar': ['--api-session', '--session', '--ses'], 'secret': True, }, 'api_bind': { 'short': '-b', 'long': '--bind', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_API_BIND', 'help': 'Address or hostname to bind the API server', 'similar': [], 'secret': False, }, 'dry_run': { 'short': '-n', 'long': '--dry_run', 'has_arg': False, 're-exec': True, 'env': 'BLOCKSTACK_DRY_RUN', 'help': 'Do not send transactions. Return the signed transaction instead.', 'similar': ['--dry-run', '--dryrun'], 'secret': False, }, 'wallet_password': { 'short': '-p', 'long': '--password', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLIENT_WALLET_PASSWORD', 'help': 'Wallet decryption password', 'similar': ['--pass', '--passwd'], 'secret': True, }, 'indexer_host': { 'short': '-H', 'long': '--host', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLI_SERVER_HOST', 'help': 'Hostname or IP address of the Blockstack blockchain indexer', 'similar': ['--ip', '--ipv4'], 'secret': False, }, 'indexer_port': { 'short': '-P', 'long': '--port', 'has_arg': True, 're-exec': False, 'env': 'BLOCKSTACK_CLI_SERVER_PORT', 'help': 'Port number of the Blockstack blockchain indexer', 'similar': [], 'secret': False, }, 'secret_fd': { 'short': '-f', 'long': '--secrets', 'has_arg': True, 're-exec': False, 'help': 'Used internally; file descriptor number to serialized secrets preserved across execv(2).', 'similar': [], 'secret': False, }, } if '-v' in argv or '--version' in argv: print(VERSION) sys.exit(0) arg_info = parse_args( global_cli_args, argv, config_path=config_path ) if 'error' in arg_info: print("Failed to parse global CLI arguments: {}".format(arg_info['error']), file=sys.stderr) print("Global CLI arguments:\n{}\n".format( "\n".join( ["\t{}/{}\n\t\t{}".format(cliarg['short'], cliarg['long'], cliarg['help']) for argname, cliarg in global_cli_args.items()] )), file=sys.stderr) if 'similar' in arg_info: siminfo = arg_info['similar'] assert len(siminfo.keys()) == 1 opt = siminfo.keys()[0] arg = siminfo[opt] print("Suggestion: Use '{}' instead of '{}'".format(opt, arg), file=sys.stderr) sys.exit(1) cli_debug = arg_info['args'].get('debug') cli_config_argv = (arg_info['args'].has_key('config')) # set (non-secret) environment variables for envar, enval in arg_info['envs'].items(): if os.environ.get(envar) is None: if cli_debug: print("Set {} to {}".format(envar, enval), file=sys.stderr) os.environ[envar] = enval # set secrets... for secvar, secval in arg_info['secrets'].items(): set_secret(secvar, secval) # re-exec? if arg_info['re-exec']: new_argv = arg_info['new_argv'] if len(arg_info['secrets']) > 0: secbuf = serialize_secrets() fd = write_secrets(secbuf) new_argv += ['--secrets', str(fd)] new_argv = [sys.executable] + new_argv if cli_debug: print("Re-exec as `{}`".format(", ".join([ '"{}"'.format(i) for i in new_argv])), file=sys.stderr) try: os.execv(new_argv[0], new_argv) except: import traceback as tb tb.print_exc() sys.exit(1) # load secrets if arg_info['args'].has_key('secret_fd'): fd_str = arg_info['args']['secret_fd'] if fd_str: try: fd = int(fd_str) except: print('Invalid secret fd {}'.format(fd_str), file=sys.stderr) sys.exit(1) log.debug("Load secrets from {}".format(fd)) try: os.lseek(fd, 0, os.SEEK_SET) secbuf = os.read(fd, 65536) os.close(fd) load_secrets(secbuf) except Exception as e: traceback.print_exc() sys.exit(1) # do one-time opt-in request uuid_path = client_uuid_path(config_dir=os.path.dirname(config_path)) first_time = False client_uuid = None if not os.path.exists(uuid_path): first_time = True client_uuid = get_or_set_uuid(config_dir=os.path.dirname(config_path)) if os.environ.get('BLOCKSTACK_CLIENT_INTERACTIVE_YES') != '1': # interactive allowed # prompt for email print("Would you like to receive an email when there is a new release of this software available?") email_addr = raw_input("Email address (leave blank to opt out): ") # will only process real email addresses when we email announcements out if len(email_addr) > 0: analytics_user_register( client_uuid, email_addr ) res = config.setup_config(config_path=config_path, interactive=(os.environ.get("BLOCKSTACK_CLIENT_INTERACTIVE_YES") != '1')) if 'error' in res: exit_with_error("Failed to load and verify config file: {}".format(res['error'])) conf = res['config'] # if the wallet exists, make sure that it's the latest version wallet_path = os.path.join(os.path.dirname(config_path), WALLET_FILENAME) if os.path.exists(wallet_path): res = inspect_wallet(wallet_path=wallet_path) if 'error' in res: exit_with_error("Failed to inspect wallet at {}".format(wallet_path)) if res['migrate'] or res['format'] != 'current': if len(sys.argv) <= 1 or sys.argv[1] != 'setup_wallet': exit_with_error("Wallet is in legacy format. Please unlock and migrate it with `blockstack setup_wallet`.") parser = BlockstackArgumentParser( description='Blockstack cli version {}'.format(config.VERSION) ) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods all_method_names = get_cli_methods() all_methods = parse_methods(all_method_names) build_method_subparsers(subparsers, all_methods) # Print default help message, if no argument is given if len(argv) == 1 or '-h' in argv or '--help' in argv: parser.print_help() sys.exit(0) interactive, args, directive = False, None, None try: # capture stderr so we don't repeat ourselves args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = BlockstackArgumentParser( description='Blockstack cli version {}'.format(config.VERSION) ) directive_subparsers = directive_parser.add_subparsers( dest='action' ) # only parse the directive build_method_subparsers( directive_subparsers, all_methods, include_args=False, include_opts=False ) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:] ) # want interactive prompting interactive, directive = True, directive_args.action except SystemExit: # still invalid return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server, blockstack_port = conf['blockstack-client']['server'], conf['blockstack-client']['port'] # initialize blockstack connection session( server_host=blockstack_server, server_port=blockstack_port, set_global=True ) prompt_func = lambda help, name: raw_input('optional: {} ("{}"): '.format(help, name)) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] pragmas = method_info['pragmas'] # interactive? if interactive: arg_names = [mi['name'] for mi in method_info['args']] opt_names = [mi['name'] for mi in method_info['opts']] arg_usage = ' '.join(arg_names) opt_usage = ' '.join( ['[{}]'.format(opt) for opt in opt_names] ) print('') print('Interactive prompt engaged. Press Ctrl+C to quit') print('Help for "{}": {}'.format(method_info['command'], method_info['help'])) print('Arguments: {} {}'.format(method_info['command'], arg_usage, opt_usage)) print('') required_args = prompt_args(method_info['args'], prompt_func) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args(method_info['opts'], prompt_func) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command']] + required_args + optional_args try: args, unknown_args = parser.parse_known_args(args=full_args) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method(args, config_path=config_path) return {'status': True, 'result': result, 'pragmas': pragmas} # not found return {'error': 'No such command "{}"'.format(args.action)}
def run_cli(argv=None, config_path=CONFIG_PATH): """ Run a CLI command from arguments (defaults to sys.argv) Return the result of the command on success. The result will be a dict, and will have 'error' defined on error condition. """ if argv is None: argv = sys.argv cli_debug = False cli_config_argv = False cli_default_yes = False cli_api_pass = None cli_dry_run = False if '-v' in argv or '--version' in argv: print(VERSION) sys.exit(0) # debug? new_argv, cli_debug = find_arg(argv, False, '-d', '--debug') if new_argv is None: # invalid sys.exit(1) if cli_debug: os.environ['BLOCKSTACK_DEBUG'] = '1' log.setLevel(logging.DEBUG) log.debug("Activated debugging") # alternative config path? new_argv, cli_config_path = find_arg(argv, True, '-c', '--config') if new_argv is None: # invalid sys.exit(1) argv = new_argv if cli_config_path: cli_config_argv = True config_path = cli_config_path log.debug('Use config file {}'.format(config_path)) os.environ['BLOCKSTACK_CLIENT_CONFIG'] = config_path # CLI-given password? new_argv, cli_password = find_arg(argv, True, '-p', '--password') if new_argv is None: # invalid sys.exit(1) argv = new_argv if cli_password and os.environ.get( 'BLOCKSTACK_CLIENT_WALLET_PASSWORD') is None: log.debug("Use CLI password") os.environ["BLOCKSTACK_CLIENT_WALLET_PASSWORD"] = cli_password # assume YES to all prompts? new_argv, cli_default_yes = find_arg(argv, False, '-y', '--yes') if new_argv is None: # invalid sys.exit(1) if cli_default_yes or os.environ.get( "BLOCKSTACK_CLIENT_INTERACTIVE_YES") == "1": if cli_debug: print("Assume YES to all interactive prompts", file=sys.stderr) os.environ["BLOCKSTACK_CLIENT_INTERACTIVE_YES"] = '1' # API password? new_argv, cli_api_pass = find_arg(argv, True, '-a', '--api_password') if new_argv is None: # invalid sys.exit(1) argv = new_argv if cli_api_pass: os.environ['BLOCKSTACK_API_PASSWORD'] = cli_api_pass # dry-run? new_argv, cli_dry_run = find_arg(argv, False, '-n', '--dry-run') if new_argv is None: # invalid sys.exit(1) if cli_dry_run or os.environ.get("BLOCKSTACK_DRY_RUN") == "1": if cli_debug: print('Dry-run; no transactions will be sent', file=sys.stderr) os.environ['BLOCKSTACK_DRY_RUN'] = "1" if cli_config_argv or cli_debug or cli_dry_run: # re-exec to reset variables if cli_debug: print("Re-exec {} with {}".format(argv[0], argv), file=sys.stderr) os.execv(argv[0], argv) # do one-time opt-in request uuid_path = client_uuid_path(config_dir=os.path.dirname(config_path)) first_time = False client_uuid = None if not os.path.exists(uuid_path): first_time = True client_uuid = get_or_set_uuid(config_dir=os.path.dirname(config_path)) if os.environ.get('BLOCKSTACK_CLIENT_INTERACTIVE_YES') != '1': # interactive allowed # prompt for email print( "Would you like to receive an email when there is a new release of this software available?" ) email_addr = raw_input("Email address (leave blank to opt out): ") # will only process real email addresses when we email announcements out if len(email_addr) > 0: analytics_user_register(client_uuid, email_addr) conf = config.get_config( path=config_path, interactive=(os.environ.get('BLOCKSTACK_CLIENT_INTERACTIVE_YES') != '1')) if conf is None: return {'error': 'Failed to load config'} conf_version = conf.get('client_version', '') if not semver_match(conf_version, VERSION): # back up the config file if not cli_config_argv: # default config file backup_path = config.backup_config_file(config_path=config_path) if not backup_path: exit_with_error( "Failed to back up legacy configuration file {}".format( config_path)) else: exit_with_error( "Backed up legacy configuration file from {} to {} and re-generated a new, default configuration. Please restart." .format(config_path, backup_path)) advanced_mode = conf.get('advanced_mode', False) parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) all_methods = [] subparsers = parser.add_subparsers(dest='action') # add basic methods all_method_names = get_cli_methods() all_methods = parse_methods(all_method_names) build_method_subparsers(subparsers, all_methods) if not advanced_mode: # remove advanced methods all_methods = filter(lambda m: 'advanced' not in m['pragmas'], all_methods) # Print default help message, if no argument is given if len(argv) == 1 or '-h' in argv or '--help' in argv: parser.print_help() sys.exit(0) interactive, args, directive = False, None, None try: args, unknown_args = parser.parse_known_args(args=argv[1:]) directive = args.action except SystemExit: # bad arguments # special case: if the method is specified, but no method arguments are given, # then switch to prompting the user for individual arguments. try: directive_parser = argparse.ArgumentParser( description='Blockstack cli version {}'.format(config.VERSION)) directive_subparsers = directive_parser.add_subparsers( dest='action') # only parse the directive build_method_subparsers(directive_subparsers, all_methods, include_args=False, include_opts=False) directive_args, directive_unknown_args = directive_parser.parse_known_args( args=argv[1:]) # want interactive prompting interactive, directive = True, directive_args.action except SystemExit: # still invalid parser.print_help() return {'error': 'Invalid arguments. Try passing "-h".'} result = {} blockstack_server, blockstack_port = conf['server'], conf['port'] # initialize blockstack connection session(conf=conf, server_host=blockstack_server, server_port=blockstack_port, set_global=True) prompt_func = lambda help, name: raw_input('optional: {} ("{}"): '.format( help, name)) # dispatch to the apporpriate method for method_info in all_methods: if directive != method_info['command']: continue method = method_info['method'] pragmas = method_info['pragmas'] # interactive? if interactive: print('') print('Interactive prompt engaged. Press Ctrl+C to quit') print('Help for "{}": {}'.format(method_info['command'], method_info['help'])) print('') required_args = prompt_args(method_info['args'], prompt_func) if required_args is None: return {'error': 'Failed to prompt for arguments'} optional_args = prompt_args(method_info['opts'], prompt_func) if optional_args is None: return {'error': 'Failed to prompt for arguments'} full_args = [method_info['command'] ] + required_args + optional_args try: args, unknown_args = parser.parse_known_args(args=full_args) except SystemExit: # invalid arguments return {'error': 'Invalid arguments. Please try again.'} result = method(args, config_path=config_path) return {'status': True, 'result': result, 'pragmas': pragmas} # not found return {'error': 'No such command "{}"'.format(args.action)}