option argument length

Peter Otten __peter__ at web.de
Wed Dec 7 17:12:38 EST 2005


Ritesh Raj Sarraf wrote:

> ./sarraf.py --fetch-update /bar
> 
> If the user gives the /bar argument, the program should save the
> downloaded files to /bar. But I'm assuming that the user could be dumb or
> too lazy, in which case --fetch-udpate should use the parser.set_defaults
> value i.e. /foo
> 
> ./sarraf.py --set-upgrade foo.dat --upgrade-type minimal
> 
> set-upgrade will again write data to foo.dat. If the user doesn't pass it
> as an arguemnt it should take the defaults (again whatever is there in
> parser.set_defaults). This will be inclusive with the --upgrade-type
> option because the user will have a choice of selecting what kind of
> upgrade he'd like to do, minimal or full or blah.
> 
> For this I think this should be enough:
> 
> if not options.set_upgrade and options.upgrade_type:
> parser.error("They are mutually inclusive options")
> 
> 
> But my main concern is what if the user doesn't pass any arguemtns. Every
> option I have has a default value. So I want to check what the user has
> passed.
> But unfortunately the args variable has "0" as its value always.

args are just the leftover arguments. For

./sarraf.py alpha --set-upgrade foo.dat beta

it would be ["alpha", "beta"].

---

I think your description is starting to make sense to me. Your user can
either update or upgrade but you cannot just check the value of e. g.
set_upgrade because you want to treat the default value and that same value
given on the command line differently.

If this is a correct assessment I don't think what you want is covered by
optparse. However, I hacked something together:

import optparse

parser = optparse.OptionParser()

parser.add_option("--alpha")
parser.add_option("--beta")

class Values(object):
    def __init__(self):
        self.__defaults = {}
    def set_defaults(self, **kw):
        self.__defaults.update(kw)
    def __len__(self):
        """Number of options set by the user."""
        return len(self.__dict__) -1
    def __getattr__(self, name):
        try:
            return self.__defaults[name]
        except KeyError:
            raise AttributeError
    def is_default(self, name):
        """Return True when the default fro option 'name'
        wasn't overriden by the user"""
        return name not in self.__dict__

values = Values()
values.set_defaults(alpha="xxx", beta="yyy")

options, args = parser.parse_args(values=values)

print "len(options) =", len(options)
print "alpha =", options.alpha,
print "(using default)" * options.is_default("alpha")
print "beta =", options.beta,
print "(using default)" * options.is_default("beta")

Not particularly elegant but I'm not able to come up with something better
for the moment. Maybe you should just provide fewer defaults to the parser.
Or you could look into option callbacks for an alternate approach.

> Is my way (up till now) of using optparse logically incorrect or improper
> ?

Well, as the optparse author points out, "required options" are a
self-contradictory term -- don't use them if you can avoid it. Would your
problem go away if you used two different scripts, one for updating and the
other for upgrading?

Peter




More information about the Python-list mailing list