optdict: Advanced dict-based options interface

This class provides the module OptionsDict, which is a Python class based on dict with a variety of advanced features and an interface to and from JSON files.

The OptionsDict can be used in isolation as an alternative to dict but that can be initiated from a JSON file name. For example if the file settings.json has the contents

{
    "a": 3,
    "b": true,
    "c": ["fun", "bad"],
    "d": JSONFile("d.json")
}

and d.json contains

{
    "north": 0.0,
    "south": 180.0 // heading angle
}

Then an OptionsDict can be instantiated using

opts = OptionsDict("settings.json")

Note two features of this example:

  • including other JSON files using the JSONFile() directive

  • comments using the // syntax

The other way to use OptionsDict is to create subclasses, and the reason to do this is to only allow specified option names (keys) or to only allow certain types and/or values for some keys.

class MyOpts(OptionsDict):
    _optlist = {
        "a",
        "b",
        "c"
    }
    _opttypes = {
        "a": int,
        "b": str,
        "c": (dict, list)
    }
    _optvals = {
        "a": {0, 1, 2}
    }
    _rc = {
        "b": "fun"
    }

opts = MyOpts(c={"on": True}, a=2)

Now if we try to set a parameter that’s not in _optlist, we’ll either get ignored, warned, or raise an exception, depending on the “warning mode”:

>>> opts.set_opt("d", 1)
Unknown 'MyOpts' option 'd'

We can also access the default value for b if it has not been set:

>>> opts.get_opt("b")
"fun"

Types and values can be constrained and checked seperately on assignment and retrieval.

>>> opts.set_opt("a", 1.0)
For 'MyOpts' option 'a': got type 'float'; expected 'int'
>>> opts.set_opt("b", 1.0, mode=WARNMODE_NONE)
>>> opts["b"]
1.0
>>> opts.get_opt("b")
For 'MyOpts' option 'b': got type 'float'; expected 'str'
>>> opts.set_opt("a", 3)
Unknown value 3 for MyOpts option 'a'; available options: 0 1 2

The type checkers can have somewhat surprising behavior if trying to use a list.

>>> opt.set_opt("c", [1, 2], mode=WARNMODE_WARN)
... option 'c' phase 0: got type 'int'; expected 'dict' | 'list'

This seems confusing because [1, 2] is a list, which seems to be allowed. However, optdict (by default, anyway) interprets [1, 2] as 1 for phase 0 and 2 for phases 1 and beyond:

>>> opts.set_opt("c", [1, 2], mode=WARNMODE_NONE)
>>> opts.get_opt('c", j=0, mode=WARNMODE_NONE)
1

There are two solutions to these cases where a list might be intended as an atomic input value (not a sequence of phase-specific values):

>>> opts.set_opt("c", [[1, 2]]
>>> opts.get_opt("c", j=0)
[1, 2]
>>> opts.get_opt("c")
[[1, 2]]
>>> MyOpts._optlistdepth["c"] = 1
>>> opts.set_opt("c", [1, 2])
>>> opts.get_opt("c", j=0)
[1, 2]
>>> opts.get_opt("c")
[1, 2]

Note

Type checking for both int and float can be tricky when dealing with numeric data, which may originate from numpy types that look like integers but fail the isinstance() test. For example

>>> isinstance(np.arange(4)[0], int)
False

To help in this situation, optdict provides some extra tuples of types that include most numpy types such as int32, int64, float32, etc.

>>> isinstance(np.arange(4)[0], INT_TYPES)
True

The special type lists provided are

ARRAY_TYPES

list, tuple, np.ndarray

BOOL_TYPES

bool, bool_

FLOAT_TYPES

float, float16, float32, float64, float128

INT_TYPES

int, int8, int16, int32, int64, uint8, uint16, uint32, uint64

Phases

Each entry in an instance of OptionsDict is interpreted not as a static value but a sequence of inputs for different “phases” of some operation such as running a Computational Fluid Dynamics (CFD) solver. For example, (by default) a list entry such as

{"PhaseIters": [100, 200]}

means that the setting PhaseIters will take the value 100 for phase 0 (using Python’s 0-based indexing) and 200 for phase 1. In addition, this 200 setting is automatically extended to phases 2, 3, etc. to allow for more consolidated input. If the options instance instead has

{"PhaseIters": 100}

then the value of PhaseIters is 100 for all possible phases.

Note that the duality of this example means that optdict must distinguish between array-like and non-array-like entries, which in some cases can introduce extra considerations. For example, consider a setting called Schedule that for every phase is a list of two ints. Setting a value of [50, 100] will not produce the desired results because it will be interpreted as 50 for phase 0 rather than the full list for all phases. The simplest solution is to use

{"Schedule": [[50, 100]]}

It is also possible to use the listdepth keyword argument to OptionsDict.get_opt() or define Schedule to be special by setting the _listdepth class attribute in a subclass.

class MyOpts(OptionsDict):
    _listdepth = {
        "Schedule": 1
    }

opts = MyOpts(Schedule=[50, 100])
assert opts.get_opt("Schedule", j=0) == [50, 100]

This element-access approach is implemented by the function optitem.getel().

Special Dictionaries

Options in an instance of OptionsDict can also be defined as “special dicts,” of which there are are four types. These work in combination with a run matrix that’s stored in the x attribute of the options instance.

# Define run matrix
x = {
    "mach": [0.5, 0.75, 1.0, 1.25, 1.5],
    "alpha": 0.0,
    "beta": 0.0,
    "arch": ["cas", "rom", "rom", "bro", "sky"],
}
# Define options
opts = OptionsDict({
    "my_expression": {"@expr": "$mach * $mach - 1"},
    "my_constrained_expr": {
        "@cons": {
            "$mach <= 1": 0.0,
            "True": {"@expr": "$mach * $mach - 1"}
        }
    },
    "my_map": {
        "@map": {"cas": 10, "rom": 5, "sky": 20, "_default_": 40},
        "key": "arch"
    },
    "my_raw_value": {
        "@raw": {"@expr": "$mach * $mach - 1"}
    },
})
# Save trajectory
opts.save_x(x)

The @expr tag allows users to define an arbitrary expression with run matrix keys from opts.x denoted using a $ sigil. Users may also assume that numpy has been imported as np. The following example evaluates M21 for case i=3, where mach=1.25.

>>> opts.get_opt("my_expression", i=3)
0.5625

The next type of special dict is the @cons tag, which allows for similar expressions on the left-hand side. The definition for my_constrained_expr above is equivalent to the regular code

if mach <= 1:
    return 0.0
else:
    return mach * mach - 1

Here the expression True serves as an else clause because it is evaluated as elif True.

The third type of special dict is @map, which allows a user to define specific values (or another special dict) based on the value of some other key in opts.x, and the value of that key must be a str.

>>> opts.x["arch"][2]
'rom'
>>> opts.get_opt("my_map", i=2)
5
>>> opts.x["arch"][3]
'bro'
>>> opts.get_opt("my_map", i=3)
40
>>> opts.x["arch"][4]
'sky'
>>> opts.get_opt("my_map", i=4)
20

Finally, a @raw value allows users to specify a raw value that might otherwise get expanded.

>>> opts.get_opt("my_raw_value", i=1)
{"@expr": "$mach * $mach - 1"}

These special dicts may also recurse.

Class Attributes

Below is a discussion of the data attributes of the OptionsDict class and their purposes. The class attributes, despite having names starting with _, are intended for use when developers or users create subclasses of OptionsDict.

The class attributes naturally combine, so that second- or higher-order subclasses need not repeat attributes like _optlist. So in the example

class MyOpts1(OptionsDict):
    _optlist = {"a"}
    _opttypes = {"a": str}

class MyOpts2(MyOpts1):
    _optlist = {"b"}
    _opttypes = {"b": (int, float)}

instances of MyOpts2 will allow options named either a or b and check the types of both, but options with any other name will not be allowed in such MyOpts2 instances.

OptionsDict._optlist: set

If nonempty, a set of allowed option names.

See also:
OptionsDict._opttypes: dict

Specified type or tuple[type] that restricts the allowed type for each specified option. For example

_opttypes = {
    "a": str,
    "b": (int, float)
}

will require the two tests

isinstance(opts["a"], str)
isinstance(opts["b"], (int, float))

to both return True.

See also:
OptionsDict._optmap: dict[str]

Dictionary of aliases where the key is the alias and the value is the full name of an option. In other words, any attempt to get or set an option key will really affect _optmap.get(key, key).

class MyOpts(OptionsDict):
    _optlist = {"Alpha", "Beta"}
    _optmap = {
        "a": "Alpha",
        "A": "Alpha",
        "b": "Beta",
        "B": "Beta"
    }

This class has two options, "Alpha" and "Beta", but six ways to set them.

>>> opts = MyOpts(a=3)
>>> opts
{'Alpha': 3}
See also:
OptionsDict._optvals: dict[set]

Dictionary of specific values allowed for certain options. This attribute is mostly suited for string options, for which a limited set of possible values is more likely.

When a user tries to set a value that’s not in the possibilities specified in _optvals, they will also see a helpful warning of the closest allowed option(s).

The canonical type for the values in _optvals is set, but a tuple may be better suited when only a few values are permitted.

See also:
OptionsDict._optlistdepth: dict[int]

List depth for named options. If _optlistdepth[opt] is 1, then a list for opt is interpreted as a scalar.

See also:
OptionsDict._optring: dict[bool]

A dict of whether each option should be treated as a “ring”, meaning a list is repeated in full. If _optring[opt] is true, then opt is treated as a ring. Otherwise the last entry will be repeated. The default is False, but this can be overridden using _optlist["_default_"] = True.

See also:
OptionsDict._rc: dict

Default value for any option

See also:
OptionsDict._xoptkey: str

Name of option (including its aliases) for which the value (which must be a list, set, or tuple) is appended to an instance’s _xoptlist.

In other words, if _xoptkey is "Components", and opts["Components"] is ["a", "b", "c"], then a, b, and c will be allowed as option names for opts.

OptionsDict._sec_cls: dict[type]

Dictionary of classes to use as type for named subsections

See also:
OptionsDict._sec_cls_opt: str

Name of option to use as determining which class to use from _sec_cls_optmap to initialize each subsection.

A typical value for this option is "Type". If this attribute is set to None, then no value-dependent subsection class conversions are attempted.

OptionsDict._sec_cls_optmap: dict[type]

Dictionary of classes to use to convert each subsection according to its base value of of _sec_cls_opt.

This attribute is used if some sections should be converted to different types (for example force & moment options vs line load options) depending on their contents.

See also:
OptionsDict._sec_prefix: dict[str]

Optional prefixes to use for each option in a subsection controlled by _sec_cls.

See also:
OptionsDict._sec_initfrom: dict[str]

If used with _sec_cls, sections will be initialized with values from a parent section named in this attribute.

OptionsDict._sec_parent: dict

Defines some subsections to fall back to either their parent section or another subsection for default values, before trying locally defined defaults.

Can be either -1 (for parent section) or str

OptionsDict.__slots__: tuple[str]

Tuple of attributes allowed in instances of OptionsDict. This prevents users from setting arbitrary attributes of OptionsDict instances.

When subclassing OptionsDict, this behavior will go away unless the following syntax is used:

class MyOpts(OptionsDict):
    __slots__ = tuple()

Alternatively, developers may allow specified additional slots by listing those in a tuple as a class attribute of the subclass.

OptionsDict._rst_types: dict[str]

Prespecified string to use as the type and/or default value for automatic property get/set functions. A default can be constructed based on OptionsDict._opttypes.

See also:
OptionsDict._rst_descriptions: dict[str]

Documentation string used to describe one or more options, to be used in automatic property get/set functions.

See also:
class cape.optdict.OptionsDict(*args, **kw)

Advanced dict-based options interface

Call:
>>> opts = OptionsDict(fjson, **kw)
>>> opts = OptionsDict(mydict, **kw)
Inputs:
fjson: str

Name of JSON file to read

mydict: dict | OptionsDict

Another dict instance

_name: {None} | str

Name to use in error messages and warnings

_x: {None} | dict

Supporting values such as run matrix

_warnmode: {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

_warnmode_iname: {_warnmode} | 0 | 1 | 2 | 3

Warning mode for checking input option names

_warnmode_itype: {_warnmode} | 0 | 1 | 2 | 3

Warning mode for checking input value and type

_warnmode_oname: {_warnmode} | 0 | 1 | 2 | 3

Warning mode for checking output option names

_warnmode_otype: {_warnmode} | 0 | 1 | 2 | 3

Warning mode for checking output value and type

kw: dict

Keyword arguments interpreted as option/value pairs

Outputs:
opts: OptionsDict

Options interface

Slots:
opts.x: None | dict

Supporting values such as run matrix

opts._xoptlist: None | set

Option names specifically allowed for this instance

opts._xopttypes: dict

Type or tuple of types allowed for some or all options

opts._xoptvals: dict

Instance-specific values allowed for some or all options

Versions:
  • 2021-12-05 @ddalle: v0.1; started

  • 2021-12-06 @ddalle: v1.0

  • 2022-09-20 @ddalle: v1.1; get_opt() w/ x

  • 2022-09-24 @ddalle: v1.2: _warnmode

  • 2022-09-30 @ddalle: v1.3: _rc and four warnmodes

classmethod add_extender(opt: str, prefix=None, name=None, doc=True)

Add extender method for option opt

For example cls.add_extender("a") will add a function add_a(), which has a signatures like OptionsDict.extend_opt() except that it doesn’t have the opt input.

Call:
>>> cls.add_extender(opt, prefix=None, name=None)
Inputs:
cls: type

A subclass of OptionsDict

opt: str

Name of option

prefix: {None} | str

Optional prefix in method name

name: {opt} | str

Alternate name to use in name of get and set functions

doc: {True} | False

Whether or not to add docstring to getter function

Versions:
  • 2022-10-14 @ddalle: v1.0

classmethod add_extenders(optlist, prefix=None, name=None, doc=True)

Add list of property extenders with common settings

Call:
>>> cls.add_extenders(optlist, prefix=None, name=None)
Inputs:
cls: type

A subclass of OptionsDict

optlist: list[str]

Name of options to process

prefix: {None} | str

Optional prefix, e.g. opt="a", prefix="my" will add functions get_my_a() and set_my_a()

name: {opt} | str

Alternate name to use in name of get and set functions

doc: {True} | False

Whether or not to add docstring to functions

Versions:
  • 2022-10-14 @ddalle: v1.0

classmethod add_getter(opt: str, prefix=None, name=None, doc=True)

Add getter method for option opt

For example cls.add_property("a") will add a function get_a(), which has a signatures like OptionsDict.get_opt() except that it doesn’t have the opt input.

Call:
>>> cls.add_getter(opt, prefix=None, name=None)
Inputs:
cls: type

A subclass of OptionsDict

opt: str

Name of option

prefix: {None} | str

Optional prefix in method name

name: {opt} | str

Alternate name to use in name of get and set functions

doc: {True} | False

Whether or not to add docstring to getter function

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

  • 2022-10-03 @ddalle: v1.1; docstrings

  • 2022-10-10 @ddalle: v1.2; metadata, try/catch

classmethod add_getters(optlist, prefix=None, name=None, doc=True)

Add list of property getters with common settings

Call:
>>> cls.add_getters(optlist, prefix=None, name=None)
Inputs:
cls: type

A subclass of OptionsDict

optlist: list[str]

Name of options to process

prefix: {None} | str

Optional prefix, e.g. opt="a", prefix="my" will add functions get_my_a() and set_my_a()

name: {opt} | str

Alternate name to use in name of get and set functions

doc: {True} | False

Whether or not to add docstring to functions

Versions:
  • 2022-10-14 @ddalle: v1.0

classmethod add_properties(optlist, prefix=None, name=None, doc=True)

Add list of getters and setters with common settings

Call:
>>> cls.add_properties(optlist, prefix=None, name=None)
Inputs:
cls: type

A subclass of OptionsDict

optlist: list[str]

Name of options to process

prefix: {None} | str

Optional prefix, e.g. opt="a", prefix="my" will add functions get_my_a() and set_my_a()

name: {opt} | str

Alternate name to use in name of get and set functions

doc: {True} | False

Whether or not to add docstring to functions

Versions:
  • 2022-10-14 @ddalle: v1.0

classmethod add_property(opt: str, prefix=None, name=None, doc=True)

Add getter and setter methods for option opt

For example cls.add_property("a") will add functions get_a() and set_a(), which have signatures like OptionsDict.get_opt() and OptionsDict.set_opt() except that they don’t have the opt input.

Call:
>>> cls.add_property(opt, prefix=None, name=None)
Inputs:
cls: type

A subclass of OptionsDict

opt: str

Name of option

prefix: {None} | str

Optional prefix, e.g. opt="a", prefix="my" will add functions get_my_a() and set_my_a()

name: {opt} | str

Alternate name to use in name of get and set functions

doc: {True} | False

Whether or not to add docstring to functions

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

  • 2022-10-03 @ddalle: v1.1; docstrings

  • 2022-10-10 @ddalle: v1.2; metadata, try/catch

classmethod add_setter(opt: str, prefix=None, name=None, doc=True)

Add getter and setter methods for option opt

For example cls.add_property("a") will add a function set_a(), which has a signature like OptionsDict.set_opt() except that it doesn’t have the opt input.

Call:
>>> cls.add_setter(opt, prefix=None, name=None)
Inputs:
cls: type

A subclass of OptionsDict

opt: str

Name of option

prefix: {None} | str

Optional prefix for method name

name: {opt} | str

Alternate name to use in name of get and set functions

doc: {True} | False

Whether or not to add docstring to setter function

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

  • 2022-10-03 @ddalle: v1.1; docstrings

  • 2022-10-10 @ddalle: v1.2; metadata, try/catch

classmethod add_setters(optlist, prefix=None, name=None, doc=True)

Add list of property setters with common settings

Call:
>>> cls.add_setters(optlist, prefix=None, name=None)
Inputs:
cls: type

A subclass of OptionsDict

optlist: list[str]

Name of options to process

prefix: {None} | str

Optional prefix, e.g. opt="a", prefix="my" will add functions get_my_a() and set_my_a()

name: {opt} | str

Alternate name to use in name of get and set functions

doc: {True} | False

Whether or not to add docstring to functions

Versions:
  • 2022-10-14 @ddalle: v1.0

add_xopt(opt: str)

Add an additional instance-specific allowed option name

Call:
>>> opts.add_xopt(opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option

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

add_xopts(optlist)

Add several instance-specific allowed option names

Call:
>>> opts.add_xopts(optlist)
Inputs:
opts: OptionsDict

Options interface

optlist: list | set | tuple

List of options to combine

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

add_xopttype(opt: str, opttype)

Add instance-specific allowed type(s) for opt

Call:
>>> opts.add_xopttype(opt, opttype)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option

opttype: type | tuple

Type or tuple thereof of allowed type(s) for opt

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

apply_optmap(opt: str)

Replace opt with opt1 if suggested using the _optmap

Call:
>>> opt1 = opts.apply_optmap(opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to test

Outputs:
opt1: str

Final name of option, opt or a standardized alias

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

  • 2024-10-10 @ddalle: v1.1; add _ignore_case option

check_opt(opt: str, val, mode=None, out=False) bool

Check if val is consistent constraints for option opt

Call:
>>> valid, v2 = opts.check_opt(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

out: True | {False}

Option to use output/input warning modes

Outputs:
valid: True | False

Whether or not value val is allowed for option opt

v2: any

Either val or converted to new class

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

  • 2022-09-30 @ddalle: v2.0; expanded warnmodes

check_optname(opt: str, mode=None) bool

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: str, val, mode=None) bool

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

check_optval(opt: str, val, mode=None) bool

Check if val is an acceptable value for option opt

No checks are performed val if it is a special dict that cannot be evaluated to a single value.

Call:
>>> valid = opts.check_optval(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 value val is allowed for option opt

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

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

copy()

Create a copy of an options interface

Call:
>>> opts1 = opts.copy()
Inputs:
opts: OptionsDict

Options instance

Outputs:
opts1: OptionsDict

Deep copy of options instance

Versions:
  • 2019-05-10 @ddalle: v1.0 (odict)

  • 2022-10-03 @ddalle: v1.0

describe() str

Generate a description of an options instance in text form

Call:
>>> txt = options.describe()
Inputs:
options: OptionsDict

Options instance

Outputs:
txt: str

Free-form text description of options

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

describe_opt(opt: str) str

Create a description for an option

Call:
>>> txt = self.describe_opt(opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option

Outputs:
txt: str

Description of the value of opt

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

expand_jsonfile(fname: str, **kw)

Recursively read a JSON file

Call:
>>> opts.expand_jsonfile(fname)
Inputs:
opts: OptionsDict

Options interface

fname: str

Name of JSON file to read

Attributes:
opts.lines: list[str]

Original code with comments

opts.code: list[str]

Original code with comments stripped

opts.filenames: list[str]

List of one or more JSON file names read

opts.linenos: list[int]

Line number of each line within original file

opts.filenos: list[int]

Index of file from which each line came

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

extend_opt(opt: str, val, mode=None)

Extend an array-like or dict-like option

This function allows for targeted additions to list and dict values for opt without redefining the entire entry.

Call:
>>> opts.extend_opt(opt, val, mode=None)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to extend

val: any

Value to append to opts[opt]. If opts[opt] is a dict, val must also be a dict

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

Versions:
  • 2022-10-14 @ddalle: v1.0

classmethod genr8_extender_docstring(opt: str, name, prefix, indent=8, tab=4)

Create automatic docstring for extender function

Call:
>>> txt = cls.genr8_extender_docstring(opt, name, pre, **kw)
Inputs:
cls: type

A subclass of OptionsDict

opt: str

Name of option

name: {opt} | str

Alternate name to use in name of functions

pre: None | str

Optional prefix, e.g. opt="a", prefix="my" will add functions get_my_a() and set_my_a()

indent: {8} | int >= 0

Number of spaces in lowest-level indent

tab: {4} | int > 0

Number of additional spaces in each indent

Outputs:
txt: str

Contents for set_{opt} function docstring

Versions:
  • 2022-10-03 @ddalle: v1.0

classmethod genr8_getter_docstring(opt: str, name, prefix, **kw)

Create automatic docstring for getter function

Call:
>>> txt = cls.genr8_getter_docstring(opt, name, prefx, **kw)
Inputs:
cls: type

A subclass of OptionsDict

opt: str

Name of option

name: {opt} | str

Alternate name to use in name of functions

prefix: None | str

Optional prefix, e.g. opt="a", prefix="my" will add functions get_my_a() and set_my_a()

indent: {8} | int >= 0

Number of spaces in lowest-level indent

tab: {4} | int > 0

Number of additional spaces in each indent

extra_args: {None} | dict[tuple]

Dictionary of args and their types and descriptions

Outputs:
txt: str

Contents for get_{opt} function docstring

Versions:
  • 2022-10-03 @ddalle: v1.0

  • 2023-04-20 @ddalle: v1.1; extra inputs

genr8_opt_query(opt: str, val: Any) str

Generate a query to ask about the value of an option

Call:
>>> txt = opts.genr8_opt_query(opt, val)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option

val: any

Value of the option

Outputs:
txt: str

Text of query

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

genr8_opt_response(opt: str, val: Any) str

Generate a response to describe how to set a value

This will look something like

Set

```json
        "Reports": [
            "report1",
            "report2"
        ]
```

in the `"Report"` section or set

```python
opts["Report"]["Reports"] = [
    "case",
    "mach"
]
```

in Python.
Call:
>>> txt = opts.present_opt(opt, val)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option

val: any

Value of the option

Outputs:
txt: str

Text of representation

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

genr8_prompts(maxdepth: int = 1) list

Create list of prompts and responses for options interface

Call:
>>> prompts = opts.genr8_prompts(maxdepth=1)
Inputs:
opts: OptionsDict

Options interface

maxdepth: {2} | int

Maximum depth of OptionsDict to show

Outputs:
prompts: list[str, :class;`str`]

List of questions and answers about the value of each key in opts, recursivelyz

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

genr8_query() str

Generate a question about the contents of opts

Call:
>>> txt = options.genr8_query()
Inputs:
options: OptionsDict

Options instance

Outputs:
txt: str

A question whose answer is the contents of opts

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

genr8_response(maxdepth: int = 1) str

Create a response about how to create opts

Call:
>>> txt = opts.genr8_response(maxdepth=1)
Inputs:
opts: OptionsDict

Options interface

maxdepth: {1} | int

Maximum depth of OptionsDict to show

Outputs:
txt: str

Text representation of some portion of opts

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

genr8_section_md() str

Create a section name for use in descriptive text

Call:
>>> section = opts.genr8_section_md()
Inputs:
opts: OptionsDict

Options interface

Outputs:
section: str

Name of section or "top level"

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

classmethod genr8_setter_docstring(opt: str, name, prefix, indent=8, tab=4)

Create automatic docstring for setter function

Call:
>>> txt = cls.genr8_setter_docstring(opt, name, prefx, **kw)
Inputs:
cls: type

A subclass of OptionsDict

opt: str

Name of option

name: {opt} | str

Alternate name to use in name of functions

prefx: None | str

Optional prefix, e.g. opt="a", prefix="my" will add functions get_my_a() and set_my_a()

indent: {8} | int >= 0

Number of spaces in lowest-level indent

tab: {4} | int > 0

Number of additional spaces in each indent

Outputs:
txt: str

Contents for set_{opt} function docstring

Versions:
  • 2022-10-03 @ddalle: v1.0

get_opt(opt: str, j=None, i=None, **kw)

Get named property, by phase, case index, etc.

Call:
>>> val = opts.get_opt(opt, j=None, i=None, **kw)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to access

j: {None} | int

Phase index; use None to just return v

i: {None} | int | np.ndarray

opts.x index(es) to use with @expr, @map, etc.

vdef: {None} | object

Manual default

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

ring: {opts._optring[key]} | True | False

Override option to loop through phase inputs

listdepth: {0} | int > 0

Depth of list to treat as a scalar

x: {None} | dict

Ref conditions to use with @expr, @map, etc.; often a run matrix; used in combination with i

sample: {True} | False

Apply j, i, and other settings recursively if output is a list or dict

Outputs:
val: object

Value of opt for given conditions, in the simplest case opts[opt]

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

  • 2023.06-13 @ddalle: v1.1; implement ring opt

  • 2023-06-14 @ddalle: v1.2; enforce listdepth fully

get_opt_default(opt: str)

Get default value for named option

Call:
>>> vdef = opts.get_opt_default(self, opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to access

Outputs:
vdef: object

Default value if any, else None

Versions:
  • 2022-10-30 @ddalle: v1.0

get_subkey_base(sec: str, key: str, **kw) str

Get root value of cascading subsection key

For example, with the options

>>> opts = OptionsDict({
    "A": {"Type": "BaseType"},
    "B": {"Type": "A"},
    "C": {"Type": "C"}
})
>>> opts.get_subkey_base("C", "Type")
'BaseType'

The function will find the deepest-level parent of section "C" using "Type" as the name of the parent section. When no parents remain, it will return either the final "Type" value or the name of the last parent. The other possibility is

>>> opts = OptionsDict({
    "A": {},
    "B": {"Type": "A"},
    "C": {"Type": "C"}
})
>>> opts.get_subkey_base("C", "Type")
'A'
Call:
>>> base = opts.get_subkey_base(sec, key, **kw)
Inputs:
opts: OptionsDict

Options interface

sec: str

Name of subsection to access

key: {"Type"} | str

Key in opts[sec] that defines parent of sec

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:
base: str

Value of key from deepest parent of sec found

Versions:
  • 2022-11-06 @ddalle: v1.0

get_subopt(sec: str, opt: str, key='Type', **kw)

Get subsection option, applying cascading definitions

This function allows for cascading section definitions so that common settings can be defined in a parent section only once.

Examples:
>>> opts = OptionsDict(
    A={"a": 1, "b": 2},
    B={"c": 3, "Type": "A"},
    C={"a": 17, "Type": "B"})
>>> opts.get_subopt("C", "a")
17
>>> opts.get_subopt("C", "b")
2
>>> opts.get_subopt("C", "c")
3
Call:
>>> v = opts.get_subopt(sec, opt, key="Type", **kw)
Inputs:
opts: OptionsDict

Options interface

sec: str

Name of subsection to access

opt: str

Name of option to access

key: {"Type"} | str

Key in opts[sec] that defines parent of sec

j: {None} | int

Phase index; use None to just return v

i: {None} | int | np.ndarray

opts.x index(es) to use with @expr, @map, etc.

vdef: {None} | object

Manual default

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

ring: {opts._optring[key]} | True | False

Override option to loop through phase inputs

listdepth: {0} | int > 0

Depth of list to treat as a scalar

x: {None} | dict

Ref conditions to use with @expr, @map, etc.; often a run matrix; used in combination with i

sample: {True} | False

Apply j, i, and other settings recursively if output is a list or dict

Outputs:
val: object

Value of opt for given conditions, in the simplest case simply opts[sec][opt]

Versions:
  • 2022-10-05 @ddalle: v1.0

  • 2022-11-06 @ddalle: v1.1; special opt==key case

classmethod getcls_name() str

Get defined name for an OptionsDict subclass

Call:
>>> name = cls.getcls_name()
Inputs:
cls: type

A subclass of OptionsDict

Outputs:
name: str

Name from either opts or its class

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

getx_aliases(opt: str) set

Get list of aliases for an option

Call:
>>> aliases = opts.getx_aliases(opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

(Final) option name

Outputs:
aliases: set[str]

Set of unique aliases for opt, including opt

Versions:
  • 2022-11-04 @ddalle: v1.0

classmethod getx_cls_dict(attr: str)

Get combined dict for cls and its bases

This allows a subclass of OptionsDict to only add to the _opttypes or _sec_cls attribute rather than manually include contents of all the bases.

Call:
>>> clsdict = cls.getx_cls_dict(attr)
Inputs:
cls: type

A subclass of OptionsDict

attr: str

Name of class attribute to search

Outputs:
clsdict: dict

Combination of getattr(cls, attr) and getattr(base, attr) for each base in cls.__bases__, etc.

Versions:
  • 2022-10-24 @ddalle: v1.0

classmethod getx_cls_key(attr: str, key: str, vdef=None)

Access key from a dict class attribute

This will look in the bases of cls if getattr(cls, attr) does not have key. If cls is a subclass of another OptionsDict class, it will search trhough the bases of cls until the first time it finds a class attribute attr that is a dict containing key.

Call:
>>> v = cls.getx_cls_key(attr, key, vdef=None)
Inputs:
cls: type

A subclass of OptionsDict

attr: str

Name of class attribute to search

key: str

Key name in cls.__dict__[attr]

vdef: {None} | object

Default value to use if not found in class attributes

Outputs:
v: None | ojbect

Any value, None if not found

Versions:
  • 2022-10-01 @ddalle: v1.0

classmethod getx_cls_set(attr: str)

Get combined set for cls and its bases

This allows a subclass of OptionsDict to only add to the _optlist attribute rather than manually include the _optlist of all the bases.

Call:
>>> v = cls.getx_cls_set(attr)
Inputs:
cls: type

A subclass of OptionsDict

attr: str

Name of class attribute to search

Outputs:
v: set

Combination of getattr(cls, attr) and getattr(base, attr) for each base in cls.__bases__, etc.

Versions:
  • 2022-10-04 @ddalle: v1.0

getx_i(i=None)

Get run matrix index to use for option expansion

This function returns None only if i is None and opts.i is also None.

Call:
>>> i1 = opts.getx_i(i=None)
Inputs:
opts: OptionsDict

Options interface

i: {None} | int | np.ndarray

Optional mask of cases to sample

Outputs:
i1: opts.i | i

i if other than None; else opts.i

Versions:
  • 2023-05-02 @ddalle: v1.0

getx_listdepth(opt: str) int

Get list depth for a specified key

Call:
>>> depth = opts.getx_listdepth(opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to query

Outputs:
depth: {0} | int >= 0

Depth of expected list-type values, for example if 1 a list is expected for this option

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

  • 2022-09-18 @ddalle: v1.1; simple dict

  • 2023-06-13 @ddalle: v1.2; use getx_cls_dict()

getx_name() str

Get saved name for OptionsDict instance

Call:
>>> name = opts.getx_name()
Inputs:
opts: OptionsDict

Options instance

Outputs:
name: str

Name from either opts or its class

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

getx_opt_parent(opt: str)

Get value from fall-back opts._xparent

Call:
>>> v = opts.getx_opt_parent(opt, **kw)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to access

Outputs:
val: object

Value of opt for given conditions, in the simplest case simply opts[opt]

Versions:
  • 2022-12-02 @ddalle: v1.0

getx_optinfo(opt: str, **kw) str

Create output description for option

Call:
>>> txt = opts.getx_optinfo(opt, **kw)
Inputs:
opts: OptionsDict

Options interface

opt: str

Option name

indent: {8} | int >= 0

Number of spaces in lowest-level indent

tab: {4} | int > 0

Number of additional spaces in each indent

v: True | {False}

Verbose flag, returns show_option() output

Outputs:
txt: str

Text for opt description

Versions:
  • 2023-06-14 @aburkhea: v1.0

  • 2023-06-22 @ddalle: v1.1
    • default indent 8->0

    • name help_opt() -> getx_optinfo()

getx_optlist() set

Get list of explicitly named options

Call:
>>> optlist = opts.getx_optlist()
Inputs:
opts: OptionsDict

Options interface

Outputs:
optlist: set

Allowed option names; if empty, all options allowed

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

  • 2022-10-04 @ddalle: v2.0: recurse throubh bases

getx_optring(opt: str) bool

Check if opt should be looped

If True, cycle through entire list. If False, just repeat the final entry.

Call:
>>> ring = opts.getx_optring(opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to query

Outputs:
depth: {0} | int >= 0

Depth of expected list-type values, for example if 1 a list is expected for this option

Versions:
  • 2023-06-13 @ddalle: v1.0

getx_opttype(opt: str)

Get allowed type(s) for opt

Call:
>>> opttype = opts.getx_opttype(opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option

Outputs:
opttype: None | type | tuple

Type or tuple thereof of allowed type(s) for opt

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

getx_optvals(opt: str)

Get set of acceptable values for option opt

Call:
>>> vals = opts.getx_optvals(opt)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option

Outputs:
vals: None | set

Allowed values for option opt

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

getx_xvals(col: str, i=None)

Get values for one run matrix key

Call:
>>> v = opts.getx_xvals(col, i=None)
Inputs:
opts: OptionsDict

Options interface

col: str

Name of opts.x key to sample

i: {None} | int | np.ndarray

Optional mask of cases to sample

Outputs:
v: any

Values of opts.x or opts.x[i], usually an array

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

help_opt(opt: str, **kw)

Open interactive help for option opt

Call:
>>> opts.help_opt(opt, **kw)
Inputs:
opts: OptionsDict

Options interface

opt: str

Option name

indent: {8} | int >= 0

Number of spaces in lowest-level indent

tab: {4} | int > 0

Number of additional spaces in each indent

v: {True} | False

Verbose flag, returns show_option output

Versions:
  • 2023-06-22 @ddalle: v1.0

init_post()

Custom function to run at end of __init__()

This function can be used on subclasses of OptionsDict to do extra special initiation without needing to rewrite the instantiation function.

The OptionsDict.init_post() function performs no actions, but a subclass can redefine this function to do custom tasks for every new instance of that class.

Call:
>>> opts.init_post()
Inputs:
opts: OptionsDict

Options interface

Versions:
  • 2022-10-04 @ddalle: v1.0

init_section(cls, sec=None, **kw)

Initialize a generic section

Call:
>>> opts.init_section(cls, sec=None, **kw)
Inputs:
opts: odict

Options interface

cls: type

Class to use for opts[sec]

sec: {cls.__name__} | str

Specific key name to use for subsection

initfrom: {None} | str

Other subsection from which to inherit defaults

prefix: {None} | str

Prefix to add at beginning of each key

Versions:
  • 2021-10-18 @ddalle: v1.0 (odict)

  • 2022-10-10 @ddalle: v1.0; append name

  • 2022-12-03 @ddalle: v1.1; parent -> initfrom

init_sections()

Initialize standard sections for a class

Call:
>>> opts.init_sections()
Inputs:
opts: odict

Options interface

Versions:
  • 2022-10-10 @ddalle: v1.0

  • 2022-12-03 @ddalle: v1.1; parent -> initfrom

preprocess_dict(a: dict)

Perform custom preprocessing steps before set_opt()

Call:
>>> opts.preprocess_dict(a)
Inputs:
opts: OptionsDict

Options interface

a: dict

Dictionary of options to merge into opts

Versions:
  • 2023-06-22 @ddalle: v1.0

present(maxdepth: int = 2)

Present the value in markdown to specified depth

Call:
>>> txt = opts.present(maxdepth=2)
Inputs:
opts: OptionsDict

Options interface

maxdepth: {2} | int

Maximum depth of OptionsDict to show

Outputs:
txt: str

Text representation of some portion of opts

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

present_opt(opt: str, val: Any) str

Present the value of an option

This will look something like

```json
    "Reports": [
        "report1",
        "report2"
    ]
```
Call:
>>> txt = opts.present_opt(opt, val)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option

val: any

Value of the option

Outputs:
txt: str

Text of representation

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

classmethod print_rst(**kw) str

Print documentation to reST format for all available options

Call:
>>> txt, children = cls.print_rst(**kw)
Inputs:
cls: type

A subclass of OptionsDict

recurse: True | {False}

Whether to include subsection class options

narrow: True``| {``False}

Whether to only include options new to this class

depth: {0} | int

Section depth level to determine format of reST header

v: True | {False}

Option to use more verbose format for each option

recurse_seccls: {recurse} | True | False

Option to recurse into cls._sec_cls

recurse_clsmap: {recurse} | True | False

Option to recurse into cls._sec_clsmap

Outputs:
txt: str

Formatted text of all options

children: dict[type]

Child subsections not included in txt

Versions:
  • 2023-07-12 @ddalle: v1.0

  • 2023-07-14 @ddalle: v1.1; add children output

classmethod promote_sections(skip=[])

Promote all sections based on class attribute _sec_cls

Call:
>>> cls.promote_sections(skip=[])
Inputs:
cls: type

Parent class

skip: {[]} | list

List of sections to skip

Versions:
  • 2022-10-23 @ddalle: v1.0

classmethod promote_subsec(cls2, sec=None, skip=[], **kw)

Promote all methods of a subsection class to parent class

Methods of parent class will not be overwritten

Call:
>>> promote_subsec(cls1, cls2, sec=None, skip=[], **kw)
Inputs:
cls: type

Parent class

cls2: type

Subsection class

sec: {None} | str

Name of subsection, defaults to cls2.__name__

skip: {[]} | list

List of methods from cls2 not to add to cls1

init: {True} | False

If True, initialize subsection when cls1 methods used

parent: {None} | str

Name of section from which to get default settings

Versions:
  • 2022-10-14 @ddalle: v1.0

read_jsonfile(fname: str)

Read a JSON file (w/ comments and includes)

Call:
>>> opts.read_jsonfile(fname)
Inputs:
opts: OptionsDict

Options interface

fname: str

Name of JSON file to read

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

  • 2021-12-14 @ddalle: v2.0; helpful JSON errors

  • 2024-12-20 @ddalle: v2.1; leave JSON file attrs

read_yamlfile(fname: str)

Read a YAML file

Call:
>>> opts.read_yamlfile(fname)
Inputs:
opts: OptionsDict

Options interface

fname: str

Name of JSON file to read

Versions:
  • 2024-10-09 @ddalle: v1.0

sample_dict(v: dict, j=None, i=None, _depth=0, **kw)

Expand a value, selectin phase, applying conditions, etc.

Call:
>>> val = opts.expand_val(v, j=None, i=None, **kw)
Inputs:
opts: OptionsDict

Options interface

v: dict | list[dict]

Initial raw option value

f: True | {False}

Force j and i to be integers

j: {None} | int

Phase index; use None to just return v

i: {None} | int | np.ndarray

opts.x index(es) to use with @expr, @map, etc.

vdef: {None} | object

Manual default

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

ring: {opts._optring[key]} | True | False

Override option to loop through phase inputs

listdepth: {0} | int > 0

Depth of list to treat as a scalar

x: {None} | dict

Ref conditions to use with @expr, @map, etc.; often a run matrix; used in combination with i

sample: {True} | False

Apply j, i, and other settings recursively if output is a list or dict

Outputs:
val: dict

Value of opt for given conditions, in the simplest case v, perhaps v[j]

Versions:
  • 2023-05-15 @ddalle: v1.0

  • 2023-06-14 @ddalle: v1.1; apply _rc if possible

save_x(x: dict, recursive=True)

Set full conditions dict

Call:
>>> opts.save_x(x, recursive=True)
Inputs:
opts: OptionsDict

Options interface

x: dict

Supporting conditions or run matrix

recursive: {True} | False

Option ro apply x to subsections of opts

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

  • 2022-10-28 @ddalle: v1.1; recursive

set_opt(opt: str, val, j=None, mode=None)

Set value of one option

This command is similar to opts[opt] = val, but with checks performed prior to assignment.

Call:
>>> opts.set_opt(val, j=None, mode=None)
Inputs:
opts: OptionsDict

Options interface

opt: str

Name of option to set

val: any

Value to save in opts[opt]

j: {None} | int

Phase index; use None to just return v

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

listdepth: {0} | int > 0

Depth of list to treat as a scalar

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

  • 2022-09-30 @ddalle: v1.1: _process_lastwarn()

set_opts(a: dict, mode=None)

Set values of several options

This command is similar to opts.update(a), but with checks performed prior to assignment.

Call:
>>> opts.set_opts(a, mode=None)
Inputs:
opts: OptionsDict

Options interface

a: dict

Dictionary of options to merge into opts

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

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

setx_i(i=None, recursive=True)

Set current default run matrix index

Call:
>>> opts.setx_i(i=None)
Inputs:
opts: OptionsDict

Options interface

i: {None} | int

Run matrix index

recursive: {True} | False

Option ro apply x to subsections of opts

Versions:
  • 2023-05-02 @ddalle: v1.0

  • 2023-06-02 @ddalle: v1.1; recursive

setx_parent(parent: dict)

Set an object to define fall-back values

This takes precedence over _rc

Call:
>>> opts.setx_parent(parent)
Inputs:
opts OptionsDict

Options interface

parent: dict | OptionsDict

Fall-back options dict

Versions:
  • 2022-12-02 @ddalle: v1.0

show_opt(opt: str, **kw)

Display verbose help information for opt

Call:
>>> txt = opts.show_opt(opt, **kw)
Inputs:
opts: OptionsDict

Options interface

opt: str

Option name

indent: {0} | int >= 0

Number of spaces in lowest-level indent

tab: {4} | int > 0

Number of additional spaces in each indent

c: {-} | "=" | "*” | "^"

Character to use for reST title lines

overline: True | {False}

Option to have overline and underline for title

underline: {True} | False

Option to print opt as a reST section title

Outputs:
txt: str

Text of opt help message

Versions:
  • 2023-06-14 @aburkhea: v1.0

  • 2023-06-22 @ddalle: v2.0; only show nontrivial items

write_jsonfile(fname: str, **kw)

Write options to JSON file

Call:
>>> opts.write_jsonfile(fname, indent=4)
Inputs:
opts: OptionsDict

Options interface

fname: str

Name of file to write

indent: {4} | int

Number of spaces in indent

Versions:
  • 2024-08-29 @ddalle: v1.0

write_jsonl_training(fname: str, maxdepth: int = 2)

Create a JSONL file for fine-tuning LLM based on these opts

Call:
>>> opts.write_jsonl_training(fname, maxdepth=2)
Inputs:
opts: OptionsDict

Options interface

fname: str

Name of JSON-lines file to write

maxdepth: {2} | int

Maximum depth of OptionsDict to show

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

write_yamlfile(fname: str, **kw)

Write options to YAML file

Call:
>>> opts.write_yamlfile(fname, indent=4)
Inputs:
opts: OptionsDict

Options interface

fname: str

Name of file to write

indent: {4} | int

Number of spaces in indent

Versions:
  • 2024-10-09 @ddalle: v1.0

cape.optdict.genr8_rst_type_list(opttypes, vdef=None, listdepth=0)

Format a string to represent one or more types in reST

Examples of potential output:

Call:
>>> txt = genr8_rst_type_list(opttype, vdef=None)
>>> txt = genr8_rst_type_list(opttypes, vdef=None)
Inputs:
opttype: type

Single allowed type

opttypes: tuple[type]

Tuple of allowed types

vdef: {None} | object

Default value

listdepth: {0} | 1

List depth; serves as flag that function returns list

Outputs:
txt: str

reStructuredText representation of opttypes

Versions:
  • 2022-10-03 @ddalle: v1.0

  • 2023-04-20 @ddalle: v1.1; add listdepth

  • 2023-07-12 @ddalle: v1.2; shorten some type descriptors

  • 2023-07-16 @ddalle: v2.0; catch INT_TYPES + FLOAT_TYPES

cape.optdict.genr8_rst_value_list(optvals, vdef=None)

Format a string to represent several possible values in reST

Call:
>>> txt = genr8_rst_value_list(optvals, vdef=None)
Inputs:
optvals: set | iterable

Possible values for some parameter to take

vdef: {None} | object

A default value to highlight with {} characters

Outputs:
txt: str

reStructuredText representation of optvals

Versions:
  • 2022-10-02 @ddalle: v1.0

cape.optdict.normalize_optname(opt: str) str

Normalize option name to a valid Python variable name

For example, you can have an option name "@1d+2" but not a method called get_@1d+2(). This function will normalize the above to d2 by eliminating non-word characters and stripping leading digits. This is so that OptionsDict.add_property() will suggest a valid function name get_d2().

Call:
>>> name = normalize_optname(opt)
Inputs:
opt: str

Option name

Outputs:
name: str

Normalized version, valid Python expression

Versions:
  • 2022-10-02 @ddalle: v1.0

cape.optdict.promote_subsec(cls1, cls2, sec=None, skip=[], **kw)

Promote all methods of a subsection class to parent class

Methods of parent class will not be overwritten

Call:
>>> promote_subsec(cls1, cls2, sec=None, skip=[], **kw)
Inputs:
cls1: type

Parent class

cls2: type

Subsection class

sec: {None} | str

Name of subsection, defaults to cls2.__name__

skip: {[]} | list

List of methods from cls2 not to add to cls1

init: {True} | False

If True, initialize subsection when cls1 methods used

parent: {None} | str

Name of section from which to get default settings

Versions:
  • 2019-01-10 @ddalle: v1.0

cape.optdict.strip_comment(line)

Strip a comment from a line

Call:
>>> code = strip_comment(line)
Examples:
>>> strip_comment('  "a": 2,\n')
'  "a": 2,\n'
>>> strip_comment('  // "a": 2,\n')
'\n'
>>> strip_comment('  "a": ["a//b", // comment\n')
'  "a": ["a//b", \n'
Inputs:
line: str

A line of text, possibly including a // comment

Outputs:
code: str

Input line with comments removed

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

cape.optdict.subsec_func(cls, sec=None, parent=None, init=True)

Decorator (w/ args) to apply a function from a subsection class

Call:
>>> f = subsec_func(cls, sec=None, parent=None, init=True)
Inputs:
cls:type

Class to apply to subsection

sec: {cls.__name} | str

Name of subsection

init: {True} | False

If True and nontrivial cls, initialize subsection

parent: {None} | str

Name of section from which to get default settings

Outputs:
f: function

Decorator with arguments expanded

Examples:
@subsec_func("RunControl", RunControl)
def get_PhaseSequence(self, *a, **kw):
    pass
Versions:
  • 2019-01-10 @ddalle: v1.0

  • 2021-10-18 @ddalle: v1.1; default sec