Skip to content

hololinked.td.interaction_affordance.ActionAffordance

Bases: InteractionAffordance

creates action affordance schema from actions (or methods).

Schema
UML Diagram
Supported Fields

Source code in hololinked\td\interaction_affordance.py
class ActionAffordance(InteractionAffordance):
    """
    creates action affordance schema from actions (or methods).

    [Schema](https://www.w3.org/TR/wot-thing-description11/#actionaffordance) <br>
    [UML Diagram](https://docs.hololinked.dev/UML/PDF/InteractionAffordance.pdf) <br>
    [Supported Fields]() <br>
    """
    input: JSON = None
    output: JSON = None
    safe: bool = None
    idempotent: bool = None 
    synchronous: bool = None 

    def __init__(self, action: typing.Callable | None = None):
        super().__init__()
        self.action = action 

    @property 
    def what(self):
        return ResourceTypes.ACTION

    def build(self, action, owner) -> None:
        self.action = action
        self.owner = owner
        self.title = self.action.name
        if self.action.__doc__:
            self.description = self.format_doc(action.__doc__)
        if self.action.execution_info.argument_schema:
            self.input = self.action.execution_info.argument_schema 
        if self.action.execution_info.return_value_schema: 
            self.output = self.action.execution_info.return_value_schema 
        if (not (hasattr(owner, 'state_machine') and owner.state_machine is not None and 
                owner.state_machine.has_object(self.action)) and 
                self.action.execution_info.idempotent):
            self.idempotent = self.action.execution_info.idempotent
        if self.action.execution_info.synchronous:
            self.synchronous = self.action.execution_info.synchronous
        if self.action.execution_info.safe:
            self.safe = self.action.execution_info.safe 

    def build_forms(self, protocol: str, authority : str, **protocol_metadata) -> None:
        self.forms = []
        for method in self.action.execution_info_validator.http_method:
            form = Form()
            form.op = 'invokeaction'
            form.href = f'{authority}/{self.owner.id}/{protocol_metadata.get("path", "")}/{self.action.name}'
            form.htv_methodName = method.upper()
            form.contentType = 'application/json'
            # form.additionalResponses = [AdditionalExpectedResponse().asdict()]
            self.forms.append(form.asdict())

    @classmethod
    def generate(cls, action : typing.Callable, owner, **kwargs) -> JSON:
        affordance = ActionAffordance(action=action)
        affordance.owner = owner
        affordance._build(owner=owner) 
        if kwargs.get('protocol', None) and kwargs.get('authority', None):
            affordance._build_forms(protocol=kwargs['protocol'], authority=kwargs['authority'])
        return affordance.asdict()

    @classmethod
    def from_TD(self, name: str, TD: JSON) -> "ActionAffordance":
        action = TD["actions"][name] # type: typing.Dict[str, JSON]
        action_affordance = ActionAffordance()
        if action.get("title", None):
            action_affordance.title = action.get("title", None)
        if action.get("description", None):
            action_affordance.description = action.get("description", None)
        if action.get("input", None):
            action_affordance.input = action.get("input", None)
        if action.get("output", None):
            action_affordance.output = action.get("output", None)
        if action.get("safe", None) is not None:
            action_affordance.safe = action.get("safe", None)
        if action.get("idempotent", None) is not None:
            action_affordance.idempotent = action.get("idempotent", None)
        if action.get("synchronous", None) is not None:
            action_affordance.synchronous = action.get("synchronous", None)
        if action.get("forms", None):
            action_affordance.forms = action.get("forms", [])
        action_affordance._name = name
        action_affordance._thing_id = TD["id"]
        return action_affordance
field supported meaning default usage
input ✔️ schema of the input required to invoke action input_schema value of action decorator
output ✔️ schema of the output returned by the action output_schema value of action decorator
safe ✔️ true if the action is safe safe value of action decorator
idempotent ✔️ true if the action is idempotent idempotent value of action decorator
synchronous ✔️ true if the action is synchronous synchronous value of action decorator, (false for async or threaded functions)