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,176 +1,235 @@
1
- from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
- import json
3
- from typing import Dict
4
-
5
- from azure.durable_functions.constants import HTTP_ACTION_NAME
6
- from azure.durable_functions.models import DurableHttpRequest
7
- from .orchestrator_test_utils import assert_orchestration_state_equals, \
8
- get_orchestration_state_result, assert_valid_schema, assert_dict_are_equal
9
- from tests.test_utils.ContextBuilder import ContextBuilder
10
- from azure.durable_functions.models.OrchestratorState import OrchestratorState
11
- from azure.durable_functions.models.actions.CallHttpAction import CallHttpAction
12
- from azure.durable_functions.models.TokenSource import ManagedIdentityTokenSource
13
-
14
- TEST_URI: str = \
15
- 'https://localhost:7071/we_just_need_a_uri_to_use_for_testing'
16
- SIMPLE_RESULT: str = json.dumps({'name': 'simple'})
17
- CONTENT = json.dumps({'name': 'some data', 'additional': 'data'})
18
- HEADERS = {'header1': 'value1', 'header2': 'value2'}
19
- TOKEN_SOURCE = ManagedIdentityTokenSource('https://management.core.windows.net/')
20
-
21
-
22
- def simple_get_generator_function(context):
23
- url = TEST_URI
24
- yield context.call_http("GET", url)
25
-
26
-
27
- def complete_generator_function(context):
28
- url = TEST_URI
29
-
30
- yield context.call_http(method="POST", uri=url, content=json.loads(CONTENT),
31
- headers=HEADERS, token_source=TOKEN_SOURCE)
32
-
33
-
34
- def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
35
- return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
36
-
37
-
38
- def add_http_action(state: OrchestratorState, request):
39
- action = CallHttpAction(request)
40
- state.actions.append([action])
41
-
42
-
43
- def add_completed_http_events(
44
- context_builder: ContextBuilder, id_: int, result: str):
45
- context_builder.add_task_scheduled_event(name=HTTP_ACTION_NAME, id_=id_)
46
- context_builder.add_orchestrator_completed_event()
47
- context_builder.add_orchestrator_started_event()
48
- context_builder.add_task_completed_event(id_=id_, result=result)
49
-
50
-
51
- def add_failed_http_events(
52
- context_builder: ContextBuilder, id_: int, reason: str, details: str):
53
- context_builder.add_task_scheduled_event(name=HTTP_ACTION_NAME, id_=id_)
54
- context_builder.add_orchestrator_completed_event()
55
- context_builder.add_orchestrator_started_event()
56
- context_builder.add_task_failed_event(
57
- id_=id_, reason=reason, details=details)
58
-
59
-
60
- def get_request() -> DurableHttpRequest:
61
- return DurableHttpRequest(method='GET', uri=TEST_URI)
62
-
63
-
64
- def post_request() -> DurableHttpRequest:
65
- return DurableHttpRequest(method="POST", uri=TEST_URI, content=json.dumps(CONTENT),
66
- headers=HEADERS, token_source=TOKEN_SOURCE)
67
-
68
-
69
- def test_initial_orchestration_state():
70
- context_builder = ContextBuilder('test_simple_function')
71
-
72
- result = get_orchestration_state_result(
73
- context_builder, simple_get_generator_function)
74
-
75
- expected_state = base_expected_state()
76
- request = get_request()
77
- add_http_action(expected_state, request)
78
- expected = expected_state.to_json()
79
-
80
- assert_valid_schema(result)
81
- assert_orchestration_state_equals(expected, result)
82
-
83
-
84
- def test_completed_state():
85
- context_builder = ContextBuilder('test_simple_function')
86
- add_completed_http_events(context_builder, 0, SIMPLE_RESULT)
87
-
88
- result = get_orchestration_state_result(
89
- context_builder, simple_get_generator_function)
90
-
91
- expected_state = base_expected_state()
92
- request = get_request()
93
- add_http_action(expected_state, request)
94
- expected_state._is_done = True
95
- expected = expected_state.to_json()
96
-
97
- assert_valid_schema(result)
98
- assert_orchestration_state_equals(expected, result)
99
-
100
-
101
- def test_failed_state():
102
- failed_reason = 'Reasons'
103
- failed_details = 'Stuff and Things'
104
- context_builder = ContextBuilder('test_simple_function')
105
- add_failed_http_events(
106
- context_builder, 0, failed_reason, failed_details)
107
-
108
- try:
109
- result = get_orchestration_state_result(
110
- context_builder, simple_get_generator_function)
111
- # We expected an exception
112
- assert False
113
- except Exception as e:
114
- error_label = "\n\n$OutOfProcData$:"
115
- error_str = str(e)
116
-
117
- expected_state = base_expected_state()
118
- request = get_request()
119
- add_http_action(expected_state, request)
120
-
121
- error_msg = f'{failed_reason} \n {failed_details}'
122
- expected_state._error = error_msg
123
- state_str = expected_state.to_json_string()
124
-
125
- expected_error_str = f"{error_msg}{error_label}{state_str}"
126
- assert expected_error_str == error_str
127
-
128
-
129
- def test_initial_post_state():
130
- context_builder = ContextBuilder('test_simple_function')
131
-
132
- result = get_orchestration_state_result(
133
- context_builder, complete_generator_function)
134
-
135
- expected_state = base_expected_state()
136
- request = post_request()
137
- add_http_action(expected_state, request)
138
- expected = expected_state.to_json()
139
-
140
- # assert_valid_schema(result)
141
- assert_orchestration_state_equals(expected, result)
142
- validate_result_http_request(result)
143
-
144
-
145
- def validate_result_http_request(result):
146
- http_request = result['actions'][0][0]['httpRequest']
147
- assert http_request is not None
148
- assert http_request['method'] == 'POST'
149
- assert http_request['uri'] == TEST_URI
150
- content = http_request['content']
151
- assert isinstance(content, str)
152
- content = json.loads(content)
153
- test_content = json.loads(CONTENT)
154
- assert_dict_are_equal(test_content, content)
155
- assert content['name'] == 'some data'
156
- headers: Dict[str, str] = http_request['headers']
157
- assert_dict_are_equal(HEADERS, headers)
158
- assert http_request['tokenSource']['resource'] == TOKEN_SOURCE.resource
159
-
160
-
161
- def test_post_completed_state():
162
- context_builder = ContextBuilder('test_simple_function')
163
- add_completed_http_events(context_builder, 0, SIMPLE_RESULT)
164
-
165
- result = get_orchestration_state_result(
166
- context_builder, complete_generator_function)
167
-
168
- expected_state = base_expected_state()
169
- request = post_request()
170
- add_http_action(expected_state, request)
171
- expected_state._is_done = True
172
- expected = expected_state.to_json()
173
-
174
- # assert_valid_schema(result)
175
- assert_orchestration_state_equals(expected, result)
176
- validate_result_http_request(result)
1
+ from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
+ import json
3
+ import pytest
4
+ from typing import Dict
5
+
6
+ from azure.durable_functions.constants import HTTP_ACTION_NAME
7
+ from azure.durable_functions.models import DurableHttpRequest
8
+ from .orchestrator_test_utils import assert_orchestration_state_equals, \
9
+ get_orchestration_state_result, assert_valid_schema, assert_dict_are_equal
10
+ from tests.test_utils.ContextBuilder import ContextBuilder
11
+ from azure.durable_functions.models.OrchestratorState import OrchestratorState
12
+ from azure.durable_functions.models.actions.CallHttpAction import CallHttpAction
13
+ from azure.durable_functions.models.TokenSource import ManagedIdentityTokenSource
14
+
15
+ TEST_URI: str = \
16
+ 'https://localhost:7071/we_just_need_a_uri_to_use_for_testing'
17
+ SIMPLE_RESULT: str = json.dumps({'name': 'simple'})
18
+ CONTENT = json.dumps({'name': 'some data', 'additional': 'data'})
19
+ HEADERS = {'header1': 'value1', 'header2': 'value2'}
20
+ TOKEN_SOURCE = ManagedIdentityTokenSource('https://management.core.windows.net/')
21
+
22
+
23
+ def simple_get_generator_function(context):
24
+ url = TEST_URI
25
+ yield context.call_http("GET", url)
26
+
27
+
28
+ def complete_generator_function(context):
29
+ url = TEST_URI
30
+
31
+ yield context.call_http(method="POST", uri=url, content=json.loads(CONTENT),
32
+ headers=HEADERS, token_source=TOKEN_SOURCE)
33
+
34
+
35
+ def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
36
+ return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
37
+
38
+
39
+ def add_http_action(state: OrchestratorState, request):
40
+ action = CallHttpAction(request)
41
+ state.actions.append([action])
42
+
43
+
44
+ def add_completed_http_events(
45
+ context_builder: ContextBuilder, id_: int, result: str):
46
+ context_builder.add_task_scheduled_event(name=HTTP_ACTION_NAME, id_=id_)
47
+ context_builder.add_orchestrator_completed_event()
48
+ context_builder.add_orchestrator_started_event()
49
+ context_builder.add_task_completed_event(id_=id_, result=result)
50
+
51
+
52
+ def add_failed_http_events(
53
+ context_builder: ContextBuilder, id_: int, reason: str, details: str):
54
+ context_builder.add_task_scheduled_event(name=HTTP_ACTION_NAME, id_=id_)
55
+ context_builder.add_orchestrator_completed_event()
56
+ context_builder.add_orchestrator_started_event()
57
+ context_builder.add_task_failed_event(
58
+ id_=id_, reason=reason, details=details)
59
+
60
+
61
+ def get_request() -> DurableHttpRequest:
62
+ return DurableHttpRequest(method='GET', uri=TEST_URI)
63
+
64
+
65
+ def post_request() -> DurableHttpRequest:
66
+ return DurableHttpRequest(method="POST", uri=TEST_URI, content=json.dumps(CONTENT),
67
+ headers=HEADERS, token_source=TOKEN_SOURCE)
68
+
69
+
70
+ def test_initial_orchestration_state():
71
+ context_builder = ContextBuilder('test_simple_function')
72
+
73
+ result = get_orchestration_state_result(
74
+ context_builder, simple_get_generator_function)
75
+
76
+ expected_state = base_expected_state()
77
+ request = get_request()
78
+ add_http_action(expected_state, request)
79
+ expected = expected_state.to_json()
80
+
81
+ assert_valid_schema(result)
82
+ assert_orchestration_state_equals(expected, result)
83
+
84
+
85
+ def test_completed_state():
86
+ context_builder = ContextBuilder('test_simple_function')
87
+ add_completed_http_events(context_builder, 0, SIMPLE_RESULT)
88
+
89
+ result = get_orchestration_state_result(
90
+ context_builder, simple_get_generator_function)
91
+
92
+ expected_state = base_expected_state()
93
+ request = get_request()
94
+ add_http_action(expected_state, request)
95
+ expected_state._is_done = True
96
+ expected = expected_state.to_json()
97
+
98
+ assert_valid_schema(result)
99
+ assert_orchestration_state_equals(expected, result)
100
+
101
+
102
+ def test_failed_state():
103
+ failed_reason = 'Reasons'
104
+ failed_details = 'Stuff and Things'
105
+ context_builder = ContextBuilder('test_simple_function')
106
+ add_failed_http_events(
107
+ context_builder, 0, failed_reason, failed_details)
108
+
109
+ try:
110
+ result = get_orchestration_state_result(
111
+ context_builder, simple_get_generator_function)
112
+ # We expected an exception
113
+ assert False
114
+ except Exception as e:
115
+ error_label = "\n\n$OutOfProcData$:"
116
+ error_str = str(e)
117
+
118
+ expected_state = base_expected_state()
119
+ request = get_request()
120
+ add_http_action(expected_state, request)
121
+
122
+ error_msg = f'{failed_reason} \n {failed_details}'
123
+ expected_state._error = error_msg
124
+ state_str = expected_state.to_json_string()
125
+
126
+ expected_error_str = f"{error_msg}{error_label}{state_str}"
127
+ assert expected_error_str == error_str
128
+
129
+
130
+ def test_initial_post_state():
131
+ context_builder = ContextBuilder('test_simple_function')
132
+
133
+ result = get_orchestration_state_result(
134
+ context_builder, complete_generator_function)
135
+
136
+ expected_state = base_expected_state()
137
+ request = post_request()
138
+ add_http_action(expected_state, request)
139
+ expected = expected_state.to_json()
140
+
141
+ # assert_valid_schema(result)
142
+ assert_orchestration_state_equals(expected, result)
143
+ validate_result_http_request(result)
144
+
145
+
146
+ def validate_result_http_request(result):
147
+ http_request = result['actions'][0][0]['httpRequest']
148
+ assert http_request is not None
149
+ assert http_request['method'] == 'POST'
150
+ assert http_request['uri'] == TEST_URI
151
+ content = http_request['content']
152
+ assert isinstance(content, str)
153
+ content = json.loads(content)
154
+ test_content = json.loads(CONTENT)
155
+ assert_dict_are_equal(test_content, content)
156
+ assert content['name'] == 'some data'
157
+ headers: Dict[str, str] = http_request['headers']
158
+ assert_dict_are_equal(HEADERS, headers)
159
+ assert http_request['tokenSource']['resource'] == TOKEN_SOURCE.resource
160
+
161
+
162
+ def test_post_completed_state():
163
+ context_builder = ContextBuilder('test_simple_function')
164
+ add_completed_http_events(context_builder, 0, SIMPLE_RESULT)
165
+
166
+ result = get_orchestration_state_result(
167
+ context_builder, complete_generator_function)
168
+
169
+ expected_state = base_expected_state()
170
+ request = post_request()
171
+ add_http_action(expected_state, request)
172
+ expected_state._is_done = True
173
+ expected = expected_state.to_json()
174
+
175
+ # assert_valid_schema(result)
176
+ assert_orchestration_state_equals(expected, result)
177
+ validate_result_http_request(result)
178
+
179
+ @pytest.mark.parametrize("content, expected_content, is_raw_str", [
180
+ (None, None, False),
181
+ ("string data", '"string data"', False),
182
+ ('{"key": "value"}', '"{\\"key\\": \\"value\\"}"', False),
183
+ ('["list", "content"]', '"[\\"list\\", \\"content\\"]"', False),
184
+ ('[]', '"[]"', False),
185
+ ('42', '"42"', False),
186
+ ('true', '"true"', False),
187
+ # Cases that test actual behavior (not strictly adhering to Optional[str])
188
+ ({"key": "value"}, '{"key": "value"}', False),
189
+ (["list", "content"], '["list", "content"]', False),
190
+ ([], '[]', False),
191
+ (42, '42', False),
192
+ (True, 'true', False),
193
+ # Cases when is_raw_str is True
194
+ ("string data", "string data", True),
195
+ ('{"key": "value"}', '{"key": "value"}', True),
196
+ ('[]', '[]', True),
197
+ ])
198
+ def test_call_http_content_handling(content, expected_content, is_raw_str):
199
+ def orchestrator_function(context):
200
+ yield context.call_http("POST", TEST_URI, content, is_raw_str=is_raw_str)
201
+
202
+ context_builder = ContextBuilder('test_call_http_content_handling')
203
+ result = get_orchestration_state_result(context_builder, orchestrator_function)
204
+
205
+ assert len(result['actions']) == 1
206
+ http_action = result['actions'][0][0]['httpRequest']
207
+
208
+ assert http_action['method'] == "POST"
209
+ assert http_action['uri'] == TEST_URI
210
+ assert http_action['content'] == expected_content
211
+
212
+ # Test that call_http raises a TypeError when is_raw_str is True but content is not a string
213
+ def test_call_http_non_string_content_with_raw_str():
214
+ def orchestrator_function(context):
215
+ yield context.call_http("POST", TEST_URI, {"key": "value"}, is_raw_str=True)
216
+
217
+ context_builder = ContextBuilder('test_call_http_non_string_content_with_raw_str')
218
+
219
+ try:
220
+ result = get_orchestration_state_result(context_builder, orchestrator_function)
221
+ assert False
222
+ except Exception as e:
223
+ error_label = "\n\n$OutOfProcData$:"
224
+ error_str = str(e)
225
+
226
+ expected_state = base_expected_state()
227
+ error_msg = "Invalid use of 'is_raw_str' parameter: 'is_raw_str' is "\
228
+ "set to 'True' but 'content' is not an instance of type 'str'. "\
229
+ "Either set 'is_raw_str' to 'False', or ensure your 'content' "\
230
+ "is of type 'str'."
231
+ expected_state._error = error_msg
232
+ state_str = expected_state.to_json_string()
233
+
234
+ expected_error_str = f"{error_msg}{error_label}{state_str}"
235
+ assert expected_error_str == error_str
@@ -1,67 +1,67 @@
1
- from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
- from .orchestrator_test_utils \
3
- import assert_orchestration_state_equals, get_orchestration_state_result, assert_valid_schema
4
- from tests.test_utils.ContextBuilder import ContextBuilder
5
- from azure.durable_functions.models.OrchestratorState import OrchestratorState
6
- from azure.durable_functions.models.actions.CallActivityAction \
7
- import CallActivityAction
8
- from azure.durable_functions.models.actions.ContinueAsNewAction \
9
- import ContinueAsNewAction
10
-
11
-
12
- def generator_function(context):
13
- yield context.call_activity("Hello", "Tokyo")
14
- context.continue_as_new("Cause I can")
15
-
16
-
17
- def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
18
- return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
19
-
20
-
21
- def add_hello_action(state: OrchestratorState, input_: str):
22
- action = CallActivityAction(function_name='Hello', input_=input_)
23
- state.actions.append([action])
24
-
25
-
26
- def add_continue_as_new_action(state: OrchestratorState, input_: str):
27
- action = ContinueAsNewAction(input_=input_)
28
- state.actions.append([action])
29
- state._is_done = True
30
-
31
-
32
- def add_hello_completed_events(
33
- context_builder: ContextBuilder, id_: int, result: str):
34
- context_builder.add_task_scheduled_event(name='Hello', id_=id_)
35
- context_builder.add_orchestrator_completed_event()
36
- context_builder.add_orchestrator_started_event()
37
- context_builder.add_task_completed_event(id_=id_, result=result)
38
-
39
-
40
- def test_initial_orchestration_state():
41
- context_builder = ContextBuilder('test_simple_function')
42
-
43
- result = get_orchestration_state_result(
44
- context_builder, generator_function)
45
-
46
- expected_state = base_expected_state()
47
- add_hello_action(expected_state, 'Tokyo')
48
- expected = expected_state.to_json()
49
-
50
- assert_valid_schema(result)
51
- assert_orchestration_state_equals(expected, result)
52
-
53
-
54
- def test_tokyo_state():
55
- context_builder = ContextBuilder('test_simple_function')
56
- add_hello_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
57
-
58
- result = get_orchestration_state_result(
59
- context_builder, generator_function)
60
-
61
- expected_state = base_expected_state()
62
- add_hello_action(expected_state, 'Tokyo')
63
- add_continue_as_new_action(expected_state, 'Cause I can')
64
- expected = expected_state.to_json()
65
-
66
- assert_valid_schema(result)
67
- assert_orchestration_state_equals(expected, result)
1
+ from azure.durable_functions.models.ReplaySchema import ReplaySchema
2
+ from .orchestrator_test_utils \
3
+ import assert_orchestration_state_equals, get_orchestration_state_result, assert_valid_schema
4
+ from tests.test_utils.ContextBuilder import ContextBuilder
5
+ from azure.durable_functions.models.OrchestratorState import OrchestratorState
6
+ from azure.durable_functions.models.actions.CallActivityAction \
7
+ import CallActivityAction
8
+ from azure.durable_functions.models.actions.ContinueAsNewAction \
9
+ import ContinueAsNewAction
10
+
11
+
12
+ def generator_function(context):
13
+ yield context.call_activity("Hello", "Tokyo")
14
+ context.continue_as_new("Cause I can")
15
+
16
+
17
+ def base_expected_state(output=None, replay_schema: ReplaySchema = ReplaySchema.V1) -> OrchestratorState:
18
+ return OrchestratorState(is_done=False, actions=[], output=output, replay_schema=replay_schema.value)
19
+
20
+
21
+ def add_hello_action(state: OrchestratorState, input_: str):
22
+ action = CallActivityAction(function_name='Hello', input_=input_)
23
+ state.actions.append([action])
24
+
25
+
26
+ def add_continue_as_new_action(state: OrchestratorState, input_: str):
27
+ action = ContinueAsNewAction(input_=input_)
28
+ state.actions.append([action])
29
+ state._is_done = True
30
+
31
+
32
+ def add_hello_completed_events(
33
+ context_builder: ContextBuilder, id_: int, result: str):
34
+ context_builder.add_task_scheduled_event(name='Hello', id_=id_)
35
+ context_builder.add_orchestrator_completed_event()
36
+ context_builder.add_orchestrator_started_event()
37
+ context_builder.add_task_completed_event(id_=id_, result=result)
38
+
39
+
40
+ def test_initial_orchestration_state():
41
+ context_builder = ContextBuilder('test_simple_function')
42
+
43
+ result = get_orchestration_state_result(
44
+ context_builder, generator_function)
45
+
46
+ expected_state = base_expected_state()
47
+ add_hello_action(expected_state, 'Tokyo')
48
+ expected = expected_state.to_json()
49
+
50
+ assert_valid_schema(result)
51
+ assert_orchestration_state_equals(expected, result)
52
+
53
+
54
+ def test_tokyo_state():
55
+ context_builder = ContextBuilder('test_simple_function')
56
+ add_hello_completed_events(context_builder, 0, "\"Hello Tokyo!\"")
57
+
58
+ result = get_orchestration_state_result(
59
+ context_builder, generator_function)
60
+
61
+ expected_state = base_expected_state()
62
+ add_hello_action(expected_state, 'Tokyo')
63
+ add_continue_as_new_action(expected_state, 'Cause I can')
64
+ expected = expected_state.to_json()
65
+
66
+ assert_valid_schema(result)
67
+ assert_orchestration_state_equals(expected, result)