personal_knowledge_library 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of personal_knowledge_library might be problematic. Click here for more details.
- knowledge/__init__.py +91 -0
- knowledge/base/__init__.py +22 -0
- knowledge/base/access.py +167 -0
- knowledge/base/entity.py +267 -0
- knowledge/base/language.py +27 -0
- knowledge/base/ontology.py +2734 -0
- knowledge/base/search.py +473 -0
- knowledge/base/tenant.py +192 -0
- knowledge/nel/__init__.py +11 -0
- knowledge/nel/base.py +495 -0
- knowledge/nel/engine.py +123 -0
- knowledge/ontomapping/__init__.py +667 -0
- knowledge/ontomapping/manager.py +320 -0
- knowledge/public/__init__.py +27 -0
- knowledge/public/cache.py +115 -0
- knowledge/public/helper.py +373 -0
- knowledge/public/relations.py +128 -0
- knowledge/public/wikidata.py +1324 -0
- knowledge/services/__init__.py +128 -0
- knowledge/services/asyncio/__init__.py +7 -0
- knowledge/services/asyncio/base.py +458 -0
- knowledge/services/asyncio/graph.py +1420 -0
- knowledge/services/asyncio/group.py +450 -0
- knowledge/services/asyncio/search.py +439 -0
- knowledge/services/asyncio/users.py +270 -0
- knowledge/services/base.py +533 -0
- knowledge/services/graph.py +1897 -0
- knowledge/services/group.py +819 -0
- knowledge/services/helper.py +142 -0
- knowledge/services/ontology.py +1234 -0
- knowledge/services/search.py +488 -0
- knowledge/services/session.py +444 -0
- knowledge/services/tenant.py +281 -0
- knowledge/services/users.py +445 -0
- knowledge/utils/__init__.py +10 -0
- knowledge/utils/graph.py +417 -0
- knowledge/utils/wikidata.py +197 -0
- knowledge/utils/wikipedia.py +175 -0
- personal_knowledge_library-3.0.0.dist-info/LICENSE +201 -0
- personal_knowledge_library-3.0.0.dist-info/METADATA +1163 -0
- personal_knowledge_library-3.0.0.dist-info/RECORD +42 -0
- personal_knowledge_library-3.0.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,1420 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright © 2024-present Wacom. All rights reserved.
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import urllib
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Optional, List, Dict, Tuple
|
|
9
|
+
from urllib.parse import urlparse
|
|
10
|
+
|
|
11
|
+
import aiohttp
|
|
12
|
+
import orjson
|
|
13
|
+
|
|
14
|
+
from knowledge.base.entity import (
|
|
15
|
+
DATA_PROPERTIES_TAG,
|
|
16
|
+
TYPE_TAG,
|
|
17
|
+
URI_TAG,
|
|
18
|
+
LABELS_TAG,
|
|
19
|
+
IS_MAIN_TAG,
|
|
20
|
+
RELATIONS_TAG,
|
|
21
|
+
LOCALE_TAG,
|
|
22
|
+
EntityStatus,
|
|
23
|
+
Label,
|
|
24
|
+
URIS_TAG,
|
|
25
|
+
FORCE_TAG,
|
|
26
|
+
VISIBILITY_TAG,
|
|
27
|
+
RELATION_TAG,
|
|
28
|
+
TEXT_TAG,
|
|
29
|
+
)
|
|
30
|
+
from knowledge.base.language import LocaleCode, EN_US
|
|
31
|
+
from knowledge.base.ontology import (
|
|
32
|
+
DataProperty,
|
|
33
|
+
OntologyPropertyReference,
|
|
34
|
+
ThingObject,
|
|
35
|
+
OntologyClassReference,
|
|
36
|
+
ObjectProperty,
|
|
37
|
+
)
|
|
38
|
+
from knowledge.nel.base import KnowledgeGraphEntity, EntityType, KnowledgeSource, EntitySource
|
|
39
|
+
from knowledge.services import AUTHORIZATION_HEADER_FLAG, IS_OWNER_PARAM
|
|
40
|
+
from knowledge.services import (
|
|
41
|
+
SUBJECT_URI,
|
|
42
|
+
RELATION_URI,
|
|
43
|
+
OBJECT_URI,
|
|
44
|
+
LANGUAGE_PARAMETER,
|
|
45
|
+
LIMIT,
|
|
46
|
+
LISTING,
|
|
47
|
+
TOTAL_COUNT,
|
|
48
|
+
SEARCH_TERM,
|
|
49
|
+
TYPES_PARAMETER,
|
|
50
|
+
APPLICATION_JSON_HEADER,
|
|
51
|
+
SUBJECT,
|
|
52
|
+
OBJECT,
|
|
53
|
+
PREDICATE,
|
|
54
|
+
LIMIT_PARAMETER,
|
|
55
|
+
ESTIMATE_COUNT,
|
|
56
|
+
TARGET,
|
|
57
|
+
ACTIVATION_TAG,
|
|
58
|
+
SEARCH_PATTERN_PARAMETER,
|
|
59
|
+
LITERAL_PARAMETER,
|
|
60
|
+
VALUE,
|
|
61
|
+
NEXT_PAGE_ID_TAG,
|
|
62
|
+
ENTITIES_TAG,
|
|
63
|
+
RESULT_TAG,
|
|
64
|
+
EXACT_MATCH,
|
|
65
|
+
)
|
|
66
|
+
from knowledge.services.asyncio.base import AsyncServiceAPIClient, handle_error
|
|
67
|
+
from knowledge.services.base import (
|
|
68
|
+
WacomServiceAPIClient,
|
|
69
|
+
WacomServiceException,
|
|
70
|
+
USER_AGENT_HEADER_FLAG,
|
|
71
|
+
CONTENT_TYPE_HEADER_FLAG,
|
|
72
|
+
DEFAULT_TIMEOUT,
|
|
73
|
+
format_exception,
|
|
74
|
+
)
|
|
75
|
+
from knowledge.services.graph import Visibility, SearchPattern, MIME_TYPE
|
|
76
|
+
from knowledge.services.helper import split_updates, entity_payload
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# -------------------------------------------- Service API Client ------------------------------------------------------
|
|
80
|
+
class AsyncWacomKnowledgeService(AsyncServiceAPIClient):
|
|
81
|
+
"""
|
|
82
|
+
AsyncWacomKnowledgeService
|
|
83
|
+
---------------------
|
|
84
|
+
Client for the Semantic Ink Private knowledge system.
|
|
85
|
+
|
|
86
|
+
Operations for entities:
|
|
87
|
+
- Creation of entities
|
|
88
|
+
- Update of entities
|
|
89
|
+
- Deletion of entities
|
|
90
|
+
- Listing of entities
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
application_name: str
|
|
95
|
+
Name of the application
|
|
96
|
+
service_url: str
|
|
97
|
+
URL of the service
|
|
98
|
+
service_endpoint: str
|
|
99
|
+
Base endpoint
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
USER_ENDPOINT: str = "user"
|
|
103
|
+
ENTITY_ENDPOINT: str = "entity"
|
|
104
|
+
ENTITY_BULK_ENDPOINT: str = "entity/bulk"
|
|
105
|
+
ENTITY_IMAGE_ENDPOINT: str = "entity/image/"
|
|
106
|
+
ACTIVATIONS_ENDPOINT: str = "entity/activations"
|
|
107
|
+
LISTING_ENDPOINT: str = "entity/types"
|
|
108
|
+
NAMED_ENTITY_LINKING_ENDPOINT: str = "nel/text"
|
|
109
|
+
RELATION_ENDPOINT: str = "entity/{}/relation"
|
|
110
|
+
RELATIONS_ENDPOINT: str = "entity/{}/relations"
|
|
111
|
+
SEARCH_LABELS_ENDPOINT: str = "semantic-search/labels"
|
|
112
|
+
SEARCH_TYPES_ENDPOINT: str = "semantic-search/types"
|
|
113
|
+
SEARCH_LITERALS_ENDPOINT: str = "semantic-search/literal"
|
|
114
|
+
SEARCH_DESCRIPTION_ENDPOINT: str = "semantic-search/description"
|
|
115
|
+
SEARCH_RELATION_ENDPOINT: str = "semantic-search/relation"
|
|
116
|
+
ONTOLOGY_UPDATE_ENDPOINT: str = "ontology-update"
|
|
117
|
+
|
|
118
|
+
def __init__(
|
|
119
|
+
self,
|
|
120
|
+
application_name: str,
|
|
121
|
+
service_url: str = WacomServiceAPIClient.SERVICE_URL,
|
|
122
|
+
service_endpoint: str = "graph/v1",
|
|
123
|
+
graceful_shutdown: bool = False,
|
|
124
|
+
):
|
|
125
|
+
super().__init__(
|
|
126
|
+
application_name=application_name,
|
|
127
|
+
service_url=service_url,
|
|
128
|
+
service_endpoint=service_endpoint,
|
|
129
|
+
graceful_shutdown=graceful_shutdown,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
async def entity(self, uri: str, auth_key: Optional[str] = None) -> ThingObject:
|
|
133
|
+
"""
|
|
134
|
+
Retrieve entity information from personal knowledge, using the URI as identifier.
|
|
135
|
+
|
|
136
|
+
**Remark:** Object properties (relations) must be requested separately.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
uri: str
|
|
141
|
+
URI of entity
|
|
142
|
+
auth_key: Optional[str]
|
|
143
|
+
Use a different auth key than the one from the client
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
thing: ThingObject
|
|
148
|
+
Entities with is type URI, description, an image/icon, and tags (labels).
|
|
149
|
+
|
|
150
|
+
Raises
|
|
151
|
+
------
|
|
152
|
+
WacomServiceException
|
|
153
|
+
If the graph service returns an error code or the entity is not found in the knowledge graph
|
|
154
|
+
"""
|
|
155
|
+
if auth_key is None:
|
|
156
|
+
auth_key, _ = await self.handle_token()
|
|
157
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{uri}"
|
|
158
|
+
headers: Dict[str, str] = {
|
|
159
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
160
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
161
|
+
}
|
|
162
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
163
|
+
async with session.get(url, headers=headers, verify_ssl=self.verify_calls) as response:
|
|
164
|
+
if response.ok:
|
|
165
|
+
e: Dict[str, Any] = await response.json()
|
|
166
|
+
pref_label: List[Label] = []
|
|
167
|
+
aliases: List[Label] = []
|
|
168
|
+
# Extract labels and alias
|
|
169
|
+
for label in e[LABELS_TAG]:
|
|
170
|
+
if label[IS_MAIN_TAG]: # Labels
|
|
171
|
+
pref_label.append(Label.create_from_dict(label))
|
|
172
|
+
else: # Alias
|
|
173
|
+
aliases.append(Label.create_from_dict(label))
|
|
174
|
+
else:
|
|
175
|
+
raise await handle_error(
|
|
176
|
+
f"Retrieving of entity content failed. URI:={uri}.", response, headers=headers
|
|
177
|
+
)
|
|
178
|
+
await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
|
|
179
|
+
# Create ThingObject
|
|
180
|
+
thing: ThingObject = ThingObject.from_dict(e)
|
|
181
|
+
return thing
|
|
182
|
+
|
|
183
|
+
async def set_entity_image_local(self, entity_uri: str, path: Path, auth_key: Optional[str] = None) -> str:
|
|
184
|
+
"""Setting the image of the entity.
|
|
185
|
+
The image is stored locally.
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
entity_uri: str
|
|
190
|
+
URI of the entity.
|
|
191
|
+
path: Path
|
|
192
|
+
The path of image.
|
|
193
|
+
auth_key: Optional[str] [default:=None]
|
|
194
|
+
Auth key from user if not set, the client auth key will be used
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
image_id: str
|
|
199
|
+
ID of uploaded image
|
|
200
|
+
|
|
201
|
+
Raises
|
|
202
|
+
------
|
|
203
|
+
WacomServiceException
|
|
204
|
+
If the graph service returns an error code.
|
|
205
|
+
"""
|
|
206
|
+
if auth_key is None:
|
|
207
|
+
auth_key, _ = await self.handle_token()
|
|
208
|
+
with path.open("rb") as fp:
|
|
209
|
+
image_bytes: bytes = fp.read()
|
|
210
|
+
file_name: str = str(path.absolute())
|
|
211
|
+
_, file_extension = os.path.splitext(file_name.lower())
|
|
212
|
+
mime_type = MIME_TYPE[file_extension]
|
|
213
|
+
return await self.set_entity_image(entity_uri, image_bytes, file_name, mime_type, auth_key=auth_key)
|
|
214
|
+
|
|
215
|
+
async def set_entity_image_url(
|
|
216
|
+
self,
|
|
217
|
+
entity_uri: str,
|
|
218
|
+
image_url: str,
|
|
219
|
+
file_name: Optional[str] = None,
|
|
220
|
+
mime_type: Optional[str] = None,
|
|
221
|
+
auth_key: Optional[str] = None,
|
|
222
|
+
) -> str:
|
|
223
|
+
"""Setting the image of the entity.
|
|
224
|
+
The image for the URL is downloaded and then pushed to the backend.
|
|
225
|
+
|
|
226
|
+
Parameters
|
|
227
|
+
----------
|
|
228
|
+
auth_key: str
|
|
229
|
+
Auth key from user
|
|
230
|
+
entity_uri: str
|
|
231
|
+
URI of the entity.
|
|
232
|
+
image_url: str
|
|
233
|
+
URL of the image.
|
|
234
|
+
file_name: str [default:=None]
|
|
235
|
+
Name of the file. If None the name is extracted from URL.
|
|
236
|
+
mime_type: str [default:=None]
|
|
237
|
+
Mime type.
|
|
238
|
+
auth_key: Optional[str] [default:=None]
|
|
239
|
+
Auth key from user if not set, the client auth key will be used
|
|
240
|
+
|
|
241
|
+
Returns
|
|
242
|
+
-------
|
|
243
|
+
image_id: str
|
|
244
|
+
ID of uploaded image
|
|
245
|
+
|
|
246
|
+
Raises
|
|
247
|
+
------
|
|
248
|
+
WacomServiceException
|
|
249
|
+
If the graph service returns an error code.
|
|
250
|
+
"""
|
|
251
|
+
if auth_key is None:
|
|
252
|
+
auth_key, _ = await self.handle_token()
|
|
253
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
254
|
+
headers: Dict[str, str] = {USER_AGENT_HEADER_FLAG: self.user_agent}
|
|
255
|
+
async with session.get(image_url, headers=headers, verify_ssl=self.verify_calls) as response:
|
|
256
|
+
if response.ok:
|
|
257
|
+
image_bytes: bytes = await response.content.read()
|
|
258
|
+
file_name: str = image_url if file_name is None else file_name
|
|
259
|
+
if mime_type is None:
|
|
260
|
+
_, file_extension = os.path.splitext(file_name.lower())
|
|
261
|
+
if file_extension not in MIME_TYPE:
|
|
262
|
+
raise WacomServiceException(
|
|
263
|
+
"Creation of entity image failed. Mime-type cannot be "
|
|
264
|
+
"identified or is not supported."
|
|
265
|
+
)
|
|
266
|
+
mime_type = MIME_TYPE[file_extension]
|
|
267
|
+
|
|
268
|
+
return await self.set_entity_image(entity_uri, image_bytes, file_name, mime_type, auth_key=auth_key)
|
|
269
|
+
raise await handle_error(f"Creation of entity image failed. URI:={entity_uri}.", response, headers=headers)
|
|
270
|
+
|
|
271
|
+
async def set_entity_image(
|
|
272
|
+
self,
|
|
273
|
+
entity_uri: str,
|
|
274
|
+
image_byte: bytes,
|
|
275
|
+
file_name: str = "icon.jpg",
|
|
276
|
+
mime_type: str = "image/jpeg",
|
|
277
|
+
auth_key: Optional[str] = None,
|
|
278
|
+
) -> str:
|
|
279
|
+
"""Setting the image of the entity.
|
|
280
|
+
The image for the URL is downloaded and then pushed to the backend.
|
|
281
|
+
|
|
282
|
+
Parameters
|
|
283
|
+
----------
|
|
284
|
+
entity_uri: str
|
|
285
|
+
URI of the entity.
|
|
286
|
+
image_byte: bytes
|
|
287
|
+
Binary encoded image.
|
|
288
|
+
file_name: str [default:=None]
|
|
289
|
+
Name of the file. If None the name is extracted from URL.
|
|
290
|
+
mime_type: str [default:=None]
|
|
291
|
+
Mime type.
|
|
292
|
+
auth_key: Optional[str] [default:=None]
|
|
293
|
+
Auth key from user if not set, the client auth key will be used
|
|
294
|
+
Returns
|
|
295
|
+
-------
|
|
296
|
+
image_id: str
|
|
297
|
+
ID of uploaded image
|
|
298
|
+
|
|
299
|
+
Raises
|
|
300
|
+
------
|
|
301
|
+
WacomServiceException
|
|
302
|
+
If the graph service returns an error code.
|
|
303
|
+
"""
|
|
304
|
+
if auth_key is None:
|
|
305
|
+
auth_key, _ = await self.handle_token()
|
|
306
|
+
headers: dict = {AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
|
|
307
|
+
data: aiohttp.FormData = aiohttp.FormData()
|
|
308
|
+
data.add_field("file", image_byte, filename=file_name, content_type=mime_type)
|
|
309
|
+
url: str = f"{self.service_base_url}{self.ENTITY_IMAGE_ENDPOINT}{urllib.parse.quote(entity_uri)}"
|
|
310
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
311
|
+
async with session.patch(
|
|
312
|
+
url, headers=headers, data=data, timeout=DEFAULT_TIMEOUT, verify_ssl=self.verify_calls
|
|
313
|
+
) as response:
|
|
314
|
+
if response.ok:
|
|
315
|
+
image_id: str = (await response.json(loads=orjson.loads))["imageId"]
|
|
316
|
+
else:
|
|
317
|
+
raise await handle_error(
|
|
318
|
+
f"Creation of entity image failed. URI:={entity_uri}.", response, headers=headers
|
|
319
|
+
)
|
|
320
|
+
await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
|
|
321
|
+
return image_id
|
|
322
|
+
|
|
323
|
+
async def delete_entities(self, uris: List[str], force: bool = False, auth_key: Optional[str] = None):
|
|
324
|
+
"""
|
|
325
|
+
Delete a list of entities.
|
|
326
|
+
|
|
327
|
+
Parameters
|
|
328
|
+
----------
|
|
329
|
+
uris: List[str]
|
|
330
|
+
List of URI of entities. **Remark:** More than 100 entities are not possible in one request
|
|
331
|
+
force: bool
|
|
332
|
+
Force deletion process
|
|
333
|
+
auth_key: Optional[str]
|
|
334
|
+
Use a different auth key than the one from the client
|
|
335
|
+
|
|
336
|
+
Raises
|
|
337
|
+
------
|
|
338
|
+
WacomServiceException
|
|
339
|
+
If the graph service returns an error code
|
|
340
|
+
ValueError
|
|
341
|
+
If more than 100 entities are given
|
|
342
|
+
"""
|
|
343
|
+
if len(uris) > 100:
|
|
344
|
+
raise ValueError("Please delete less than 100 entities.")
|
|
345
|
+
if auth_key is None:
|
|
346
|
+
auth_key, _ = await self.handle_token()
|
|
347
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}"
|
|
348
|
+
headers: Dict[str, str] = {
|
|
349
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
350
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
351
|
+
}
|
|
352
|
+
params: Dict[str, Any] = {URIS_TAG: uris, FORCE_TAG: str(force)}
|
|
353
|
+
async with aiohttp.ClientSession() as session:
|
|
354
|
+
async with session.delete(url, headers=headers, params=params, verify_ssl=self.verify_calls) as response:
|
|
355
|
+
if not response.ok:
|
|
356
|
+
raise await handle_error(
|
|
357
|
+
"Deletion of entities failed.", response, parameters=params, headers=headers
|
|
358
|
+
)
|
|
359
|
+
await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
|
|
360
|
+
|
|
361
|
+
async def delete_entity(self, uri: str, force: bool = False, auth_key: Optional[str] = None):
|
|
362
|
+
"""
|
|
363
|
+
Deletes an entity.
|
|
364
|
+
|
|
365
|
+
Parameters
|
|
366
|
+
----------
|
|
367
|
+
uri: str
|
|
368
|
+
URI of entity
|
|
369
|
+
force: bool
|
|
370
|
+
Force deletion process
|
|
371
|
+
auth_key: Optional[str]
|
|
372
|
+
Use a different auth key than the one from the client
|
|
373
|
+
|
|
374
|
+
Raises
|
|
375
|
+
------
|
|
376
|
+
WacomServiceException
|
|
377
|
+
If the graph service returns an error code
|
|
378
|
+
"""
|
|
379
|
+
if auth_key is None:
|
|
380
|
+
auth_key, _ = await self.handle_token()
|
|
381
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{uri}"
|
|
382
|
+
headers: Dict[str, str] = {
|
|
383
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
384
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
385
|
+
}
|
|
386
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
387
|
+
async with session.delete(
|
|
388
|
+
url, headers=headers, params={FORCE_TAG: str(force)}, verify_ssl=self.verify_calls
|
|
389
|
+
) as response:
|
|
390
|
+
if not response.ok:
|
|
391
|
+
raise await handle_error(f"Deletion of entity failed. URI:={uri}.", response, headers=headers)
|
|
392
|
+
await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
|
|
393
|
+
|
|
394
|
+
async def exists(self, uri: str) -> bool:
|
|
395
|
+
"""
|
|
396
|
+
Check if entity exists in knowledge graph.
|
|
397
|
+
|
|
398
|
+
Parameters
|
|
399
|
+
----------
|
|
400
|
+
uri: str -
|
|
401
|
+
URI for entity
|
|
402
|
+
|
|
403
|
+
Returns
|
|
404
|
+
-------
|
|
405
|
+
flag: bool
|
|
406
|
+
Flag if entity does exist
|
|
407
|
+
"""
|
|
408
|
+
try:
|
|
409
|
+
obj: ThingObject = await self.entity(uri)
|
|
410
|
+
return obj is not None
|
|
411
|
+
except WacomServiceException:
|
|
412
|
+
return False
|
|
413
|
+
|
|
414
|
+
@staticmethod
|
|
415
|
+
async def __entity__(entity: ThingObject):
|
|
416
|
+
return entity_payload(entity)
|
|
417
|
+
|
|
418
|
+
async def create_entity_bulk(
|
|
419
|
+
self,
|
|
420
|
+
entities: List[ThingObject],
|
|
421
|
+
batch_size: int = 10,
|
|
422
|
+
ignore_images: bool = False,
|
|
423
|
+
auth_key: Optional[str] = None,
|
|
424
|
+
) -> List[ThingObject]:
|
|
425
|
+
"""
|
|
426
|
+
Creates entity in graph.
|
|
427
|
+
|
|
428
|
+
Parameters
|
|
429
|
+
----------
|
|
430
|
+
entities: List[ThingObject]
|
|
431
|
+
Entities
|
|
432
|
+
batch_size: int
|
|
433
|
+
Batch size
|
|
434
|
+
ignore_images: bool
|
|
435
|
+
Do not automatically upload images
|
|
436
|
+
auth_key: Optional[str]
|
|
437
|
+
If auth key is not set, the client auth key will be used.
|
|
438
|
+
|
|
439
|
+
Returns
|
|
440
|
+
-------
|
|
441
|
+
uris: List[ThingObject]
|
|
442
|
+
List of ThingObjects with URI
|
|
443
|
+
|
|
444
|
+
Raises
|
|
445
|
+
------
|
|
446
|
+
WacomServiceException
|
|
447
|
+
If the graph service returns an error code
|
|
448
|
+
"""
|
|
449
|
+
if auth_key is None:
|
|
450
|
+
auth_key, _ = await self.handle_token()
|
|
451
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_BULK_ENDPOINT}"
|
|
452
|
+
# Header info
|
|
453
|
+
headers: Dict[str, str] = {
|
|
454
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
455
|
+
CONTENT_TYPE_HEADER_FLAG: APPLICATION_JSON_HEADER,
|
|
456
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
457
|
+
}
|
|
458
|
+
payload: List[Dict[str, Any]] = [await AsyncWacomKnowledgeService.__entity__(e) for e in entities]
|
|
459
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
460
|
+
for bulk_idx in range(0, len(entities), batch_size):
|
|
461
|
+
bulk = payload[bulk_idx : bulk_idx + batch_size]
|
|
462
|
+
|
|
463
|
+
async with session.post(url, json=bulk, headers=headers, verify_ssl=self.verify_calls) as response:
|
|
464
|
+
if response.ok:
|
|
465
|
+
response_dict: Dict[str, Any] = await response.json(loads=orjson.loads)
|
|
466
|
+
for idx, uri in enumerate(response_dict[URIS_TAG]):
|
|
467
|
+
entities[bulk_idx + idx].uri = uri
|
|
468
|
+
if (
|
|
469
|
+
entities[bulk_idx + idx].image is not None
|
|
470
|
+
and entities[bulk_idx + idx].image != ""
|
|
471
|
+
and not ignore_images
|
|
472
|
+
):
|
|
473
|
+
try:
|
|
474
|
+
await self.set_entity_image_url(
|
|
475
|
+
uri, entities[bulk_idx + idx].image, auth_key=auth_key
|
|
476
|
+
)
|
|
477
|
+
except WacomServiceException as we:
|
|
478
|
+
logging.error(
|
|
479
|
+
f"Failed to upload image for entity {uri}. " f"{format_exception(we)}"
|
|
480
|
+
)
|
|
481
|
+
entities[bulk_idx + idx].uri = response_dict[URIS_TAG][idx]
|
|
482
|
+
await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
|
|
483
|
+
return entities
|
|
484
|
+
|
|
485
|
+
async def create_entity(
|
|
486
|
+
self, entity: ThingObject, auth_key: Optional[str] = None, ignore_image: bool = False
|
|
487
|
+
) -> str:
|
|
488
|
+
"""
|
|
489
|
+
Creates entity in graph.
|
|
490
|
+
|
|
491
|
+
Parameters
|
|
492
|
+
----------
|
|
493
|
+
entity: ThingObject
|
|
494
|
+
Entities object that needs to be created
|
|
495
|
+
auth_key: Optional[str]
|
|
496
|
+
Use a different auth key than the one from the client
|
|
497
|
+
ignore_image: bool
|
|
498
|
+
Ignore image.
|
|
499
|
+
|
|
500
|
+
Returns
|
|
501
|
+
-------
|
|
502
|
+
uri: str
|
|
503
|
+
URI of entity
|
|
504
|
+
|
|
505
|
+
Raises
|
|
506
|
+
------
|
|
507
|
+
WacomServiceException
|
|
508
|
+
If the graph service returns an error code
|
|
509
|
+
"""
|
|
510
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}"
|
|
511
|
+
if auth_key is None:
|
|
512
|
+
auth_key, _ = await self.handle_token()
|
|
513
|
+
# Header info
|
|
514
|
+
headers: Dict[str, str] = {
|
|
515
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
516
|
+
CONTENT_TYPE_HEADER_FLAG: APPLICATION_JSON_HEADER,
|
|
517
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
518
|
+
}
|
|
519
|
+
payload: Dict[str, Any] = await AsyncWacomKnowledgeService.__entity__(entity)
|
|
520
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
521
|
+
async with session.post(url, json=payload, headers=headers, verify_ssl=self.verify_calls) as response:
|
|
522
|
+
if response.ok and not ignore_image:
|
|
523
|
+
uri: str = (await response.json(loads=orjson.loads))[URI_TAG]
|
|
524
|
+
# Set image
|
|
525
|
+
if entity.image is not None and entity.image.startswith("file:"):
|
|
526
|
+
p = urlparse(entity.image)
|
|
527
|
+
await self.set_entity_image_local(uri, Path(p.path), auth_key=auth_key)
|
|
528
|
+
elif entity.image is not None and entity.image != "":
|
|
529
|
+
await self.set_entity_image_url(uri, entity.image, auth_key=auth_key)
|
|
530
|
+
if not response.ok:
|
|
531
|
+
# Handle error
|
|
532
|
+
raise await handle_error("Creation of entity failed.", response, payload=payload, headers=headers)
|
|
533
|
+
await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
|
|
534
|
+
return uri
|
|
535
|
+
|
|
536
|
+
async def update_entity(self, entity: ThingObject, auth_key: Optional[str] = None):
|
|
537
|
+
"""
|
|
538
|
+
Updates entity in graph.
|
|
539
|
+
|
|
540
|
+
Parameters
|
|
541
|
+
----------
|
|
542
|
+
entity: ThingObject
|
|
543
|
+
entity object
|
|
544
|
+
auth_key: Optional[str]
|
|
545
|
+
Use a different auth key than the one from the client
|
|
546
|
+
|
|
547
|
+
Raises
|
|
548
|
+
------
|
|
549
|
+
WacomServiceException
|
|
550
|
+
If the graph service returns an error code
|
|
551
|
+
"""
|
|
552
|
+
if auth_key is None:
|
|
553
|
+
auth_key, _ = await self.handle_token()
|
|
554
|
+
uri: str = entity.uri
|
|
555
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{uri}"
|
|
556
|
+
# Header info
|
|
557
|
+
headers: dict = {
|
|
558
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
559
|
+
CONTENT_TYPE_HEADER_FLAG: APPLICATION_JSON_HEADER,
|
|
560
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
561
|
+
}
|
|
562
|
+
payload: Dict[str, Any] = await AsyncWacomKnowledgeService.__entity__(entity)
|
|
563
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
564
|
+
async with session.patch(
|
|
565
|
+
url, json=payload, headers=headers, timeout=DEFAULT_TIMEOUT, verify_ssl=self.verify_calls
|
|
566
|
+
) as response:
|
|
567
|
+
if not response.ok:
|
|
568
|
+
raise await handle_error(
|
|
569
|
+
f"Update of entity failed. URI:={uri}.", response, payload=payload, headers=headers
|
|
570
|
+
)
|
|
571
|
+
await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
|
|
572
|
+
|
|
573
|
+
async def relations(
|
|
574
|
+
self, uri: str, auth_key: Optional[str] = None
|
|
575
|
+
) -> Dict[OntologyPropertyReference, ObjectProperty]:
|
|
576
|
+
"""
|
|
577
|
+
Retrieve the relations (object properties) of an entity.
|
|
578
|
+
|
|
579
|
+
Parameters
|
|
580
|
+
----------
|
|
581
|
+
uri: str
|
|
582
|
+
Entities URI of the source
|
|
583
|
+
|
|
584
|
+
auth_key: Optional[str]
|
|
585
|
+
Use a different auth key than the one from the client
|
|
586
|
+
|
|
587
|
+
Returns
|
|
588
|
+
-------
|
|
589
|
+
relations: Dict[OntologyPropertyReference, ObjectProperty]
|
|
590
|
+
All relations a dict
|
|
591
|
+
|
|
592
|
+
Raises
|
|
593
|
+
------
|
|
594
|
+
WacomServiceException
|
|
595
|
+
If the graph service returns an error code
|
|
596
|
+
"""
|
|
597
|
+
if auth_key is None:
|
|
598
|
+
auth_key, _ = await self.handle_token()
|
|
599
|
+
url: str = (
|
|
600
|
+
f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{urllib.parse.quote(uri)}"
|
|
601
|
+
f"/relations"
|
|
602
|
+
)
|
|
603
|
+
headers: Dict[str, str] = {
|
|
604
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
605
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
606
|
+
}
|
|
607
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
608
|
+
async with session.get(url, headers=headers, verify_ssl=self.verify_calls) as response:
|
|
609
|
+
if response.ok:
|
|
610
|
+
rel: list = (await response.json(loads=orjson.loads)).get(RELATIONS_TAG)
|
|
611
|
+
else:
|
|
612
|
+
raise await handle_error(f"Retrieving of relations failed. URI:={uri}.", response, headers=headers)
|
|
613
|
+
# Graceful shutdown to close the session and file descriptor
|
|
614
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
615
|
+
return ObjectProperty.create_from_list(rel)
|
|
616
|
+
|
|
617
|
+
async def labels(self, uri: str, locale: LocaleCode = EN_US, auth_key: Optional[str] = None) -> List[Label]:
|
|
618
|
+
"""
|
|
619
|
+
Extract list labels of entity.
|
|
620
|
+
|
|
621
|
+
Parameters
|
|
622
|
+
----------
|
|
623
|
+
uri: str
|
|
624
|
+
Entities URI of the source
|
|
625
|
+
locale: str
|
|
626
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format <language_code>_<country>, e.g., en_US.
|
|
627
|
+
auth_key: Optional[str] = None
|
|
628
|
+
Use a different auth key than the one from the client
|
|
629
|
+
|
|
630
|
+
Returns
|
|
631
|
+
-------
|
|
632
|
+
labels: List[Label]
|
|
633
|
+
List of labels of an entity.
|
|
634
|
+
|
|
635
|
+
Raises
|
|
636
|
+
------
|
|
637
|
+
WacomServiceException
|
|
638
|
+
If the graph service returns an error code
|
|
639
|
+
"""
|
|
640
|
+
if auth_key is None:
|
|
641
|
+
auth_key, _ = await self.handle_token()
|
|
642
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{uri}/labels"
|
|
643
|
+
headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
|
|
644
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
645
|
+
async with session.get(
|
|
646
|
+
url,
|
|
647
|
+
headers=headers,
|
|
648
|
+
params={
|
|
649
|
+
LOCALE_TAG: locale,
|
|
650
|
+
},
|
|
651
|
+
verify_ssl=self.verify_calls,
|
|
652
|
+
) as response:
|
|
653
|
+
if response.ok:
|
|
654
|
+
labels: list = (await response.json(loads=orjson.loads)).get(LABELS_TAG)
|
|
655
|
+
else:
|
|
656
|
+
raise await handle_error(f"Failed to pull labels. URI:={uri}.", response, headers=headers)
|
|
657
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
658
|
+
return [Label.create_from_dict(label) for label in labels]
|
|
659
|
+
|
|
660
|
+
async def literals(
|
|
661
|
+
self, uri: str, locale: LocaleCode = EN_US, auth_key: Optional[str] = None
|
|
662
|
+
) -> List[DataProperty]:
|
|
663
|
+
"""
|
|
664
|
+
Collect all literals of entity.
|
|
665
|
+
|
|
666
|
+
Parameters
|
|
667
|
+
----------
|
|
668
|
+
uri: str
|
|
669
|
+
Entities URI of the source
|
|
670
|
+
locale: LocaleCode [default:=EN_US]
|
|
671
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format <language_code>_<country>, e.g., en_US.
|
|
672
|
+
auth_key: Optional[str] [default:=None]
|
|
673
|
+
Use a different auth key than the one from the client
|
|
674
|
+
Returns
|
|
675
|
+
-------
|
|
676
|
+
literals: List[DataProperty]
|
|
677
|
+
List of data properties of an entity.
|
|
678
|
+
|
|
679
|
+
Raises
|
|
680
|
+
------
|
|
681
|
+
WacomServiceException
|
|
682
|
+
If the graph service returns an error code
|
|
683
|
+
"""
|
|
684
|
+
if auth_key is None:
|
|
685
|
+
auth_key, _ = await self.handle_token()
|
|
686
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{uri}/literals"
|
|
687
|
+
headers: Dict[str, str] = {
|
|
688
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
689
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
690
|
+
}
|
|
691
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
692
|
+
async with session.get(
|
|
693
|
+
url,
|
|
694
|
+
headers=headers,
|
|
695
|
+
params={
|
|
696
|
+
LOCALE_TAG: locale,
|
|
697
|
+
},
|
|
698
|
+
verify_ssl=self.verify_calls,
|
|
699
|
+
) as response:
|
|
700
|
+
if response.ok:
|
|
701
|
+
literals: list = (await response.json(loads=orjson.loads)).get(DATA_PROPERTIES_TAG)
|
|
702
|
+
else:
|
|
703
|
+
raise await handle_error(f"Failed to pull literals. URI:={uri}.", response, headers=headers)
|
|
704
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
705
|
+
return DataProperty.create_from_list(literals)
|
|
706
|
+
|
|
707
|
+
async def create_relation(
|
|
708
|
+
self, source: str, relation: OntologyPropertyReference, target: str, auth_key: Optional[str] = None
|
|
709
|
+
):
|
|
710
|
+
"""
|
|
711
|
+
Creates a relation for an entity to a source entity.
|
|
712
|
+
|
|
713
|
+
Parameters
|
|
714
|
+
----------
|
|
715
|
+
source: str
|
|
716
|
+
Entities URI of the source
|
|
717
|
+
relation: OntologyPropertyReference
|
|
718
|
+
ObjectProperty property
|
|
719
|
+
target: str
|
|
720
|
+
Entities URI of the target
|
|
721
|
+
auth_key: Optional[str] [default:=None]
|
|
722
|
+
Use a different auth key than the one from the client
|
|
723
|
+
|
|
724
|
+
Raises
|
|
725
|
+
------
|
|
726
|
+
WacomServiceException
|
|
727
|
+
If the graph service returns an error code
|
|
728
|
+
"""
|
|
729
|
+
if auth_key is None:
|
|
730
|
+
auth_key, _ = await self.handle_token()
|
|
731
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{source}/relation"
|
|
732
|
+
headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
|
|
733
|
+
params: dict = {RELATION_TAG: relation.iri, TARGET: target}
|
|
734
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
735
|
+
async with session.post(url, params=params, headers=headers, verify_ssl=self.verify_calls) as response:
|
|
736
|
+
if not response.ok:
|
|
737
|
+
raise await handle_error(
|
|
738
|
+
f"Creation of relation failed. URI:={source}.", response, headers=headers, parameters=params
|
|
739
|
+
)
|
|
740
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
741
|
+
|
|
742
|
+
async def create_relations_bulk(
|
|
743
|
+
self, source: str, relations: Dict[OntologyPropertyReference, List[str]], auth_key: Optional[str] = None
|
|
744
|
+
):
|
|
745
|
+
"""
|
|
746
|
+
Creates all the relations for an entity to a source entity.
|
|
747
|
+
|
|
748
|
+
Parameters
|
|
749
|
+
----------
|
|
750
|
+
source: str
|
|
751
|
+
Entities URI of the source
|
|
752
|
+
|
|
753
|
+
relations: Dict[OntologyPropertyReference, List[str]]
|
|
754
|
+
ObjectProperty property and targets mapping.
|
|
755
|
+
|
|
756
|
+
auth_key: Optional[str] = None
|
|
757
|
+
If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
|
|
758
|
+
|
|
759
|
+
Raises
|
|
760
|
+
------
|
|
761
|
+
WacomServiceException
|
|
762
|
+
If the graph service returns an error code
|
|
763
|
+
"""
|
|
764
|
+
if auth_key is None:
|
|
765
|
+
auth_key, _ = await self.handle_token()
|
|
766
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{source}/relations"
|
|
767
|
+
headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
|
|
768
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
769
|
+
for update_bulk in split_updates(relations):
|
|
770
|
+
async with session.post(
|
|
771
|
+
url, json=update_bulk, headers=headers, verify_ssl=self.verify_calls
|
|
772
|
+
) as response:
|
|
773
|
+
if not response.ok:
|
|
774
|
+
raise await handle_error(
|
|
775
|
+
f"Creation of relation failed. URI:={source}.",
|
|
776
|
+
response,
|
|
777
|
+
headers=headers,
|
|
778
|
+
parameters=update_bulk,
|
|
779
|
+
)
|
|
780
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
781
|
+
|
|
782
|
+
async def remove_relation(
|
|
783
|
+
self, source: str, relation: OntologyPropertyReference, target: str, auth_key: Optional[str] = None
|
|
784
|
+
):
|
|
785
|
+
"""
|
|
786
|
+
Removes a relation.
|
|
787
|
+
|
|
788
|
+
Parameters
|
|
789
|
+
----------
|
|
790
|
+
source: str
|
|
791
|
+
Entities uri of the source
|
|
792
|
+
relation: OntologyPropertyReference
|
|
793
|
+
ObjectProperty property
|
|
794
|
+
target: str
|
|
795
|
+
Entities uri of the target
|
|
796
|
+
auth_key: Optional[str] [default:=None]
|
|
797
|
+
Use a different auth key than the one from the client
|
|
798
|
+
|
|
799
|
+
Raises
|
|
800
|
+
------
|
|
801
|
+
WacomServiceException
|
|
802
|
+
If the graph service returns an error code
|
|
803
|
+
"""
|
|
804
|
+
if auth_key is None:
|
|
805
|
+
auth_key, _ = await self.handle_token()
|
|
806
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{source}/relation"
|
|
807
|
+
params: Dict[str, str] = {RELATION_TAG: relation.iri, TARGET: target}
|
|
808
|
+
headers: Dict[str, str] = {
|
|
809
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
810
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
811
|
+
}
|
|
812
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
813
|
+
async with session.delete(
|
|
814
|
+
url, params=params, headers=headers, timeout=DEFAULT_TIMEOUT, verify_ssl=self.verify_calls
|
|
815
|
+
) as response:
|
|
816
|
+
if not response.ok:
|
|
817
|
+
raise await handle_error(
|
|
818
|
+
f"Removal of relation failed. URI:={source}.", response, headers=headers, parameters=params
|
|
819
|
+
)
|
|
820
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
821
|
+
|
|
822
|
+
async def activations(
|
|
823
|
+
self, uris: List[str], depth: int, auth_key: Optional[str] = None
|
|
824
|
+
) -> Tuple[Dict[str, ThingObject], List[Tuple[str, OntologyPropertyReference, str]]]:
|
|
825
|
+
"""
|
|
826
|
+
Spreading activation, retrieving the entities related to an entity.
|
|
827
|
+
|
|
828
|
+
Parameters
|
|
829
|
+
----------
|
|
830
|
+
uris: List[str]
|
|
831
|
+
List of URIS for entity.
|
|
832
|
+
depth: int
|
|
833
|
+
Depth of activations
|
|
834
|
+
auth_key: Optional[str] [default:=None]
|
|
835
|
+
Use a different auth key than the one from the client
|
|
836
|
+
|
|
837
|
+
Returns
|
|
838
|
+
-------
|
|
839
|
+
entity_map: Dict[str, ThingObject]
|
|
840
|
+
Map with entity and its URI as key.
|
|
841
|
+
relations: List[Tuple[str, OntologyPropertyReference, str]]
|
|
842
|
+
List of relations with subject predicate, (Property), and subject
|
|
843
|
+
|
|
844
|
+
Raises
|
|
845
|
+
------
|
|
846
|
+
WacomServiceException
|
|
847
|
+
If the graph service returns an error code, and activation failed.
|
|
848
|
+
"""
|
|
849
|
+
if auth_key is None:
|
|
850
|
+
auth_key, _ = await self.handle_token()
|
|
851
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ACTIVATIONS_ENDPOINT}"
|
|
852
|
+
headers: Dict[str, str] = {
|
|
853
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
854
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
855
|
+
}
|
|
856
|
+
params: dict = {URIS_TAG: uris, ACTIVATION_TAG: depth}
|
|
857
|
+
|
|
858
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
859
|
+
async with session.get(url, headers=headers, params=params, verify_ssl=self.verify_calls) as response:
|
|
860
|
+
if response.ok:
|
|
861
|
+
entities: Dict[str, Any] = await response.json(loads=orjson.loads)
|
|
862
|
+
things: Dict[str, ThingObject] = {
|
|
863
|
+
e[URI_TAG]: ThingObject.from_dict(e) for e in entities[ENTITIES_TAG]
|
|
864
|
+
}
|
|
865
|
+
relations: List[Tuple[str, OntologyPropertyReference, str]] = []
|
|
866
|
+
for r in entities[RELATIONS_TAG]:
|
|
867
|
+
relation: OntologyPropertyReference = OntologyPropertyReference.parse(r[PREDICATE])
|
|
868
|
+
relations.append((r[SUBJECT], relation, r[OBJECT]))
|
|
869
|
+
if r[SUBJECT] in things:
|
|
870
|
+
things[r[SUBJECT]].add_relation(ObjectProperty(relation, outgoing=[r[OBJECT]]))
|
|
871
|
+
else:
|
|
872
|
+
raise await handle_error(
|
|
873
|
+
f"Activation failed. URIS:={uris}.", response, headers=headers, parameters=params
|
|
874
|
+
)
|
|
875
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
876
|
+
return things, relations
|
|
877
|
+
|
|
878
|
+
async def listing(
|
|
879
|
+
self,
|
|
880
|
+
filter_type: OntologyClassReference,
|
|
881
|
+
page_id: Optional[str] = None,
|
|
882
|
+
limit: int = 30,
|
|
883
|
+
locale: Optional[LocaleCode] = None,
|
|
884
|
+
visibility: Optional[Visibility] = None,
|
|
885
|
+
is_owner: Optional[bool] = None,
|
|
886
|
+
estimate_count: bool = False,
|
|
887
|
+
auth_key: Optional[str] = None,
|
|
888
|
+
) -> Tuple[List[ThingObject], int, str]:
|
|
889
|
+
"""
|
|
890
|
+
List all entities visible to users.
|
|
891
|
+
|
|
892
|
+
Parameters
|
|
893
|
+
----------
|
|
894
|
+
filter_type: OntologyClassReference
|
|
895
|
+
Filtering with entity
|
|
896
|
+
page_id: Optional[str]
|
|
897
|
+
Page id. Start from this page id
|
|
898
|
+
limit: int
|
|
899
|
+
Limit of the returned entities.
|
|
900
|
+
locale: Optional[LocaleCode] [default:=None]
|
|
901
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., en_US.
|
|
902
|
+
visibility: Optional[Visibility] [default:=None]
|
|
903
|
+
Filter the entities based on its visibilities
|
|
904
|
+
is_owner: Optional[bool] [default:=None]
|
|
905
|
+
Filter the entities based on its owner
|
|
906
|
+
estimate_count: bool [default:=False]
|
|
907
|
+
Request an estimate of the entities in a tenant.
|
|
908
|
+
auth_key: Optional[str]
|
|
909
|
+
Auth key from user if not set, the client auth key will be used
|
|
910
|
+
|
|
911
|
+
Returns
|
|
912
|
+
-------
|
|
913
|
+
entities: List[ThingObject]
|
|
914
|
+
List of entities
|
|
915
|
+
estimated_total_number: int
|
|
916
|
+
Number of all entities
|
|
917
|
+
next_page_id: str
|
|
918
|
+
Identifier of the next page
|
|
919
|
+
|
|
920
|
+
Raises
|
|
921
|
+
------
|
|
922
|
+
WacomServiceException
|
|
923
|
+
If the graph service returns an error code
|
|
924
|
+
"""
|
|
925
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.LISTING_ENDPOINT}"
|
|
926
|
+
if auth_key is None:
|
|
927
|
+
auth_key, _ = await self.handle_token()
|
|
928
|
+
# Header with auth token
|
|
929
|
+
headers: Dict[str, str] = {
|
|
930
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
931
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
932
|
+
}
|
|
933
|
+
# Parameter with filtering and limit
|
|
934
|
+
parameters: Dict[str, str] = {
|
|
935
|
+
TYPE_TAG: filter_type.iri,
|
|
936
|
+
LIMIT_PARAMETER: str(limit),
|
|
937
|
+
ESTIMATE_COUNT: str(estimate_count),
|
|
938
|
+
}
|
|
939
|
+
if is_owner is not None:
|
|
940
|
+
parameters[IS_OWNER_PARAM] = str(is_owner)
|
|
941
|
+
if locale:
|
|
942
|
+
parameters[LOCALE_TAG] = locale
|
|
943
|
+
if visibility:
|
|
944
|
+
parameters[VISIBILITY_TAG] = str(visibility.value)
|
|
945
|
+
# If filtering is configured
|
|
946
|
+
if page_id is not None:
|
|
947
|
+
parameters[NEXT_PAGE_ID_TAG] = page_id
|
|
948
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
949
|
+
# Send request
|
|
950
|
+
async with session.get(url, params=parameters, headers=headers, verify_ssl=self.verify_calls) as response:
|
|
951
|
+
# If response is successful
|
|
952
|
+
if response.ok:
|
|
953
|
+
entities_resp: Dict[str, Any] = await response.json(loads=orjson.loads)
|
|
954
|
+
next_page_id: str = entities_resp[NEXT_PAGE_ID_TAG]
|
|
955
|
+
estimated_total_number: int = entities_resp.get(TOTAL_COUNT, 0)
|
|
956
|
+
entities: List[ThingObject] = []
|
|
957
|
+
if LISTING in entities_resp:
|
|
958
|
+
for e in entities_resp[LISTING]:
|
|
959
|
+
thing: ThingObject = ThingObject.from_dict(e)
|
|
960
|
+
thing.status_flag = EntityStatus.SYNCED
|
|
961
|
+
entities.append(thing)
|
|
962
|
+
else:
|
|
963
|
+
raise await handle_error(
|
|
964
|
+
f"Failed to list the entities (since:= {page_id}, limit:={limit}). ", response
|
|
965
|
+
)
|
|
966
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
967
|
+
return entities, estimated_total_number, next_page_id
|
|
968
|
+
|
|
969
|
+
async def ontology_update(self, fix: bool = False, auth_key: Optional[str] = None):
|
|
970
|
+
"""
|
|
971
|
+
Update the ontology.
|
|
972
|
+
|
|
973
|
+
**Remark:**
|
|
974
|
+
Works for users with role 'TenantAdmin'.
|
|
975
|
+
|
|
976
|
+
Parameters
|
|
977
|
+
----------
|
|
978
|
+
fix: bool [default:=False]
|
|
979
|
+
Fix the ontology if tenant is in inconsistent state.
|
|
980
|
+
auth_key: Optional[str] [default:=None]
|
|
981
|
+
Auth key from user if not set, the client auth key will be used
|
|
982
|
+
|
|
983
|
+
Raises
|
|
984
|
+
------
|
|
985
|
+
WacomServiceException
|
|
986
|
+
If the graph service returns an error code and commit failed.
|
|
987
|
+
"""
|
|
988
|
+
if auth_key is None:
|
|
989
|
+
auth_key, _ = await self.handle_token()
|
|
990
|
+
url: str = (
|
|
991
|
+
f"{self.service_base_url}{AsyncWacomKnowledgeService.ONTOLOGY_UPDATE_ENDPOINT}" f'{"/fix" if fix else ""}'
|
|
992
|
+
)
|
|
993
|
+
# Header with auth token
|
|
994
|
+
headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
|
|
995
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
996
|
+
async with session.patch(
|
|
997
|
+
url, headers=headers, timeout=DEFAULT_TIMEOUT, verify_ssl=self.verify_calls
|
|
998
|
+
) as response:
|
|
999
|
+
if not response.ok:
|
|
1000
|
+
raise await handle_error("Ontology update failed. ", response, headers=headers)
|
|
1001
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
1002
|
+
|
|
1003
|
+
async def search_all(
|
|
1004
|
+
self,
|
|
1005
|
+
search_term: str,
|
|
1006
|
+
language_code: LocaleCode,
|
|
1007
|
+
types: List[OntologyClassReference],
|
|
1008
|
+
limit: int = 30,
|
|
1009
|
+
next_page_id: str = None,
|
|
1010
|
+
auth_key: Optional[str] = None,
|
|
1011
|
+
) -> Tuple[List[ThingObject], str]:
|
|
1012
|
+
"""Search term in labels, literals and description.
|
|
1013
|
+
|
|
1014
|
+
Parameters
|
|
1015
|
+
----------
|
|
1016
|
+
search_term: str
|
|
1017
|
+
Search term.
|
|
1018
|
+
language_code: LocaleCode
|
|
1019
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., en_US.
|
|
1020
|
+
types: List[OntologyClassReference]
|
|
1021
|
+
Limits the types for search.
|
|
1022
|
+
limit: int (default:= 30)
|
|
1023
|
+
Size of the page for pagination.
|
|
1024
|
+
next_page_id: str [default:=None]
|
|
1025
|
+
ID of the next page within pagination.
|
|
1026
|
+
auth_key: Optional[str] [default:=None]
|
|
1027
|
+
Auth key from user if not set, the client auth key will be used
|
|
1028
|
+
|
|
1029
|
+
Returns
|
|
1030
|
+
-------
|
|
1031
|
+
results: List[ThingObject]
|
|
1032
|
+
List of things matching the search term
|
|
1033
|
+
next_page_id: str
|
|
1034
|
+
ID of the next page.
|
|
1035
|
+
|
|
1036
|
+
Raises
|
|
1037
|
+
------
|
|
1038
|
+
WacomServiceException
|
|
1039
|
+
If the graph service returns an error code.
|
|
1040
|
+
"""
|
|
1041
|
+
if auth_key is None:
|
|
1042
|
+
auth_key, _ = await self.handle_token()
|
|
1043
|
+
headers: Dict[str, str] = {
|
|
1044
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
1045
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
1046
|
+
}
|
|
1047
|
+
parameters: Dict[str, Any] = {
|
|
1048
|
+
SEARCH_TERM: search_term,
|
|
1049
|
+
LANGUAGE_PARAMETER: language_code,
|
|
1050
|
+
TYPES_PARAMETER: [ot.iri for ot in types],
|
|
1051
|
+
LIMIT: limit,
|
|
1052
|
+
}
|
|
1053
|
+
# Only add next page id if it is not None
|
|
1054
|
+
if next_page_id is not None:
|
|
1055
|
+
parameters[NEXT_PAGE_ID_TAG] = next_page_id
|
|
1056
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.SEARCH_TYPES_ENDPOINT}"
|
|
1057
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
1058
|
+
async with session.get(
|
|
1059
|
+
url, headers=headers, params=parameters, timeout=DEFAULT_TIMEOUT, verify_ssl=self.verify_calls
|
|
1060
|
+
) as response:
|
|
1061
|
+
if not response.ok:
|
|
1062
|
+
raise await handle_error(
|
|
1063
|
+
f"Search on labels {search_term} failed. ", response, headers=headers, parameters=parameters
|
|
1064
|
+
)
|
|
1065
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
1066
|
+
return await AsyncWacomKnowledgeService.__search_results__(await response.json(loads=orjson.loads))
|
|
1067
|
+
|
|
1068
|
+
async def search_labels(
|
|
1069
|
+
self,
|
|
1070
|
+
search_term: str,
|
|
1071
|
+
language_code: LocaleCode,
|
|
1072
|
+
exact_match: bool = False,
|
|
1073
|
+
limit: int = 30,
|
|
1074
|
+
next_page_id: str = None,
|
|
1075
|
+
auth_key: Optional[str] = None,
|
|
1076
|
+
) -> Tuple[List[ThingObject], str]:
|
|
1077
|
+
"""Search for matches in labels.
|
|
1078
|
+
|
|
1079
|
+
Parameters
|
|
1080
|
+
----------
|
|
1081
|
+
search_term: str
|
|
1082
|
+
Search term.
|
|
1083
|
+
language_code: LocaleCode
|
|
1084
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., en_US.
|
|
1085
|
+
exact_match: bool [default:=False]
|
|
1086
|
+
Exact match of the search term.
|
|
1087
|
+
limit: int (default:= 30)
|
|
1088
|
+
Size of the page for pagination.
|
|
1089
|
+
next_page_id: str [default:=None]
|
|
1090
|
+
ID of the next page within pagination.
|
|
1091
|
+
auth_key: Optional[str] [default:=None]
|
|
1092
|
+
Auth key from user if not set, the client auth key will be used
|
|
1093
|
+
|
|
1094
|
+
Returns
|
|
1095
|
+
-------
|
|
1096
|
+
results: List[ThingObject]
|
|
1097
|
+
List of things matching the search term
|
|
1098
|
+
next_page_id: str
|
|
1099
|
+
ID of the next page.
|
|
1100
|
+
|
|
1101
|
+
Raises
|
|
1102
|
+
------
|
|
1103
|
+
WacomServiceException
|
|
1104
|
+
If the graph service returns an error code.
|
|
1105
|
+
"""
|
|
1106
|
+
if auth_key is None:
|
|
1107
|
+
auth_key, _ = await self.handle_token()
|
|
1108
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.SEARCH_LABELS_ENDPOINT}"
|
|
1109
|
+
headers: Dict[str, str] = {
|
|
1110
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
1111
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
1112
|
+
}
|
|
1113
|
+
parameters: Dict[str, Any] = {
|
|
1114
|
+
SEARCH_TERM: search_term,
|
|
1115
|
+
LOCALE_TAG: language_code,
|
|
1116
|
+
EXACT_MATCH: str(exact_match),
|
|
1117
|
+
LIMIT: str(limit),
|
|
1118
|
+
}
|
|
1119
|
+
# Only add next page id if it is not None
|
|
1120
|
+
if next_page_id is not None:
|
|
1121
|
+
parameters[NEXT_PAGE_ID_TAG] = next_page_id
|
|
1122
|
+
|
|
1123
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
1124
|
+
async with session.get(
|
|
1125
|
+
url, headers=headers, params=parameters, timeout=DEFAULT_TIMEOUT, verify_ssl=self.verify_calls
|
|
1126
|
+
) as response:
|
|
1127
|
+
if not response.ok:
|
|
1128
|
+
raise await handle_error(
|
|
1129
|
+
f"Search on labels {search_term} failed. ", response, headers=headers, parameters=parameters
|
|
1130
|
+
)
|
|
1131
|
+
entities, next_page_id = await AsyncWacomKnowledgeService.__search_results__(
|
|
1132
|
+
await response.json(loads=orjson.loads)
|
|
1133
|
+
)
|
|
1134
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
1135
|
+
return entities, next_page_id
|
|
1136
|
+
|
|
1137
|
+
async def search_literal(
|
|
1138
|
+
self,
|
|
1139
|
+
search_term: str,
|
|
1140
|
+
literal: OntologyPropertyReference,
|
|
1141
|
+
pattern: SearchPattern = SearchPattern.REGEX,
|
|
1142
|
+
language_code: LocaleCode = EN_US,
|
|
1143
|
+
limit: int = 30,
|
|
1144
|
+
next_page_id: str = None,
|
|
1145
|
+
auth_key: Optional[str] = None,
|
|
1146
|
+
) -> Tuple[List[ThingObject], str]:
|
|
1147
|
+
"""
|
|
1148
|
+
Search for matches in literals.
|
|
1149
|
+
|
|
1150
|
+
Parameters
|
|
1151
|
+
----------
|
|
1152
|
+
search_term: str
|
|
1153
|
+
Search term.
|
|
1154
|
+
literal: OntologyPropertyReference
|
|
1155
|
+
Literal used for the search
|
|
1156
|
+
pattern: SearchPattern (default:= SearchPattern.REGEX)
|
|
1157
|
+
Search pattern. The chosen search pattern must fit the type of the entity.
|
|
1158
|
+
language_code: LocaleCode
|
|
1159
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., en_US.
|
|
1160
|
+
limit: int (default:= 30)
|
|
1161
|
+
Size of the page for pagination.
|
|
1162
|
+
next_page_id: str [default:=None]
|
|
1163
|
+
ID of the next page within pagination.
|
|
1164
|
+
auth_key: Optional[str] [default:=None]
|
|
1165
|
+
Auth key from user if not set, the client auth key will be used
|
|
1166
|
+
Returns
|
|
1167
|
+
-------
|
|
1168
|
+
results: List[ThingObject]
|
|
1169
|
+
List of things matching the search term
|
|
1170
|
+
next_page_id: str
|
|
1171
|
+
ID of the next page.
|
|
1172
|
+
|
|
1173
|
+
Raises
|
|
1174
|
+
------
|
|
1175
|
+
WacomServiceException
|
|
1176
|
+
If the graph service returns an error code.
|
|
1177
|
+
"""
|
|
1178
|
+
if auth_key is None:
|
|
1179
|
+
auth_key, _ = await self.handle_token()
|
|
1180
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.SEARCH_LITERALS_ENDPOINT}"
|
|
1181
|
+
parameters: Dict[str, Any] = {
|
|
1182
|
+
VALUE: search_term,
|
|
1183
|
+
LITERAL_PARAMETER: literal.iri,
|
|
1184
|
+
LANGUAGE_PARAMETER: language_code,
|
|
1185
|
+
LIMIT: str(limit),
|
|
1186
|
+
SEARCH_PATTERN_PARAMETER: pattern.value,
|
|
1187
|
+
}
|
|
1188
|
+
# Only add next page id if it is not None
|
|
1189
|
+
if next_page_id is not None:
|
|
1190
|
+
parameters[NEXT_PAGE_ID_TAG] = next_page_id
|
|
1191
|
+
headers: Dict[str, str] = {AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
|
|
1192
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
1193
|
+
async with session.get(
|
|
1194
|
+
url, headers=headers, params=parameters, timeout=DEFAULT_TIMEOUT, verify_ssl=self.verify_calls
|
|
1195
|
+
) as response:
|
|
1196
|
+
if not response.ok:
|
|
1197
|
+
raise await handle_error(
|
|
1198
|
+
f"Search on literals {search_term} failed. ", response, headers=headers, parameters=parameters
|
|
1199
|
+
)
|
|
1200
|
+
entities, n_p = await AsyncWacomKnowledgeService.__search_results__(
|
|
1201
|
+
await response.json(loads=orjson.loads)
|
|
1202
|
+
)
|
|
1203
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
1204
|
+
return entities, n_p
|
|
1205
|
+
|
|
1206
|
+
async def search_relation(
|
|
1207
|
+
self,
|
|
1208
|
+
relation: OntologyPropertyReference,
|
|
1209
|
+
language_code: LocaleCode,
|
|
1210
|
+
subject_uri: str = None,
|
|
1211
|
+
object_uri: str = None,
|
|
1212
|
+
limit: int = 30,
|
|
1213
|
+
next_page_id: str = None,
|
|
1214
|
+
auth_key: Optional[str] = None,
|
|
1215
|
+
) -> Tuple[List[ThingObject], str]:
|
|
1216
|
+
"""
|
|
1217
|
+
Search for matches in literals.
|
|
1218
|
+
|
|
1219
|
+
Parameters
|
|
1220
|
+
----------
|
|
1221
|
+
relation: OntologyPropertyReference
|
|
1222
|
+
Search term.
|
|
1223
|
+
language_code: LocaleCode
|
|
1224
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., en_US.
|
|
1225
|
+
subject_uri: str [default:=None]
|
|
1226
|
+
URI of the subject
|
|
1227
|
+
object_uri: str [default:=None]
|
|
1228
|
+
URI of the object
|
|
1229
|
+
limit: int (default:= 30)
|
|
1230
|
+
Size of the page for pagination.
|
|
1231
|
+
next_page_id: str [default:=None]
|
|
1232
|
+
ID of the next page within pagination.
|
|
1233
|
+
auth_key: Optional[str] [default:=None]
|
|
1234
|
+
Auth key from user if not set, the client auth key will be used
|
|
1235
|
+
|
|
1236
|
+
Returns
|
|
1237
|
+
-------
|
|
1238
|
+
results: List[ThingObject]
|
|
1239
|
+
List of things matching the search term
|
|
1240
|
+
next_page_id: str
|
|
1241
|
+
ID of the next page.
|
|
1242
|
+
|
|
1243
|
+
Raises
|
|
1244
|
+
------
|
|
1245
|
+
WacomServiceException
|
|
1246
|
+
If the graph service returns an error code.
|
|
1247
|
+
"""
|
|
1248
|
+
if auth_key is None:
|
|
1249
|
+
auth_key, _ = await self.handle_token()
|
|
1250
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.SEARCH_RELATION_ENDPOINT}"
|
|
1251
|
+
parameters: Dict[str, Any] = {RELATION_URI: relation.iri, LANGUAGE_PARAMETER: language_code, LIMIT: str(limit)}
|
|
1252
|
+
if subject_uri is not None and object_uri is not None:
|
|
1253
|
+
raise WacomServiceException("Only one parameter is allowed: either subject_uri or object_uri!")
|
|
1254
|
+
if subject_uri is None and object_uri is None:
|
|
1255
|
+
raise WacomServiceException("At least one parameters is must be defined: either subject_uri or object_uri!")
|
|
1256
|
+
if subject_uri is not None:
|
|
1257
|
+
parameters[SUBJECT_URI] = subject_uri
|
|
1258
|
+
if object_uri is not None:
|
|
1259
|
+
parameters[OBJECT_URI] = object_uri
|
|
1260
|
+
# Only add next page id if it is not None
|
|
1261
|
+
if next_page_id is not None:
|
|
1262
|
+
parameters[NEXT_PAGE_ID_TAG] = next_page_id
|
|
1263
|
+
headers: dict = {AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
|
|
1264
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
1265
|
+
async with session.get(url, headers=headers, params=parameters, verify_ssl=self.verify_calls) as response:
|
|
1266
|
+
if not response.ok:
|
|
1267
|
+
raise await handle_error(
|
|
1268
|
+
f"Search on: subject:={subject_uri}, relation {relation.iri}, "
|
|
1269
|
+
f"object:= {object_uri} failed. ",
|
|
1270
|
+
response,
|
|
1271
|
+
headers=headers,
|
|
1272
|
+
parameters=parameters,
|
|
1273
|
+
)
|
|
1274
|
+
entities, n_p = await AsyncWacomKnowledgeService.__search_results__(
|
|
1275
|
+
await response.json(loads=orjson.loads)
|
|
1276
|
+
)
|
|
1277
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
1278
|
+
return entities, n_p
|
|
1279
|
+
|
|
1280
|
+
async def search_description(
|
|
1281
|
+
self,
|
|
1282
|
+
search_term: str,
|
|
1283
|
+
language_code: LocaleCode,
|
|
1284
|
+
limit: int = 30,
|
|
1285
|
+
auth_key: Optional[str] = None,
|
|
1286
|
+
next_page_id: str = None,
|
|
1287
|
+
) -> Tuple[List[ThingObject], str]:
|
|
1288
|
+
"""Search for matches in description.
|
|
1289
|
+
|
|
1290
|
+
Parameters
|
|
1291
|
+
----------
|
|
1292
|
+
search_term: str
|
|
1293
|
+
Search term.
|
|
1294
|
+
language_code: LocaleCode
|
|
1295
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., en_US.
|
|
1296
|
+
limit: int (default:= 30)
|
|
1297
|
+
Size of the page for pagination.
|
|
1298
|
+
auth_key: Optional[str] [default:=None]
|
|
1299
|
+
Auth key from user if not set, the client auth key will be used
|
|
1300
|
+
next_page_id: str [default:=None]
|
|
1301
|
+
ID of the next page within pagination.
|
|
1302
|
+
|
|
1303
|
+
Returns
|
|
1304
|
+
-------
|
|
1305
|
+
results: List[ThingObject]
|
|
1306
|
+
List of things matching the search term
|
|
1307
|
+
next_page_id: str
|
|
1308
|
+
ID of the next page.
|
|
1309
|
+
|
|
1310
|
+
Raises
|
|
1311
|
+
------
|
|
1312
|
+
WacomServiceException
|
|
1313
|
+
If the graph service returns an error code.
|
|
1314
|
+
"""
|
|
1315
|
+
if auth_key is None:
|
|
1316
|
+
auth_key, _ = await self.handle_token()
|
|
1317
|
+
url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.SEARCH_DESCRIPTION_ENDPOINT}"
|
|
1318
|
+
parameters: Dict[str, Any] = {SEARCH_TERM: search_term, LOCALE_TAG: language_code, LIMIT: str(limit)}
|
|
1319
|
+
# Only add next page id if it is not None
|
|
1320
|
+
if next_page_id is not None:
|
|
1321
|
+
parameters[NEXT_PAGE_ID_TAG] = next_page_id
|
|
1322
|
+
headers: dict = {AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
|
|
1323
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
1324
|
+
async with session.get(url, headers=headers, params=parameters, verify_ssl=self.verify_calls) as response:
|
|
1325
|
+
if not response.ok:
|
|
1326
|
+
raise await handle_error(
|
|
1327
|
+
f"Search on descriptions {search_term} failed. ",
|
|
1328
|
+
response,
|
|
1329
|
+
headers=headers,
|
|
1330
|
+
parameters=parameters,
|
|
1331
|
+
)
|
|
1332
|
+
entities, n_p = await AsyncWacomKnowledgeService.__search_results__(
|
|
1333
|
+
await response.json(loads=orjson.loads)
|
|
1334
|
+
)
|
|
1335
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
1336
|
+
return entities, n_p
|
|
1337
|
+
|
|
1338
|
+
@staticmethod
|
|
1339
|
+
async def __search_results__(response: Dict[str, Any]) -> Tuple[List[ThingObject], str]:
|
|
1340
|
+
results: List[ThingObject] = []
|
|
1341
|
+
for elem in response[RESULT_TAG]:
|
|
1342
|
+
results.append(ThingObject.from_dict(elem))
|
|
1343
|
+
return results, response[NEXT_PAGE_ID_TAG]
|
|
1344
|
+
|
|
1345
|
+
async def link_personal_entities(
|
|
1346
|
+
self, text: str, language_code: LocaleCode = EN_US, auth_key: Optional[str] = None
|
|
1347
|
+
) -> List[KnowledgeGraphEntity]:
|
|
1348
|
+
"""
|
|
1349
|
+
Performs Named Entities Linking on a text. It only finds entities which are accessible by the user identified by
|
|
1350
|
+
the auth key.
|
|
1351
|
+
|
|
1352
|
+
Parameters
|
|
1353
|
+
----------
|
|
1354
|
+
auth_key: str
|
|
1355
|
+
Auth key identifying a user within the Wacom personal knowledge service.
|
|
1356
|
+
text: str
|
|
1357
|
+
Text where the entities shall be tagged in.
|
|
1358
|
+
language_code: LocaleCode
|
|
1359
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1360
|
+
|
|
1361
|
+
Returns
|
|
1362
|
+
-------
|
|
1363
|
+
entities: List[KnowledgeGraphEntity]
|
|
1364
|
+
List of knowledge graph entities.
|
|
1365
|
+
|
|
1366
|
+
Raises
|
|
1367
|
+
------
|
|
1368
|
+
WacomServiceException
|
|
1369
|
+
If the Named Entities Linking service returns an error code.
|
|
1370
|
+
"""
|
|
1371
|
+
if auth_key is None:
|
|
1372
|
+
auth_key, _ = await self.handle_token()
|
|
1373
|
+
named_entities: List[KnowledgeGraphEntity] = []
|
|
1374
|
+
url: str = f"{self.service_base_url}{self.NAMED_ENTITY_LINKING_ENDPOINT}"
|
|
1375
|
+
headers: Dict[str, str] = {
|
|
1376
|
+
AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
|
|
1377
|
+
USER_AGENT_HEADER_FLAG: self.user_agent,
|
|
1378
|
+
CONTENT_TYPE_HEADER_FLAG: APPLICATION_JSON_HEADER,
|
|
1379
|
+
}
|
|
1380
|
+
payload: Dict[str, str] = {LOCALE_TAG: language_code, TEXT_TAG: text}
|
|
1381
|
+
|
|
1382
|
+
# Create a session and mount the retry adapter
|
|
1383
|
+
async with AsyncServiceAPIClient.__async_session__() as session:
|
|
1384
|
+
async with session.post(url, headers=headers, json=payload, verify_ssl=self.verify_calls) as response:
|
|
1385
|
+
if response.ok:
|
|
1386
|
+
results: dict = await response.json(loads=orjson.loads)
|
|
1387
|
+
for e in results:
|
|
1388
|
+
entity_types: List[str] = []
|
|
1389
|
+
# --------------------------- Entities content ---------------------------------------------------
|
|
1390
|
+
source: Optional[EntitySource] = None
|
|
1391
|
+
if "uri" in e:
|
|
1392
|
+
source = EntitySource(e["uri"], KnowledgeSource.WACOM_KNOWLEDGE)
|
|
1393
|
+
# --------------------------- Ontology types ---------------------------------------------------
|
|
1394
|
+
if "type" in e:
|
|
1395
|
+
entity_types.append(e["type"])
|
|
1396
|
+
# ----------------------------------------------------------------------------------------------
|
|
1397
|
+
start: int = e["startPosition"]
|
|
1398
|
+
end: int = e["endPosition"]
|
|
1399
|
+
ne: KnowledgeGraphEntity = KnowledgeGraphEntity(
|
|
1400
|
+
ref_text=text[start : end + 1],
|
|
1401
|
+
start_idx=start,
|
|
1402
|
+
end_idx=end,
|
|
1403
|
+
label=e["value"],
|
|
1404
|
+
confidence=0.0,
|
|
1405
|
+
source=source,
|
|
1406
|
+
content_link="",
|
|
1407
|
+
ontology_types=entity_types,
|
|
1408
|
+
entity_type=EntityType.PERSONAL_ENTITY,
|
|
1409
|
+
)
|
|
1410
|
+
ne.relevant_type = OntologyClassReference.parse(e["type"])
|
|
1411
|
+
named_entities.append(ne)
|
|
1412
|
+
else:
|
|
1413
|
+
raise await handle_error(
|
|
1414
|
+
f"Named entity linking for text:={text}@{language_code} failed. ",
|
|
1415
|
+
response,
|
|
1416
|
+
headers=headers,
|
|
1417
|
+
parameters=payload,
|
|
1418
|
+
)
|
|
1419
|
+
await asyncio.sleep(0.250 if self.use_graceful_shutdown else 0)
|
|
1420
|
+
return named_entities
|