Kyo
Kyo

Reputation: 287

Passing optional arguments from optparse

I'm trying to figure out how to pass optional arguments from optparse. The problem I'm having is if an optparse option is not specified, it defaults to a None type, but if I pass the None type into a function, it yells at me instead of using the default (Which is understandable and valid).

conn = psycopg2.connect(database=options.db, hostname=options.hostname, port=options.port)

The question is, how do I use the function's defaults for optional arguments but still pass in user inputs if there is an input without having a huge number of if statements.

Upvotes: 1

Views: 1311

Answers (2)

Tobias
Tobias

Reputation: 2561

The opo module of my thebops package (pip install thebops, https://bitbucket.org/therp/thebops) contains an add_optval_option function. This uses an additional keyword argument empty which specifies the value to use if the option is used without a value. If one of the option strings is found in the commandline, this value is injected into the argument list.

This is still hackish, but at least it is made a simple-to-use function ...

It works well under the following circumstances:

  • The argument vector does already exist when the option is created. This is usually true.
  • All programs I found which sport arguments with optional values require the given value to be attached as --option=value or -ovalue rather than --option value or -o value.

Maybe I'll tweak thebops.optparse to support the empty argument as well; but I'd like to have a test suite first to prevent regressions, preferably the original Optik / optparse tests.

This is the code:

from sys import argv
def add_optval_option(pog, *args, **kwargs):
    """
    Add an option which can be specified without a value;
    in this case, the value (if given) must be contained
    in the same argument as seen by the shell,
    i.e.:

    --option=VALUE, --option will work;
    --option VALUE will *not* work

    Arguments:
    pog -- parser or group
    empty -- the value to use when used without a value

    Note:
      If you specify a short option string as well, the syntax given by the
      help will be wrong; -oVALUE will be supported, -o VALUE will not!
      Thus it might be wise to create a separate option for the short
      option strings (in a "hidden" group which isn't added to the parser after
      being populated) and just mention it in the help string.
    """
    if 'empty' in kwargs:
        empty_val = kwargs.pop('empty')
        # in this case it's a good idea to have a <default> value; this can be
        # given by another option with the same <dest>, though
        for i in range(1, len(argv)):
            a = argv[i]
            if a == '--':
                break
            if a in args:
                argv.insert(i+1, empty_val)
                break
    pog.add_option(*args, **kwargs)

Upvotes: 0

jfocht
jfocht

Reputation: 1754

Define a function remove_none_values that filters a dictionary for none-valued arguments.

def remove_none_values(d):
    return dict((k,v) for (k,v) in d.iteritems() if not v is None)

kwargs = {
  'database': options.db,
  'hostname': options.hostname,
  ...
}
conn = psycopg2.connect(**remove_none_values(kwargs))

Or, define a function wrapper that removes none values before passing the data on to the original function.

def ignore_none_valued_kwargs(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        newkwargs = dict((k,v) for (k,v) in d.iteritems() if not v is None)
        return f(*args, **kwargs)
    return wrapper

my_connect = ignore_none_valued_kwargs(psycopg2)
conn = my_connect(database=options.db, hostname=options.hostname, port=options.port)

Upvotes: 2

Related Questions