-
Notifications
You must be signed in to change notification settings - Fork 9
/
api_v1.py
174 lines (143 loc) · 5.9 KB
/
api_v1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# -*- coding: utf-8 -*-
"""
.. module:: MyCapytain.resolvers.cts.remote
:synopsis: Resolver built for CTS APIs
.. moduleauthor:: Thibault Clérice <leponteineptique@gmail.com>
"""
from typing import Union, Optional, Any, Dict
import re
from pyld.jsonld import expand
from MyCapytain.resolvers.prototypes import Resolver
from MyCapytain.common.reference import BaseReference, BaseReferenceSet, \
DtsReference, DtsReferenceSet, DtsCitation
from MyCapytain.retrievers.dts import HttpDtsRetriever
from MyCapytain.common.utils.dts import parse_metadata
from MyCapytain.resources.collections.dts import HttpResolverDtsCollection
from MyCapytain.resources.texts.remote.dts import DtsResolverDocument
from MyCapytain.errors import EmptyReference, PaginationBrowsingError
__all__ = [
"HttpDtsResolver"
]
_empty = [{"@value": None}]
_re_page = re.compile("page=(\d+)")
def _parse_ref(ref_dict, default_type: str=None):
if "https://w3id.org/dts/api#ref" in ref_dict:
refs = ref_dict["https://w3id.org/dts/api#ref"][0]["@value"],
elif "https://w3id.org/dts/api#start" in ref_dict and \
"https://w3id.org/dts/api#end" in ref_dict:
refs = (
ref_dict["https://w3id.org/dts/api#start"][0]["@value"],
ref_dict["https://w3id.org/dts/api#end"][0]["@value"]
)
else:
raise EmptyReference("A reference is either empty or malformed")
type_ = default_type
if "https://w3id.org/dts/api#citeType" in ref_dict:
type_ = ref_dict["https://w3id.org/dts/api#citeType"][0]["@value"]
obj = DtsReference(*refs, type_=type_)
parse_metadata(obj.metadata, ref_dict)
return obj
class HttpDtsResolver(Resolver):
""" HttpDtsResolver provide a resolver for DTS API http endpoint.
:param endpoint: DTS API Retriever
"""
def __init__(self, endpoint: Union[str, HttpDtsRetriever]):
if not isinstance(endpoint, HttpDtsRetriever):
endpoint = HttpDtsRetriever(endpoint)
self._endpoint = endpoint
@property
def endpoint(self) -> HttpDtsRetriever:
""" DTS Endpoint of the resolver
:return: DTS Endpoint
:rtype: HttpDtsRetriever
"""
return self._endpoint
def getMetadata(self, objectId: str=None, **filters) -> HttpResolverDtsCollection:
""" Retrieves metadata calling the Collections Endpoint """
req = self.endpoint.get_collection(objectId)
req.raise_for_status()
collection = HttpResolverDtsCollection.parse(req.json(), resolver=self)
# Pagination is not completed upon first query.
# Pagination will be treated direction in the HttpResolverDtsCollection
return collection
def getReffs(
self,
textId: str,
level: int=1,
subreference: Union[str, BaseReference]=None,
include_descendants: bool=False,
additional_parameters: Optional[Dict[str, Any]]=None
) -> DtsReferenceSet:
""" Retrieve references by calling the Navigation API """
if not additional_parameters:
additional_parameters = {}
references = []
default_type = None
level_ = level
page = 1
while page:
kwargs = dict(
level=level, ref=subreference,
exclude=additional_parameters.get("exclude", None),
group_by=additional_parameters.get("groupBy", 1)
)
if page != 1:
kwargs["page"] = page
response = self.endpoint.get_navigation(textId, **kwargs)
response.raise_for_status()
data = response.json()
data = expand(data)
if not len(data):
raise PaginationBrowsingError(
"The contacted endpoint seems to not have any data about collection %s " % self.id
)
data = data[0]
level_ = data.get("https://w3id.org/dts/api#level", _empty)[0]["@value"]
default_type = data.get("https://w3id.org/dts/api#citeType", _empty)[0]["@value"]
members = data.get("https://www.w3.org/ns/hydra/core#member", [])
references.extend([
_parse_ref(ref, default_type=default_type)
for ref in members
])
page = None
if "https://www.w3.org/ns/hydra/core#view" in data:
if "https://www.w3.org/ns/hydra/core#next" in data["https://www.w3.org/ns/hydra/core#view"][0]:
page = _re_page.findall(
data["https://www.w3.org/ns/hydra/core#view"]
[0]["https://www.w3.org/ns/hydra/core#next"]
[0]["@value"]
)[0]
citation = None
if default_type:
citation = DtsCitation(name=default_type)
reffs = DtsReferenceSet(
*references,
level=level_,
citation=citation
)
return reffs
def getTextualNode(
self,
textId: str,
subreference: Union[str, BaseReference]=None,
prevnext: bool=False,
metadata: bool=False
) -> DtsResolverDocument:
""" Retrieve a text node from the API via the Document Endpoint
:param textId: CtsTextMetadata Identifier
:type textId: str
:param subreference: CapitainsCtsPassage Reference
:type subreference: str
:param prevnext: Retrieve graph representing previous and next passage
:type prevnext: boolean
:param metadata: Retrieve metadata about the passage and the text
:type metadata: boolean
:return: CapitainsCtsPassage
:rtype: CapitainsCtsPassage
"""
return DtsResolverDocument.parse(
identifier=textId,
reference=subreference,
resolver=self,
response=self.endpoint.get_document(collection_id=textId, ref=subreference)
)