Passed
Pull Request — master (#645)
by Juho
02:55
created

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

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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