Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RSDK-2870: use api instead of subtype #824

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ The SDK provides a number of abstract base components and services (collectively
1. Define all requirements of the resource in `{RESOURCE_NAME}.py`
1. Implement the gRPC service for the new resource in `service.py`
1. Create a gRPC client for the new resource in `client.py`
1. Register the subtype and define package exports in `__init__.py`
1. Register the API and define package exports in `__init__.py`
1. Write tests for the new resource and add the resource to `tests.mocks.{components|services}`
1. If the resource is a component, add the component to `examples.server.v1.components` and its corresponding concrete type in `examples.server.v1.server`

Expand Down
2 changes: 1 addition & 1 deletion docs/examples/module_step2.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async def close(self):


async def main():
Registry.register_resource_creator(Sensor.SUBTYPE, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new))
Registry.register_resource_creator(Sensor.API, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new))


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/module_step2_optional.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ async def close(self):


async def main():
Registry.register_resource_creator(Sensor.SUBTYPE, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new, MySensor.validate_config))
Registry.register_resource_creator(Sensor.API, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new, MySensor.validate_config))


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/module_step3.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ async def main():
This function creates and starts a new module, after adding all desired resource model.
Resource creators must be registered to the resource registry before the module adds the resource model.
"""
Registry.register_resource_creator(Sensor.SUBTYPE, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new))
Registry.register_resource_creator(Sensor.API, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new))

module = Module.from_args()
module.add_model_from_registry(Sensor.SUBTYPE, MySensor.MODEL)
module.add_model_from_registry(Sensor.API, MySensor.MODEL)
await module.start()


Expand Down
2 changes: 1 addition & 1 deletion examples/complex_module/src/arm/my_arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,4 @@ async def close(self):
LOGGER.info(f"{self.name} is closed.")


Registry.register_resource_creator(Arm.SUBTYPE, MyArm.MODEL, ResourceCreatorRegistration(MyArm.new))
Registry.register_resource_creator(Arm.API, MyArm.MODEL, ResourceCreatorRegistration(MyArm.new))
2 changes: 1 addition & 1 deletion examples/complex_module/src/base/my_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@ async def get_geometries(self) -> List[Geometry]:
raise NotImplementedError()


Registry.register_resource_creator(Base.SUBTYPE, MyBase.MODEL, ResourceCreatorRegistration(MyBase.new, MyBase.validate_config))
Registry.register_resource_creator(Base.API, MyBase.MODEL, ResourceCreatorRegistration(MyBase.new, MyBase.validate_config))
4 changes: 2 additions & 2 deletions examples/complex_module/src/gizmo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"""
This file registers the Gizmo subtype with the Viam Registry, as well as the specific MyGizmo model.
This file registers the Gizmo API with the Viam Registry, as well as the specific MyGizmo model.
"""

from viam.components.motor import * # noqa: F403 Need to import motor so the component registers itself
from viam.resource.registry import Registry, ResourceRegistration

from .api import Gizmo, GizmoClient, GizmoService

Registry.register_subtype(ResourceRegistration(Gizmo, GizmoService, lambda name, channel: GizmoClient(name, channel)))
Registry.register_api(ResourceRegistration(Gizmo, GizmoService, lambda name, channel: GizmoClient(name, channel)))
6 changes: 3 additions & 3 deletions examples/complex_module/src/gizmo/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
and the gRPC client that will be able to make calls to this component.

In this example, the ``Gizmo`` abstract class defines what functionality is required for all Gizmos. It extends ``ComponentBase``,
as all component types must. It also defines its specific ``SUBTYPE``, which is used internally to keep track of supported types.
as all component types must. It also defines its specific ``API``, which is used internally to keep track of supported types.

The ``GizmoService`` implements the gRPC service for the Gizmo. This will allow other robots and clients to make requests of the Gizmo.
It extends both from ``GizmoServiceBase`` and ``ResourceRPCServiceBase``. The former is the gRPC service as defined by the proto,
Expand All @@ -28,7 +28,7 @@
from viam.components.component_base import ComponentBase
from viam.components.generic.client import do_command
from viam.resource.rpc_service_base import ResourceRPCServiceBase
from viam.resource.types import RESOURCE_TYPE_COMPONENT, Subtype
from viam.resource.types import RESOURCE_TYPE_COMPONENT, API
from viam.utils import ValueTypes

from ..proto.gizmo_grpc import GizmoServiceBase, GizmoServiceStub
Expand All @@ -49,7 +49,7 @@
class Gizmo(ComponentBase):
"""Example component to use with the example module."""

SUBTYPE: Final = Subtype("acme", RESOURCE_TYPE_COMPONENT, "gizmo")
API: Final = API("acme", RESOURCE_TYPE_COMPONENT, "gizmo")

@abc.abstractmethod
async def do_one(self, arg1: str, **kwargs) -> bool:
Expand Down
4 changes: 2 additions & 2 deletions examples/complex_module/src/gizmo/my_gizmo.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def validate_config(cls, config: ComponentConfig) -> Sequence[str]:
# can raise errors that will be returned to the parent through gRPC. Validate functions can
# also return a sequence of strings representing the implicit dependencies of the resource.
if "invalid" in config.attributes.fields:
raise Exception(f"'invalid' attribute not allowed for model {cls.SUBTYPE}:{cls.MODEL}")
raise Exception(f"'invalid' attribute not allowed for model {cls.API}:{cls.MODEL}")
arg1 = config.attributes.fields["arg1"].string_value
if arg1 == "":
raise Exception("A arg1 attribute is required for Gizmo component.")
Expand Down Expand Up @@ -79,4 +79,4 @@ async def close(self):
LOGGER.info(f"{self.name} is closed.")


Registry.register_resource_creator(Gizmo.SUBTYPE, MyGizmo.MODEL, ResourceCreatorRegistration(MyGizmo.new, MyGizmo.validate_config))
Registry.register_resource_creator(Gizmo.API, MyGizmo.MODEL, ResourceCreatorRegistration(MyGizmo.new, MyGizmo.validate_config))
8 changes: 4 additions & 4 deletions examples/complex_module/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ async def main():
Resource models must be pre-registered. For an example, see the `gizmo.__init__.py` file.
"""
module = Module.from_args()
module.add_model_from_registry(Gizmo.SUBTYPE, MyGizmo.MODEL)
module.add_model_from_registry(SummationService.SUBTYPE, MySummationService.MODEL)
module.add_model_from_registry(Arm.SUBTYPE, MyArm.MODEL)
module.add_model_from_registry(Base.SUBTYPE, MyBase.MODEL)
module.add_model_from_registry(Gizmo.API, MyGizmo.MODEL)
module.add_model_from_registry(SummationService.API, MySummationService.MODEL)
module.add_model_from_registry(Arm.API, MyArm.MODEL)
module.add_model_from_registry(Base.API, MyBase.MODEL)
await module.start()


Expand Down
4 changes: 2 additions & 2 deletions examples/complex_module/src/summation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""
This file registers the Summation subtype with the Viam Registry, as well as the specific MySummation model.
This file registers the Summation API with the Viam Registry, as well as the specific MySummation model.
"""

from viam.resource.registry import Registry, ResourceRegistration

from .api import SummationClient, SummationRPCService, SummationService

Registry.register_subtype(ResourceRegistration(SummationService, SummationRPCService, lambda name, channel: SummationClient(name, channel)))
Registry.register_api(ResourceRegistration(SummationService, SummationRPCService, lambda name, channel: SummationClient(name, channel)))
6 changes: 3 additions & 3 deletions examples/complex_module/src/summation/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

In this example, the ``Summation`` abstract class defines what functionality is required for all Summation services.
It extends ``ServiceBase``, as all service types must.
It also defines its specific ``SUBTYPE``, which is used internally to keep track of supported types.
It also defines its specific ``API``, which is used internally to keep track of supported types.

The ``SummationRPCService`` implements the gRPC service for the Summation service. This will allow other robots and clients to make
requests of the Summation service. It extends both from ``SummationServiceBase`` and ``RPCServiceBase``.
Expand All @@ -27,7 +27,7 @@
from grpclib.server import Stream

from viam.resource.rpc_service_base import ResourceRPCServiceBase
from viam.resource.types import RESOURCE_TYPE_SERVICE, Subtype
from viam.resource.types import RESOURCE_TYPE_SERVICE, API
from viam.services.service_base import ServiceBase

from ..proto.summation_grpc import SummationServiceBase, SummationServiceStub
Expand All @@ -37,7 +37,7 @@
class SummationService(ServiceBase):
"""Example service to use with the example module"""

SUBTYPE: Final = Subtype("acme", RESOURCE_TYPE_SERVICE, "summation")
API: Final = API("acme", RESOURCE_TYPE_SERVICE, "summation")

@abc.abstractmethod
async def sum(self, nums: Sequence[float]) -> float:
Expand Down
2 changes: 1 addition & 1 deletion examples/complex_module/src/summation/my_summation.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceNam
self.subtract = config.attributes.fields["subtract"].bool_value or False


Registry.register_resource_creator(SummationService.SUBTYPE, MySummationService.MODEL, ResourceCreatorRegistration(MySummationService.new))
Registry.register_resource_creator(SummationService.API, MySummationService.MODEL, ResourceCreatorRegistration(MySummationService.new))
4 changes: 2 additions & 2 deletions examples/simple_module/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ async def main():
"""This function creates and starts a new module, after adding all desired resource models.
Resource creators must be registered to the resource registry before the module adds the resource model.
"""
Registry.register_resource_creator(Sensor.SUBTYPE, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new, MySensor.validate_config))
Registry.register_resource_creator(Sensor.API, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new, MySensor.validate_config))

module = Module.from_args()
module.add_model_from_registry(Sensor.SUBTYPE, MySensor.MODEL)
module.add_model_from_registry(Sensor.API, MySensor.MODEL)
await module.start()


Expand Down
35 changes: 23 additions & 12 deletions src/viam/app/data_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ class TabularDataPoint:
resource_name: str
"""The resource name"""

resource_subtype: str
"""The resource subtype. Ex: `rdk:component:sensor`"""
resource_api: str
"""The resource API. Ex: `rdk:component:sensor`"""

purplenicole730 marked this conversation as resolved.
Show resolved Hide resolved
method_name: str
"""The method used for data capture. Ex: `Readings`"""
Expand Down Expand Up @@ -196,7 +196,7 @@ def __str__(self) -> str:
f"TabularDataPoint("
f"robot='{self.robot_name}' (id={self.robot_id}), "
f"part='{self.part_name}' (id={self.part_id}), "
f"resource='{self.resource_name}' ({self.resource_subtype}), "
f"resource='{self.resource_name}' ({self.resource_api}), "
f"method='{self.method_name}', "
f"org={self.organization_id}, "
f"location={self.location_id}, "
Expand All @@ -211,6 +211,15 @@ def __eq__(self, other: object) -> bool:
return str(self) == str(other)
return False

@property
def resource_subtype(self) -> str:
warnings.warn(
"`TabularDataPoint.resource_subtype` is deprecated. Use `TabularDataPoint.resource_api` instead.",
DeprecationWarning,
stacklevel=2,
)
return self.resource_api

def __init__(self, channel: Channel, metadata: Mapping[str, str]):
"""Create a `DataClient` that maintains a connection to app.

Expand Down Expand Up @@ -367,8 +376,9 @@ async def tabular_data_by_mql(
response: TabularDataByMQLResponse = await self._data_client.TabularDataByMQL(request, metadata=self._metadata)
return [bson.decode(bson_bytes) for bson_bytes in response.raw_data]

@_alias_param("resource_api", param_alias="resource_subtype")
async def get_latest_tabular_data(
self, part_id: str, resource_name: str, resource_subtype: str, method_name: str
self, part_id: str, resource_name: str, resource_api: str, method_name: str
purplenicole730 marked this conversation as resolved.
Show resolved Hide resolved
) -> Optional[Tuple[datetime, datetime, Dict[str, ValueTypes]]]:
"""Gets the most recent tabular data captured from the specified data source, as long as it was synced within the last year.

Expand All @@ -377,7 +387,7 @@ async def get_latest_tabular_data(
tabular_data = await data_client.get_latest_tabular_data(
part_id="77ae3145-7b91-123a-a234-e567cdca8910",
resource_name="camera-1",
resource_subtype="rdk:component:camera",
resource_api="rdk:component:camera",
method_name="GetImage"
)

Expand All @@ -392,7 +402,7 @@ async def get_latest_tabular_data(
Args:
part_id (str): The ID of the part that owns the data.
resource_name (str): The name of the requested resource that captured the data. Ex: "my-sensor".
resource_subtype (str): The subtype of the requested resource that captured the data. Ex: "rdk:component:sensor".
resource_api (str): The API of the requested resource that captured the data. Ex: "rdk:component:sensor".
method_name (str): The data capture method name. Ex: "Readings".

Returns:
Expand All @@ -406,18 +416,19 @@ async def get_latest_tabular_data(
"""

request = GetLatestTabularDataRequest(
part_id=part_id, resource_name=resource_name, resource_subtype=resource_subtype, method_name=method_name
part_id=part_id, resource_name=resource_name, resource_subtype=resource_api, method_name=method_name
)
response: GetLatestTabularDataResponse = await self._data_client.GetLatestTabularData(request, metadata=self._metadata)
if not response.payload:
return None
return response.time_captured.ToDatetime(), response.time_synced.ToDatetime(), struct_to_dict(response.payload)

@_alias_param("resource_api", param_alias="resource_subtype")
async def export_tabular_data(
self,
part_id: str,
resource_name: str,
resource_subtype: str,
resource_api: str,
purplenicole730 marked this conversation as resolved.
Show resolved Hide resolved
method_name: str,
start_time: Optional[datetime] = None,
end_time: Optional[datetime] = None,
Expand All @@ -429,7 +440,7 @@ async def export_tabular_data(
tabular_data = await data_client.export_tabular_data(
part_id="<PART-ID>",
resource_name="<RESOURCE-NAME>",
resource_subtype="<RESOURCE-SUBTYPE>",
resource_api="<RESOURCE-API>",
method_name="<METHOD-NAME>",
start_time="<START_TIME>"
end_time="<END_TIME>"
Expand All @@ -440,7 +451,7 @@ async def export_tabular_data(
Args:
part_id (str): The ID of the part that owns the data.
resource_name (str): The name of the requested resource that captured the data.
resource_subtype (str): The subtype of the requested resource that captured the data.
resource_api (str): The API of the requested resource that captured the data.
method_name (str): The data capture method name.
start_time (datetime): Optional start time for requesting a specific range of data.
end_time (datetime): Optional end time for requesting a specific range of data.
Expand All @@ -453,15 +464,15 @@ async def export_tabular_data(

interval = CaptureInterval(start=datetime_to_timestamp(start_time), end=datetime_to_timestamp(end_time))
request = ExportTabularDataRequest(
part_id=part_id, resource_name=resource_name, resource_subtype=resource_subtype, method_name=method_name, interval=interval
part_id=part_id, resource_name=resource_name, resource_subtype=resource_api, method_name=method_name, interval=interval
)
response: List[ExportTabularDataResponse] = await self._data_client.ExportTabularData(request, metadata=self._metadata)

return [
DataClient.TabularDataPoint(
part_id=resp.part_id,
resource_name=resp.resource_name,
resource_subtype=resp.resource_subtype,
resource_api=resp.resource_subtype,
method_name=resp.method_name,
time_captured=resp.time_captured.ToDatetime(),
organization_id=resp.organization_id,
Expand Down
2 changes: 1 addition & 1 deletion src/viam/components/arm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
"Pose",
]

Registry.register_subtype(ResourceRegistration(Arm, ArmRPCService, lambda name, channel: ArmClient(name, channel)))
Registry.register_api(ResourceRegistration(Arm, ArmRPCService, lambda name, channel: ArmClient(name, channel)))
4 changes: 2 additions & 2 deletions src/viam/components/arm/arm.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import abc
from typing import Any, Dict, Final, Optional, Tuple

from viam.resource.types import RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, Subtype
from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT

from ..component_base import ComponentBase
from . import JointPositions, KinematicsFileFormat, Pose
Expand All @@ -26,7 +26,7 @@ class Arm(ComponentBase):
For more information, see `Arm component <https://docs.viam.com/dev/reference/apis/components/arm/>`_.
"""

SUBTYPE: Final = Subtype(RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, "arm") # pyright: ignore [reportIncompatibleVariableOverride]
API: Final = API(RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, "arm") # pyright: ignore [reportIncompatibleVariableOverride]

@abc.abstractmethod
async def get_end_position(
Expand Down
2 changes: 1 addition & 1 deletion src/viam/components/audio_input/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
]


Registry.register_subtype(
Registry.register_api(
ResourceRegistration(
AudioInput,
AudioInputRPCService,
Expand Down
4 changes: 2 additions & 2 deletions src/viam/components/audio_input/audio_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from viam.media.audio import Audio, AudioStream
from viam.proto.component.audioinput import PropertiesResponse
from viam.resource.types import RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, Subtype
from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT
from viam.streams import StreamSource

from ..component_base import ComponentBase
Expand All @@ -22,7 +22,7 @@ class AudioInput(ComponentBase, StreamSource[Audio]):
overridden, it must call the ``super().__init__()`` function.
"""

SUBTYPE: Final = Subtype( # pyright: ignore [reportIncompatibleVariableOverride]
API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, "audio_input"
)

Expand Down
2 changes: 1 addition & 1 deletion src/viam/components/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
"Vector3",
]

Registry.register_subtype(ResourceRegistration(Base, BaseRPCService, lambda name, channel: BaseClient(name, channel)))
Registry.register_api(ResourceRegistration(Base, BaseRPCService, lambda name, channel: BaseClient(name, channel)))
4 changes: 2 additions & 2 deletions src/viam/components/base/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from dataclasses import dataclass
from typing import Any, Dict, Final, Optional

from viam.resource.types import RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, Subtype
from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT

from ..component_base import ComponentBase
from . import Vector3
Expand All @@ -23,7 +23,7 @@ class Base(ComponentBase):
For more information, see `Base component <https://docs.viam.com/dev/reference/apis/components/base/>`_.
"""

SUBTYPE: Final = Subtype( # pyright: ignore [reportIncompatibleVariableOverride]
API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, "base"
)

Expand Down
2 changes: 1 addition & 1 deletion src/viam/components/board/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@

__all__ = ["Board", "Tick", "TickStream"]

Registry.register_subtype(ResourceRegistration(Board, BoardRPCService, lambda name, channel: BoardClient(name, channel)))
Registry.register_api(ResourceRegistration(Board, BoardRPCService, lambda name, channel: BoardClient(name, channel)))
Loading
Loading