[getopt-sig] option-class
A.T. Hofkamp
a.t.hofkamp@tue.nl
Thu, 21 Feb 2002 14:56:16 +0100 (CET)
Hello all,
Seeing all the positive reactions to Optik, I got curious how it compared to
'my' module 'argtools' (http://se.wtb.tue.nl/~hat/argtools).
Therefore, I took the example from the Optik page, and re-implemented it in
argtools.
Obviously, I am a bit biased to my own argtools package. However, please bear
with me. The real important part of this mail starts around point 4 and 5 when
I start discussing options and option classes.
The Optik example (from its hoem page):
-------------------------
from Optik import *
parser = OptionParser()
parser.add_option("-f", "--file",
action="store", type="string", dest="filename",
help="write report to FILE", metavar="FILE")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=1,
help="don't print status messages to stdout")
(options, args) = parser.parse_args()
-------------------------
Since I have Python 1.5.2, I cannot run this example.
The argtools re-implementation:
-------------------------
from argtools import *
parser = OptionParser()
file = parser.AddOption(StringOption("f file"))
verbose = parser.AddOption( VoidOption("q quiet"))
parser.ProcessCommandLine()
args = parser.ArgList()
-------------------------
the results can be queried with
print "Results:"
print "File option: value="+file.Value()
print "Quiet option: used="+str(verbose.Used())
When comparing both pieces of code, I notice the following:
1) I can run the argtools example.
One can argue that Python 2.0 is now minimal, but it is not standard
everywhere. For example, my Python version came standard with Red Hat 7.1, a
quite recent Linux distribution.
We are also still using Red Hat 6.2 here, so world-wide there is still a
large userbase with older versions of Python.
Especially for less experienced users, requiring that the latest version
must be installed just for an option processing package is a big requirement.
(especially for a STANDARD PACKAGE).
2) Optik code looks bulkier.
If I have more "-q"-like options, there is a lot redundancy, which leads to
the usual maintenance and consistency problems.
Part of the bulkiness originates from having to specify a helptext (argtools
currently does not support help as part of the option), but if you remove
that, like below
-------------------------
from Optik import *
parser = OptionParser()
parser.add_option("-f", "--file",
action="store", type="string", dest="filename")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose", default=1)
(options, args) = parser.parse_args()
-------------------------
it is still not pretty.
There are exactly 80 chars on the -q line, exclusive the whitespace at the
front, so having a single line for a single option inside a function or
class is difficult at least.
3) Optik has at most 1 short and 1 long name for an option.
This covers most uses. On the other hand, what if I have 3 names for a
single option (or 2 long or short names). Some times, we don't have a choice
in which or how many names should be supported.
In argtools, I solved this by having a single string for all option names
(with a short option being a single letter, and a long option being more
than 1 letter).
4) Optik puts all results in 'options'. Argtools stores the results in the
option itself.
I think this is an important difference. Optik enforces the option
processing results to a single place. In argtools, this can be decided by
the programmer.
I use as convention to derive a new class from the OptionParser, and store
the options inside that class, but different solutions can be chosen too.
For example, if options come from different parts, there may be no desire to
have a central point where all results of all options are available.
(What if 2 options use the same 'dest' ?!? (especially, if you have no
control over those names)).
5) Extending Optik to new types of options is done by deriving a new option, a
new parser, or by using callback functions.
Argtools allows extensions with new types of options by deriving a new
option class.
I think that in a widely used standard Python package, the concept
'callback' should not be used, and possibly, it should not even be available,
as it defies all forms of good programming.
Especially, in an object-oriented framework, deriving a new class is _THE_
only way to go in my opinion. Anything else may be possible, but not for the
normal user.
Optik differentiates between adding a new type of option-argument (e.g. a
boolean argument), and a new action that should take place. In the former
case, a new option should be derived, in the latter case, a new parser
should be derived.
Also, I need to copy variables, make the right modifications in various
places, etc. To me, extending Optik doesn't feel simple and logical.
I don't see the logic behind the changes, other than the fact that the
parser seems to be doing stuff it shouldn't do.
Argtools on the other hand allows all extensions w.r.t. option-types or
option processing of arguments to be done inside a (derived) option class.
By limiting all changes to a single class, extending seems to be much easier.
Being the author of argtools, I am biased towards the good features of
argtools. However, I feel that the concept 'option' (or rather 'option-type')
as a seperate concept in the API has a lot of positive impact.
It makes the object-oriented nature of the framework more tangible, more explicit.
An option knows everything about itself. It knows its names, whether or not it
should take arguments, the syntax of those arguments, and what to do with the
argument, once it is encountered. For example, making an option that takes a
prime number is quite easy. Take the NumberOption, and derive an option with a
check that the number is a prime. Building an option that takes a complex
number is as simple as taking the ValueOption class, and adding a check whether
the argument is a proper complex number. Implementing an option that does
something different than storing the value is also done by deriving a new
option class.
With options knowing everything about themselves, the parser job is limited
to just parsing the command line, and offering the options to the list of
option objects, an extremely well-defined job.
All in all, the 'option' class concept that exists in argtools seems to make it
an extremely robust, extendible, and clean toolkit.
I hope I didn't offend people with my plugging of argtools, at least it was not
my intention.
My goal is not to push argtools as _THE_ solution. Instead, I hope to have
shown that adding the 'option class' concept in the final option processing
module which we are designing seems to make a lot of extensions fairly natural.
Therefore, the concept should be carefully considered for inclusion.
Albert
--
Constructing a computer program is like writing a painting