azure-functions-durable 1.2.8__py3-none-any.whl → 1.2.10__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.
- azure/durable_functions/__init__.py +81 -81
- azure/durable_functions/constants.py +9 -9
- azure/durable_functions/decorators/__init__.py +3 -3
- azure/durable_functions/decorators/durable_app.py +249 -249
- azure/durable_functions/decorators/metadata.py +109 -109
- azure/durable_functions/entity.py +125 -125
- azure/durable_functions/models/DurableEntityContext.py +201 -201
- azure/durable_functions/models/DurableHttpRequest.py +58 -58
- azure/durable_functions/models/DurableOrchestrationBindings.py +66 -66
- azure/durable_functions/models/DurableOrchestrationClient.py +781 -711
- azure/durable_functions/models/DurableOrchestrationContext.py +722 -707
- azure/durable_functions/models/DurableOrchestrationStatus.py +156 -156
- azure/durable_functions/models/EntityStateResponse.py +23 -23
- azure/durable_functions/models/FunctionContext.py +7 -7
- azure/durable_functions/models/OrchestrationRuntimeStatus.py +32 -29
- azure/durable_functions/models/OrchestratorState.py +117 -116
- azure/durable_functions/models/PurgeHistoryResult.py +33 -33
- azure/durable_functions/models/ReplaySchema.py +8 -8
- azure/durable_functions/models/RetryOptions.py +69 -69
- azure/durable_functions/models/RpcManagementOptions.py +86 -86
- azure/durable_functions/models/Task.py +426 -426
- azure/durable_functions/models/TaskOrchestrationExecutor.py +346 -333
- azure/durable_functions/models/TokenSource.py +56 -56
- azure/durable_functions/models/__init__.py +24 -24
- azure/durable_functions/models/actions/Action.py +23 -23
- azure/durable_functions/models/actions/ActionType.py +18 -18
- azure/durable_functions/models/actions/CallActivityAction.py +41 -41
- azure/durable_functions/models/actions/CallActivityWithRetryAction.py +45 -45
- azure/durable_functions/models/actions/CallEntityAction.py +46 -46
- azure/durable_functions/models/actions/CallHttpAction.py +35 -35
- azure/durable_functions/models/actions/CallSubOrchestratorAction.py +40 -40
- azure/durable_functions/models/actions/CallSubOrchestratorWithRetryAction.py +44 -44
- azure/durable_functions/models/actions/CompoundAction.py +35 -35
- azure/durable_functions/models/actions/ContinueAsNewAction.py +36 -36
- azure/durable_functions/models/actions/CreateTimerAction.py +48 -48
- azure/durable_functions/models/actions/NoOpAction.py +35 -35
- azure/durable_functions/models/actions/SignalEntityAction.py +47 -47
- azure/durable_functions/models/actions/WaitForExternalEventAction.py +63 -63
- azure/durable_functions/models/actions/WhenAllAction.py +14 -14
- azure/durable_functions/models/actions/WhenAnyAction.py +14 -14
- azure/durable_functions/models/actions/__init__.py +24 -24
- azure/durable_functions/models/entities/EntityState.py +74 -74
- azure/durable_functions/models/entities/OperationResult.py +76 -76
- azure/durable_functions/models/entities/RequestMessage.py +53 -53
- azure/durable_functions/models/entities/ResponseMessage.py +48 -48
- azure/durable_functions/models/entities/Signal.py +62 -62
- azure/durable_functions/models/entities/__init__.py +17 -17
- azure/durable_functions/models/history/HistoryEvent.py +92 -92
- azure/durable_functions/models/history/HistoryEventType.py +27 -25
- azure/durable_functions/models/history/__init__.py +8 -8
- azure/durable_functions/models/utils/__init__.py +7 -7
- azure/durable_functions/models/utils/entity_utils.py +103 -91
- azure/durable_functions/models/utils/http_utils.py +69 -69
- azure/durable_functions/models/utils/json_utils.py +56 -56
- azure/durable_functions/orchestrator.py +71 -71
- {azure_functions_durable-1.2.8.dist-info → azure_functions_durable-1.2.10.dist-info}/LICENSE +21 -21
- {azure_functions_durable-1.2.8.dist-info → azure_functions_durable-1.2.10.dist-info}/METADATA +58 -58
- azure_functions_durable-1.2.10.dist-info/RECORD +100 -0
- {azure_functions_durable-1.2.8.dist-info → azure_functions_durable-1.2.10.dist-info}/WHEEL +1 -1
- tests/models/test_DecoratorMetadata.py +135 -135
- tests/models/test_Decorators.py +107 -107
- tests/models/test_DurableOrchestrationBindings.py +68 -56
- tests/models/test_DurableOrchestrationClient.py +730 -612
- tests/models/test_DurableOrchestrationContext.py +102 -102
- tests/models/test_DurableOrchestrationStatus.py +59 -59
- tests/models/test_OrchestrationState.py +28 -28
- tests/models/test_RpcManagementOptions.py +79 -79
- tests/models/test_TokenSource.py +10 -10
- tests/orchestrator/models/OrchestrationInstance.py +18 -18
- tests/orchestrator/orchestrator_test_utils.py +130 -130
- tests/orchestrator/schemas/OrchetrationStateSchema.py +66 -66
- tests/orchestrator/test_call_http.py +235 -176
- tests/orchestrator/test_continue_as_new.py +67 -67
- tests/orchestrator/test_create_timer.py +126 -126
- tests/orchestrator/test_entity.py +395 -395
- tests/orchestrator/test_external_event.py +53 -53
- tests/orchestrator/test_fan_out_fan_in.py +175 -175
- tests/orchestrator/test_is_replaying_flag.py +101 -101
- tests/orchestrator/test_retries.py +308 -308
- tests/orchestrator/test_sequential_orchestrator.py +841 -801
- tests/orchestrator/test_sequential_orchestrator_custom_status.py +119 -119
- tests/orchestrator/test_sequential_orchestrator_with_retry.py +465 -465
- tests/orchestrator/test_serialization.py +30 -30
- tests/orchestrator/test_sub_orchestrator.py +95 -95
- tests/orchestrator/test_sub_orchestrator_with_retry.py +129 -129
- tests/orchestrator/test_task_any.py +60 -60
- tests/tasks/tasks_test_utils.py +17 -17
- tests/tasks/test_new_uuid.py +34 -34
- tests/test_utils/ContextBuilder.py +174 -174
- tests/test_utils/EntityContextBuilder.py +56 -56
- tests/test_utils/constants.py +1 -1
- tests/test_utils/json_utils.py +30 -30
- tests/test_utils/testClasses.py +56 -56
- tests/utils/__init__.py +1 -0
- tests/utils/test_entity_utils.py +24 -0
- azure_functions_durable-1.2.8.data/data/_manifest/bsi.json +0 -1
- azure_functions_durable-1.2.8.data/data/_manifest/manifest.cat +0 -0
- azure_functions_durable-1.2.8.data/data/_manifest/manifest.spdx.json +0 -12845
- azure_functions_durable-1.2.8.data/data/_manifest/manifest.spdx.json.sha256 +0 -1
- azure_functions_durable-1.2.8.dist-info/RECORD +0 -102
- {azure_functions_durable-1.2.8.dist-info → azure_functions_durable-1.2.10.dist-info}/top_level.txt +0 -0
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
import json
|
|
3
|
-
from dateutil.parser import parse as dt_parse
|
|
4
|
-
from azure.durable_functions.models.ReplaySchema import ReplaySchema
|
|
5
|
-
|
|
6
|
-
from azure.durable_functions.models.DurableOrchestrationContext \
|
|
7
|
-
import DurableOrchestrationContext
|
|
8
|
-
from tests.test_utils.ContextBuilder import ContextBuilder
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@pytest.fixture
|
|
12
|
-
def starting_context():
|
|
13
|
-
context = DurableOrchestrationContext.from_json(
|
|
14
|
-
'{"history":[{"EventType":12,"EventId":-1,"IsPlayed":false,'
|
|
15
|
-
'"Timestamp":"2019-12-08T23:18:41.3240927Z"}, '
|
|
16
|
-
'{"OrchestrationInstance":{'
|
|
17
|
-
'"InstanceId":"48d0f95957504c2fa579e810a390b938", '
|
|
18
|
-
'"ExecutionId":"fd183ee02e4b4fd18c95b773cfb5452b"},"EventType":0,'
|
|
19
|
-
'"ParentInstance":null, '
|
|
20
|
-
'"Name":"DurableOrchestratorTrigger","Version":"","Input":"null",'
|
|
21
|
-
'"Tags":null,"EventId":-1,"IsPlayed":false, '
|
|
22
|
-
'"Timestamp":"2019-12-08T23:18:39.756132Z"}],"input":null,'
|
|
23
|
-
'"instanceId":"48d0f95957504c2fa579e810a390b938", '
|
|
24
|
-
'"isReplaying":false,"parentInstanceId":null} ')
|
|
25
|
-
return context
|
|
26
|
-
|
|
27
|
-
@pytest.fixture
|
|
28
|
-
def starting_context_v2():
|
|
29
|
-
context = DurableOrchestrationContext.from_json(
|
|
30
|
-
'{"history":[{"EventType":12,"EventId":-1,"IsPlayed":false,'
|
|
31
|
-
'"Timestamp":"2019-12-08T23:18:41.3240927Z"}, '
|
|
32
|
-
'{"OrchestrationInstance":{'
|
|
33
|
-
'"InstanceId":"48d0f95957504c2fa579e810a390b938", '
|
|
34
|
-
'"ExecutionId":"fd183ee02e4b4fd18c95b773cfb5452b"},"EventType":0,'
|
|
35
|
-
'"ParentInstance":null, '
|
|
36
|
-
'"Name":"DurableOrchestratorTrigger","Version":"","Input":"null",'
|
|
37
|
-
'"Tags":null,"EventId":-1,"IsPlayed":false, '
|
|
38
|
-
'"Timestamp":"2019-12-08T23:18:39.756132Z"}],"input":null,'
|
|
39
|
-
'"instanceId":"48d0f95957504c2fa579e810a390b938", '
|
|
40
|
-
'"upperSchemaVersion": 1, '
|
|
41
|
-
'"isReplaying":false,"parentInstanceId":null} ')
|
|
42
|
-
return context
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def test_extracts_is_replaying(starting_context):
|
|
46
|
-
assert not starting_context.is_replaying
|
|
47
|
-
|
|
48
|
-
def test_assumes_v1_replayschema(starting_context):
|
|
49
|
-
assert starting_context._replay_schema is ReplaySchema.V1
|
|
50
|
-
|
|
51
|
-
def test_assumes_v2_replayschema(starting_context_v2):
|
|
52
|
-
assert starting_context_v2._replay_schema is ReplaySchema.V2
|
|
53
|
-
|
|
54
|
-
def test_extracts_instance_id(starting_context):
|
|
55
|
-
assert "48d0f95957504c2fa579e810a390b938" == starting_context.instance_id
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def test_sets_current_utc_datetime(starting_context):
|
|
59
|
-
assert \
|
|
60
|
-
dt_parse("2019-12-08T23:18:41.3240927Z") == \
|
|
61
|
-
starting_context.current_utc_datetime
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def test_extracts_histories(starting_context):
|
|
65
|
-
assert 2 == len(starting_context.histories)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def test_added_function_context_args():
|
|
69
|
-
context_builder = ContextBuilder('test_function_context')
|
|
70
|
-
|
|
71
|
-
additional_attributes = {"attrib1": 1, "attrib2": "two",
|
|
72
|
-
"attrib3": {"randomDictionary": "random"}}
|
|
73
|
-
|
|
74
|
-
context_as_string = context_builder.to_json_string(**additional_attributes)
|
|
75
|
-
|
|
76
|
-
durable_context = DurableOrchestrationContext.from_json(context_as_string)
|
|
77
|
-
|
|
78
|
-
assert durable_context.function_context is not None
|
|
79
|
-
for key in additional_attributes:
|
|
80
|
-
assert additional_attributes[key] == getattr(durable_context.function_context, key)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def test_get_input_none(starting_context):
|
|
84
|
-
test = starting_context.get_input()
|
|
85
|
-
assert None == test
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def test_get_input_string():
|
|
89
|
-
builder = ContextBuilder('test_function_context')
|
|
90
|
-
builder.input_ = json.dumps('Seattle')
|
|
91
|
-
context = DurableOrchestrationContext.from_json(builder.to_json_string())
|
|
92
|
-
assert 'Seattle' == context.get_input()
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def test_get_input_json_str():
|
|
96
|
-
builder = ContextBuilder('test_function_context')
|
|
97
|
-
builder.input_ = json.dumps({ 'city': 'Seattle' })
|
|
98
|
-
context = DurableOrchestrationContext.from_json(builder.to_json_string())
|
|
99
|
-
|
|
100
|
-
result = context.get_input()
|
|
101
|
-
|
|
102
|
-
assert 'Seattle' == result['city']
|
|
1
|
+
import pytest
|
|
2
|
+
import json
|
|
3
|
+
from dateutil.parser import parse as dt_parse
|
|
4
|
+
from azure.durable_functions.models.ReplaySchema import ReplaySchema
|
|
5
|
+
|
|
6
|
+
from azure.durable_functions.models.DurableOrchestrationContext \
|
|
7
|
+
import DurableOrchestrationContext
|
|
8
|
+
from tests.test_utils.ContextBuilder import ContextBuilder
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.fixture
|
|
12
|
+
def starting_context():
|
|
13
|
+
context = DurableOrchestrationContext.from_json(
|
|
14
|
+
'{"history":[{"EventType":12,"EventId":-1,"IsPlayed":false,'
|
|
15
|
+
'"Timestamp":"2019-12-08T23:18:41.3240927Z"}, '
|
|
16
|
+
'{"OrchestrationInstance":{'
|
|
17
|
+
'"InstanceId":"48d0f95957504c2fa579e810a390b938", '
|
|
18
|
+
'"ExecutionId":"fd183ee02e4b4fd18c95b773cfb5452b"},"EventType":0,'
|
|
19
|
+
'"ParentInstance":null, '
|
|
20
|
+
'"Name":"DurableOrchestratorTrigger","Version":"","Input":"null",'
|
|
21
|
+
'"Tags":null,"EventId":-1,"IsPlayed":false, '
|
|
22
|
+
'"Timestamp":"2019-12-08T23:18:39.756132Z"}],"input":null,'
|
|
23
|
+
'"instanceId":"48d0f95957504c2fa579e810a390b938", '
|
|
24
|
+
'"isReplaying":false,"parentInstanceId":null} ')
|
|
25
|
+
return context
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def starting_context_v2():
|
|
29
|
+
context = DurableOrchestrationContext.from_json(
|
|
30
|
+
'{"history":[{"EventType":12,"EventId":-1,"IsPlayed":false,'
|
|
31
|
+
'"Timestamp":"2019-12-08T23:18:41.3240927Z"}, '
|
|
32
|
+
'{"OrchestrationInstance":{'
|
|
33
|
+
'"InstanceId":"48d0f95957504c2fa579e810a390b938", '
|
|
34
|
+
'"ExecutionId":"fd183ee02e4b4fd18c95b773cfb5452b"},"EventType":0,'
|
|
35
|
+
'"ParentInstance":null, '
|
|
36
|
+
'"Name":"DurableOrchestratorTrigger","Version":"","Input":"null",'
|
|
37
|
+
'"Tags":null,"EventId":-1,"IsPlayed":false, '
|
|
38
|
+
'"Timestamp":"2019-12-08T23:18:39.756132Z"}],"input":null,'
|
|
39
|
+
'"instanceId":"48d0f95957504c2fa579e810a390b938", '
|
|
40
|
+
'"upperSchemaVersion": 1, '
|
|
41
|
+
'"isReplaying":false,"parentInstanceId":null} ')
|
|
42
|
+
return context
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_extracts_is_replaying(starting_context):
|
|
46
|
+
assert not starting_context.is_replaying
|
|
47
|
+
|
|
48
|
+
def test_assumes_v1_replayschema(starting_context):
|
|
49
|
+
assert starting_context._replay_schema is ReplaySchema.V1
|
|
50
|
+
|
|
51
|
+
def test_assumes_v2_replayschema(starting_context_v2):
|
|
52
|
+
assert starting_context_v2._replay_schema is ReplaySchema.V2
|
|
53
|
+
|
|
54
|
+
def test_extracts_instance_id(starting_context):
|
|
55
|
+
assert "48d0f95957504c2fa579e810a390b938" == starting_context.instance_id
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_sets_current_utc_datetime(starting_context):
|
|
59
|
+
assert \
|
|
60
|
+
dt_parse("2019-12-08T23:18:41.3240927Z") == \
|
|
61
|
+
starting_context.current_utc_datetime
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_extracts_histories(starting_context):
|
|
65
|
+
assert 2 == len(starting_context.histories)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_added_function_context_args():
|
|
69
|
+
context_builder = ContextBuilder('test_function_context')
|
|
70
|
+
|
|
71
|
+
additional_attributes = {"attrib1": 1, "attrib2": "two",
|
|
72
|
+
"attrib3": {"randomDictionary": "random"}}
|
|
73
|
+
|
|
74
|
+
context_as_string = context_builder.to_json_string(**additional_attributes)
|
|
75
|
+
|
|
76
|
+
durable_context = DurableOrchestrationContext.from_json(context_as_string)
|
|
77
|
+
|
|
78
|
+
assert durable_context.function_context is not None
|
|
79
|
+
for key in additional_attributes:
|
|
80
|
+
assert additional_attributes[key] == getattr(durable_context.function_context, key)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_get_input_none(starting_context):
|
|
84
|
+
test = starting_context.get_input()
|
|
85
|
+
assert None == test
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_get_input_string():
|
|
89
|
+
builder = ContextBuilder('test_function_context')
|
|
90
|
+
builder.input_ = json.dumps('Seattle')
|
|
91
|
+
context = DurableOrchestrationContext.from_json(builder.to_json_string())
|
|
92
|
+
assert 'Seattle' == context.get_input()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_get_input_json_str():
|
|
96
|
+
builder = ContextBuilder('test_function_context')
|
|
97
|
+
builder.input_ = json.dumps({ 'city': 'Seattle' })
|
|
98
|
+
context = DurableOrchestrationContext.from_json(builder.to_json_string())
|
|
99
|
+
|
|
100
|
+
result = context.get_input()
|
|
101
|
+
|
|
102
|
+
assert 'Seattle' == result['city']
|
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
from typing import Dict, Any
|
|
3
|
-
|
|
4
|
-
from dateutil.parser import parse as dt_parse
|
|
5
|
-
|
|
6
|
-
from azure.durable_functions.constants import DATETIME_STRING_FORMAT
|
|
7
|
-
from azure.durable_functions.models.DurableOrchestrationStatus import DurableOrchestrationStatus
|
|
8
|
-
from azure.durable_functions.models.OrchestrationRuntimeStatus import OrchestrationRuntimeStatus
|
|
9
|
-
from azure.durable_functions.models.history import HistoryEventType
|
|
10
|
-
|
|
11
|
-
TEST_NAME = 'what ever I want it to be'
|
|
12
|
-
TEST_INSTANCE_ID = '2e2568e7-a906-43bd-8364-c81733c5891e'
|
|
13
|
-
TEST_CREATED_TIME = '2020-01-01T05:00:00Z'
|
|
14
|
-
TEST_LAST_UPDATED_TIME = '2020-01-01T05:00:00Z'
|
|
15
|
-
TEST_INPUT = 'My Input'
|
|
16
|
-
TEST_OUTPUT = 'My Output'
|
|
17
|
-
TEST_RUNTIME_STATUS = "Running"
|
|
18
|
-
TEST_CUSTOM_STATUS = "My Custom Status"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def get_event(
|
|
22
|
-
event_type: HistoryEventType, id_: int = -1,
|
|
23
|
-
is_played: bool = False, timestamp=None) -> Dict[str, Any]:
|
|
24
|
-
if not timestamp:
|
|
25
|
-
timestamp = datetime.now()
|
|
26
|
-
event = dict(EventType=event_type, EventId=id_, IsPlayed=is_played,
|
|
27
|
-
Timestamp=timestamp.strftime(DATETIME_STRING_FORMAT))
|
|
28
|
-
return event
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def test_all_the_args():
|
|
32
|
-
orchestration_started = get_event(HistoryEventType.ORCHESTRATOR_STARTED)
|
|
33
|
-
execution_started = get_event(HistoryEventType.EXECUTION_STARTED)
|
|
34
|
-
history = [orchestration_started, execution_started]
|
|
35
|
-
response = dict(name=TEST_NAME, instanceId=TEST_INSTANCE_ID, createdTime=TEST_CREATED_TIME,
|
|
36
|
-
lastUpdatedTime=TEST_LAST_UPDATED_TIME, input=TEST_INPUT, output=TEST_OUTPUT,
|
|
37
|
-
runtimeStatus=TEST_RUNTIME_STATUS, customStatus=TEST_CUSTOM_STATUS,
|
|
38
|
-
history=history)
|
|
39
|
-
|
|
40
|
-
result = DurableOrchestrationStatus.from_json(response)
|
|
41
|
-
|
|
42
|
-
assert result.runtime_status.name == TEST_RUNTIME_STATUS
|
|
43
|
-
assert result.custom_status == TEST_CUSTOM_STATUS
|
|
44
|
-
assert result.instance_id == TEST_INSTANCE_ID
|
|
45
|
-
assert result.output == TEST_OUTPUT
|
|
46
|
-
assert result.created_time == dt_parse(TEST_CREATED_TIME)
|
|
47
|
-
assert result.last_updated_time == dt_parse(TEST_LAST_UPDATED_TIME)
|
|
48
|
-
assert result.input_ == TEST_INPUT
|
|
49
|
-
assert result.name == TEST_NAME
|
|
50
|
-
assert result.history[0]['EventType'] == HistoryEventType.ORCHESTRATOR_STARTED
|
|
51
|
-
assert result.history[1]['EventType'] == HistoryEventType.EXECUTION_STARTED
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def test_no_args():
|
|
55
|
-
response = ''
|
|
56
|
-
|
|
57
|
-
result = DurableOrchestrationStatus.from_json(response)
|
|
58
|
-
|
|
59
|
-
assert result is not None
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Dict, Any
|
|
3
|
+
|
|
4
|
+
from dateutil.parser import parse as dt_parse
|
|
5
|
+
|
|
6
|
+
from azure.durable_functions.constants import DATETIME_STRING_FORMAT
|
|
7
|
+
from azure.durable_functions.models.DurableOrchestrationStatus import DurableOrchestrationStatus
|
|
8
|
+
from azure.durable_functions.models.OrchestrationRuntimeStatus import OrchestrationRuntimeStatus
|
|
9
|
+
from azure.durable_functions.models.history import HistoryEventType
|
|
10
|
+
|
|
11
|
+
TEST_NAME = 'what ever I want it to be'
|
|
12
|
+
TEST_INSTANCE_ID = '2e2568e7-a906-43bd-8364-c81733c5891e'
|
|
13
|
+
TEST_CREATED_TIME = '2020-01-01T05:00:00Z'
|
|
14
|
+
TEST_LAST_UPDATED_TIME = '2020-01-01T05:00:00Z'
|
|
15
|
+
TEST_INPUT = 'My Input'
|
|
16
|
+
TEST_OUTPUT = 'My Output'
|
|
17
|
+
TEST_RUNTIME_STATUS = "Running"
|
|
18
|
+
TEST_CUSTOM_STATUS = "My Custom Status"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_event(
|
|
22
|
+
event_type: HistoryEventType, id_: int = -1,
|
|
23
|
+
is_played: bool = False, timestamp=None) -> Dict[str, Any]:
|
|
24
|
+
if not timestamp:
|
|
25
|
+
timestamp = datetime.now()
|
|
26
|
+
event = dict(EventType=event_type, EventId=id_, IsPlayed=is_played,
|
|
27
|
+
Timestamp=timestamp.strftime(DATETIME_STRING_FORMAT))
|
|
28
|
+
return event
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_all_the_args():
|
|
32
|
+
orchestration_started = get_event(HistoryEventType.ORCHESTRATOR_STARTED)
|
|
33
|
+
execution_started = get_event(HistoryEventType.EXECUTION_STARTED)
|
|
34
|
+
history = [orchestration_started, execution_started]
|
|
35
|
+
response = dict(name=TEST_NAME, instanceId=TEST_INSTANCE_ID, createdTime=TEST_CREATED_TIME,
|
|
36
|
+
lastUpdatedTime=TEST_LAST_UPDATED_TIME, input=TEST_INPUT, output=TEST_OUTPUT,
|
|
37
|
+
runtimeStatus=TEST_RUNTIME_STATUS, customStatus=TEST_CUSTOM_STATUS,
|
|
38
|
+
history=history)
|
|
39
|
+
|
|
40
|
+
result = DurableOrchestrationStatus.from_json(response)
|
|
41
|
+
|
|
42
|
+
assert result.runtime_status.name == TEST_RUNTIME_STATUS
|
|
43
|
+
assert result.custom_status == TEST_CUSTOM_STATUS
|
|
44
|
+
assert result.instance_id == TEST_INSTANCE_ID
|
|
45
|
+
assert result.output == TEST_OUTPUT
|
|
46
|
+
assert result.created_time == dt_parse(TEST_CREATED_TIME)
|
|
47
|
+
assert result.last_updated_time == dt_parse(TEST_LAST_UPDATED_TIME)
|
|
48
|
+
assert result.input_ == TEST_INPUT
|
|
49
|
+
assert result.name == TEST_NAME
|
|
50
|
+
assert result.history[0]['EventType'] == HistoryEventType.ORCHESTRATOR_STARTED
|
|
51
|
+
assert result.history[1]['EventType'] == HistoryEventType.EXECUTION_STARTED
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_no_args():
|
|
55
|
+
response = ''
|
|
56
|
+
|
|
57
|
+
result = DurableOrchestrationStatus.from_json(response)
|
|
58
|
+
|
|
59
|
+
assert result is not None
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
from azure.durable_functions.models.ReplaySchema import ReplaySchema
|
|
2
|
-
from typing import List
|
|
3
|
-
|
|
4
|
-
from azure.durable_functions.models.actions.Action import Action
|
|
5
|
-
from azure.durable_functions.models.actions.CallActivityAction \
|
|
6
|
-
import CallActivityAction
|
|
7
|
-
from azure.durable_functions.models.OrchestratorState import OrchestratorState
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def test_empty_state_to_json_string():
|
|
11
|
-
actions: List[List[Action]] = []
|
|
12
|
-
state = OrchestratorState(is_done=False, actions=actions, output=None, replay_schema=ReplaySchema.V1.value)
|
|
13
|
-
result = state.to_json_string()
|
|
14
|
-
expected_result = '{"isDone": false, "actions": []}'
|
|
15
|
-
assert expected_result == result
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def test_single_action_state_to_json_string():
|
|
19
|
-
actions: List[List[Action]] = []
|
|
20
|
-
action: Action = CallActivityAction(
|
|
21
|
-
function_name="MyFunction", input_="AwesomeInput")
|
|
22
|
-
actions.append([action])
|
|
23
|
-
state = OrchestratorState(is_done=False, actions=actions, output=None, replay_schema=ReplaySchema.V1.value)
|
|
24
|
-
result = state.to_json_string()
|
|
25
|
-
expected_result = ('{"isDone": false, "actions": [[{"actionType": 0, '
|
|
26
|
-
'"functionName": "MyFunction", "input": '
|
|
27
|
-
'"\\"AwesomeInput\\""}]]}')
|
|
28
|
-
assert expected_result == result
|
|
1
|
+
from azure.durable_functions.models.ReplaySchema import ReplaySchema
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from azure.durable_functions.models.actions.Action import Action
|
|
5
|
+
from azure.durable_functions.models.actions.CallActivityAction \
|
|
6
|
+
import CallActivityAction
|
|
7
|
+
from azure.durable_functions.models.OrchestratorState import OrchestratorState
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_empty_state_to_json_string():
|
|
11
|
+
actions: List[List[Action]] = []
|
|
12
|
+
state = OrchestratorState(is_done=False, actions=actions, output=None, replay_schema=ReplaySchema.V1.value)
|
|
13
|
+
result = state.to_json_string()
|
|
14
|
+
expected_result = '{"isDone": false, "actions": []}'
|
|
15
|
+
assert expected_result == result
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_single_action_state_to_json_string():
|
|
19
|
+
actions: List[List[Action]] = []
|
|
20
|
+
action: Action = CallActivityAction(
|
|
21
|
+
function_name="MyFunction", input_="AwesomeInput")
|
|
22
|
+
actions.append([action])
|
|
23
|
+
state = OrchestratorState(is_done=False, actions=actions, output=None, replay_schema=ReplaySchema.V1.value)
|
|
24
|
+
result = state.to_json_string()
|
|
25
|
+
expected_result = ('{"isDone": false, "actions": [[{"actionType": 0, '
|
|
26
|
+
'"functionName": "MyFunction", "input": '
|
|
27
|
+
'"\\"AwesomeInput\\""}]]}')
|
|
28
|
+
assert expected_result == result
|
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
from furl import furl
|
|
2
|
-
from datetime import datetime, timedelta
|
|
3
|
-
|
|
4
|
-
from azure.durable_functions.models import OrchestrationRuntimeStatus
|
|
5
|
-
from azure.durable_functions.models.RpcManagementOptions import RpcManagementOptions
|
|
6
|
-
from azure.durable_functions.constants import DATETIME_STRING_FORMAT
|
|
7
|
-
from tests.test_utils.constants import RPC_BASE_URL
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def assert_urls_match(expected, result):
|
|
11
|
-
expected_url = furl(expected)
|
|
12
|
-
result_url = furl(result)
|
|
13
|
-
|
|
14
|
-
assert result_url.path == expected_url.path
|
|
15
|
-
assert len(result_url.args) == len(expected_url.args)
|
|
16
|
-
|
|
17
|
-
for arg in expected_url.args:
|
|
18
|
-
assert expected_url.args[arg] == result_url.args[arg]
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def test_just_instance_id():
|
|
22
|
-
instance_id = 'test1234'
|
|
23
|
-
options = RpcManagementOptions(instance_id=instance_id)
|
|
24
|
-
result = options.to_url(RPC_BASE_URL)
|
|
25
|
-
expected = f"{RPC_BASE_URL}instances/{instance_id}"
|
|
26
|
-
assert_urls_match(expected=expected, result=result)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def test_instance_id_with_optional_booleans():
|
|
30
|
-
instance_id = 'test1234'
|
|
31
|
-
options = RpcManagementOptions(instance_id=instance_id, show_history=True,
|
|
32
|
-
show_history_output=True, show_input=True)
|
|
33
|
-
result = options.to_url(RPC_BASE_URL)
|
|
34
|
-
expected = f"{RPC_BASE_URL}instances/{instance_id}?" \
|
|
35
|
-
"showHistory=True&showHistoryOutput=True&showInput=True"
|
|
36
|
-
|
|
37
|
-
assert_urls_match(expected=expected, result=result)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def test_just_the_strings():
|
|
41
|
-
task_hub_name = 'my_hub'
|
|
42
|
-
connection_name = 'my_connection'
|
|
43
|
-
options = RpcManagementOptions(connection_name=connection_name, task_hub_name=task_hub_name)
|
|
44
|
-
result = options.to_url(RPC_BASE_URL)
|
|
45
|
-
expected = f"{RPC_BASE_URL}instances/?connectionName={connection_name}&taskHub={task_hub_name}"
|
|
46
|
-
|
|
47
|
-
assert_urls_match(expected=expected, result=result)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_one_runtime_status():
|
|
51
|
-
runtime_status = [OrchestrationRuntimeStatus.Running]
|
|
52
|
-
options = RpcManagementOptions(runtime_status=runtime_status)
|
|
53
|
-
result = options.to_url(RPC_BASE_URL)
|
|
54
|
-
expected = f"{RPC_BASE_URL}instances/?runtimeStatus=Running"
|
|
55
|
-
|
|
56
|
-
assert_urls_match(expected=expected, result=result)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def test_two_runtime_status():
|
|
60
|
-
runtime_status = [OrchestrationRuntimeStatus.Running, OrchestrationRuntimeStatus.Completed]
|
|
61
|
-
options = RpcManagementOptions(runtime_status=runtime_status)
|
|
62
|
-
result = options.to_url(RPC_BASE_URL)
|
|
63
|
-
expected = f"{RPC_BASE_URL}instances/?runtimeStatus=Running,Completed"
|
|
64
|
-
|
|
65
|
-
assert_urls_match(expected=expected, result=result)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def test_datetime_status():
|
|
69
|
-
created_time_from = datetime.now()
|
|
70
|
-
created_time_to = created_time_from + timedelta(minutes=1)
|
|
71
|
-
options = RpcManagementOptions(created_time_from=created_time_from,
|
|
72
|
-
created_time_to=created_time_to)
|
|
73
|
-
result = options.to_url(RPC_BASE_URL)
|
|
74
|
-
from_as_string = created_time_from.strftime(DATETIME_STRING_FORMAT)
|
|
75
|
-
to_as_string = created_time_to.strftime(DATETIME_STRING_FORMAT)
|
|
76
|
-
expected = f"{RPC_BASE_URL}instances/?createdTimeFrom={from_as_string}" \
|
|
77
|
-
f"&createdTimeTo={to_as_string}"
|
|
78
|
-
|
|
79
|
-
assert_urls_match(expected=expected, result=result)
|
|
1
|
+
from furl import furl
|
|
2
|
+
from datetime import datetime, timedelta
|
|
3
|
+
|
|
4
|
+
from azure.durable_functions.models import OrchestrationRuntimeStatus
|
|
5
|
+
from azure.durable_functions.models.RpcManagementOptions import RpcManagementOptions
|
|
6
|
+
from azure.durable_functions.constants import DATETIME_STRING_FORMAT
|
|
7
|
+
from tests.test_utils.constants import RPC_BASE_URL
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def assert_urls_match(expected, result):
|
|
11
|
+
expected_url = furl(expected)
|
|
12
|
+
result_url = furl(result)
|
|
13
|
+
|
|
14
|
+
assert result_url.path == expected_url.path
|
|
15
|
+
assert len(result_url.args) == len(expected_url.args)
|
|
16
|
+
|
|
17
|
+
for arg in expected_url.args:
|
|
18
|
+
assert expected_url.args[arg] == result_url.args[arg]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_just_instance_id():
|
|
22
|
+
instance_id = 'test1234'
|
|
23
|
+
options = RpcManagementOptions(instance_id=instance_id)
|
|
24
|
+
result = options.to_url(RPC_BASE_URL)
|
|
25
|
+
expected = f"{RPC_BASE_URL}instances/{instance_id}"
|
|
26
|
+
assert_urls_match(expected=expected, result=result)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_instance_id_with_optional_booleans():
|
|
30
|
+
instance_id = 'test1234'
|
|
31
|
+
options = RpcManagementOptions(instance_id=instance_id, show_history=True,
|
|
32
|
+
show_history_output=True, show_input=True)
|
|
33
|
+
result = options.to_url(RPC_BASE_URL)
|
|
34
|
+
expected = f"{RPC_BASE_URL}instances/{instance_id}?" \
|
|
35
|
+
"showHistory=True&showHistoryOutput=True&showInput=True"
|
|
36
|
+
|
|
37
|
+
assert_urls_match(expected=expected, result=result)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_just_the_strings():
|
|
41
|
+
task_hub_name = 'my_hub'
|
|
42
|
+
connection_name = 'my_connection'
|
|
43
|
+
options = RpcManagementOptions(connection_name=connection_name, task_hub_name=task_hub_name)
|
|
44
|
+
result = options.to_url(RPC_BASE_URL)
|
|
45
|
+
expected = f"{RPC_BASE_URL}instances/?connectionName={connection_name}&taskHub={task_hub_name}"
|
|
46
|
+
|
|
47
|
+
assert_urls_match(expected=expected, result=result)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_one_runtime_status():
|
|
51
|
+
runtime_status = [OrchestrationRuntimeStatus.Running]
|
|
52
|
+
options = RpcManagementOptions(runtime_status=runtime_status)
|
|
53
|
+
result = options.to_url(RPC_BASE_URL)
|
|
54
|
+
expected = f"{RPC_BASE_URL}instances/?runtimeStatus=Running"
|
|
55
|
+
|
|
56
|
+
assert_urls_match(expected=expected, result=result)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_two_runtime_status():
|
|
60
|
+
runtime_status = [OrchestrationRuntimeStatus.Running, OrchestrationRuntimeStatus.Completed]
|
|
61
|
+
options = RpcManagementOptions(runtime_status=runtime_status)
|
|
62
|
+
result = options.to_url(RPC_BASE_URL)
|
|
63
|
+
expected = f"{RPC_BASE_URL}instances/?runtimeStatus=Running,Completed"
|
|
64
|
+
|
|
65
|
+
assert_urls_match(expected=expected, result=result)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_datetime_status():
|
|
69
|
+
created_time_from = datetime.now()
|
|
70
|
+
created_time_to = created_time_from + timedelta(minutes=1)
|
|
71
|
+
options = RpcManagementOptions(created_time_from=created_time_from,
|
|
72
|
+
created_time_to=created_time_to)
|
|
73
|
+
result = options.to_url(RPC_BASE_URL)
|
|
74
|
+
from_as_string = created_time_from.strftime(DATETIME_STRING_FORMAT)
|
|
75
|
+
to_as_string = created_time_to.strftime(DATETIME_STRING_FORMAT)
|
|
76
|
+
expected = f"{RPC_BASE_URL}instances/?createdTimeFrom={from_as_string}" \
|
|
77
|
+
f"&createdTimeTo={to_as_string}"
|
|
78
|
+
|
|
79
|
+
assert_urls_match(expected=expected, result=result)
|
tests/models/test_TokenSource.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
from azure.durable_functions.models.TokenSource import ManagedIdentityTokenSource
|
|
2
|
-
|
|
3
|
-
def test_serialization_fields():
|
|
4
|
-
"""Validates the TokenSource contains the expected fields when serialized to JSON"""
|
|
5
|
-
token_source = ManagedIdentityTokenSource(resource="TOKEN_SOURCE")
|
|
6
|
-
token_source_json = token_source.to_json()
|
|
7
|
-
|
|
8
|
-
# Output JSON should contain a resource field and a kind field set to `AzureManagedIdentity`
|
|
9
|
-
assert "resource" in token_source_json.keys()
|
|
10
|
-
assert "kind" in token_source_json.keys()
|
|
1
|
+
from azure.durable_functions.models.TokenSource import ManagedIdentityTokenSource
|
|
2
|
+
|
|
3
|
+
def test_serialization_fields():
|
|
4
|
+
"""Validates the TokenSource contains the expected fields when serialized to JSON"""
|
|
5
|
+
token_source = ManagedIdentityTokenSource(resource="TOKEN_SOURCE")
|
|
6
|
+
token_source_json = token_source.to_json()
|
|
7
|
+
|
|
8
|
+
# Output JSON should contain a resource field and a kind field set to `AzureManagedIdentity`
|
|
9
|
+
assert "resource" in token_source_json.keys()
|
|
10
|
+
assert "kind" in token_source_json.keys()
|
|
11
11
|
assert token_source_json["kind"] == "AzureManagedIdentity"
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import uuid
|
|
2
|
-
from typing import Any, Dict
|
|
3
|
-
|
|
4
|
-
from tests.test_utils.json_utils import add_attrib
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class OrchestrationInstance:
|
|
8
|
-
def __init__(self):
|
|
9
|
-
self.instance_id: str = str(uuid.uuid4())
|
|
10
|
-
self.execution_id: str = str(uuid.uuid4())
|
|
11
|
-
|
|
12
|
-
def to_json(self) -> Dict[str, Any]:
|
|
13
|
-
json_dict = {}
|
|
14
|
-
|
|
15
|
-
add_attrib(json_dict, self, 'instance_id', 'InstanceId')
|
|
16
|
-
add_attrib(json_dict, self, 'execution_id', 'ExecutionId')
|
|
17
|
-
|
|
18
|
-
return json_dict
|
|
1
|
+
import uuid
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
from tests.test_utils.json_utils import add_attrib
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OrchestrationInstance:
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self.instance_id: str = str(uuid.uuid4())
|
|
10
|
+
self.execution_id: str = str(uuid.uuid4())
|
|
11
|
+
|
|
12
|
+
def to_json(self) -> Dict[str, Any]:
|
|
13
|
+
json_dict = {}
|
|
14
|
+
|
|
15
|
+
add_attrib(json_dict, self, 'instance_id', 'InstanceId')
|
|
16
|
+
add_attrib(json_dict, self, 'execution_id', 'ExecutionId')
|
|
17
|
+
|
|
18
|
+
return json_dict
|