|
39 | 39 | from fastapi import FastAPI, HTTPException, Request, Body, BackgroundTasks |
40 | 40 | from pydantic import BaseModel, create_model |
41 | 41 |
|
42 | | -from .base_descriptor import BaseDescriptor |
| 42 | +from .base_descriptor import ( |
| 43 | + BaseDescriptor, |
| 44 | + BaseDescriptorInfo, |
| 45 | + DescriptorInfoCollection, |
| 46 | +) |
43 | 47 | from .logs import add_thing_log_destination |
44 | 48 | from .utilities import model_to_dict, wrap_plain_types_in_rootmodel |
45 | 49 | from .invocations import InvocationModel, InvocationStatus, LogRecordModel |
@@ -622,6 +626,54 @@ def delete_invocation(id: uuid.UUID) -> None: |
622 | 626 | OwnerT = TypeVar("OwnerT", bound="Thing") |
623 | 627 |
|
624 | 628 |
|
| 629 | +class ActionInfo( |
| 630 | + BaseDescriptorInfo[ |
| 631 | + "ActionDescriptor", OwnerT, Callable[ActionParams, ActionReturn] |
| 632 | + ], |
| 633 | + Generic[OwnerT, ActionParams, ActionReturn], |
| 634 | +): |
| 635 | + """Convenient access to the metadata of an action.""" |
| 636 | + |
| 637 | + @property |
| 638 | + def response_timeout(self) -> float: |
| 639 | + """The time to wait before replying to the HTTP request initiating an action.""" |
| 640 | + return self.get_descriptor().response_timeout |
| 641 | + |
| 642 | + @property |
| 643 | + def retention_time(self) -> float: |
| 644 | + """How long to retain the action's output for, in seconds.""" |
| 645 | + return self.get_descriptor().retention_time |
| 646 | + |
| 647 | + @property |
| 648 | + def input_model(self) -> type[BaseModel]: |
| 649 | + """A Pydantic model for the input parameters of an Action.""" |
| 650 | + return self.get_descriptor().input_model |
| 651 | + |
| 652 | + @property |
| 653 | + def output_model(self) -> type[BaseModel]: |
| 654 | + """A Pydantic model for the output parameters of an Action.""" |
| 655 | + return self.get_descriptor().output_model |
| 656 | + |
| 657 | + @property |
| 658 | + def invocation_model(self) -> type[BaseModel]: |
| 659 | + """A Pydantic model for an invocation of this action.""" |
| 660 | + return self.get_descriptor().invocation_model |
| 661 | + |
| 662 | + @property |
| 663 | + def func(self) -> Callable[Concatenate[OwnerT, ActionParams], ActionReturn]: |
| 664 | + """The function that runs the action.""" |
| 665 | + return self.get_descriptor().func |
| 666 | + |
| 667 | + |
| 668 | +class ActionCollection( |
| 669 | + DescriptorInfoCollection[OwnerT, ActionInfo], |
| 670 | + Generic[OwnerT], |
| 671 | +): |
| 672 | + """Access to the metadata of each Action.""" |
| 673 | + |
| 674 | + _descriptorinfo_class = ActionInfo |
| 675 | + |
| 676 | + |
625 | 677 | class ActionDescriptor( |
626 | 678 | BaseDescriptor[OwnerT, Callable[ActionParams, ActionReturn]], |
627 | 679 | Generic[ActionParams, ActionReturn, OwnerT], |
@@ -914,6 +966,15 @@ def action_affordance( |
914 | 966 | output=type_to_dataschema(self.output_model, title=f"{self.name}_output"), |
915 | 967 | ) |
916 | 968 |
|
| 969 | + def descriptor_info(self, owner: OwnerT | None = None) -> ActionInfo: |
| 970 | + """Return an `.ActionInfo` object describing this action. |
| 971 | +
|
| 972 | + The returned object will either refer to the class, or be bound to a particular |
| 973 | + instance. If it is bound, more properties will be available - e.g. we will be |
| 974 | + able to get the bound function. |
| 975 | + """ |
| 976 | + return self._descriptor_info(ActionInfo, owner) |
| 977 | + |
917 | 978 |
|
918 | 979 | @overload |
919 | 980 | def action( |
|
0 commit comments