Skip to content

Commit 53d0937

Browse files
author
Daniel Yoo
committed
Update Placeholder doc and add more tests for step field 'result_selector'
1 parent c05c90f commit 53d0937

File tree

5 files changed

+112
-77
lines changed

5 files changed

+112
-77
lines changed

doc/placeholders.rst

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ Placeholders
33

44
Once defined, a workflow is static unless you update it explicitly. But, you can pass
55
input to workflow executions. You can have dynamic values
6-
that you use in the **parameters** fields of the steps in your workflow. For this,
6+
that you use in the **parameters** or **result_selector** fields of the steps in your workflow. For this,
77
the AWS Step Functions Data Science SDK provides a way to define placeholders to pass around when you
8-
create your workflow. There are 2 mechanisms for passing dynamic values in a workflow.
8+
create your workflow. There are 3 mechanisms for passing dynamic values in a workflow.
99

1010
The first mechanism is a global input to the workflow execution. This input is
1111
accessible to all the steps in the workflow. The SDK provides :py:meth:`stepfunctions.inputs.ExecutionInput`
@@ -64,10 +64,10 @@ that returns the placeholder output for that step.
6464
parameters={
6565
"FunctionName": "MakeApiCall",
6666
"Payload": {
67-
"input": "20192312"
68-
}
67+
"input": "20192312"
6968
}
70-
)
69+
}
70+
)
7171
7272
lambda_state_second = LambdaStep(
7373
state_id="MySecondLambdaStep",
@@ -81,7 +81,23 @@ that returns the placeholder output for that step.
8181
8282
definition = Chain([lambda_state_first, lambda_state_second])
8383
84+
The third mechanism is a placeholder for a step's result. The result of a step can be modified
85+
with the **result_selector** field to replace the step's result.
86+
87+
.. code-block:: python
88+
lambda_result = StepResult(
89+
schema={
90+
"Id": str,
91+
}
92+
)
8493
94+
lambda_state_first = LambdaStep(
95+
state_id="MyFirstLambdaStep",
96+
result_selector={
97+
"Output": lambda_result["Id"],
98+
"Status": "Success"
99+
}
100+
)
85101
86102
.. autoclass:: stepfunctions.inputs.Placeholder
87103

@@ -90,3 +106,6 @@ that returns the placeholder output for that step.
90106

91107
.. autoclass:: stepfunctions.inputs.StepInput
92108
:inherited-members:
109+
110+
.. autoclass:: stepfunctions.inputs.StepResult
111+
:inherited-members:

src/stepfunctions/steps/states.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,16 +210,6 @@ def update_parameters(self, params):
210210
if Field.Parameters in self.allowed_fields():
211211
self.fields[Field.Parameters.value] = params
212212

213-
def update_result_selector(self, result_selector):
214-
"""
215-
Update `result_selector` field in the state, if supported.
216-
217-
Args:
218-
params (dict or list): The value of this field becomes the effective result of the state.
219-
"""
220-
if Field.ResultSelector in self.allowed_fields():
221-
self.fields[Field.ResultSelector.value] = result_selector
222-
223213
def next(self, next_step):
224214
"""
225215
Specify the next state or chain to transition to.

tests/unit/test_placeholders.py

Lines changed: 65 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,64 +17,64 @@
1717

1818
from stepfunctions.inputs import ExecutionInput, StepInput, StepResult
1919

20-
def test_placeholder_creation_with_subscript_operator():
21-
step_input = StepInput()
22-
placeholder_variable = step_input["A"]
20+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
21+
def test_placeholder_creation_with_subscript_operator(placeholder):
22+
placeholder_variable = placeholder["A"]
2323
assert placeholder_variable.name == "A"
2424
assert placeholder_variable.type is None
2525

26-
def test_placeholder_creation_with_type():
27-
workflow_input = ExecutionInput()
28-
placeholder_variable = workflow_input["A"]["b"].get("C", float)
26+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
27+
def test_placeholder_creation_with_type(placeholder):
28+
placeholder_variable = placeholder["A"]["b"].get("C", float)
2929
assert placeholder_variable.name == "C"
3030
assert placeholder_variable.type == float
3131

32-
def test_placeholder_creation_with_int_key():
33-
workflow_input = ExecutionInput()
34-
placeholder_variable = workflow_input["A"][0]
32+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
33+
def test_placeholder_creation_with_int_key(placeholder):
34+
placeholder_variable = placeholder["A"][0]
3535
assert placeholder_variable.name == 0
3636
assert placeholder_variable.type == None
3737

38-
def test_placeholder_creation_with_invalid_key():
39-
step_input = StepInput()
38+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
39+
def test_placeholder_creation_with_invalid_key(placeholder):
4040
with pytest.raises(ValueError):
41-
step_input["A"][1.3]
41+
placeholder["A"][1.3]
4242
with pytest.raises(ValueError):
43-
step_input["A"].get(1.2, str)
43+
placeholder["A"].get(1.2, str)
4444

45-
def test_placeholder_creation_failure_with_type():
46-
workflow_input = ExecutionInput()
47-
placeholder_variable = workflow_input["A"]["b"].get("C", float)
45+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
46+
def test_placeholder_creation_failure_with_type(placeholder):
47+
placeholder_variable = placeholder["A"]["b"].get("C", float)
4848
with pytest.raises(ValueError):
49-
workflow_input["A"]["b"].get("C", int)
49+
placeholder["A"]["b"].get("C", int)
5050

51-
def test_placeholder_path():
52-
workflow_input = ExecutionInput()
53-
placeholder_variable = workflow_input["A"]["b"]["C"]
51+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
52+
def test_placeholder_path(placeholder):
53+
placeholder_variable = placeholder["A"]["b"]["C"]
5454
expected_path = ["A", "b", "C"]
5555
assert placeholder_variable._get_path() == expected_path
5656

57-
def test_placeholder_contains():
58-
step_input = StepInput()
59-
var_one = step_input["Key01"]
60-
var_two = step_input["Key02"]["Key03"]
61-
var_three = step_input["Key01"]["Key04"]
62-
var_four = step_input["Key05"]
57+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
58+
def test_placeholder_contains(placeholder):
59+
var_one = placeholder["Key01"]
60+
var_two = placeholder["Key02"]["Key03"]
61+
var_three = placeholder["Key01"]["Key04"]
62+
var_four = placeholder["Key05"]
6363

64-
step_input_two = StepInput()
65-
var_five = step_input_two["Key07"]
64+
placeholder_two = StepInput()
65+
var_five = placeholder_two["Key07"]
6666

67-
assert step_input.contains(var_three) == True
68-
assert step_input.contains(var_five) == False
69-
assert step_input_two.contains(var_three) == False
67+
assert placeholder.contains(var_three) == True
68+
assert placeholder.contains(var_five) == False
69+
assert placeholder_two.contains(var_three) == False
7070

71-
def test_placeholder_schema_as_dict():
72-
workflow_input = ExecutionInput()
73-
workflow_input["A"]["b"].get("C", float)
74-
workflow_input["Message"]
75-
workflow_input["Key01"]["Key02"]
76-
workflow_input["Key03"]
77-
workflow_input["Key03"]["Key04"]
71+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
72+
def test_placeholder_schema_as_dict(placeholder):
73+
placeholder["A"]["b"].get("C", float)
74+
placeholder["Message"]
75+
placeholder["Key01"]["Key02"]
76+
placeholder["Key03"]
77+
placeholder["Key03"]["Key04"]
7878

7979
expected_schema = {
8080
"A": {
@@ -91,14 +91,14 @@ def test_placeholder_schema_as_dict():
9191
}
9292
}
9393

94-
assert workflow_input.get_schema_as_dict() == expected_schema
94+
assert placeholder.get_schema_as_dict() == expected_schema
9595

96-
def test_placeholder_schema_as_json():
97-
step_input = StepInput()
98-
step_input["Response"].get("StatusCode", int)
99-
step_input["Hello"]["World"]
100-
step_input["A"]
101-
step_input["Hello"]["World"].get("Test", str)
96+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
97+
def test_placeholder_schema_as_json(placeholder):
98+
placeholder["Response"].get("StatusCode", int)
99+
placeholder["Hello"]["World"]
100+
placeholder["A"]
101+
placeholder["Hello"]["World"].get("Test", str)
102102

103103
expected_schema = {
104104
"Response": {
@@ -112,29 +112,27 @@ def test_placeholder_schema_as_json():
112112
"A": "str"
113113
}
114114

115-
assert step_input.get_schema_as_json() == json.dumps(expected_schema)
115+
assert placeholder.get_schema_as_json() == json.dumps(expected_schema)
116116

117-
def test_placeholder_is_empty():
118-
workflow_input = ExecutionInput()
119-
placeholder_variable = workflow_input["A"]["B"]["C"]
117+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
118+
def test_placeholder_is_empty(placeholder):
119+
placeholder_variable = placeholder["A"]["B"]["C"]
120120
assert placeholder_variable._is_empty() == True
121-
workflow_input["A"]["B"]["C"]["D"]
121+
placeholder["A"]["B"]["C"]["D"]
122122
assert placeholder_variable._is_empty() == False
123123

124+
@pytest.mark.parametrize("placeholder", [StepInput(), StepResult(), ExecutionInput()])
125+
def test_placeholder_make_immutable(placeholder):
126+
placeholder["A"]["b"].get("C", float)
127+
placeholder["Message"]
128+
placeholder["Key01"]["Key02"]
129+
placeholder["Key03"]
130+
placeholder["Key03"]["Key04"]
124131

125-
def test_placeholder_make_immutable():
126-
workflow_input = ExecutionInput()
127-
workflow_input["A"]["b"].get("C", float)
128-
workflow_input["Message"]
129-
workflow_input["Key01"]["Key02"]
130-
workflow_input["Key03"]
131-
workflow_input["Key03"]["Key04"]
132-
133-
assert check_immutable(workflow_input) == False
134-
135-
workflow_input._make_immutable()
136-
assert check_immutable(workflow_input) == True
132+
assert check_immutable(placeholder) == False
137133

134+
placeholder._make_immutable()
135+
assert check_immutable(placeholder) == True
138136

139137
def test_placeholder_with_schema():
140138
test_schema = {
@@ -168,6 +166,11 @@ def test_step_input_jsonpath():
168166
placeholder_variable = step_input["A"]["b"].get(0, float)
169167
assert placeholder_variable.to_jsonpath() == "$['A']['b'][0]"
170168

169+
def test_step_result_jsonpath():
170+
step_result = StepResult()
171+
placeholder_variable = step_result["A"]["b"].get(0, float)
172+
assert placeholder_variable.to_jsonpath() == "$['A']['b'][0]"
173+
171174
# UTILS
172175

173176
def check_immutable(placeholder):

tests/unit/test_placeholders_with_steps.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,3 +459,22 @@ def test_schema_validation_for_step_result():
459459
"ParamB": "SampleValueB"
460460
}
461461
)
462+
463+
def test_schema_validation_success_for_step_result():
464+
step_result = StepResult(
465+
schema={
466+
"Payload": {
467+
"Key01": str
468+
}
469+
}
470+
)
471+
472+
try:
473+
test_step = Task(
474+
state_id='StateOne',
475+
result_selector={
476+
'ParamA': step_result["Payload"]["Key01"]
477+
}
478+
)
479+
except:
480+
pytest.fail("Step should fetch step result key successfully without raising an Exception")

tests/unit/test_steps.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def test_state_creation():
3232
input_path='$.Input',
3333
output_path='$.Output',
3434
parameters={'Key': 'Value'},
35+
result_selector={'foo': 'bar'},
3536
result_path='$.Result'
3637
)
3738

@@ -43,6 +44,9 @@ def test_state_creation():
4344
'Parameters': {
4445
'Key': 'Value'
4546
},
47+
'ResultSelector': {
48+
'foo': 'bar'
49+
},
4650
'ResultPath': '$.Result',
4751
'End': True
4852
}

0 commit comments

Comments
 (0)