acceldata-sdk-python 26.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. acceldata/__init__.py +7 -0
  2. acceldata/client/__init__.py +0 -0
  3. acceldata/client/adoc_client.py +666 -0
  4. acceldata/client/http_client.py +346 -0
  5. acceldata/client/transient_retry.py +142 -0
  6. acceldata/constants/__init__.py +1 -0
  7. acceldata/constants/constants.py +13 -0
  8. acceldata/exceptions/__init__.py +52 -0
  9. acceldata/exceptions/api_errors.py +85 -0
  10. acceldata/exceptions/exceptions.py +174 -0
  11. acceldata/exceptions/sdk_exceptions.py +98 -0
  12. acceldata/mappers/__init__.py +21 -0
  13. acceldata/mappers/catalog_executions.py +107 -0
  14. acceldata/models/__init__.py +0 -0
  15. acceldata/models/api/catalog/above_configs.py +99 -0
  16. acceldata/models/api/catalog/above_configs_success.py +138 -0
  17. acceldata/models/api/catalog/absolute_configs.py +197 -0
  18. acceldata/models/api/catalog/absolute_configs_fallback.py +101 -0
  19. acceldata/models/api/catalog/absolute_threshold_config.py +105 -0
  20. acceldata/models/api/catalog/analysis_job_context.py +102 -0
  21. acceldata/models/api/catalog/analytics_pipeline.py +385 -0
  22. acceldata/models/api/catalog/analytics_pipeline_endpoint.py +136 -0
  23. acceldata/models/api/catalog/anomaly_config.py +95 -0
  24. acceldata/models/api/catalog/anomaly_details.py +119 -0
  25. acceldata/models/api/catalog/anomaly_threshold_config.py +105 -0
  26. acceldata/models/api/catalog/artifact.py +92 -0
  27. acceldata/models/api/catalog/assembly.py +171 -0
  28. acceldata/models/api/catalog/asset.py +162 -0
  29. acceldata/models/api/catalog/asset_catalog_listing.py +159 -0
  30. acceldata/models/api/catalog/asset_catalog_listing_response.py +102 -0
  31. acceldata/models/api/catalog/asset_label_request.py +96 -0
  32. acceldata/models/api/catalog/asset_progress.py +96 -0
  33. acceldata/models/api/catalog/asset_progress_details.py +117 -0
  34. acceldata/models/api/catalog/asset_tag.py +124 -0
  35. acceldata/models/api/catalog/asset_tag_info.py +140 -0
  36. acceldata/models/api/catalog/asset_tag_request.py +95 -0
  37. acceldata/models/api/catalog/asset_tag_response.py +96 -0
  38. acceldata/models/api/catalog/asset_tags_response.py +102 -0
  39. acceldata/models/api/catalog/asset_type.py +96 -0
  40. acceldata/models/api/catalog/auto_anomaly_feature_analysis.py +160 -0
  41. acceldata/models/api/catalog/auto_anomaly_item_execution.py +133 -0
  42. acceldata/models/api/catalog/auto_anomaly_meta_data.py +162 -0
  43. acceldata/models/api/catalog/auto_anomaly_rule_execution.py +102 -0
  44. acceldata/models/api/catalog/auto_anomaly_summary.py +124 -0
  45. acceldata/models/api/catalog/backing_asset.py +126 -0
  46. acceldata/models/api/catalog/below_configs.py +99 -0
  47. acceldata/models/api/catalog/big_decimal.py +100 -0
  48. acceldata/models/api/catalog/big_integer.py +98 -0
  49. acceldata/models/api/catalog/bounds_date_time_marker_config.py +110 -0
  50. acceldata/models/api/catalog/bounds_file_event_marker_config.py +108 -0
  51. acceldata/models/api/catalog/bounds_id_marker_config.py +96 -0
  52. acceldata/models/api/catalog/catalog_asset_meta_data.py +128 -0
  53. acceldata/models/api/catalog/changes_by_config.py +105 -0
  54. acceldata/models/api/catalog/column_mapping.py +139 -0
  55. acceldata/models/api/catalog/column_metadata.py +90 -0
  56. acceldata/models/api/catalog/column_metric_with_anomaly_details.py +119 -0
  57. acceldata/models/api/catalog/column_variable.py +111 -0
  58. acceldata/models/api/catalog/composite_policy_execution.py +102 -0
  59. acceldata/models/api/catalog/composite_policy_item_execution.py +104 -0
  60. acceldata/models/api/catalog/connection.py +118 -0
  61. acceldata/models/api/catalog/connection_test_result.py +106 -0
  62. acceldata/models/api/catalog/connection_type.py +90 -0
  63. acceldata/models/api/catalog/connection_types_response.py +96 -0
  64. acceldata/models/api/catalog/crawler.py +88 -0
  65. acceldata/models/api/catalog/crawler_action_response.py +90 -0
  66. acceldata/models/api/catalog/crawler_execution.py +147 -0
  67. acceldata/models/api/catalog/crawler_execution_response.py +102 -0
  68. acceldata/models/api/catalog/crawler_status_response.py +90 -0
  69. acceldata/models/api/catalog/create_profile.py +194 -0
  70. acceldata/models/api/catalog/custom_sql_config.py +121 -0
  71. acceldata/models/api/catalog/data_bricks_spark_resource_config.py +104 -0
  72. acceldata/models/api/catalog/data_cadence_rule.py +236 -0
  73. acceldata/models/api/catalog/data_cadence_rule_details.py +125 -0
  74. acceldata/models/api/catalog/data_cadence_rule_execution.py +102 -0
  75. acceldata/models/api/catalog/data_cadence_rule_item.py +104 -0
  76. acceldata/models/api/catalog/data_cadence_rule_item_execution.py +158 -0
  77. acceldata/models/api/catalog/data_cadence_rule_response.py +98 -0
  78. acceldata/models/api/catalog/data_drift_execution.py +102 -0
  79. acceldata/models/api/catalog/data_drift_item_execution.py +121 -0
  80. acceldata/models/api/catalog/data_quality_engine.py +90 -0
  81. acceldata/models/api/catalog/data_quality_execution.py +106 -0
  82. acceldata/models/api/catalog/data_quality_rule.py +323 -0
  83. acceldata/models/api/catalog/data_quality_rule_details.py +186 -0
  84. acceldata/models/api/catalog/data_quality_rule_response.py +120 -0
  85. acceldata/models/api/catalog/data_quality_rules_response.py +102 -0
  86. acceldata/models/api/catalog/databricks_compute_config.py +113 -0
  87. acceldata/models/api/catalog/dataplane_engine.py +105 -0
  88. acceldata/models/api/catalog/dataplane_health_metrics.py +101 -0
  89. acceldata/models/api/catalog/dataplane_job.py +216 -0
  90. acceldata/models/api/catalog/dataplane_job_status.py +113 -0
  91. acceldata/models/api/catalog/dataplane_request.py +96 -0
  92. acceldata/models/api/catalog/dataproc_compute_config.py +106 -0
  93. acceldata/models/api/catalog/dataproc_spark_resource_config.py +104 -0
  94. acceldata/models/api/catalog/date_based_partition_marker_config.py +116 -0
  95. acceldata/models/api/catalog/date_partitioning_marker_config.py +113 -0
  96. acceldata/models/api/catalog/date_time_marker_config.py +109 -0
  97. acceldata/models/api/catalog/day_month_year_based_partition_marker_config.py +124 -0
  98. acceldata/models/api/catalog/decreased_by_config.py +105 -0
  99. acceldata/models/api/catalog/delete_artifact_response.py +88 -0
  100. acceldata/models/api/catalog/dq_rule_execution.py +248 -0
  101. acceldata/models/api/catalog/drift.py +121 -0
  102. acceldata/models/api/catalog/enable_rule_request.py +88 -0
  103. acceldata/models/api/catalog/engine.py +90 -0
  104. acceldata/models/api/catalog/execution_cancellation_response.py +92 -0
  105. acceldata/models/api/catalog/execution_response.py +144 -0
  106. acceldata/models/api/catalog/execution_result.py +126 -0
  107. acceldata/models/api/catalog/executions_response.py +102 -0
  108. acceldata/models/api/catalog/failed_asset_detail.py +90 -0
  109. acceldata/models/api/catalog/failed_summary.py +98 -0
  110. acceldata/models/api/catalog/file.py +94 -0
  111. acceldata/models/api/catalog/file_marker_config.py +99 -0
  112. acceldata/models/api/catalog/generic_config_fallback.py +101 -0
  113. acceldata/models/api/catalog/generic_execution.py +221 -0
  114. acceldata/models/api/catalog/generic_rule_execution.py +137 -0
  115. acceldata/models/api/catalog/global_storage_config_dto.py +172 -0
  116. acceldata/models/api/catalog/hosted_dp_deployment_response.py +98 -0
  117. acceldata/models/api/catalog/id_marker_config.py +94 -0
  118. acceldata/models/api/catalog/increased_by_config.py +105 -0
  119. acceldata/models/api/catalog/item.py +160 -0
  120. acceldata/models/api/catalog/item_execution.py +192 -0
  121. acceldata/models/api/catalog/item_segment.py +131 -0
  122. acceldata/models/api/catalog/job_schedule.py +118 -0
  123. acceldata/models/api/catalog/job_spec.py +96 -0
  124. acceldata/models/api/catalog/kubernetes_metrics.py +91 -0
  125. acceldata/models/api/catalog/label.py +97 -0
  126. acceldata/models/api/catalog/livy_compute_config.py +103 -0
  127. acceldata/models/api/catalog/livy_spark_resource_config.py +106 -0
  128. acceldata/models/api/catalog/look_back_config.py +90 -0
  129. acceldata/models/api/catalog/manual_tag_request.py +92 -0
  130. acceldata/models/api/catalog/mapping.py +97 -0
  131. acceldata/models/api/catalog/marker.py +88 -0
  132. acceldata/models/api/catalog/marker_config.py +349 -0
  133. acceldata/models/api/catalog/marker_config_fallback.py +101 -0
  134. acceldata/models/api/catalog/meta.py +92 -0
  135. acceldata/models/api/catalog/meta_data.py +92 -0
  136. acceldata/models/api/catalog/meta_data_item.py +94 -0
  137. acceldata/models/api/catalog/mini_profile_request.py +112 -0
  138. acceldata/models/api/catalog/notification_payload.py +114 -0
  139. acceldata/models/api/catalog/offset_based_marker_config.py +97 -0
  140. acceldata/models/api/catalog/operational_config.py +92 -0
  141. acceldata/models/api/catalog/pattern_configuration.py +90 -0
  142. acceldata/models/api/catalog/pipe_line_request.py +92 -0
  143. acceldata/models/api/catalog/pipeline_compute_config.py +110 -0
  144. acceldata/models/api/catalog/policy_execution_marker_config.py +94 -0
  145. acceldata/models/api/catalog/policy_execution_request.py +229 -0
  146. acceldata/models/api/catalog/policy_group.py +114 -0
  147. acceldata/models/api/catalog/policy_transform_udf.py +113 -0
  148. acceldata/models/api/catalog/process_metrics.py +91 -0
  149. acceldata/models/api/catalog/profile_anomaly_details_response.py +109 -0
  150. acceldata/models/api/catalog/profile_anomaly_item_execution.py +127 -0
  151. acceldata/models/api/catalog/profile_anomaly_rule_execution.py +102 -0
  152. acceldata/models/api/catalog/profile_anomaly_rule_item.py +109 -0
  153. acceldata/models/api/catalog/profile_cancellation_response.py +92 -0
  154. acceldata/models/api/catalog/profile_request.py +211 -0
  155. acceldata/models/api/catalog/profile_request_response.py +92 -0
  156. acceldata/models/api/catalog/property_template.py +178 -0
  157. acceldata/models/api/catalog/property_templates.py +123 -0
  158. acceldata/models/api/catalog/pub_sub_lookback_marker_config.py +96 -0
  159. acceldata/models/api/catalog/pub_sub_timestamp_marker_config.py +108 -0
  160. acceldata/models/api/catalog/quality_rule.py +381 -0
  161. acceldata/models/api/catalog/quality_rule_execution_metrics.py +114 -0
  162. acceldata/models/api/catalog/quality_rule_with_latest_execution.py +115 -0
  163. acceldata/models/api/catalog/range_configs.py +109 -0
  164. acceldata/models/api/catalog/reconciliation_item.py +102 -0
  165. acceldata/models/api/catalog/reconciliation_item_execution.py +157 -0
  166. acceldata/models/api/catalog/reconciliation_rule.py +339 -0
  167. acceldata/models/api/catalog/reconciliation_rule_details.py +225 -0
  168. acceldata/models/api/catalog/reconciliation_rule_execution.py +102 -0
  169. acceldata/models/api/catalog/reconciliation_rule_response.py +98 -0
  170. acceldata/models/api/catalog/reconciliation_rules_response.py +102 -0
  171. acceldata/models/api/catalog/relative_config.py +197 -0
  172. acceldata/models/api/catalog/relative_config_fallback.py +101 -0
  173. acceldata/models/api/catalog/relative_threshold_config.py +111 -0
  174. acceldata/models/api/catalog/root_cause_analysis.py +108 -0
  175. acceldata/models/api/catalog/rule_execution.py +327 -0
  176. acceldata/models/api/catalog/rule_execution_result.py +90 -0
  177. acceldata/models/api/catalog/rule_item_result.py +125 -0
  178. acceldata/models/api/catalog/rule_meta_data.py +94 -0
  179. acceldata/models/api/catalog/rule_spark_sql_dynamic_filter_variable_mapping.py +100 -0
  180. acceldata/models/api/catalog/rule_tag.py +101 -0
  181. acceldata/models/api/catalog/rule_threshold_configuration.py +236 -0
  182. acceldata/models/api/catalog/rule_threshold_configuration_fallback.py +101 -0
  183. acceldata/models/api/catalog/rules_with_latest_execution_response.py +102 -0
  184. acceldata/models/api/catalog/sample_data_api_response.py +122 -0
  185. acceldata/models/api/catalog/schema_drift_item_execution.py +131 -0
  186. acceldata/models/api/catalog/schema_drift_rule_execution.py +102 -0
  187. acceldata/models/api/catalog/secret_manager_configuration.py +90 -0
  188. acceldata/models/api/catalog/secret_manager_configuration_with_option.py +98 -0
  189. acceldata/models/api/catalog/security_config.py +90 -0
  190. acceldata/models/api/catalog/segment_metric_json.py +142 -0
  191. acceldata/models/api/catalog/segments_analysis.py +145 -0
  192. acceldata/models/api/catalog/short_segment.py +97 -0
  193. acceldata/models/api/catalog/simple_quality_rule_response.py +92 -0
  194. acceldata/models/api/catalog/snapshot_data.py +117 -0
  195. acceldata/models/api/catalog/source_model.py +90 -0
  196. acceldata/models/api/catalog/source_type.py +100 -0
  197. acceldata/models/api/catalog/source_types_response.py +102 -0
  198. acceldata/models/api/catalog/spark_job_status.py +113 -0
  199. acceldata/models/api/catalog/spark_resource_config.py +114 -0
  200. acceldata/models/api/catalog/standard_response_assembly.py +92 -0
  201. acceldata/models/api/catalog/standard_response_crawler_action_response.py +92 -0
  202. acceldata/models/api/catalog/standard_response_crawler_status_response.py +92 -0
  203. acceldata/models/api/catalog/standard_response_delete_artifact_response.py +92 -0
  204. acceldata/models/api/catalog/standard_response_list.py +96 -0
  205. acceldata/models/api/catalog/standard_response_map.py +88 -0
  206. acceldata/models/api/catalog/standard_response_meta_data.py +92 -0
  207. acceldata/models/api/catalog/standard_response_mini_profile_request.py +92 -0
  208. acceldata/models/api/catalog/standard_response_profile_request.py +92 -0
  209. acceldata/models/api/catalog/start_profiling_request.py +92 -0
  210. acceldata/models/api/catalog/tag_domain.py +116 -0
  211. acceldata/models/api/catalog/threshold_breach_details.py +101 -0
  212. acceldata/models/api/catalog/time_based_config.py +92 -0
  213. acceldata/models/api/catalog/time_based_threshold_config.py +105 -0
  214. acceldata/models/api/catalog/timestamp_based_marker_config.py +115 -0
  215. acceldata/models/api/catalog/udf_variable.py +97 -0
  216. acceldata/models/api/catalog/yunikorn_compute_config.py +133 -0
  217. acceldata/models/api/catalog/yunikorn_spark_resource_config.py +154 -0
  218. acceldata/models/api/pipeline/big_decimal.py +100 -0
  219. acceldata/models/api/pipeline/big_integer.py +98 -0
  220. acceldata/models/api/pipeline/child_span_response.py +96 -0
  221. acceldata/models/api/pipeline/create_span_event.py +109 -0
  222. acceldata/models/api/pipeline/edge.py +108 -0
  223. acceldata/models/api/pipeline/event_alert_object.py +95 -0
  224. acceldata/models/api/pipeline/generic_config_fallback.py +101 -0
  225. acceldata/models/api/pipeline/identifier.py +146 -0
  226. acceldata/models/api/pipeline/job_request.py +130 -0
  227. acceldata/models/api/pipeline/meta.py +107 -0
  228. acceldata/models/api/pipeline/meta_data.py +92 -0
  229. acceldata/models/api/pipeline/metric.py +103 -0
  230. acceldata/models/api/pipeline/node.py +201 -0
  231. acceldata/models/api/pipeline/node_response.py +92 -0
  232. acceldata/models/api/pipeline/notification_payload.py +114 -0
  233. acceldata/models/api/pipeline/pipeline.py +152 -0
  234. acceldata/models/api/pipeline/pipeline_baseline_metric.py +92 -0
  235. acceldata/models/api/pipeline/pipeline_details.py +118 -0
  236. acceldata/models/api/pipeline/pipeline_details_response.py +102 -0
  237. acceldata/models/api/pipeline/pipeline_input_request.py +92 -0
  238. acceldata/models/api/pipeline/pipeline_listing_info.py +118 -0
  239. acceldata/models/api/pipeline/pipeline_response.py +92 -0
  240. acceldata/models/api/pipeline/pipeline_run.py +136 -0
  241. acceldata/models/api/pipeline/pipeline_run_request.py +92 -0
  242. acceldata/models/api/pipeline/pipeline_runs_response.py +102 -0
  243. acceldata/models/api/pipeline/pipeline_summary.py +98 -0
  244. acceldata/models/api/pipeline/pipelines_listing_response.py +102 -0
  245. acceldata/models/api/pipeline/policy_summary.py +102 -0
  246. acceldata/models/api/pipeline/span.py +115 -0
  247. acceldata/models/api/pipeline/span_event.py +114 -0
  248. acceldata/models/api/pipeline/span_event_request.py +92 -0
  249. acceldata/models/api/pipeline/span_event_response.py +92 -0
  250. acceldata/models/api/pipeline/span_request.py +94 -0
  251. acceldata/models/api/pipeline/spans_response.py +96 -0
  252. acceldata/models/api/pipeline/tag.py +97 -0
  253. acceldata/models/sdk/__init__.py +0 -0
  254. acceldata/models/sdk/catalog/__init__.py +105 -0
  255. acceldata/models/sdk/catalog/asset_resource.py +112 -0
  256. acceldata/models/sdk/catalog/asset_source_type.py +59 -0
  257. acceldata/models/sdk/catalog/custom_asset_metadata.py +11 -0
  258. acceldata/models/sdk/catalog/datasource_resource.py +88 -0
  259. acceldata/models/sdk/catalog/executor.py +524 -0
  260. acceldata/models/sdk/catalog/policy_execution_request.py +114 -0
  261. acceldata/models/sdk/catalog/policy_execution_type.py +16 -0
  262. acceldata/models/sdk/catalog/policy_filter.py +94 -0
  263. acceldata/models/sdk/catalog/policy_rule_resources.py +388 -0
  264. acceldata/models/sdk/catalog/profile_request_resource.py +77 -0
  265. acceldata/models/sdk/catalog/profiling.py +82 -0
  266. acceldata/models/sdk/catalog/profiling_configuration_error.py +5 -0
  267. acceldata/models/sdk/pipeline/__init__.py +62 -0
  268. acceldata/models/sdk/pipeline/create_job_input.py +108 -0
  269. acceldata/models/sdk/pipeline/create_pipeline_input_request.py +72 -0
  270. acceldata/models/sdk/pipeline/events/__init__.py +5 -0
  271. acceldata/models/sdk/pipeline/events/generic_event.py +31 -0
  272. acceldata/models/sdk/pipeline/events/log_event.py +34 -0
  273. acceldata/models/sdk/pipeline/events/span_event.py +8 -0
  274. acceldata/models/sdk/pipeline/pipeline_resource.py +171 -0
  275. acceldata/models/sdk/pipeline/pipeline_run_input.py +84 -0
  276. acceldata/models/sdk/pipeline/pipeline_run_resource.py +208 -0
  277. acceldata/models/sdk/pipeline/pipeline_source_type.py +20 -0
  278. acceldata/models/sdk/pipeline/span_resource.py +327 -0
  279. acceldata/openapi_deserialization_patches.py +161 -0
  280. acceldata/openapi_repr_patches.py +62 -0
  281. acceldata/services/__init__.py +0 -0
  282. acceldata/services/api_timestamp.py +31 -0
  283. acceldata/services/asset_service.py +651 -0
  284. acceldata/services/datasource_service.py +120 -0
  285. acceldata/services/generic_service.py +132 -0
  286. acceldata/services/marker_config.py +232 -0
  287. acceldata/services/pipeline_big_decimal_api.py +102 -0
  288. acceldata/services/pipeline_response_parse.py +209 -0
  289. acceldata/services/pipeline_service.py +494 -0
  290. acceldata/services/rule_service.py +620 -0
  291. acceldata/urls/__init__.py +1 -0
  292. acceldata/urls/catalog_urls.py +137 -0
  293. acceldata/urls/pipeline_urls.py +55 -0
  294. acceldata/utils/__init__.py +6 -0
  295. acceldata/utils/datetime_utils.py +16 -0
  296. acceldata/utils/operation_ack.py +22 -0
  297. acceldata/utils/span_helpers.py +95 -0
  298. acceldata/utils/time_range_utils.py +90 -0
  299. acceldata_sdk_python-26.7.0.dist-info/METADATA +26 -0
  300. acceldata_sdk_python-26.7.0.dist-info/RECORD +303 -0
  301. acceldata_sdk_python-26.7.0.dist-info/WHEEL +5 -0
  302. acceldata_sdk_python-26.7.0.dist-info/licenses/LICENSE +22 -0
  303. acceldata_sdk_python-26.7.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,494 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from dataclasses import asdict, is_dataclass
5
+ from datetime import datetime
6
+ from enum import Enum
7
+ from typing import TYPE_CHECKING, Any, Optional
8
+
9
+ from acceldata.models.api.pipeline.pipeline_runs_response import PipelineRunsResponse
10
+ from pydantic import BaseModel, JsonValue
11
+
12
+ from acceldata.client.http_client import BaseHttpClient
13
+ from acceldata.exceptions import InvalidPipelineRunLookupError, PipelineRunNotFoundError
14
+ from acceldata.models.api.pipeline.node_response import NodeResponse
15
+ from acceldata.models.api.pipeline.pipeline_details_response import PipelineDetailsResponse
16
+ from acceldata.models.api.pipeline.pipeline_response import PipelineResponse
17
+ from acceldata.models.api.pipeline.pipeline import Pipeline
18
+ from acceldata.models.api.pipeline.pipeline_run import PipelineRun
19
+ from acceldata.models.api.pipeline.tag import Tag
20
+ from acceldata.models.api.pipeline.pipelines_listing_response import PipelinesListingResponse
21
+ from acceldata.models.api.pipeline.span import Span
22
+ from acceldata.models.api.pipeline.span_event import SpanEvent
23
+ from acceldata.models.api.pipeline.span_event_request import SpanEventRequest
24
+ from acceldata.models.api.pipeline.span_request import SpanRequest
25
+ from acceldata.models.api.pipeline.spans_response import SpansResponse
26
+ from acceldata.models.sdk.pipeline.create_pipeline_input_request import CreatePipelineInputRequest
27
+ from acceldata.models.sdk.pipeline.pipeline_run_input import PipelineRunResult, PipelineRunStatus
28
+ from acceldata.services.pipeline_response_parse import (
29
+ pipeline_response_from_api_dict,
30
+ span_from_api_dict,
31
+ span_request_from_api_dict,
32
+ spans_response_from_api_dict,
33
+ )
34
+ from acceldata.utils.operation_ack import ack_failure, ack_success
35
+
36
+ if TYPE_CHECKING:
37
+ from acceldata.models.sdk.pipeline.span_resource import SpanResource
38
+
39
+ logger = logging.getLogger("pipelineservice")
40
+
41
+
42
+ def _sanitize_for_json(obj: Any) -> Any:
43
+ if obj is None:
44
+ return None
45
+ if isinstance(obj, Enum):
46
+ return obj.value
47
+ if isinstance(obj, datetime):
48
+ return obj.isoformat()
49
+ if isinstance(obj, dict):
50
+ return {str(k): _sanitize_for_json(v) for k, v in obj.items()}
51
+ if isinstance(obj, (list, tuple)):
52
+ return [_sanitize_for_json(x) for x in obj]
53
+ if isinstance(obj, (str, int, float, bool)):
54
+ return obj
55
+ if isinstance(obj, BaseModel):
56
+ if hasattr(obj, "model_dump"):
57
+ dumped = obj.model_dump(by_alias=True, exclude_none=True)
58
+ else:
59
+ dumped = obj.dict(by_alias=True, exclude_none=True)
60
+ return _sanitize_for_json(dumped)
61
+ if is_dataclass(obj):
62
+ return _sanitize_for_json(asdict(obj))
63
+ return obj
64
+
65
+
66
+ class PipelineService:
67
+ def __init__(self, http_client: BaseHttpClient) -> None:
68
+ self._client = http_client
69
+ self.logger = logger
70
+
71
+ def _convert_pipeline_to_dict(self, pipeline: Optional[CreatePipelineInputRequest]) -> dict[str, JsonValue]:
72
+ if isinstance(pipeline, dict):
73
+ return dict(pipeline)
74
+ if pipeline is None:
75
+ raise TypeError("create_pipeline_input_request is required")
76
+ # CreatePipelineInputRequest is a Pydantic BaseModel, not a dataclass — use to_dict().
77
+ if isinstance(pipeline, BaseModel):
78
+ outer = pipeline.to_dict()
79
+ inner = outer.get("pipeline")
80
+ if not isinstance(inner, dict):
81
+ raise TypeError(
82
+ "CreatePipelineInputRequest must serialize to a dict with a 'pipeline' object"
83
+ )
84
+ raw = _sanitize_for_json(inner)
85
+ elif is_dataclass(pipeline):
86
+ raw = _sanitize_for_json(asdict(pipeline))
87
+ else:
88
+ raise TypeError(
89
+ f"Unsupported pipeline request type: {type(pipeline).__name__}"
90
+ )
91
+ if not isinstance(raw, dict):
92
+ raise TypeError("Pipeline serialization must produce a JSON object")
93
+ return raw
94
+
95
+ def create_pipeline(self, create_pipeline_input_request: Optional[CreatePipelineInputRequest] = None,
96
+ **kwargs) -> PipelineResponse:
97
+ payload = self._convert_pipeline_to_dict(create_pipeline_input_request)
98
+ url = self._client.pipeline_urls.pipelines_root()
99
+ response = self._client._put(url, payload={"pipeline": payload})
100
+ if not isinstance(response, dict):
101
+ raise TypeError(f"Expected dict from create pipeline, got {type(response).__name__}")
102
+ p = response.get("pipeline")
103
+ if not isinstance(p, dict):
104
+ raise TypeError("Create pipeline response must include a 'pipeline' object")
105
+ out = pipeline_response_from_api_dict(response)
106
+ pid = out.pipeline.id if out.pipeline is not None else None
107
+ ack_success(self.logger, "create_pipeline", pipeline_id=pid)
108
+ return out
109
+
110
+ def update_pipeline(self, pipeline: Pipeline) -> PipelineResponse:
111
+ """PUT ``/pipelines`` with a full :class:`~acceldata.models.api.pipeline.pipeline.Pipeline` body (must include ``id`` when updating)."""
112
+ if pipeline.id is None:
113
+ raise ValueError("Pipeline id is required to update a pipeline")
114
+ raw = _sanitize_for_json(pipeline.to_dict())
115
+ if not isinstance(raw, dict):
116
+ raise TypeError("Pipeline serialization must produce a JSON object")
117
+ url = self._client.pipeline_urls.pipelines_root()
118
+ response = self._client._put(url, payload={"pipeline": raw})
119
+ if not isinstance(response, dict):
120
+ raise TypeError(f"Expected dict from update pipeline, got {type(response).__name__}")
121
+ p = response.get("pipeline")
122
+ if not isinstance(p, dict):
123
+ raise TypeError("Update pipeline response must include a 'pipeline' object")
124
+ out = pipeline_response_from_api_dict(response)
125
+ pid = out.pipeline.id if out.pipeline is not None else None
126
+ ack_success(self.logger, "update_pipeline", pipeline_id=pid)
127
+ return out
128
+
129
+ def replace_pipeline_tags(
130
+ self, pipeline_identity: str | int, tags: list[Tag]
131
+ ) -> PipelineResponse:
132
+ """GET the pipeline by identity, replace its ``tags`` list, and PUT the full pipeline back."""
133
+ current = self.get_pipeline(str(pipeline_identity))
134
+ pl = current.pipeline
135
+ if pl is None:
136
+ raise TypeError("get_pipeline returned no pipeline object")
137
+ updated = pl.model_copy(update={"tags": list(tags)})
138
+ return self.update_pipeline(updated)
139
+
140
+ def delete_pipeline(self, pipeline_id: str | int) -> dict[str, JsonValue]:
141
+ url = self._client.pipeline_urls.pipeline_by_identity(pipeline_id)
142
+ response = self._client._delete(url)
143
+ ack_success(self.logger, "delete_pipeline", pipeline_id=pipeline_id)
144
+ if isinstance(response, dict):
145
+ return response
146
+ return {}
147
+
148
+ def create_job(self, job: dict[str, Any], pipeline_id: int) -> NodeResponse:
149
+ url = self._client.pipeline_urls.pipeline_jobs(pipeline_id)
150
+ response = self._client._put(url, payload=job)
151
+ if not isinstance(response, dict):
152
+ raise TypeError(f"Expected dict from create job, got {type(response).__name__}")
153
+ node = NodeResponse.from_dict(response)
154
+ job_uid = node.node.uid if node.node is not None else None
155
+ ack_success(self.logger, "create_job", pipeline_id=pipeline_id, job_uid=job_uid)
156
+ return node
157
+
158
+ def get_pipeline_run(
159
+ self,
160
+ pipeline_run_id: Optional[int] = None,
161
+ continuation_id: Optional[str] = None,
162
+ pipeline_id: Optional[int] = None,
163
+ ) -> PipelineRun:
164
+ if pipeline_run_id is not None:
165
+ url = self._client.pipeline_urls.pipeline_run_by_id(pipeline_run_id)
166
+ response = self._client._get(url)
167
+ if not isinstance(response, dict):
168
+ raise TypeError(f"Expected dict from get pipeline run, got {type(response).__name__}")
169
+ r = response.get("run")
170
+ elif continuation_id is not None and pipeline_id is not None:
171
+ url = self._client.pipeline_urls.pipeline_runs(pipeline_id)
172
+ response = self._client._get(url, params={"continuationId": continuation_id})
173
+ if not isinstance(response, dict):
174
+ raise TypeError(f"Expected dict from pipeline runs listing, got {type(response).__name__}")
175
+ runs = response.get("runs") or []
176
+ if not isinstance(runs, list) or not runs:
177
+ ack_failure(
178
+ self.logger,
179
+ "get_pipeline_run",
180
+ "run_not_found",
181
+ continuation_id=continuation_id,
182
+ pipeline_id=pipeline_id,
183
+ )
184
+ raise PipelineRunNotFoundError(
185
+ (
186
+ f"No pipeline run found for continuation_id={continuation_id!r} on pipeline_id={pipeline_id}. "
187
+ "Confirm the continuation id matches the active run, or use get_latest_pipeline_run() "
188
+ "when a single latest run is sufficient."
189
+ ),
190
+ continuation_id=continuation_id,
191
+ pipeline_id=pipeline_id,
192
+ )
193
+ r = runs[0]
194
+ else:
195
+ ack_failure(
196
+ self.logger,
197
+ "get_pipeline_run",
198
+ "invalid_lookup",
199
+ pipeline_run_id=pipeline_run_id,
200
+ continuation_id=continuation_id,
201
+ pipeline_id=pipeline_id,
202
+ )
203
+ raise InvalidPipelineRunLookupError(
204
+ "Provide pipeline_run_id, or both continuation_id and pipeline_id together."
205
+ )
206
+ if not isinstance(r, dict):
207
+ raise TypeError("Pipeline run response must include a 'run' object")
208
+ run = PipelineRun.from_dict(r)
209
+ ack_success(
210
+ self.logger,
211
+ "get_pipeline_run",
212
+ pipeline_run_id=run.id,
213
+ continuation_id=continuation_id,
214
+ )
215
+ return run
216
+
217
+ def get_latest_pipeline_run(self, pipeline_id: int) -> PipelineRun:
218
+ url = self._client.pipeline_urls.pipeline_latest_run(pipeline_id)
219
+ response = self._client._get(url)
220
+ if not isinstance(response, dict):
221
+ raise TypeError(f"Expected dict from latest pipeline run, got {type(response).__name__}")
222
+ r = response.get("run")
223
+ if not isinstance(r, dict):
224
+ raise TypeError("Latest pipeline run response must include a 'run' object")
225
+ run = PipelineRun.from_dict(r)
226
+ ack_success(self.logger, "get_latest_pipeline_run", pipeline_id=pipeline_id, pipeline_run_id=run.id)
227
+ return run
228
+
229
+ def get_pipeline_runs(self, pipeline_id: int) -> PipelineRunsResponse:
230
+ url = self._client.pipeline_urls.pipeline_runs(pipeline_id)
231
+ response = self._client._get(url)
232
+ if not isinstance(response, dict):
233
+ raise TypeError(f"Expected dict from pipeline runs, got {type(response).__name__}")
234
+ listing = PipelineRunsResponse.from_dict(response)
235
+ ack_success(self.logger, "get_pipeline_runs", pipeline_id=pipeline_id)
236
+ return listing
237
+
238
+ def create_pipeline_run(
239
+ self,
240
+ pipeline_id: int,
241
+ *,
242
+ context_data: Optional[dict[str, Any]] = None,
243
+ continuation_id: Optional[str] = None,
244
+ started_at: Optional[datetime] = None,
245
+ ) -> PipelineRun:
246
+ run_inner: dict[str, Any] = {
247
+ "pipelineId": pipeline_id,
248
+ "status": PipelineRunStatus.STARTED.value,
249
+ }
250
+ if continuation_id is not None:
251
+ run_inner["continuationId"] = continuation_id
252
+ if context_data is not None:
253
+ run_inner["args"] = context_data
254
+ if started_at is not None:
255
+ run_inner["startedAt"] = started_at.isoformat()
256
+ payload = {"run": _sanitize_for_json(run_inner)}
257
+ url = self._client.pipeline_urls.pipeline_runs(pipeline_id)
258
+ response = self._client._post(url, payload=payload)
259
+ if not isinstance(response, dict):
260
+ raise TypeError(f"Expected dict from create pipeline run, got {type(response).__name__}")
261
+ r = response.get("run")
262
+ if not isinstance(r, dict):
263
+ raise TypeError("Create pipeline run response must include a 'run' object")
264
+ run = PipelineRun.from_dict(r)
265
+ ack_success(
266
+ self.logger,
267
+ "create_pipeline_run",
268
+ pipeline_id=pipeline_id,
269
+ pipeline_run_id=run.id,
270
+ continuation_id=continuation_id,
271
+ )
272
+ return run
273
+
274
+ def update_pipeline_run(
275
+ self,
276
+ pipeline_run_id: int,
277
+ *,
278
+ pipeline_id: int,
279
+ result: PipelineRunResult,
280
+ status: PipelineRunStatus,
281
+ version_id: Optional[int] = None,
282
+ context_data: Optional[dict[str, Any]] = None,
283
+ continuation_id: Optional[str] = None,
284
+ started_at: Optional[datetime] = None,
285
+ finished_at: Optional[datetime] = None,
286
+ ) -> PipelineRun:
287
+
288
+ run_inner: dict[str, Any] = {
289
+ "pipelineId": pipeline_id,
290
+ "result": result.value,
291
+ "status": status.value,
292
+ }
293
+ if version_id is not None:
294
+ run_inner["versionId"] = version_id
295
+ if continuation_id is not None:
296
+ run_inner["continuationId"] = continuation_id
297
+ if context_data is not None:
298
+ run_inner["args"] = context_data
299
+ if started_at is not None:
300
+ run_inner["startedAt"] = started_at.isoformat()
301
+ if finished_at is not None:
302
+ run_inner["finishedAt"] = finished_at.isoformat()
303
+ payload = {"run": _sanitize_for_json(run_inner)}
304
+ url = self._client.pipeline_urls.pipeline_run_by_id(pipeline_run_id)
305
+ response = self._client._put(url, payload=payload)
306
+ if not isinstance(response, dict):
307
+ raise TypeError(f"Expected dict from update pipeline run, got {type(response).__name__}")
308
+ r = response.get("run")
309
+ if not isinstance(r, dict):
310
+ raise TypeError("Update pipeline run response must include a 'run' object")
311
+ run = PipelineRun.from_dict(r)
312
+ ack_success(
313
+ self.logger,
314
+ "update_pipeline_run",
315
+ pipeline_run_id=pipeline_run_id,
316
+ pipeline_id=pipeline_id,
317
+ result=result.value,
318
+ status=status.value,
319
+ )
320
+ return run
321
+
322
+ def create_span(
323
+ self,
324
+ pipeline_run_id: int,
325
+ payload: dict[str, JsonValue],
326
+ ) -> Span:
327
+ url = self._client.pipeline_urls.pipeline_run_spans(pipeline_run_id)
328
+ response = self._client._post(url, payload=payload)
329
+ if not isinstance(response, dict):
330
+ raise TypeError(f"Expected dict from create span, got {type(response).__name__}")
331
+ s = response.get("span")
332
+ if not isinstance(s, dict):
333
+ raise TypeError("Create span response must include a 'span' object")
334
+ res = span_from_api_dict(s)
335
+ if res is None:
336
+ raise TypeError("Could not parse span from create span response")
337
+ ack_success(
338
+ self.logger,
339
+ "create_span",
340
+ pipeline_run_id=pipeline_run_id,
341
+ span_uid=res.uid,
342
+ span_id=res.id,
343
+ )
344
+ return res
345
+
346
+ def get_child_spans(self, span_id: int) -> list[Span]:
347
+ url = self._client.pipeline_urls.span_child_spans(span_id)
348
+ response = self._client._get(url)
349
+ if not isinstance(response, dict):
350
+ raise TypeError(f"Expected dict from child spans, got {type(response).__name__}")
351
+ raw = response.get("childSpans") or []
352
+ if not isinstance(raw, list):
353
+ raise TypeError("childSpans must be a list when present")
354
+ out: list[Span] = []
355
+ for item in raw:
356
+ if not isinstance(item, dict):
357
+ raise TypeError("Each child span must be an object")
358
+ s = span_from_api_dict(item)
359
+ if s is not None:
360
+ out.append(s)
361
+ ack_success(self.logger, "get_child_spans", span_id=span_id, count=len(out))
362
+ return out
363
+
364
+ def create_span_event(self, request: SpanEventRequest) -> SpanEvent:
365
+ if request.event.span_id is None:
366
+ raise ValueError("To create a span event, spanId is required.")
367
+ url = self._client.pipeline_urls.span_events(request.event.span_id)
368
+ payload = _sanitize_for_json(request.to_dict())
369
+ self.logger.info(f"create span event payload: {payload}")
370
+ if not isinstance(payload, dict):
371
+ raise TypeError("Span event payload must serialize to a JSON object")
372
+ response = self._client._post(url, payload=payload)
373
+ if not isinstance(response, dict):
374
+ raise TypeError(f"Expected dict from create span event, got {type(response).__name__}")
375
+ ev = response.get("event")
376
+ if not isinstance(ev, dict):
377
+ raise TypeError("Create span event response must include an 'event' object")
378
+ out = SpanEvent.from_dict(ev)
379
+ if out is None:
380
+ raise TypeError("Could not parse span event from response")
381
+ ack_success(
382
+ self.logger,
383
+ "create_span_event",
384
+ span_id=request.event.span_id,
385
+ event_uid=request.event.event_uid,
386
+ )
387
+ return out
388
+
389
+ # get pipeline by uid or id
390
+ def get_pipeline(self, pipeline_identity: str) -> PipelineResponse:
391
+ """
392
+ Description:
393
+ To get an existing pipeline from the catalog
394
+ :param pipeline_identity: uid or id of the pipeline
395
+ :return:(Pipeline) pipeline class instance
396
+ """
397
+ url = self._client.pipeline_urls.pipeline_by_identity(pipeline_identity)
398
+ response = self._client._get(url)
399
+ if not isinstance(response, dict):
400
+ raise TypeError(f"Expected dict from get pipeline, got {type(response).__name__}")
401
+ out = pipeline_response_from_api_dict(response)
402
+ pid = out.pipeline.id if out.pipeline is not None else None
403
+ ack_success(self.logger, "get_pipeline", pipeline_identity=pipeline_identity, pipeline_id=pid)
404
+ return out
405
+
406
+ def get_root_span(self, pipeline_run_id: int) -> Optional[SpanResource]:
407
+ from acceldata.models.sdk.pipeline.span_resource import wrap_fetched_span
408
+
409
+ url = self._client.pipeline_urls.pipeline_run_spans(pipeline_run_id)
410
+ response = self._client._get(url, params={"onlyRootSpan": "true"})
411
+ if not isinstance(response, dict):
412
+ raise TypeError(f"Expected dict from root span, got {type(response).__name__}")
413
+ spans = response.get("spans") or []
414
+ if not spans:
415
+ # Some deployments omit root when ``onlyRootSpan`` is set; fall back to full listing.
416
+ full = self._client._get(url)
417
+ if not isinstance(full, dict):
418
+ raise TypeError(f"Expected dict from spans listing, got {type(full).__name__}")
419
+ for item in full.get("spans") or []:
420
+ if not isinstance(item, dict):
421
+ raise TypeError("Each span must be an object")
422
+ if item.get("parentSpanId") is not None:
423
+ continue
424
+ span = span_from_api_dict(item)
425
+ if span is not None:
426
+ return wrap_fetched_span(self, span)
427
+ return None
428
+ first = spans[0]
429
+ if not isinstance(first, dict):
430
+ raise TypeError("spans[0] must be an object")
431
+ span = span_from_api_dict(first)
432
+ if span is None:
433
+ raise TypeError("Could not parse root span from response")
434
+ return wrap_fetched_span(self, span)
435
+
436
+ def get_pipelines(self) -> PipelinesListingResponse:
437
+ """
438
+ Description:
439
+ To get all pipelines from ADOC
440
+ :return:(List[PipelineListingInfo]) PipelineListingInfo class instance
441
+ """
442
+ url = self._client.pipeline_urls.pipelines_summary()
443
+ response = self._client._get(url)
444
+ if not isinstance(response, dict):
445
+ raise TypeError(f"Expected dict from list pipelines, got {type(response).__name__}")
446
+ listing = PipelinesListingResponse.from_dict(response)
447
+ ack_success(self.logger, "get_pipelines")
448
+ return listing
449
+
450
+ def get_run_details(self, pipeline_id: int, version_id: int) -> PipelineDetailsResponse:
451
+ url = self._client.pipeline_urls.pipeline_graph_by_version_id(pipeline_id, version_id)
452
+ response = self._client._get(url)
453
+ if not isinstance(response, dict):
454
+ raise TypeError(f"Expected dict from get_run_details, got {type(response).__name__}")
455
+ details = PipelineDetailsResponse.from_dict(response)
456
+ ack_success(self.logger, "get_run_details", pipeline_id=pipeline_id, version_id=version_id)
457
+ return details
458
+
459
+ def get_spans(self, pipeline_run_id: int) -> SpansResponse:
460
+ """
461
+ Description:
462
+ List spans for the pipeline run.
463
+ :return: :class:`~acceldata.models.api.pipeline.spans_response.SpansResponse`
464
+ """
465
+ url = self._client.pipeline_urls.pipeline_run_spans(pipeline_run_id=pipeline_run_id)
466
+ response = self._client._get(url=url)
467
+ if not isinstance(response, dict):
468
+ raise TypeError(f"Expected dict from get_spans, got {type(response).__name__}")
469
+ spans = spans_response_from_api_dict(response)
470
+ ack_success(self.logger, "get_spans", pipeline_run_id=pipeline_run_id)
471
+ return spans
472
+
473
+ def get_span(self, pipeline_run_id: int, span_identity: str) -> Span:
474
+ url = self._client.pipeline_urls.pipeline_run_span_by_uid(pipeline_run_id=pipeline_run_id,
475
+ span_identity=span_identity)
476
+ response = self._client._get(url=url)
477
+ if not isinstance(response, dict):
478
+ raise TypeError(f"Expected dict from get_span, got {type(response).__name__}")
479
+ # API returns SpanRequest: { "span": { ... }, "associatedJobUids": [...] }
480
+ if isinstance(response.get("span"), dict):
481
+ envelope = span_request_from_api_dict(response)
482
+ if envelope is None or envelope.span is None:
483
+ raise TypeError("get_span response missing span")
484
+ span = envelope.span
485
+ else:
486
+ span = span_from_api_dict(response)
487
+ ack_success(
488
+ self.logger,
489
+ "get_span",
490
+ pipeline_run_id=pipeline_run_id,
491
+ span_identity=span_identity,
492
+ span_id=span.id,
493
+ )
494
+ return span