cape.cfdx.options.actionopts: Customize case-disposition actions

This provides a list of what CAPE should normally do in any of a variety of case disposition actions. The most common example is how to handle “approved” cases. This would normally start with

$ cape approve -I {CASES}
$ cape dex -I {CASES}

but may also include custom actions (e.g. ./tools/writesurfcp.py) or divide the commands into groups.

$ cape --PASS -I {CASES}
$ cape --dex "[A-L]*" -I {CASES}
$ cape --dex "[M-Z]*" -I {CASES}
$ ./tools/writesurfcp.py -I {CASES}

This would look like the following in the "Actions" section of the CAPE JSON file:

"Actions": {
    "approve": [
        {
            "type": "cntl",
            "function": "MarkPASS"
        },
        "./tools/writesurfcp.py",
        {
            "type": "cli",
            "function": "cape_extract_dex",
            "index": 2,
            "kwargs": {
                "dex": "[A-L]*"
            }
        },
        {
            "type": "cli",
            "function": "cape_extract_dex",
            "index": 2,
            "kwargs": {
                "dex": "[M-Z]*"
            }
        }
    ]
}

This means that when a user calls

$ cape perform approve -I {CASES}

The following commands will happen:

$ cape approve -I {CASES}
$ ./tools/writesurfcp.py -I {CASES}
$ cape dex --dex "[A-L]*" -I {CASES}
$ cape dex --dex "[M-Z]*" -I {CASES}

However, the last two are run simultaneously because they have the same value for "index". Each action in such a group runs in a forked child process with its STDOUT redirected to a log file named log/cape-perform.{j+1}.{k+1} (relative to the root folder) and its STDERR shown on the terminal, along with the action’s title, any error messages, and a live status board while the group is running. Since the actions run in child processes, only their on-disk side effects persist in the main process.

User-defined tools for cape review and cape dispatch are also defined in this section: the "UserTools" option is a list of names, and each name is defined as an action just like "approve" in the example above.

"Actions": {
    "UserTools": ["writecp"],
    "writecp": "./tools/writesurfcp.py {I}"
}

The names "approve", "defail", "dezombie", "extend", and "extend2" have default definitions (see DEFAULT_ACTIONS) that reproduce the behavior of cape approve, cape defail, etc., unless redefined in this section.

For shell commands, a {I} placeholder is replaced by the case indices being processed; shell commands without one get -I {CASES} appended automatically. Shell commands from the legacy top-level UserTools option (a dict of names and commands), however, must contain a {I} placeholder.

Actions of type "shell" or "cli" also accept an "AddFileName" option. When true, the name of the JSON file the current run matrix was read from (relative to the root folder, following any links) is passed along: -f {JSON} is appended to shell commands, and an f={JSON} keyword argument is added to cli function calls (unless the action’s kwargs already set "f"). This option has no effect for "cntl" actions.

class cape.cfdx.options.actionopts.ActionOpts(*args, **kw)
class cape.cfdx.options.actionopts.ActionsOpts(*args, **kw)
check_optname(opt, mode=None)

Check validity of option named opt

Call:
>>> valid = opts.check_optname(opt, mode=None)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to test

mode: {None} | 0 | 1 | 2 | 3

Warning mode code

0:

no checks

1:

validate silently

2:

validate and show warnings

3:

raise an exception if invalid

Outputs:
valid: True | False

Whether or not option name opt is allowed

Versions:
  • 2022-09-18 @ddalle: v1.0

  • 2022-09-30 @ddalle: v2.0: _save_lastwarn()

check_opttype(opt, val, mode=None)

Check type of a named option’s value

This uses the options type dictionary in type(opts)._opttypes and/or opts._xopttypes. If opt is present in neither of these dicts, no checks are performed.

Special dicts, e.g

{
    "@map": {
        "a": 2,
        "b": 3,
    },
    "key": "arch"
}

are checked against their own special rules, for example

  • "@expr" must be a str

  • "@map" must be a dict

  • "@cons" must be a dict

  • "@map" must be accompanied by "key", a str

Call:
>>> valid, v2 = opts.opts.check_opttype(opt, val, mode=None)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to test

val: any

Value for opt to test

mode: {None} | 0 | 1 | 2 | 3

Warning mode code

0:

no checks

1:

validate silently

2:

validate and show warnings

3:

raise an exception if invalid

Outputs:
valid: True | False

Whether or not option name opt is allowed

v2: any

Either val or converted to new class

Versions:
  • 2022-09-18 @ddalle: v1.0

  • 2022-09-30 @ddalle: v1.1; use _lastwarn

get_Action(name) → list

Get list of action definitions for an action name

Call:
>>> actlist = opts.get_Action(name)
Inputs:
opts: ActionsOpts

Actions options interface

name: str

Name of action, e.g. "approve" or a UserTools name

Outputs:
actlist: None | list[ActionOpts]

List of actions to perform, or None if name is neither defined locally nor a default action name

get_UserToolsNames() → list

Get names of user-defined tools

Call:
>>> names = opts.get_UserToolsNames()
Inputs:
opts: ActionsOpts

Actions options interface

Outputs:
names: list[str]

Names of user tools for cape review/dispatch