Completed
Push — master ( aff041...1d33ed )
by Juho
20s queued 18s
created

annif.config.AnnifConfigDirectory.__getitem__()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 2
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 2
dl 2
loc 2
rs 10
c 0
b 0
f 0
1
"""Configuration file handling"""
2
3
4
import os.path
5
import configparser
6
import tomli
7
import annif
8
import annif.util
9
from glob import glob
10
from annif.exception import ConfigurationException
11
12
13
logger = annif.logger
14
15
16 View Code Duplication
class AnnifConfigCFG:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
17
    """Class for reading configuration in CFG/INI format"""
18
19
    def __init__(self, filename):
20
        self._config = configparser.ConfigParser()
21
        self._config.optionxform = annif.util.identity
22
        with open(filename, encoding='utf-8-sig') as projf:
23
            try:
24
                logger.debug(
25
                    f"Reading configuration file {filename} in CFG format")
26
                self._config.read_file(projf)
27
            except (configparser.DuplicateOptionError,
28
                    configparser.DuplicateSectionError) as err:
29
                raise ConfigurationException(err)
30
31
    @property
32
    def project_ids(self):
33
        return self._config.sections()
34
35
    def __getitem__(self, key):
36
        return self._config[key]
37
38
39 View Code Duplication
class AnnifConfigTOML:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
40
    """Class for reading configuration in TOML format"""
41
42
    def __init__(self, filename):
43
        with open(filename, "rb") as projf:
44
            try:
45
                logger.debug(
46
                    f"Reading configuration file {filename} in TOML format")
47
                self._config = tomli.load(projf)
48
            except tomli.TOMLDecodeError as err:
49
                raise ConfigurationException(
50
                    f"Parsing TOML file '{filename}' failed: {err}")
51
52
    @property
53
    def project_ids(self):
54
        return self._config.keys()
55
56
    def __getitem__(self, key):
57
        return self._config[key]
58
59
60 View Code Duplication
class AnnifConfigDirectory:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
61
    """Class for reading configuration from directory"""
62
63
    def __init__(self, directory):
64
        files = glob(os.path.join(directory, '*.cfg'))
65
        files.extend(glob(os.path.join(directory, '*.toml')))
66
        logger.debug(f"Reading configuration files in directory {directory}")
67
68
        self._config = dict()
69
        for file in files:
70
            source_config = parse_config(file)
71
            for proj_id in source_config.project_ids:
72
                self._check_duplicate_project_ids(proj_id, file)
73
                self._config[proj_id] = source_config[proj_id]
74
75
    def _check_duplicate_project_ids(self, proj_id, file):
76
        if proj_id in self._config:
77
            # Error message resembles configparser's DuplicateSection message
78
            raise ConfigurationException(
79
                f'While reading from "{file}": project ID "{proj_id}" already '
80
                'exists in another configuration file in the directory.')
81
82
    @property
83
    def project_ids(self):
84
        return self._config.keys()
85
86
    def __getitem__(self, key):
87
        return self._config[key]
88
89
90
def check_config(projects_config_path):
91
    if os.path.exists(projects_config_path):
92
        return projects_config_path
93
    else:
94
        logger.warning(
95
            'Project configuration file or directory ' +
96
            f'"{projects_config_path}" is missing. Please provide one. ' +
97
            'You can set the path to the project configuration ' +
98
            'using the ANNIF_PROJECTS environment ' +
99
            'variable or the command-line option "--projects".')
100
        return None
101
102
103
def find_config():
104
    for path in ('projects.cfg', 'projects.toml', 'projects.d'):
105
        if os.path.exists(path):
106
            return path
107
108
    logger.warning(
109
        'Could not find project configuration ' +
110
        '"projects.cfg", "projects.toml" or "projects.d". ' +
111
        'You can set the path to the project configuration ' +
112
        'using the ANNIF_PROJECTS environment ' +
113
        'variable or the command-line option "--projects".')
114
    return None
115
116
117 View Code Duplication
def parse_config(projects_config_path):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
118
    if projects_config_path:
119
        projects_config_path = check_config(projects_config_path)
120
    else:
121
        projects_config_path = find_config()
122
123
    if not projects_config_path:  # not found
124
        return None
125
126
    if os.path.isdir(projects_config_path):
127
        return AnnifConfigDirectory(projects_config_path)
128
    elif projects_config_path.endswith('.toml'):  # TOML format
129
        return AnnifConfigTOML(projects_config_path)
130
    else:  # classic CFG/INI style format
131
        return AnnifConfigCFG(projects_config_path)
132