diff --git a/annif/default_config.py b/annif/default_config.py index 133225c14..cf310a289 100644 --- a/annif/default_config.py +++ b/annif/default_config.py @@ -36,3 +36,7 @@ class TestingInitializeConfig(TestingConfig): class TestingNoProjectsConfig(TestingConfig): PROJECTS_FILE = 'tests/notfound.cfg' + + +class TestingInvalidProjectsConfig(TestingConfig): + PROJECTS_FILE = 'tests/projects_invalid.cfg' diff --git a/annif/project.py b/annif/project.py index 5bd03d0b3..1454c76e7 100644 --- a/annif/project.py +++ b/annif/project.py @@ -62,10 +62,13 @@ def _init_access(self): project_id=self.project_id) def _initialize_analyzer(self): - analyzer = self.analyzer - logger.debug("Project '%s': initialized analyzer: %s", - self.project_id, - str(analyzer)) + try: + analyzer = self.analyzer + logger.debug("Project '%s': initialized analyzer: %s", + self.project_id, + str(analyzer)) + except AnnifException as err: + logger.warning(err.format_message()) def _initialize_subjects(self): try: @@ -87,10 +90,10 @@ def _initialize_vectorizer(self): def _initialize_backend(self): logger.debug("Project '%s': initializing backend", self.project_id) - if not self.backend: - logger.debug("Cannot initialize backend: does not exist") - return try: + if not self.backend: + logger.debug("Cannot initialize backend: does not exist") + return self.backend.initialize() except AnnifException as err: logger.warning(err.format_message()) @@ -120,13 +123,22 @@ def _suggest_with_backend(self, text, backend_params): @property def analyzer(self): - if self._analyzer is None and self.analyzer_spec: - self._analyzer = annif.analyzer.get_analyzer(self.analyzer_spec) + if self._analyzer is None: + if self.analyzer_spec: + self._analyzer = annif.analyzer.get_analyzer( + self.analyzer_spec) + else: + raise ConfigurationException( + "analyzer setting is missing (and needed by the backend)", + project_id=self.project_id) return self._analyzer @property def backend(self): if self._backend is None: + if 'backend' not in self.config: + raise ConfigurationException( + "backend setting is missing", project_id=self.project_id) backend_id = self.config['backend'] try: backend_class = annif.backend.get_backend(backend_id) @@ -214,7 +226,7 @@ def dump(self): return {'project_id': self.project_id, 'name': self.name, 'language': self.language, - 'backend': {'backend_id': self.config['backend']} + 'backend': {'backend_id': self.config.get('backend')} } @@ -230,7 +242,11 @@ def _create_projects(projects_file, datadir, init_projects): config = configparser.ConfigParser() config.optionxform = lambda option: option with open(projects_file, encoding='utf-8') as projf: - config.read_file(projf) + try: + config.read_file(projf) + except (configparser.DuplicateOptionError, + configparser.DuplicateSectionError) as err: + raise ConfigurationException(err) # create AnnifProject objects from the configuration file projects = collections.OrderedDict() diff --git a/tests/projects.cfg b/tests/projects.cfg index 8185205b8..eaccea36f 100644 --- a/tests/projects.cfg +++ b/tests/projects.cfg @@ -44,6 +44,12 @@ language=en backend=tfidf analyzer=snowball(english) +[nobackend] +name=Dummy with no backend +language=en +vocab=dummy +analyzer=snowball(english) + [pav] name=PAV Ensemble Finnish language=fi diff --git a/tests/projects_invalid.cfg b/tests/projects_invalid.cfg new file mode 100644 index 000000000..67b91cb9e --- /dev/null +++ b/tests/projects_invalid.cfg @@ -0,0 +1,23 @@ +# Project configuration for Annif unit tests + +[duplicatedproject] +name=Dummy with no backend +language=en +backend=dummy +vocab=dummy +analyzer=snowball(english) + +[duplicatedproject] +name=Dummy with no backend +language=en +backend=dummy +vocab=dummy +analyzer=snowball(english) + +[duplicatedvocab] +name=Dummy with no backend +language=en +backend=dummy +vocab=dummy +vocab=dummy +analyzer=snowball(english) diff --git a/tests/test_project.py b/tests/test_project.py index b70a41af4..331aedf7f 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -68,6 +68,13 @@ def test_get_project_nonexistent(app): annif.project.get_project('nonexistent') +def test_get_project_noanalyzer(app): + with app.app_context(): + project = annif.project.get_project('noanalyzer') + with pytest.raises(ConfigurationException): + analyzer = project.analyzer + + def test_get_project_novocab(app): with app.app_context(): project = annif.project.get_project('novocab') @@ -75,6 +82,21 @@ def test_get_project_novocab(app): vocab = project.vocab +def test_get_project_nobackend(app): + with app.app_context(): + project = annif.project.get_project('nobackend') + with pytest.raises(ConfigurationException): + backend = project.backend + + +def test_get_project_invalid_config_file(app): + app = annif.create_app( + config_name='annif.default_config.TestingInvalidProjectsConfig') + with app.app_context(): + with pytest.raises(ConfigurationException): + project = annif.project.get_project('duplicatedvocab') + + def test_project_load_vocabulary_tfidf(app, vocabulary, testdatadir): with app.app_context(): project = annif.project.get_project('tfidf-fi')