def argparse_dict(default_dict_, lbl=None, verbose=None, only_specified=False, force_keys={}, type_hint=None, alias_dict={}): r""" Gets values for a dict based on the command line Args: default_dict_ (?): only_specified (bool): if True only returns keys that are specified on commandline. no defaults. Returns: dict_: dict_ - a dictionary CommandLine: python -m utool.util_arg --test-argparse_dict python -m utool.util_arg --test-argparse_dict --foo=3 python -m utool.util_arg --test-argparse_dict --flag1 python -m utool.util_arg --test-argparse_dict --flag2 python -m utool.util_arg --test-argparse_dict --noflag2 python -m utool.util_arg --test-argparse_dict --thresh=43 python -m utool.util_arg --test-argparse_dict --bins=-10 python -m utool.util_arg --test-argparse_dict --bins=-10 --only-specified --helpx Example: >>> # DISABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> import utool as ut >>> # build test data >>> default_dict_ = { ... 'bins': 8, ... 'foo': None, ... 'flag1': False, ... 'flag2': True, ... 'max': 0.2, ... 'neg': -5, ... 'thresh': -5.333, ... } >>> # execute function >>> only_specified = ut.get_argflag('--only-specified') >>> dict_ = argparse_dict(default_dict_, only_specified=only_specified) >>> # verify results >>> result = ut.dict_str(dict_, sorted_=True) >>> print(result) """ if verbose is None: verbose = VERBOSE_ARGPARSE def make_argstrs(key, prefix_list): for prefix in prefix_list: yield prefix + key yield prefix + key.replace('-', '_') yield prefix + key.replace('_', '-') def get_dictkey_cmdline_val(key, default, type_hint): # see if the user gave a commandline value for this dict key defaulttype_ = None if default is None else type(default) if type_hint is None: type_ = defaulttype_ elif isinstance(type_hint, dict): type_ = type_hint.get(key, defaulttype_) elif isinstance(type_hint, type): type_ = type_hint else: raise NotImplementedError('Unknown type of type_hint=%r' % (type_hint,)) was_specified = False if isinstance(default, bool): val = default if default is True: falsekeys = list(set(make_argstrs(key, ['--no', '--no-']))) notval, was_specified = get_argflag(falsekeys, return_specified=True) val = not notval if not was_specified: truekeys = list(set(make_argstrs(key, ['--']))) val_, was_specified = get_argflag(truekeys, return_specified=True) if was_specified: val = val_ elif default is False: truekeys = list(set(make_argstrs(key, ['--']))) val, was_specified = get_argflag(truekeys, return_specified=True) else: argtup = list(set(make_argstrs(key, ['--']))) #if key == 'species': # import utool as ut # ut.embed() val, was_specified = get_argval(argtup, type_=type_, default=default, return_specified=True) return val, was_specified dict_ = {} num_specified = 0 for key, default in six.iteritems(default_dict_): val, was_specified = get_dictkey_cmdline_val(key, default, type_hint) if not was_specified: alias_keys = meta_util_iter.ensure_iterable(alias_dict.get(key, [])) for alias_key in alias_keys: val, was_specified = get_dictkey_cmdline_val(alias_key, default, type_hint) if was_specified: break if VERBOSE_ARGPARSE: if was_specified: num_specified += 1 print('[argparse_dict] Specified key=%r, val=%r' % (key, val)) #if key == 'foo': # import utool as ut # ut.embed() if not only_specified or was_specified or key in force_keys: dict_[key] = val if VERBOSE_ARGPARSE: print('[argparse_dict] num_specified = %r' % (num_specified,)) print('[argparse_dict] force_keys = %r' % (force_keys,)) #dict_ = {key: get_dictkey_cmdline_val(key, default) for key, default in #six.iteritems(default_dict_)} if verbose: for key in dict_: if dict_[key] != default_dict_[key]: print('[argparse_dict] GOT ARGUMENT: cfgdict[%r] = %r' % (key, dict_[key])) do_helpx = get_argflag('--helpx', help_='Specifies that argparse_dict should print help and quit') if get_argflag(('--help', '--help2')) or do_helpx: import utool as ut print('COMMAND LINE IS ACCEPTING THESE PARAMS WITH DEFAULTS:') if lbl is not None: print(lbl) #print(ut.align(ut.dict_str(dict_, sorted_=True), ':')) print(ut.align(ut.dict_str(default_dict_, sorted_=True), ':')) if do_helpx: sys.exit(1) return dict_
def get_argflag(argstr_, default=False, help_='', return_specified=None, need_prefix=True, return_was_specified=False, argv=None, debug=None, **kwargs): """ Checks if the commandline has a flag or a corresponding noflag Args: argstr_ (str, list, or tuple): the flag to look for default (bool): dont use this (default = False) help_ (str): a help string (default = '') return_specified (bool): returns if flag was specified or not (default = False) Returns: tuple: (parsed_val, was_specified) TODO: depricate return_was_specified CommandLine: python -m utool.util_arg --exec-get_argflag --noface --exec-mode python -m utool.util_arg --exec-get_argflag --foo --exec-mode python -m utool.util_arg --exec-get_argflag --no-foo --exec-mode python -m utool.util_arg --exec-get_argflag --foo=True --exec-mode python -m utool.util_arg --exec-get_argflag --foo=False --exec-mode Example: >>> # DISABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> argstr_ = '--foo' >>> default = False >>> help_ = '' >>> return_specified = True >>> (parsed_val, was_specified) = get_argflag(argstr_, default, help_, return_specified) >>> result = ('(parsed_val, was_specified) = %s' % (str((parsed_val, was_specified)),)) >>> print(result) """ if argv is None: argv = sys.argv assert isinstance(default, bool), 'default must be boolean' argstr_list = meta_util_iter.ensure_iterable(argstr_) #if VERYVERBOSE: # print('[util_arg] checking argstr_list=%r' % (argstr_list,)) # arg registration _register_arg(argstr_list, bool, default, help_) parsed_val = default was_specified = False if debug is None: debug = DEBUG # Check environment variables for default as well as argv import os #""" #set UTOOL_NOCNN=True #export UTOOL_NOCNN True #""" #argv_orig = argv[:] # HACK: make this not happen very time you loop for key, val in os.environ.items(): key = key.upper() sentinal = 'UTOOL_' if key.startswith(sentinal): flag = '--' + key[len(sentinal):].lower().replace('_', '-') if val.upper() in ['TRUE', 'ON']: pass elif val.upper() in ['FALSE', 'OFF']: continue else: continue #flag += '=False' new_argv = [flag] argv = argv[:] + new_argv if debug: print('ENV SPECIFIED COMMAND LINE') print('argv.extend(new_argv=%r)' % (new_argv,)) for argstr in argstr_list: #if VERYVERBOSE: # print('[util_arg] * checking argstr=%r' % (argstr,)) if not (argstr.find('--') == 0 or (argstr.find('-') == 0 and len(argstr) == 2)): raise AssertionError('Invalid argstr: %r' % (argstr,)) if not need_prefix: noprefix = argstr.replace('--', '') if noprefix in argv: parsed_val = True was_specified = True break #if argstr.find('--no') == 0: #argstr = argstr.replace('--no', '--') noarg = argstr.replace('--', '--no') if argstr in argv: parsed_val = True was_specified = True #if VERYVERBOSE: # print('[util_arg] * ...WAS_SPECIFIED. AND PARSED') break elif noarg in argv: parsed_val = False was_specified = True #if VERYVERBOSE: # print('[util_arg] * ...WAS_SPECIFIED. AND NOT PARSED') break elif argstr + '=True' in argv: parsed_val = True was_specified = True break elif argstr + '=False' in argv: parsed_val = False was_specified = True break if return_specified is None: return_specified = return_was_specified if return_specified: return parsed_val, was_specified else: return parsed_val
def get_argval(argstr_, type_=None, default=None, help_=None, smartcast=True, return_specified=None, argv=None, verbose=None, debug=None, return_was_specified=False): r""" Returns a value of an argument specified on the command line after some flag Args: argstr_ (str or tuple): string or tuple of strings denoting the command line values to parse type_ (None): type of the variable to parse (default = None) default (None): (default = None) help_ (None): help for this argument (not fully integrated) (default = None) smartcast (bool): tries to be smart about casting the parsed strings (default = True) return_specified (bool): (default = False) argv (None): override sys.argv with custom command line vector (default = None) TODO: depricate return_was_specified CommandLine: python -m utool.util_arg --test-get_argval python -m utool.util_arg --exec-get_argval:0 python -m utool.util_arg --exec-get_argval:1 python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest="holy grail" python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest="42" python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest=42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest', float)]])" --quest 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval(('--nAssign'), int)]])" --nAssign 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval(('--test'), str)]])" --test python -c "import utool; print([(type(x), x) for x in [utool.get_argval(('--test'), str)]])" --test "foobar is good" --youbar ok Example: >>> # ENABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> import utool as ut >>> import sys >>> argv = ['--spam', 'eggs', '--quest=holy grail', '--ans=42', '--the-val=1,2,3'] >>> # specify a list of args and kwargs to get_argval >>> argstr_kwargs_list = [ >>> ('--spam', dict(type_=str, default=None, argv=argv)), >>> ('--quest', dict(type_=str, default=None, argv=argv)), >>> (('--ans', '--foo'), dict(type_=int, default=None, argv=argv)), >>> (('--not-there', '--absent'), dict(argv=argv)), >>> ('--the_val', dict(type_=list, argv=argv)), >>> ('--the-val', dict(type_=list, argv=argv)), >>> ] >>> # Execute the command with for each of the test cases >>> res_list = [] >>> argstr_list = ut.get_list_column(argstr_kwargs_list, 0) >>> for argstr_, kwargs in argstr_kwargs_list: >>> res = get_argval(argstr_, **kwargs) >>> res_list.append(res) >>> result = ut.dict_str(ut.odict(zip(argstr_list, res_list))) >>> result = result.replace('u\'', '\'') # hack >>> print(result) { '--spam': 'eggs', '--quest': 'holy grail', ('--ans', '--foo'): 42, ('--not-there', '--absent'): None, '--the_val': [1, 2, 3], '--the-val': [1, 2, 3], } Example: >>> # ENABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> import utool as ut >>> import sys >>> argv = ['--slice1', '::', '--slice2=4:', '--slice3=::4', '--slice4', '[1,2,3,4]', '--slice5=3'] >>> # specify a list of args and kwargs to get_argval >>> argstr_kwargs_list = [ >>> ('--slice1', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ('--slice2', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ('--slice3', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ('--slice4', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ('--slice5', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ] >>> # Execute the command with for each of the test cases >>> res_list = [] >>> argstr_list = ut.get_list_column(argstr_kwargs_list, 0) >>> list1 = [1, 3, 5, 7, 9] >>> import numpy as np >>> list2 = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 1]]) >>> for argstr_, kwargs in argstr_kwargs_list: >>> res = get_argval(argstr_, **kwargs) >>> print('---') >>> print('res = %r' % (res,)) >>> print('list1[%r=%r] = %r' % (argstr_, res, ut.take(list1, res),)) >>> print('list2[%r=%r] = %r' % (argstr_, res, list2[res].tolist(),)) >>> res_list.append(res) >>> result = ut.dict_str(ut.odict(zip(argstr_list, res_list))) >>> result = result.replace('u\'', '\'') # hack >>> print(result) """ if verbose is None: pass # verbose = VERYVERBOSE if debug is None: debug = DEBUG # debug = VERYVERBOSE if argv is None: argv = sys.argv #verbose = 1 if verbose: print('[get_argval] Searching Commandline for argstr_=%r' % (argstr_,)) #print('[get_argval] * type_ = %r' % (type_,)) #print('[get_argval] * default = %r' % (default,)) #print('[get_argval] * help_ = %r' % (help_,)) #print('[get_argval] * smartcast = %r' % (smartcast,)) if return_specified is None: return_specified = return_was_specified #print(argstr_) was_specified = False arg_after = default if type_ is bool: arg_after = False if default is None else default try: # New for loop way (accounts for =) argstr_list = meta_util_iter.ensure_iterable(argstr_) # arg registration _register_arg(argstr_list, type_, default, help_) # expand out hypens EXPAND_HYPENS = True if EXPAND_HYPENS: argstr_list2 = [] seen_ = set([]) for argstr in argstr_list: if argstr not in seen_: argstr_list2.append(argstr) seen_.add(argstr) if argstr.startswith('--'): num = 2 elif argstr.startswith('-'): num = 1 else: continue argstr2_0 = argstr[0:num] + argstr[num:].replace('_', '-') argstr2_1 = argstr[0:num] + argstr[num:].replace('-', '_') if argstr2_0 not in seen_: argstr_list2.append(argstr2_0) seen_.add(argstr2_0) if argstr2_1 not in seen_: argstr_list2.append(argstr2_1) seen_.add(argstr2_1) argstr_list = argstr_list2 # Check environment variables for default as well as argv import os """ set UTOOL_NOCNN=True export UTOOL_NOCNN True """ #argv_orig = argv[:] for key, val in os.environ.items(): key = key.upper() sentinal = 'UTOOL_' if key.startswith(sentinal): key = '--' + key[len(sentinal):].lower() new_argv = [key, val] if val.upper() in ['TRUE', 'FALSE', 'ON', 'OFF']: # handled by argflag continue argv = argv[:] + new_argv if debug: print('argv.extend(new_argv=%r)' % (new_argv,)) for argx, item in enumerate(argv): for argstr in argstr_list: if item == argstr: if type_ is bool: if debug: print('[get_argval] ... argstr=%r' % (argstr,)) print('[get_argval] ... Found bool argx=%r' % (argx,)) arg_after = True was_specified = True break if argx < len(argv): if type_ is list: # HACK FOR LIST. TODO INTEGRATE if debug: print('[get_argval] ... argstr=%r' % (argstr,)) print('[get_argval] ... Found noequal list argx=%r' % (argx,)) arg_after = parse_arglist_hack(argx, argv=argv) if debug: print('[get_argval] ... arg_after=%r' % (arg_after,)) print('argv=%r' % (argv,)) if smartcast: arg_after = list(map(util_type.smart_cast2, arg_after)) if debug: print('[get_argval] ... smartcast arg_after=%r' % (arg_after,)) else: if debug: print('[get_argval] ... argstr=%r' % (argstr,)) print('[get_argval] ... Found type_=%r argx=%r' % (type_, argx,)) if type_ is None: #arg_after = util_type.try_cast(argv[argx + 1], type_) arg_after = util_type.smart_cast2(argv[argx + 1]) else: arg_after = util_type.try_cast(argv[argx + 1], type_) if was_specified: print('WARNING: argstr=%r already specified' % (argstr,)) was_specified = True break elif item.startswith(argstr + '='): val_after = ''.join(item.split('=')[1:]) if type_ is list: # HACK FOR LIST. TODO INTEGRATE if verbose: print('[get_argval] ... Found equal list') #import IPython #IPython.embed() val_after_ = val_after.rstrip(']').lstrip('[') if True: # Hacker way to be less hacky about parsing lists from utool import util_gridsearch blocks = util_gridsearch.parse_nestings(val_after_) sentinal = '##COM&&' changed = [(block[0], block[1].replace(',', sentinal)) if block[0] == 'nonNested' else block for block in blocks] val_after2 = util_gridsearch.recombine_nestings(changed) arg_after = val_after2.split(sentinal) else: arg_after = val_after_.split(',') if smartcast: arg_after = list(map(util_type.smart_cast2, arg_after)) else: if type_ is None: arg_after = util_type.smart_cast2(val_after) else: arg_after = util_type.try_cast(val_after, type_) if not isinstance(type_, six.string_types) and issubclass(type_, six.string_types): if arg_after == 'None': # hack arg_after = None if was_specified: print('WARNING: argstr=%r already specified' % (argstr,)) was_specified = True break except Exception as ex: import utool as ut ut.printex(ex, 'problem in arg_val', keys=['type_']) if ut.SUPER_STRICT: raise pass if verbose: print('[get_argval] ... Parsed arg_after=%r, was_specified=%r' % (arg_after, was_specified)) if return_specified: return arg_after, was_specified else: return arg_after
def get_argval(argstr_, type_=None, default=None, help_=None, smartcast=True, return_was_specified=False): """ Returns a value of an argument specified on the command line after some flag Examples: >>> from utool.util_arg import * # NOQA >>> import sys >>> sys.argv.extend(['--spam', 'eggs', '--quest=holy grail', '--ans=42']) >>> res1 = get_argval('--spam', type_=str, default=None) >>> res2 = get_argval('--quest', type_=str, default=None) >>> res3 = get_argval('--ans', type_=int, default=None) >>> result = ', '.join(map(str, (res1, res2, res3))) >>> print(result) eggs, holy grail, 42 CommandLine: python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest="holy grail" python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest="42" python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest=42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest', float)]])" --quest 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval(('--nAssign'), int)]])" --nAssign 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval(('--test'), str)]])" --test """ #print(argstr_) was_specified = False arg_after = default if type_ is bool: arg_after = False if default is None else default try: # New for loop way (accounts for =) argstr_list = meta_util_iter.ensure_iterable(argstr_) # arg registration _register_arg(argstr_list, type_, default, help_) for argx, item in enumerate(sys.argv): for argstr in argstr_list: if item == argstr: if type_ is bool: arg_after = True was_specified = True break if argx < len(sys.argv): if type_ is list: # HACK FOR LIST. TODO INTEGRATE arg_after = parse_arglist_hack(argx) if smartcast: arg_after = list(map(util_type.smart_cast2, arg_after)) else: if type_ is None: #arg_after = util_type.try_cast(sys.argv[argx + 1], type_) arg_after = util_type.smart_cast2(sys.argv[argx + 1]) else: arg_after = util_type.try_cast(sys.argv[argx + 1], type_) was_specified = True break elif item.startswith(argstr + '='): val_after = ''.join(item.split('=')[1:]) if type_ is list: #import utool as ut #ut.embed() # HACK FOR LIST. TODO INTEGRATE val_after_ = val_after.rstrip(']').lstrip('[') arg_after = val_after_.split(',') if smartcast: arg_after = list(map(util_type.smart_cast2, arg_after)) else: if type_ is None: arg_after = util_type.smart_cast2(val_after) else: arg_after = util_type.try_cast(val_after, type_) was_specified = True break except Exception as ex: import utool as ut ut.printex(ex, 'problem in arg_val') pass if return_was_specified: return arg_after, was_specified else: return arg_after
def get_argflag(argstr_, default=False, help_='', return_was_specified=False, **kwargs): """ Checks if the commandline has a flag or a corresponding noflag Args: argstr_ (str, list, or tuple): the flag to look for default (bool): dont use this (default = False) help_ (str): a help string (default = '') return_was_specified (bool): returns if flag was specified or not (default = False) Returns: tuple: (parsed_val, was_specified) CommandLine: python -m utool.util_arg --exec-get_argflag --noface --exec-mode python -m utool.util_arg --exec-get_argflag --foo --exec-mode python -m utool.util_arg --exec-get_argflag --no-foo --exec-mode python -m utool.util_arg --exec-get_argflag --foo=True --exec-mode python -m utool.util_arg --exec-get_argflag --foo=False --exec-mode Example: >>> # DISABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> argstr_ = '--foo' >>> default = False >>> help_ = '' >>> return_was_specified = True >>> (parsed_val, was_specified) = get_argflag(argstr_, default, help_, return_was_specified) >>> result = ('(parsed_val, was_specified) = %s' % (str((parsed_val, was_specified)),)) >>> print(result) """ assert isinstance(default, bool), 'default must be boolean' argstr_list = meta_util_iter.ensure_iterable(argstr_) #if VERYVERBOSE: # print('[util_arg] checking argstr_list=%r' % (argstr_list,)) # arg registration _register_arg(argstr_list, bool, default, help_) parsed_val = default was_specified = False for argstr in argstr_list: #if VERYVERBOSE: # print('[util_arg] * checking argstr=%r' % (argstr,)) if not (argstr.find('--') == 0 or (argstr.find('-') == 0 and len(argstr) == 2)): raise AssertionError('Invalid argstr: %r' % (argstr,)) #if argstr.find('--no') == 0: #argstr = argstr.replace('--no', '--') noarg = argstr.replace('--', '--no') if argstr in sys.argv: parsed_val = True was_specified = True #if VERYVERBOSE: # print('[util_arg] * ...WAS_SPECIFIED. AND PARSED') break elif noarg in sys.argv: parsed_val = False was_specified = True #if VERYVERBOSE: # print('[util_arg] * ...WAS_SPECIFIED. AND NOT PARSED') break elif argstr + '=True' in sys.argv: parsed_val = True was_specified = True break elif argstr + '=False' in sys.argv: parsed_val = False was_specified = True break if return_was_specified: return parsed_val, was_specified else: return parsed_val
def argparse_dict(default_dict_, lbl=None, verbose=None, only_specified=False, force_keys={}, type_hint=None, alias_dict={}): r""" Gets values for a dict based on the command line Args: default_dict_ (?): only_specified (bool): if True only returns keys that are specified on commandline. no defaults. Returns: dict_: dict_ - a dictionary CommandLine: python -m utool.util_arg --test-argparse_dict python -m utool.util_arg --test-argparse_dict --foo=3 python -m utool.util_arg --test-argparse_dict --flag1 python -m utool.util_arg --test-argparse_dict --flag2 python -m utool.util_arg --test-argparse_dict --noflag2 python -m utool.util_arg --test-argparse_dict --thresh=43 python -m utool.util_arg --test-argparse_dict --bins=-10 python -m utool.util_arg --test-argparse_dict --bins=-10 --only-specified --helpx Example: >>> # DISABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> import utool as ut >>> # build test data >>> default_dict_ = { ... 'bins': 8, ... 'foo': None, ... 'flag1': False, ... 'flag2': True, ... 'max': 0.2, ... 'neg': -5, ... 'thresh': -5.333, ... } >>> # execute function >>> only_specified = ut.get_argflag('--only-specified') >>> dict_ = argparse_dict(default_dict_, only_specified=only_specified) >>> # verify results >>> result = ut.dict_str(dict_, sorted_=True) >>> print(result) """ if verbose is None: verbose = VERBOSE_ARGPARSE def make_argstrs(key, prefix_list): for prefix in prefix_list: yield prefix + key yield prefix + key.replace('-', '_') yield prefix + key.replace('_', '-') def get_dictkey_cmdline_val(key, default, type_hint): # see if the user gave a commandline value for this dict key defaulttype_ = None if default is None else type(default) if type_hint is None: type_ = defaulttype_ elif isinstance(type_hint, dict): type_ = type_hint.get(key, defaulttype_) elif isinstance(type_hint, type): type_ = type_hint else: raise NotImplementedError('Unknown type of type_hint=%r' % (type_hint, )) was_specified = False if isinstance(default, bool): val = default if default is True: falsekeys = list(set(make_argstrs(key, ['--no', '--no-']))) notval, was_specified = get_argflag(falsekeys, return_specified=True) val = not notval if not was_specified: truekeys = list(set(make_argstrs(key, ['--']))) val_, was_specified = get_argflag(truekeys, return_specified=True) if was_specified: val = val_ elif default is False: truekeys = list(set(make_argstrs(key, ['--']))) val, was_specified = get_argflag(truekeys, return_specified=True) else: argtup = list(set(make_argstrs(key, ['--']))) #if key == 'species': # import utool as ut # ut.embed() val, was_specified = get_argval(argtup, type_=type_, default=default, return_specified=True) return val, was_specified dict_ = {} num_specified = 0 for key, default in six.iteritems(default_dict_): val, was_specified = get_dictkey_cmdline_val(key, default, type_hint) if not was_specified: alias_keys = meta_util_iter.ensure_iterable(alias_dict.get( key, [])) for alias_key in alias_keys: val, was_specified = get_dictkey_cmdline_val( alias_key, default, type_hint) if was_specified: break if VERBOSE_ARGPARSE: if was_specified: num_specified += 1 print('[argparse_dict] Specified key=%r, val=%r' % (key, val)) #if key == 'foo': # import utool as ut # ut.embed() if not only_specified or was_specified or key in force_keys: dict_[key] = val if VERBOSE_ARGPARSE: print('[argparse_dict] num_specified = %r' % (num_specified, )) print('[argparse_dict] force_keys = %r' % (force_keys, )) #dict_ = {key: get_dictkey_cmdline_val(key, default) for key, default in #six.iteritems(default_dict_)} if verbose: for key in dict_: if dict_[key] != default_dict_[key]: print('[argparse_dict] GOT ARGUMENT: cfgdict[%r] = %r' % (key, dict_[key])) do_helpx = get_argflag( '--helpx', help_='Specifies that argparse_dict should print help and quit') if get_argflag(('--help', '--help2')) or do_helpx: import utool as ut print('COMMAND LINE IS ACCEPTING THESE PARAMS WITH DEFAULTS:') if lbl is not None: print(lbl) #print(ut.align(ut.dict_str(dict_, sorted_=True), ':')) print(ut.align(ut.dict_str(default_dict_, sorted_=True), ':')) if do_helpx: sys.exit(1) return dict_
def get_argval(argstr_, type_=None, default=None, help_=None, smartcast=True, return_specified=None, argv=None, verbose=None, debug=None, return_was_specified=False): r""" Returns a value of an argument specified on the command line after some flag Args: argstr_ (str or tuple): string or tuple of strings denoting the command line values to parse type_ (None): type of the variable to parse (default = None) default (None): (default = None) help_ (None): help for this argument (not fully integrated) (default = None) smartcast (bool): tries to be smart about casting the parsed strings (default = True) return_specified (bool): (default = False) argv (None): override sys.argv with custom command line vector (default = None) TODO: depricate return_was_specified CommandLine: python -m utool.util_arg --test-get_argval python -m utool.util_arg --exec-get_argval:0 python -m utool.util_arg --exec-get_argval:1 python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest="holy grail" python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest="42" python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest=42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest')]])" --quest 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval('--quest', float)]])" --quest 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval(('--nAssign'), int)]])" --nAssign 42 python -c "import utool; print([(type(x), x) for x in [utool.get_argval(('--test'), str)]])" --test python -c "import utool; print([(type(x), x) for x in [utool.get_argval(('--test'), str)]])" --test "foobar is good" --youbar ok Example: >>> # ENABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> import utool as ut >>> import sys >>> argv = ['--spam', 'eggs', '--quest=holy grail', '--ans=42', '--the-val=1,2,3'] >>> # specify a list of args and kwargs to get_argval >>> argstr_kwargs_list = [ >>> ('--spam', dict(type_=str, default=None, argv=argv)), >>> ('--quest', dict(type_=str, default=None, argv=argv)), >>> (('--ans', '--foo'), dict(type_=int, default=None, argv=argv)), >>> (('--not-there', '--absent'), dict(argv=argv)), >>> ('--the_val', dict(type_=list, argv=argv)), >>> ('--the-val', dict(type_=list, argv=argv)), >>> ] >>> # Execute the command with for each of the test cases >>> res_list = [] >>> argstr_list = ut.get_list_column(argstr_kwargs_list, 0) >>> for argstr_, kwargs in argstr_kwargs_list: >>> res = get_argval(argstr_, **kwargs) >>> res_list.append(res) >>> result = ut.dict_str(ut.odict(zip(argstr_list, res_list))) >>> result = result.replace('u\'', '\'') # hack >>> print(result) { '--spam': 'eggs', '--quest': 'holy grail', ('--ans', '--foo'): 42, ('--not-there', '--absent'): None, '--the_val': [1, 2, 3], '--the-val': [1, 2, 3], } Example: >>> # ENABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> import utool as ut >>> import sys >>> argv = ['--slice1', '::', '--slice2=4:', '--slice3=::4', '--slice4', '[1,2,3,4]', '--slice5=3'] >>> # specify a list of args and kwargs to get_argval >>> argstr_kwargs_list = [ >>> ('--slice1', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ('--slice2', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ('--slice3', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ('--slice4', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ('--slice5', dict(type_='fuzzy_subset', default=None, argv=argv)), >>> ] >>> # Execute the command with for each of the test cases >>> res_list = [] >>> argstr_list = ut.get_list_column(argstr_kwargs_list, 0) >>> list1 = [1, 3, 5, 7, 9] >>> import numpy as np >>> list2 = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 1]]) >>> for argstr_, kwargs in argstr_kwargs_list: >>> res = get_argval(argstr_, **kwargs) >>> print('---') >>> print('res = %r' % (res,)) >>> print('list1[%r=%r] = %r' % (argstr_, res, ut.take(list1, res),)) >>> print('list2[%r=%r] = %r' % (argstr_, res, list2[res].tolist(),)) >>> res_list.append(res) >>> result = ut.dict_str(ut.odict(zip(argstr_list, res_list))) >>> result = result.replace('u\'', '\'') # hack >>> print(result) """ if verbose is None: pass # verbose = VERYVERBOSE if debug is None: debug = DEBUG # debug = VERYVERBOSE if argv is None: argv = sys.argv #verbose = 1 if verbose: print('[get_argval] Searching Commandline for argstr_=%r' % (argstr_, )) #print('[get_argval] * type_ = %r' % (type_,)) #print('[get_argval] * default = %r' % (default,)) #print('[get_argval] * help_ = %r' % (help_,)) #print('[get_argval] * smartcast = %r' % (smartcast,)) if return_specified is None: return_specified = return_was_specified #print(argstr_) was_specified = False arg_after = default if type_ is bool: arg_after = False if default is None else default try: # New for loop way (accounts for =) argstr_list = meta_util_iter.ensure_iterable(argstr_) # arg registration _register_arg(argstr_list, type_, default, help_) # expand out hypens EXPAND_HYPENS = True if EXPAND_HYPENS: argstr_list2 = [] seen_ = set([]) for argstr in argstr_list: if argstr not in seen_: argstr_list2.append(argstr) seen_.add(argstr) if argstr.startswith('--'): num = 2 elif argstr.startswith('-'): num = 1 else: continue argstr2_0 = argstr[0:num] + argstr[num:].replace('_', '-') argstr2_1 = argstr[0:num] + argstr[num:].replace('-', '_') if argstr2_0 not in seen_: argstr_list2.append(argstr2_0) seen_.add(argstr2_0) if argstr2_1 not in seen_: argstr_list2.append(argstr2_1) seen_.add(argstr2_1) argstr_list = argstr_list2 # Check environment variables for default as well as argv import os """ set UTOOL_NOCNN=True export UTOOL_NOCNN True """ #argv_orig = argv[:] for key, val in os.environ.items(): key = key.upper() sentinal = 'UTOOL_' if key.startswith(sentinal): key = '--' + key[len(sentinal):].lower() new_argv = [key, val] if val.upper() in ['TRUE', 'FALSE', 'ON', 'OFF']: # handled by argflag continue argv = argv[:] + new_argv if debug: print('argv.extend(new_argv=%r)' % (new_argv, )) for argx, item in enumerate(argv): for argstr in argstr_list: if item == argstr: if type_ is bool: if debug: print('[get_argval] ... argstr=%r' % (argstr, )) print('[get_argval] ... Found bool argx=%r' % (argx, )) arg_after = True was_specified = True break if argx < len(argv): if type_ is list: # HACK FOR LIST. TODO INTEGRATE if debug: print('[get_argval] ... argstr=%r' % (argstr, )) print( '[get_argval] ... Found noequal list argx=%r' % (argx, )) arg_after = parse_arglist_hack(argx, argv=argv) if debug: print('[get_argval] ... arg_after=%r' % (arg_after, )) print('argv=%r' % (argv, )) if smartcast: arg_after = list( map(util_type.smart_cast2, arg_after)) if debug: print( '[get_argval] ... smartcast arg_after=%r' % (arg_after, )) else: if debug: print('[get_argval] ... argstr=%r' % (argstr, )) print( '[get_argval] ... Found type_=%r argx=%r' % ( type_, argx, )) if type_ is None: #arg_after = util_type.try_cast(argv[argx + 1], type_) arg_after = util_type.smart_cast2(argv[argx + 1]) else: arg_after = util_type.try_cast( argv[argx + 1], type_) if was_specified: print('WARNING: argstr=%r already specified' % (argstr, )) was_specified = True break elif item.startswith(argstr + '='): val_after = ''.join(item.split('=')[1:]) if type_ is list: # HACK FOR LIST. TODO INTEGRATE if verbose: print('[get_argval] ... Found equal list') #import IPython #IPython.embed() val_after_ = val_after.rstrip(']').lstrip('[') if True: # Hacker way to be less hacky about parsing lists from utool import util_gridsearch blocks = util_gridsearch.parse_nestings(val_after_) sentinal = '##COM&&' changed = [(block[0], block[1].replace(',', sentinal)) if block[0] == 'nonNested' else block for block in blocks] val_after2 = util_gridsearch.recombine_nestings( changed) arg_after = val_after2.split(sentinal) else: arg_after = val_after_.split(',') if smartcast: arg_after = list( map(util_type.smart_cast2, arg_after)) else: if type_ is None: arg_after = util_type.smart_cast2(val_after) else: arg_after = util_type.try_cast(val_after, type_) if not isinstance(type_, six.string_types) and issubclass( type_, six.string_types): if arg_after == 'None': # hack arg_after = None if was_specified: print('WARNING: argstr=%r already specified' % (argstr, )) was_specified = True break except Exception as ex: import utool as ut ut.printex(ex, 'problem in arg_val', keys=['type_']) if ut.SUPER_STRICT: raise pass if verbose: print('[get_argval] ... Parsed arg_after=%r, was_specified=%r' % (arg_after, was_specified)) if return_specified: return arg_after, was_specified else: return arg_after
def get_argflag(argstr_, default=False, help_='', return_specified=None, need_prefix=True, return_was_specified=False, argv=None, debug=None, **kwargs): """ Checks if the commandline has a flag or a corresponding noflag Args: argstr_ (str, list, or tuple): the flag to look for default (bool): dont use this (default = False) help_ (str): a help string (default = '') return_specified (bool): returns if flag was specified or not (default = False) Returns: tuple: (parsed_val, was_specified) TODO: depricate return_was_specified CommandLine: python -m utool.util_arg --exec-get_argflag --noface --exec-mode python -m utool.util_arg --exec-get_argflag --foo --exec-mode python -m utool.util_arg --exec-get_argflag --no-foo --exec-mode python -m utool.util_arg --exec-get_argflag --foo=True --exec-mode python -m utool.util_arg --exec-get_argflag --foo=False --exec-mode Example: >>> # DISABLE_DOCTEST >>> from utool.util_arg import * # NOQA >>> argstr_ = '--foo' >>> default = False >>> help_ = '' >>> return_specified = True >>> (parsed_val, was_specified) = get_argflag(argstr_, default, help_, return_specified) >>> result = ('(parsed_val, was_specified) = %s' % (str((parsed_val, was_specified)),)) >>> print(result) """ if argv is None: argv = sys.argv assert isinstance(default, bool), 'default must be boolean' argstr_list = meta_util_iter.ensure_iterable(argstr_) #if VERYVERBOSE: # print('[util_arg] checking argstr_list=%r' % (argstr_list,)) # arg registration _register_arg(argstr_list, bool, default, help_) parsed_val = default was_specified = False if debug is None: debug = DEBUG # Check environment variables for default as well as argv import os #""" #set UTOOL_NOCNN=True #export UTOOL_NOCNN True #""" #argv_orig = argv[:] # HACK: make this not happen very time you loop for key, val in os.environ.items(): key = key.upper() sentinal = 'UTOOL_' if key.startswith(sentinal): flag = '--' + key[len(sentinal):].lower().replace('_', '-') if val.upper() in ['TRUE', 'ON']: pass elif val.upper() in ['FALSE', 'OFF']: continue else: continue #flag += '=False' new_argv = [flag] argv = argv[:] + new_argv if debug: print('ENV SPECIFIED COMMAND LINE') print('argv.extend(new_argv=%r)' % (new_argv, )) for argstr in argstr_list: #if VERYVERBOSE: # print('[util_arg] * checking argstr=%r' % (argstr,)) if not (argstr.find('--') == 0 or (argstr.find('-') == 0 and len(argstr) == 2)): raise AssertionError('Invalid argstr: %r' % (argstr, )) if not need_prefix: noprefix = argstr.replace('--', '') if noprefix in argv: parsed_val = True was_specified = True break #if argstr.find('--no') == 0: #argstr = argstr.replace('--no', '--') noarg = argstr.replace('--', '--no') if argstr in argv: parsed_val = True was_specified = True #if VERYVERBOSE: # print('[util_arg] * ...WAS_SPECIFIED. AND PARSED') break elif noarg in argv: parsed_val = False was_specified = True #if VERYVERBOSE: # print('[util_arg] * ...WAS_SPECIFIED. AND NOT PARSED') break elif argstr + '=True' in argv: parsed_val = True was_specified = True break elif argstr + '=False' in argv: parsed_val = False was_specified = True break if return_specified is None: return_specified = return_was_specified if return_specified: return parsed_val, was_specified else: return parsed_val