Skip to content

Commit b660eed

Browse files
authored
Merge pull request #300 from NatLibFi/issue282-handling-syntax-errors-in-projects-config
Issue282 handling syntax errors in projects config
2 parents d2dff10 + 47d4f2a commit b660eed

File tree

5 files changed

+82
-11
lines changed

5 files changed

+82
-11
lines changed

annif/default_config.py

+4
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ class TestingInitializeConfig(TestingConfig):
3636

3737
class TestingNoProjectsConfig(TestingConfig):
3838
PROJECTS_FILE = 'tests/notfound.cfg'
39+
40+
41+
class TestingInvalidProjectsConfig(TestingConfig):
42+
PROJECTS_FILE = 'tests/projects_invalid.cfg'

annif/project.py

+27-11
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,13 @@ def _init_access(self):
6363
project_id=self.project_id)
6464

6565
def _initialize_analyzer(self):
66-
analyzer = self.analyzer
67-
logger.debug("Project '%s': initialized analyzer: %s",
68-
self.project_id,
69-
str(analyzer))
66+
try:
67+
analyzer = self.analyzer
68+
logger.debug("Project '%s': initialized analyzer: %s",
69+
self.project_id,
70+
str(analyzer))
71+
except AnnifException as err:
72+
logger.warning(err.format_message())
7073

7174
def _initialize_subjects(self):
7275
try:
@@ -88,10 +91,10 @@ def _initialize_vectorizer(self):
8891

8992
def _initialize_backend(self):
9093
logger.debug("Project '%s': initializing backend", self.project_id)
91-
if not self.backend:
92-
logger.debug("Cannot initialize backend: does not exist")
93-
return
9494
try:
95+
if not self.backend:
96+
logger.debug("Cannot initialize backend: does not exist")
97+
return
9598
self.backend.initialize()
9699
except AnnifException as err:
97100
logger.warning(err.format_message())
@@ -121,13 +124,22 @@ def _suggest_with_backend(self, text, backend_params):
121124

122125
@property
123126
def analyzer(self):
124-
if self._analyzer is None and self.analyzer_spec:
125-
self._analyzer = annif.analyzer.get_analyzer(self.analyzer_spec)
127+
if self._analyzer is None:
128+
if self.analyzer_spec:
129+
self._analyzer = annif.analyzer.get_analyzer(
130+
self.analyzer_spec)
131+
else:
132+
raise ConfigurationException(
133+
"analyzer setting is missing (and needed by the backend)",
134+
project_id=self.project_id)
126135
return self._analyzer
127136

128137
@property
129138
def backend(self):
130139
if self._backend is None:
140+
if 'backend' not in self.config:
141+
raise ConfigurationException(
142+
"backend setting is missing", project_id=self.project_id)
131143
backend_id = self.config['backend']
132144
try:
133145
backend_class = annif.backend.get_backend(backend_id)
@@ -215,7 +227,7 @@ def dump(self):
215227
return {'project_id': self.project_id,
216228
'name': self.name,
217229
'language': self.language,
218-
'backend': {'backend_id': self.config['backend']}
230+
'backend': {'backend_id': self.config.get('backend')}
219231
}
220232

221233
def remove_model_data(self):
@@ -242,7 +254,11 @@ def _create_projects(projects_file, datadir, init_projects):
242254
config = configparser.ConfigParser()
243255
config.optionxform = lambda option: option
244256
with open(projects_file, encoding='utf-8') as projf:
245-
config.read_file(projf)
257+
try:
258+
config.read_file(projf)
259+
except (configparser.DuplicateOptionError,
260+
configparser.DuplicateSectionError) as err:
261+
raise ConfigurationException(err)
246262

247263
# create AnnifProject objects from the configuration file
248264
projects = collections.OrderedDict()

tests/projects.cfg

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ language=en
4444
backend=tfidf
4545
analyzer=snowball(english)
4646

47+
[nobackend]
48+
name=Dummy with no backend
49+
language=en
50+
vocab=dummy
51+
analyzer=snowball(english)
52+
4753
[pav]
4854
name=PAV Ensemble Finnish
4955
language=fi

tests/projects_invalid.cfg

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Project configuration for Annif unit tests
2+
3+
[duplicatedproject]
4+
name=Dummy with no backend
5+
language=en
6+
backend=dummy
7+
vocab=dummy
8+
analyzer=snowball(english)
9+
10+
[duplicatedproject]
11+
name=Dummy with no backend
12+
language=en
13+
backend=dummy
14+
vocab=dummy
15+
analyzer=snowball(english)
16+
17+
[duplicatedvocab]
18+
name=Dummy with no backend
19+
language=en
20+
backend=dummy
21+
vocab=dummy
22+
vocab=dummy
23+
analyzer=snowball(english)

tests/test_project.py

+22
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,35 @@ def test_get_project_nonexistent(app):
6868
annif.project.get_project('nonexistent')
6969

7070

71+
def test_get_project_noanalyzer(app):
72+
with app.app_context():
73+
project = annif.project.get_project('noanalyzer')
74+
with pytest.raises(ConfigurationException):
75+
analyzer = project.analyzer
76+
77+
7178
def test_get_project_novocab(app):
7279
with app.app_context():
7380
project = annif.project.get_project('novocab')
7481
with pytest.raises(ConfigurationException):
7582
vocab = project.vocab
7683

7784

85+
def test_get_project_nobackend(app):
86+
with app.app_context():
87+
project = annif.project.get_project('nobackend')
88+
with pytest.raises(ConfigurationException):
89+
backend = project.backend
90+
91+
92+
def test_get_project_invalid_config_file(app):
93+
app = annif.create_app(
94+
config_name='annif.default_config.TestingInvalidProjectsConfig')
95+
with app.app_context():
96+
with pytest.raises(ConfigurationException):
97+
project = annif.project.get_project('duplicatedvocab')
98+
99+
78100
def test_project_load_vocabulary_tfidf(app, vocabulary, testdatadir):
79101
with app.app_context():
80102
project = annif.project.get_project('tfidf-fi')

0 commit comments

Comments
 (0)