Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python ArgumentParser nested arguments

I want to create argument parser with following signature:

./myapp [-a [-b BVAL] | -c]

In other words, user could provide argument -b BVAL only in case if he provided argument -a.

It's quite easy to create mutually exclusive group of -a and -c, but I can't figure out how to create relationship allow -b only if -a provided

like image 711
kovpas Avatar asked Dec 21 '22 12:12

kovpas


1 Answers

You could inherit from ArgumentParser to add some custom functionality. Here I am raising an exception, but you could modify this to implement whatever you would like. Just change the on_dependency_error() method to suit your needs.

from argparse import ArgumentParser

class FancyParser(ArgumentParser):
    # {'b': 'a'} Where b depends on a
    dependencies = {}

    def on_dependency_error(self, arg, depends_on):
        raise FancyParser.DependencyError(
                    'Argument %s depends on %s' % (arg, depends_on))

    def add_argument(self, *args, **kwargs):
        depends_on = kwargs.get('depends_on')
        if depends_on:
            self.dependencies[kwargs.get('dest') or args[0]] = depends_on
            del kwargs['depends_on']
        return super(FancyParser, self).add_argument(*args, **kwargs)

    def parse_args(self, *args, **kwargs):
        args = super(FancyParser, self).parse_args(*args, **kwargs)
        for arg, depends_on in self.dependencies.iteritems():
            if getattr(args, arg) and not getattr(args, depends_on):
                self.on_dependency_error(arg, depends_on)
        return args

    class DependencyError(Exception):
        def __init__(self, *args, **kwargs):
            return super(FancyParser.DependencyError,
                         self).__init__(*args, **kwargs)

You can then use it like this -

args = ['-a', '-b', 'BVAL', '-c']
parser = FancyParser()
parser.add_argument('-a', dest='a', action='store_true')
parser.add_argument('-b', dest='b', depends_on='a')
parser.add_argument('-c', dest='c', action='store_true')
try:
    parser.parse_args(args)
except FancyParser.DependencyError as e:
    # Whatever here...
    pass
like image 196
pyrospade Avatar answered Jan 05 '23 08:01

pyrospade