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.
Files changed (121) hide show
  1. dex/__init__.py +146 -0
  2. dex/_grpc_errors.py +73 -0
  3. dex/_invocation_context.py +269 -0
  4. dex/_native.pyd +0 -0
  5. dex/_native.pyi +20 -0
  6. dex/_utils.py +18 -0
  7. dex/_value_hydrator.py +223 -0
  8. dex/_value_mapper.py +174 -0
  9. dex/_worker_dispatcher.py +451 -0
  10. dex/_worker_service.py +60 -0
  11. dex/attribute.py +87 -0
  12. dex/blob_cache.py +73 -0
  13. dex/channel.py +165 -0
  14. dex/client.py +715 -0
  15. dex/client_options.py +19 -0
  16. dex/codec.py +286 -0
  17. dex/command_request.py +120 -0
  18. dex/command_results.py +107 -0
  19. dex/communication.py +136 -0
  20. dex/communication_schema.py +54 -0
  21. dex/condition.py +74 -0
  22. dex/context.py +86 -0
  23. dex/data_attributes.py +70 -0
  24. dex/dexpb/__init__.py +1 -0
  25. dex/dexpb/dex_pb2.py +381 -0
  26. dex/dexpb/dex_pb2.pyi +1734 -0
  27. dex/dexpb/dex_pb2_grpc.py +1298 -0
  28. dex/errors.py +109 -0
  29. dex/flow.py +456 -0
  30. dex/flow_config.py +29 -0
  31. dex/flow_info.py +51 -0
  32. dex/flow_options.py +122 -0
  33. dex/object_encoder.py +799 -0
  34. dex/persistence.py +89 -0
  35. dex/persistence_options.py +12 -0
  36. dex/persistence_schema.py +51 -0
  37. dex/py.typed +1 -0
  38. dex/registry.py +204 -0
  39. dex/reset_workflow_type_and_options.py +67 -0
  40. dex/rpc.py +93 -0
  41. dex/runtime_errors.py +81 -0
  42. dex/search_attributes.py +184 -0
  43. dex/state_decision.py +153 -0
  44. dex/state_execution_locals.py +66 -0
  45. dex/state_movement.py +115 -0
  46. dex/state_schema.py +48 -0
  47. dex/step.py +194 -0
  48. dex/step_execution.py +42 -0
  49. dex/stop_workflow_options.py +18 -0
  50. dex/tests/__init__.py +80 -0
  51. dex/tests/dex-service-env/.env +7 -0
  52. dex/tests/dex-service-env/docker-compose-init.sh +44 -0
  53. dex/tests/dex-service-env/docker-compose.yml +97 -0
  54. dex/tests/dex-service-env/dynamicconfig/README.md +39 -0
  55. dex/tests/dex-service-env/dynamicconfig/development-sql.yaml +9 -0
  56. dex/tests/dex-service-env/dynamicconfig/docker.yaml +2 -0
  57. dex/tests/test_abnormal_exit_workflow.py +43 -0
  58. dex/tests/test_basic_workflow.py +70 -0
  59. dex/tests/test_conditional_complete.py +50 -0
  60. dex/tests/test_describe_workflow.py +40 -0
  61. dex/tests/test_empty_data_decodes_properly.py +74 -0
  62. dex/tests/test_internal_channel.py +28 -0
  63. dex/tests/test_internal_channel_with_no_prefix_channel.py +41 -0
  64. dex/tests/test_persistence_data_attributes.py +62 -0
  65. dex/tests/test_persistence_search_attributes.py +127 -0
  66. dex/tests/test_persistence_state_execution_locals.py +38 -0
  67. dex/tests/test_rpc.py +64 -0
  68. dex/tests/test_rpc_with_memo.py +195 -0
  69. dex/tests/test_rpc_with_memo_duplicate_java_tests.py +117 -0
  70. dex/tests/test_signal.py +51 -0
  71. dex/tests/test_skip_wait_until.py +76 -0
  72. dex/tests/test_state_failure_recovery.py +28 -0
  73. dex/tests/test_timer.py +35 -0
  74. dex/tests/test_wait_for_state_execution_completion.py +53 -0
  75. dex/tests/test_workflow_errors.py +87 -0
  76. dex/tests/test_workflow_state_options.py +118 -0
  77. dex/tests/test_workflow_state_options_override.py +44 -0
  78. dex/tests/worker_server.py +64 -0
  79. dex/tests/workflows/abnormal_exit_workflow.py +42 -0
  80. dex/tests/workflows/basic_workflow.py +62 -0
  81. dex/tests/workflows/conditional_complete_workflow.py +95 -0
  82. dex/tests/workflows/describe_workflow.py +46 -0
  83. dex/tests/workflows/empty_data_workflow.py +45 -0
  84. dex/tests/workflows/internal_channel_workflow.py +129 -0
  85. dex/tests/workflows/internal_channel_workflow_with_no_prefix_channel.py +100 -0
  86. dex/tests/workflows/java_duplicate_rpc_memo_workflow.py +276 -0
  87. dex/tests/workflows/persistence_data_attributes_workflow.py +98 -0
  88. dex/tests/workflows/persistence_search_attributes_workflow.py +159 -0
  89. dex/tests/workflows/persistence_state_execution_local_workflow.py +63 -0
  90. dex/tests/workflows/recovery_workflow.py +82 -0
  91. dex/tests/workflows/rpc_memo_workflow.py +231 -0
  92. dex/tests/workflows/rpc_workflow.py +117 -0
  93. dex/tests/workflows/state_options_override_workflow.py +93 -0
  94. dex/tests/workflows/state_options_workflow.py +84 -0
  95. dex/tests/workflows/timer_workflow.py +46 -0
  96. dex/tests/workflows/wait_for_state_with_state_execution_id_workflow.py +70 -0
  97. dex/tests/workflows/wait_for_state_with_wait_for_key_workflow.py +71 -0
  98. dex/tests/workflows/wait_internal_channel_workflow.py +47 -0
  99. dex/tests/workflows/wait_signal_workflow.py +147 -0
  100. dex/timer.py +21 -0
  101. dex/type_store.py +99 -0
  102. dex/unregistered_client.py +585 -0
  103. dex/utils/__init__.py +3 -0
  104. dex/utils/dex_typing.py +25 -0
  105. dex/utils/persistence_utils.py +32 -0
  106. dex/wait.py +49 -0
  107. dex/worker.py +121 -0
  108. dex/worker_options.py +22 -0
  109. dex/worker_service.py +432 -0
  110. dex/workflow.py +79 -0
  111. dex/workflow_context.py +44 -0
  112. dex/workflow_info.py +16 -0
  113. dex/workflow_options.py +74 -0
  114. dex/workflow_state.py +123 -0
  115. dex/workflow_state_options.py +154 -0
  116. dex_python_sdk-0.0.2.dist-info/METADATA +202 -0
  117. dex_python_sdk-0.0.2.dist-info/RECORD +121 -0
  118. dex_python_sdk-0.0.2.dist-info/WHEEL +4 -0
  119. dex_python_sdk-0.0.2.dist-info/licenses/LEGACY_NOTICES.md +61 -0
  120. dex_python_sdk-0.0.2.dist-info/licenses/LICENSE +192 -0
  121. 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.