cape.argread: Command-Line Argument Processor

argread: Parse command-line arguments and options

This class provides the ArgReader class, instances of which can be used to customize available command-line options for a given interface.

The ArgReader class has the function ArgReader.parse(), which interprets sys.argv and splits it into a list of args and kwargs. The base ArgReader class will parse command-line arguments in useful ways, but one of the main intents is to subclass ArgReader and customize how various CLI arguments are parsed.

Here are some examples of the base interpreter, which can also be used with the convenience function readkeys().

>>> readkeys(["prog", "arg1", "arg2", "-v", "--name", "argread"])
("arg1", "arg2"), {"v": True, "name": "argread"}
>>> readkeys(["prog", "-v", "1", "2", "-name", "argread", "d=3"])
("2",), {"v": "1", "name": "argread", "d": "3"}

Notice that the 1 goes as the value of the option v. The 2 is not preceded by a str starting with a dash, so it gets interpreted as an arg.

There is an alternate function readflags() that interprets multi-letter args starting with a single dash differently:

>>> readflags(["prog", "-lh", "fname"])
("fname",), {"l": True, "h": True}

There is a third function readflagstar() that interprets arguments like tar

>>> readflagstar(["prog", "-cvf", "fname"])
(), {"c": True, "v": True, "f": "fname"}

These convenience functions make it easy to parse many command-line inputs with minimal effort, but it is also possible to declare richer and more specific interfaces by subclassing ArgReader.

For example

class MyParser(ArgReader):
    _optlist_noval = (
        "default",
        "verbose",
    )
    _optmap = {
        "d": "default",
        "v": verbose",
    }

has two properties. First -d and -v are abbreviations for --default and --verbose, respectively, because of the entries in MyParser._optmap. Second, neither option can take a “value”, so

$ prog -d hub url

would be parsed as

("hub", "url"), {"default": True}

In other words, the word hub didn’t get interpreted as the value for the option d as it would with the default ArgReader.

Another common use case is to convert CLI strings to another type. For example suppose you have an option i that takes in the index of something you want to work with, like

$ prog -i 3

The default readkeys() in this case would return

(), {"i": "3"}

you can convert this str "3" to an int with the following subclass

class MyConverter(ArgReader):
    _optconverters = {
        "i": int,
    }
exception cape.argread.ArgReadError

Base error class for this package

exception cape.argread.ArgReadValueError
class cape.argread.ArgReader

Class to parse command-line interface arguments

Call:
>>> parser = ArgReader(**kw)
Outputs:
parser: ArgReader

Instance of command-line argument parser

Attributes:
See also:
  • _vendor.kwparse.KwargParser

apply_cmdmap(cmdname: str) str

Apply aliases for sub-command name

Call:
>>> fullcmdname = parser.apply_cmdmap(cmdname)
Inputs:
parser: ArgReader

Command-line argument parser

cmdname: str

Name of sub-command as supplied by user

Outputs:
fullcmdname: str

Standardized name of cmdname, usually just cmdname

Versions:
  • 2024-11-11 @ddalle: v1.0

argv

list[str] – List of raw CLI commands parsed

argvals

list – Current values of non-keyword arguments

cmdname

str – Name of subcommand to use, if any

decide_cmdname(argv: list | None = None) SubCmdTuple

Identify sub-command if appropriate

Call:
>>> cmdname, subargv = parser.decide_cmdname(argv=None)
Inputs:
parser: ArgReader

Command-line argument parser

argv: {None} | list[str]

Raw command-line args to parse {sys.argv}

Outputs:
cmdname: str

(Standardized) name of sub-command as supplied by user

subargv: list[str]

Command-line arguments for sub-command to parse

Versions:
  • 2024-11-11 @ddalle: v1.0

equal_sign_key = True

Option to allow equal-sign options, e.g. key=val becomes {"key": "val"}

exc_cls

Base exception class: Exception

alias of ArgReadError

fullparse(argv: list | None = None) SubParserTuple

Identify sub-command and use appropriate parser

Call:
>>> cmdname, subparser = parser.fullparse(argv=None)
Inputs:
parser: ArgReader

Command-line argument parser

argv: {None} | list[str]

Optional arguments to parse, else sys.argv

Outputs:
cmdname: None | str

Name of command, if identified or inferred

subparser: ArgReadder

Parser for cmdname applied to remaining CLI args

Versions:
  • 2024-11-11 @ddalle: v1.0

genr8_help() str

Generate automatic help message to use w/ -h

Call:
>>> msg = parser.genr8_optshelp()
Inputs:
parser: ArgReader

Command-line argument parser

Outputs:
msg: str

Help message

genr8_opthelp(opt: str) str

Generate a help message for a particular option

Call:
>>> msg = parser.genr8_opthelp(opt)
Inputs:
parser: ArgReader

Command-line argument parser

opt: str

Name of option

Outputs:
msg: str

Help message for option opt

genr8_optshelp() str

Generate help message for all the options in _optlist

Call:
>>> msg = parser.genr8_optshelp()
Inputs:
parser: ArgReader

Command-line argument parser

Outputs:
msg: str

Help message for all options

get_aliases(opt: str) list

Get list of aliases for a particular option

Call:
>>> names = parser.get_aliases(opt)
Inputs:
parser: ArgReader

Command-line argument parser

opt: str

Name of option

Outputs:
names: list[str]

List of aliases, including opt; primary name first

get_args() ArgTuple

Get full list of args and options from parsed inputs

Call:
>>> args, kwargs = parser.get_args()
Outputs:
args: list[str]

List of positional parameter argument values

kwargs: dict

Dictionary of named options and their values

Versions:
  • 2023-11-08 @ddalle: v1.0

get_kwargs() dict

Get full list of kwargs, including repeated values

Call:
>>> args, kwargs = parser.get_args()
Outputs:
kwargs: dict

Dictionary of named options and their values

Versions:
  • 2024-12-19 @ddalle: v1.0

infer_cmdname() str | None

Infer sub-command if not determined by first argument

This command is usually overwritten in subclasses for special command-line interfaces where the primary task is inferred from options. This version always returns None

Call:
>>> cmdname = parser.infer_cmdname()
Inputs:
parser: ArgReader

Command-line argument parser

Outputs:
cmdname: str

Name of sub-command

Versions:
  • 2024-11-11 @ddalle: v1.0

kwargs_double_dash

list[str] – List of options that were entered with a double dash

kwargs_equal_sign

list[str] – List of options that were entered using key=val syntax

kwargs_replaced

list[str] – List of options that have duplicates

kwargs_sequence

list[str] – List of options in original order

kwargs_single_dash

list[str] – List of options that were entered with a single dash

param_sequence

list[str, object] – List of option name and value as parsed (includes duplicates in their original order)

parse(argv: list | None = None) ArgTuple

Parse CLI args

Call:
>>> a, kw = parser.parse(argv=None)
Inputs:
parser: ArgReader

Command-line argument parser

argv: {None} | list[str]

Optional arguments to parse, else sys.argv

Outputs:
a: list

List of positional arguments

kw: dict

Dictionary of options and their values

kw[“__replaced__”]: list[(str, any)]

List of any options replaced by later values

Versions:
  • 2021-11-21 @ddalle: v1.0

prog

str – Name of program read from argv[0]

reconstruct(params: list | None = None) list

Recreate a command from parsed information

Call:
>>> cmdlist = parser.reconstruct()
Inputs:
parser: ArgReader

Command-line argument parser

params: {None} | list[tuple]

Optional list of parameters (default from parser)

Outputs:
cmdlist: list[str]

Reconstruction of originally parsed command

Versions:
  • 2024-11-11 @ddalle: v1.0

save_arg(arg)

Save a positional argument

Call:
>>> parser.save_arg(arg, narg=None)
Inputs:
parser: ArgReader

Command-line argument parser

arg: str

Name/value of next parameter

Versions:
  • 2021-11-23 @ddalle: v1.0

save_double_dash(k, v=True)

Save a double-dash keyword and value

Call:
>>> parser.save_double_dash(k, v=True)
Inputs:
parser: ArgReader

Command-line argument parser

k: str

Name of key to save

v: {True} | False | str

Value to save

Versions:
  • 2021-11-23 @ddalle: v1.0

save_equal_key(k, v)

Save an equal-sign key/value pair, like "mach=0.9"

Call:
>>> parser.save_equal_key(k, v)
Inputs:
parser: ArgReader

Command-line argument parser

k: str

Name of key to save

v: str

Value to save

Versions:
  • 2021-11-23 @ddalle: v1.0

save_single_dash(k, v=True)

Save a single-dash keyword and value

Call:
>>> parser.save_single_dash(k, v=True)
Inputs:
parser: ArgReader

Command-line argument parser

k: str

Name of key to save

v: {True} | False | str

Value to save

Versions:
  • 2021-11-23 @ddalle: v1.0

single_dash_lastkey = False

Option to interpret multi-char words with a single dash the way POSIX command tar does, e.g. -cvf val becomes {"c": True, "v": True, "f": "val"}

single_dash_split = False

Option to interpret multi-char words with a single dash as single-letter boolean options, e.g. -lh becomes {"l": True, "h": True}

class cape.argread.ArgTuple(a, kw)
a

Alias for field number 0

kw

Alias for field number 1

class cape.argread.FlagsArgReader

Subclass of ArgReader for readflags()

The class attribute FlagsArgRead.single_dash_split is set to True so that -opt val is interpreted as

{"o": True, "p": True, "t": True}

and "val" becomes an argument.

single_dash_split = True

Option to interpret multi-char words with a single dash as single-letter boolean options, e.g. -lh becomes {"l": True, "h": True}

class cape.argread.KeysArgReader

Subclass of ArgReader for readkeys()

The class attribute KeysArgRead.single_dash_split is set to False so that -opt val is interpreted as

{"opt": "val"}
single_dash_split = False

Option to interpret multi-char words with a single dash as single-letter boolean options, e.g. -lh becomes {"l": True, "h": True}

class cape.argread.MetaArgReader(name: str, bases: tuple, namespace: dict)

Metaclass for ArgReader

This metaclass combines attributes w/ bases. For example if creating a new class Class2 that inherits from Class1, this will automatically combine Class1._optlist` and ``Class2._optlist and save the result as Class2._optlist. This happens behind the scenes so that users do not need to worry about repeating _optlist entries.

class cape.argread.SubCmdTuple(cmdname, argv)
argv

Alias for field number 1

cmdname

Alias for field number 0

class cape.argread.SubParserTuple(cmdname, subparser)
cmdname

Alias for field number 0

subparser

Alias for field number 1

class cape.argread.TarFlagsArgReader

Subclass of ArgReader for readflags()

The class attributes are

TarArgRead.single_dash_split = True
TarArgRead.single_dash_lastkey = True

so that -opt val is interpreted as

{"o": True, "p": True, "t": "val"}
single_dash_lastkey = True

Option to interpret multi-char words with a single dash the way POSIX command tar does, e.g. -cvf val becomes {"c": True, "v": True, "f": "val"}

single_dash_split = True

Option to interpret multi-char words with a single dash as single-letter boolean options, e.g. -lh becomes {"l": True, "h": True}

cape.argread.readflags(argv=None)

Parse args where -cj becomes c=True, j=True

Call:
>>> a, kw = readflags(argv=None)
Inputs:
argv: {None} | list[str]

List of args other than sys.argv

Outputs:
a: list[str]

List of positional args

kw: dict[str | bool]

Keyword arguments

Versions:
  • 2021-12-01 @ddalle: v1.0

cape.argread.readflagstar(argv=None)

Parse args where -cf a becomes c=True, f="a"

Call:
>>> a, kw = readflags(argv=None)
Inputs:
argv: {None} | list[str]

List of args other than sys.argv

Outputs:
a: list[str]

List of positional args

kw: dict[str | bool]

Keyword arguments

Versions:
  • 2021-12-01 @ddalle: v1.0

cape.argread.readkeys(argv=None)

Parse args where -cj becomes cj=True

Call:
>>> a, kw = readkeys(argv=None)
Inputs:
argv: {None} | list[str]

List of args other than sys.argv

Outputs:
a: list[str]

List of positional args

kw: dict[str | bool]

Keyword arguments

Versions:
  • 2021-12-01 @ddalle: v1.0