Discuss: don't use argparse to handle command-line arguments

31 views
Skip to first unread message

Edward K. Ream

unread,
Jun 15, 2023, 4:36:13 AM6/15/23
to leo-editor
Leo issue #3351 reports a problem with how Leo handles --trace arguments.

Last night I marked this issue Can'tFix because I could see no easy way to make python's argparse module do what I want.

But when I awoke this morning, I saw no reason to live with argparse's limitations!

Indeed, the argparse module is a faux helper. It defines a complex (rigid!) scripting language. Scanning sys.argv with "help" would give Leo complete control.

Summary

I plan to rewrite LM.scanOptions without argparse.

Does anyone know why this plan might not be a good idea?

Edward

Edward K. Ream

unread,
Jun 15, 2023, 5:36:55 AM6/15/23
to leo-editor
On Thursday, June 15, 2023 at 3:36:13 AM UTC-5 Edward K. Ream wrote:

I plan to rewrite LM.scanOptions without argparse.

Initial work is promising.  Everything seems easier w/o argparse!  See PR #3382.

Edward

Thomas Passin

unread,
Jun 15, 2023, 8:50:14 AM6/15/23
to leo-editor
I wrote my own a few years ago.  It was simple to use and understand.  It was too simple, perhaps, but it did what I needed for a range of small programs.  The only thing it doesn't do is to flag unknown options: it ignores them instead.

I say, if you don't need all the complexity of argparse don't use it!

Thomas Passin

unread,
Jun 15, 2023, 10:37:55 AM6/15/23
to leo-editor
Just for general interest, here's my little argument parser:

import sys

def getopt (param, default=None):
    """Return a named parameter value from the command line.

    The parameter and its value must be of the form

        -param value

    The parameter string and its following value are removed
    from sys.argv. If the parameter is not present on the command line,
    then the value of the variable is not changed, and nothing
    is removed from sys.argv.

    Param can be a flag (that is, a boolean will be returned and the
    value on the command line following the flag will not be returned
    or consumed) if the "default" parameter is omitted or None.
    Typical code for this usage would be:

    WANT_HELP = getopt('-h')
    if WANT_HELP:
        print(__doc__)
        sys.exit(1)

    NOTE: this function converts the result type to the type
    of "default" - e.g., int(), float(), or bool().

    ARGUMENTS
    param -- the name of the command line option, including the
             '-' character if used.
    default -- the default value for the parameter.  If omitted,
               the function returns True if the param is present.

    RETURNS
    the new value of the parameter, or the default value if param
    is missing from the command line, or True if param is a flag
    (i.e., "default" is omitted or None).
    """

    try:
        opt = sys.argv.index(param)
        del sys.argv[opt]
        if default is not None:
            option = type(default)(sys.argv.pop(opt))
        else:
            option = True # don't consume the next parameter
    except ValueError:
        option = default # param is not in sys.argv
    except IndexError:
        msg = '"%s" parameter is missing its required value' % param
        raise ValueError(msg)
    return option

Edward K. Ream

unread,
Jun 15, 2023, 11:38:45 AM6/15/23
to leo-e...@googlegroups.com
On Thu, Jun 15, 2023 at 7:50 AM Thomas Passin <tbp1...@gmail.com> wrote:

I say, if you don't need all the complexity of argparse don't use it!

Nobody needs all that complexity :-)

The argparse module is founded on a design mistake that python was created to avoid. In effect, argparse creates a specialized internal scripting language masquerading as an API. This API/language has no advantages:

- Why use specialized parsers (and subparsers, and all the other blah, blah, blah) when regexs suffice?
- Why compute a help message when a string suffices?
- It's easy to compute all valid arguments by applying a simple regex to the help message.

Edward
Reply all
Reply to author
Forward
0 new messages