Skip to content

Commit ca5edfd

Browse files
authored
Merge pull request #239 from labthings/ensure-action-output-models-are-models
Ensure action output models are models
2 parents 403ceca + c7e3d47 commit ca5edfd

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

src/labthings_fastapi/actions.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
from .base_descriptor import BaseDescriptor
4343
from .logs import add_thing_log_destination
44-
from .utilities import model_to_dict
44+
from .utilities import model_to_dict, wrap_plain_types_in_rootmodel
4545
from .invocations import InvocationModel, InvocationStatus, LogRecordModel
4646
from .dependencies.invocation import NonWarningInvocationID
4747
from .exceptions import (
@@ -477,7 +477,6 @@ def list_all_invocations(
477477

478478
@app.get(
479479
ACTION_INVOCATIONS_PATH + "/{id}",
480-
response_model=InvocationModel,
481480
responses={404: {"description": "Invocation ID not found"}},
482481
)
483482
def action_invocation(
@@ -683,7 +682,7 @@ def __init__(
683682
remove_first_positional_arg=True,
684683
ignore=[p.name for p in self.dependency_params],
685684
)
686-
self.output_model = return_type(func)
685+
self.output_model = wrap_plain_types_in_rootmodel(return_type(func))
687686
self.invocation_model = create_model(
688687
f"{name}_invocation",
689688
__base__=InvocationModel,

tests/test_actions.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def action_wrapper(*args, **kwargs):
161161
return action_wrapper
162162

163163

164-
def assert_input_models_equivalent(model_a, model_b):
164+
def assert_models_equivalent(model_a, model_b):
165165
"""Check two basemodels are equivalent."""
166166
keys = list(model_a.model_fields.keys())
167167
assert list(model_b.model_fields.keys()) == keys
@@ -198,11 +198,10 @@ def decorated(
198198
"""An example decorated action with type annotations."""
199199
return 0.5
200200

201-
assert_input_models_equivalent(
202-
Example.action.input_model, Example.decorated.input_model
201+
assert_models_equivalent(Example.action.input_model, Example.decorated.input_model)
202+
assert_models_equivalent(
203+
Example.action.output_model, Example.decorated.output_model
203204
)
204-
assert Example.action.output_model == Example.decorated.output_model
205-
206205
# Check we can make the thing and it has a valid TD
207206
example = create_thing_without_server(Example)
208207
example.validate_thing_description()

tests/test_numpy_type.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from pydantic import BaseModel, RootModel
44
import numpy as np
5+
from fastapi.testclient import TestClient
56

67
from labthings_fastapi.testing import create_thing_without_server
78
from labthings_fastapi.types.numpy import NDArray, DenumpifyingDict
@@ -70,6 +71,14 @@ class MyNumpyThing(lt.Thing):
7071
def action_with_arrays(self, a: NDArray) -> NDArray:
7172
return a * 2
7273

74+
@lt.action
75+
def read_array(self) -> NDArray:
76+
return np.array([1, 2])
77+
78+
@lt.property
79+
def array_property(self) -> NDArray:
80+
return np.array([3, 4, 5])
81+
7382

7483
def test_thing_description():
7584
"""Make sure the TD validates when numpy types are used."""
@@ -102,3 +111,16 @@ def test_rootmodel():
102111
m = ArrayModel(root=input)
103112
assert isinstance(m.root, np.ndarray)
104113
assert (m.model_dump() == [0, 1, 2]).all()
114+
115+
116+
def test_numpy_over_http():
117+
"""Read numpy array over http."""
118+
server = lt.ThingServer({"np_thing": MyNumpyThing})
119+
with TestClient(server.app) as client:
120+
np_thing_client = lt.ThingClient.from_url("/np_thing/", client=client)
121+
122+
arrayprop = np_thing_client.array_property
123+
assert np.array_equal(np.asarray(arrayprop), np.array([3, 4, 5]))
124+
125+
array = np_thing_client.read_array()
126+
assert np.array_equal(np.asarray(array), np.array([1, 2]))

0 commit comments

Comments
 (0)