0

For my toy project mpu I want to have the following commands:

# Creates a Python project based on a template
$ mpu init

# Checks a Python project for style 
$ mpu stylecheck

So let's say I have a command run_init() and a command run_stylecheck() and an argparse.ArgumentParser object called parser:

def run_init():
    print('init is executed')

def run_stylecheck():
    print('stylecheck is executed')

def get_parser(parser=None):
    """Get parser for packaging part."""
    from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
    if parser is None:
        parser = ArgumentParser(description=__doc__,
                                formatter_class=ArgumentDefaultsHelpFormatter)
    subparsers = parser.add_subparsers(dest='subparser_name')
    pkg_init_parser = subparsers.add_parser('init')
    return parser

get_parser().parse_args()

How can I add those two commands to it?

Restrictions

Please no solutions that suggest to parse sys.argv manually and also not click. The first is not an option as it is too hard to extend, the second one is not an option as I specifically don't want to use external dependencies - although click is awesome.

https://stackoverflow.com/a/27529806/562769 I think is also not an option as this will be a lot of different commands and the submodule providing the parser object will not be calling that object.

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
  • As an addition to that answer, for your “init” parser, call `.set_defaults(func=run_init)` and then afterwards you can just call `args.func(args)`. – Dietrich Epp Sep 03 '18 at 18:44
  • Hm. I have a cascade of parsers and for this to work I would need to do it in the main parser. I really don't like this as I'm unsure of side-effects. It should not be necessary to change the main parser object to make the "leaf parser" work. – Martin Thoma Sep 03 '18 at 18:49
  • What's your problem? You can add `stylecheck` just like you added `init`. `args.subparser_name` will then be the name you gave. Then map that on to functions with a dictionary, or use the `set_defaults` trick. One way or other you have to map a string from the command line onto a function object, and then call that object. This is basic Python. – hpaulj Sep 03 '18 at 20:59
  • @MartinThoma: I am not sure why you say you would need to do this in the main parser. You call `.set_defaults()` on the parser for the subcommand. If you called it on the main parser, you would end up with the same value for `func` for every subcommand. I'm also not sure why you say it would be necessary to change the main parser to make the leaf parser work... could you explain that reasoning? If you are unsure of the side effects, you can refer to the documentation in the argparse module, which is quite thorough and has multiple examples for sub-command parsers. – Dietrich Epp Sep 03 '18 at 21:35
  • If you don't like the linked answers, I'd suggest implementing one or more, and ask a new question, being clear about its deficiency. I like to remind posters that the primary purpose of `argparse` is determine what your user wants. Your own code is responsible for acting on that information. `argparse` can streamline some common patterns. but execution is not its primary design purpose. – hpaulj Sep 04 '18 at 00:30

0 Answers0