Changeset View
Standalone View
swh/core/config.py
# Copyright (C) 2015-2020 The Software Heritage developers | # Copyright (C) 2015-2020 The Software Heritage developers | ||||
# See the AUTHORS file at the top-level directory of this distribution | # See the AUTHORS file at the top-level directory of this distribution | ||||
# License: GNU General Public License version 3, or any later version | # License: GNU General Public License version 3, or any later version | ||||
# See top-level LICENSE file for more information | # See top-level LICENSE file for more information | ||||
from copy import deepcopy | from copy import deepcopy | ||||
from itertools import chain | from itertools import chain | ||||
import logging | import logging | ||||
import os | import os | ||||
from typing import Any, Callable, Dict, List, Optional, Tuple | from typing import Any, Callable, Dict, List, Optional, Tuple | ||||
from deprecated import deprecated | |||||
import yaml | import yaml | ||||
logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||
SWH_CONFIG_DIRECTORIES = [ | SWH_CONFIG_DIRECTORIES = [ | ||||
"~/.config/swh", | "~/.config/swh", | ||||
"~/.swh", | "~/.swh", | ||||
▲ Show 20 Lines • Show All 261 Lines • ▼ Show 20 Lines | def load_named_config(name, default_conf=None, global_conf=True): | ||||
if global_conf: | if global_conf: | ||||
conf.update(load_global_config()) | conf.update(load_global_config()) | ||||
conf.update(priority_read(swh_config_paths(name), default_conf)) | conf.update(priority_read(swh_config_paths(name), default_conf)) | ||||
return conf | return conf | ||||
def load_from_envvar(default_config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: | |||||
"""Load configuration yaml file from the environment variable SWH_CONFIG_FILENAME, | |||||
eventually enriched with default configuration key/value from the default_config | |||||
dict if provided. | |||||
Returns: | |||||
Configuration dict | |||||
Raises: | |||||
AssertionError if SWH_CONFIG_FILENAME is undefined | |||||
""" | |||||
assert ( | |||||
"SWH_CONFIG_FILENAME" in os.environ | |||||
), "SWH_CONFIG_FILENAME environment variable is undefined." | |||||
cfg_path = os.environ["SWH_CONFIG_FILENAME"] | |||||
cfg = read_raw_config(config_basepath(cfg_path)) | |||||
cfg = merge_configs(default_config or {}, cfg) | |||||
return cfg | |||||
@deprecated(version="0.3.0", reason="Use swh.core.config.load_from_envvar instead") | |||||
class SWHConfig: | class SWHConfig: | ||||
"""Mixin to add configuration parsing abilities to classes | """Mixin to add configuration parsing abilities to classes | ||||
The class should override the class attributes: | The class should override the class attributes: | ||||
- DEFAULT_CONFIG (default configuration to be parsed) | - DEFAULT_CONFIG (default configuration to be parsed) | ||||
- CONFIG_BASE_FILENAME (the filename of the configuration to be used) | - CONFIG_BASE_FILENAME (the filename of the configuration to be used) | ||||
This class defines one classmethod, parse_config_file, which | This class defines one classmethod, parse_config_file, which | ||||
parses a configuration file using the default config as set in the | parses a configuration file using the default config as set in the | ||||
class attribute. | class attribute. | ||||
""" | """ | ||||
tenma: `assert "SWH_CONFIG_FILENAME" in os.environ, "SWH_CONFIG_FILENAME environment variable is… | |||||
DEFAULT_CONFIG = {} # type: Dict[str, Tuple[str, Any]] | DEFAULT_CONFIG = {} # type: Dict[str, Tuple[str, Any]] | ||||
CONFIG_BASE_FILENAME = "" # type: Optional[str] | CONFIG_BASE_FILENAME = "" # type: Optional[str] | ||||
Done Inline ActionsWARNING: mutable value in class definition. As with function definitions, this will only be eval'd once.
I think this class is meant to be instanciated, we don't want to share config between instances. In that case, use factory like attrs ones or write a constructor.
For this, we better think of a strategy that does not involves user discipline but works automatically. tenma: WARNING: mutable value in class definition. As with function definitions, this will only be… | |||||
Done Inline Actionsalternatively, we can just make it None vlorentz: alternatively, we can just make it None | |||||
Done Inline ActionsNo, often a bad idea to have nullable types where it is not necessary, for reliability reasons. In this mixin, only a declaration, which conveniently serves as a spec btw, and in user class only an initialization is needed. In fact it could be seen as a lazy constant, which is very safe (reliable) construct. tenma: No, often a bad idea to have nullable types where it is not necessary, for reliability reasons. | |||||
Done Inline Actions
I'm opened to an example of what's implied by that suggestion. Please, for example, wrap the snippet in tiple backquote <sample-code> so it's nicely rendered here ;) ardumont: > WARNING
> ...
I'm opened to an example of what's implied by that suggestion.
Please, for… | |||||
Done Inline Actionsto be complete, here is @tenma's suggestion: @attr.s class Config: conf = attr.ib(factory=dict) ardumont: to be complete, here is @tenma's suggestion:
```
@attr.s
class Config:
conf = attr.ib… | |||||
@classmethod | @classmethod | ||||
def parse_config_file( | def parse_config_file( | ||||
cls, | cls, | ||||
base_filename=None, | base_filename=None, | ||||
config_filename=None, | config_filename=None, | ||||
additional_configs=None, | additional_configs=None, | ||||
global_config=True, | global_config=True, | ||||
Show All 33 Lines | ): | ||||
cls.DEFAULT_CONFIG, *additional_configs | cls.DEFAULT_CONFIG, *additional_configs | ||||
) | ) | ||||
config = {} | config = {} | ||||
if global_config: | if global_config: | ||||
config = load_global_config() | config = load_global_config() | ||||
config.update(priority_read(config_filenames, full_default_config)) | config.update(priority_read(config_filenames, full_default_config)) | ||||
Done Inline Actionss/should be defined/is undefined vlorentz: s/should be defined/is undefined | |||||
return config | return config | ||||
Done Inline ActionsA default config, albeit empty, is defined (as dict), and merge_config has no input domain restriction. So this conditional is not needed. tenma: A default config, albeit empty, is defined (as dict), and `merge_config` has no input domain… | |||||
Done Inline ActionsI repeat, this branch will always match, so no need to keep it. tenma: I repeat, this branch will always match, so no need to keep it. | |||||
Done Inline Actionsyes, I did not adapt it yet since i'm unclear as to what i need to do for the DEFAULT_CONFIG field remark first... ardumont: yes, I did not adapt it yet since i'm unclear as to what i need to do for the DEFAULT_CONFIG… |
assert "SWH_CONFIG_FILENAME" in os.environ, "SWH_CONFIG_FILENAME environment variable is undefined." est encore plus clair, ça dit "vous avez pas suivi le contrat"