Skip to content

configs 🗿

Configuration for FaceSim3D project.

Note: store private configs in the same folder as config.toml, namely: ./[PRIVATE_PREFIX]_configs.toml

Author: Simon M. Hofmann | [firstname].[lastname]@cbs.mpg.de | 2022

Classes:

Name Description
CONFIG

Configuration object.

Functions:

Name Description
update_logger_configs

Update logger name and filename.

CONFIG 🗿

CONFIG(config_dict: dict | None = None)

Configuration object.

Initialise CONFIG class object.

Methods:

Name Description
asdict

Convert the config object to dict.

show

Display the nested configuration information.

update

Update the config object with new entries.

update_paths

Update relative paths to PROJECT_ROOT dir.

Source code in code/facesim3d/configs.py
41
42
43
44
def __init__(self, config_dict: dict | None = None) -> None:
    """Initialise CONFIG class object."""
    if config_dict is not None:
        self.update(config_dict)

asdict 🗿

asdict()

Convert the config object to dict.

Source code in code/facesim3d/configs.py
88
89
90
91
92
93
94
95
96
def asdict(self):
    """Convert the config object to dict."""
    dict_out = {}
    for key, val in self.__dict__.items():
        if isinstance(val, CONFIG):
            dict_out.update({key: val.asdict()})
        else:
            dict_out.update({key: val})
    return dict_out

show 🗿

show(indent: int = 0)

Display the nested configuration information.

Parameters:

Name Type Description Default
indent int

The number of tabs to use for indentation (default: 0)

0

Returns:

Type Description

None

Source code in code/facesim3d/configs.py
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def show(self, indent: int = 0):
    """
    Display the nested configuration information.

    :param indent: The number of tabs to use for indentation (default: 0)
    :return: None
    """
    for key, val in self.__dict__.items():
        if isinstance(val, CONFIG):
            print("\t" * indent + f"{key}:")
            val.show(indent=indent + 1)
        else:
            _val = val.replace("\n", "\\n").replace("\t", "\\t") if isinstance(val, str) else val
            print("\t" * indent + f"{key}: " + (f"'{_val}'" if isinstance(val, str) else f"{val}"))

update 🗿

update(new_configs: dict[str, Any]) -> None

Update the config object with new entries.

Source code in code/facesim3d/configs.py
65
66
67
68
69
70
71
def update(self, new_configs: dict[str, Any]) -> None:
    """Update the config object with new entries."""
    for k, val in new_configs.items():
        if isinstance(val, list | tuple):
            setattr(self, k, [CONFIG(x) if isinstance(x, dict) else x for x in val])
        else:
            setattr(self, k, CONFIG(val) if isinstance(val, dict) else val)

update_paths 🗿

update_paths(
    parent_path: str | None = None,
    for_logging: bool = False,
)

Update relative paths to PROJECT_ROOT dir.

Source code in code/facesim3d/configs.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def update_paths(self, parent_path: str | None = None, for_logging: bool = False):
    """Update relative paths to PROJECT_ROOT dir."""
    # Use project root dir as the parent path if it is not specified
    parent_path = self.PROJECT_ROOT if hasattr(self, "PROJECT_ROOT") else parent_path

    if parent_path is not None:
        parent_path = str(Path(parent_path).absolute())

        for key, path in self.__dict__.items():
            if isinstance(path, str) and not Path(path).is_absolute():
                if for_logging and key != "filename":
                    # In the case of logging configs, apply only on filename
                    continue
                self.__dict__.update({key: str(Path(parent_path).joinpath(path))})

            elif isinstance(path, CONFIG):
                path.update_paths(parent_path=parent_path, for_logging=for_logging)

    else:
        print("Paths can't be converted to absolute paths, since no PROJECT_ROOT is found!")

update_logger_configs 🗿

update_logger_configs(
    new_logger_name: str,
    new_logger_filename: str | Path,
    logger: Logger,
) -> Logger

Update logger name and filename.

Parameters:

Name Type Description Default
new_logger_name str

new logger name

required
new_logger_filename str | Path

new logger filename

required
logger Logger

updated logger object

required
Source code in code/facesim3d/configs.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def update_logger_configs(
    new_logger_name: str, new_logger_filename: str | Path, logger: logging.Logger
) -> logging.Logger:
    """
    Update logger name and filename.

    :param new_logger_name: new logger name
    :param new_logger_filename: new logger filename
    :param logger: updated logger object
    """
    # Set new logger name
    logger.name = new_logger_name

    # Check filename
    if not str(new_logger_filename).endswith(".log"):
        msg = f"Given filename '{new_logger_filename}' does not end with '.log'."
        raise ValueError(msg)

    # Create parent dirs
    Path(new_logger_filename).parent.mkdir(parents=True, exist_ok=True)

    # Overwrite logger
    for handler in logger.handlers:
        if isinstance(handler, logging.FileHandler):
            new_file_handler = logging.FileHandler(filename=new_logger_filename)
            new_file_handler.setFormatter(handler.formatter)
            new_file_handler.setLevel(handler.level)
            logger.removeHandler(handler)
            logger.addHandler(new_file_handler)
    return logger