Handle the case where the condition execution call result returns an unquoted string value with whitespace in it which causes an Exception to be raised when passed into ast.literal_eval.

This can be especially evident for JSON API endpoints.
We never encountered this before because on-chain conditions didn't return strings.
pull/3553/head
derekpierre 2024-09-13 11:24:09 -04:00
parent b00485822b
commit c81fd58a37
No known key found for this signature in database
2 changed files with 32 additions and 7 deletions

View File

@ -295,7 +295,17 @@ class ReturnValueTest:
f"Index '{index}' not found in returned data."
)
if isinstance(processed_data, (list, tuple)):
# string results that have whitespace but are not already quoted will
# cause a problem for subsequent literal_eval
if isinstance(processed_data, str):
# string that contains whitespace, check if already quoted; if not, quote it
if " " in processed_data and not (
(processed_data.startswith("'") and processed_data.endswith("'"))
or (processed_data.startswith('"') and processed_data.endswith('"'))
):
# quote the string
processed_data = f"'{processed_data}'"
elif isinstance(processed_data, (list, tuple)):
# convert any bytes in list to hex (include nested lists/tuples); no additional indexing
processed_data = [
self._process_data(data=item, index=None) for item in processed_data

View File

@ -101,7 +101,7 @@ def test_json_api_condition_fetch_failure(mocker):
condition = JsonApiCondition(
endpoint="https://api.example.com/data",
query="$.store.book[0].price",
return_value_test=ReturnValueTest("==", "1"),
return_value_test=ReturnValueTest("==", 1),
)
with pytest.raises(InvalidCondition) as excinfo:
condition.fetch()
@ -110,17 +110,32 @@ def test_json_api_condition_fetch_failure(mocker):
def test_json_api_condition_verify(mocker):
mock_response = mocker.Mock(status_code=200)
mock_response.json.return_value = {"store": {"book": [{"price": "1"}]}}
mock_response.json.return_value = {"store": {"book": [{"price": 1}]}}
mocker.patch("requests.get", return_value=mock_response)
condition = JsonApiCondition(
endpoint="https://api.example.com/data",
query="$.store.book[0].price",
return_value_test=ReturnValueTest("==", "1"),
return_value_test=ReturnValueTest("==", 1),
)
result, value = condition.verify()
assert result is True
assert value == "1"
assert value == 1
def test_json_api_condition_verify_string(mocker):
mock_response = mocker.Mock(status_code=200)
mock_response.json.return_value = {"store": {"book": [{"title": "Test Title"}]}}
mocker.patch("requests.get", return_value=mock_response)
condition = JsonApiCondition(
endpoint="https://api.example.com/data",
query="$.store.book[0].title",
return_value_test=ReturnValueTest("==", "'Test Title'"),
)
result, value = condition.verify()
assert result is True
assert value == "Test Title"
def test_json_api_condition_verify_invalid_json(mocker):
@ -131,7 +146,7 @@ def test_json_api_condition_verify_invalid_json(mocker):
condition = JsonApiCondition(
endpoint="https://api.example.com/data",
query="$.store.book[0].price",
return_value_test=ReturnValueTest("==", "2"),
return_value_test=ReturnValueTest("==", 2),
)
with pytest.raises(ConditionEvaluationFailed) as excinfo:
condition.verify()
@ -150,7 +165,7 @@ def test_non_json_response(mocker):
condition = JsonApiCondition(
endpoint="https://api.example.com/data",
query="$.store.book[0].price",
return_value_test=ReturnValueTest("==", "18"),
return_value_test=ReturnValueTest("==", 18),
)
with pytest.raises(ConditionEvaluationFailed) as excinfo: