Passed
Pull Request — master (#645)
by Juho
03:15
created

annif.backend.http.HTTPBackend.modification_time()   A

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
"""HTTP/REST client backend that makes calls to a web service
2
and returns the results"""
3
4
5
import importlib
6
7
import dateutil.parser
8
import requests
9
import requests.exceptions
10
11
from annif.exception import OperationFailedException
12
from annif.suggestion import ListSuggestionResult, SubjectSuggestion
13
14
from . import backend
15
16
17
class HTTPBackend(backend.AnnifBackend):
18
    name = "http"
19
    _headers = None
20
21
    @property
22
    def headers(self):
23
        if self._headers is None:
24
            version = importlib.metadata.version("annif")
25
            self._headers = {
26
                "User-Agent": f"Annif/{version}",
27
            }
28
        return self._headers
29
30
    @property
31
    def is_trained(self):
32
        return self._get_project_info("is_trained")
33
34
    @property
35
    def modification_time(self):
36
        mtime = self._get_project_info("modification_time")
37
        if mtime is None:
38
            return None
39
        return dateutil.parser.parse(mtime)
40
41
    def _get_project_info(self, key):
42
        params = self._get_backend_params(None)
43
        try:
44
            req = requests.get(
45
                params["endpoint"].replace("/suggest", ""), headers=self.headers
46
            )
47
            req.raise_for_status()
48
        except requests.exceptions.RequestException as err:
49
            msg = f"HTTP request failed: {err}"
50
            raise OperationFailedException(msg) from err
51
        try:
52
            response = req.json()
53
        except ValueError as err:
54
            msg = f"JSON decode failed: {err}"
55
            raise OperationFailedException(msg) from err
56
57
        if key in response:
58
            return response[key]
59
        else:
60
            return None
61
62
    def _suggest(self, text, params):
63
        data = {"text": text}
64
        if "project" in params:
65
            data["project"] = params["project"]
66
67
        try:
68
            req = requests.post(params["endpoint"], data=data, headers=self.headers)
69
            req.raise_for_status()
70
        except requests.exceptions.RequestException as err:
71
            self.warning("HTTP request failed: {}".format(err))
72
            return ListSuggestionResult([])
73
74
        try:
75
            response = req.json()
76
        except ValueError as err:
77
            self.warning("JSON decode failed: {}".format(err))
78
            return ListSuggestionResult([])
79
80
        if "results" in response:
81
            results = response["results"]
82
        else:
83
            results = response
84
85
        try:
86
            subject_suggestions = [
87
                SubjectSuggestion(
88
                    subject_id=self.project.subjects.by_uri(hit["uri"]),
89
                    score=hit["score"],
90
                )
91
                for hit in results
92
                if hit["score"] > 0.0
93
            ]
94
        except (TypeError, ValueError) as err:
95
            self.warning("Problem interpreting JSON data: {}".format(err))
96
            return ListSuggestionResult([])
97
98
        return ListSuggestionResult(subject_suggestions)
99