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,247 @@
1
+ import asyncio as _asyncio
2
+ import logging
3
+ from concurrent.futures import ThreadPoolExecutor, as_completed
4
+ from typing import Dict, List
5
+ from urllib.parse import quote
6
+
7
+ import httpx
8
+
9
+ _logger = logging.getLogger(__name__)
10
+
11
+ from ...api.workspace_data import delete_entities
12
+ from ..ontology import query_ontology
13
+ from ...client import Client
14
+ from ..exceptions import ApiConnectionError
15
+
16
+
17
+ def _files_delete_url(client: Client, os_workspace: str, os_entity_uid: str) -> str:
18
+ base = client.get_base_url_v1()
19
+ return f"{base}/api/v1/files/delete-file/{quote(os_workspace, safe='')}/{quote(os_entity_uid, safe='')}"
20
+
21
+
22
+ def _query_survivors_sync(os_entity_uids: List[str], client: Client) -> Dict[str, str]:
23
+ """Return {entity_uid: os_workspace} for every UID that still exists."""
24
+ uids_text = ", ".join(f"'{uid}'" for uid in os_entity_uids)
25
+ rows = (
26
+ query_ontology.sync(
27
+ f"SELECT `os_entity_uid`, `os_workspace` FROM `timbr`.`os_workspace_item` WHERE `os_entity_uid` IN ({uids_text})",
28
+ client=client,
29
+ )
30
+ or []
31
+ )
32
+ return {
33
+ row["os_entity_uid"]: row["os_workspace"]
34
+ for row in rows
35
+ if row.get("os_entity_uid") and row.get("os_workspace")
36
+ }
37
+
38
+
39
+ async def _query_survivors_async(
40
+ os_entity_uids: List[str], client: Client
41
+ ) -> Dict[str, str]:
42
+ """Return {entity_uid: os_workspace} for every UID that still exists."""
43
+ uids_text = ", ".join(f"'{uid}'" for uid in os_entity_uids)
44
+ rows = (
45
+ await query_ontology.asyncio(
46
+ f"SELECT `os_entity_uid`, `os_workspace` FROM `timbr`.`os_workspace_item` WHERE `os_entity_uid` IN ({uids_text})",
47
+ client=client,
48
+ )
49
+ or []
50
+ )
51
+ return {
52
+ row["os_entity_uid"]: row["os_workspace"]
53
+ for row in rows
54
+ if row.get("os_entity_uid") and row.get("os_workspace")
55
+ }
56
+
57
+
58
+ def _files_delete_one_sync(
59
+ os_workspace: str, os_entity_uid: str, client: Client
60
+ ) -> bool:
61
+ """DELETE /api/v1/files/delete-file/{os_workspace}/{entity_uid}. Returns True on 204, False on 404."""
62
+ url = _files_delete_url(client, os_workspace, os_entity_uid)
63
+ with httpx.Client(verify=client.verify_ssl) as httpx_client:
64
+ resp = httpx_client.delete(
65
+ url,
66
+ headers=client.get_headers(),
67
+ timeout=client.get_timeout(),
68
+ follow_redirects=client.follow_redirects,
69
+ )
70
+ if resp.status_code == 204:
71
+ return True
72
+ if resp.status_code == 404:
73
+ return False
74
+ raise ApiConnectionError("delete_entities (files fallback)", resp, client)
75
+
76
+
77
+ async def _files_delete_one_async(
78
+ os_workspace: str, os_entity_uid: str, client: Client
79
+ ) -> bool:
80
+ """DELETE /api/v1/files/delete-file/{os_workspace}/{entity_uid}. Returns True on 204, False on 404."""
81
+ url = _files_delete_url(client, os_workspace, os_entity_uid)
82
+ async with httpx.AsyncClient(verify=client.verify_ssl) as httpx_client:
83
+ resp = await httpx_client.delete(
84
+ url,
85
+ headers=client.get_headers(),
86
+ timeout=client.get_timeout(),
87
+ follow_redirects=client.follow_redirects,
88
+ )
89
+ if resp.status_code == 204:
90
+ return True
91
+ if resp.status_code == 404:
92
+ return False
93
+ raise ApiConnectionError("delete_entities (files fallback)", resp, client)
94
+
95
+
96
+ def sync(
97
+ os_entity_uids: List[str],
98
+ safe: bool = False,
99
+ raise_on_missing: bool = False,
100
+ client: Client = None,
101
+ ):
102
+ """
103
+ # Delete a list of local entities given their IDs
104
+
105
+ ## Arguments
106
+ - `os_entity_uids`: The list of IDs
107
+ - `safe`: Whether to raise a ValueError before removal if some entities in the list do not exist
108
+ - `raise_on_missing`: Whether to raise a ConnectionError if some of the entities could not be deleted
109
+ - `client`: The Client with which to connect to Octostar. If None, the default one is used
110
+
111
+ ## Returns
112
+ The number of successfully deleted entities
113
+
114
+ ## Raises
115
+ - `ValueError`: If the list of IDs contain invalid entries (and safe is enabled)
116
+ - `ApiConnectionError`: If the request was unsuccessful on the server
117
+ - `ConnectionError`: If some of the entities could not be removed (and raise_on_missing is enabled)
118
+ """
119
+ assert len(os_entity_uids) > 0
120
+ if safe:
121
+ uids_text = ", ".join(f"'{uid}'" for uid in os_entity_uids)
122
+ uids = query_ontology.sync(
123
+ f"SELECT `os_entity_uid` FROM `timbr`.`os_thing` WHERE `os_entity_uid` IN ({uids_text})",
124
+ client=client,
125
+ )
126
+ if len(uids or []) < len(os_entity_uids):
127
+ raise ValueError("Attempting to remove an entity which does not exist!")
128
+
129
+ response = delete_entities.sync_detailed(json_body=os_entity_uids, client=client)
130
+ if response.status_code != 200:
131
+ raise ApiConnectionError("delete_entities", response, client)
132
+ deleted = response.parsed.additional_properties.get("deleted_count", 0)
133
+
134
+ if deleted >= len(os_entity_uids):
135
+ return deleted
136
+
137
+ # v1/entities/delete silently ignores certain entity types. Query for any survivors and fall back to the
138
+ # v1/files/delete-file endpoint in parallel, which handles the remaining entity types.
139
+ survivors = _query_survivors_sync(os_entity_uids, client)
140
+ if not survivors:
141
+ total = deleted
142
+ if total < len(os_entity_uids):
143
+ _logger.warning("Deleted only %d/%d entities", total, len(os_entity_uids))
144
+ if raise_on_missing:
145
+ raise ConnectionError(
146
+ "Failed to delete some entities! (likely they did not exist prior to this call)"
147
+ )
148
+ return total
149
+
150
+ files_deleted = 0
151
+ max_workers = min(len(survivors), 10)
152
+ with ThreadPoolExecutor(max_workers=max_workers) as executor:
153
+ futures = {
154
+ executor.submit(_files_delete_one_sync, ws, uid, client): uid
155
+ for uid, ws in survivors.items()
156
+ }
157
+ for future in as_completed(futures):
158
+ uid = futures[future]
159
+ try:
160
+ if future.result():
161
+ files_deleted += 1
162
+ except Exception as e:
163
+ _logger.error("files fallback delete failed for %s: %s", uid, e)
164
+
165
+ total = deleted + files_deleted
166
+ if total < len(os_entity_uids):
167
+ _logger.warning("Deleted only %d/%d entities", total, len(os_entity_uids))
168
+ if raise_on_missing:
169
+ raise ConnectionError(
170
+ "Failed to delete some entities! (likely they did not exist prior to this call)"
171
+ )
172
+ return total
173
+
174
+
175
+ async def asyncio(
176
+ os_entity_uids: List[str],
177
+ safe: bool = False,
178
+ raise_on_missing: bool = False,
179
+ client: Client = None,
180
+ ):
181
+ """
182
+ # Delete asynchronously a list of local entities given their IDs
183
+
184
+ ## Arguments
185
+ (Same as sync function)
186
+
187
+ ## Returns
188
+ The number of successfully deleted entities
189
+
190
+ ## Raises
191
+ - `ValueError`: If the list of IDs contain invalid entries (and safe is enabled)
192
+ - `ApiConnectionError`: If the request was unsuccessful on the server
193
+ - `ConnectionError`: If some of the entities could not be removed (and raise_on_missing is enabled)
194
+ """
195
+ assert len(os_entity_uids) > 0
196
+ if safe:
197
+ uids_text = ", ".join(f"'{uid}'" for uid in os_entity_uids)
198
+ uids = await query_ontology.asyncio(
199
+ f"SELECT `os_entity_uid` FROM `timbr`.`os_thing` WHERE `os_entity_uid` IN ({uids_text})",
200
+ client=client,
201
+ )
202
+ if len(uids or []) < len(os_entity_uids):
203
+ raise ValueError("Attempting to remove an entity which does not exist!")
204
+
205
+ response = await delete_entities.asyncio_detailed(
206
+ json_body=os_entity_uids, client=client
207
+ )
208
+ if response.status_code != 200:
209
+ raise ApiConnectionError("delete_entities", response, client)
210
+ deleted = response.parsed.additional_properties.get("deleted_count", 0)
211
+
212
+ if deleted >= len(os_entity_uids):
213
+ return deleted
214
+
215
+ # v1/entities/delete silently ignores certain entity types. Query for any survivors and fall back to the
216
+ # v1/files/delete-file endpoint in parallel, which handles the remaining entity types.
217
+ survivors = await _query_survivors_async(os_entity_uids, client)
218
+ if not survivors:
219
+ total = deleted
220
+ if total < len(os_entity_uids):
221
+ _logger.warning("Deleted only %d/%d entities", total, len(os_entity_uids))
222
+ if raise_on_missing:
223
+ raise ConnectionError(
224
+ "Failed to delete some entities! (likely they did not exist prior to this call)"
225
+ )
226
+ return total
227
+
228
+ results = await _asyncio.gather(
229
+ *[_files_delete_one_async(ws, uid, client) for uid, ws in survivors.items()],
230
+ return_exceptions=True,
231
+ )
232
+
233
+ files_deleted = 0
234
+ for uid, result in zip(survivors.keys(), results):
235
+ if isinstance(result, Exception):
236
+ _logger.error("files fallback delete failed for %s: %s", uid, result)
237
+ elif result:
238
+ files_deleted += 1
239
+
240
+ total = deleted + files_deleted
241
+ if total < len(os_entity_uids):
242
+ _logger.warning("Deleted only %d/%d entities", total, len(os_entity_uids))
243
+ if raise_on_missing:
244
+ raise ConnectionError(
245
+ "Failed to delete some entities! (likely they did not exist prior to this call)"
246
+ )
247
+ return total
@@ -0,0 +1,81 @@
1
+ import logging
2
+
3
+ _logger = logging.getLogger(__name__)
4
+
5
+ from ..ontology import query_ontology
6
+ from ...client import Client
7
+ from . import delete_entities as _delete_entities
8
+
9
+
10
+ def sync(
11
+ os_entity_uid: str,
12
+ safe: bool = False,
13
+ raise_on_missing: bool = False,
14
+ client: Client = None,
15
+ ):
16
+ """
17
+ # Delete a local entity given its ID
18
+
19
+ ## Arguments
20
+ - `os_entity_uid`: The ID of the entity to delete
21
+ - `safe`: Whether to raise a ValueError before removal if the entity does not exist
22
+ - `raise_on_missing`: Whether to raise a ConnectionError if the entity could not be deleted
23
+ - `client`: The Client with which to connect to Octostar. If None, the default one is used
24
+
25
+ ## Returns
26
+ True if the entity was successfully deleted, False if no entity was deleted
27
+
28
+ ## Raises
29
+ - `ValueError`: If the ID is not a valid entity ID (and safe is enabled)
30
+ - `ApiConnectionError`: If the request was unsuccessful on the server
31
+ - `ConnectionError`: If the entity could not be removed (and raise_on_missing is enabled)
32
+ """
33
+ if safe:
34
+ uids = query_ontology.sync(
35
+ f"SELECT `os_entity_uid` FROM `timbr`.`os_thing` WHERE `os_entity_uid`='{os_entity_uid}'",
36
+ client=client,
37
+ )
38
+ if not uids:
39
+ raise ValueError("Attempting to remove an entity which does not exist!")
40
+
41
+ deleted = _delete_entities.sync(
42
+ [os_entity_uid], raise_on_missing=raise_on_missing, client=client
43
+ )
44
+ return deleted >= 1
45
+
46
+
47
+ async def asyncio(
48
+ os_entity_uid: str,
49
+ safe: bool = False,
50
+ raise_on_missing: bool = False,
51
+ client: Client = None,
52
+ ):
53
+ """
54
+ # Delete asynchronously a local entity given its ID
55
+
56
+ ## Arguments
57
+ - `os_entity_uid`: The ID of the entity to delete
58
+ - `safe`: Whether to raise a ValueError before removal if the entity does not exist
59
+ - `raise_on_missing`: Whether to raise a ConnectionError if the entity could not be deleted
60
+ - `client`: The Client with which to connect to Octostar. If None, the default one is used
61
+
62
+ ## Returns
63
+ True if the entity was successfully deleted, False if no entity was deleted
64
+
65
+ ## Raises
66
+ - `ValueError`: If the ID is not a valid entity ID (and safe is enabled)
67
+ - `ApiConnectionError`: If the request was unsuccessful on the server
68
+ - `ConnectionError`: If the entity could not be removed (and raise_on_missing is enabled)
69
+ """
70
+ if safe:
71
+ uids = await query_ontology.asyncio(
72
+ f"SELECT `os_entity_uid` FROM `timbr`.`os_thing` WHERE `os_entity_uid`='{os_entity_uid}'",
73
+ client=client,
74
+ )
75
+ if not uids:
76
+ raise ValueError("Attempting to remove an entity which does not exist!")
77
+
78
+ deleted = await _delete_entities.asyncio(
79
+ [os_entity_uid], raise_on_missing=raise_on_missing, client=client
80
+ )
81
+ return deleted >= 1
@@ -0,0 +1,78 @@
1
+ import logging
2
+
3
+ _logger = logging.getLogger(__name__)
4
+
5
+ from ..ontology import query_ontology
6
+ from ...client import Client
7
+ from . import delete_entities as _delete_entities
8
+
9
+
10
+ def sync(
11
+ os_relationship_uid: str,
12
+ safe: bool = False,
13
+ raise_on_missing: bool = False,
14
+ client: Client = None,
15
+ ):
16
+ """
17
+ # Delete a local relationship between two entities given its ID
18
+
19
+ ## Arguments
20
+ - `os_relationship_uid`: The ID of the relationship to delete
21
+ - `safe`: Whether to raise a ValueError before removal if the relationship does not exist
22
+ - `raise_on_missing`: Whether to raise a ConnectionError if the relationship could not be deleted
23
+ - `client`: The Client with which to connect to Octostar. If None, the default one is used
24
+
25
+ ## Returns
26
+ True if the relationship was successfully deleted, False if no relationship was deleted
27
+
28
+ ## Raises
29
+ - `ValueError`: If the ID is not a valid relationship ID (and safe is enabled)
30
+ - `ApiConnectionError`: If the request was unsuccessful on the server
31
+ - `ConnectionError`: If the relationship could not be removed (and raise_on_missing is enabled)
32
+ """
33
+ if safe:
34
+ uids = query_ontology.sync(
35
+ f"SELECT `os_entity_uid` FROM `timbr`.`os_relationship` WHERE `os_entity_uid`='{os_relationship_uid}'",
36
+ client=client,
37
+ )
38
+ if not uids:
39
+ raise ValueError("Attempting to remove an entity which does not exist!")
40
+
41
+ deleted = _delete_entities.sync(
42
+ [os_relationship_uid], raise_on_missing=raise_on_missing, client=client
43
+ )
44
+ return deleted >= 1
45
+
46
+
47
+ async def asyncio(
48
+ os_relationship_uid: str,
49
+ safe: bool = False,
50
+ raise_on_missing: bool = False,
51
+ client: Client = None,
52
+ ):
53
+ """
54
+ # Delete asynchronously a local relationship between two entities given its ID
55
+
56
+ ## Arguments
57
+ (Same as sync function)
58
+
59
+ ## Returns
60
+ True if the relationship was successfully deleted, False if no relationship was deleted
61
+
62
+ ## Raises
63
+ - `ValueError`: If the ID is not a valid relationship ID (and safe is enabled)
64
+ - `ApiConnectionError`: If the request was unsuccessful on the server
65
+ - `ConnectionError`: If the relationship could not be removed (and raise_on_missing is enabled)
66
+ """
67
+ if safe:
68
+ uids = await query_ontology.asyncio(
69
+ f"SELECT `os_entity_uid` FROM `timbr`.`os_relationship` WHERE `os_entity_uid`='{os_relationship_uid}'",
70
+ client=client,
71
+ )
72
+ if not uids:
73
+ raise ValueError("Attempting to remove an entity which does not exist!")
74
+
75
+ deleted = await _delete_entities.asyncio(
76
+ [os_relationship_uid], raise_on_missing=raise_on_missing, client=client
77
+ )
78
+ return deleted >= 1
@@ -0,0 +1,85 @@
1
+ import logging
2
+ from typing import List
3
+
4
+ _logger = logging.getLogger(__name__)
5
+
6
+ from ..ontology import query_ontology
7
+ from ...client import Client
8
+ from . import delete_entities as _delete_entities
9
+
10
+
11
+ def sync(
12
+ os_relationship_uids: List[str],
13
+ safe: bool = False,
14
+ raise_on_missing: bool = False,
15
+ client: Client = None,
16
+ ):
17
+ """
18
+ # Delete a list of local relationships given their IDs
19
+
20
+ ## Arguments
21
+ - `os_relationships_uids`: The list of IDs
22
+ - `safe`: Whether to raise a ValueError before removal if some relationships in the list do not exist
23
+ - `raise_on_missing`: Whether to raise a ConnectionError if some of the relationships could not be deleted
24
+ - `client`: The Client with which to connect to Octostar. If None, the default one is used
25
+
26
+ ## Returns
27
+ The number of successfully deleted relationships
28
+
29
+ ## Raises
30
+ - `ValueError`: If the list of IDs contain invalid entries (and safe is enabled)
31
+ - `ApiConnectionError`: If the request was unsuccessful on the server
32
+ - `ConnectionError`: If some of the relationships could not be removed (and raise_on_missing is enabled)
33
+ """
34
+ assert len(os_relationship_uids) > 0
35
+ if safe:
36
+ uids_text = ", ".join(f"'{uid}'" for uid in os_relationship_uids)
37
+ uids = query_ontology.sync(
38
+ f"SELECT `os_entity_uid` FROM `timbr`.`os_relationship` WHERE `os_entity_uid` IN ({uids_text})",
39
+ client=client,
40
+ )
41
+ if len(uids or []) < len(os_relationship_uids):
42
+ raise ValueError(
43
+ "Attempting to remove a relationship which does not exist!"
44
+ )
45
+
46
+ return _delete_entities.sync(
47
+ os_relationship_uids, raise_on_missing=raise_on_missing, client=client
48
+ )
49
+
50
+
51
+ async def asyncio(
52
+ os_relationship_uids: List[str],
53
+ safe: bool = False,
54
+ raise_on_missing: bool = False,
55
+ client: Client = None,
56
+ ):
57
+ """
58
+ # Delete asynchronously a list of local relationships given their IDs
59
+
60
+ ## Arguments
61
+ (Same as sync function)
62
+
63
+ ## Returns
64
+ The number of successfully deleted relationships
65
+
66
+ ## Raises
67
+ - `ValueError`: If the list of IDs contain invalid entries (and safe is enabled)
68
+ - `ApiConnectionError`: If the request was unsuccessful on the server
69
+ - `ConnectionError`: If some of the relationships could not be removed (and raise_on_missing is enabled)
70
+ """
71
+ assert len(os_relationship_uids) > 0
72
+ if safe:
73
+ uids_text = ", ".join(f"'{uid}'" for uid in os_relationship_uids)
74
+ uids = await query_ontology.asyncio(
75
+ f"SELECT `os_entity_uid` FROM `timbr`.`os_relationship` WHERE `os_entity_uid` IN ({uids_text})",
76
+ client=client,
77
+ )
78
+ if len(uids or []) < len(os_relationship_uids):
79
+ raise ValueError(
80
+ "Attempting to remove a relationship which does not exist!"
81
+ )
82
+
83
+ return await _delete_entities.asyncio(
84
+ os_relationship_uids, raise_on_missing=raise_on_missing, client=client
85
+ )
@@ -0,0 +1,85 @@
1
+ import logging
2
+ import httpx
3
+
4
+ _logger = logging.getLogger(__name__)
5
+
6
+ from ...client import Client, get_default_client
7
+ from ..commons import network_retry_strategy
8
+ from ..exceptions import ApiConnectionError
9
+
10
+
11
+ DEFAULT_TIMEOUT = 120
12
+
13
+
14
+ def _delete_api_url(client: Client, filename: str) -> str:
15
+ """Build the blob delete API endpoint URL."""
16
+ base = client.get_base_url_v1()
17
+ return f"{base}/api/v1/files/delete-blob/{filename}"
18
+
19
+
20
+ def sync(
21
+ filename: str,
22
+ client: Client = None,
23
+ ):
24
+ """
25
+ # Delete a temporary blob from the user's temp bucket
26
+
27
+ Permanently removes a file from the authenticated user's temporary S3 bucket.
28
+ Use this to clean up temporary files that are no longer needed.
29
+
30
+ ## Arguments
31
+ - `filename`: The name of the file in the temp bucket to delete
32
+ - `client`: The Client with which to connect to Octostar. If None, the default one is used
33
+
34
+ ## Raises
35
+ - `ApiConnectionError`: If the deletion request failed
36
+ """
37
+ if not client:
38
+ client = get_default_client()
39
+
40
+ api_url = _delete_api_url(client, filename)
41
+ headers = dict(client.get_headers())
42
+
43
+ response = None
44
+ try:
45
+ for attempt in network_retry_strategy():
46
+ with attempt:
47
+ with httpx.Client(timeout=DEFAULT_TIMEOUT) as http_client:
48
+ response = http_client.delete(api_url, headers=headers)
49
+ response.raise_for_status()
50
+ except Exception:
51
+ raise ApiConnectionError("delete_temporary_blob", response, client)
52
+
53
+
54
+ async def asyncio(
55
+ filename: str,
56
+ client: Client = None,
57
+ ):
58
+ """
59
+ # Delete a temporary blob from the user's temp bucket (async)
60
+
61
+ Permanently removes a file from the authenticated user's temporary S3 bucket.
62
+ Use this to clean up temporary files that are no longer needed.
63
+
64
+ ## Arguments
65
+ - `filename`: The name of the file in the temp bucket to delete
66
+ - `client`: The Client with which to connect to Octostar. If None, the default one is used
67
+
68
+ ## Raises
69
+ - `ApiConnectionError`: If the deletion request failed
70
+ """
71
+ if not client:
72
+ client = get_default_client()
73
+
74
+ api_url = _delete_api_url(client, filename)
75
+ headers = dict(client.get_headers())
76
+
77
+ response = None
78
+ try:
79
+ for attempt in network_retry_strategy():
80
+ with attempt:
81
+ async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT) as http_client:
82
+ response = await http_client.delete(api_url, headers=headers)
83
+ response.raise_for_status()
84
+ except Exception:
85
+ raise ApiConnectionError("delete_temporary_blob", response, client)