tranche

class tranche.Tranche

Bases: object

A “meta” config parser that keeps a dictionary of config parsers and their sources to combine when needed. The custom config parser allows provenance of the source of different config options and allows the “user” config options to always take precedence over other config options (even if they are added later).

Example

>>> config = Tranche()
>>> config.add_from_file('default.cfg')
>>> config.add_user_config('user.cfg')
>>> value = config.get('section', 'option')
combined

The combined config options

Type:

{None, configparser.ConfigParser}

combined_comments

The combined comments associated with sections and options

Type:

{None, dict}

sources

The source of each section or option

Type:

{None, dict}

add_from_file(filename)

Add the contents of a config file to the parser.

Parameters:

filename (str) – The relative or absolute path to the config file

Return type:

None

add_from_package(package, config_filename, exception=True)

Add the contents of a config file to the parser.

Parameters:
  • package (str or Package) – The package where config_filename is found

  • config_filename (str) – The name of the config file to add

  • exception (bool, optional) – Whether to raise an exception if the config file isn’t found

Return type:

None

add_user_config(filename)

Add a the contents of a user config file to the parser. These options take precedence over all other options.

Parameters:

filename (str) – The relative or absolute path to the config file

Return type:

None

append(other)

Append a deep copy of another config parser to this one. Config options from other will take precedence over those from this config parser.

Parameters:

other (tranche.Tranche) – The other, higher priority config parser

Return type:

None

combine(raw=False)

Combine the config files into one. This is normally handled automatically.

Parameters:

raw (bool, optional) – Whether to combine “raw” config options, rather than using extended interpolation

Return type:

None

copy()

Get a deep copy of the config parser

Returns:

config_copy – The deep copy

Return type:

tranche.Tranche

explain(section, option)

Explain the provenance of an option.

Returns a dictionary with the effective value, the source file path, and which layer provided it (“user” or “base”).

Parameters:
  • section (str) – The name of the config section

  • option (str) – The name of the config option

Returns:

info – {“value”: …, “source”: <path>, “layer”: “user”|”base”}

Return type:

dict

get(section, option)

Get an option value for a given section.

Parameters:
  • section (str) – The name of the config section

  • option (str) – The name of the config option

Returns:

value – The value of the config option

Return type:

str

getboolean(section, option)

Get an option boolean value for a given section.

Parameters:
  • section (str) – The name of the config section

  • option (str) – The name of the config option

Returns:

value – The value of the config option

Return type:

bool

getexpression(section, option, dtype=None, backend=None, allow_numpy=False)

Get an option as an expression (typically a list, though tuples and dicts are also available). The expression is required to have valid python syntax, so that string entries are required to be in single or double quotes.

Parameters:
  • section (str) – The section in the config file

  • option (str) – The option in the config file

  • dtype ({Type[bool], Type[int], Type[float], Type[list], Type[tuple], Type[str]}, optional) – If supplied, each element in a list or tuple, or each value in a dictionary are cast to this type. This is likely most useful for ensuring that all elements in a list of numbers are of type float, rather than int, when the distinction is important.

  • backend ({"literal", "safe"} or None) –

    • None (default): choose “safe” if allow_numpy=True else “literal”.

    • ”literal”: use ast.literal_eval (safest, literals only)

    • ”safe”: use a whitelisted AST evaluator optionally allowing numpy

  • allow_numpy (bool, optional) – If True and backend=”safe”, enable limited numpy functions (np.arange, np.linspace, np.array) under names “np”/”numpy”.

Return type:

Any

getfloat(section, option)

Get an option float value for a given section.

Parameters:
  • section (str) – The name of the config section

  • option (str) – The name of the config option

Returns:

value – The value of the config option

Return type:

float

getint(section, option)

Get an option integer value for a given section.

Parameters:
  • section (str) – The name of the config section

  • option (str) – The name of the config option

Returns:

value – The value of the config option

Return type:

int

getlist(section, option, dtype=<class 'str'>)

Get an option value as a list for a given section.

Parameters:
  • section (str) – The name of the config section

  • option (str) – The name of the config option

  • dtype ({Type[str], Type[int], Type[float]}) – The type of the elements in the list

Returns:

value – The value of the config option parsed into a list

Return type:

list

getnumpy(section, option, dtype=None, backend=None)

Shortcut for expressions requiring NumPy.

Equivalent to getexpression(..., allow_numpy=True) with adaptive backend selection (safe if backend is None).

Parameters:
  • section (str) – Section name.

  • option (str) – Option name.

  • dtype (type, optional) – Cast list/tuple/dict elements to this type.

  • backend ({"literal", "safe"} or None, optional) – Override backend. None => choose “safe”.

Return type:

Any

has_option(section, option)

Whether the given section has the given option

Parameters:
  • section (str) – The name of the config section

  • option (str) – The name of the config option

Returns:

found – Whether the option was found in the section

Return type:

bool

has_section(section)

Whether the given section is part of the config

Parameters:

section (str) – The name of the config section

Returns:

found – Whether the option was found in the section

Return type:

bool

list_files()

Get a list of files contributing to the combined config options

Returns:

filenames – A list of file paths

Return type:

list of str

prepend(other)

Prepend a deep copy of another config parser to this one. Config options from this config parser will take precedence over those from other.

Parameters:

other (tranche.Tranche) – The other, higher priority config parser

Return type:

None

register_symbol(name, obj)

Make ‘name’ available to the safe expression backend.

Restrictions:

  • name must not contain ‘__’ or ‘.’

  • cannot override reserved core names: ‘np’, ‘numpy’, ‘math’, ‘range’, ‘int’, ‘float’, ‘pi’

Examples

Register a stdlib function (math.sqrt) and call it from the config:

>>> import math
>>> config = Tranche()
>>> config.register_symbol('sqrt', math.sqrt)
>>> # INI has:
>>> #  [calc]
>>> #  val = sqrt(9)
>>> config.getexpression('calc', 'val', backend='safe')
3.0

Register a reducer (statistics.mean):

>>> import statistics
>>> config.register_symbol('mean', statistics.mean)
>>> # INI has:
>>> #  [data]
>>> #  avg = mean([1, 2, 3])
>>> config.getexpression('data', 'avg', backend='safe')
2

Register a type (datetime.timedelta) supporting keyword args:

>>> from datetime import timedelta
>>> config.register_symbol('timedelta', timedelta)
>>> # INI has:
>>> #  [sched]
>>> #  interval = timedelta(days=2)
>>> config.getexpression('sched', 'interval', backend='safe')
datetime.timedelta(days=2)
Parameters:
  • name (str) – The name to register

  • obj (any) – The object to register under the given name

Return type:

None

set(section, option, value=None, comment=None, user=False)
Set the value of the given option in the given section. The file from

which this function was called is also retained for provenance.

Parameters:
  • section (str) – The name of the config section

  • option (str) – The name of the config option

  • value (str, optional) – The value to set the option to

  • comment (str, optional) – A comment to include with the config option when it is written to a file

  • user (bool, optional) – Whether this config option was supplied by the user (e.g. through a command-line flag) and should take priority over other sources

Return type:

None

validate(validator)

Call a user-provided validator function on the config as a nested dict.

The validator is called with a dictionary of the form:

{section: {option: value, …}, …}

where all values are strings as returned by get().

This allows integration with validation libraries such as Pydantic or voluptuous, or custom validation logic. If the validator raises an exception, it will propagate to the caller.

Parameters:

validator (Callable[[dict[str, dict[str, str]]], None]) – A function that takes a nested dictionary of config values and raises on error.

Return type:

None

Examples

>>> def my_validator(cfg):
...     assert 'main' in cfg
...     assert 'foo' in cfg['main']
>>> config.validate(my_validator)
write(fp, include_sources=True, include_comments=True, raw=True)

Write the config options to the given file pointer.

Parameters:
  • fp (TextIO) – The file pointer to write to.

  • include_sources (bool, optional) – Whether to include a comment above each option indicating the source file where it was defined

  • include_comments (bool, optional) – Whether to include the original comments associated with each section or option

  • raw (bool, optional) – Whether to write “raw” config options, rather than using extended interpolation

Return type:

None