Completed
Pull Request — master (#272)
by Osma
04:32
created

annif.rest.analyze()   A

Complexity

Conditions 3

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 17
rs 9.75
c 0
b 0
f 0
cc 3
nop 4
1
"""Definitions for REST API operations. These are wired via Connexion to
2
methods defined in the Swagger specification."""
3
4
import connexion
5
import annif.project
6
from annif.corpus import Document, DocumentList
7
from annif.suggestion import SuggestionFilter
8
from annif.exception import AnnifException
9
from annif.project import Access
10
11
12
def project_not_found_error(project_id):
13
    """return a Connexion error object when a project is not found"""
14
15
    return connexion.problem(
16
        status=404,
17
        title='Project not found',
18
        detail="Project '{}' not found".format(project_id))
19
20
21
def server_error(err):
22
    """return a Connexion error object when there is a server error (project
23
    or backend problem)"""
24
25
    return connexion.problem(
26
        status=503,
27
        title='Service unavailable',
28
        detail=err.format_message())
29
30
31
def list_projects():
32
    """return a dict with projects formatted according to Swagger spec"""
33
34
    return {
35
        'projects': [
36
            proj.dump() for proj in annif.project.get_projects(
37
                min_access=Access.public).values()]}
38
39
40
def show_project(project_id):
41
    """return a single project formatted according to Swagger spec"""
42
43
    try:
44
        project = annif.project.get_project(
45
            project_id, min_access=Access.hidden)
46
    except ValueError:
47
        return project_not_found_error(project_id)
48
    return project.dump()
49
50
51
def suggest(project_id, text, limit, threshold):
52
    """suggest subjects for the given text and return a dict with results
53
    formatted according to Swagger spec"""
54
55
    try:
56
        project = annif.project.get_project(
57
            project_id, min_access=Access.hidden)
58
    except ValueError:
59
        return project_not_found_error(project_id)
60
61
    hit_filter = SuggestionFilter(limit, threshold)
62
    try:
63
        result = project.suggest(text)
64
    except AnnifException as err:
65
        return server_error(err)
66
    hits = hit_filter(result)
67
    return {'results': [hit._asdict() for hit in hits]}
68
69
70
def _documents_to_corpus(documents):
71
    corpus = [Document(text=d['text'],
72
                       uris=[subj['uri'] for subj in d['subjects']],
73
                       labels=[subj['label'] for subj in d['subjects']])
74
              for d in documents
75
              if 'text' in d and 'subjects' in d]
76
    return DocumentList(corpus)
77
78
79
def learn(project_id, documents):
80
    """learn from documents and return an empty 204 response if succesful"""
81
82
    try:
83
        project = annif.project.get_project(
84
            project_id, min_access=Access.hidden)
85
    except ValueError:
86
        return project_not_found_error(project_id)
87
88
    corpus = _documents_to_corpus(documents)
89
90
    try:
91
        project.learn(corpus)
92
    except AnnifException as err:
93
        return server_error(err)
94
95
    return None, 204
96