dex-python-sdk 0.0.1__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 (93) hide show
  1. dex/__init__.py +14 -0
  2. dex/client.py +568 -0
  3. dex/client_options.py +34 -0
  4. dex/command_request.py +130 -0
  5. dex/command_results.py +116 -0
  6. dex/communication.py +141 -0
  7. dex/communication_schema.py +68 -0
  8. dex/data_attributes.py +75 -0
  9. dex/dexpb/__init__.py +1 -0
  10. dex/dexpb/dex_pb2.py +305 -0
  11. dex/dexpb/dex_pb2.pyi +1273 -0
  12. dex/dexpb/dex_pb2_grpc.py +1126 -0
  13. dex/errors.py +132 -0
  14. dex/object_encoder.py +818 -0
  15. dex/persistence.py +94 -0
  16. dex/persistence_options.py +24 -0
  17. dex/persistence_schema.py +58 -0
  18. dex/py.typed +1 -0
  19. dex/registry.py +209 -0
  20. dex/reset_workflow_type_and_options.py +77 -0
  21. dex/rpc.py +100 -0
  22. dex/search_attributes.py +189 -0
  23. dex/state_decision.py +161 -0
  24. dex/state_execution_locals.py +71 -0
  25. dex/state_movement.py +123 -0
  26. dex/state_schema.py +54 -0
  27. dex/stop_workflow_options.py +23 -0
  28. dex/tests/__init__.py +84 -0
  29. dex/tests/dex-service-env/.env +7 -0
  30. dex/tests/dex-service-env/docker-compose-init.sh +44 -0
  31. dex/tests/dex-service-env/docker-compose.yml +87 -0
  32. dex/tests/dex-service-env/dynamicconfig/README.md +39 -0
  33. dex/tests/dex-service-env/dynamicconfig/development-sql.yaml +6 -0
  34. dex/tests/dex-service-env/dynamicconfig/docker.yaml +0 -0
  35. dex/tests/test_abnormal_exit_workflow.py +48 -0
  36. dex/tests/test_basic_workflow.py +75 -0
  37. dex/tests/test_conditional_complete.py +56 -0
  38. dex/tests/test_describe_workflow.py +45 -0
  39. dex/tests/test_empty_data_decodes_properly.py +79 -0
  40. dex/tests/test_internal_channel.py +33 -0
  41. dex/tests/test_internal_channel_with_no_prefix_channel.py +46 -0
  42. dex/tests/test_persistence_data_attributes.py +67 -0
  43. dex/tests/test_persistence_search_attributes.py +132 -0
  44. dex/tests/test_persistence_state_execution_locals.py +43 -0
  45. dex/tests/test_rpc.py +69 -0
  46. dex/tests/test_rpc_with_memo.py +200 -0
  47. dex/tests/test_rpc_with_memo_duplicate_java_tests.py +122 -0
  48. dex/tests/test_signal.py +56 -0
  49. dex/tests/test_skip_wait_until.py +85 -0
  50. dex/tests/test_state_failure_recovery.py +33 -0
  51. dex/tests/test_timer.py +40 -0
  52. dex/tests/test_wait_for_state_execution_completion.py +58 -0
  53. dex/tests/test_workflow_errors.py +92 -0
  54. dex/tests/test_workflow_state_options.py +123 -0
  55. dex/tests/test_workflow_state_options_override.py +49 -0
  56. dex/tests/worker_server.py +74 -0
  57. dex/tests/workflows/abnormal_exit_workflow.py +48 -0
  58. dex/tests/workflows/basic_workflow.py +69 -0
  59. dex/tests/workflows/conditional_complete_workflow.py +101 -0
  60. dex/tests/workflows/describe_workflow.py +52 -0
  61. dex/tests/workflows/empty_data_workflow.py +51 -0
  62. dex/tests/workflows/internal_channel_workflow.py +137 -0
  63. dex/tests/workflows/internal_channel_workflow_with_no_prefix_channel.py +108 -0
  64. dex/tests/workflows/java_duplicate_rpc_memo_workflow.py +285 -0
  65. dex/tests/workflows/persistence_data_attributes_workflow.py +104 -0
  66. dex/tests/workflows/persistence_search_attributes_workflow.py +167 -0
  67. dex/tests/workflows/persistence_state_execution_local_workflow.py +69 -0
  68. dex/tests/workflows/recovery_workflow.py +90 -0
  69. dex/tests/workflows/rpc_memo_workflow.py +238 -0
  70. dex/tests/workflows/rpc_workflow.py +125 -0
  71. dex/tests/workflows/state_options_override_workflow.py +100 -0
  72. dex/tests/workflows/state_options_workflow.py +92 -0
  73. dex/tests/workflows/timer_workflow.py +52 -0
  74. dex/tests/workflows/wait_for_state_with_state_execution_id_workflow.py +77 -0
  75. dex/tests/workflows/wait_for_state_with_wait_for_key_workflow.py +78 -0
  76. dex/tests/workflows/wait_internal_channel_workflow.py +53 -0
  77. dex/tests/workflows/wait_signal_workflow.py +154 -0
  78. dex/type_store.py +105 -0
  79. dex/unregistered_client.py +595 -0
  80. dex/utils/__init__.py +14 -0
  81. dex/utils/dex_typing.py +31 -0
  82. dex/utils/persistence_utils.py +37 -0
  83. dex/worker_service.py +441 -0
  84. dex/workflow.py +86 -0
  85. dex/workflow_context.py +50 -0
  86. dex/workflow_info.py +21 -0
  87. dex/workflow_options.py +79 -0
  88. dex/workflow_state.py +134 -0
  89. dex/workflow_state_options.py +160 -0
  90. dex_python_sdk-0.0.1.dist-info/METADATA +140 -0
  91. dex_python_sdk-0.0.1.dist-info/RECORD +93 -0
  92. dex_python_sdk-0.0.1.dist-info/WHEEL +4 -0
  93. dex_python_sdk-0.0.1.dist-info/licenses/LICENSE +201 -0
dex/errors.py ADDED
@@ -0,0 +1,132 @@
1
+ # Copyright (c) 2022-2026 Super Durable, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import json as jsonlib
16
+ from httpx import Response
17
+
18
+ from dex.dex_api.models import (
19
+ ErrorResponse,
20
+ ErrorSubStatus,
21
+ WorkflowGetResponse,
22
+ WorkflowStatus,
23
+ )
24
+
25
+
26
+ class WorkflowDefinitionError(Exception):
27
+ pass
28
+
29
+
30
+ class InvalidArgumentError(Exception):
31
+ pass
32
+
33
+
34
+ class NotRegisteredError(Exception):
35
+ pass
36
+
37
+
38
+ class HttpError(RuntimeError):
39
+ def __init__(self, status: int, err_resp: ErrorResponse):
40
+ super().__init__(err_resp.detail)
41
+ self.sub_status = err_resp.sub_status
42
+ self.error_resp = err_resp
43
+ self.status = status
44
+
45
+
46
+ class ClientSideError(HttpError):
47
+ pass
48
+
49
+
50
+ class ServerSideError(HttpError):
51
+ pass
52
+
53
+
54
+ class WorkflowStillRunningError(ClientSideError):
55
+ pass
56
+
57
+
58
+ class WorkflowRPCExecutionError(ClientSideError):
59
+ pass
60
+
61
+
62
+ class WorkflowRPCAcquiringLockFailure(ClientSideError):
63
+ pass
64
+
65
+
66
+ class WorkflowAlreadyStartedError(ClientSideError):
67
+ pass
68
+
69
+
70
+ class WorkflowNotExistsError(ClientSideError):
71
+ pass
72
+
73
+
74
+ def process_http_error(status: int, err_resp: ErrorResponse) -> HttpError:
75
+ if 400 <= status < 500:
76
+ if err_resp.sub_status == ErrorSubStatus.WORKFLOW_ALREADY_STARTED_SUB_STATUS:
77
+ return WorkflowAlreadyStartedError(status, err_resp)
78
+ elif err_resp.sub_status == ErrorSubStatus.WORKFLOW_NOT_EXISTS_SUB_STATUS:
79
+ return WorkflowNotExistsError(status, err_resp)
80
+ else:
81
+ return ClientSideError(status, err_resp)
82
+ else:
83
+ return ServerSideError(status, err_resp)
84
+
85
+
86
+ class WorkflowAbnormalExitError(RuntimeError):
87
+ def __init__(self, get_response: WorkflowGetResponse):
88
+ self.run_id = get_response.workflow_run_id
89
+ self.workflow_status = get_response.workflow_status
90
+ self.error_type = get_response.error_type
91
+ self.error_message = get_response.error_message
92
+ # TODO add methods to decode the state results into objects
93
+ self._state_results = get_response.results
94
+
95
+
96
+ class WorkflowFailed(WorkflowAbnormalExitError):
97
+ pass
98
+
99
+
100
+ class WorkflowTimeout(WorkflowAbnormalExitError):
101
+ pass
102
+
103
+
104
+ class WorkflowTerminated(WorkflowAbnormalExitError):
105
+ pass
106
+
107
+
108
+ class WorkflowCanceled(WorkflowAbnormalExitError):
109
+ pass
110
+
111
+
112
+ def process_workflow_abnormal_exit_error(
113
+ get_response: WorkflowGetResponse,
114
+ ) -> WorkflowAbnormalExitError:
115
+ status = get_response.workflow_status
116
+ if status == WorkflowStatus.CANCELED:
117
+ return WorkflowCanceled(get_response)
118
+ elif status == WorkflowStatus.FAILED:
119
+ return WorkflowFailed(get_response)
120
+ elif status == WorkflowStatus.TERMINATED:
121
+ return WorkflowTerminated(get_response)
122
+ elif status == WorkflowStatus.TIMEOUT:
123
+ return WorkflowTimeout(get_response)
124
+ return WorkflowAbnormalExitError(get_response)
125
+
126
+
127
+ def parse_unexpected_error(err) -> ErrorResponse:
128
+ try:
129
+ response = Response(err.status_code, content=err.content)
130
+ return ErrorResponse.from_dict(response.json())
131
+ except Exception:
132
+ return ErrorResponse.from_dict(jsonlib.loads(err.content))