Skip to content

Config Manager

Provide settings modules.

ConfigManager

Provide config management representation.

defaults property readonly

Get configuration defaults.

filepaths: Tuple[str, ...] property readonly

Retrieve filepaths.

settings: SettingsMap property readonly

Create settings to prototype idea.

__getattr__(self, attr) special

Proxy calls to settings store.

Source code in compendium/config_manager.py
72
73
74
75
76
77
78
79
80
81
82
83
def __getattr__(
    self, attr: str
) -> Callable[[VarArg(Any), KwArg(Any)], Any]:
    '''Proxy calls to settings store.'''
    if hasattr(self.__dict__.get('data'), attr):

        def wrapper(*args, **kwargs):
            '''Call query for data store.'''
            return getattr(self.data, attr)(*args, **kwargs)

        return wrapper
    raise AttributeError(attr)

__init__(self, name, *args, **kwargs) special

Initialize single settings management.

merge_sections: [] merge_strategy: - overlay - partition - last

Source code in compendium/config_manager.py
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def __init__(self, name: str, *args: str, **kwargs: Any) -> None:
    '''Initialize single settings management.

    merge_sections: []
    merge_strategy:
      - overlay
      - partition
      - last

    '''
    # Setup logging
    if 'log_level' in kwargs:
        log.setLevel(getattr(logging, kwargs.pop('log_level').upper()))
    if 'log_handler' in kwargs:
        log_handler = kwargs.pop('log_handler')
        log.addHandler(logging.StreamHandler(log_handler))  # type: ignore

    # Setup filepaths
    self.name = name
    # TODO: args should be filepaths
    self._filepaths: List[str] = list(args)
    # self.config_files: List[Dict[str, Union[str, ConfigFile]]] = []

    # Load environs
    if 'prefix' in kwargs:
        self.prefix = kwargs.pop('prefix')
    if 'separator' in kwargs:
        self.separator = kwargs.pop('separator')
    if kwargs.pop('load_dotenv', False):
        self.load_dotenv()
    if kwargs.pop('load_environs', True):
        self.environs = self.load_environs()
    # if kwargs.pop('load_startup_args', True):
    #     self.environs.update(kwargs.pop('load_startup_args', {}))

    # Load defaults
    defaults = kwargs.pop('defaults', {})

    # Populate settings
    if 'data' in kwargs:
        self.data = SettingsMap(*kwargs.pop('data'))
        if defaults != {}:
            self.defaults.update(defaults)
    else:
        self.data = SettingsMap(defaults)

__repr__(self) special

Get string representation of data.

Source code in compendium/config_manager.py
85
86
87
def __repr__(self) -> str:
    '''Get string representation of data.'''
    return repr(self.data)

add_filepath(self, filepath)

Load settings from configuration in filepath.

Source code in compendium/config_manager.py
109
110
111
112
def add_filepath(self, filepath: str) -> None:
    '''Load settings from configuration in filepath.'''
    logging.debug("searching for {}".format(filepath))
    self._filepaths.append(filepath)

load_config(self, filepath, update=True)

Load settings from configuration.

Source code in compendium/config_manager.py
122
123
124
125
126
127
128
129
130
131
132
def load_config(
    self, filepath: str, update: bool = True
) -> Optional[ConfigFile]:
    '''Load settings from configuration.'''
    if os.path.exists(filepath):
        config_file = ConfigFile(filepath=filepath)
        config_file.load()
        if update:
            self.data.push(config_file)
        return config_file
    return None

load_configs(self)

Load configuration files from filepaths.

Source code in compendium/config_manager.py
134
135
136
137
def load_configs(self) -> None:
    '''Load configuration files from filepaths.'''
    for filepath in self._filepaths:
        self.load_config(filepath)

HierarchyConfigManager

Manage settings from hierarchy config_files.

__init__(self, name, *args, **kwargs) special

Initialize settings from hirarchy filepaths.

Parameters

str

Name of name.

list, optional

Include sections to be merged

list, optional

Strategy to used when merging: overlay, parition, and last - overlay will replace exsisting entries - partition will keeps each seettings separate - last will only use the last loaded

bool, optional

Enable system filepath lookup for config_files.

bool, optional

Enable user filepath lookup for config_files.

bool, optional

Enable local filepath lookup for config_files.

Source code in compendium/config_manager.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
def __init__(self, name: str, *args: str, **kwargs: Any) -> None:
    '''Initialize settings from hirarchy filepaths.

    Parameters
    ----------
    name: str
        Name of name.
    merge_sections: list, optional
        Include sections to be merged
    merge_strategy: list, optional
        Strategy to used when merging: overlay, parition, and last
          - overlay will replace exsisting entries
          - partition will keeps each seettings separate
          - last will only use the last loaded
    enable_system_filepaths: bool, optional
        Enable system filepath lookup for config_files.
    enable_global_filepaths: bool, optional
        Enable user filepath lookup for config_files.
    enable_local_filepaths: bool, optional
        Enable local filepath lookup for config_files.

    '''
    self.basedir = kwargs.pop('basedir', os.sep)
    self.filename = kwargs.pop('filename', 'config.toml')
    self.enable_system_filepaths = bool(
        kwargs.get('enable_system_filepaths', False)
    )
    self.enable_global_filepaths = bool(
        kwargs.get('enable_global_filepaths', False)
    )
    self.enable_local_filepaths = bool(
        kwargs.get('enable_local_filepaths', True)
    )
    super().__init__(name, *args, **kwargs)
    self._prep_filepaths()

TreeConfigManager

Manage settings from nested tree config_files.

namepaths: Tuple[str, ...] property readonly

Return list of namepaths.

__init__(self, name, *args, **kwargs) special

Initialize nested settings management.

Source code in compendium/config_manager.py
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
def __init__(self, name: str, *args: str, **kwargs: Any) -> None:
    '''Initialize nested settings management.'''
    self.parent = kwargs.pop('parent', None)
    if 'children' in kwargs:
        self.children = kwargs.pop('children')
    load_root = kwargs.pop('load_root', False)
    load_children = kwargs.pop('load_children', False)

    self.filename = kwargs.pop('filename', 'config.toml')
    self.basedir = kwargs.pop('basedir', os.getcwd())

    super().__init__(name, *args, **kwargs)

    if not self.parent and args == ():
        self._prep_filepaths()
    else:
        self._filepaths == list(args)

    if load_root:
        super().load_config(self.filepaths[0])
    if load_children:
        self.load_configs()

get_config(self, namepath)

Get config from store by attribute.

Source code in compendium/config_manager.py
255
256
257
258
259
def get_config(self, namepath):
    '''Get config from store by attribute.'''
    r = Resolver('name')
    results = r.get(self, namepath)
    return results

get_filepath(self, name)

Get filepath from namepath.

Source code in compendium/config_manager.py
248
249
250
251
252
253
def get_filepath(self, name: str) -> Optional[str]:
    '''Get filepath from namepath.'''
    for x in self.filepaths:
        if name == self.get_namepath(x):
            return x
    return None

get_name(self, filepath)

Get name from tree path.

Source code in compendium/config_manager.py
228
229
230
231
232
233
234
235
236
def get_name(self, filepath: str) -> str:
    '''Get name from tree path.'''
    name = os.path.dirname(os.path.relpath(filepath, self.basedir),).split(
        os.sep
    )[-1]
    if name != '':
        return name
    else:
        return self.name

get_namepath(self, filepath)

Get name from tree path.

Source code in compendium/config_manager.py
238
239
240
241
242
243
244
245
246
def get_namepath(self, filepath: str) -> str:
    '''Get name from tree path.'''
    name = os.path.dirname(
        os.path.relpath(filepath, self.basedir),
    ).replace(os.sep, self.separator)
    if name != '':
        return f"{self.separator}{self.name}{self.separator}{name}"
    else:
        return f"{self.separator}{self.name}"

load_config(self, filepath, update=False, *args, **kwargs)

Load config.

Source code in compendium/config_manager.py
303
304
305
306
307
308
309
310
def load_config(
    self, filepath: str, update: bool = False, *args: str, **kwargs: Any
) -> Optional[ConfigFile]:
    '''Load config.'''
    config_file = super().load_config(filepath, update)
    return self.new_child(
        self.get_name(filepath), data=config_file, *args, **kwargs
    )

load_configs(self)

Load configuration files from filepaths.

Source code in compendium/config_manager.py
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
def load_configs(self) -> None:
    '''Load configuration files from filepaths.'''

    def get_child_paths(namepath: str):
        '''Get relative child paths of namepath.'''
        child_paths = []
        for path in self.filepaths[1:]:
            child_path = os.path.dirname(
                os.path.relpath(path, self.basedir)
            )
            if len(child_path.split(os.sep)) > 1 and child_path.startswith(
                namepath
            ):
                child_paths.append(path)
        return child_paths

    if self.children == ():
        # get children filepaths for parent
        filepaths = self.filepaths if self.parent else self.filepaths[1:]
        for x in filepaths:
            namepath = os.path.dirname(os.path.relpath(x, self.basedir))
            # print('---', self.name, namepath, self.parent)
            if len(namepath.split(os.sep)) == 1:
                child_paths = get_child_paths(namepath)
                children = list(self.children)
                children.append(
                    self.load_config(
                        x,
                        False,
                        *child_paths,
                        basedir=f"{self.basedir}{os.sep}{namepath}",
                    )
                )
                self.children = children
    else:
        raise exceptions.CompendiumConfigManagerError(
            'children configurations already loaded'
        )

new_child(self, name, *args, **kwargs)

Get child config node.

Source code in compendium/config_manager.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
def new_child(
    self, name: str, *args: str, **kwargs: Any
) -> 'TreeConfigManager':
    '''Get child config node.'''
    if 'basedir' not in kwargs:
        kwargs['basedir'] = self.basedir
    if 'filename' not in kwargs:
        kwargs['filename'] = self.filename
    kwargs['parent'] = self
    # (
    #     self.get_config(
    #         self.get_namepath(filepath).rsplit(self.separator, 1)[0]
    #     )
    # )

    data = self.data.maps
    # filepath = (
    #     kwargs.pop('filepath', None)
    #     or self.get_filepath(
    #         f"{self.separator}{self.name}{self.separator}{name}"
    #     )
    # )
    # if filepath is not None:
    #     config_file = self.load_config(filepath)
    #     if config_file is not None:
    #         data = [config_file] + data  # type: ignore
    if 'data' in kwargs and kwargs['data'] not in self.data.maps:
        data = [kwargs.pop('data')] + data
    kwargs['data'] = data
    kwargs['load_children'] = True
    return self.__class__(name, *args, **kwargs)