Skip to content

Commit

Permalink
pydantic and json load error
Browse files Browse the repository at this point in the history
  • Loading branch information
stan-dot committed Mar 20, 2024
1 parent 7dcbcfa commit bec80e0
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/blueapi/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def store_finished_event(event: WorkerEvent) -> None:
if event.is_complete():
finished_event.append(event)

parameters = parameters or "{}"
parameters = json.loads(parameters) or "{}"
schema: PlanModel = client.get_plan(name)
progress_tracking = f"Trying to run plan: {name}."
print(progress_tracking)
Expand Down
122 changes: 107 additions & 15 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,33 +149,62 @@ def test_config_passed_down_to_command_children(
):
config_path = "tests/example_yaml/rest_config.yaml"

mock_handler.side_effect = Mock(return_value=handler)
with patch("uvicorn.run", side_effect=None):
result = runner.invoke(main, ["-c", config_path, "serve"])
assert result.exit_code == 0

mock_requests.return_value = client.get("/plans/sleep")
output = runner.invoke(
main, ["-c", config_path, "controller", "run", "sleep", '{"time": 5}']
)
assert result.exit_code == 0
print(output)
# 'Trying to run plan: sleep.\nChecking supplied parameters against expected parameters...\nInput validation failed: __root__: value is not a valid dict\nfailed to run the sleep plan, supplied params {"time": 5}\n do not match the expected params: {\'time\': {\'title\': \'Time\', \'type\': \'number\'}}\n'

# expect the first call to be to the helper
# Put a plan in handler.context manually.
plan = Plan(name="my-plan", model=MyModel)
handler._context.plans = {"my-plan": plan}

# Setup requests.get call to return the output of the FastAPI call for plans.
# Call the CLI function and check the output.
mock_requests.return_value = client.get("/plans")
plans = runner.invoke(main, ["controller", "plans"])

assert (
plans.output == "{'plans': [{'description': None,\n"
" 'name': 'my-plan',\n"
" 'parameter_schema': {'properties': {'id': {'title': 'Id',\n"
" 'type': 'string'}},\n"
" 'required': ['id'],\n"
" 'title': 'MyModel',\n"
" 'type': 'object'}}]}\n"
)

# Setup requests.get call to return the output of the FastAPI call for devices.
# Call the CLI function and check the output - expect nothing as no devices set.
handler._context.devices = {}
mock_requests.return_value = client.get("/devices")
unset_devices = runner.invoke(main, [ "-c", config_path, "controller", "devices"])
assert unset_devices.output == "{'devices': []}\n"

assert mock_requests.call_args[0] == (
"GET",
"http://a.fake.host:12345/plans/sleep",
"http://a.fake.host:12345/devices",
)

mock_requests.return_value = client.post(
"/tasks", json={"name": "sleep", "params": {"time": 5}}
)
# Put a device in handler.context manually.
device = MyDevice("my-device")
handler._context.devices = {"my-device": device}

# Setup requests.get call to return the output of the FastAPI call for devices.
# Call the CLI function and check the output.
mock_requests.return_value = client.get("/devices")
devices = runner.invoke(main, ["controller", "devices"])

assert mock_requests.call_args[1] == (
"POST",
"http://a.fake.host:12345/tasks",
"GET",
"http://a.fake.host:12345/devices",
)

assert (
devices.output
== "{'devices': [{'name': 'my-device', 'protocols': ['HasName']}]}\n"
)

@pytest.mark.handler
@patch("blueapi.service.handler.Handler")
Expand All @@ -187,7 +216,38 @@ def test_plan_accepted_with_right_parameters(
client: TestClient,
runner: CliRunner,
):
pass

# needed so that the handler is instantiated as MockHandler() instead of Handler().
mock_handler.side_effect = Mock(return_value=handler)

# Setup the (Mock)Handler.
with patch("uvicorn.run", side_effect=None):
result = runner.invoke(main, ["serve"])

assert result.exit_code == 0

mock_requests.return_value = client.get("/plans/sleep")
output = runner.invoke(
main, [ "controller", "run", "sleep", '{"time": 5}']
)
assert result.exit_code == 0
print(output)
# 'Trying to run plan: sleep.\nChecking supplied parameters against expected parameters...\nInput validation failed: __root__: value is not a valid dict\nfailed to run the sleep plan, supplied params {"time": 5}\n do not match the expected params: {\'time\': {\'title\': \'Time\', \'type\': \'number\'}}\n'

# expect the first call to be to the helper
assert mock_requests.call_args[0] == (
"GET",
"http://localhost:12345/plans/sleep",
)

mock_requests.return_value = client.post(
"/tasks", json={"name": "sleep", "params": {"time": 5}}
)

assert mock_requests.call_args[1] == (
"POST",
"http://localhost:12345/tasks",
)


@pytest.mark.handler
Expand All @@ -200,4 +260,36 @@ def test_plan_rejected_with_wrong_parameters(
client: TestClient,
runner: CliRunner,
):
pass

# needed so that the handler is instantiated as MockHandler() instead of Handler().
mock_handler.side_effect = Mock(return_value=handler)

# Setup the (Mock)Handler.
with patch("uvicorn.run", side_effect=None):
result = runner.invoke(main, ["serve"])

assert result.exit_code == 0

mock_requests.return_value = client.get("/plans/sleep")
output = runner.invoke(
main, [ "controller", "run", "sleep", '{"time": 5}']
)
assert result.exit_code == 0
print(output)
# 'Trying to run plan: sleep.\nChecking supplied parameters against expected parameters...\nInput validation failed: __root__: value is not a valid dict\nfailed to run the sleep plan, supplied params {"time": 5}\n do not match the expected params: {\'time\': {\'title\': \'Time\', \'type\': \'number\'}}\n'

# expect the first call to be to the helper
assert mock_requests.call_args[0] == (
"GET",
"http://a.fake.host:12345/plans/sleep",
)

mock_requests.return_value = client.post(
"/tasks", json={"name": "sleep", "params": {"time": 5}}
)

assert mock_requests.call_args[1] == (
"POST",
"http://a.fake.host:12345/tasks",
)

0 comments on commit bec80e0

Please sign in to comment.