neithere / argh

An argparse wrapper that doesn't make you say "argh" each time you deal with it.
http://argh.rtfd.org
GNU Lesser General Public License v3.0
369 stars 56 forks source link

Customisable guess logic #99

Open martinpengellyphillips opened 8 years ago

martinpengellyphillips commented 8 years ago

Would be useful to have an easy way to customise the assembling._guess logic so that it can be changed in one place for a program rather than having to duplicate argh decorators.

For example, would prefer boolean arguments to be treated as explicitly set truthy / falsey values rather than switches. At present have to do the following for each related boolean argument and feel like this could be centralised somehow:

@argh.decorators.arg('--with-some-flag', action='store', type=explicit_bool_type)
def foo(with_some_flag=True):
    ...
neithere commented 8 years ago

Thank you for the idea but I'm not sure I understand what you are trying to achieve. Perhaps you could draft some unit tests so we could see if it's possible to make them pass?

In general, Argh is indeed customizable via arguments to its functions and decorators that set attributes on command functions, but it's not configurable e.g. on app level. I could imagine some wrappers around it that handle configuration, or even some deeper changes, but there should be a clear vision and a set of well-defined use cases.

martinpengellyphillips commented 8 years ago

Sure - will try and work up some unit tests.

In the meantime I'll expand on the example to help clarify requirements:

Given a custom type


def bool_type(string):
    '''Return a boolean value depending on string value'''
    affirmatives = ('y', 'yes', 'true', 'on', '1')
    negatives = ('n', 'no', 'false', 'off', '0')

    if string.lower() in affirmatives:
        return True

    elif string.lower() in negatives:
        return False

    raise argparse.ArgumentTypeError(
        '{0!r} is not a valid boolean value. '
        'Use one of: {1}'.format(string, ', '.join(affirmatives + negatives))
    )

It would be nice to not have to repeatedly reference this custom type everywhere that a bool value might be encounted (especially as that can introduce a lot of bolierplate code):

@argh.decorators.arg(
    '--with-option-a', action='store',
    type=custom_types.bool_type
)
@argh.decorators.arg(
    '--with-option-b', action='store',
    type=custom_types.bool_type
)
@argh.decorators.arg(
    '--with-option-c', action='store',
    type=custom_types.bool_type
)
def foo(with_option_a=True, with_option_b=False, with_option_c=True):
    pass

Looking at https://github.com/neithere/argh/blob/master/argh/assembling.py#L134 it seems the concept for inferring type from argument default value is already present, but private and hard to extend. So this is a request for being able to officially extend the guess logic to deal with type inferrence in a custom way at the app level, with the goal of reducing boilerplate.

neithere commented 1 year ago

It would be interesting to see how this can be combined with #107.

Just to summarise the idea for myself: