Skip to content

Config

Configuration and model building utilities.

Build Module

build_module(config, hyperpar=None)

Build a module based on the provided configuration. Every (possibly nested) dictionary with a 'class' key will be replaced by an instance initialized with arguments and keywords provided as 'args' and 'kwargs' keys.

Parameters:

Name Type Description Default
config Union[str, Dict, List]

The configuration for building the module.

required
hyperpar Union[str, Dict, None]

The hyperparameters for the module. Defaults to None.

None

Returns:

Type Description
Any

Union[List, Dict, Callable]: The built module.

Raises:

Type Description
AssertionError

If hyperpar is provided and is not a dictionary.

Source code in aimnet/config.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
def build_module(config: str | dict | list, hyperpar: str | dict | None = None) -> Any:
    """
    Build a module based on the provided configuration.
    Every (possibly nested) dictionary with a 'class' key will be replaced by an instance initialized with
    arguments and keywords provided as 'args' and 'kwargs' keys.

    Args:
        config (Union[str, Dict, List]): The configuration for building the module.
        hyperpar (Union[str, Dict, None], optional): The hyperparameters for the module. Defaults to None.

    Returns:
        Union[List, Dict, Callable]: The built module.

    Raises:
        AssertionError: If `hyperpar` is provided and is not a dictionary.

    """
    if isinstance(hyperpar, str):
        hyperpar = load_yaml(hyperpar)  # type: ignore[assignment]
    if hyperpar and not isinstance(hyperpar, dict):
        raise TypeError("Hyperpar must be a dictionary")
    config = load_yaml(config, hyperpar)
    for d, k, v in _iter_rec_bottomup(config):
        if isinstance(v, dict) and "class" in v:
            d[k] = get_init_module(  # type: ignore[index]
                v["class"],
                args=v.get("args", []),  # type: ignore[assignment]
                kwargs=v.get("kwargs", {}),
            )
    if "class" in config:
        config = get_init_module(  # type: ignore[assignment]
            config["class"],  # type: ignore[call-overload]
            args=config.get("args", []),  # type: ignore[union-attr]
            kwargs=config.get("kwargs", {}),  # type: ignore[union-attr]
        )
    return config  # type: ignore[assignment]

Module Lookup

get_module(name)

Retrieves a module and function based on the given name.

Parameters:

Name Type Description Default
name str

The name of the module and function in the format 'module.function'.

required

Returns:

Name Type Description
function Callable[..., Any]

The function object.

Raises:

Type Description
ImportError

If the module cannot be imported.

AttributeError

If the function does not exist in the module.

Source code in aimnet/config.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def get_module(name: str) -> Callable[..., Any]:
    """
    Retrieves a module and function based on the given name.

    Args:
        name (str): The name of the module and function in the format 'module.function'.

    Returns:
        function: The function object.

    Raises:
        ImportError: If the module cannot be imported.
        AttributeError: If the function does not exist in the module.
    """
    parts = name.split(".")
    module_name, func_name = ".".join(parts[:-1]), parts[-1]
    module = import_module(module_name)
    func = getattr(module, func_name)
    return func  # type: ignore[no-any-return]

get_init_module(name, args=None, kwargs=None)

Get the initialized module based on the given name, arguments, and keyword arguments.

Parameters:

Name Type Description Default
name str

The name of the module.

required
args List

The arguments to pass to the module constructor. Defaults to an empty list.

None
kwargs Dict

The keyword arguments to pass to the module constructor. Defaults to an empty dictionary.

None

Returns:

Type Description
Any

The initialized module.

Source code in aimnet/config.py
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def get_init_module(name: str, args: list | None = None, kwargs: dict | None = None) -> Any:
    """
    Get the initialized module based on the given name, arguments, and keyword arguments.

    Args:
        name (str): The name of the module.
        args (List, optional): The arguments to pass to the module constructor. Defaults to an empty list.
        kwargs (Dict, optional): The keyword arguments to pass to the module constructor. Defaults to an empty dictionary.

    Returns:
        The initialized module.

    """
    args = args if args is not None else []
    kwargs = kwargs if kwargs is not None else {}
    return get_module(name)(*args, **kwargs)  # type: ignore[no-any-return]

YAML Loading

load_yaml(config, hyperpar=None, *, basedir=None)

Load a YAML configuration file and apply optional hyperparameters.

Parameters:

Name Type Description Default
config Union[str, List, Dict]

The YAML configuration file path or a YAML object.

required
hyperpar Optional[Union[Dict, str, None]]

Optional hyperparameters to apply to the configuration.

None

Returns:

Type Description
dict[str, Any] | list

Union[List, Dict]: The loaded and processed configuration.

Raises:

Type Description
FileNotFoundError

If a file specified in the configuration does not exist.

Source code in aimnet/config.py
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
def load_yaml(
    config: dict[str, Any] | list | str,
    hyperpar: dict[str, Any] | str | None = None,
    *,
    basedir: str | None = None,
) -> dict[str, Any] | list:
    """
    Load a YAML configuration file and apply optional hyperparameters.

    Args:
        config (Union[str, List, Dict]): The YAML configuration file path or a YAML object.
        hyperpar (Optional[Union[Dict, str, None]]): Optional hyperparameters to apply to the configuration.

    Returns:
        Union[List, Dict]: The loaded and processed configuration.

    Raises:
        FileNotFoundError: If a file specified in the configuration does not exist.

    """
    if isinstance(hyperpar, str):
        hyperpar = load_yaml(hyperpar)  # type: ignore[assignment]
        if not isinstance(hyperpar, dict):
            raise TypeError("Loaded hyperpar must be a dict")
    if isinstance(config, (list, dict)):
        config = copy.deepcopy(config)
        if hyperpar:
            for d, k, v in _iter_rec_bottomup(config):
                if isinstance(v, str) and "{{" in v:
                    d[k] = Template(v).render(**hyperpar)  # type: ignore[assignment, index]
    else:
        basedir = os.path.dirname(os.path.abspath(config))
        with open(config, encoding="utf-8") as f:
            config = f.read()
        if hyperpar:
            config = Template(config).render(**hyperpar)
        config = yaml.load(config, Loader=yaml.FullLoader)  # noqa: S506
    # plugin yaml configs
    for d, k, v in _iter_rec_bottomup(config):  # type: ignore[arg-type]
        if isinstance(v, str) and any(v.endswith(x) for x in (".yml", ".yaml")):
            if not os.path.isfile(v) and basedir is not None:
                v = os.path.join(basedir, v)
            d[k] = load_yaml(v, hyperpar)  # type: ignore[assignment, index]
    return config  # type: ignore[return-value]

Dotted Dictionaries

dict_to_dotted(d, parent='')

Source code in aimnet/config.py
149
150
151
152
153
154
155
156
157
158
159
def dict_to_dotted(d, parent=""):
    if parent:
        parent += "."
    for k, v in list(d.items()):
        if isinstance(v, dict) and v:
            v = dict_to_dotted(v, parent + k)
            d.update(v)
            d.pop(k)
        else:
            d[parent + k] = d.pop(k)
    return d

dotted_to_dict(d)

Source code in aimnet/config.py
162
163
164
165
166
167
168
169
170
171
172
173
174
def dotted_to_dict(d):
    for k, v in list(d.items()):
        if "." not in k:
            continue
        ks = k.split(".")
        ds = d
        for ksp in ks[:-1]:
            if ksp not in ds:
                ds[ksp] = {}
            ds = ds[ksp]
        ds[ks[-1]] = v
        d.pop(k)
    return d