optparse alternative

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Henry Ludemann

    #1

    optparse alternative

    I've been writing an optparse alternative (using getopt) that is at a
    stage where I'd be interested in people's opinions. It allows you to
    easily creating command line interfaces to existing functions, using
    flags (which are optional) and arguments. It will automatically print a
    nicely formatted usage (eg: -h or --help), and easily & automatically
    validates parameter existence and type.

    You can download it, and read a bit more about it, at
    <http://hl.id.au/Projects/CommandLine/>

    I'm interested in comments and criticisms; I've tried to write it
    according to the python coding guildlines.

    Example usage of a cmdline usage;

    $ python test.py --help
    Usage: test.py [OPTIONS] SOMEARG
    An example to show usage of command line

    Arguments
    SOMEARG Some float argument

    Mandatory arguments to long flags are mandatory for short options
    too
    -h, --help Show this help page
    -s, --setflag Set the flag

    Email bug reports to bugs@example.co m

    Source for the above example;

    def someFunc(someAr g, someFlag = False):
    print "Flag value =", someFlag
    print "Arg value =", someArg

    from cmdline.Command import Command
    command = Command(someFun c, "An example to show usage of command
    line", "Email bug reports to bugs@example.co m")
    command.addFlag ('s', 'setflag', 'Set the flag', 'someFlag')
    command.addArgu ment('SOMEARG', 'Some float argument', 'someArg',
    float)
    command.invoke( )

    Normal use of test.py would have given

    $ python test.py 3
    Flag value = False
    Arg value = 3.0

  • Steven Bethard

    #2
    Re: optparse alternative

    Henry Ludemann wrote:[color=blue]
    > I've been writing an optparse alternative (using getopt) that is at a
    > stage where I'd be interested in people's opinions.[/color]

    Looks interesting, but is it really that different from optparse?

    I do like the fact that you can specify a type with a conversion
    function. (In optparse, AFAIK, to add a new type you have to write your
    own subclass of Option that screws with Option.TYPES and
    Option.TYPE_CHE CKER, which I've always thought was kinda nasty.)

    But I wonder if it wouldn't be better to extend optparse with the
    functionality instead of writing an entirely new module...

    STeVe

    Comment

    • Steven Bethard

      #3
      Re: optparse alternative

      Henry Ludemann wrote:[color=blue]
      > I've been writing an optparse alternative (using getopt) that is at a
      > stage where I'd be interested in people's opinions.[/color]

      Some more detailed comments:

      * The more I think about it, the more I like that you're basically
      constructing options to match a function signature. But I can imagine
      that this might be too restrictive for some uses. It might be worth
      having an alternate interface that provides an options object like
      optparse does.

      * Any reason why you aren't using new-style classes?

      * I think the code would be easier to navigate in a single module.

      * Your code alternates between underscore_name s and camelCaseNames.
      Might be better to stick with one or the other. (PEP 8 suggests the
      former.)

      * File specific comments:

      Argument.py:
      Drop the get_name method; name attribute is already accessible. (The
      property builtin makes getters and setters generally unnecessary.)

      CommandArgument .py:
      Drop the get_param_name method; param_name attribute is already accessible

      Flag.py:
      __init__ should have defaults where applicable (e.g. the comments say
      you can provide None for short_flag, but it doesn't default to this).
      Should also probably produce an error if neither short_flag nor
      long_flag is set. (Or do this in Command._add_op tions)

      In get_value, use "self.argum ent is None" not "self.argum ent == None".

      get_flag_name should default to long_flag, not short_flag

      Command.py:
      add_flag should call _validate_param _name *before* _add_options (in case
      an exception is raised and caught).

      In _get_params,
      for arg_index in range(len(metho d_args)):
      arg = method_args[arg_index]
      could be replaced with
      for arg_index, arg in enumerate(metho d_args):

      MulipleLines.py :
      Can you use the (standard library) textwrap module instead? Seems like
      they do about the same thing, but I haven't looked in too much detail.


      Hope these comments are at least marginally useful. ;)

      STeVe

      Comment

      • Michael Hoffman

        #4
        Re: optparse alternative

        Henry Ludemann wrote:
        [color=blue]
        > I've been writing an optparse alternative (using getopt) that is at a
        > stage where I'd be interested in people's opinions.[/color]

        Thanks for the work and letting us see it!

        As far as I can tell, your module has one functional advantage over
        optparse--it validates arguments as well as options. The rest seems to
        be cosmetics, and personally I prefer the cosmetics of optparse. For
        one thing, it uses the variable/function naming style found throughout
        most of the stdlib. optparse has also been widely used and tested for
        the last four years.

        I think you would be better off trying to extend optparse to deal with
        non-option arguments, and you can tap into the installed base of
        existing optparse users and even get your code included in the stdlib
        if Greg Ward agrees. Whereas that's really unlikely for an entirely
        new module--there just isn't the need for a THIRD way to do the same
        thing.

        Just a suggestion.
        --
        Michael Hoffman

        Comment

        • Henry Ludemann

          #5
          Re: optparse alternative

          Thanks for the comments...

          Steven Bethard wrote:
          [color=blue]
          > Looks interesting, but is it really that different from optparse?[/color]

          In the sense that they both do the same thing, no, not really. But the
          way they do it is quite different; optparse bases itself on setting
          variables, while this module is for invoking functions. I like this way
          a better, as it acts as a more 'usual' client of the code, in the sense
          that it uses publically exposed interfaces rather then internal
          variables for passing the information. That said, the reason I started
          this was that at the time I wasn't aware of optparse; my search through
          the help needed to be a bit more thorough. When I found optparse, I
          decided to continue on with this approach (mostly because I was having
          fun with it).
          [color=blue]
          > I do like the fact that you can specify a type with a conversion
          > function. (In optparse, AFAIK, to add a new type you have to write
          > your own subclass of Option that screws with Option.TYPES and
          > Option.TYPE_CHE CKER, which I've always thought was kinda nasty.)[/color]

          Yeah, it works quite nicely; as it is a general function, you can use
          your own methods for creating arbitrary objects (so long as they take
          one parameter (a string)).
          [color=blue]
          > But I wonder if it wouldn't be better to extend optparse with the
          > functionality instead of writing an entirely new module...[/color]

          The way of getting the data through to the program is quite different
          (method vs data), so that would be a fairly radical change / addition
          for optparse.

          Comment

          • Henry Ludemann

            #6
            Re: optparse alternative

            [color=blue]
            >
            > * The more I think about it, the more I like that you're basically
            > constructing options to match a function signature. But I can imagine
            > that this might be too restrictive for some uses. It might be worth
            > having an alternate interface that provides an options object like
            > optparse does.[/color]


            It is matching options to a function signiture, and for complex methods,
            this might be too restrictive (for example, you'd get methods with 10 -
            20 params). That said, many cases don't have this many things that can
            be set.

            Although your point about providing an alternate interface is a good one...
            [color=blue]
            > * Any reason why you aren't using new-style classes?[/color]


            Ignorance. I'll look into it...
            [color=blue]
            > * I think the code would be easier to navigate in a single module.[/color]


            It might be easier to navigate (eg: when you want to go to a method
            implmentation), but from a maintenance point of view I feel modular code
            is easier... Mostly this is instint from other languages (mostly c++).
            [color=blue]
            > * Your code alternates between underscore_name s and camelCaseNames.
            > Might be better to stick with one or the other. (PEP 8 suggests the
            > former.)[/color]


            Yeah, I coded it before I looked at PEP8. Initially it was all camel
            case, and I attempted to retrofit it. It seems like classes should still
            be CamelCase, yes?
            [color=blue]
            > * File specific comments:
            >
            > Argument.py:
            > Drop the get_name method; name attribute is already accessible. (The
            > property builtin makes getters and setters generally unnecessary.)
            >
            > CommandArgument .py:
            > Drop the get_param_name method; param_name attribute is already
            > accessible
            >
            > Flag.py:
            > __init__ should have defaults where applicable (e.g. the comments say
            > you can provide None for short_flag, but it doesn't default to this).
            > Should also probably produce an error if neither short_flag nor
            > long_flag is set. (Or do this in Command._add_op tions)
            >
            > In get_value, use "self.argum ent is None" not "self.argum ent == None".
            >
            > get_flag_name should default to long_flag, not short_flag
            >
            > Command.py:
            > add_flag should call _validate_param _name *before* _add_options (in
            > case an exception is raised and caught).
            >
            > In _get_params,
            > for arg_index in range(len(metho d_args)):
            > arg = method_args[arg_index]
            > could be replaced with
            > for arg_index, arg in enumerate(metho d_args):[/color]


            Will do...
            [color=blue]
            >
            > MulipleLines.py :
            > Can you use the (standard library) textwrap module instead? Seems
            > like they do about the same thing, but I haven't looked in too much
            > detail.[/color]


            Doh! Yep, they do the same thing. This is another case of my not
            checking the standard library well enough.
            [color=blue]
            > Hope these comments are at least marginally useful. ;)[/color]


            Yes, very useful. Thanks very much for spending the time to go over it...

            Comment

            • Henry Ludemann

              #7
              Re: optparse alternative

              [color=blue]
              > As far as I can tell, your module has one functional advantage over
              > optparse--it validates arguments as well as options.[/color]

              Functionality wise, that is probably about it. It is more from a
              seperation of command line / functionality code that I wrote this; that
              the command line code should be seperate from the actual functional code.
              [color=blue]
              > The rest seems to be cosmetics, and personally I prefer the cosmetics
              > of optparse.[/color]

              All to their own... I actually wrote this before I was aware of
              optparse, and so didn't consider the benefits / disadvantages of that
              way of doing it. It's simply a different approach. That said, what I
              like about this approach is that it is non-obtrusive on the functional code.
              [color=blue]
              > For one thing, it uses the variable/function naming style found
              > throughout
              > most of the stdlib.[/color]

              True... I originally wrote the code in camel case, and have attempted to
              change it to the standard from PEP 8. I guess I missed a few things :-)
              [color=blue]
              > optparse has also been widely used and tested for
              > the last four years.[/color]

              Again, true, but then again, this module (unlike optparse) uses the
              standard getopt module for all command line parsing, which has been
              around for even longer. So the bugs are all in the method invoking (my
              code), and not in the parsing. <grin>
              [color=blue]
              > I think you would be better off trying to extend optparse to deal with
              > non-option arguments, and you can tap into the installed base of
              > existing optparse users and even get your code included in the stdlib
              > if Greg Ward agrees. Whereas that's really unlikely for an entirely
              > new module--there just isn't the need for a THIRD way to do the same
              > thing.[/color]

              Yeah, a third module would be a bit redundent. I had actually written
              most of this module before I became aware of optparse (it was one of
              those bash the head against the wall moments when I found it), but
              decided to continue with this version because I liked the cosmetics of
              it (it seemed less intrusive on the functional code). Once it was more
              or less finished, I decided to clean it up and post it in the hope it
              might be useful to someone else, and perhaps more, to get any comments
              that could improve it. And besides, variety is the spice of life :-)
              [color=blue]
              > Just a suggestion.[/color]

              Thanks for your comments...

              Comment

              • Michael Hoffman

                #8
                Re: optparse alternative

                Henry Ludemann wrote:
                [color=blue]
                > I had actually written most of this module before I became aware
                > of optparse (it was one of those bash the head against the wall
                > moments when I found it),[/color]

                I've been there :)
                --
                Michael Hoffman

                Comment

                Working...