[Enhancement Proposal]: different types for 'nargs' > 1
"Andrea 'fwyzard' Bocci" <[email protected]> Wed, 20 Oct 2004 19:54:26 +0200
| Newsgroups | gmane.comp.python.optik.user |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format.
--------------020101060905040708030609
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Right now an Option with 'nargs' > 1 accept n arguments of the same all
of the same 'type'.
What I'd find usefull is the possibility to set the type of each
argument indipendently, ie. something like
type = ('choice', 'float')
wich is automatically transformed in
type = 'tuple',
types = ('choice', 'float')
BTW, these should automatically instruct Option to consume 2 arguments
(nargs = 2).
So far, I've implemented all this, introducing these changes to Option:
- new type (and type checker): 'tuple' (and check_tuple)
- new class attribute/constructor keyword: 'types', to hold the tuple
of types
- modified _check_type to check 'tuple' as a type and then each type
inside the tuple
- modified some type check from
something == 'type'
to
something == 'type' or ('tuple' == self.type and something in self.types)
and some minor ones here and there, to hold it all together.
I've implemented this either as a subclass or as a patch agains
option.py (CVS 1.51a). The latter is attached.
Hope anyone finds this interesting and/or usefull :-)
.fw.
--------------020101060905040708030609
Content-Type: text/x-patch;
name="tuple.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="tuple.diff"
? build
Index: lib/option.py
===================================================================
RCS file: /cvsroot/optik/optik/lib/option.py,v
retrieving revision 1.33
diff -u -3 -p -r1.33 option.py
--- lib/option.py 24 Jul 2004 23:21:21 -0000 1.33
+++ lib/option.py 20 Oct 2004 17:08:45 -0000
@@ -43,6 +43,11 @@ def check_choice(option, opt, value):
_("option %s: invalid choice: %r (choose from %s)")
% (opt, value, choices))
+def check_tuple(option, opt, value):
+ value = [option.check_value(opt, v) for (v, option.type) in map(None, value, option.types)]
+ option.type = "tuple"
+ return tuple(value)
+
# Not supplying a default is different from a default of None,
# so we need an explicit "not supplied" value.
NO_DEFAULT = ("NO", "DEFAULT")
@@ -55,7 +60,8 @@ class Option:
_long_opts : [string]
action : string
- type : string
+ type : { string | tuple of strings | list of strings }
+ types : { tuple of strings | list of strings }
dest : string
default : any
nargs : int
@@ -72,6 +78,7 @@ class Option:
# keyword args to the constructor.
ATTRS = ['action',
'type',
+ 'types',
'dest',
'default',
'nargs',
@@ -113,7 +120,7 @@ class Option:
# The set of known types for option parsers. Again, listed here for
# constructor argument validation.
- TYPES = ("string", "int", "long", "float", "complex", "choice")
+ TYPES = ("string", "int", "long", "float", "complex", "choice", "tuple")
# Dictionary of argument checking functions, which convert and
# validate option arguments according to the option type.
@@ -136,6 +143,7 @@ class Option:
"float" : check_builtin,
"complex": check_builtin,
"choice" : check_choice,
+ "tuple" : check_tuple,
}
@@ -226,6 +234,22 @@ class Option:
raise OptionError("invalid action: %r" % self.action, self)
def _check_type(self):
+ if type(self.type) in (types.TupleType, types.ListType):
+ if not self.type:
+ # take care of empty sequences
+ self.type = None
+ else:
+ # check each type, and save them in 'types'
+ self.types = tuple([self._check_type() for self.type in self.type])
+ self.type = "tuple"
+ elif self.type == "tuple":
+ if type(self.types) not in (types.TupleType, types.ListType):
+ raise OptionError("must supply a list or tuple of types for type 'tuple'", self)
+ else:
+ # check each type, and save them in 'types'
+ self.types = tuple([self._check_type() for self.type in self.types])
+ self.type = "tuple"
+
if self.type is None:
# XXX should factor out another class attr here: list of
# actions that *require* a type
@@ -248,9 +272,11 @@ class Option:
if self.action not in self.TYPED_ACTIONS:
raise OptionError(
"must not supply a type for action %r" % self.action, self)
+ # return the final type - usefull for checking "tuple" types
+ return self.type
def _check_choice(self):
- if self.type == "choice":
+ if self.type == "choice" or (self.type == "tuple" and "choice" in self.types):
if self.choices is None:
raise OptionError(
"must supply a list of choices for type 'choice'", self)
@@ -286,7 +312,12 @@ class Option:
def _check_nargs(self):
if self.action in self.TYPED_ACTIONS:
if self.nargs is None:
- self.nargs = 1
+ if self.type == "tuple":
+ self.nargs = len(self.types)
+ else:
+ self.nargs = 1
+ elif self.type == "tuple" and self.nargs != len(self.types):
+ raise OptionError("if supplied, 'nargs' must be equal to len('types')", self)
elif self.nargs is not None:
raise OptionError(
"'nargs' must not be supplied for action %r" % self.action,
@@ -358,7 +389,7 @@ class Option:
def convert_value(self, opt, value):
if value is not None:
- if self.nargs == 1:
+ if self.nargs == 1 or self.type == "tuple":
return self.check_value(opt, value)
else:
return tuple([self.check_value(opt, v) for v in value])
--------------020101060905040708030609--
-------------------------------------------------------
This SF.net email is sponsored by: IT Product Guide on ITManagersJournal
Use IT products in your business? Tell us what you think of them. Give us
Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more
http://productguide.itmanagersjournal.com/guidepromo.tmpl