Skip to content

configuration

PROCESS I/O library configuration API.

Designed to be used by utility developers when creating configuration mechanisms for their tool.

ConfigurationParser

Abstract parser class. Must be subclassed to be used.

The parser should always put read-in data in the data property.

Source code in process/core/io/configuration.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class ConfigurationParser:
    """Abstract parser class. Must be subclassed to be used.

    The parser should always put read-in data in the data property.
    """

    def __init__(self):
        self._data = None

    @property
    def data(self):
        return self._data

    @data.setter
    def data(self, value):
        """Validate the configuration is provided in a specific format.

        Parameters
        ----------
        value :

        """
        self.data_validate(value)
        self._data = value

    @data.deleter
    def data(self):
        del self._data

    def data_validate(self, value):
        """Check that value corresponds to a specific data format.

        Parameters
        ----------
        value :

        """
        if not isinstance(value, dict) and value is not None:
            raise ValueError("Configuration data must be specified as a dictionary")

data deletable property writable

data_validate(value)

Check that value corresponds to a specific data format.

Parameters:

Name Type Description Default
value
required
Source code in process/core/io/configuration.py
43
44
45
46
47
48
49
50
51
52
def data_validate(self, value):
    """Check that value corresponds to a specific data format.

    Parameters
    ----------
    value :

    """
    if not isinstance(value, dict) and value is not None:
        raise ValueError("Configuration data must be specified as a dictionary")

JsonConfigParser

Bases: ConfigurationParser

JSON configuration parser.

Source code in process/core/io/configuration.py
55
56
57
58
59
60
61
62
63
64
65
class JsonConfigParser(ConfigurationParser):
    """JSON configuration parser."""

    def __init__(self, filename):
        self.data = None
        try:
            with open(filename) as fh:
                config_file_data = json.load(fh)
                self.data = config_file_data
        except FileNotFoundError:
            logger.error(f"Cannot find configuration file {filename}")

data = config_file_data instance-attribute

Config

Generic configuration for PROCESS tools. Read-only.

Source code in process/core/io/configuration.py
 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
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
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
class Config:
    """Generic configuration for PROCESS tools. Read-only."""

    def __init__(self, config_file, parser=JsonConfigParser):
        self.config_file = config_file
        parser = JsonConfigParser(config_file)
        self.config_data = self._lowercase(parser.data)

    def _lowercase(self, objekt):
        if isinstance(objekt, list):
            return [self._lowercase(item) for item in objekt]
        if isinstance(objekt, dict):
            return {key.lower(): self._lowercase(value) for key, value in objekt.items()}
        return objekt

    def _search_config_for(self, config, *keys):
        """Recursively search config (a dict) for keys.

        Parameters
        ----------
        config :

        *keys :

        """
        try:
            search_key = keys[0].lower() if isinstance(keys[0], str) else keys[0]
            value = config[search_key]
        except IndexError:
            raise
        except KeyError:
            raise
        except TypeError:
            raise

        if isinstance(config, dict) and len(keys) > 1:
            return self._search_config_for(value, *keys[1:])
        if not isinstance(value, dict) and len(keys) > 1:
            raise KeyError(f"{search_key} cannot be found in {value}")
        return self._lowercase(value)

    def get(self, *config_keys, default=None):
        """

        Parameters
        ----------
        *config_keys :

        default :
             (Default value = None)

        Returns
        -------
        type
            For nested configs, sequential items in config_keys can be used.
            For example, if the configuration is:
            {"a": "b", "c": {1: "hello", 2: {"x": "alpha", "z": "beta"}}}
            you can access the value of "z" by calling get("c", 2, "z").
        """

        try:
            return self._search_config_for(self.config_data, *config_keys)
        except KeyError:
            if default:
                logger.info(f"Using default for {config_keys}")
                return default
            logger.exception(
                f"Cannot find value or default for {config_keys} in configuration"
            )
        except (IndexError, TypeError):
            raise

config_file = config_file instance-attribute

config_data = self._lowercase(parser.data) instance-attribute

get(*config_keys, default=None)

Parameters:

Name Type Description Default
*config_keys
()
default

(Default value = None)

None

Returns:

Type Description
type

For nested configs, sequential items in config_keys can be used. For example, if the configuration is: {"a": "b", "c": {1: "hello", 2: {"x": "alpha", "z": "beta"}}} you can access the value of "z" by calling get("c", 2, "z").

Source code in process/core/io/configuration.py
109
110
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
def get(self, *config_keys, default=None):
    """

    Parameters
    ----------
    *config_keys :

    default :
         (Default value = None)

    Returns
    -------
    type
        For nested configs, sequential items in config_keys can be used.
        For example, if the configuration is:
        {"a": "b", "c": {1: "hello", 2: {"x": "alpha", "z": "beta"}}}
        you can access the value of "z" by calling get("c", 2, "z").
    """

    try:
        return self._search_config_for(self.config_data, *config_keys)
    except KeyError:
        if default:
            logger.info(f"Using default for {config_keys}")
            return default
        logger.exception(
            f"Cannot find value or default for {config_keys} in configuration"
        )
    except (IndexError, TypeError):
        raise