dex-python-sdk 0.1.10__tar.gz → 0.2.0__tar.gz
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.
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/PKG-INFO +2 -2
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/README.md +1 -1
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_grpc_errors.py +52 -2
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/async_client.py +0 -1
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/client.py +0 -1
- dex_python_sdk-0.2.0/dex/dexpb/dex_pb2.py +441 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/dexpb/dex_pb2.pyi +2 -4
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/flow_options.py +0 -2
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/pyproject.toml +1 -1
- dex_python_sdk-0.1.10/dex/dexpb/dex_pb2.py +0 -441
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/LEGACY_NOTICES.md +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/LICENSE +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/__init__.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_async_value_hydrator.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_async_worker_dispatcher.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_async_worker_service.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_invocation_context.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_native.pyi +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_utils.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_value_hydrator.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_value_mapper.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_worker_dispatcher.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/_worker_service.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/async_worker.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/attribute.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/blob_cache.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/channel.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/client_options.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/codec.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/condition.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/context.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/dexpb/__init__.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/dexpb/dex_pb2_grpc.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/flow.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/flow_config.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/flow_info.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/flow_result.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/py.typed +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/runtime_errors.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/step.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/step_execution.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/subflow.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/timer.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/wait.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/worker.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/dex/worker_options.py +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/Cargo.lock +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/Cargo.toml +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/Cargo.toml +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/LICENSE +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/src/config.rs +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/src/entry.rs +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/src/error.rs +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/src/format.rs +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/src/lib.rs +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/src/policy.rs +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/src/store.rs +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache/tests/blob_cache_integration.rs +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache-python/Cargo.toml +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache-python/LICENSE +0 -0
- {dex_python_sdk-0.1.10 → dex_python_sdk-0.2.0}/sdk-rust/crates/dex-blob-cache-python/src/lib.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dex-python-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Requires-Dist: grpcio>=1.83.0
|
|
5
5
|
Requires-Dist: grpcio-status>=1.83.0
|
|
6
6
|
Requires-Dist: protobuf>=7.35.1
|
|
@@ -193,7 +193,7 @@ options = dex.StartFlowOptions(
|
|
|
193
193
|
Register async hooks with `allow_async_handlers=True` and run them with
|
|
194
194
|
`AsyncWorker`. `FAIL` produces `FlowErrorType.FLOW_TIMEOUT` and permits Flow
|
|
195
195
|
retry; `CANCEL` cancels without retry. Continue-as-new preserves the deadline,
|
|
196
|
-
while retry
|
|
196
|
+
while retry runs receive a fresh budget. A zero or absent timeout
|
|
197
197
|
disables the feature.
|
|
198
198
|
|
|
199
199
|
`Registry` validates every Flow, Step, RPC signature, durable name, lock, and
|
|
@@ -177,7 +177,7 @@ options = dex.StartFlowOptions(
|
|
|
177
177
|
Register async hooks with `allow_async_handlers=True` and run them with
|
|
178
178
|
`AsyncWorker`. `FAIL` produces `FlowErrorType.FLOW_TIMEOUT` and permits Flow
|
|
179
179
|
retry; `CANCEL` cancels without retry. Continue-as-new preserves the deadline,
|
|
180
|
-
while retry
|
|
180
|
+
while retry runs receive a fresh budget. A zero or absent timeout
|
|
181
181
|
disables the feature.
|
|
182
182
|
|
|
183
183
|
`Registry` validates every Flow, Step, RPC signature, durable name, lock, and
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
|
+
import traceback
|
|
12
|
+
from dataclasses import dataclass
|
|
11
13
|
from typing import Any, Literal, cast
|
|
12
14
|
|
|
13
15
|
import grpc
|
|
@@ -29,6 +31,28 @@ from dex.runtime_errors import (
|
|
|
29
31
|
|
|
30
32
|
FlowTargetRequirement = Literal["none", "existing", "active"]
|
|
31
33
|
|
|
34
|
+
MAX_WORKER_STACK_TRACE_BYTES = 16 * 1024
|
|
35
|
+
_STACK_TRACE_TRUNCATION_MARKER = b"\n... stack trace truncated by Dex Python SDK ..."
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class RetryAfterError(Exception):
|
|
40
|
+
"""Requests a delay before the next retry while preserving the current failure."""
|
|
41
|
+
|
|
42
|
+
after_seconds: int
|
|
43
|
+
cause: BaseException
|
|
44
|
+
|
|
45
|
+
def __str__(self) -> str:
|
|
46
|
+
return str(self.cause)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def retry_after(after_seconds: int, cause: BaseException) -> RetryAfterError:
|
|
50
|
+
if cause is None:
|
|
51
|
+
raise ValueError("cause is required")
|
|
52
|
+
if after_seconds <= 0:
|
|
53
|
+
raise ValueError("after_seconds must be positive")
|
|
54
|
+
return RetryAfterError(after_seconds=after_seconds, cause=cause)
|
|
55
|
+
|
|
32
56
|
|
|
33
57
|
def translate_rpc_error(
|
|
34
58
|
error: grpc.RpcError,
|
|
@@ -118,11 +142,21 @@ async def async_abort_worker_error(
|
|
|
118
142
|
|
|
119
143
|
|
|
120
144
|
def _worker_error_status(error: BaseException) -> status_pb2.Status:
|
|
121
|
-
|
|
145
|
+
retry_after_error: RetryAfterError | None = None
|
|
146
|
+
reported = error
|
|
147
|
+
if isinstance(error, RetryAfterError):
|
|
148
|
+
retry_after_error = error
|
|
149
|
+
reported = error.cause
|
|
150
|
+
|
|
151
|
+
message = str(reported) or type(reported).__name__
|
|
152
|
+
stack_trace_source = error if retry_after_error is not None else reported
|
|
122
153
|
worker_error = pb.WorkerErrorResponse(
|
|
123
154
|
detail=message,
|
|
124
|
-
error_type=f"{type(
|
|
155
|
+
error_type=f"{type(reported).__module__}.{type(reported).__qualname__}",
|
|
156
|
+
stack_trace=_worker_stack_trace(stack_trace_source),
|
|
125
157
|
)
|
|
158
|
+
if retry_after_error is not None:
|
|
159
|
+
worker_error.retry_after_seconds = retry_after_error.after_seconds
|
|
126
160
|
packed = any_pb2.Any()
|
|
127
161
|
packed.Pack(worker_error)
|
|
128
162
|
return status_pb2.Status(
|
|
@@ -132,6 +166,22 @@ def _worker_error_status(error: BaseException) -> status_pb2.Status:
|
|
|
132
166
|
)
|
|
133
167
|
|
|
134
168
|
|
|
169
|
+
def _worker_stack_trace(error: BaseException) -> str:
|
|
170
|
+
if error.__traceback__ is None:
|
|
171
|
+
return ""
|
|
172
|
+
lines = traceback.format_exception(type(error), error, error.__traceback__)
|
|
173
|
+
encoded = "".join(lines).encode()
|
|
174
|
+
if len(encoded) <= MAX_WORKER_STACK_TRACE_BYTES:
|
|
175
|
+
return encoded.decode()
|
|
176
|
+
prefix_length = MAX_WORKER_STACK_TRACE_BYTES - len(_STACK_TRACE_TRUNCATION_MARKER)
|
|
177
|
+
while prefix_length > 0 and (encoded[prefix_length] & 0xC0) == 0x80:
|
|
178
|
+
prefix_length -= 1
|
|
179
|
+
return (
|
|
180
|
+
encoded[:prefix_length].decode(errors="replace")
|
|
181
|
+
+ _STACK_TRACE_TRUNCATION_MARKER.decode()
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
135
185
|
def _map_sub_status(value: int) -> ErrorSubStatus:
|
|
136
186
|
statuses: dict[int, ErrorSubStatus] = {
|
|
137
187
|
int(pb.ERROR_SUB_STATUS_UNCATEGORIZED): ErrorSubStatus.UNCATEGORIZED,
|
|
@@ -1018,7 +1018,6 @@ class AsyncClient:
|
|
|
1018
1018
|
),
|
|
1019
1019
|
IdReusePolicy.DISALLOW: pb.ID_REUSE_POLICY_DISALLOW_REUSE,
|
|
1020
1020
|
}[options.id_reuse_policy],
|
|
1021
|
-
cron_schedule=options.cron_schedule or "",
|
|
1022
1021
|
flow_already_started_options=pb.FlowAlreadyStartedOptions(
|
|
1023
1022
|
ignore_already_started_error=options.ignore_already_started
|
|
1024
1023
|
),
|
|
@@ -1019,7 +1019,6 @@ class Client:
|
|
|
1019
1019
|
),
|
|
1020
1020
|
IdReusePolicy.DISALLOW: pb.ID_REUSE_POLICY_DISALLOW_REUSE,
|
|
1021
1021
|
}[options.id_reuse_policy],
|
|
1022
|
-
cron_schedule=options.cron_schedule or "",
|
|
1023
1022
|
flow_already_started_options=pb.FlowAlreadyStartedOptions(
|
|
1024
1023
|
ignore_already_started_error=options.ignore_already_started
|
|
1025
1024
|
),
|