[getopt-sig] mapping cmdline-interface to python function
holger@trillke.net
holger@trillke.net
Tue, 9 Apr 2002 14:11:44 +0200
Hello,
Please bear with me as this is my first time i make a proposal to
a python-sig. i am not new at enjoying and programming
python, though :-)
The basic idea is to map the commandline interface into
a python class resp. a function. This can be done
via code inspection supporting both the programmer
to easily specify (in a pythonic way) options/arguments/documentation
and the user to get nice output of false usage.
Basically you can write a function and let
a special module ('main') do all the laborious
work for looking at sys.args
I start with a sample program that uses the proposed
functionality. it's a program that takes at least
one filename, requires a "--id" or "-i" option together with
a decimal value. it also accepts more than one filename.
import main # this contains the code to map
# cmdline-interface to classes
# makes heavy intelligent use of
# code inspection
exec main.map_command_line_to('program') # classname as string
class program:
version="0.1"
authors="Holger Krekel <holger@trillke.net>"
download="http://www.trillke.net/~hpk/program/"
help = """ longish tutorial with examples ...."
def run(self,
quiet =('q',None,0), # quiet operation
verbose=('v',None,0), # print verbose information
id=('i','%d',1), # specficies the id to use
filein='%s', # the file to be read
*morefiles):
""" This program demonstrates the use of the main
commandline interface mapper.
it allows you to express without redundance
the options, documentation and types of options
and parameters for you function in one place
and it is a natural place :-)"""
OK. This is a complete specification of parsing and gettings
the cmdline-args. Let me explain the the lines
of the example:
- the names of the variables are longoptions.
quiet =('q',None,0), # quiet operation
- if variables have a tuple as a default value, then
this is a specification with the following meaning:
optionaliases,argumentspec, required = (...)
- optionalias is a string or a tuple of strings to specify
alias option names
- argumentspec specifies in string notation what is expected
(could of course contain more than one '%d %s')
- required indicates if this option is required
- an optional fourth element could contain a (typed!) default value
- if variables have a string as a default value, then
this is a (non-option) argument and you can specify
if it should be a decimal/string ...
filein='%s', # the file to be read
*morefiles):
- additional args are in morefiles
- the documentation behind the variables is the
documentation for this option! So if you
give an id that is not a decimal value, you would
get a type-error which cites the documentation
and urges the user to use a decimal value. This
happens automatically.
id=('i','%d',1), # id to look for in the files
- usage is in the __doc__ string of the function
""" This program demonstrates the use of the main
commandline interface mapper...."""
- non '__.*' class attributes are long options for informational use
by the user. so
"program --version" prints 0.1
"program --download" prints http://www.trillke.net/~hpk/program
"program --authors" prints
"program --help" prints a longish help (not just usage which)
this posting is already long enough, so i am not going into
details of my plan for implementation. But please note several
things:
- the program will just get all correct options and args
or None if it wasn't specified (and not required).
the main module educates the user about intended usage
and your program can just work with the preprocessed given objects
just as it would if have been called directly in python!
if you say "program --id 17 /etc/passwd /etc/groups"
your program.run function will have the following vars
in locals()
quiet = None
verbose= None
id=17
filein='/etc/passwd'
morefiles=('/etc/groups')
- documentation for options and program is right where
the program is.
- we can easily provide hooks in the class to check for
correct combinations of arguments, special forbidden
usages and so on.
- Please note, that we could improve this design so that
other python modules could easily use this program without making
up an intermediate commandline-representation. they would call
another function of the class "program" which raises a precise
exception if you give wrong parameters. But it would feel as
a ordinary python function... This idea really guides the
whole design.
Basically it makes writing standard commandline interfaces with *rich*
functionality for the user a snap. Maybe it could even use optik or
other libs as a backend.
What do you think? I would really like to work with some people
on improving the design before going to code it.
holger