As shown in Concepts and usage, a Computer can be populated programmatically. genno can also read a simple configuration format in which settings and tasks are specified.


Ways to configure#

Configuration is read through the Computer.configure() method, or the top level genno.configure() function.

Both methods accept either keyword arguments specifying the configuration values, or a path keyword argument that gives the path to a .json or .yaml-format file. For instance, the following are all equivalent:

# Create the computer before configuring from a JSON file
c = Computer()

# Create and configure from a YAML file in one step
c = Computer(path="config-W.yaml")

# Pass a data structure to configure()
info = dict(
    dict(comp="product", key="W:a-b-c-d", inputs=["X::", "Y:d"], sums=True)
c = Computer()

# Use the API to add a computation directly
c = Computer()
# add_product() infers the dimensions of W will be a-b-c-d
c.add_product("W", "X:a-b-c-d", "Y:d", sums=True)

…with the following file contents:

- comp: product
  key: W:a-b-c-d
  inputs: ["X::", "Y:d"]
  sums: true
  "general": [
      "comp": "product",
      "key": "W:a-b-c-d",
      "inputs": ["X::", "Y:d"],
      "sums": true

Global- and specific configuration#

Configuration is either global or specific to a certain Computer. For instance, units: configuration is global; it affects all Computers, and can be set using either genno.configure() or Computer.configure(). On the other hand, other configuration such as files: input adds tasks to a specific Computer, so it can only be set using Computer.configure().

genno.configure(path: Path | str | None = None, **config)[source]#

Configure genno globally.

Modifies global variables that affect the behaviour of all Computers and operators. Configuration keys loaded from file are superseded by keyword arguments. Messages are logged at level logging.INFO if config contains unhandled sections.

  • path (pathlib.Path, optional) – Path to a configuration file in JSON or YAML format.

  • **config – Configuration keys/sections and values.

Custom handlers#

The configuration file is divided into sections. Generally each section contains a list of items, and each item is itself a mapping; see the built-in sections listed below. genno.config has one handler function for each section, and is extensible. For instance, the genno compatibility module for pyam defines a handler for the section iamc:; or the separate package ixmp defines a handler for the sections filters: and rename_dims:.

The handles() decorator can be used to mark a custom function that handles a custom configuration section:

from genno.config import handles

def custom_handler(c: Computer, info):
    print(f"Handle {info['name']}")
    print(f"  with inputs {repr(info['inputs'])}")

    # Use a default value for one setting
    key = info.get("key", "foo")
    print(f"Output key: {key}")

    # Manipulate the Computer instance `c` in some way
    c.add("… etc.")
 # This section is handled by genno's built-in handlers
 - comp: product
    key: W:a-b-c-d
    inputs: ["X::", "Y:d"]
    sums: true

 # These items are handled by the custom handler
 - name: item-a
   inputs: [X, Y]
 - name: item-b
   key: bar
   inputs: [W, Z]
class genno.config.ConfigHandler(key: str, callback: Callable[[Computer | None, Mapping | Sequence], Any], iterate: bool, discard: bool)[source]#

Class for a configuration key/section handler.

callback: Callable[[Computer | None, Mapping | Sequence], Any]#


discard: bool#

If True, discard the configuration contents after handling.

iterate: bool#

If True, apply callback iteratively to each member of the value/section.

key: str#

Configuration key or section handled.

genno.config.HANDLERS: Dict[str, ConfigHandler] = {'aggregate': ConfigHandler(key='aggregate', callback=<function aggregate>, iterate=True, discard=True), 'alias': ConfigHandler(key='alias', callback=<function alias>, iterate=True, discard=True), 'cache_path': ConfigHandler(key='cache_path', callback=<function store>, iterate=False, discard=False), 'cache_skip': ConfigHandler(key='cache_skip', callback=<function store>, iterate=False, discard=False), 'combine': ConfigHandler(key='combine', callback=<function combine>, iterate=True, discard=True), 'config_dir': ConfigHandler(key='config_dir', callback=<function store>, iterate=False, discard=False), 'default': ConfigHandler(key='default', callback=<function default>, iterate=False, discard=True), 'files': ConfigHandler(key='files', callback=<function files>, iterate=True, discard=True), 'general': ConfigHandler(key='general', callback=<function general>, iterate=True, discard=True), 'iamc': ConfigHandler(key='iamc', callback=<function iamc>, iterate=True, discard=True), 'report': ConfigHandler(key='report', callback=<function report>, iterate=True, discard=True), 'units': ConfigHandler(key='units', callback=<function units>, iterate=False, discard=True)}#

Registry of configuration section handlers.

genno.config.STORE: Set[str] = {}#

Deprecated since version 1.25.0: Instead, use:

from genno.config import handles, store

handles("section_name", False, False)(store)

Configuration sections/keys to be stored with no action.

genno.config.handles(section_name: str, iterate: bool = True, discard: bool = True)[source]#

Decorator to register a configuration section handler in HANDLERS.

  • section_name (str) – The name of the configuration section to handle. Using a name already present in HANDLERS overrides that handler.

  • iterate (bool, optional) – If True, the handler is called once for each item (either list item, or (key, value) tuple) in the section. If False, the entire section contents, of whatever type, are passed to tha handler.

  • discard (bool, optional) – If True, configuration section data is discarded after the handler is called. If False, the data is retained and stored on the Computer.

Specific sections#


genno.config.aggregate(c: Computer, info)[source]#

Handle one entry from the aggregate: config section.

Computer-specific configuration.

Invokes Computer.aggregate() add tasks with operator.aggregate() or operator.sum(), computing sums across labels within one dimension of a quantity. Each entry contains:

_quantities: list of 0 or more keys

Quantities to be aggregated. The full dimensionality of the key(s) is inferred.

_tag: (str)

New tag to append to the keys for the aggregated quantities.

_dim: (str)

Dimensions on which to aggregate.

_fail: (str or int)

Action or log level when aggregation fails; corresponds to the fail argument to Computer.aggregate().

Note the leading underscores. This is to distinguish these from all other keys, which are treated as group names. The corresponding values are lists of labels along the dimension to sum.


- _quantities: [foo, bar]
  _tag: aggregated
  _dim: a

  baz123: [baz1, baz2, baz3]
  baz12: [baz1, baz2]

If the full dimensionality of the input quantities are foo:a-b and bar:a-b-c, then add_aggregate() creates the new quantities foo:a-b:aggregated and bar:a-b-c:aggregated. These new quantities have the new labels baz123 and baz12 along their a dimension, with sums of the indicated values.


genno.config.alias(c: Computer, info)[source]#

Handle one entry from the alias: config section.

Computer-specific configuration.

This section simply makes the output of one task available under another key.

  "foo:x-y": "bar:x-y"
  "baz:x-y": "bar:x-y"


Computer-specific configuration that controls the behaviour of functions decorated with Computer.cache().

cache_path: (pathlib.Path, optional)

Base path for cache files. If not provided, defaults to the current working directory.

cache_skip: (bool, optional)

If True, existing cache files are never used; files with the same cache key are overwritten.


genno.config.combine(c: Computer, info)[source]#

Handle one entry from the combine: config section.

Computer-specific configuration.

Add tasks with combine(), computing a weighted sum of multiple Quantities. Each item contains:


Key for the new quantity, including dimensionality.

inputs: (list of dict)

Inputs to the weighted sum. Each dict contains:

quantity: (required)

Key for the input quantity. The final dimensionality is inferred from the dimensions of key plus dimension to select on.

select: (dict, optional)

Selectors to be applied to the input quantity. Keys are dimensions; values are either single labels, or lists of labels. In the latter case, the sum is taken across these values, so that the result has the same dimensionality as key.

weight: (int, optional)

Weight for the input quantity; default 1.


For the following YAML:

- key: foo:a-b-c
  - quantity: bar
    weight: -1
  - quantity: baz::tag
    select: {d: [d1, d2, d3]}

The code infers:

\[\text{foo}_{abc} = -1 \times \text{bar}_{abc} + 1 \times \sum_{d \in \{ d1, d2, d3 \}}{\text{baz}_{abcd}^\text{(tag)}} \quad \forall \quad a, b, c\]

default: key/task#

genno.config.default(c: Computer, info)[source]#

Handle the default: config section.

Computer-specific configuration.

This sets Computer.default_key, used when get() is called without arguments.

files: input#

genno.config.files(c: Computer, info)[source]#

Handle one entry from the files: config section.

Computer-specific configuration.

Invokes Computer.add_file() to add operator.load_file(). If the path: key is a relative path, it is resolved relative to the directory that contains the configuration file, else the current working directory.

- path: ./input0.csv
  key: d_check
# 'dims' argument can be supplied as list or dict
- path: ./input1.csv
  key: input1-0
  dims: [i, j_dim]  # Omit extra dimension 'foo'
- path: ./input1.csv
  key: input1-1
  dims: {i: i, j_dim: j}


genno.config.general(c: Computer, info)[source]#

Handle one entry from the general: config section.

Computer-specific configuration.

This is, as the name implies, the most generalized section. Each item contains:


Refers to the name of a operator that is available in the namespace of genno.operator, or a custom operator registered by compatibility modules or third-party packages. See Computer.add() and Computer.get_operator(). For instance, if “product”, then Computer.add_product() is called, which also automatically infers the correct dimensions for each input.

If omitted, None, or YAML null, no specific callable is used, but instead key: is configured to retrieve a simple list of the inputs:. In this case, args: are ignored.


The key for the computed quantity.

If the key has the single dimension “*” (e.g. key: "X:*:tag"), then dimensions of the resulting key are inferred to be the union of the dimensions of each of the inputs:, below.


A list of (1 or more) keys to which the operator is applied.

args: (dict, optional)

Keyword arguments to the operator.

add args: (dict, optional)

Keyword arguments to Computer.add() itself.

report:# Computer, info)[source]#

Handle one entry from the report: config section.

Computer-specific configuration.

A ‘report’ is a concatenation of 1 or more other quantities.


- key: foo
  members: [X, Y]


genno.config.units(c: Computer, info)[source]#

Handle the units: config section.

Global configuration.


replace: (mapping of str -> str)

Replace units before they are parsed by pint. Added to REPLACE_UNITS.

define: (str)

Multi-line block of unit definitions, added to the pint application registry so that units are recognized. See the pint documentation on defining units.

    dollar: USD
  # YAML multi-line string
  define: |-
    pp = [person]
    tiny = 0.1 millimetre