2017-03-14

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.

Show more