#11 optional values for options

open
None
5
2004-10-26
2004-10-20
No

Maybe I'm pushing it too much, but what about having
options with optional values?
Like,
test.py --set variable --verbose
but also
test.py --set variable 3.14 --verbose

Is this against the Tao?

I'm still thinking on how to implement this, but won't
bother anyone with it if it's regarded as poor style.

Need sleep.

Discussion

  • Andrea Bocci

    Andrea Bocci - 2004-10-20

    Logged In: YES
    user_id=526376

    Elaborating on...

    To (partially) resolve the ambiguity arising from optional
    option arguments, I would suggest using a strong type
    checking: in the example above, I'd define --set as
    make_option ('-s', '--set',
    action = 'store',
    type = 'string',
    optarg = 1,
    opttype = 'float',
    dest = 'result')

    and modify Option so that the optional argument is accepted
    only if it matches the desired type.

    optarg would default to 0
    opttype would default to type

    a string (possibly) matching an option (ie: -x, --xxx) would
    be considered as the next option

    Still have to think it thoroughly, though.

     
  • Greg Ward

    Greg Ward - 2004-10-26
    • assigned_to: nobody --> gward
     
  • Greg Ward

    Greg Ward - 2004-10-26

    Logged In: YES
    user_id=14422

    Option option arguments are not against the tao. They are
    just tricky to implement properly. I tried a couple of
    times but never got it quite right. Feel free to give it a
    shot.

    This is one change that probably cannot be done nicely by
    subclassing OptionParser, but I encourage you to try it that
    way first. A patch will probably end up being smaller and
    simpler, but I'd like to see how ugly a subclass is.

    Also, I think you're being too ambitious. All I've ever
    wanted is options that take a single argument, or nothing at
    all. Multiple optional arguments might be just a variation
    on that theme, but I suspect it's making a hard job even harder.

     
  • Rene Leonhardt

    Rene Leonhardt - 2006-12-30

    Logged In: YES
    user_id=153827
    Originator: NO

    Dear Greg,

    First of all many thanks for contributing this great Option parser to the community!

    I am using it since a few days and after looking into the source code I don't see why optional values should be so hard?

    Lines 1383 and 1422 are the key to optional values:
    value = tuple(rargs[0:nargs])

    I tested both locations, ragrs contains *all* parsed values for each option, regardless of nargs value.
    I think this is because of line 698:
    return tuple([self.check_value(opt, v) for v in value])

    So the only thing missing is an option attribute to represent the optional value count.
    For example:
    nargs=1, oargs=1
    would require one value and would allow a second value for an option.

    oargs would be 0 by default.

    I implemented and tested the 9 necessary code changes of the current optparse.py Subversion revision 53201:

    @@ -447,6 +447,7 @@
    + oargs : int
    @@ -463,6 +464,7 @@
    + 'oargs',
    @@ -694,6 +696,8 @@
    + if self.oargs is None:
    + self.oargs = 0
    @@ -1472,17 +1476,18 @@
    + oargs = nargs + option.oargs
    - elif nargs == 1:
    + elif oargs == 1:
    - value = tuple(rargs[0:nargs])
    - del rargs[0:nargs]
    + value = tuple(rargs[0:oargs])
    + del rargs[0:oargs]
    @@ -1511,17 +1516,18 @@
    + oargs = nargs + option.oargs
    - elif nargs == 1:
    + elif oargs == 1:
    - value = tuple(rargs[0:nargs])
    - del rargs[0:nargs]
    + value = tuple(rargs[0:oargs])
    + del rargs[0:oargs]

    If you want I can email you the new file and the full patch file.

    Best regards and greetings from Germany,
    René

     
  • Rene Leonhardt

    Rene Leonhardt - 2006-12-30

    Logged In: YES
    user_id=153827
    Originator: NO

    In case you want to look at the line numbers from the examples, they were take from optparse version 1.5a2 (Python 2.4.4).
    The line numbers for the current version 1.5.3, revision 53201, are 1484, 1523 and 770 (Python 2.5.0).

    Keep up the good work,
    René

     
  • Rene Leonhardt

    Rene Leonhardt - 2006-12-31

    Logged In: YES
    user_id=153827
    Originator: NO

    Dear Greg,

    I fixed a problem with nargs=0 and oargs>0.
    In addition I changed the value to None if no arg should be stored (instead of storing an empty tuple).

    The patch to the current version 1.5.3, revision 53201, now contains 10 differences in total:

    @@ -447,6 +447,7 @@
    + oargs : int
    @@ -463,6 +464,7 @@
    + 'oargs',
    @@ -694,6 +696,8 @@
    + if self.oargs is None:
    + self.oargs = 0
    @@ -764,7 +768,8 @@
    - if self.nargs == 1:
    + oargs = self.nargs + self.oargs
    + if self.nargs == 1 or oargs == 1:
    @@ -1472,17 +1477,20 @@
    + oargs = nargs + option.oargs
    - elif nargs == 1:
    + elif oargs == 0:
    + value = None
    + elif oargs == 1:
    - value = tuple(rargs[0:nargs])
    - del rargs[0:nargs]
    + value = tuple(rargs[0:oargs])
    + del rargs[0:oargs]
    @@ -1511,17 +1519,20 @@
    + oargs = nargs + option.oargs
    - elif nargs == 1:
    + elif oargs == 0:
    + value = None
    + elif oargs == 1:
    - value = tuple(rargs[0:nargs])
    - del rargs[0:nargs]
    + value = tuple(rargs[0:oargs])
    + del rargs[0:oargs]

    If you are interested in negating boolean values for long options by prefixing with "no-" like Bazaar does, I have implemented and tested a patch if you are interested.
    "Boolean options can be negated by adding or removing the prefix "no-"."
    http://bazaar-vcs.org/ConfiguringBzr#head-be8a030f1ed022c87b40e66104f7ec2e6451a1bd

    I.e. it automatically supports --no-verbose in addition to --verbose without requiring changing modules which use optparse.
    Additionally using modules can add the option argument negate=True (default: False) to programmatically negate the positive value of --verbose and the negative value of --no-verbose.
    The implementation (and maybe the confusion) is complete because the module can define an option with action="store_true", negate=True or any other combination.

    Here is the complete patch for to the current version 1.5.3, revision 53201, including 8 differences in total:

    @@ -447,6 +447,7 @@
    + negate : bool
    @@ -463,6 +464,7 @@
    + 'negate',
    @@ -684,6 +686,9 @@
    + if takes_value and self._long_opts and self.negate is None:
    + self.negate = False
    +
    @@ -787,9 +792,9 @@
    - setattr(values, dest, True)
    + setattr(values, dest, True ^ self.negate)
    - setattr(values, dest, False)
    + setattr(values, dest, False ^ self.negate)
    @@ -1469,7 +1474,13 @@
    + if type(opt) == tuple:
    + negate = opt[1]
    + opt = opt[0]
    + else:
    + negate = False
    + option.negate ^= negate
    @@ -1660,6 +1671,8 @@
    + elif s.startswith("--no-") and wordmap.has_key("--" + s[5:]):
    + return ("--" + s[5:], True)

    Best regards,
    René

     
  • Rene Leonhardt

    Rene Leonhardt - 2006-12-31

    Logged In: YES
    user_id=153827
    Originator: NO

    Hello

    There was a special case left nargs=0, oargs=1, I included the small fix in the patch below.

    The patch to the current version 1.5.3, revision 53201, still contains 10 differences in total:

    @@ -447,6 +447,7 @@
    + oargs : int
    @@ -463,6 +464,7 @@
    + 'oargs',
    @@ -694,6 +696,8 @@
    + if self.oargs is None:
    + self.oargs = 0
    @@ -764,7 +768,8 @@
    - if self.nargs == 1:
    + oargs = self.nargs + self.oargs
    + if self.nargs == 1 or oargs == 1:
    @@ -1472,17 +1477,20 @@
    + oargs = nargs + option.oargs
    - elif nargs == 1:
    + elif len(rargs) == 0 or oargs == 0:
    + value = None
    + elif oargs == 1:
    - value = tuple(rargs[0:nargs])
    - del rargs[0:nargs]
    + value = tuple(rargs[0:oargs])
    + del rargs[0:oargs]
    @@ -1511,17 +1519,20 @@
    + oargs = nargs + option.oargs
    - elif nargs == 1:
    + elif len(rargs) == 0 or oargs == 0:
    + value = None
    + elif oargs == 1:
    - value = tuple(rargs[0:nargs])
    - del rargs[0:nargs]
    + value = tuple(rargs[0:oargs])
    + del rargs[0:oargs]

    Best regards,
    René

     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.





No, thanks