Exemple #1
0
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_
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
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_
Exemple #7
0
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
Exemple #8
0
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