dex-python-sdk 0.0.2__cp311-abi3-win_amd64.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.
- dex/__init__.py +146 -0
- dex/_grpc_errors.py +73 -0
- dex/_invocation_context.py +269 -0
- dex/_native.pyd +0 -0
- dex/_native.pyi +20 -0
- dex/_utils.py +18 -0
- dex/_value_hydrator.py +223 -0
- dex/_value_mapper.py +174 -0
- dex/_worker_dispatcher.py +451 -0
- dex/_worker_service.py +60 -0
- dex/attribute.py +87 -0
- dex/blob_cache.py +73 -0
- dex/channel.py +165 -0
- dex/client.py +715 -0
- dex/client_options.py +19 -0
- dex/codec.py +286 -0
- dex/command_request.py +120 -0
- dex/command_results.py +107 -0
- dex/communication.py +136 -0
- dex/communication_schema.py +54 -0
- dex/condition.py +74 -0
- dex/context.py +86 -0
- dex/data_attributes.py +70 -0
- dex/dexpb/__init__.py +1 -0
- dex/dexpb/dex_pb2.py +381 -0
- dex/dexpb/dex_pb2.pyi +1734 -0
- dex/dexpb/dex_pb2_grpc.py +1298 -0
- dex/errors.py +109 -0
- dex/flow.py +456 -0
- dex/flow_config.py +29 -0
- dex/flow_info.py +51 -0
- dex/flow_options.py +122 -0
- dex/object_encoder.py +799 -0
- dex/persistence.py +89 -0
- dex/persistence_options.py +12 -0
- dex/persistence_schema.py +51 -0
- dex/py.typed +1 -0
- dex/registry.py +204 -0
- dex/reset_workflow_type_and_options.py +67 -0
- dex/rpc.py +93 -0
- dex/runtime_errors.py +81 -0
- dex/search_attributes.py +184 -0
- dex/state_decision.py +153 -0
- dex/state_execution_locals.py +66 -0
- dex/state_movement.py +115 -0
- dex/state_schema.py +48 -0
- dex/step.py +194 -0
- dex/step_execution.py +42 -0
- dex/stop_workflow_options.py +18 -0
- dex/tests/__init__.py +80 -0
- dex/tests/dex-service-env/.env +7 -0
- dex/tests/dex-service-env/docker-compose-init.sh +44 -0
- dex/tests/dex-service-env/docker-compose.yml +97 -0
- dex/tests/dex-service-env/dynamicconfig/README.md +39 -0
- dex/tests/dex-service-env/dynamicconfig/development-sql.yaml +9 -0
- dex/tests/dex-service-env/dynamicconfig/docker.yaml +2 -0
- dex/tests/test_abnormal_exit_workflow.py +43 -0
- dex/tests/test_basic_workflow.py +70 -0
- dex/tests/test_conditional_complete.py +50 -0
- dex/tests/test_describe_workflow.py +40 -0
- dex/tests/test_empty_data_decodes_properly.py +74 -0
- dex/tests/test_internal_channel.py +28 -0
- dex/tests/test_internal_channel_with_no_prefix_channel.py +41 -0
- dex/tests/test_persistence_data_attributes.py +62 -0
- dex/tests/test_persistence_search_attributes.py +127 -0
- dex/tests/test_persistence_state_execution_locals.py +38 -0
- dex/tests/test_rpc.py +64 -0
- dex/tests/test_rpc_with_memo.py +195 -0
- dex/tests/test_rpc_with_memo_duplicate_java_tests.py +117 -0
- dex/tests/test_signal.py +51 -0
- dex/tests/test_skip_wait_until.py +76 -0
- dex/tests/test_state_failure_recovery.py +28 -0
- dex/tests/test_timer.py +35 -0
- dex/tests/test_wait_for_state_execution_completion.py +53 -0
- dex/tests/test_workflow_errors.py +87 -0
- dex/tests/test_workflow_state_options.py +118 -0
- dex/tests/test_workflow_state_options_override.py +44 -0
- dex/tests/worker_server.py +64 -0
- dex/tests/workflows/abnormal_exit_workflow.py +42 -0
- dex/tests/workflows/basic_workflow.py +62 -0
- dex/tests/workflows/conditional_complete_workflow.py +95 -0
- dex/tests/workflows/describe_workflow.py +46 -0
- dex/tests/workflows/empty_data_workflow.py +45 -0
- dex/tests/workflows/internal_channel_workflow.py +129 -0
- dex/tests/workflows/internal_channel_workflow_with_no_prefix_channel.py +100 -0
- dex/tests/workflows/java_duplicate_rpc_memo_workflow.py +276 -0
- dex/tests/workflows/persistence_data_attributes_workflow.py +98 -0
- dex/tests/workflows/persistence_search_attributes_workflow.py +159 -0
- dex/tests/workflows/persistence_state_execution_local_workflow.py +63 -0
- dex/tests/workflows/recovery_workflow.py +82 -0
- dex/tests/workflows/rpc_memo_workflow.py +231 -0
- dex/tests/workflows/rpc_workflow.py +117 -0
- dex/tests/workflows/state_options_override_workflow.py +93 -0
- dex/tests/workflows/state_options_workflow.py +84 -0
- dex/tests/workflows/timer_workflow.py +46 -0
- dex/tests/workflows/wait_for_state_with_state_execution_id_workflow.py +70 -0
- dex/tests/workflows/wait_for_state_with_wait_for_key_workflow.py +71 -0
- dex/tests/workflows/wait_internal_channel_workflow.py +47 -0
- dex/tests/workflows/wait_signal_workflow.py +147 -0
- dex/timer.py +21 -0
- dex/type_store.py +99 -0
- dex/unregistered_client.py +585 -0
- dex/utils/__init__.py +3 -0
- dex/utils/dex_typing.py +25 -0
- dex/utils/persistence_utils.py +32 -0
- dex/wait.py +49 -0
- dex/worker.py +121 -0
- dex/worker_options.py +22 -0
- dex/worker_service.py +432 -0
- dex/workflow.py +79 -0
- dex/workflow_context.py +44 -0
- dex/workflow_info.py +16 -0
- dex/workflow_options.py +74 -0
- dex/workflow_state.py +123 -0
- dex/workflow_state_options.py +154 -0
- dex_python_sdk-0.0.2.dist-info/METADATA +202 -0
- dex_python_sdk-0.0.2.dist-info/RECORD +121 -0
- dex_python_sdk-0.0.2.dist-info/WHEEL +4 -0
- dex_python_sdk-0.0.2.dist-info/licenses/LEGACY_NOTICES.md +61 -0
- dex_python_sdk-0.0.2.dist-info/licenses/LICENSE +192 -0
- dex_python_sdk-0.0.2.dist-info/sboms/dex-blob-cache-python.cyclonedx.json +2406 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Legacy Materials in this file remain under their original licenses.
|
|
2
|
+
# See LEGACY_NOTICES.md.
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import List, Optional, Union
|
|
7
|
+
|
|
8
|
+
class CommunicationMethodType(Enum):
|
|
9
|
+
SignalChannel = 1
|
|
10
|
+
InternalChannel = 2
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class CommunicationMethod:
|
|
14
|
+
name: str
|
|
15
|
+
method_type: CommunicationMethodType
|
|
16
|
+
value_type: Optional[type]
|
|
17
|
+
is_prefix: bool
|
|
18
|
+
|
|
19
|
+
@classmethod
|
|
20
|
+
def signal_channel_def(cls, name: str, value_type: Union[type, None]):
|
|
21
|
+
return CommunicationMethod(
|
|
22
|
+
name,
|
|
23
|
+
CommunicationMethodType.SignalChannel,
|
|
24
|
+
value_type if value_type is not None else type(None),
|
|
25
|
+
False,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def internal_channel_def(cls, name: str, value_type: Union[type, None]):
|
|
30
|
+
return CommunicationMethod(
|
|
31
|
+
name,
|
|
32
|
+
CommunicationMethodType.InternalChannel,
|
|
33
|
+
value_type if value_type is not None else type(None),
|
|
34
|
+
False,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def internal_channel_def_by_prefix(
|
|
39
|
+
cls, name_prefix: str, value_type: Union[type, None]
|
|
40
|
+
):
|
|
41
|
+
return CommunicationMethod(
|
|
42
|
+
name_prefix,
|
|
43
|
+
CommunicationMethodType.InternalChannel,
|
|
44
|
+
value_type if value_type is not None else type(None),
|
|
45
|
+
True,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
@dataclass
|
|
49
|
+
class CommunicationSchema:
|
|
50
|
+
communication_methods: List[CommunicationMethod] = field(default_factory=list)
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def create(cls, *methods: CommunicationMethod):
|
|
54
|
+
return CommunicationSchema(list(methods))
|
dex/condition.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Legacy Materials in this file remain under their original licenses.
|
|
2
|
+
# See LEGACY_NOTICES.md.
|
|
3
|
+
|
|
4
|
+
# Modifications Copyright (c) 2026 Super Durable, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Modifications after the Legacy Cutoff are licensed under the
|
|
7
|
+
# Super Durable Source License 1.0.
|
|
8
|
+
# Legacy Materials remain under their original licenses.
|
|
9
|
+
# See LICENSE and LEGACY_NOTICES.md.
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from datetime import timedelta
|
|
15
|
+
from typing import TYPE_CHECKING, Generic, TypeVar
|
|
16
|
+
|
|
17
|
+
from dex._utils import validate_condition_id
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from dex.channel import Channel, ChannelMap
|
|
21
|
+
|
|
22
|
+
ValueT = TypeVar("ValueT")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class Condition:
|
|
27
|
+
condition_id: str | None = None
|
|
28
|
+
|
|
29
|
+
def __post_init__(self) -> None:
|
|
30
|
+
validate_condition_id(self.condition_id)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class TimerCondition(Condition):
|
|
35
|
+
duration: timedelta = timedelta(0)
|
|
36
|
+
|
|
37
|
+
def __post_init__(self) -> None:
|
|
38
|
+
super().__post_init__()
|
|
39
|
+
if self.duration < timedelta(0):
|
|
40
|
+
raise ValueError("timer duration must not be negative")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True)
|
|
44
|
+
class ChannelCondition(Condition, Generic[ValueT]):
|
|
45
|
+
channel: Channel[ValueT] | ChannelMap[ValueT] | None = None
|
|
46
|
+
instance: str | None = None
|
|
47
|
+
at_least: int | None = None
|
|
48
|
+
at_most: int | None = None
|
|
49
|
+
|
|
50
|
+
def __post_init__(self) -> None:
|
|
51
|
+
super().__post_init__()
|
|
52
|
+
if self.channel is None:
|
|
53
|
+
raise ValueError("channel condition requires a channel")
|
|
54
|
+
if self.at_least is None and self.at_most is None:
|
|
55
|
+
raise ValueError("channel condition requires a bound")
|
|
56
|
+
if self.at_least is not None and self.at_least < 0:
|
|
57
|
+
raise ValueError("at_least must not be negative")
|
|
58
|
+
if self.at_most is not None and self.at_most < 0:
|
|
59
|
+
raise ValueError("at_most must not be negative")
|
|
60
|
+
if (
|
|
61
|
+
self.at_least is not None
|
|
62
|
+
and self.at_most is not None
|
|
63
|
+
and self.at_most < self.at_least
|
|
64
|
+
):
|
|
65
|
+
raise ValueError("at_most must not be below at_least")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass(frozen=True)
|
|
69
|
+
class ConditionCombination:
|
|
70
|
+
conditions: tuple[Condition, ...]
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def of(*conditions: Condition) -> ConditionCombination:
|
|
74
|
+
return ConditionCombination(conditions)
|
dex/context.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Legacy Materials in this file remain under their original licenses.
|
|
2
|
+
# See LEGACY_NOTICES.md.
|
|
3
|
+
|
|
4
|
+
# Modifications Copyright (c) 2026 Super Durable, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Modifications after the Legacy Cutoff are licensed under the
|
|
7
|
+
# Super Durable Source License 1.0.
|
|
8
|
+
# Legacy Materials remain under their original licenses.
|
|
9
|
+
# See LICENSE and LEGACY_NOTICES.md.
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import TYPE_CHECKING, Protocol, Sequence, TypeVar
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from dex.attribute import Attribute, AttributeMap
|
|
17
|
+
from dex.channel import Channel, ChannelMap
|
|
18
|
+
|
|
19
|
+
ValueT = TypeVar("ValueT")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Context(Protocol):
|
|
23
|
+
@property
|
|
24
|
+
def flow_id(self) -> str: ...
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def run_id(self) -> str: ...
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def step_execution_id(self) -> str: ...
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def from_step_execution_id(self) -> str: ...
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def attempt(self) -> int: ...
|
|
37
|
+
|
|
38
|
+
def has_timer_fired(self, index: int | None = None) -> bool: ...
|
|
39
|
+
|
|
40
|
+
def wait_for_method_failed(self) -> bool: ...
|
|
41
|
+
|
|
42
|
+
def set_step_execution_local(self, key: str, value: object) -> None: ...
|
|
43
|
+
|
|
44
|
+
def get_step_execution_local(
|
|
45
|
+
self, key: str, value_type: type[ValueT]
|
|
46
|
+
) -> ValueT | None: ...
|
|
47
|
+
|
|
48
|
+
def record_event(self, name: str, value: object) -> None: ...
|
|
49
|
+
|
|
50
|
+
def _get_attribute(
|
|
51
|
+
self,
|
|
52
|
+
definition: Attribute[ValueT] | AttributeMap[ValueT],
|
|
53
|
+
instance: str | None,
|
|
54
|
+
) -> ValueT: ...
|
|
55
|
+
|
|
56
|
+
def _set_attribute(
|
|
57
|
+
self,
|
|
58
|
+
definition: Attribute[ValueT] | AttributeMap[ValueT],
|
|
59
|
+
instance: str | None,
|
|
60
|
+
value: ValueT,
|
|
61
|
+
) -> None: ...
|
|
62
|
+
|
|
63
|
+
def _delete_attribute(
|
|
64
|
+
self,
|
|
65
|
+
definition: Attribute[object] | AttributeMap[object],
|
|
66
|
+
instance: str | None,
|
|
67
|
+
) -> None: ...
|
|
68
|
+
|
|
69
|
+
def _publish_channel(
|
|
70
|
+
self,
|
|
71
|
+
definition: Channel[ValueT] | ChannelMap[ValueT],
|
|
72
|
+
instance: str | None,
|
|
73
|
+
value: ValueT,
|
|
74
|
+
) -> None: ...
|
|
75
|
+
|
|
76
|
+
def _channel_size(
|
|
77
|
+
self,
|
|
78
|
+
definition: Channel[object] | ChannelMap[object],
|
|
79
|
+
instance: str | None,
|
|
80
|
+
) -> int: ...
|
|
81
|
+
|
|
82
|
+
def _channel_results(
|
|
83
|
+
self,
|
|
84
|
+
definition: Channel[ValueT] | ChannelMap[ValueT],
|
|
85
|
+
instance: str | None,
|
|
86
|
+
) -> Sequence[ValueT]: ...
|
dex/data_attributes.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Legacy Materials in this file remain under their original licenses.
|
|
2
|
+
# See LEGACY_NOTICES.md.
|
|
3
|
+
|
|
4
|
+
# Modifications Copyright (c) 2026 Super Durable, Inc.
|
|
5
|
+
#
|
|
6
|
+
# Modifications after the Legacy Cutoff are licensed under the
|
|
7
|
+
# Super Durable Source License 1.0.
|
|
8
|
+
# Legacy Materials remain under their original licenses.
|
|
9
|
+
# See LICENSE and LEGACY_NOTICES.md.
|
|
10
|
+
|
|
11
|
+
from typing import Any, Union
|
|
12
|
+
|
|
13
|
+
from dex.errors import WorkflowDefinitionError
|
|
14
|
+
from dex.dex_api.models import EncodedObject
|
|
15
|
+
from dex.dex_api.types import Unset
|
|
16
|
+
from dex.object_encoder import ObjectEncoder
|
|
17
|
+
from dex.type_store import TypeStore
|
|
18
|
+
|
|
19
|
+
class DataAttributes:
|
|
20
|
+
_type_store: TypeStore
|
|
21
|
+
_object_encoder: ObjectEncoder
|
|
22
|
+
_current_values: dict[str, Union[EncodedObject, None, Unset]]
|
|
23
|
+
_updated_values_to_return: dict[str, Union[EncodedObject, Unset]]
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
type_store: TypeStore,
|
|
28
|
+
object_encoder: ObjectEncoder,
|
|
29
|
+
current_values: dict[str, Union[EncodedObject, None, Unset]],
|
|
30
|
+
):
|
|
31
|
+
self._object_encoder = object_encoder
|
|
32
|
+
self._type_store = type_store
|
|
33
|
+
self._current_values = current_values
|
|
34
|
+
self._updated_values_to_return = {}
|
|
35
|
+
|
|
36
|
+
def get_data_attribute(self, key: str) -> Any:
|
|
37
|
+
is_registered = self._type_store.is_valid_name_or_prefix(key)
|
|
38
|
+
if not is_registered:
|
|
39
|
+
raise WorkflowDefinitionError(f"data attribute %s is not registered {key}")
|
|
40
|
+
|
|
41
|
+
encoded_object = self._current_values.get(key)
|
|
42
|
+
if encoded_object is None:
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
registered_type = self._type_store.get_type(key)
|
|
46
|
+
return self._object_encoder.decode(encoded_object, registered_type)
|
|
47
|
+
|
|
48
|
+
def set_data_attribute(self, key: str, value: Any):
|
|
49
|
+
is_registered = self._type_store.is_valid_name_or_prefix(key)
|
|
50
|
+
if not is_registered:
|
|
51
|
+
raise WorkflowDefinitionError(
|
|
52
|
+
f"data attribute {key} is not registered {key}"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
registered_type = self._type_store.get_type(key)
|
|
56
|
+
if (
|
|
57
|
+
value is not None
|
|
58
|
+
and registered_type is not None
|
|
59
|
+
and not isinstance(value, registered_type)
|
|
60
|
+
):
|
|
61
|
+
raise WorkflowDefinitionError(
|
|
62
|
+
f"data attribute {key} is of the right type {registered_type}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
encoded_value = self._object_encoder.encode(value)
|
|
66
|
+
self._current_values[key] = encoded_value
|
|
67
|
+
self._updated_values_to_return[key] = encoded_value
|
|
68
|
+
|
|
69
|
+
def get_updated_values_to_return(self) -> dict[str, Union[EncodedObject, Unset]]:
|
|
70
|
+
return self._updated_values_to_return
|
dex/dexpb/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Generated package for Dex protobuf stubs.
|