I would love to make the 'subcommands' functionality provided in argparse more 
user-friendly.
I think I have a worthwhile feature request to share:
  
  * Be able to add multiple subcommands to an ArgumentParser, without needing 
to track the 'action_object'

I've outlined an motivating example below, and shared an implementation of this 
feature that I've started using in one of my projects.

Thanks!
-Ryan

# Motivating Example

I am working with ArgumentParser subcommands a lot recently, and I've run into 
the interesting implementation detail when it comes to 'adding multiple 
subcommands to a parser': `argparse.ArgumentParser` provides a [special 'action 
object' to manage 
subcommands](https://docs.python.org/3/library/argparse.html#sub-commands).

Lets look at an example of how this works:

First, setup our `root_parser`:

    root_parser = ArgumentParser()

Then, later on, lets add a 'post' subcommand:

    action_object = root_parser.add_subparsers()
    post_parser = action_object.add_subparser("post")

Finally, lets add a 'get' subcommand to the `root_parser`:

    action_object = root_parser.add_subparsers()          <--- Error here!
    get_parser = action_object.add_subparser("get")

This second code block will not work, and will raise an error!

    : error: cannot have multiple subparser arguments

So, it seems these ephemeral 'action objects' are a thorn in my side. 
Specifically, these objects are impeding the following functionality:

* Add multiple subcommands to an ArgumentParser **from multiple scopes**

So, I would like some way for to track the 'action object' alongside 
`root_parser` to enable 'adding subcommands from multiple scopes.'
This can be done by extending `ArgumentParser` to track that 'action object, 
then provide some `add_subcommand(str)` method.
Let's rewrite the example code blocks above assuming we have this new method -- 
we'll use the class name `SubcommandArgumentParser`.

    root_parser = SubcommandArgumentParser()

The Post parser...

    post_parser = root_parser.add_subcommand("post")

The Get parser...

    get_parser = root_parser.add_subcommand("get")

I wonder, am I totally missing some obvious complexity of 
subparsers/subcommands with this suggested feature?
 that this could make working with subcommadns 

# Example Implementation

Here is an implementation of that functionality that I put together for my 
project.

class SubcommandArgumentParser(configargparse.ArgumentParser):
    count = 0

    def __init__(self, *args, **kwargs):
        self.subparser_factory = None
        super().__init__(args, kwargs)

    def _create_subparser_factory(self):
        unique_str = f'action{SubcommandArgumentParser.count}'
        SubcommandArgumentParser.count += 1
        # Create the subparser factory!
        self.subparser_factory = self.add_subparsers(dest=unique_str)
        self.subparser_factory.required = True

    def add_subparser(self, subcommand: str) -> 'SubcommandArgumentParser':
        """Some programs split functionality up into subcommands. Each 
        subcommand has a dedicated `configargparse.ArgumentParser`. 
 
        Arguments:
            subcommand (str): The subcommand to be added to this parser.

        Returns:
            SubcommandArgumentParser: The ArgumentParser that can be 

        Example:
            Given a Subcommand
                parser.add_subparser()
        """
        if self.subparser_factory is None:
            self._create_subparser_factory()
        return self.subparser_factory.add_parser(subcommand)
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/G26ZM6QMITGEQ7NPH4YD4MFYGMCOH2VM/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to