I'm currently working on a command-line "database migration" utility. Here are some of the requirements regarding reading the command-line arguments part:
It should accept regular database connection parameters: host, database name, port, user and password (do not allow to specify password as a command-line argument, ask for password separately)
It works in two modes - "validate" and "apply" - one of them has to be specified explicitly, both cannot be specified
There should be an integer "batch size" argument specified
There can be an optional range of integer ids specified via --id-begin and --id-end (the beginning of the range defaults to 1 if not specified)
Instead of a range, there can also be a --name argument specified
Both name and id range cannot be present
There should be a "verbose" flag
My Solution
Here is what I came up with:
I'm using argparse module and extracted the parsing command-line arguments into a separate .parse_args() function which returns the parsed arguments (which is argparse.Namespace instance):
The Questions
The code works and I've even covered it with tests (put them into a gist). But, I don't particularly like the way I check the requirements for name and id ranges, mutually exclusive "apply" and "validate" modes. It feels like I could have used more argparse specific features like custom types or actions. What do you think?
I would also appreciate other ideas about handling the password - using getpass() helps to not have the password shown on the terminal explicitly, but requires mocking it in tests.