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.
Files changed (257) hide show
  1. octostar/__init__.py +9 -0
  2. octostar/api/__init__.py +1 -0
  3. octostar/api/apps/__init__.py +0 -0
  4. octostar/api/apps/deploy_app.py +210 -0
  5. octostar/api/apps/execute_app_job.py +188 -0
  6. octostar/api/apps/get_app_logs.py +210 -0
  7. octostar/api/apps/get_apps_url.py +188 -0
  8. octostar/api/apps/get_job_logs.py +210 -0
  9. octostar/api/apps/get_job_progress.py +162 -0
  10. octostar/api/apps/kill_job.py +160 -0
  11. octostar/api/apps/list_app_jobs.py +276 -0
  12. octostar/api/apps/list_apps.py +251 -0
  13. octostar/api/apps/set_job_progress.py +216 -0
  14. octostar/api/apps/undeploy_app.py +160 -0
  15. octostar/api/metadata/__init__.py +0 -0
  16. octostar/api/metadata/get_version.py +232 -0
  17. octostar/api/metadata/get_whoami.py +232 -0
  18. octostar/api/notifications/__init__.py +0 -0
  19. octostar/api/notifications/delete_stream.py +222 -0
  20. octostar/api/notifications/get_subscriptions.py +240 -0
  21. octostar/api/notifications/publish_notification.py +275 -0
  22. octostar/api/notifications/pull_events_from_stream.py +282 -0
  23. octostar/api/notifications/push_event_to_stream.py +265 -0
  24. octostar/api/notifications/toast.py +264 -0
  25. octostar/api/ontology/__init__.py +0 -0
  26. octostar/api/ontology/fetch_ontology_data.py +275 -0
  27. octostar/api/ontology/get_ontologies.py +237 -0
  28. octostar/api/ontology/multi_query.py +297 -0
  29. octostar/api/ontology/query.py +276 -0
  30. octostar/api/pipeline/__init__.py +1 -0
  31. octostar/api/pipeline/get_processing_status.py +185 -0
  32. octostar/api/pipeline/update_processing_status.py +164 -0
  33. octostar/api/search/__init__.py +0 -0
  34. octostar/api/search/get_annotations.py +153 -0
  35. octostar/api/workspace_data/__init__.py +0 -0
  36. octostar/api/workspace_data/delete_blob.py +212 -0
  37. octostar/api/workspace_data/delete_entities.py +326 -0
  38. octostar/api/workspace_data/download_blob.py +235 -0
  39. octostar/api/workspace_data/get_attachment.py +336 -0
  40. octostar/api/workspace_data/get_files_tree.py +397 -0
  41. octostar/api/workspace_data/upload_blob.py +235 -0
  42. octostar/api/workspace_data/upsert_entities.py +284 -0
  43. octostar/api/workspace_permissions/__init__.py +0 -0
  44. octostar/api/workspace_permissions/get_permissions.py +325 -0
  45. octostar/api/workspace_tags/__init__.py +0 -0
  46. octostar/api/workspace_tags/delete_tag_from_entities.py +141 -0
  47. octostar/api/workspace_tags/tag_entities.py +180 -0
  48. octostar/client.py +492 -0
  49. octostar/errors.py +50 -0
  50. octostar/models/__init__.py +249 -0
  51. octostar/models/acknowledgement.py +74 -0
  52. octostar/models/acknowledgement_with_data.py +82 -0
  53. octostar/models/app_status.py +239 -0
  54. octostar/models/app_status_annotations.py +66 -0
  55. octostar/models/app_status_labels.py +69 -0
  56. octostar/models/app_with_url.py +82 -0
  57. octostar/models/child_processing_status.py +118 -0
  58. octostar/models/delete_entities_response_401.py +74 -0
  59. octostar/models/delete_entities_response_409.py +82 -0
  60. octostar/models/delete_entities_response_500.py +82 -0
  61. octostar/models/delete_stream_response_401.py +74 -0
  62. octostar/models/delete_tag_from_entities_response_401.py +74 -0
  63. octostar/models/deploy_app_json_body.py +90 -0
  64. octostar/models/deploy_app_json_body_secrets.py +65 -0
  65. octostar/models/deploy_app_response_200.py +98 -0
  66. octostar/models/deploy_app_response_200_data.py +60 -0
  67. octostar/models/deploy_app_response_400.py +82 -0
  68. octostar/models/deploy_app_response_403.py +82 -0
  69. octostar/models/deploy_app_response_404.py +82 -0
  70. octostar/models/deploy_app_response_409.py +82 -0
  71. octostar/models/deploy_app_response_500.py +82 -0
  72. octostar/models/entity.py +80 -0
  73. octostar/models/entity_response.py +99 -0
  74. octostar/models/entity_response_s3_urls.py +93 -0
  75. octostar/models/entity_response_s3_urls_additional_property.py +105 -0
  76. octostar/models/entity_response_s3_urls_additional_property_fields.py +114 -0
  77. octostar/models/execute_app_job_json_body.py +151 -0
  78. octostar/models/execute_app_job_json_body_annotation.py +65 -0
  79. octostar/models/execute_app_job_response_401.py +74 -0
  80. octostar/models/fetch_ontology_data_response_200.py +60 -0
  81. octostar/models/fetch_ontology_data_response_401.py +74 -0
  82. octostar/models/fetch_ontology_data_response_500.py +82 -0
  83. octostar/models/get_app_logs_response_401.py +74 -0
  84. octostar/models/get_app_logs_response_404.py +74 -0
  85. octostar/models/get_app_logs_response_500.py +82 -0
  86. octostar/models/get_apps_url_json_body.py +76 -0
  87. octostar/models/get_apps_url_response_401.py +74 -0
  88. octostar/models/get_apps_url_response_500.py +82 -0
  89. octostar/models/get_attachment_response_200.py +74 -0
  90. octostar/models/get_attachment_response_401.py +74 -0
  91. octostar/models/get_files_tree_response_200.py +106 -0
  92. octostar/models/get_files_tree_response_200_status.py +8 -0
  93. octostar/models/get_files_tree_response_400.py +111 -0
  94. octostar/models/get_files_tree_response_400_data.py +60 -0
  95. octostar/models/get_files_tree_response_400_status.py +8 -0
  96. octostar/models/get_files_tree_response_401.py +74 -0
  97. octostar/models/get_files_tree_response_500.py +111 -0
  98. octostar/models/get_files_tree_response_500_data.py +60 -0
  99. octostar/models/get_files_tree_response_500_status.py +8 -0
  100. octostar/models/get_job_logs_response_401.py +74 -0
  101. octostar/models/get_job_logs_response_404.py +74 -0
  102. octostar/models/get_job_logs_response_500.py +82 -0
  103. octostar/models/get_job_progress_response_401.py +74 -0
  104. octostar/models/get_object_response_401.py +74 -0
  105. octostar/models/get_ontologies_response_401.py +74 -0
  106. octostar/models/get_ontologies_response_500.py +81 -0
  107. octostar/models/get_permissions_response_200.py +98 -0
  108. octostar/models/get_permissions_response_400.py +82 -0
  109. octostar/models/get_permissions_response_401.py +74 -0
  110. octostar/models/get_permissions_response_500.py +82 -0
  111. octostar/models/get_processing_status_response_200.py +104 -0
  112. octostar/models/get_processing_status_response_200_data.py +87 -0
  113. octostar/models/get_processing_status_response_400.py +82 -0
  114. octostar/models/get_processing_status_response_500.py +82 -0
  115. octostar/models/get_subscriptions_response_200_item.py +74 -0
  116. octostar/models/get_version_response_200.py +74 -0
  117. octostar/models/get_version_response_404.py +74 -0
  118. octostar/models/get_whoami_response_200.py +129 -0
  119. octostar/models/get_whoami_response_401.py +74 -0
  120. octostar/models/insert_entity.py +114 -0
  121. octostar/models/insert_entity_base.py +266 -0
  122. octostar/models/insert_entity_relationships_item.py +107 -0
  123. octostar/models/insert_entity_request.py +94 -0
  124. octostar/models/internal_server_error.py +82 -0
  125. octostar/models/job_execution_result.py +146 -0
  126. octostar/models/job_status.py +196 -0
  127. octostar/models/job_status_labels.py +60 -0
  128. octostar/models/job_with_url.py +82 -0
  129. octostar/models/kill_job_response_401.py +74 -0
  130. octostar/models/list_app_jobs_response_401.py +74 -0
  131. octostar/models/list_app_jobs_response_500.py +82 -0
  132. octostar/models/list_apps_response_401.py +74 -0
  133. octostar/models/list_apps_response_500.py +82 -0
  134. octostar/models/multi_query_json_body.py +100 -0
  135. octostar/models/multi_query_json_body_queries_item.py +80 -0
  136. octostar/models/multi_query_response_400.py +82 -0
  137. octostar/models/multi_query_response_401.py +74 -0
  138. octostar/models/not_found_error.py +74 -0
  139. octostar/models/octostar_event.py +96 -0
  140. octostar/models/octostar_event_octostar_payload.py +100 -0
  141. octostar/models/octostar_event_octostar_payload_level.py +11 -0
  142. octostar/models/os_notification.py +122 -0
  143. octostar/models/processing_status.py +262 -0
  144. octostar/models/processing_status_code.py +14 -0
  145. octostar/models/progress_request.py +73 -0
  146. octostar/models/publish_notification_response_401.py +74 -0
  147. octostar/models/pull_events_from_stream_response_401.py +74 -0
  148. octostar/models/push_event_to_stream_response_401.py +74 -0
  149. octostar/models/query_json_body.py +101 -0
  150. octostar/models/query_json_body_params.py +60 -0
  151. octostar/models/query_response_400.py +82 -0
  152. octostar/models/query_response_401.py +74 -0
  153. octostar/models/set_job_progress_response_401.py +74 -0
  154. octostar/models/string_to_value_label_map.py +99 -0
  155. octostar/models/string_to_value_label_map_data.py +89 -0
  156. octostar/models/string_to_value_label_map_data_additional_property.py +80 -0
  157. octostar/models/successful_get_tags.py +103 -0
  158. octostar/models/successful_insertion.py +98 -0
  159. octostar/models/tag_entities_response_401.py +74 -0
  160. octostar/models/toast_level.py +11 -0
  161. octostar/models/toast_response_401.py +74 -0
  162. octostar/models/undeploy_app_response_401.py +74 -0
  163. octostar/models/update_processing_status_response_200.py +82 -0
  164. octostar/models/update_processing_status_response_400.py +82 -0
  165. octostar/models/update_processing_status_response_500.py +82 -0
  166. octostar/models/upsert_entities_response_401.py +74 -0
  167. octostar/models/upsert_entity.py +114 -0
  168. octostar/models/upsert_entity_base.py +266 -0
  169. octostar/models/upsert_entity_relationships_item.py +107 -0
  170. octostar/py.typed +1 -0
  171. octostar/types.py +54 -0
  172. octostar/utils/__init__.py +15 -0
  173. octostar/utils/chat/__init__.py +0 -0
  174. octostar/utils/chat/chat.py +513 -0
  175. octostar/utils/chat/detokenize.py +105 -0
  176. octostar/utils/chat/get_default_model.py +50 -0
  177. octostar/utils/chat/list_models.py +91 -0
  178. octostar/utils/chat/tokenize.py +105 -0
  179. octostar/utils/commons.py +226 -0
  180. octostar/utils/exceptions.py +134 -0
  181. octostar/utils/jobs/__init__.py +0 -0
  182. octostar/utils/jobs/apps/__init__.py +0 -0
  183. octostar/utils/jobs/apps/deploy_app.py +81 -0
  184. octostar/utils/jobs/apps/execute_app_job.py +114 -0
  185. octostar/utils/jobs/apps/get_app_logs.py +113 -0
  186. octostar/utils/jobs/apps/get_app_secret.py +102 -0
  187. octostar/utils/jobs/apps/get_apps_url.py +73 -0
  188. octostar/utils/jobs/apps/list_app_jobs.py +62 -0
  189. octostar/utils/jobs/apps/list_apps.py +126 -0
  190. octostar/utils/jobs/apps/undeploy_app.py +48 -0
  191. octostar/utils/jobs/get_job_logs.py +113 -0
  192. octostar/utils/jobs/get_job_progress.py +76 -0
  193. octostar/utils/jobs/kill_job.py +47 -0
  194. octostar/utils/jobs/set_job_progress.py +67 -0
  195. octostar/utils/meta/__init__.py +0 -0
  196. octostar/utils/meta/get_version.py +30 -0
  197. octostar/utils/meta/get_whoami.py +30 -0
  198. octostar/utils/notifications/__init__.py +0 -0
  199. octostar/utils/notifications/delete_stream.py +58 -0
  200. octostar/utils/notifications/get_my_subscriptions.py +49 -0
  201. octostar/utils/notifications/publish_notification.py +73 -0
  202. octostar/utils/notifications/pull_event_from_stream.py +63 -0
  203. octostar/utils/notifications/pull_events_from_stream.py +64 -0
  204. octostar/utils/notifications/push_event_to_stream.py +109 -0
  205. octostar/utils/notifications/push_events_to_stream.py +137 -0
  206. octostar/utils/notifications/toast.py +92 -0
  207. octostar/utils/ontology/__init__.py +10 -0
  208. octostar/utils/ontology/fetch_ontology_data.py +141 -0
  209. octostar/utils/ontology/get_ontologies.py +55 -0
  210. octostar/utils/ontology/multiquery_ontology.py +287 -0
  211. octostar/utils/ontology/query_ontology.py +186 -0
  212. octostar/utils/pipeline/__init__.py +1 -0
  213. octostar/utils/pipeline/get_processing_status.py +230 -0
  214. octostar/utils/pipeline/update_processing_status.py +286 -0
  215. octostar/utils/search/__init__.py +11 -0
  216. octostar/utils/search/bulk_update.py +138 -0
  217. octostar/utils/search/count.py +117 -0
  218. octostar/utils/search/get_entity_annotations.py +304 -0
  219. octostar/utils/search/get_index_definition.py +111 -0
  220. octostar/utils/search/multi_search.py +129 -0
  221. octostar/utils/workspace/__init__.py +0 -0
  222. octostar/utils/workspace/delete_entities.py +247 -0
  223. octostar/utils/workspace/delete_entity.py +81 -0
  224. octostar/utils/workspace/delete_relationship.py +78 -0
  225. octostar/utils/workspace/delete_relationships.py +85 -0
  226. octostar/utils/workspace/delete_temporary_blob.py +85 -0
  227. octostar/utils/workspace/extract_entities.py +140 -0
  228. octostar/utils/workspace/get_filepath_from_item.py +85 -0
  229. octostar/utils/workspace/get_filepaths_from_items.py +100 -0
  230. octostar/utils/workspace/get_files_tree.py +102 -0
  231. octostar/utils/workspace/get_item_from_filepath.py +102 -0
  232. octostar/utils/workspace/get_items_from_filepaths.py +108 -0
  233. octostar/utils/workspace/linkcharts/__init__.py +0 -0
  234. octostar/utils/workspace/linkcharts/create_linkchart.py +241 -0
  235. octostar/utils/workspace/permissions/PermissionLevel.py +8 -0
  236. octostar/utils/workspace/permissions/__init__.py +1 -0
  237. octostar/utils/workspace/permissions/get_permissions.py +81 -0
  238. octostar/utils/workspace/read_attachment.py +284 -0
  239. octostar/utils/workspace/read_file.py +113 -0
  240. octostar/utils/workspace/read_temporary_blob.py +428 -0
  241. octostar/utils/workspace/saved_searches/__init__.py +0 -0
  242. octostar/utils/workspace/saved_searches/create_saved_search.py +183 -0
  243. octostar/utils/workspace/tags/__init__.py +0 -0
  244. octostar/utils/workspace/tags/delete_tag_from_entities.py +96 -0
  245. octostar/utils/workspace/tags/tag_entities.py +175 -0
  246. octostar/utils/workspace/upsert_entities.py +268 -0
  247. octostar/utils/workspace/upsert_entity.py +110 -0
  248. octostar/utils/workspace/upsert_relationship.py +128 -0
  249. octostar/utils/workspace/upsert_relationships.py +194 -0
  250. octostar/utils/workspace/write_attachment.py +263 -0
  251. octostar/utils/workspace/write_file.py +335 -0
  252. octostar/utils/workspace/write_temporary_blob.py +218 -0
  253. octostar_python_client-0.1.759.dist-info/METADATA +159 -0
  254. octostar_python_client-0.1.759.dist-info/RECORD +257 -0
  255. octostar_python_client-0.1.759.dist-info/WHEEL +5 -0
  256. octostar_python_client-0.1.759.dist-info/licenses/LICENSE +21 -0
  257. 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