azure-functions-durable 1.2.9__py3-none-any.whl → 1.3.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.
Files changed (104) hide show
  1. azure/durable_functions/__init__.py +81 -81
  2. azure/durable_functions/constants.py +9 -9
  3. azure/durable_functions/decorators/__init__.py +3 -3
  4. azure/durable_functions/decorators/durable_app.py +260 -249
  5. azure/durable_functions/decorators/metadata.py +109 -109
  6. azure/durable_functions/entity.py +129 -125
  7. azure/durable_functions/models/DurableEntityContext.py +201 -201
  8. azure/durable_functions/models/DurableHttpRequest.py +58 -58
  9. azure/durable_functions/models/DurableOrchestrationBindings.py +66 -66
  10. azure/durable_functions/models/DurableOrchestrationClient.py +812 -781
  11. azure/durable_functions/models/DurableOrchestrationContext.py +761 -707
  12. azure/durable_functions/models/DurableOrchestrationStatus.py +156 -156
  13. azure/durable_functions/models/EntityStateResponse.py +23 -23
  14. azure/durable_functions/models/FunctionContext.py +7 -7
  15. azure/durable_functions/models/OrchestrationRuntimeStatus.py +32 -32
  16. azure/durable_functions/models/OrchestratorState.py +117 -116
  17. azure/durable_functions/models/PurgeHistoryResult.py +33 -33
  18. azure/durable_functions/models/ReplaySchema.py +9 -8
  19. azure/durable_functions/models/RetryOptions.py +69 -69
  20. azure/durable_functions/models/RpcManagementOptions.py +86 -86
  21. azure/durable_functions/models/Task.py +540 -426
  22. azure/durable_functions/models/TaskOrchestrationExecutor.py +352 -336
  23. azure/durable_functions/models/TokenSource.py +56 -56
  24. azure/durable_functions/models/__init__.py +26 -24
  25. azure/durable_functions/models/actions/Action.py +23 -23
  26. azure/durable_functions/models/actions/ActionType.py +18 -18
  27. azure/durable_functions/models/actions/CallActivityAction.py +41 -41
  28. azure/durable_functions/models/actions/CallActivityWithRetryAction.py +45 -45
  29. azure/durable_functions/models/actions/CallEntityAction.py +46 -46
  30. azure/durable_functions/models/actions/CallHttpAction.py +35 -35
  31. azure/durable_functions/models/actions/CallSubOrchestratorAction.py +40 -40
  32. azure/durable_functions/models/actions/CallSubOrchestratorWithRetryAction.py +44 -44
  33. azure/durable_functions/models/actions/CompoundAction.py +35 -35
  34. azure/durable_functions/models/actions/ContinueAsNewAction.py +36 -36
  35. azure/durable_functions/models/actions/CreateTimerAction.py +48 -48
  36. azure/durable_functions/models/actions/NoOpAction.py +35 -35
  37. azure/durable_functions/models/actions/SignalEntityAction.py +47 -47
  38. azure/durable_functions/models/actions/WaitForExternalEventAction.py +63 -63
  39. azure/durable_functions/models/actions/WhenAllAction.py +14 -14
  40. azure/durable_functions/models/actions/WhenAnyAction.py +14 -14
  41. azure/durable_functions/models/actions/__init__.py +24 -24
  42. azure/durable_functions/models/entities/EntityState.py +74 -74
  43. azure/durable_functions/models/entities/OperationResult.py +94 -76
  44. azure/durable_functions/models/entities/RequestMessage.py +53 -53
  45. azure/durable_functions/models/entities/ResponseMessage.py +48 -48
  46. azure/durable_functions/models/entities/Signal.py +62 -62
  47. azure/durable_functions/models/entities/__init__.py +17 -17
  48. azure/durable_functions/models/history/HistoryEvent.py +92 -92
  49. azure/durable_functions/models/history/HistoryEventType.py +27 -27
  50. azure/durable_functions/models/history/__init__.py +8 -8
  51. azure/durable_functions/models/utils/__init__.py +7 -7
  52. azure/durable_functions/models/utils/entity_utils.py +103 -91
  53. azure/durable_functions/models/utils/http_utils.py +80 -69
  54. azure/durable_functions/models/utils/json_utils.py +96 -56
  55. azure/durable_functions/orchestrator.py +73 -71
  56. azure/durable_functions/testing/OrchestratorGeneratorWrapper.py +42 -0
  57. azure/durable_functions/testing/__init__.py +6 -0
  58. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/LICENSE +21 -21
  59. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/METADATA +59 -58
  60. azure_functions_durable-1.3.0.dist-info/RECORD +103 -0
  61. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/WHEEL +1 -1
  62. tests/models/test_DecoratorMetadata.py +135 -135
  63. tests/models/test_Decorators.py +107 -107
  64. tests/models/test_DurableOrchestrationBindings.py +68 -68
  65. tests/models/test_DurableOrchestrationClient.py +730 -730
  66. tests/models/test_DurableOrchestrationContext.py +102 -102
  67. tests/models/test_DurableOrchestrationStatus.py +59 -59
  68. tests/models/test_OrchestrationState.py +28 -28
  69. tests/models/test_RpcManagementOptions.py +79 -79
  70. tests/models/test_TokenSource.py +10 -10
  71. tests/orchestrator/models/OrchestrationInstance.py +18 -18
  72. tests/orchestrator/orchestrator_test_utils.py +130 -130
  73. tests/orchestrator/schemas/OrchetrationStateSchema.py +66 -66
  74. tests/orchestrator/test_call_http.py +235 -176
  75. tests/orchestrator/test_continue_as_new.py +67 -67
  76. tests/orchestrator/test_create_timer.py +126 -126
  77. tests/orchestrator/test_entity.py +397 -395
  78. tests/orchestrator/test_external_event.py +53 -53
  79. tests/orchestrator/test_fan_out_fan_in.py +175 -175
  80. tests/orchestrator/test_is_replaying_flag.py +101 -101
  81. tests/orchestrator/test_retries.py +308 -308
  82. tests/orchestrator/test_sequential_orchestrator.py +841 -841
  83. tests/orchestrator/test_sequential_orchestrator_custom_status.py +119 -119
  84. tests/orchestrator/test_sequential_orchestrator_with_retry.py +465 -465
  85. tests/orchestrator/test_serialization.py +30 -30
  86. tests/orchestrator/test_sub_orchestrator.py +95 -95
  87. tests/orchestrator/test_sub_orchestrator_with_retry.py +129 -129
  88. tests/orchestrator/test_task_any.py +60 -60
  89. tests/tasks/tasks_test_utils.py +17 -17
  90. tests/tasks/test_long_timers.py +70 -0
  91. tests/tasks/test_new_uuid.py +34 -34
  92. tests/test_utils/ContextBuilder.py +174 -174
  93. tests/test_utils/EntityContextBuilder.py +56 -56
  94. tests/test_utils/constants.py +1 -1
  95. tests/test_utils/json_utils.py +30 -30
  96. tests/test_utils/testClasses.py +56 -56
  97. tests/utils/__init__.py +1 -0
  98. tests/utils/test_entity_utils.py +24 -0
  99. azure_functions_durable-1.2.9.data/data/_manifest/bsi.json +0 -1
  100. azure_functions_durable-1.2.9.data/data/_manifest/manifest.cat +0 -0
  101. azure_functions_durable-1.2.9.data/data/_manifest/manifest.spdx.json +0 -11985
  102. azure_functions_durable-1.2.9.data/data/_manifest/manifest.spdx.json.sha256 +0 -1
  103. azure_functions_durable-1.2.9.dist-info/RECORD +0 -102
  104. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/top_level.txt +0 -0
@@ -1,127 +1,127 @@
1
- from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
- from azure.durable_functions.models.actions.WhenAnyAction import WhenAnyAction
3
- from tests.test_utils.ContextBuilder import ContextBuilder
4
- from .orchestrator_test_utils \
5
- import get_orchestration_state_result, assert_orchestration_state_equals, assert_valid_schema
6
- from azure.durable_functions.models.actions.CreateTimerAction import CreateTimerAction
7
- from azure.durable_functions.models.OrchestratorState import OrchestratorState
8
- from azure.durable_functions.constants import DATETIME_STRING_FORMAT
9
- from datetime import datetime, timedelta, timezone
10
-
11
-
12
- def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
13
- return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema)
14
-
15
- def add_timer_fired_events(context_builder: ContextBuilder, id_: int, timestamp: str):
16
- fire_at: str = context_builder.add_timer_created_event(id_, timestamp)
17
- context_builder.add_orchestrator_completed_event()
18
- context_builder.add_orchestrator_started_event()
19
- context_builder.add_timer_fired_event(id_=id_, fire_at=fire_at)
20
-
21
- def generator_function(context):
22
-
23
- # Create a timezone aware datetime object, just like a normal
24
- # call to `context.current_utc_datetime` would create
25
- timestamp = "2020-07-23T21:56:54.936700Z"
26
- fire_at = datetime.strptime(timestamp, DATETIME_STRING_FORMAT)
27
- fire_at = fire_at.replace(tzinfo=timezone.utc)
28
-
29
- yield context.create_timer(fire_at)
30
- return "Done!"
31
-
32
- def generator_function_timer_can_be_cancelled(context):
33
- time_limit1 = context.current_utc_datetime + timedelta(minutes=5)
34
- timer_task1 = context.create_timer(time_limit1)
35
-
36
- time_limit2 = context.current_utc_datetime + timedelta(minutes=10)
37
- timer_task2 = context.create_timer(time_limit2)
38
-
39
- winner = yield context.task_any([timer_task1, timer_task2])
40
- if winner == timer_task1:
41
- timer_task2.cancel()
42
- return "Done!"
43
- else:
44
- raise Exception("timer task 1 should complete before timer task 2")
45
-
46
- def add_timer_action(state: OrchestratorState, fire_at: datetime):
47
- action = CreateTimerAction(fire_at=fire_at)
48
- state._actions.append([action])
49
-
50
- def test_timers_comparison_with_relaxed_precision():
51
- """Test if that two `datetime` different but equivalent
52
- serializations of timer deadlines are found to be equivalent.
53
-
54
- The Durable Extension may sometimes drop redundant zeroes on
55
- a datetime object. For instance, the date
56
- 2020-07-23T21:56:54.936700Z
57
- may get transformed into
58
- 2020-07-23T21:56:54.9367Z
59
- This test ensures that dropping redundant zeroes does not affect
60
- our ability to recognize that a timer has been fired.
61
- """
62
-
63
- # equivalent to 2020-07-23T21:56:54.936700Z
64
- relaxed_timestamp = "2020-07-23T21:56:54.9367Z"
65
- fire_at = datetime.strptime(relaxed_timestamp, DATETIME_STRING_FORMAT)
66
-
67
- context_builder = ContextBuilder("relaxed precision")
68
- add_timer_fired_events(context_builder, 0, relaxed_timestamp)
69
-
70
- result = get_orchestration_state_result(
71
- context_builder, generator_function)
72
-
73
- expected_state = base_expected_state(output='Done!')
74
- add_timer_action(expected_state, fire_at)
75
-
76
- expected_state._is_done = True
77
- expected = expected_state.to_json()
78
-
79
- #assert_valid_schema(result)
80
- # TODO: getting the following error when validating the schema
81
- # "Additional properties are not allowed ('fireAt', 'isCanceled' were unexpected)">
82
- assert_orchestration_state_equals(expected, result)
83
-
84
- def test_timers_can_be_cancelled():
85
-
86
- context_builder = ContextBuilder("test_timers_can_be_cancelled")
87
- fire_at1 = context_builder.current_datetime + timedelta(minutes=5)
88
- fire_at2 = context_builder.current_datetime + timedelta(minutes=10)
89
- add_timer_fired_events(context_builder, 0, str(fire_at1))
90
- add_timer_fired_events(context_builder, 1, str(fire_at2))
91
-
92
- result = get_orchestration_state_result(
93
- context_builder, generator_function_timer_can_be_cancelled)
94
-
95
- expected_state = base_expected_state(output='Done!')
96
- expected_state._actions.append(
97
- [CreateTimerAction(fire_at=fire_at1), CreateTimerAction(fire_at=fire_at2, is_cancelled=True)])
98
-
99
- expected_state._is_done = True
100
- expected = expected_state.to_json()
101
-
102
- assert_orchestration_state_equals(expected, result)
103
- assert result["actions"][0][1]["isCanceled"]
104
-
105
- def test_timers_can_be_cancelled_replayV2():
106
-
107
- context_builder = ContextBuilder("test_timers_can_be_cancelled", replay_schema=ReplaySchema.V2)
108
- fire_at1 = context_builder.current_datetime + timedelta(minutes=5)
109
- fire_at2 = context_builder.current_datetime + timedelta(minutes=10)
110
- add_timer_fired_events(context_builder, 0, str(fire_at1))
111
- add_timer_fired_events(context_builder, 1, str(fire_at2))
112
-
113
- result = get_orchestration_state_result(
114
- context_builder, generator_function_timer_can_be_cancelled)
115
-
116
- expected_state = base_expected_state(output='Done!', replay_schema=ReplaySchema.V2)
117
- expected_state._actions = [
118
- [WhenAnyAction(
119
- [CreateTimerAction(fire_at=fire_at1), CreateTimerAction(fire_at=fire_at2, is_cancelled=True)]
120
- )]
121
- ]
122
-
123
- expected_state._is_done = True
124
- expected = expected_state.to_json()
125
-
126
- assert_orchestration_state_equals(expected, result)
1
+ from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
+ from azure.durable_functions.models.actions.WhenAnyAction import WhenAnyAction
3
+ from tests.test_utils.ContextBuilder import ContextBuilder
4
+ from .orchestrator_test_utils \
5
+ import get_orchestration_state_result, assert_orchestration_state_equals, assert_valid_schema
6
+ from azure.durable_functions.models.actions.CreateTimerAction import CreateTimerAction
7
+ from azure.durable_functions.models.OrchestratorState import OrchestratorState
8
+ from azure.durable_functions.constants import DATETIME_STRING_FORMAT
9
+ from datetime import datetime, timedelta, timezone
10
+
11
+
12
+ def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
13
+ return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema)
14
+
15
+ def add_timer_fired_events(context_builder: ContextBuilder, id_: int, timestamp: str):
16
+ fire_at: str = context_builder.add_timer_created_event(id_, timestamp)
17
+ context_builder.add_orchestrator_completed_event()
18
+ context_builder.add_orchestrator_started_event()
19
+ context_builder.add_timer_fired_event(id_=id_, fire_at=fire_at)
20
+
21
+ def generator_function(context):
22
+
23
+ # Create a timezone aware datetime object, just like a normal
24
+ # call to `context.current_utc_datetime` would create
25
+ timestamp = "2020-07-23T21:56:54.936700Z"
26
+ fire_at = datetime.strptime(timestamp, DATETIME_STRING_FORMAT)
27
+ fire_at = fire_at.replace(tzinfo=timezone.utc)
28
+
29
+ yield context.create_timer(fire_at)
30
+ return "Done!"
31
+
32
+ def generator_function_timer_can_be_cancelled(context):
33
+ time_limit1 = context.current_utc_datetime + timedelta(minutes=5)
34
+ timer_task1 = context.create_timer(time_limit1)
35
+
36
+ time_limit2 = context.current_utc_datetime + timedelta(minutes=10)
37
+ timer_task2 = context.create_timer(time_limit2)
38
+
39
+ winner = yield context.task_any([timer_task1, timer_task2])
40
+ if winner == timer_task1:
41
+ timer_task2.cancel()
42
+ return "Done!"
43
+ else:
44
+ raise Exception("timer task 1 should complete before timer task 2")
45
+
46
+ def add_timer_action(state: OrchestratorState, fire_at: datetime):
47
+ action = CreateTimerAction(fire_at=fire_at)
48
+ state._actions.append([action])
49
+
50
+ def test_timers_comparison_with_relaxed_precision():
51
+ """Test if that two `datetime` different but equivalent
52
+ serializations of timer deadlines are found to be equivalent.
53
+
54
+ The Durable Extension may sometimes drop redundant zeroes on
55
+ a datetime object. For instance, the date
56
+ 2020-07-23T21:56:54.936700Z
57
+ may get transformed into
58
+ 2020-07-23T21:56:54.9367Z
59
+ This test ensures that dropping redundant zeroes does not affect
60
+ our ability to recognize that a timer has been fired.
61
+ """
62
+
63
+ # equivalent to 2020-07-23T21:56:54.936700Z
64
+ relaxed_timestamp = "2020-07-23T21:56:54.9367Z"
65
+ fire_at = datetime.strptime(relaxed_timestamp, DATETIME_STRING_FORMAT)
66
+
67
+ context_builder = ContextBuilder("relaxed precision")
68
+ add_timer_fired_events(context_builder, 0, relaxed_timestamp)
69
+
70
+ result = get_orchestration_state_result(
71
+ context_builder, generator_function)
72
+
73
+ expected_state = base_expected_state(output='Done!')
74
+ add_timer_action(expected_state, fire_at)
75
+
76
+ expected_state._is_done = True
77
+ expected = expected_state.to_json()
78
+
79
+ #assert_valid_schema(result)
80
+ # TODO: getting the following error when validating the schema
81
+ # "Additional properties are not allowed ('fireAt', 'isCanceled' were unexpected)">
82
+ assert_orchestration_state_equals(expected, result)
83
+
84
+ def test_timers_can_be_cancelled():
85
+
86
+ context_builder = ContextBuilder("test_timers_can_be_cancelled")
87
+ fire_at1 = context_builder.current_datetime + timedelta(minutes=5)
88
+ fire_at2 = context_builder.current_datetime + timedelta(minutes=10)
89
+ add_timer_fired_events(context_builder, 0, str(fire_at1))
90
+ add_timer_fired_events(context_builder, 1, str(fire_at2))
91
+
92
+ result = get_orchestration_state_result(
93
+ context_builder, generator_function_timer_can_be_cancelled)
94
+
95
+ expected_state = base_expected_state(output='Done!')
96
+ expected_state._actions.append(
97
+ [CreateTimerAction(fire_at=fire_at1), CreateTimerAction(fire_at=fire_at2, is_cancelled=True)])
98
+
99
+ expected_state._is_done = True
100
+ expected = expected_state.to_json()
101
+
102
+ assert_orchestration_state_equals(expected, result)
103
+ assert result["actions"][0][1]["isCanceled"]
104
+
105
+ def test_timers_can_be_cancelled_replayV2():
106
+
107
+ context_builder = ContextBuilder("test_timers_can_be_cancelled", replay_schema=ReplaySchema.V2)
108
+ fire_at1 = context_builder.current_datetime + timedelta(minutes=5)
109
+ fire_at2 = context_builder.current_datetime + timedelta(minutes=10)
110
+ add_timer_fired_events(context_builder, 0, str(fire_at1))
111
+ add_timer_fired_events(context_builder, 1, str(fire_at2))
112
+
113
+ result = get_orchestration_state_result(
114
+ context_builder, generator_function_timer_can_be_cancelled)
115
+
116
+ expected_state = base_expected_state(output='Done!', replay_schema=ReplaySchema.V2)
117
+ expected_state._actions = [
118
+ [WhenAnyAction(
119
+ [CreateTimerAction(fire_at=fire_at1), CreateTimerAction(fire_at=fire_at2, is_cancelled=True)]
120
+ )]
121
+ ]
122
+
123
+ expected_state._is_done = True
124
+ expected = expected_state.to_json()
125
+
126
+ assert_orchestration_state_equals(expected, result)
127
127
  assert result["actions"][0][0]['compoundActions'][1]["isCanceled"]