Skip to content

Commit 1e4b435

Browse files
committed
RWS: Refactor loading of configuration
Simplify it and bring it closer to how CMS itself loads its configuration.
1 parent 50eb75e commit 1e4b435

File tree

2 files changed

+32
-54
lines changed

2 files changed

+32
-54
lines changed

cmsranking/Config.py

Lines changed: 31 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -68,30 +68,27 @@ def __init__(self):
6868
sys.exit(1)
6969
self.log_dir = os.path.join(self.base_dir, 'log/ranking')
7070
self.lib_dir = os.path.join(self.base_dir, 'lib/ranking')
71-
self.conf_paths = [os.path.join(self.base_dir, 'etc/cms_ranking.toml')]
7271

73-
# Allow users to override config file path using environment
72+
# Default config file path can be overridden using environment
7473
# variable 'CMS_RANKING_CONFIG'.
75-
if CMS_RANKING_CONFIG_ENV_VAR in os.environ:
76-
self.conf_paths = [os.environ[CMS_RANKING_CONFIG_ENV_VAR]]
74+
default_config_file = os.path.join(self.base_dir, 'etc/cms_ranking.toml')
75+
self.config_file = os.environ.get('CMS_RANKING_CONFIG', default_config_file)
7776

7877
def get(self, key):
7978
"""Get the config value for the given key.
8079
8180
"""
8281
return getattr(self, key)
8382

84-
def load(self, config_override_fobj=None):
85-
"""Look for config files on disk and load them.
83+
def load(self, config_override: str | None = None):
84+
"""Load the configuration file.
8685
8786
"""
88-
# If a command-line override is given it is used exclusively.
89-
if config_override_fobj is not None:
90-
if not self._load_one(config_override_fobj):
91-
sys.exit(1)
92-
else:
93-
if not self._load_many(self.conf_paths):
94-
sys.exit(1)
87+
88+
config_file = config_override if config_override is not None else self.config_file
89+
if not self._load_config(config_file):
90+
logging.critical(f'Cannot load configuration file {config_file}')
91+
sys.exit(1)
9592

9693
try:
9794
os.makedirs(self.lib_dir)
@@ -110,58 +107,39 @@ def load(self, config_override_fobj=None):
110107

111108
add_file_handler(self.log_dir)
112109

113-
def _load_many(self, conf_paths: list[str]) -> bool:
114-
"""Load the first existing config file among the given ones.
115-
116-
Take a list of paths where config files may reside and attempt
117-
to load the first one that exists.
118-
119-
conf_paths: paths of config file candidates, from most
120-
to least prioritary.
121-
returns: whether loading was successful.
122-
123-
"""
124-
for conf_path in conf_paths:
125-
try:
126-
with open(conf_path, "rb") as conf_fobj:
127-
logger.info("Using config file %s.", conf_path)
128-
return self._load_one(conf_fobj)
129-
except FileNotFoundError:
130-
# If it doesn't exist we just skip to the next one.
131-
pass
132-
except OSError as error:
133-
logger.critical("Unable to access config file %s: [%s] %s.",
134-
conf_path, errno.errorcode[error.errno],
135-
os.strerror(error.errno))
136-
return False
137-
tried = " ".join(conf_paths)
138-
logging.warning(f"No configuration file found, tried: {tried}. "
139-
"Falling back to default values.")
140-
return True
141-
142-
def _load_one(self, conf_fobj: typing.BinaryIO) -> bool:
110+
def _load_config(self, path: str) -> bool:
143111
"""Populate config parameters from the given file.
144112
145113
Parse it as TOML and store in self all configuration properties
146114
it defines. Log critical message and return False if anything
147115
goes wrong or seems odd.
148116
149-
conf_fobj: the config file.
117+
path: the path of the TOML config file.
150118
returns: whether parsing was successful.
151119
152120
"""
153-
# Parse config file.
121+
# Load config file.
154122
try:
155-
data = tomllib.load(conf_fobj)
156-
except ValueError:
157-
logger.critical("Config file is invalid TOML.")
123+
with open(path, 'rb') as f:
124+
data = tomllib.load(f)
125+
except FileNotFoundError:
126+
logger.debug("Couldn't find config file %s (maybe you need to "
127+
"convert it from cms_ranking.conf to cms_ranking.toml?).", path)
128+
return False
129+
except OSError as error:
130+
logger.warning("I/O error while opening file %s: [%s] %s",
131+
path, errno.errorcode[error.errno],
132+
os.strerror(error.errno))
133+
return False
134+
except ValueError as error:
135+
logger.warning("Invalid syntax in file %s: %s", path, error)
158136
return False
159137

160138
# Store every config property.
161139
for key, value in data.items():
162-
if not hasattr(self, key):
163-
logger.critical("Invalid field %s in config file, maybe a "
164-
"typo?", key)
165-
return False
166-
setattr(self, key, value)
140+
if hasattr(self, key):
141+
setattr(self, key, value)
142+
else:
143+
logger.warning("Unrecognized key %s in config!", key)
144+
167145
return True

cmsranking/RankingWebServer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ def main() -> int:
526526
"""
527527
parser = argparse.ArgumentParser(
528528
description="Ranking for CMS.")
529-
parser.add_argument("--config", type=argparse.FileType("rb"),
529+
parser.add_argument("--config", type=str,
530530
help="override config file")
531531
parser.add_argument("-d", "--drop", action="store_true",
532532
help="drop the data already stored")

0 commit comments

Comments
 (0)