octostar-python-client 0.1.759__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.
- octostar/__init__.py +9 -0
- octostar/api/__init__.py +1 -0
- octostar/api/apps/__init__.py +0 -0
- octostar/api/apps/deploy_app.py +210 -0
- octostar/api/apps/execute_app_job.py +188 -0
- octostar/api/apps/get_app_logs.py +210 -0
- octostar/api/apps/get_apps_url.py +188 -0
- octostar/api/apps/get_job_logs.py +210 -0
- octostar/api/apps/get_job_progress.py +162 -0
- octostar/api/apps/kill_job.py +160 -0
- octostar/api/apps/list_app_jobs.py +276 -0
- octostar/api/apps/list_apps.py +251 -0
- octostar/api/apps/set_job_progress.py +216 -0
- octostar/api/apps/undeploy_app.py +160 -0
- octostar/api/metadata/__init__.py +0 -0
- octostar/api/metadata/get_version.py +232 -0
- octostar/api/metadata/get_whoami.py +232 -0
- octostar/api/notifications/__init__.py +0 -0
- octostar/api/notifications/delete_stream.py +222 -0
- octostar/api/notifications/get_subscriptions.py +240 -0
- octostar/api/notifications/publish_notification.py +275 -0
- octostar/api/notifications/pull_events_from_stream.py +282 -0
- octostar/api/notifications/push_event_to_stream.py +265 -0
- octostar/api/notifications/toast.py +264 -0
- octostar/api/ontology/__init__.py +0 -0
- octostar/api/ontology/fetch_ontology_data.py +275 -0
- octostar/api/ontology/get_ontologies.py +237 -0
- octostar/api/ontology/multi_query.py +297 -0
- octostar/api/ontology/query.py +276 -0
- octostar/api/pipeline/__init__.py +1 -0
- octostar/api/pipeline/get_processing_status.py +185 -0
- octostar/api/pipeline/update_processing_status.py +164 -0
- octostar/api/search/__init__.py +0 -0
- octostar/api/search/get_annotations.py +153 -0
- octostar/api/workspace_data/__init__.py +0 -0
- octostar/api/workspace_data/delete_blob.py +212 -0
- octostar/api/workspace_data/delete_entities.py +326 -0
- octostar/api/workspace_data/download_blob.py +235 -0
- octostar/api/workspace_data/get_attachment.py +336 -0
- octostar/api/workspace_data/get_files_tree.py +397 -0
- octostar/api/workspace_data/upload_blob.py +235 -0
- octostar/api/workspace_data/upsert_entities.py +284 -0
- octostar/api/workspace_permissions/__init__.py +0 -0
- octostar/api/workspace_permissions/get_permissions.py +325 -0
- octostar/api/workspace_tags/__init__.py +0 -0
- octostar/api/workspace_tags/delete_tag_from_entities.py +141 -0
- octostar/api/workspace_tags/tag_entities.py +180 -0
- octostar/client.py +492 -0
- octostar/errors.py +50 -0
- octostar/models/__init__.py +249 -0
- octostar/models/acknowledgement.py +74 -0
- octostar/models/acknowledgement_with_data.py +82 -0
- octostar/models/app_status.py +239 -0
- octostar/models/app_status_annotations.py +66 -0
- octostar/models/app_status_labels.py +69 -0
- octostar/models/app_with_url.py +82 -0
- octostar/models/child_processing_status.py +118 -0
- octostar/models/delete_entities_response_401.py +74 -0
- octostar/models/delete_entities_response_409.py +82 -0
- octostar/models/delete_entities_response_500.py +82 -0
- octostar/models/delete_stream_response_401.py +74 -0
- octostar/models/delete_tag_from_entities_response_401.py +74 -0
- octostar/models/deploy_app_json_body.py +90 -0
- octostar/models/deploy_app_json_body_secrets.py +65 -0
- octostar/models/deploy_app_response_200.py +98 -0
- octostar/models/deploy_app_response_200_data.py +60 -0
- octostar/models/deploy_app_response_400.py +82 -0
- octostar/models/deploy_app_response_403.py +82 -0
- octostar/models/deploy_app_response_404.py +82 -0
- octostar/models/deploy_app_response_409.py +82 -0
- octostar/models/deploy_app_response_500.py +82 -0
- octostar/models/entity.py +80 -0
- octostar/models/entity_response.py +99 -0
- octostar/models/entity_response_s3_urls.py +93 -0
- octostar/models/entity_response_s3_urls_additional_property.py +105 -0
- octostar/models/entity_response_s3_urls_additional_property_fields.py +114 -0
- octostar/models/execute_app_job_json_body.py +151 -0
- octostar/models/execute_app_job_json_body_annotation.py +65 -0
- octostar/models/execute_app_job_response_401.py +74 -0
- octostar/models/fetch_ontology_data_response_200.py +60 -0
- octostar/models/fetch_ontology_data_response_401.py +74 -0
- octostar/models/fetch_ontology_data_response_500.py +82 -0
- octostar/models/get_app_logs_response_401.py +74 -0
- octostar/models/get_app_logs_response_404.py +74 -0
- octostar/models/get_app_logs_response_500.py +82 -0
- octostar/models/get_apps_url_json_body.py +76 -0
- octostar/models/get_apps_url_response_401.py +74 -0
- octostar/models/get_apps_url_response_500.py +82 -0
- octostar/models/get_attachment_response_200.py +74 -0
- octostar/models/get_attachment_response_401.py +74 -0
- octostar/models/get_files_tree_response_200.py +106 -0
- octostar/models/get_files_tree_response_200_status.py +8 -0
- octostar/models/get_files_tree_response_400.py +111 -0
- octostar/models/get_files_tree_response_400_data.py +60 -0
- octostar/models/get_files_tree_response_400_status.py +8 -0
- octostar/models/get_files_tree_response_401.py +74 -0
- octostar/models/get_files_tree_response_500.py +111 -0
- octostar/models/get_files_tree_response_500_data.py +60 -0
- octostar/models/get_files_tree_response_500_status.py +8 -0
- octostar/models/get_job_logs_response_401.py +74 -0
- octostar/models/get_job_logs_response_404.py +74 -0
- octostar/models/get_job_logs_response_500.py +82 -0
- octostar/models/get_job_progress_response_401.py +74 -0
- octostar/models/get_object_response_401.py +74 -0
- octostar/models/get_ontologies_response_401.py +74 -0
- octostar/models/get_ontologies_response_500.py +81 -0
- octostar/models/get_permissions_response_200.py +98 -0
- octostar/models/get_permissions_response_400.py +82 -0
- octostar/models/get_permissions_response_401.py +74 -0
- octostar/models/get_permissions_response_500.py +82 -0
- octostar/models/get_processing_status_response_200.py +104 -0
- octostar/models/get_processing_status_response_200_data.py +87 -0
- octostar/models/get_processing_status_response_400.py +82 -0
- octostar/models/get_processing_status_response_500.py +82 -0
- octostar/models/get_subscriptions_response_200_item.py +74 -0
- octostar/models/get_version_response_200.py +74 -0
- octostar/models/get_version_response_404.py +74 -0
- octostar/models/get_whoami_response_200.py +129 -0
- octostar/models/get_whoami_response_401.py +74 -0
- octostar/models/insert_entity.py +114 -0
- octostar/models/insert_entity_base.py +266 -0
- octostar/models/insert_entity_relationships_item.py +107 -0
- octostar/models/insert_entity_request.py +94 -0
- octostar/models/internal_server_error.py +82 -0
- octostar/models/job_execution_result.py +146 -0
- octostar/models/job_status.py +196 -0
- octostar/models/job_status_labels.py +60 -0
- octostar/models/job_with_url.py +82 -0
- octostar/models/kill_job_response_401.py +74 -0
- octostar/models/list_app_jobs_response_401.py +74 -0
- octostar/models/list_app_jobs_response_500.py +82 -0
- octostar/models/list_apps_response_401.py +74 -0
- octostar/models/list_apps_response_500.py +82 -0
- octostar/models/multi_query_json_body.py +100 -0
- octostar/models/multi_query_json_body_queries_item.py +80 -0
- octostar/models/multi_query_response_400.py +82 -0
- octostar/models/multi_query_response_401.py +74 -0
- octostar/models/not_found_error.py +74 -0
- octostar/models/octostar_event.py +96 -0
- octostar/models/octostar_event_octostar_payload.py +100 -0
- octostar/models/octostar_event_octostar_payload_level.py +11 -0
- octostar/models/os_notification.py +122 -0
- octostar/models/processing_status.py +262 -0
- octostar/models/processing_status_code.py +14 -0
- octostar/models/progress_request.py +73 -0
- octostar/models/publish_notification_response_401.py +74 -0
- octostar/models/pull_events_from_stream_response_401.py +74 -0
- octostar/models/push_event_to_stream_response_401.py +74 -0
- octostar/models/query_json_body.py +101 -0
- octostar/models/query_json_body_params.py +60 -0
- octostar/models/query_response_400.py +82 -0
- octostar/models/query_response_401.py +74 -0
- octostar/models/set_job_progress_response_401.py +74 -0
- octostar/models/string_to_value_label_map.py +99 -0
- octostar/models/string_to_value_label_map_data.py +89 -0
- octostar/models/string_to_value_label_map_data_additional_property.py +80 -0
- octostar/models/successful_get_tags.py +103 -0
- octostar/models/successful_insertion.py +98 -0
- octostar/models/tag_entities_response_401.py +74 -0
- octostar/models/toast_level.py +11 -0
- octostar/models/toast_response_401.py +74 -0
- octostar/models/undeploy_app_response_401.py +74 -0
- octostar/models/update_processing_status_response_200.py +82 -0
- octostar/models/update_processing_status_response_400.py +82 -0
- octostar/models/update_processing_status_response_500.py +82 -0
- octostar/models/upsert_entities_response_401.py +74 -0
- octostar/models/upsert_entity.py +114 -0
- octostar/models/upsert_entity_base.py +266 -0
- octostar/models/upsert_entity_relationships_item.py +107 -0
- octostar/py.typed +1 -0
- octostar/types.py +54 -0
- octostar/utils/__init__.py +15 -0
- octostar/utils/chat/__init__.py +0 -0
- octostar/utils/chat/chat.py +513 -0
- octostar/utils/chat/detokenize.py +105 -0
- octostar/utils/chat/get_default_model.py +50 -0
- octostar/utils/chat/list_models.py +91 -0
- octostar/utils/chat/tokenize.py +105 -0
- octostar/utils/commons.py +226 -0
- octostar/utils/exceptions.py +134 -0
- octostar/utils/jobs/__init__.py +0 -0
- octostar/utils/jobs/apps/__init__.py +0 -0
- octostar/utils/jobs/apps/deploy_app.py +81 -0
- octostar/utils/jobs/apps/execute_app_job.py +114 -0
- octostar/utils/jobs/apps/get_app_logs.py +113 -0
- octostar/utils/jobs/apps/get_app_secret.py +102 -0
- octostar/utils/jobs/apps/get_apps_url.py +73 -0
- octostar/utils/jobs/apps/list_app_jobs.py +62 -0
- octostar/utils/jobs/apps/list_apps.py +126 -0
- octostar/utils/jobs/apps/undeploy_app.py +48 -0
- octostar/utils/jobs/get_job_logs.py +113 -0
- octostar/utils/jobs/get_job_progress.py +76 -0
- octostar/utils/jobs/kill_job.py +47 -0
- octostar/utils/jobs/set_job_progress.py +67 -0
- octostar/utils/meta/__init__.py +0 -0
- octostar/utils/meta/get_version.py +30 -0
- octostar/utils/meta/get_whoami.py +30 -0
- octostar/utils/notifications/__init__.py +0 -0
- octostar/utils/notifications/delete_stream.py +58 -0
- octostar/utils/notifications/get_my_subscriptions.py +49 -0
- octostar/utils/notifications/publish_notification.py +73 -0
- octostar/utils/notifications/pull_event_from_stream.py +63 -0
- octostar/utils/notifications/pull_events_from_stream.py +64 -0
- octostar/utils/notifications/push_event_to_stream.py +109 -0
- octostar/utils/notifications/push_events_to_stream.py +137 -0
- octostar/utils/notifications/toast.py +92 -0
- octostar/utils/ontology/__init__.py +10 -0
- octostar/utils/ontology/fetch_ontology_data.py +141 -0
- octostar/utils/ontology/get_ontologies.py +55 -0
- octostar/utils/ontology/multiquery_ontology.py +287 -0
- octostar/utils/ontology/query_ontology.py +186 -0
- octostar/utils/pipeline/__init__.py +1 -0
- octostar/utils/pipeline/get_processing_status.py +230 -0
- octostar/utils/pipeline/update_processing_status.py +286 -0
- octostar/utils/search/__init__.py +11 -0
- octostar/utils/search/bulk_update.py +138 -0
- octostar/utils/search/count.py +117 -0
- octostar/utils/search/get_entity_annotations.py +304 -0
- octostar/utils/search/get_index_definition.py +111 -0
- octostar/utils/search/multi_search.py +129 -0
- octostar/utils/workspace/__init__.py +0 -0
- octostar/utils/workspace/delete_entities.py +247 -0
- octostar/utils/workspace/delete_entity.py +81 -0
- octostar/utils/workspace/delete_relationship.py +78 -0
- octostar/utils/workspace/delete_relationships.py +85 -0
- octostar/utils/workspace/delete_temporary_blob.py +85 -0
- octostar/utils/workspace/extract_entities.py +140 -0
- octostar/utils/workspace/get_filepath_from_item.py +85 -0
- octostar/utils/workspace/get_filepaths_from_items.py +100 -0
- octostar/utils/workspace/get_files_tree.py +102 -0
- octostar/utils/workspace/get_item_from_filepath.py +102 -0
- octostar/utils/workspace/get_items_from_filepaths.py +108 -0
- octostar/utils/workspace/linkcharts/__init__.py +0 -0
- octostar/utils/workspace/linkcharts/create_linkchart.py +241 -0
- octostar/utils/workspace/permissions/PermissionLevel.py +8 -0
- octostar/utils/workspace/permissions/__init__.py +1 -0
- octostar/utils/workspace/permissions/get_permissions.py +81 -0
- octostar/utils/workspace/read_attachment.py +284 -0
- octostar/utils/workspace/read_file.py +113 -0
- octostar/utils/workspace/read_temporary_blob.py +428 -0
- octostar/utils/workspace/saved_searches/__init__.py +0 -0
- octostar/utils/workspace/saved_searches/create_saved_search.py +183 -0
- octostar/utils/workspace/tags/__init__.py +0 -0
- octostar/utils/workspace/tags/delete_tag_from_entities.py +96 -0
- octostar/utils/workspace/tags/tag_entities.py +175 -0
- octostar/utils/workspace/upsert_entities.py +268 -0
- octostar/utils/workspace/upsert_entity.py +110 -0
- octostar/utils/workspace/upsert_relationship.py +128 -0
- octostar/utils/workspace/upsert_relationships.py +194 -0
- octostar/utils/workspace/write_attachment.py +263 -0
- octostar/utils/workspace/write_file.py +335 -0
- octostar/utils/workspace/write_temporary_blob.py +218 -0
- octostar_python_client-0.1.759.dist-info/METADATA +159 -0
- octostar_python_client-0.1.759.dist-info/RECORD +257 -0
- octostar_python_client-0.1.759.dist-info/WHEEL +5 -0
- octostar_python_client-0.1.759.dist-info/licenses/LICENSE +21 -0
- octostar_python_client-0.1.759.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from ...client import Client, get_default_client
|
|
4
|
+
from ..commons import network_retry_strategy
|
|
5
|
+
from ..exceptions import ApiConnectionError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def sync(body: dict, timeout: Optional[float] = 30.0, client: Optional[Client] = None):
|
|
9
|
+
"""
|
|
10
|
+
# Make a request for a count query to the search engine.
|
|
11
|
+
|
|
12
|
+
## Arguments
|
|
13
|
+
- `body`: The body for the search request. It should be compatible with OpenSearch's _count body format.
|
|
14
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
15
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
16
|
+
|
|
17
|
+
## Returns
|
|
18
|
+
The raw dictionary response from OpenSearch, containing the requested count.
|
|
19
|
+
|
|
20
|
+
## Raises
|
|
21
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
22
|
+
"""
|
|
23
|
+
if not client:
|
|
24
|
+
client = get_default_client()
|
|
25
|
+
endpoint_url = (
|
|
26
|
+
f"{client.get_base_url_v1()}/api/v1/search_api/{client.ontology}/_count"
|
|
27
|
+
)
|
|
28
|
+
headers = {
|
|
29
|
+
"Content-Type": "application/json",
|
|
30
|
+
"Authorization": f"Bearer {client.token}",
|
|
31
|
+
"x-ontology": client.ontology,
|
|
32
|
+
}
|
|
33
|
+
response = None
|
|
34
|
+
try:
|
|
35
|
+
for attempt in network_retry_strategy():
|
|
36
|
+
with attempt:
|
|
37
|
+
with httpx.Client() as httpx_client:
|
|
38
|
+
response = httpx_client.post(
|
|
39
|
+
endpoint_url, json=body, headers=headers, timeout=timeout
|
|
40
|
+
)
|
|
41
|
+
if response.status_code != 200:
|
|
42
|
+
raise ConnectionError(
|
|
43
|
+
f"Could not fetch data from search engine (status code {response.status_code}), responded with\n"
|
|
44
|
+
+ str(response.content)
|
|
45
|
+
)
|
|
46
|
+
try:
|
|
47
|
+
parsed = response.json()
|
|
48
|
+
except ValueError:
|
|
49
|
+
raise ConnectionError(
|
|
50
|
+
"Could not fetch data from search engine (failed to parse response), responded with\n"
|
|
51
|
+
+ str(response.content)
|
|
52
|
+
)
|
|
53
|
+
if parsed.get("errors"):
|
|
54
|
+
raise ConnectionError(
|
|
55
|
+
"Could not fetch data from search engine, (errors), responded with\n"
|
|
56
|
+
+ str(response.content)
|
|
57
|
+
)
|
|
58
|
+
except Exception:
|
|
59
|
+
raise ApiConnectionError("count", response, client)
|
|
60
|
+
return parsed
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
async def asyncio(
|
|
64
|
+
body: dict, timeout: Optional[float] = 30.0, client: Optional[Client] = None
|
|
65
|
+
):
|
|
66
|
+
"""
|
|
67
|
+
# Make asynchronously a request for a count query to the search engine.
|
|
68
|
+
|
|
69
|
+
## Arguments
|
|
70
|
+
- `body`: The body for the search request. It should be compatible with OpenSearch's _count body format.
|
|
71
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
72
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
73
|
+
|
|
74
|
+
## Returns
|
|
75
|
+
The raw dictionary response from OpenSearch, containing the requested count.
|
|
76
|
+
|
|
77
|
+
## Raises
|
|
78
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
79
|
+
"""
|
|
80
|
+
if not client:
|
|
81
|
+
client = get_default_client()
|
|
82
|
+
endpoint_url = (
|
|
83
|
+
f"{client.get_base_url_v1()}/api/v1/search_api/{client.ontology}/_count"
|
|
84
|
+
)
|
|
85
|
+
headers = {
|
|
86
|
+
"Content-Type": "application/json",
|
|
87
|
+
"Authorization": f"Bearer {client.token}",
|
|
88
|
+
"x-ontology": client.ontology,
|
|
89
|
+
}
|
|
90
|
+
response = None
|
|
91
|
+
try:
|
|
92
|
+
for attempt in network_retry_strategy():
|
|
93
|
+
with attempt:
|
|
94
|
+
async with httpx.AsyncClient() as httpx_client:
|
|
95
|
+
response = await httpx_client.post(
|
|
96
|
+
endpoint_url, json=body, headers=headers, timeout=timeout
|
|
97
|
+
)
|
|
98
|
+
if response.status_code != 200:
|
|
99
|
+
raise ConnectionError(
|
|
100
|
+
f"Could not fetch data from search engine (status code {response.status_code}), responded with\n"
|
|
101
|
+
+ str(response.content)
|
|
102
|
+
)
|
|
103
|
+
try:
|
|
104
|
+
parsed = response.json()
|
|
105
|
+
except ValueError:
|
|
106
|
+
raise ConnectionError(
|
|
107
|
+
"Could not fetch data from search engine (failed to parse response), responded with\n"
|
|
108
|
+
+ str(response.content)
|
|
109
|
+
)
|
|
110
|
+
if parsed.get("errors"):
|
|
111
|
+
raise ConnectionError(
|
|
112
|
+
"Could not fetch data from search engine, (errors), responded with\n"
|
|
113
|
+
+ str(response.content)
|
|
114
|
+
)
|
|
115
|
+
except Exception:
|
|
116
|
+
raise ApiConnectionError("count", response, client)
|
|
117
|
+
return parsed
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"""Thin wrapper around the server-side annotations endpoint.
|
|
2
|
+
|
|
3
|
+
All heavy lifting (fragment type resolution, DFS tree building, merge logic,
|
|
4
|
+
pagination) is handled by the ``POST /v1/search_api/{ontology}/annotations``
|
|
5
|
+
server-side endpoint. This module simply POSTs and returns the result.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import httpx
|
|
10
|
+
from typing import Any, Dict, List, Optional
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from typing import TypedDict
|
|
14
|
+
except ImportError: # pragma: no cover
|
|
15
|
+
from typing_extensions import TypedDict # type: ignore[assignment]
|
|
16
|
+
|
|
17
|
+
from ...client import Client, get_default_client
|
|
18
|
+
from ...api.search.get_annotations import _build_body
|
|
19
|
+
from ..commons import network_retry_strategy
|
|
20
|
+
from ..exceptions import ApiConnectionError
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
_FRAGMENT_BATCH_SIZE = 10000
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class MergeKwargs(TypedDict, total=False):
|
|
28
|
+
"""Tunables for the server-side fragment merge step (``merge=True``).
|
|
29
|
+
|
|
30
|
+
Declared ``total=False`` so callers can provide any subset of fields;
|
|
31
|
+
missing keys fall back to server defaults. New merge options can be
|
|
32
|
+
added here without changing the function signature.
|
|
33
|
+
|
|
34
|
+
Fields:
|
|
35
|
+
- ``inline_inserts``: When True (default on the server), insert-type
|
|
36
|
+
fragments (e.g. embedded images) are wrapped with a contextual marker
|
|
37
|
+
and included in the merged text. When False, insert-type fragments
|
|
38
|
+
are excluded from the merge entirely. Only meaningful when
|
|
39
|
+
``merge=True``.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
inline_inserts: bool
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _post_annotations(
|
|
46
|
+
client: Client,
|
|
47
|
+
body: Dict[str, Any],
|
|
48
|
+
timeout: Optional[float],
|
|
49
|
+
) -> Dict[str, Any]:
|
|
50
|
+
url = f"{client.get_base_url_v1()}/api/v1/search_api/{client.ontology}/annotations"
|
|
51
|
+
headers = {
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
"Authorization": f"Bearer {client.token}",
|
|
54
|
+
"x-ontology": client.ontology,
|
|
55
|
+
}
|
|
56
|
+
response = None
|
|
57
|
+
try:
|
|
58
|
+
for attempt in network_retry_strategy():
|
|
59
|
+
with attempt:
|
|
60
|
+
with httpx.Client() as hc:
|
|
61
|
+
response = hc.post(
|
|
62
|
+
url,
|
|
63
|
+
json=body,
|
|
64
|
+
headers=headers,
|
|
65
|
+
timeout=timeout,
|
|
66
|
+
)
|
|
67
|
+
if response.status_code != 200:
|
|
68
|
+
raise ConnectionError(
|
|
69
|
+
f"annotations endpoint returned {response.status_code}: "
|
|
70
|
+
+ f"{response.text[:500]}"
|
|
71
|
+
)
|
|
72
|
+
payload = response.json()
|
|
73
|
+
resp_errors = payload.get("errors")
|
|
74
|
+
if resp_errors:
|
|
75
|
+
logger.warning(
|
|
76
|
+
"annotations endpoint returned non-fatal warnings: %s",
|
|
77
|
+
"; ".join(resp_errors),
|
|
78
|
+
)
|
|
79
|
+
return payload["data"]
|
|
80
|
+
except ConnectionError:
|
|
81
|
+
raise ApiConnectionError("get_entity_annotations", response, client)
|
|
82
|
+
except Exception:
|
|
83
|
+
raise ApiConnectionError("get_entity_annotations", response, client)
|
|
84
|
+
return {}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
async def _post_annotations_async(
|
|
88
|
+
client: Client,
|
|
89
|
+
body: Dict[str, Any],
|
|
90
|
+
timeout: Optional[float],
|
|
91
|
+
) -> Dict[str, Any]:
|
|
92
|
+
url = f"{client.get_base_url_v1()}/api/v1/search_api/{client.ontology}/annotations"
|
|
93
|
+
headers = {
|
|
94
|
+
"Content-Type": "application/json",
|
|
95
|
+
"Authorization": f"Bearer {client.token}",
|
|
96
|
+
"x-ontology": client.ontology,
|
|
97
|
+
}
|
|
98
|
+
response = None
|
|
99
|
+
try:
|
|
100
|
+
for attempt in network_retry_strategy():
|
|
101
|
+
with attempt:
|
|
102
|
+
async with httpx.AsyncClient() as hc:
|
|
103
|
+
response = await hc.post(
|
|
104
|
+
url,
|
|
105
|
+
json=body,
|
|
106
|
+
headers=headers,
|
|
107
|
+
timeout=timeout,
|
|
108
|
+
)
|
|
109
|
+
if response.status_code != 200:
|
|
110
|
+
raise ConnectionError(
|
|
111
|
+
f"annotations endpoint returned {response.status_code}: "
|
|
112
|
+
+ f"{response.text[:500]}"
|
|
113
|
+
)
|
|
114
|
+
payload = response.json()
|
|
115
|
+
resp_errors = payload.get("errors")
|
|
116
|
+
if resp_errors:
|
|
117
|
+
logger.warning(
|
|
118
|
+
"annotations endpoint returned non-fatal warnings: %s",
|
|
119
|
+
"; ".join(resp_errors),
|
|
120
|
+
)
|
|
121
|
+
return payload["data"]
|
|
122
|
+
except ConnectionError:
|
|
123
|
+
raise ApiConnectionError("get_entity_annotations", response, client)
|
|
124
|
+
except Exception:
|
|
125
|
+
raise ApiConnectionError("get_entity_annotations", response, client)
|
|
126
|
+
return {}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def sync(
|
|
130
|
+
os_entity_uids: List[str],
|
|
131
|
+
fields: Optional[List[str]] = None,
|
|
132
|
+
timeout: Optional[float] = 30.0,
|
|
133
|
+
client: Optional[Client] = None,
|
|
134
|
+
recurse: bool = True,
|
|
135
|
+
merge: bool = True,
|
|
136
|
+
max_fragments: Optional[int] = _FRAGMENT_BATCH_SIZE,
|
|
137
|
+
fragment_filter: Optional[Dict[str, Any]] = None,
|
|
138
|
+
include_record: bool = False,
|
|
139
|
+
collapse: bool = True,
|
|
140
|
+
merge_kwargs: Optional[MergeKwargs] = None,
|
|
141
|
+
):
|
|
142
|
+
"""# Get the annotations associated with one or more entities.
|
|
143
|
+
|
|
144
|
+
## Arguments
|
|
145
|
+
- `os_entity_uids`: A list of entity IDs.
|
|
146
|
+
- `fields`: A list of annotations fields to fetch, or "None" for all
|
|
147
|
+
annotations. Nested fields can be specified with ".".
|
|
148
|
+
- `timeout`: The timeout for the connection to the search engine. Can be
|
|
149
|
+
set to "None" for no enforced timeout.
|
|
150
|
+
- `client`: The Client with which to connect to Octostar. If None, the
|
|
151
|
+
default one is used.
|
|
152
|
+
- `recurse`: If True, also fetches annotations from fragment documents whose
|
|
153
|
+
`document_fields.source_entity_uid` matches the **root file** for each
|
|
154
|
+
input. For a fragment input that root comes from `source_entity_uid`;
|
|
155
|
+
for a non-fragment from `os_entity_uid`. Fragment subtrees are ordered via
|
|
156
|
+
`document_fields.os_parent_uid` and `fragment_index`.
|
|
157
|
+
- `merge`: Only meaningful when `recurse=True`. If True, fragment
|
|
158
|
+
annotations are merged into the parent's annotations using
|
|
159
|
+
`_MERGE_STRATEGY` and the return shape is `{entity_id: annotations}`.
|
|
160
|
+
If False, all annotations (parent and fragments) are returned as-is
|
|
161
|
+
in DFS tree order and the return shape is
|
|
162
|
+
`{entity_id: {doc_id: annotations}}` where the first key is the
|
|
163
|
+
input entity followed by fragment IDs.
|
|
164
|
+
- `max_fragments`: Maximum number of fragment documents to fetch. Defaults
|
|
165
|
+
to 10 000. Set to ``None`` to fetch all fragments (paginated
|
|
166
|
+
automatically in batches of 10 000).
|
|
167
|
+
- `fragment_filter`: Optional raw OpenSearch query DSL clause applied to the
|
|
168
|
+
fragment query. Only fragments matching this filter (and their subtrees)
|
|
169
|
+
are included in the result.
|
|
170
|
+
- `include_record`: When True, each entry includes the document_fields
|
|
171
|
+
(flattened) alongside a ``#annotations`` key. When False (default), each
|
|
172
|
+
entry is the annotations dict directly (backwards-compatible).
|
|
173
|
+
- `collapse`: Only meaningful when ``merge=True``. When True (default),
|
|
174
|
+
all fragment annotations are collapsed into a single entry per entity.
|
|
175
|
+
When False, each fragment's subtree is merged into that fragment but all
|
|
176
|
+
fragments are returned (same shape as ``merge=False``).
|
|
177
|
+
- `merge_kwargs`: Options that tune the merge step. Only applied when
|
|
178
|
+
``merge=True``. Pass as a ``MergeKwargs`` dict, e.g.
|
|
179
|
+
``{"inline_inserts": False}``. See :class:`MergeKwargs` for the
|
|
180
|
+
supported fields. Grouped so new knobs can be added without changing
|
|
181
|
+
this function's signature.
|
|
182
|
+
|
|
183
|
+
## Returns
|
|
184
|
+
When `include_record=False` (default):
|
|
185
|
+
- `recurse=False` or (`merge=True` and `collapse=True`):
|
|
186
|
+
``{entity_id: annotations_dict}``
|
|
187
|
+
- `recurse=True` and (`merge=False` or `collapse=False`):
|
|
188
|
+
``{entity_id: {doc_id: annotations_dict}}``
|
|
189
|
+
|
|
190
|
+
When `include_record=True`:
|
|
191
|
+
- `recurse=False` or (`merge=True` and `collapse=True`):
|
|
192
|
+
``{entity_id: {**document_fields, "#annotations": annotations_dict}}``
|
|
193
|
+
- `recurse=True` and (`merge=False` or `collapse=False`):
|
|
194
|
+
``{entity_id: {doc_id: {**document_fields, "#annotations": annotations_dict}}}``
|
|
195
|
+
|
|
196
|
+
## Raises
|
|
197
|
+
- `ApiConnectionError`: If the query for annotations was unsuccessful.
|
|
198
|
+
"""
|
|
199
|
+
if not client:
|
|
200
|
+
client = get_default_client()
|
|
201
|
+
if not os_entity_uids:
|
|
202
|
+
return {}
|
|
203
|
+
|
|
204
|
+
body = _build_body(
|
|
205
|
+
os_entity_uids,
|
|
206
|
+
fields,
|
|
207
|
+
recurse,
|
|
208
|
+
merge,
|
|
209
|
+
max_fragments,
|
|
210
|
+
fragment_filter,
|
|
211
|
+
include_record,
|
|
212
|
+
collapse,
|
|
213
|
+
merge_kwargs,
|
|
214
|
+
)
|
|
215
|
+
return _post_annotations(client, body, timeout)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
async def asyncio(
|
|
219
|
+
os_entity_uids: List[str],
|
|
220
|
+
fields: Optional[List[str]] = None,
|
|
221
|
+
timeout: Optional[float] = 30.0,
|
|
222
|
+
client: Optional[Client] = None,
|
|
223
|
+
recurse: bool = True,
|
|
224
|
+
merge: bool = True,
|
|
225
|
+
max_fragments: Optional[int] = _FRAGMENT_BATCH_SIZE,
|
|
226
|
+
fragment_filter: Optional[Dict[str, Any]] = None,
|
|
227
|
+
include_record: bool = False,
|
|
228
|
+
collapse: bool = True,
|
|
229
|
+
merge_kwargs: Optional[MergeKwargs] = None,
|
|
230
|
+
):
|
|
231
|
+
"""# Get asynchronously the annotations associated with one or more entities.
|
|
232
|
+
|
|
233
|
+
## Arguments
|
|
234
|
+
- `os_entity_uids`: A list of entity IDs.
|
|
235
|
+
- `fields`: A list of annotations fields to fetch, or "None" for all
|
|
236
|
+
annotations. Nested fields can be specified with ".".
|
|
237
|
+
- `timeout`: The timeout for the connection to the search engine. Can be
|
|
238
|
+
set to "None" for no enforced timeout.
|
|
239
|
+
- `client`: The Client with which to connect to Octostar. If None, the
|
|
240
|
+
default one is used.
|
|
241
|
+
- `recurse`: If True, also fetches annotations from fragment documents whose
|
|
242
|
+
`document_fields.source_entity_uid` matches the **root file** for each
|
|
243
|
+
input. For a fragment input that root comes from `source_entity_uid`;
|
|
244
|
+
for a non-fragment from `os_entity_uid`. Fragment subtrees are ordered via
|
|
245
|
+
`document_fields.os_parent_uid` and `fragment_index`.
|
|
246
|
+
- `merge`: Only meaningful when `recurse=True`. If True, fragment
|
|
247
|
+
annotations are merged into the parent's annotations using
|
|
248
|
+
`_MERGE_STRATEGY` and the return shape is `{entity_id: annotations}`.
|
|
249
|
+
If False, all annotations (parent and fragments) are returned as-is
|
|
250
|
+
in DFS tree order and the return shape is
|
|
251
|
+
`{entity_id: {doc_id: annotations}}` where the first key is the
|
|
252
|
+
input entity followed by fragment IDs.
|
|
253
|
+
- `max_fragments`: Maximum number of fragment documents to fetch. Defaults
|
|
254
|
+
to 10 000. Set to ``None`` to fetch all fragments (paginated
|
|
255
|
+
automatically in batches of 10 000).
|
|
256
|
+
- `fragment_filter`: Optional raw OpenSearch query DSL clause applied to the
|
|
257
|
+
fragment query. Only fragments matching this filter (and their subtrees)
|
|
258
|
+
are included in the result.
|
|
259
|
+
- `include_record`: When True, each entry includes the document_fields
|
|
260
|
+
(flattened) alongside a ``#annotations`` key. When False (default), each
|
|
261
|
+
entry is the annotations dict directly (backwards-compatible).
|
|
262
|
+
- `collapse`: Only meaningful when ``merge=True``. When True (default),
|
|
263
|
+
all fragment annotations are collapsed into a single entry per entity.
|
|
264
|
+
When False, each fragment's subtree is merged into that fragment but all
|
|
265
|
+
fragments are returned (same shape as ``merge=False``).
|
|
266
|
+
- `merge_kwargs`: Options that tune the merge step. Only applied when
|
|
267
|
+
``merge=True``. Pass as a ``MergeKwargs`` dict, e.g.
|
|
268
|
+
``{"inline_inserts": False}``. See :class:`MergeKwargs` for the
|
|
269
|
+
supported fields. Grouped so new knobs can be added without changing
|
|
270
|
+
this function's signature.
|
|
271
|
+
|
|
272
|
+
## Returns
|
|
273
|
+
When `include_record=False` (default):
|
|
274
|
+
- `recurse=False` or (`merge=True` and `collapse=True`):
|
|
275
|
+
``{entity_id: annotations_dict}``
|
|
276
|
+
- `recurse=True` and (`merge=False` or `collapse=False`):
|
|
277
|
+
``{entity_id: {doc_id: annotations_dict}}``
|
|
278
|
+
|
|
279
|
+
When `include_record=True`:
|
|
280
|
+
- `recurse=False` or (`merge=True` and `collapse=True`):
|
|
281
|
+
``{entity_id: {**document_fields, "#annotations": annotations_dict}}``
|
|
282
|
+
- `recurse=True` and (`merge=False` or `collapse=False`):
|
|
283
|
+
``{entity_id: {doc_id: {**document_fields, "#annotations": annotations_dict}}}``
|
|
284
|
+
|
|
285
|
+
## Raises
|
|
286
|
+
- `ApiConnectionError`: If the query for annotations was unsuccessful.
|
|
287
|
+
"""
|
|
288
|
+
if not client:
|
|
289
|
+
client = get_default_client()
|
|
290
|
+
if not os_entity_uids:
|
|
291
|
+
return {}
|
|
292
|
+
|
|
293
|
+
body = _build_body(
|
|
294
|
+
os_entity_uids,
|
|
295
|
+
fields,
|
|
296
|
+
recurse,
|
|
297
|
+
merge,
|
|
298
|
+
max_fragments,
|
|
299
|
+
fragment_filter,
|
|
300
|
+
include_record,
|
|
301
|
+
collapse,
|
|
302
|
+
merge_kwargs,
|
|
303
|
+
)
|
|
304
|
+
return await _post_annotations_async(client, body, timeout)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from ...client import Client, get_default_client
|
|
4
|
+
from ..commons import network_retry_strategy
|
|
5
|
+
from ..exceptions import ApiConnectionError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def sync(timeout: Optional[float] = 30.0, client: Optional[Client] = None) -> dict:
|
|
9
|
+
"""
|
|
10
|
+
# Get the search index definition (mapping + settings).
|
|
11
|
+
|
|
12
|
+
## Arguments
|
|
13
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
14
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
15
|
+
|
|
16
|
+
## Returns
|
|
17
|
+
The raw dictionary response from OpenSearch, containing the entire mapping definition.
|
|
18
|
+
|
|
19
|
+
## Raises
|
|
20
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
21
|
+
"""
|
|
22
|
+
if not client:
|
|
23
|
+
client = get_default_client()
|
|
24
|
+
endpoint_url = f"{client.get_base_url_v1()}/api/v1/search_api/{client.ontology}/_index_definition"
|
|
25
|
+
headers = {
|
|
26
|
+
"Content-Type": "application/json",
|
|
27
|
+
"Authorization": f"Bearer {client.token}",
|
|
28
|
+
"x-ontology": client.ontology,
|
|
29
|
+
}
|
|
30
|
+
response = None
|
|
31
|
+
try:
|
|
32
|
+
for attempt in network_retry_strategy():
|
|
33
|
+
with attempt:
|
|
34
|
+
with httpx.Client() as httpx_client:
|
|
35
|
+
response = httpx_client.get(
|
|
36
|
+
endpoint_url, headers=headers, timeout=timeout
|
|
37
|
+
)
|
|
38
|
+
if response.status_code != 200:
|
|
39
|
+
raise ConnectionError(
|
|
40
|
+
f"Could not fetch data from search engine (status code {response.status_code}), responded with\n"
|
|
41
|
+
+ str(response.content)
|
|
42
|
+
)
|
|
43
|
+
try:
|
|
44
|
+
parsed = response.json()
|
|
45
|
+
except ValueError:
|
|
46
|
+
raise ConnectionError(
|
|
47
|
+
"Could not fetch data from search engine (failed to parse response), responded with\n"
|
|
48
|
+
+ str(response.content)
|
|
49
|
+
)
|
|
50
|
+
if parsed.get("errors"):
|
|
51
|
+
raise ConnectionError(
|
|
52
|
+
"Could not fetch data from search engine, (errors), responded with\n"
|
|
53
|
+
+ str(response.content)
|
|
54
|
+
)
|
|
55
|
+
except Exception:
|
|
56
|
+
raise ApiConnectionError("get_index_definition", response, client)
|
|
57
|
+
return parsed
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
async def asyncio(
|
|
61
|
+
timeout: Optional[float] = 30.0, client: Optional[Client] = None
|
|
62
|
+
) -> dict:
|
|
63
|
+
"""
|
|
64
|
+
# Get asynchronously the search index definition (mapping + settings).
|
|
65
|
+
|
|
66
|
+
## Arguments
|
|
67
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
68
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
69
|
+
|
|
70
|
+
## Returns
|
|
71
|
+
The raw dictionary response from OpenSearch, containing the entire mapping definition.
|
|
72
|
+
|
|
73
|
+
## Raises
|
|
74
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
75
|
+
"""
|
|
76
|
+
if not client:
|
|
77
|
+
client = get_default_client()
|
|
78
|
+
endpoint_url = f"{client.get_base_url_v1()}/api/v1/search_api/{client.ontology}/_index_definition"
|
|
79
|
+
headers = {
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
"Authorization": f"Bearer {client.token}",
|
|
82
|
+
"x-ontology": client.ontology,
|
|
83
|
+
}
|
|
84
|
+
response = None
|
|
85
|
+
try:
|
|
86
|
+
for attempt in network_retry_strategy():
|
|
87
|
+
with attempt:
|
|
88
|
+
async with httpx.AsyncClient() as httpx_client:
|
|
89
|
+
response = await httpx_client.get(
|
|
90
|
+
endpoint_url, headers=headers, timeout=timeout
|
|
91
|
+
)
|
|
92
|
+
if response.status_code != 200:
|
|
93
|
+
raise ConnectionError(
|
|
94
|
+
f"Could not fetch data from search engine (status code {response.status_code}), responded with\n"
|
|
95
|
+
+ str(response.content)
|
|
96
|
+
)
|
|
97
|
+
try:
|
|
98
|
+
parsed = response.json()
|
|
99
|
+
except ValueError:
|
|
100
|
+
raise ConnectionError(
|
|
101
|
+
"Could not fetch data from search engine (failed to parse response), responded with\n"
|
|
102
|
+
+ str(response.content)
|
|
103
|
+
)
|
|
104
|
+
if parsed.get("errors"):
|
|
105
|
+
raise ConnectionError(
|
|
106
|
+
"Could not fetch data from search engine, (errors), responded with\n"
|
|
107
|
+
+ str(response.content)
|
|
108
|
+
)
|
|
109
|
+
except Exception:
|
|
110
|
+
raise ApiConnectionError("get_index_definition", response, client)
|
|
111
|
+
return parsed
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from ...client import Client, get_default_client
|
|
4
|
+
from ..exceptions import ApiConnectionError
|
|
5
|
+
from ..commons import network_retry_strategy
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def sync(body: str, timeout: Optional[float] = 30.0, client: Optional[Client] = None):
|
|
9
|
+
"""
|
|
10
|
+
# Make a request for multiple searches to the search engine.
|
|
11
|
+
|
|
12
|
+
## Arguments
|
|
13
|
+
- `body`: The body for the search request. It should be compatible with OpenSearch's _msearch body format.
|
|
14
|
+
Typically, it is in newline-separated JSONs, and it will look something like:
|
|
15
|
+
```
|
|
16
|
+
{"preference": "result"}
|
|
17
|
+
{"query": <first_opensearch_query>}
|
|
18
|
+
{"preference": "result"}
|
|
19
|
+
{"query": <second_opensearch_query>}
|
|
20
|
+
...
|
|
21
|
+
```
|
|
22
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
23
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
24
|
+
|
|
25
|
+
## Returns
|
|
26
|
+
The raw dictionary response from OpenSearch, containing the results of all requested searches.
|
|
27
|
+
|
|
28
|
+
## Raises
|
|
29
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
30
|
+
"""
|
|
31
|
+
if not client:
|
|
32
|
+
client = get_default_client()
|
|
33
|
+
if not body.endswith("\n"):
|
|
34
|
+
body += "\n"
|
|
35
|
+
endpoint_url = (
|
|
36
|
+
f"{client.get_base_url_v1()}/api/v1/search_api/{client.ontology}/_msearch"
|
|
37
|
+
)
|
|
38
|
+
headers = {
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
"Authorization": f"Bearer {client.token}",
|
|
41
|
+
"x-ontology": client.ontology,
|
|
42
|
+
}
|
|
43
|
+
response = None
|
|
44
|
+
try:
|
|
45
|
+
for attempt in network_retry_strategy():
|
|
46
|
+
with attempt:
|
|
47
|
+
with httpx.Client() as httpx_client:
|
|
48
|
+
response = httpx_client.post(
|
|
49
|
+
endpoint_url, data=body, headers=headers, timeout=timeout
|
|
50
|
+
)
|
|
51
|
+
response.raise_for_status()
|
|
52
|
+
try:
|
|
53
|
+
parsed = response.json()
|
|
54
|
+
except ValueError:
|
|
55
|
+
raise ConnectionError(
|
|
56
|
+
"Could not fetch data from search engine (failed to parse response), responded with\n"
|
|
57
|
+
+ str(response.content)
|
|
58
|
+
)
|
|
59
|
+
if parsed.get("errors"):
|
|
60
|
+
raise ConnectionError(
|
|
61
|
+
"Could not fetch data from search engine, (errors), responded with\n"
|
|
62
|
+
+ str(response.content)
|
|
63
|
+
)
|
|
64
|
+
except Exception:
|
|
65
|
+
raise ApiConnectionError("multi_search", response, client)
|
|
66
|
+
return parsed
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
async def asyncio(
|
|
70
|
+
body: str, timeout: Optional[float] = 30.0, client: Optional[Client] = None
|
|
71
|
+
):
|
|
72
|
+
"""
|
|
73
|
+
# Make asynchronously a request for multiple searches to the search engine.
|
|
74
|
+
|
|
75
|
+
## Arguments
|
|
76
|
+
- `body`: The body for the search request. It should be compatible with OpenSearch's _msearch body format.
|
|
77
|
+
Typically, it is in newline-separated JSONs, and it will look something like:
|
|
78
|
+
```
|
|
79
|
+
{"preference": "result"}
|
|
80
|
+
{"query": <first_opensearch_query>}
|
|
81
|
+
{"preference": "result"}
|
|
82
|
+
{"query": <second_opensearch_query>}
|
|
83
|
+
...
|
|
84
|
+
```
|
|
85
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
86
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
87
|
+
|
|
88
|
+
## Returns
|
|
89
|
+
The raw dictionary response from OpenSearch, containing the results of all requested searches.
|
|
90
|
+
|
|
91
|
+
## Raises
|
|
92
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
93
|
+
"""
|
|
94
|
+
if not client:
|
|
95
|
+
client = get_default_client()
|
|
96
|
+
if not body.endswith("\n"):
|
|
97
|
+
body += "\n"
|
|
98
|
+
endpoint_url = (
|
|
99
|
+
f"{client.get_base_url_v1()}/api/v1/search_api/{client.ontology}/_msearch"
|
|
100
|
+
)
|
|
101
|
+
headers = {
|
|
102
|
+
"Content-Type": "application/json",
|
|
103
|
+
"Authorization": f"Bearer {client.token}",
|
|
104
|
+
"x-ontology": client.ontology,
|
|
105
|
+
}
|
|
106
|
+
response = None
|
|
107
|
+
try:
|
|
108
|
+
for attempt in network_retry_strategy():
|
|
109
|
+
with attempt:
|
|
110
|
+
async with httpx.AsyncClient() as httpx_client:
|
|
111
|
+
response = await httpx_client.post(
|
|
112
|
+
endpoint_url, data=body, headers=headers, timeout=timeout
|
|
113
|
+
)
|
|
114
|
+
response.raise_for_status()
|
|
115
|
+
try:
|
|
116
|
+
parsed = response.json()
|
|
117
|
+
except ValueError:
|
|
118
|
+
raise ConnectionError(
|
|
119
|
+
"Could not fetch data from search engine (failed to parse response), responded with\n"
|
|
120
|
+
+ str(response.content)
|
|
121
|
+
)
|
|
122
|
+
if parsed.get("errors"):
|
|
123
|
+
raise ConnectionError(
|
|
124
|
+
"Could not fetch data from search engine, (errors), responded with\n"
|
|
125
|
+
+ str(response.content)
|
|
126
|
+
)
|
|
127
|
+
except Exception:
|
|
128
|
+
raise ApiConnectionError("multi_search", response, client)
|
|
129
|
+
return parsed
|
|
File without changes
|