Parsing keyword-style program arguments (pwkit.kwargv)

The pwkit.kwargv module provides a framework for parsing keyword-style arguments to command-line programs. It’s designed so that you can easily make a routine with complex, structured configuration parameters that can also be driven from the command line.

Keywords are defined by declaring a subclass of the ParseKeywords class with fields corresponding to the support keywords:

from pwkit.kwargv import ParseKeywords, Custom

class MyConfig(ParseKeywords):
    foo = 1
    bar = str
    multi = [int]
    extra = Custom(float, required=True)

    @Custom(str)
    def declination(value):
        from pwkit.astutil import parsedeglat
        return parsedeglat(value)

Instantiating the subclass fills in all defaults. Calling the ParseKeywords.parse() method parses a list of strings (defaulting to sys.argv[1:]) and updates the instance’s properties. This framework is designed so that you can provide complex configuration to an algorithm either programmatically, or on the command line. A typical use would be:

from pwkit.kwargv import ParseKeywords, Custom

class MyConfig(ParseKeywords):
    niter = 1
    input = str
    scales = [int]
    # ...

def my_complex_algorithm(cfg):
   from pwkit.io import Path
   data = Path(cfg.input).read_fits()

   for i in range(cfg.niter):
       # ....

def call_algorithm_in_code():
    cfg = MyConfig()
    cfg.input = 'testfile.fits'
    # ...
    my_complex_algorithm(cfg)

if __name__ == '__main__':
    cfg = MyConfig().parse()
    my_complex_algorithm(cfg)

You could then execute the module as a program and specify arguments in the form ./program niter=5 input=otherfile.fits.

Keyword Specification Format

Arguments are specified in the following ways:

  • foo = 1 defines a keyword with a default value, type inferred as int. Likewise for str, bool, float.

  • bar = str defines an string keyword with default value of None. Likewise for int, bool, float.

  • multi = [int] parses as a list of integers of any length, defaulting to the empty list [] (I call these “flexible” lists.). List items are separated by commas on the command line.

  • other = [3.0, int] parses as a 2-element list, defaulting to [3.0, None]. If one value is given, the first array item is parsed, and the second is left as its default. (I call these “fixed” lists.)

  • extra = Custom(float, required=True) parses like float and then customizes keyword properties. Supported properties are the attributes of the KeywordInfo class.

  • Use Custom as a decorator (@Custom) on a function foo defines a keyword foo that’s parsed according to the Custom specification, then has its value fixed up by calling the foo() function after the basic parsing. That is, the final value is foo (intermediate_value). A common pattern is to use a fixup function for a fixed list where the first few values are mandatory (see KeywordInfo.minvals below) but later values can be guessed or defaulted.

See the KeywordInfo documentation for specification of additional keyword properties that may be specified. The Custom name is simply an alias for KeywordInfo.

pwkit.kwargv.Custom

alias of KeywordOptions

class pwkit.kwargv.KeywordInfo[source]

Properties that a keyword argument may have.

default = None

The default value for the keyword if it’s left unspecified.

fixupfunc = None

If not None, the final value of the keyword is set to the return value of fixupfunc(intermediate_value).

maxvals = None

The maximum number of values allowed. This only applies for flexible lists; fixed lists have predetermined sizes.

minvals = 0

The minimum number of values allowed in a flexible list, if the keyword is specified at all. If you want minvals = 1, use required = True.

parser = None

A callable used to convert the argument text to a Python value. This attribute is assigned automatically upon setup.

printexc = False

Print the exception as normal if there’s an exception when parsing the keyword value. Otherwise there’s just a message along the lines of “cannot parse value <val> for keyword <kw>”.

repeatable = False

If true, the keyword value(s) will always be contained in a list. If they keyword is specified multiple times (i.e. ./program kw=1 kw=2), the list will have multiple items (cfg.kw = [1, 2]). If the keyword is list-valued, using this will result in a list of lists.

required = False

Whether an error should be raised if the keyword is not seen while parsing.

scale = None

If not None, multiply numeric values by this number after parsing.

sep = ','

The textual separator between items for list-valued keywords.

uiname = None

The name of the keyword as parsed from the command-line. For instance, some_value = Custom(int, uiname="some-value") will result in a keyword that the user sets by calling ./program some-value=3. This provides a mechanism to support keyword names that are not legal Python identifiers.

exception pwkit.kwargv.KwargvError(fmt, *args)[source]

Raised when invalid arguments have been provided.

exception pwkit.kwargv.ParseError(fmt, *args)[source]

Raised when the structure of the arguments appears legitimate, but a particular value cannot be parsed into its expected type.

class pwkit.kwargv.ParseKeywords[source]

The template class for defining your keyword arguments. A subclass of pwkit.Holder. Declare attributes in a subclass following the scheme described above, then call the ParseKeywords.parse() method.

parse(args=None)[source]

Parse textual keywords as described by this class’s attributes, and update this instance’s attributes with the parsed values. args is a list of strings; if None, it defaults to sys.argv[1:]. Returns self for convenience. Raises KwargvError if invalid keywords are encountered.

See also ParseKeywords.parse_or_die().

parse_or_die(args=None)[source]

Like ParseKeywords.parse(), but calls pkwit.cli.die() if a KwargvError is raised, printing the exception text. Returns self for convenience.

pwkit.kwargv.basic(args=None)[source]

Parse the string list args as a set of keyword arguments in a very simple-minded way, splitting on equals signs. Returns a pwkit.Holder instance with attributes set to strings. The form +foo is mapped to setting foo = True on the pwkit.Holder instance. If args is None, sys.argv[1:] is used. Raises KwargvError on invalid arguments (i.e., ones without an equals sign or a leading plus sign).