0

I have a utility which allows a user to read their ~/.aws/credentials file and export environment variables.

Currently, the CLI interface looks like this:

usage: aws-env [-h] [-n] profile
Extract AWS credentials for a given profile as environment variables.
positional arguments:
 profile The profile in ~/.aws/credentials to extract credentials
 for.
optional arguments:
 -h, --help show this help message and exit
 -n, --no-export Do not use export on the variables.

What I'd like to do here is provide a ls subparser that will allow the user to list the valid profile names in their ~/.aws/credentials.

The interface would be something like this:

$ aws-env ls
profile-1
profile-2

...etcetera. Is there a way that I can natively do this in argparse so that an option appears in my -h output which shows that ls is a valid command?

asked Apr 3, 2017 at 19:36
4
  • Have you actually tried adding a subparser? docs.python.org/3/library/argparse.html#sub-commands Commented Apr 3, 2017 at 19:38
  • I need a single subparser for the ls command and a generic subparser for matching a single profile name which could be anything. Is that possible? Commented Apr 3, 2017 at 19:43
  • I'm not sure I'm following is ls the sub command with the result being the output profile-1\nprofile-2 or you want profile-X to part of the arg parser? If the latter, given you aren't giving an option for the credentials file, just read it and extract the profiles and add them to the parser. Commented Apr 3, 2017 at 20:27
  • @jonsharpe - your SO link basically says, use caution when mixing a positional argument and subparsers. In my experience subparsers work best when all arguments for the main parser are flagged (optionals). Commented Apr 3, 2017 at 22:12

1 Answer 1

2

If you go the subparsers route, you could define two parsers, 'ls' and 'extract'. 'ls' wouldn't have any arguments; 'extract' would take one positional, 'profile'.

subparsers are optional, (Argparse with required subparser), but 'profile', as currently defined, is required.

An alternative is to define two optionals, and omit the positional.

'-ls', True/False, if True to the list
'-e profile', if not None, do the extract.

Or you could leave the positional profile, but make it optional (nargs='?').

Another possibility is to look at the profile value after parsing. If it is a string like 'ls', then list instead of extract. This feels like the cleanest choice, however, the usage will not document this.


parser.add_argument('-l','--ls', action='store_true', help='list')
parser.add_argument('profile', nargs='?', help='The profile')

or

sp = parser.add_subparsers(dest='cmd')
sp.add_parser('ls')
sp1 = sp.add_parser('extract')
sp1.add_argument('profile', help='The profile')

A required mutually exclusive group

gp = parser.add_mutually_exclusive_group(required=True)
gp.add_argument('--ls', action='store_true', help='list')
gp.add_argument('profile', nargs='?', default='adefault', help='The profile')

produces:

usage: aws-env [-h] [-n] (--ls | profile)
answered Apr 3, 2017 at 21:04
Sign up to request clarification or add additional context in comments.

1 Comment

TL;DR It's not really possible, but there are workarounds.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.