Ideas for a module to process command line arguments

A

Alice Bevan–McGregor

Hey, every body has their own favorite method/ways to process command
line arguments. I've worked on a little CPython extension to handle
command line arguments may be you'll find it interesting and useful....

Even I've implemented my own way to handle command-line scripts, marrow.script:

https://github.com/pulp/marrow.script

The idea with mine that you write a Python function... and that's it.
The latest version has experimental support for class-based
"subcommand" dispatch, but it needs work, needs to be updated to
support sub-sub commands, and the help text generator needs to be
overhauled to support classes properly.

The argument list, typecasting, etc. is built from the argspec. Help
text is pulled from the docstring. Decorators are provided to override
short names, define explicit callbacks or typecasting functions, etc.

I got tired of using PasteScript and OptParse. Mostly OptParse, actually. :/

- Alice.
 
A

Alice Bevan–McGregor

It's a pity that the argument parsing modules in the standard library
are so verbose that everybody is reinventing the same thing :-( It
looks like you have reinvented plac: http://pypi.python.org/pypi/plac

And a package called `commandline`. There are many command line
parsing modules, many of which are unmaintained, few have reached 1.0.

My criteria for 1.0? 100% unit test coverage, complete documentation,
compatibility with 2.6+ and 3.1+ within a single package.
marrow.script meets that criteria, do the others? :)

- Alice.
 
A

Alice Bevan–McGregor

It's a pity that the argument parsing modules in the standard library
are so verbose that everybody is reinventing the same thing :-( It
looks like you have reinvented plac: http://pypi.python.org/pypi/plac

After looking into it, Plac's default help display isn't very helpful;
you need to massage your application a fair amount before generating
nice, complete-looking argument lists and such. For example:

def main(verbose: ('prints more info', 'flag', 'v'), dsn: 'connection
string'):

@annotate(dsn="connection string", verbose="prints more info")
def main(dsn, verbose=False):

The latter is marrow.script, and even without the annotation a more
complete help text is generated. The -v and flag nature are assumed
from the first unique character and default value. (Flags, when
present on the command line, invert the default value.) Py3k
annotations haven't been implemented yet, though.

Also included is an easy way to simulte command-line execution (i.e. by
reading arguments passed by hand and by returning the exit code, vs.
reading sys.argv and calling sys.exit()) for unit testing purposes.
Plac appears (from the documentation) to be written on top of argparse.
:(

- Alice.
 
M

Michele Simionato

... not available to python 2.5 / 2.6 users :)

JM

In that case easy_install/pip/whatever will install the dependency
automatically (who is installing
dependencies by hand nowadays?). More seriously I thought being based
on a solid module which is
also part of the standard library (for Python 2.7+) was an asset of
plac.
 
M

Mike

In that case easy_install/pip/whatever will install the dependency
automatically (who is installing
dependencies by hand nowadays?). More seriously I thought being based

I do. Is this bad? :}
 
M

Michele Simionato

After looking into it, Plac's default help display isn't very helpful;
you need to massage your application a fair amount before generating
nice, complete-looking argument lists and such.  For example:

        def main(verbose: ('prints more info', 'flag', 'v'), dsn: 'connection
string'):

        @annotate(dsn="connection string", verbose="prints more info")
        def main(dsn, verbose=False):

The latter is marrow.script, and even without the annotation a more
complete help text is generated.  The -v and flag nature are assumed
from the first unique character and default value.  (Flags, when
present on the command line, invert the default value.)

Honestly I do not see any significant difference both in the
level of verbosity for the annotations and in the quality of the help
message provided in the absence of annotations. Originally plac too
was able to recognize flags automatically by looking at the default
value (if the default value is a boolean then the option is a flag);
however I removed that functionality because I wanted to be able to
differentiate between flag and (smart) options (see
http://micheles.googlecode.com/hg/plac/doc/plac.html#scripts-with-options-and-smart-options).
 
A

Alice Bevan–McGregor

Originally plac too was able to recognize flags automatically by
looking at the default value (if the default value is a boolean then
the option is a flag); however I removed that functionality because I
wanted to be able to differentiate between flag and (smart) options
(see
http://micheles.googlecode.com/hg/plac/doc/plac.html#scripts-with-options-and-smart-options).

Not entirely sure what you mean by 'smart' options. If your'e referring to
using a single hyphen and a list of characters to represent a long
option (which, to the rest of the world, use two leading hyphens) then
that's pretty weird. ;)

Consider most of the GNU tools:

ls -lvh
tar -xzvf file.tgz (goes so far as to make the leading hyphen optional!)
less -ceF logfile
bc -qw
ps -aux (same as tar)

And even third-party tools:

mysql -fH
pg_dump -abO ...

One major system in the world that doesn't really differentiate between
long and short options is... DOS, and by extension, Windows. But they
also use / as a switch character.

Anyway; I'm happy with what I have wrought (and am continuing to update
with support for class-based sub-command dispatch) and will be
utilizing it for all scripts in the Marrow suite. To each their own,
but reinvention itself can be for motivations other than NIH. I wanted
something pure-Python, portable across the 3k barrier without code
modification (no 2to3), that didn't use optparse, getopt, or argparse
and basically be a translation layer. It can be simpler than that, as
marrow.script demonstrates.

- Alice.
 
M

Michele Simionato

entirely sure what you mean by 'smart' options.  If your'e referring to
using a single hyphen and a list of characters to represent a long
option (which, to the rest of the world, use two leading hyphens) then
that's pretty weird.  ;)

One major system in the world that doesn't really differentiate between
long and short options is... DOS, and by extension, Windows.  But they
also use / as a switch character.

Yes, and plac (it is argparse actually) can accomodate
the Windows convention by setting the prefix_chars to "/". I wanted to
be
able to give that freedom even if personally am more used to the GNU
double-dash
convention.
Anyway; I'm happy with what I have wrought (and am continuing to update
with support for class-based sub-command dispatch) and will be
utilizing it for all scripts in the Marrow suite.  To each their own,
but reinvention itself can be for motivations other than NIH.  I wanted
something pure-Python, portable across the 3k barrier without code
modification (no 2to3), that didn't use optparse, getopt, or argparse
and basically be a translation layer.  It can be simpler than that, as
marrow.script demonstrates.

No arguing against that. BTW, I was not criticizing marrow.script, I
was simply
deploring the situation in the standard library. If the same approach
for parsing
command-line options is being reinvented by different people multiple
times there
must be something wrong with the current standard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,190
Latest member
ClayE7480

Latest Threads

Top