hatchet-sdk 1.14.4__py3-none-any.whl → 1.15.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hatchet-sdk might be problematic. Click here for more details.

@@ -2005,6 +2005,272 @@ class TenantApi:
2005
2005
  _request_auth=_request_auth,
2006
2006
  )
2007
2007
 
2008
+ @validate_call
2009
+ def tenant_get_prometheus_metrics(
2010
+ self,
2011
+ tenant: Annotated[
2012
+ str,
2013
+ Field(
2014
+ min_length=36, strict=True, max_length=36, description="The tenant id"
2015
+ ),
2016
+ ],
2017
+ _request_timeout: Union[
2018
+ None,
2019
+ Annotated[StrictFloat, Field(gt=0)],
2020
+ Tuple[
2021
+ Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
2022
+ ],
2023
+ ] = None,
2024
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
2025
+ _content_type: Optional[StrictStr] = None,
2026
+ _headers: Optional[Dict[StrictStr, Any]] = None,
2027
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
2028
+ ) -> str:
2029
+ """Get prometheus metrics
2030
+
2031
+ Get the prometheus metrics for the tenant
2032
+
2033
+ :param tenant: The tenant id (required)
2034
+ :type tenant: str
2035
+ :param _request_timeout: timeout setting for this request. If one
2036
+ number provided, it will be total request
2037
+ timeout. It can also be a pair (tuple) of
2038
+ (connection, read) timeouts.
2039
+ :type _request_timeout: int, tuple(int, int), optional
2040
+ :param _request_auth: set to override the auth_settings for an a single
2041
+ request; this effectively ignores the
2042
+ authentication in the spec for a single request.
2043
+ :type _request_auth: dict, optional
2044
+ :param _content_type: force content-type for the request.
2045
+ :type _content_type: str, Optional
2046
+ :param _headers: set to override the headers for a single
2047
+ request; this effectively ignores the headers
2048
+ in the spec for a single request.
2049
+ :type _headers: dict, optional
2050
+ :param _host_index: set to override the host_index for a single
2051
+ request; this effectively ignores the host_index
2052
+ in the spec for a single request.
2053
+ :type _host_index: int, optional
2054
+ :return: Returns the result object.
2055
+ """ # noqa: E501
2056
+
2057
+ _param = self._tenant_get_prometheus_metrics_serialize(
2058
+ tenant=tenant,
2059
+ _request_auth=_request_auth,
2060
+ _content_type=_content_type,
2061
+ _headers=_headers,
2062
+ _host_index=_host_index,
2063
+ )
2064
+
2065
+ _response_types_map: Dict[str, Optional[str]] = {
2066
+ "200": "str",
2067
+ "400": "APIErrors",
2068
+ "403": "APIErrors",
2069
+ "404": "APIErrors",
2070
+ }
2071
+ response_data = self.api_client.call_api(
2072
+ *_param, _request_timeout=_request_timeout
2073
+ )
2074
+ response_data.read()
2075
+ return self.api_client.response_deserialize(
2076
+ response_data=response_data,
2077
+ response_types_map=_response_types_map,
2078
+ ).data
2079
+
2080
+ @validate_call
2081
+ def tenant_get_prometheus_metrics_with_http_info(
2082
+ self,
2083
+ tenant: Annotated[
2084
+ str,
2085
+ Field(
2086
+ min_length=36, strict=True, max_length=36, description="The tenant id"
2087
+ ),
2088
+ ],
2089
+ _request_timeout: Union[
2090
+ None,
2091
+ Annotated[StrictFloat, Field(gt=0)],
2092
+ Tuple[
2093
+ Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
2094
+ ],
2095
+ ] = None,
2096
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
2097
+ _content_type: Optional[StrictStr] = None,
2098
+ _headers: Optional[Dict[StrictStr, Any]] = None,
2099
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
2100
+ ) -> ApiResponse[str]:
2101
+ """Get prometheus metrics
2102
+
2103
+ Get the prometheus metrics for the tenant
2104
+
2105
+ :param tenant: The tenant id (required)
2106
+ :type tenant: str
2107
+ :param _request_timeout: timeout setting for this request. If one
2108
+ number provided, it will be total request
2109
+ timeout. It can also be a pair (tuple) of
2110
+ (connection, read) timeouts.
2111
+ :type _request_timeout: int, tuple(int, int), optional
2112
+ :param _request_auth: set to override the auth_settings for an a single
2113
+ request; this effectively ignores the
2114
+ authentication in the spec for a single request.
2115
+ :type _request_auth: dict, optional
2116
+ :param _content_type: force content-type for the request.
2117
+ :type _content_type: str, Optional
2118
+ :param _headers: set to override the headers for a single
2119
+ request; this effectively ignores the headers
2120
+ in the spec for a single request.
2121
+ :type _headers: dict, optional
2122
+ :param _host_index: set to override the host_index for a single
2123
+ request; this effectively ignores the host_index
2124
+ in the spec for a single request.
2125
+ :type _host_index: int, optional
2126
+ :return: Returns the result object.
2127
+ """ # noqa: E501
2128
+
2129
+ _param = self._tenant_get_prometheus_metrics_serialize(
2130
+ tenant=tenant,
2131
+ _request_auth=_request_auth,
2132
+ _content_type=_content_type,
2133
+ _headers=_headers,
2134
+ _host_index=_host_index,
2135
+ )
2136
+
2137
+ _response_types_map: Dict[str, Optional[str]] = {
2138
+ "200": "str",
2139
+ "400": "APIErrors",
2140
+ "403": "APIErrors",
2141
+ "404": "APIErrors",
2142
+ }
2143
+ response_data = self.api_client.call_api(
2144
+ *_param, _request_timeout=_request_timeout
2145
+ )
2146
+ response_data.read()
2147
+ return self.api_client.response_deserialize(
2148
+ response_data=response_data,
2149
+ response_types_map=_response_types_map,
2150
+ )
2151
+
2152
+ @validate_call
2153
+ def tenant_get_prometheus_metrics_without_preload_content(
2154
+ self,
2155
+ tenant: Annotated[
2156
+ str,
2157
+ Field(
2158
+ min_length=36, strict=True, max_length=36, description="The tenant id"
2159
+ ),
2160
+ ],
2161
+ _request_timeout: Union[
2162
+ None,
2163
+ Annotated[StrictFloat, Field(gt=0)],
2164
+ Tuple[
2165
+ Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
2166
+ ],
2167
+ ] = None,
2168
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
2169
+ _content_type: Optional[StrictStr] = None,
2170
+ _headers: Optional[Dict[StrictStr, Any]] = None,
2171
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
2172
+ ) -> RESTResponseType:
2173
+ """Get prometheus metrics
2174
+
2175
+ Get the prometheus metrics for the tenant
2176
+
2177
+ :param tenant: The tenant id (required)
2178
+ :type tenant: str
2179
+ :param _request_timeout: timeout setting for this request. If one
2180
+ number provided, it will be total request
2181
+ timeout. It can also be a pair (tuple) of
2182
+ (connection, read) timeouts.
2183
+ :type _request_timeout: int, tuple(int, int), optional
2184
+ :param _request_auth: set to override the auth_settings for an a single
2185
+ request; this effectively ignores the
2186
+ authentication in the spec for a single request.
2187
+ :type _request_auth: dict, optional
2188
+ :param _content_type: force content-type for the request.
2189
+ :type _content_type: str, Optional
2190
+ :param _headers: set to override the headers for a single
2191
+ request; this effectively ignores the headers
2192
+ in the spec for a single request.
2193
+ :type _headers: dict, optional
2194
+ :param _host_index: set to override the host_index for a single
2195
+ request; this effectively ignores the host_index
2196
+ in the spec for a single request.
2197
+ :type _host_index: int, optional
2198
+ :return: Returns the result object.
2199
+ """ # noqa: E501
2200
+
2201
+ _param = self._tenant_get_prometheus_metrics_serialize(
2202
+ tenant=tenant,
2203
+ _request_auth=_request_auth,
2204
+ _content_type=_content_type,
2205
+ _headers=_headers,
2206
+ _host_index=_host_index,
2207
+ )
2208
+
2209
+ _response_types_map: Dict[str, Optional[str]] = {
2210
+ "200": "str",
2211
+ "400": "APIErrors",
2212
+ "403": "APIErrors",
2213
+ "404": "APIErrors",
2214
+ }
2215
+ response_data = self.api_client.call_api(
2216
+ *_param, _request_timeout=_request_timeout
2217
+ )
2218
+ return response_data.response
2219
+
2220
+ def _tenant_get_prometheus_metrics_serialize(
2221
+ self,
2222
+ tenant,
2223
+ _request_auth,
2224
+ _content_type,
2225
+ _headers,
2226
+ _host_index,
2227
+ ) -> RequestSerialized:
2228
+
2229
+ _host = None
2230
+
2231
+ _collection_formats: Dict[str, str] = {}
2232
+
2233
+ _path_params: Dict[str, str] = {}
2234
+ _query_params: List[Tuple[str, str]] = []
2235
+ _header_params: Dict[str, Optional[str]] = _headers or {}
2236
+ _form_params: List[Tuple[str, str]] = []
2237
+ _files: Dict[
2238
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
2239
+ ] = {}
2240
+ _body_params: Optional[bytes] = None
2241
+
2242
+ # process the path parameters
2243
+ if tenant is not None:
2244
+ _path_params["tenant"] = tenant
2245
+ # process the query parameters
2246
+ # process the header parameters
2247
+ # process the form parameters
2248
+ # process the body parameter
2249
+
2250
+ # set the HTTP header `Accept`
2251
+ if "Accept" not in _header_params:
2252
+ _header_params["Accept"] = self.api_client.select_header_accept(
2253
+ ["text/plain", "application/json"]
2254
+ )
2255
+
2256
+ # authentication setting
2257
+ _auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
2258
+
2259
+ return self.api_client.param_serialize(
2260
+ method="GET",
2261
+ resource_path="/api/v1/tenants/{tenant}/prometheus-metrics",
2262
+ path_params=_path_params,
2263
+ query_params=_query_params,
2264
+ header_params=_header_params,
2265
+ body=_body_params,
2266
+ post_params=_form_params,
2267
+ files=_files,
2268
+ auth_settings=_auth_settings,
2269
+ collection_formats=_collection_formats,
2270
+ _host=_host,
2271
+ _request_auth=_request_auth,
2272
+ )
2273
+
2008
2274
  @validate_call
2009
2275
  def tenant_get_step_run_queue_metrics(
2010
2276
  self,
@@ -114,6 +114,11 @@ class V1TaskSummary(BaseModel):
114
114
  workflow_config: Optional[Dict[str, Any]] = Field(
115
115
  default=None, alias="workflowConfig"
116
116
  )
117
+ parent_task_external_id: Optional[StrictStr] = Field(
118
+ default=None,
119
+ description="The external ID of the parent task.",
120
+ alias="parentTaskExternalId",
121
+ )
117
122
  __properties: ClassVar[List[str]] = [
118
123
  "metadata",
119
124
  "actionId",
@@ -142,6 +147,7 @@ class V1TaskSummary(BaseModel):
142
147
  "workflowRunExternalId",
143
148
  "workflowVersionId",
144
149
  "workflowConfig",
150
+ "parentTaskExternalId",
145
151
  ]
146
152
 
147
153
  model_config = ConfigDict(
@@ -239,6 +245,7 @@ class V1TaskSummary(BaseModel):
239
245
  "workflowRunExternalId": obj.get("workflowRunExternalId"),
240
246
  "workflowVersionId": obj.get("workflowVersionId"),
241
247
  "workflowConfig": obj.get("workflowConfig"),
248
+ "parentTaskExternalId": obj.get("parentTaskExternalId"),
242
249
  }
243
250
  )
244
251
  return _obj
@@ -1,20 +1,21 @@
1
1
  import asyncio
2
+ from datetime import datetime, timedelta, timezone
3
+ from typing import Any
2
4
 
5
+ from pydantic import BaseModel
6
+
7
+ from hatchet_sdk.clients.rest.api.task_api import TaskApi
3
8
  from hatchet_sdk.clients.rest.api.tenant_api import TenantApi
4
- from hatchet_sdk.clients.rest.api.workflow_api import WorkflowApi
5
9
  from hatchet_sdk.clients.rest.api_client import ApiClient
6
- from hatchet_sdk.clients.rest.models.tenant_queue_metrics import TenantQueueMetrics
7
- from hatchet_sdk.clients.rest.models.tenant_step_run_queue_metrics import (
8
- TenantStepRunQueueMetrics,
9
- )
10
- from hatchet_sdk.clients.rest.models.workflow_metrics import WorkflowMetrics
11
- from hatchet_sdk.clients.rest.models.workflow_run_status import WorkflowRunStatus
12
- from hatchet_sdk.clients.v1.api_client import (
13
- BaseRestClient,
14
- maybe_additional_metadata_to_kv,
15
- retry,
16
- )
17
- from hatchet_sdk.utils.typing import JSONSerializableMapping
10
+ from hatchet_sdk.clients.v1.api_client import BaseRestClient, retry
11
+
12
+
13
+ class TaskMetrics(BaseModel):
14
+ cancelled: int
15
+ completed: int
16
+ failed: int
17
+ queued: int
18
+ running: int
18
19
 
19
20
 
20
21
  class MetricsClient(BaseRestClient):
@@ -22,108 +23,126 @@ class MetricsClient(BaseRestClient):
22
23
  The metrics client is a client for reading metrics out of Hatchet's metrics API.
23
24
  """
24
25
 
25
- def _wa(self, client: ApiClient) -> WorkflowApi:
26
- return WorkflowApi(client)
26
+ def _taskapi(self, client: ApiClient) -> TaskApi:
27
+ return TaskApi(client)
27
28
 
28
29
  def _ta(self, client: ApiClient) -> TenantApi:
29
30
  return TenantApi(client)
30
31
 
31
32
  @retry
32
- def get_workflow_metrics(
33
+ def get_queue_metrics(
33
34
  self,
34
- workflow_id: str,
35
- status: WorkflowRunStatus | None = None,
36
- group_key: str | None = None,
37
- ) -> WorkflowMetrics:
35
+ ) -> dict[str, Any]:
38
36
  """
39
- Retrieve workflow metrics for a given workflow ID.
37
+ Retrieve the current queue metrics for the tenant.
40
38
 
41
- :param workflow_id: The ID of the workflow to retrieve metrics for.
42
- :param status: The status of the workflow run to filter by.
43
- :param group_key: The key to group the metrics by.
44
-
45
- :return: Workflow metrics for the specified workflow ID.
39
+ :return: The current queue metrics
46
40
  """
47
41
  with self.client() as client:
48
- return self._wa(client).workflow_get_metrics(
49
- workflow=workflow_id, status=status, group_key=group_key
50
- )
42
+ return (
43
+ self._ta(client)
44
+ .tenant_get_step_run_queue_metrics(
45
+ tenant=self.client_config.tenant_id,
46
+ )
47
+ .queues
48
+ ) or {}
51
49
 
52
- async def aio_get_workflow_metrics(
50
+ async def aio_get_queue_metrics(
53
51
  self,
54
- workflow_id: str,
55
- status: WorkflowRunStatus | None = None,
56
- group_key: str | None = None,
57
- ) -> WorkflowMetrics:
52
+ ) -> dict[str, Any]:
58
53
  """
59
- Retrieve workflow metrics for a given workflow ID.
60
-
61
- :param workflow_id: The ID of the workflow to retrieve metrics for.
62
- :param status: The status of the workflow run to filter by.
63
- :param group_key: The key to group the metrics by.
54
+ Retrieve the current queue metrics for the tenant.
64
55
 
65
- :return: Workflow metrics for the specified workflow ID.
56
+ :return: The current queue metrics
66
57
  """
67
- return await asyncio.to_thread(
68
- self.get_workflow_metrics, workflow_id, status, group_key
69
- )
58
+
59
+ return await asyncio.to_thread(self.get_queue_metrics)
70
60
 
71
61
  @retry
72
- def get_queue_metrics(
62
+ def scrape_tenant_prometheus_metrics(
73
63
  self,
74
- workflow_ids: list[str] | None = None,
75
- additional_metadata: JSONSerializableMapping | None = None,
76
- ) -> TenantQueueMetrics:
64
+ ) -> str:
77
65
  """
78
- Retrieve queue metrics for a set of workflow ids and additional metadata.
79
-
80
- :param workflow_ids: A list of workflow IDs to retrieve metrics for.
81
- :param additional_metadata: Additional metadata to filter the metrics by.
66
+ Scrape Prometheus metrics for the tenant. Returns the metrics in Prometheus text format.
82
67
 
83
- :return: Workflow metrics for the specified workflow IDs.
68
+ :return: The metrics, returned in Prometheus text format
84
69
  """
85
70
  with self.client() as client:
86
- return self._wa(client).tenant_get_queue_metrics(
71
+ return self._ta(client).tenant_get_prometheus_metrics(
87
72
  tenant=self.client_config.tenant_id,
88
- workflows=workflow_ids,
89
- additional_metadata=maybe_additional_metadata_to_kv(
90
- additional_metadata
91
- ),
92
73
  )
93
74
 
94
- async def aio_get_queue_metrics(
75
+ async def aio_scrape_tenant_prometheus_metrics(
95
76
  self,
96
- workflow_ids: list[str] | None = None,
97
- additional_metadata: JSONSerializableMapping | None = None,
98
- ) -> TenantQueueMetrics:
77
+ ) -> str:
99
78
  """
100
- Retrieve queue metrics for a set of workflow ids and additional metadata.
79
+ Scrape Prometheus metrics for the tenant. Returns the metrics in Prometheus text format.
101
80
 
102
- :param workflow_ids: A list of workflow IDs to retrieve metrics for.
103
- :param additional_metadata: Additional metadata to filter the metrics by.
104
-
105
- :return: Workflow metrics for the specified workflow IDs.
81
+ :return: The metrics, returned in Prometheus text format
106
82
  """
107
- return await asyncio.to_thread(
108
- self.get_queue_metrics, workflow_ids, additional_metadata
109
- )
83
+
84
+ return await asyncio.to_thread(self.scrape_tenant_prometheus_metrics)
110
85
 
111
86
  @retry
112
- def get_task_metrics(self) -> TenantStepRunQueueMetrics:
87
+ def get_task_metrics(
88
+ self,
89
+ since: datetime | None = None,
90
+ until: datetime | None = None,
91
+ workflow_ids: list[str] | None = None,
92
+ parent_task_external_id: str | None = None,
93
+ triggering_event_external_id: str | None = None,
94
+ ) -> TaskMetrics:
113
95
  """
114
- Retrieve queue metrics
115
-
116
- :return: Step run queue metrics for the tenant
96
+ Retrieve task metrics, grouped by status (queued, running, completed, failed, cancelled).
97
+
98
+ :param since: Start time for the metrics query (defaults to the past day if unset)
99
+ :param until: End time for the metrics query
100
+ :param workflow_ids: List of workflow IDs to filter the metrics by
101
+ :param parent_task_external_id: ID of the parent task to filter by (note that parent task here refers to the task that spawned this task as a child)
102
+ :param triggering_event_external_id: ID of the triggering event to filter by
103
+ :return: Task metrics
117
104
  """
118
- with self.client() as client:
119
- return self._ta(client).tenant_get_step_run_queue_metrics(
120
- tenant=self.client_config.tenant_id
121
- )
122
105
 
123
- async def aio_get_task_metrics(self) -> TenantStepRunQueueMetrics:
106
+ since = since or datetime.now(timezone.utc) - timedelta(days=1)
107
+ until = until or datetime.now(timezone.utc)
108
+ with self.client() as client:
109
+ metrics = {
110
+ m.status.name.lower(): m.count
111
+ for m in self._taskapi(client).v1_task_list_status_metrics(
112
+ tenant=self.client_config.tenant_id,
113
+ since=since,
114
+ until=until,
115
+ workflow_ids=workflow_ids,
116
+ parent_task_external_id=parent_task_external_id,
117
+ triggering_event_external_id=triggering_event_external_id,
118
+ )
119
+ }
120
+
121
+ return TaskMetrics.model_validate(metrics)
122
+
123
+ async def aio_get_task_metrics(
124
+ self,
125
+ since: datetime | None = None,
126
+ until: datetime | None = None,
127
+ workflow_ids: list[str] | None = None,
128
+ parent_task_external_id: str | None = None,
129
+ triggering_event_external_id: str | None = None,
130
+ ) -> TaskMetrics:
124
131
  """
125
- Retrieve queue metrics
126
-
127
- :return: Step run queue metrics for the tenant
132
+ Retrieve task metrics, grouped by status (queued, running, completed, failed, cancelled).
133
+
134
+ :param since: Start time for the metrics query (defaults to the past day if unset)
135
+ :param until: End time for the metrics query
136
+ :param workflow_ids: List of workflow IDs to filter the metrics by
137
+ :param parent_task_external_id: ID of the parent task to filter by (note that parent task here refers to the task that spawned this task as a child)
138
+ :param triggering_event_external_id: ID of the triggering event to filter by
139
+ :return: Task metrics
128
140
  """
129
- return await asyncio.to_thread(self.get_task_metrics)
141
+ return await asyncio.to_thread(
142
+ self.get_task_metrics,
143
+ since,
144
+ until,
145
+ workflow_ids,
146
+ parent_task_external_id,
147
+ triggering_event_external_id,
148
+ )
@@ -5,23 +5,27 @@ K = TypeVar("K")
5
5
 
6
6
 
7
7
  @overload
8
- def remove_null_unicode_character(data: str) -> str: ...
8
+ def remove_null_unicode_character(data: str, replacement: str = "") -> str: ...
9
9
 
10
10
 
11
11
  @overload
12
- def remove_null_unicode_character(data: dict[K, T]) -> dict[K, T]: ...
12
+ def remove_null_unicode_character(
13
+ data: dict[K, T], replacement: str = ""
14
+ ) -> dict[K, T]: ...
13
15
 
14
16
 
15
17
  @overload
16
- def remove_null_unicode_character(data: list[T]) -> list[T]: ...
18
+ def remove_null_unicode_character(data: list[T], replacement: str = "") -> list[T]: ...
17
19
 
18
20
 
19
21
  @overload
20
- def remove_null_unicode_character(data: tuple[T, ...]) -> tuple[T, ...]: ...
22
+ def remove_null_unicode_character(
23
+ data: tuple[T, ...], replacement: str = ""
24
+ ) -> tuple[T, ...]: ...
21
25
 
22
26
 
23
27
  def remove_null_unicode_character(
24
- data: str | dict[K, T] | list[T] | tuple[T, ...],
28
+ data: str | dict[K, T] | list[T] | tuple[T, ...], replacement: str = ""
25
29
  ) -> str | dict[K, T] | list[T] | tuple[T, ...]:
26
30
  """
27
31
  Recursively traverse a dictionary (a task's output) and remove the unicode escape sequence \\u0000 which will cause unexpected behavior in Hatchet.
@@ -29,23 +33,29 @@ def remove_null_unicode_character(
29
33
  Needed as Hatchet does not support \\u0000 in task outputs
30
34
 
31
35
  :param data: The task output (a JSON-serializable dictionary or mapping)
36
+ :param replacement: The string to replace \\u0000 with.
37
+
32
38
  :return: The same dictionary with all \\u0000 characters removed from strings, and nested dictionaries/lists processed recursively.
33
39
  :raises TypeError: If the input is not a string, dictionary, list, or tuple.
34
40
  """
35
41
  if isinstance(data, str):
36
- return data.replace("\u0000", "")
42
+ return data.replace("\u0000", replacement)
37
43
 
38
44
  if isinstance(data, dict):
39
45
  return {
40
- key: remove_null_unicode_character(cast(Any, value))
46
+ key: remove_null_unicode_character(cast(Any, value), replacement)
41
47
  for key, value in data.items()
42
48
  }
43
49
 
44
50
  if isinstance(data, list):
45
- return [remove_null_unicode_character(cast(Any, item)) for item in data]
51
+ return [
52
+ remove_null_unicode_character(cast(Any, item), replacement) for item in data
53
+ ]
46
54
 
47
55
  if isinstance(data, tuple):
48
- return tuple(remove_null_unicode_character(cast(Any, item)) for item in data)
56
+ return tuple(
57
+ remove_null_unicode_character(cast(Any, item), replacement) for item in data
58
+ )
49
59
 
50
60
  raise TypeError(
51
61
  f"Unsupported type {type(data)}. Expected str, dict, list, or tuple."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hatchet-sdk
3
- Version: 1.14.4
3
+ Version: 1.15.0
4
4
  Summary:
5
5
  License: MIT
6
6
  Author: Alexander Belanger
@@ -24,7 +24,7 @@ hatchet_sdk/clients/rest/api/slack_api.py,sha256=0xIUw3_1_3hSTn2yw7fLRO5yb38nYLu
24
24
  hatchet_sdk/clients/rest/api/sns_api.py,sha256=1LfhnZEA450uHwtZCoM_wycOeH4UGwfNP1pw4RWSe08,33641
25
25
  hatchet_sdk/clients/rest/api/step_run_api.py,sha256=rqP4UIJSkw8DwbDnlEgupBDWUL0jlVH_Rm7bNGMUoG8,84505
26
26
  hatchet_sdk/clients/rest/api/task_api.py,sha256=erYaoDA2iJk52PPntfT0Y63hsBuk4eaqV5gaRTQ008w,89767
27
- hatchet_sdk/clients/rest/api/tenant_api.py,sha256=DO1a6YXpb4_kUO3HAYTHbHL_khFe7i1SLb6q7EoGxUc,187997
27
+ hatchet_sdk/clients/rest/api/tenant_api.py,sha256=iz67ow7wp9qgo1IRPI_IVTkoMh_ytx81wz4MPgEWWSg,198472
28
28
  hatchet_sdk/clients/rest/api/user_api.py,sha256=NYuEKLeBjXO4q8gyYq1thtbuRm9m3g0R6-q6LIfv83U,115780
29
29
  hatchet_sdk/clients/rest/api/worker_api.py,sha256=56jRXsyK7SDENly2b019EO80d8xOHU4bZnmOmjKY1iQ,33049
30
30
  hatchet_sdk/clients/rest/api/workflow_api.py,sha256=rpPXy5xZDZWo1GXQGLapTC3A5M_spk1zoK_vu_J7SVA,251652
@@ -174,7 +174,7 @@ hatchet_sdk/clients/rest/models/v1_task_point_metrics.py,sha256=shKqLFLgNAKua865
174
174
  hatchet_sdk/clients/rest/models/v1_task_run_metric.py,sha256=8trEgJ_7AHAmUQi2Qty-v5XVjgN3g7VZ6gzMTjeZ1tY,2504
175
175
  hatchet_sdk/clients/rest/models/v1_task_run_status.py,sha256=tjipWHHNx7g4lUZBdu_DDZwEqSpxPKv06YiE2Q17cXo,753
176
176
  hatchet_sdk/clients/rest/models/v1_task_status.py,sha256=4Hqczjth228k8Y23vIaxAIzTpLaS9mh9I0PrTjY8JRY,742
177
- hatchet_sdk/clients/rest/models/v1_task_summary.py,sha256=OoDcrJWCQ2IyOi_8dh826lNXjistjIb4mri4yy0dWGc,8940
177
+ hatchet_sdk/clients/rest/models/v1_task_summary.py,sha256=bx4i5YAod1nLJW1g7ETWS712Y9QVZnJ5LGiUA_Uvi-4,9228
178
178
  hatchet_sdk/clients/rest/models/v1_task_summary_list.py,sha256=0m-xf_lY9BwwbLky9i6fkTYUwh2K9mADHVZoRyF66o4,3510
179
179
  hatchet_sdk/clients/rest/models/v1_task_timing.py,sha256=ygr-r0_Mius0JDSAYIYjsXOvBByG5nxlJ0-cXOoCq7g,5969
180
180
  hatchet_sdk/clients/rest/models/v1_task_timing_list.py,sha256=1LFoKqFn11EJ_t7ZeWUFldWOWfG09tN_wTZu3a8e_SM,3509
@@ -258,7 +258,7 @@ hatchet_sdk/exceptions.py,sha256=DG-mS0wZiB-4Pnyr-BgY-LRrAEAdgP2nqQlIheU99t4,264
258
258
  hatchet_sdk/features/cron.py,sha256=k6Y-JJBPaf2Dtx-fwvNA2j7lTzHLBZpwVMA_u-p6Lvw,9723
259
259
  hatchet_sdk/features/filters.py,sha256=n6PPeRiqd5SOFlcx8V2strUaCGma9JPRAOLx44XpC0o,6443
260
260
  hatchet_sdk/features/logs.py,sha256=H_vQnOqiN5q_wQWVoOGAJp7eOPKFYZsLJ1Hb63LriRA,1190
261
- hatchet_sdk/features/metrics.py,sha256=mUz51fQsrmyp_UUoZ5KxSrOmUl2mEGoYYHRuXGxl_7w,4563
261
+ hatchet_sdk/features/metrics.py,sha256=do4kVX6cjDszHocc-IoS8BdT5ChptPc39oElbW6Cd8k,5109
262
262
  hatchet_sdk/features/rate_limits.py,sha256=eh55Z3w75cYUthqTyoWmNxj_6tN3rjebMKm3of-vxv0,2155
263
263
  hatchet_sdk/features/runs.py,sha256=8geS5l1CU3GCLudFORmCvXyjVVcgNKsNAPV9mLcI8sU,23004
264
264
  hatchet_sdk/features/scheduled.py,sha256=t7YA9CoJrzBhH82ChTSFWaTF_dyoC9i1O_wf9ywsphc,8939
@@ -283,7 +283,7 @@ hatchet_sdk/utils/backoff.py,sha256=6B5Rb5nLKw_TqqgpJMYjIBV1PTTtbOMRZCveisVhg_I,
283
283
  hatchet_sdk/utils/datetimes.py,sha256=vIZNEX8tt-bknaIuTmoLEmKVt18dBjClH3urYtCJAys,775
284
284
  hatchet_sdk/utils/opentelemetry.py,sha256=64TVwCLrUzEmcL2BUNPV_QubfiR5jajOZtVeGYLnEEA,1226
285
285
  hatchet_sdk/utils/proto_enums.py,sha256=v2gp_ZmIhPxURVXwz5lscllXwZXDl5XGXeL6gezw3o0,1241
286
- hatchet_sdk/utils/serde.py,sha256=d2iypdK2UQCPA19NgYa0Tr7CTbk25KPbaCMqcqN3CYk,1645
286
+ hatchet_sdk/utils/serde.py,sha256=YbS9rPy_kSom2G9cgYupECJrt3fbBOSbHVx6ihu7fUU,1924
287
287
  hatchet_sdk/utils/timedelta_to_expression.py,sha256=YujnBnGn7lxtkUdKIeqmOiN_ZCGBpRPjCCSzcD3jxzA,644
288
288
  hatchet_sdk/utils/typing.py,sha256=FgYnZyJSoRjNVFodxlI9gn0X8ST1KFed7xfUynIxa2U,978
289
289
  hatchet_sdk/v0/__init__.py,sha256=r3Q7l2RsLgdIkK2jjiz7-JJpD1T_Zy--Oa9MN5n_yEs,9654
@@ -514,7 +514,7 @@ hatchet_sdk/worker/runner/runner.py,sha256=Btz7wd0DQ-5aPEZLN3T5X5__8DjuxN6H4yQEV
514
514
  hatchet_sdk/worker/runner/utils/capture_logs.py,sha256=DKw6boqVsSCM1XvBWYuc833MZxCdSpMxg3l4aAqKPyw,3465
515
515
  hatchet_sdk/worker/worker.py,sha256=nDuRo_LishRuOCTnDonc7G7qeOoW93nRHGd-fQOE_bs,16541
516
516
  hatchet_sdk/workflow_run.py,sha256=KcylcqRwKADtnzOTjoiVr1vdr7qTZFtDeD5aRS6A4Y8,2823
517
- hatchet_sdk-1.14.4.dist-info/METADATA,sha256=RnI_R_0aYYdHdr5BJjxCRAlkdDyhHZjG5PU_eYx8xBs,3636
518
- hatchet_sdk-1.14.4.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
519
- hatchet_sdk-1.14.4.dist-info/entry_points.txt,sha256=Un_76pcLse-ZGBlwebhQpnTPyQrripeHW8J7qmEpGOk,1400
520
- hatchet_sdk-1.14.4.dist-info/RECORD,,
517
+ hatchet_sdk-1.15.0.dist-info/METADATA,sha256=h9GjdEJsJudw7moBNpVj-uyvJzqlT7aXBcW4NsovLmE,3636
518
+ hatchet_sdk-1.15.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
519
+ hatchet_sdk-1.15.0.dist-info/entry_points.txt,sha256=Un_76pcLse-ZGBlwebhQpnTPyQrripeHW8J7qmEpGOk,1400
520
+ hatchet_sdk-1.15.0.dist-info/RECORD,,