Skip to content

Commit f75224b

Browse files
committed
Make it possible to check (from Python) if a property can be reset.
1 parent ea58d97 commit f75224b

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

src/labthings_fastapi/properties.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,15 @@ def reset(self, obj: Owner) -> None:
426426
f"{self.__class__}."
427427
)
428428

429+
def is_resettable(self, obj: Owner | None) -> bool:
430+
r"""Determine if it's possible to reset this property.
431+
432+
By default, this returns `True` if ``reset`` has been overridden.
433+
If you override ``reset`` but want more control over this behaviour,
434+
you probably need to override `is_resettable`\ .
435+
"""
436+
return BaseProperty.reset is not self.__class__.reset
437+
429438
def add_to_fastapi(self, app: FastAPI, thing: Owner) -> None:
430439
"""Add this action to a FastAPI app, bound to a particular Thing.
431440
@@ -472,6 +481,25 @@ def set_property(body: Any) -> None:
472481
def get_property() -> Any:
473482
return self.__get__(thing)
474483

484+
if self.is_resettable(thing):
485+
486+
@app.post(
487+
thing.path + self.name + "/reset",
488+
summary=f"Reset {self.title}.",
489+
description=(
490+
f"## Reset {self.title}\n\n"
491+
"This endpoint will reset the property to its default value. "
492+
"The default value should be detailed in the Thing Description.\n\n"
493+
"Not every property supports the reset-to-default operation, and "
494+
"this endpoint is only present (e.g. in the OpenAPI docs) "
495+
"for those that do.\n\n"
496+
"This endpoint is identical to using the ``reset_property`` action"
497+
rf"with the ``name`` argument set to ``{self.name}``\ ."
498+
),
499+
)
500+
def reset() -> None:
501+
self.reset(thing)
502+
475503
def property_affordance(
476504
self, thing: Owner, path: str | None = None
477505
) -> PropertyAffordance:
@@ -933,6 +961,11 @@ def default(self) -> Value:
933961
"""
934962
return self.get_descriptor().default(self.owning_object)
935963

964+
@builtins.property
965+
def is_resettable(self) -> bool:
966+
"""Whether the property may be reset using the ``reset()`` method."""
967+
return self.get_descriptor().is_resettable(self.owning_object)
968+
936969
def reset(self) -> None:
937970
"""Reset the property to a default value.
938971

tests/test_property.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,15 @@ def strprop(self) -> str:
490490
with pytest.raises(NotBoundToInstanceError):
491491
thing.properties[name].reset()
492492

493+
# Check the `resettable` property is correct
494+
for thing in [example, Example]:
495+
for name, resettable in [
496+
("intprop", True),
497+
("listprop", True),
498+
("strprop", False),
499+
]:
500+
assert thing.properties[name].is_resettable is resettable
501+
493502
# Resetting should work for DataProperty
494503
example.intprop = 43
495504
assert example.intprop == 43

0 commit comments

Comments
 (0)