Skip to content

Commit bbfcf33

Browse files
authored
Merge pull request #367 from gkreitz/178_repository_local_languages_yaml
Load language config from parent of problem dir, if present #178
2 parents 16dd35d + 9ebafbf commit bbfcf33

File tree

4 files changed

+21
-17
lines changed

4 files changed

+21
-17
lines changed

problemtools/config.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,58 @@
11
import collections
22
import os
33
import yaml
4+
from pathlib import Path
5+
from typing import Mapping
46

57

68
class ConfigError(Exception):
79
pass
810

911

10-
def load_config(configuration_file):
12+
def load_config(configuration_file: str, priority_dirs: list[Path] = []) -> dict:
1113
"""Load a problemtools configuration file.
1214
1315
Args:
1416
configuration_file (str): name of configuration file. Name is
1517
relative to config directory so typically just a file name
1618
without paths, e.g. "languages.yaml".
1719
"""
18-
res = None
20+
res: dict | None = None
1921

20-
for dirname in __config_file_paths():
21-
path = os.path.join(dirname, configuration_file)
22+
for dirname in __config_file_paths() + priority_dirs:
23+
path = dirname / configuration_file
2224
new_config = None
23-
if os.path.isfile(path):
25+
if path.is_file():
2426
try:
2527
with open(path, 'r') as config:
2628
new_config = yaml.safe_load(config.read())
2729
except (yaml.parser.ParserError, yaml.scanner.ScannerError) as err:
28-
raise ConfigError('Config file %s: failed to parse: %s' % (path, err))
30+
raise ConfigError(f'Config file {path}: failed to parse: {err}')
2931
if res is None:
3032
if new_config is None:
31-
raise ConfigError('Base configuration file %s not found in %s' % (configuration_file, path))
33+
raise ConfigError(f'Base configuration file {configuration_file} not found in {path}')
3234
res = new_config
3335
elif new_config is not None:
3436
__update_dict(res, new_config)
3537

38+
assert res is not None, 'Failed to load config (should never happen, we should have hit an error in loop above)'
3639
return res
3740

3841

39-
def __config_file_paths():
42+
def __config_file_paths() -> list[Path]:
4043
"""
4144
Paths in which to look for config files, by increasing order of
4245
priority (i.e., any config in the last path should take precedence
4346
over the others).
4447
"""
4548
return [
46-
os.path.join(os.path.dirname(__file__), 'config'),
47-
os.path.join('/etc', 'kattis', 'problemtools'),
48-
os.path.join(os.environ.get('XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')), 'problemtools'),
49+
Path(__file__).parent / 'config',
50+
Path('/etc/kattis/problemtools'),
51+
Path(os.environ.get('XDG_CONFIG_HOME', Path.home() / '.config')) / 'problemtools',
4952
]
5053

5154

52-
def __update_dict(orig, update):
55+
def __update_dict(orig: dict, update: Mapping) -> None:
5356
"""Deep update of a dictionary
5457
5558
For each entry (k, v) in update such that both orig[k] and v are

problemtools/languages.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import fnmatch
77
import re
88
import string
9+
from pathlib import Path
910

1011
from . import config
1112

@@ -218,10 +219,10 @@ def update(self, data):
218219
priorities[lang.priority] = lang_id
219220

220221

221-
def load_language_config():
222+
def load_language_config(probdir_parent: Path) -> Languages:
222223
"""Load language configuration.
223224
224225
Returns:
225226
Languages object for the set of languages.
226227
"""
227-
return Languages(config.load_config('languages.yaml'))
228+
return Languages(config.load_config('languages.yaml', [probdir_parent]))

problemtools/verifyproblem.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1902,7 +1902,7 @@ def __init__(self, probdir: str, args: argparse.Namespace):
19021902
self.probdir = os.path.realpath(probdir)
19031903
self.shortname: str = os.path.basename(self.probdir)
19041904
super().__init__(self.shortname, self)
1905-
self.language_config = languages.load_language_config()
1905+
self.language_config = languages.load_language_config(Path(self.probdir).parent)
19061906
self.testcase_by_infile: dict[str, TestCase] = {}
19071907
self.loaded = False
19081908
self._metadata: metadata.Metadata | None = None

tests/test_config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66

77
def config_paths_mock():
8-
import os
8+
from pathlib import Path
99

10-
return [os.path.join(os.path.dirname(__file__), 'config1'), os.path.join(os.path.dirname(__file__), 'config2')]
10+
return [Path(__file__).parent / 'config1', Path(__file__).parent / 'config2']
1111

1212

1313
def test_load_basic_config(monkeypatch):

0 commit comments

Comments
 (0)