Suggested optparse enhancement

"Allan B. Wilson" <[email protected]> Sat, 3 Jul 2004 14:38:53 -0700
Newsgroups gmane.comp.python.optik.user
Message-ID <[email protected]>
[I have submitted this as a feature request on sourceforge.net, but wanted
to solicit input from list members as well.] 
 
I wanted to add a feature to optparse, which I successfully accomplished by
subclassing add_option. It works fine and meets my needs, but it occurred to
me that perhaps others might find the new capability useful enough to have
it "built in" to the standard version.
 
In a nutshell, I want to be able to write programs that (of course) have
useful default settings. However, I quickly found that it would be helpful
to be able to change defaults in certain situations. For example, I wrote a
utility to access a MySQL database. optparse defaults are set for such items
as the MySQL host system (specifically "localhost"), plus database name,
etc. Frequently I want to run the utility on the system where the database
is (thus, the localhost default). However, I also want to run the utility on
a different system, accessing the database on the first system. Therefore I
explicity need to specify the database host DNS name or IP address rather
than localhost.  (This is a real example: I can't make the database host DNS
name or IP address the default because I have written the utility to be used
by anyone who has a similar database. Thus, "localhost".) 
 
Of course, on Unix/Linux I could just define a shell alias that sets
particular options, but decided it would be more convenient to have optparse
set defaults from a .ini file (if it exists). This way I can create a
different .ini file as appropriate for each system (or situation) and
optparse will set "local" defaults.
 
I have included my .py and a sample .ini file as attachments. Please have a
look and see if the generic feature might be useful for a future version of
optparse. Of course, I would welcome any comments and suggestions to improve
what I have done.
 
Thanks
 
Allan Wilson
IniOptionParser.py (text/plain, 2.8 KB)
#!/usr/bin/python

# IniOptionParser.py -- Class to initialize optparse default options with values specified in a .ini file
#	Copyright (C) 2004 by Allan B. Wilson. All rights reserved.
#	Created: 20-Jun-04; last edit: 22-Jun-04

from optparse import OptionParser

class IniOptionParser(OptionParser):
	" Override OptionParser's 'add_option' method so that 'local' option defaults can be set from a .ini file "

	def __init__(self, *args, **kwargs):
		import os, sys
		progpath = os.path.abspath(os.path.dirname(sys.argv[0]))
		progname = os.path.splitext(os.path.basename(sys.argv[0]))[0]
		configfile = os.path.join(progpath, "%s.ini" % progname)
		if os.path.isfile(configfile):
			import ConfigParser
			self.cp = ConfigParser.ConfigParser()
			cpInput = file(configfile)
			self.cp.readfp(cpInput)
			cpInput.close()
		else:
			self.cp = None
		OptionParser.__init__(self, *args, **kwargs)

	def add_option(self, *args, **kwargs):
		if self.cp and kwargs.has_key("default") and kwargs.has_key("dest") and self.cp.has_option("Defaults", kwargs["dest"]):
			argstring = self.cp.get("Defaults", kwargs["dest"])
			argtype = type(kwargs["default"])
			if argtype is bool: kwargs["default"] = bool(argstring.capitalize() == "True" or argstring == "1" or argstring.capitalize() == "Yes")
			elif argtype is float: kwargs["default"] = float(argstring)
			elif argtype is int: kwargs["default"] = int(argstring)
			elif argtype is long: kwargs["default"] = long(argstring)
			elif argtype is str: kwargs["default"] = str(argstring)
		OptionParser.add_option(self, *args, **kwargs)

if __name__ == "__main__":
	"""	Test setting add_option defaults from a .ini file

		If there is a file in the same directory and with the same name as the running program but with a .ini extension,
		"local" defaults for options can be set from the file. For example, if this is run as IniOptionParser.py and
		in the same directory is a file named IniOptionParser.ini that contains:

		[Defaults]
		boolean=True
		string=string from .ini file

		then the defaults for options.boolean and options.string will be changed from their settings in the add_option
		calls below.
	"""

	usage = "usage: %prog [options]"
	version = "1.0"

	parser = IniOptionParser(usage=usage, version=version)
	parser.add_option("-b", "--boolean", action="store_true", dest="boolean", help="set boolean option True", default=False)
	parser.add_option("-s", "--string", action="store", type="string", dest="string", help="set string option", default="default string")
	parser.add_option("-d", "--defaults", action="store_true", dest="defaults", help="display option defaults", default=True)
	options, args = parser.parse_args()

	if options.defaults:
		print "boolean :", options.boolean
		print "string  :", options.string
		print "defaults:", options.defaults
IniOptionParser.ini (application/octet-stream, 53 B) - not displayed