:py:mod:`viam.app.app_client` ============================= .. py:module:: viam.app.app_client Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: viam.app.app_client.RobotPart viam.app.app_client.LogEntry viam.app.app_client.Fragment viam.app.app_client.RobotPartHistoryEntry viam.app.app_client.APIKeyAuthorization viam.app.app_client.AppClient Attributes ~~~~~~~~~~ .. autoapisummary:: viam.app.app_client.LOGGER .. py:data:: LOGGER .. py:class:: RobotPart A class that mirrors the `RobotPart` proto message. Use this class to make the attributes of a `viam.proto.app.RobotPart` more accessible and easier to read/interpret. .. py:property:: proto :type: viam.proto.app.RobotPart .. py:attribute:: id :type: str .. py:attribute:: name :type: str .. py:attribute:: dns_name :type: str .. py:attribute:: secret :type: str .. py:attribute:: robot :type: str .. py:attribute:: location_id :type: str .. py:attribute:: robot_config :type: Optional[Mapping[str, Any]] .. py:attribute:: last_access :type: Optional[datetime.datetime] .. py:attribute:: user_supplied_info :type: Optional[Mapping[str, Any]] .. py:attribute:: main_part :type: bool .. py:attribute:: fqdn :type: str .. py:attribute:: local_fqdn :type: str .. py:attribute:: created_on :type: Optional[datetime.datetime] .. py:attribute:: secrets :type: Optional[List[viam.proto.app.SharedSecret]] .. py:method:: from_proto(robot_part: viam.proto.app.RobotPart) -> typing_extensions.Self :classmethod: Create a `RobotPart` from the .proto defined `RobotPart`. :param robot_part: The object to copy from. :type robot_part: viam.proto.app.RobotPart :returns: The `RobotPart`. :rtype: RobotPart .. py:class:: LogEntry A class that mirrors the `LogEntry` proto message. Use this class to make the attributes of a `viam.proto.app.LogEntry` more accessible and easier to read/interpret. .. py:property:: proto :type: viam.proto.common.LogEntry .. py:attribute:: host :type: str .. py:attribute:: level :type: str .. py:attribute:: time :type: Optional[datetime.datetime] .. py:attribute:: logger_name :type: str .. py:attribute:: message :type: str .. py:attribute:: caller :type: Optional[Mapping[str, Any]] .. py:attribute:: stack :type: str .. py:attribute:: fields :type: Optional[List[Mapping[str, Any]]] .. py:method:: from_proto(log_entry: viam.proto.common.LogEntry) -> typing_extensions.Self :classmethod: Create a `LogEntry` from the .proto defined `LogEntry`. :param log_entry: The object to copy from. :type log_entry: viam.proto.app.LogEntry :returns: The `LogEntry`. :rtype: LogEntry .. py:class:: Fragment A class that mirrors the `Fragment` proto message. Use this class to make the attributes of a `viam.proto.app.RobotPart` more accessible and easier to read/interpret. .. py:property:: proto :type: viam.proto.app.Fragment .. py:attribute:: id :type: str .. py:attribute:: name :type: str .. py:attribute:: fragment :type: Optional[Mapping[str, Any]] .. py:attribute:: organization_owner :type: str .. py:attribute:: public :type: bool .. py:attribute:: created_on :type: Optional[datetime.datetime] .. py:attribute:: organization_name :type: str .. py:attribute:: robot_part_count :type: int .. py:attribute:: organization_count :type: int .. py:attribute:: only_used_by_owner :type: bool .. py:method:: from_proto(fragment: viam.proto.app.Fragment) -> typing_extensions.Self :classmethod: Create a `Fragment` from the .proto defined `Fragment`. :param fragment: The object to copy from. :type fragment: viam.proto.app.Fragment :returns: The `Fragment`. :rtype: Fragment .. py:class:: RobotPartHistoryEntry A class that mirrors the `RobotPartHistoryEntry` proto message. Use this class to make the attributes of a `viam.proto.app.RobotPartHistoryEntry` more accessible and easier to read/interpret. .. py:property:: proto :type: viam.proto.app.RobotPartHistoryEntry .. py:attribute:: part :type: str .. py:attribute:: robot :type: str .. py:attribute:: when :type: Optional[datetime.datetime] .. py:attribute:: old :type: Optional[RobotPart] .. py:method:: from_proto(robot_part_history_entry: viam.proto.app.RobotPartHistoryEntry) -> typing_extensions.Self :classmethod: Create a `RobotPartHistoryEntry` from the .proto defined `RobotPartHistoryEntry`. :param robot_part_history_entry: The object to copy from. :type robot_part_history_entry: viam.proto.app.RobotPartHistoryEntry :returns: The `RobotPartHistoryEntry`. :rtype: RobotPartHistoryEntry .. py:class:: APIKeyAuthorization(role: Union[Literal[owner], Literal[operator]], resource_type: Union[Literal[organization], Literal[location], Literal[robot]], resource_id: str) A class with the necessary authorization data for creating an API key. Use this class when constructing API key authorizations to minimize the risk of malformed or missing data. .. py:class:: AppClient(channel: grpclib.client.Channel, metadata: Mapping[str, str], location_id: Optional[str] = None) gRPC client for method calls to app. Constructor is used by `ViamClient` to instantiate relevant service stub. Calls to `AppClient` methods should be made through `ViamClient`. Establish a Connection:: import asyncio from viam.rpc.dial import DialOptions, Credentials from viam.app.viam_client import ViamClient async def connect() -> ViamClient: # Replace "" (including brackets) with your API key and "" with your API key ID dial_options = DialOptions.with_api_key("", "") return await ViamClient.create_from_dial_options(dial_options) async def main(): # Make a ViamClient viam_client = await connect() # Instantiate an AppClient called "cloud" to run cloud app API methods on cloud = viam_client.app_client viam_client.close() if __name__ == '__main__': asyncio.run(main()) .. py:method:: create_organization(name: str) -> viam.proto.app.Organization :abstractmethod: :async: .. py:method:: list_organizations() -> List[viam.proto.app.Organization] :async: List the organization(s) the user is an authorized owner of. :: org_list = await cloud.list_organizations() :returns: The list of organizations. :rtype: List[viam.proto.app.Organization] .. py:method:: list_organizations_by_user(user_id: str) -> List[viam.proto.app.OrgDetails] :abstractmethod: :async: .. py:method:: get_organization(org_id: Optional[str] = None) -> viam.proto.app.Organization :async: Return details about the requested organization. :param org_id: ID of the organization to query. If None, defaults to the currently-authed org. :type org_id: Optional[str] :raises GRPCError: If the provided org_id is invalid, or not currently authed to. :returns: The requested organization. :rtype: viam.proto.app.Organization .. py:method:: get_organization_namespace_availability(public_namespace: str) -> bool :async: Check the availability of an organization namespace. :: available = await cloud.get_organization_namespace_availability( public_namespace="my-cool-organization") :param public_namespace: Organization namespace to check. Namespaces can only contain lowercase lowercase alphanumeric and dash characters. :type public_namespace: str :raises GRPCError: If an invalid namespace (e.g., "") is provided. :returns: True if the provided namespace is available. :rtype: bool .. py:method:: update_organization(name: Optional[str] = None, public_namespace: Optional[str] = None, region: Optional[str] = None, cid: Optional[str] = None) -> viam.proto.app.Organization :async: Updates organization details. :param name: If provided, updates the org's name. :type name: Optional[str] :param public_namespace: If provided, sets the org's namespace if it hasn't already been set. :type public_namespace: Optional[str] :param region: If provided, updates the org's region. :type region: Optional[str] :param cid: If provided, update's the org's CRM ID. :type cid: Optional[str] :raises GRPCError: If the org's namespace has already been set, or if the provided namespace is already taken. :returns: The updated organization. :rtype: viam.proto.app.Organization .. py:method:: delete_organization(org_id: Optional[str] = None) -> None :abstractmethod: :async: .. py:method:: list_organization_members() -> Tuple[List[viam.proto.app.OrganizationMember], List[viam.proto.app.OrganizationInvite]] :async: List the members and invites of the currently authed-to organization. :: member_list, invite_list = await cloud.list_organization_members() :returns: A tuple containing two lists; the first [0] of organization members, and the second [1] of organization invites. :rtype: Tuple[List[viam.proto.app.OrganizationMember], List[viam.proto.app.OrganizationInvite]] .. py:method:: create_organization_invite(email: str, authorizations: Optional[List[viam.proto.app.Authorization]] = None, send_email_invite=True) -> viam.proto.app.OrganizationInvite :async: Creates an organization invite and sends it via email. :: await cloud.create_organization_invite("youremail@email.com") :param email: The email address to send the invite to. :type email: str :param authorizations: Specifications of the authorizations to include in the invite. If not provided, full owner permissions will be granted. :type authorizations: Optional[List[viam.proto.app.Authorization]] :param send_email_invite: Whether or not an email should be sent to the recipient of an invite. The user must accept the email to be added to the associated authorizations. When set to false, the user automatically receives the associated authorization on the next login of the user with the associated email address. :type send_email_invite: Optional[bool] :raises GRPCError: if an invalid email is provided, or if the user is already a member of the org. .. py:method:: update_organization_invite_authorizations(email: str, add_authorizations: Optional[List[viam.proto.app.Authorization]] = None, remove_authorizations: Optional[List[viam.proto.app.Authorization]] = None) -> viam.proto.app.OrganizationInvite :async: Update the authorizations attached to an organization invite that has already been created. Note that an invite can only have one authorization at each resource (e.g., organization, location, robot, etc.) level and must have at least one authorization overall. :: from viam.proto.app import Authorization authorization_to_add = Authorization( authorization_type="some type of auth", authorization_id="identifier", resource_type="abc", resource_id="resource-identifier123", identity_id="id12345", organization_id="org_id_123" ) update_invite = await cloud.update_organization_invite_authorizations( email="notarealemail@viam.com", add_authorizations =[authorization_to_add] ) :param email: Email of the user the invite was sent to. :type email: str :param add_authorizations: Optional list of authorizations to add to the invite. :type add_authorizations: Optional[List[viam.proto.app.Authorization]] :param remove_authorizations: Optional list of authorizations to remove from the invite. :type remove_authorizations: Optional[List[viam.proto.app.Authorization]] :raises GRPCError: If no authorizations are passed or if an invalid combination of authorizations is passed (e.g. an authorization to remove when the invite only contains one authorization). :returns: The updated invite. :rtype: viam.proto.app.OrganizationInvite .. py:method:: delete_organization_member(user_id: str) -> None :async: Remove a member from the organization. :: member_list, invite_list = await cloud.list_organization_members() first_user_id = member_list[0].user_id await cloud.delete_organization_member(first_user_id) :param user_id: The ID of the user to remove. :type user_id: str .. py:method:: delete_organization_invite(email: str) -> None :async: Deletes a pending organization invite. :: await cloud.delete_organization_invite("youremail@email.com") :param email: The email address the pending invite was sent to. :type email: str :raises GRPCError: If no pending invite is associated with the provided email address. .. py:method:: resend_organization_invite(email: str) -> viam.proto.app.OrganizationInvite :async: Re-sends a pending organization invite email. :: await cloud.resend_organization_invite("youremail@email.com") :param email: The email address associated with the invite. :type email: str :raises GRPCError: If no pending invite is associated with the provided email address. .. py:method:: create_location(name: str, parent_location_id: Optional[str] = None) -> viam.proto.app.Location :async: Create and name a location under the currently authed-to organization and the specified parent location. :: my_new_location = await cloud.create_location(name="Robotville", parent_location_id="111ab12345") :param name: Name of the location. :type name: str :param parent_location_id: Optional parent location to put the location under. Defaults to a root-level location if no location ID is provided. :type parent_location_id: Optional[str] :raises GRPCError: If either an invalid name (e.g., ""), or parent location ID (e.g., a nonexistent ID) is passed. :returns: The newly created location. :rtype: viam.proto.app.Location .. py:method:: get_location(location_id: Optional[str] = None) -> viam.proto.app.Location :async: Get a location. :: location = await cloud.get_location(location_id="123ab12345") :param location_id: ID of the location to get. Defaults to the location ID provided at `AppClient` instantiation. :type location_id: Optional[str] :raises GRPCError: If an invalid location ID is passed or if one isn't passed and there was no location ID provided at `AppClient` instantiation. :returns: The location. :rtype: viam.proto.app.Location .. py:method:: update_location(location_id: str, name: Optional[str] = None, parent_location_id: Optional[str] = None) -> viam.proto.app.Location :async: Change the name of a location and/or assign it a new parent location. :: # The following line takes the location with ID "abc12abcde" and moves it to be a # sub-location of the location with ID "xyz34xxxxx" my_updated_location = await cloud.update_location( location_id="abc12abcde", name="", parent_location_id="xyz34xxxxx", ) # The following line changes the name of the location without changing its parent location my_updated_location = await cloud.update_location( location_id="abc12abcde", name="Land Before Robots" ) # The following line moves the location back up to be a top level location without changing its name my_updated_location = await cloud.update_location( location_id="abc12abcde", name="", parent_location_id="" ) :param location_id: ID of the location to update. Must be specified. :type location_id: str :param name: Optional new name to be updated on the location. Defaults to the empty string "" (i.e., the name doesn't change). :type name: Optional[str] :param parent_location_id: Optional ID of new parent location to move the location under. Defaults to the empty string "" (i.e., no new parent location is assigned). :type parent_location_id: Optional[str] :raises GRPCError: If either an invalid location ID, name, or parent location ID is passed. :returns: The newly updated location. :rtype: viam.proto.app.Location .. py:method:: delete_location(location_id: str) -> None :async: Delete a location. :: await cloud.delete_location(location_id="abc12abcde") :param location_id: ID of the location to delete. Must be specified. :type location_id: str :raises GRPCError: If an invalid location ID is passed. .. py:method:: list_locations() -> List[viam.proto.app.Location] :async: Get a list of all locations under the currently authed-to organization. :: locations = await cloud.list_locations() :returns: The list of locations. :rtype: List[viam.proto.app.Location] .. py:method:: share_location() :abstractmethod: :async: .. py:method:: unshare_location() :abstractmethod: :async: .. py:method:: location_auth(location_id: Optional[str] = None) -> viam.proto.app.LocationAuth :async: Get a location's `LocationAuth` (location secret(s)). :: loc_auth = await cloud.location_auth(location_id="123xy12345") :param location_id: ID of the location to retrieve `LocationAuth` from. Defaults to the location ID provided at `AppClient` instantiation. :type location_id: str :raises GRPCError: If an invalid location ID is passed or if one isn't passed and there was no location ID provided at `AppClient` instantiation. :returns: The `LocationAuth` containing location secrets. :rtype: viam.proto.app.LocationAuth .. py:method:: create_location_secret(location_id: Optional[str] = None) -> viam.proto.app.LocationAuth :async: Create a new location secret. :: new_loc_auth = await cloud.create_location_secret() :param location_id: ID of the location to generate a new secret for. Defaults to the location ID provided at `AppClient` instantiation. :type location_id: Optional[str] :raises GRPCError: If an invalid location ID is passed or one isn't passed and there was no location ID provided at `AppClient` instantiation. :returns: The specified location's `LocationAuth` containing the newly created secret. :rtype: viam.proto.app.LocationAuth .. py:method:: delete_location_secret(secret_id: str, location_id: Optional[str] = None) -> None :async: Delete a location secret. :: await cloud.delete_location_secret( secret_id="abcd123-456-7890ab-cxyz98-989898xyzxyz") :param location_id: ID of the location to delete secret from. Defaults to the location ID provided at `AppClient` instantiation. :type location_id: str :param secret_id: ID of the secret to delete. :type secret_id: str :raises GRPCError: If either an invalid location ID or secret ID is passed or a location ID isn't passed and there was no location ID provided at `AppClient` instantiation. .. py:method:: get_robot(robot_id: str) -> viam.proto.app.Robot :async: Get a robot. :: robot = await cloud.get_robot(robot_id="1a123456-x1yz-0ab0-a12xyzabc") :param robot_id: ID of the robot to get. :type robot_id: str :raises GRPCError: If an invalid robot ID is passed. :returns: The robot. :rtype: viam.proto.app.Robot .. py:method:: get_rover_rental_robots() -> List[viam.proto.app.RoverRentalRobot] :async: Returns a list of rover rental robots within an org. :: rental_robots = await cloud.get_rover_rental_robots() :returns: The list of rover rental robots. :rtype: List[viam.proto.app.RoverRentalRobot] .. py:method:: get_robot_parts(robot_id: str) -> List[RobotPart] :async: Get a list of all the parts under a specific robot. :: list_of_parts = await cloud.get_robot_parts( robot_id="1a123456-x1yz-0ab0-a12xyzabc") :param robot_id: ID of the robot to get parts from. :type robot_id: str :raises GRPCError: If an invalid robot ID is passed. :returns: The list of robot parts. :rtype: List[viam.app.app_client.RobotPart] .. py:method:: get_robot_part(robot_part_id: str, dest: Optional[str] = None, indent: int = 4) -> RobotPart :async: Get a robot part. :: my_robot_part = await cloud.get_robot_part( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22") :param robot_part_id: ID of the robot part to get. :type robot_part_id: str :param dest: Optional filepath to write the robot part's config file in JSON format to. :type dest: Optional[str] :param indent: Size (in number of spaces) of indent when writing config to `dest`. Defaults to 4. :type indent: int :raises GRPCError: If an invalid robot part ID is passed. :returns: The robot part. :rtype: viam.app.app_client.RobotPart .. py:method:: get_robot_part_logs(robot_part_id: str, filter: Optional[str] = None, dest: Optional[str] = None, errors_only: bool = True, num_log_entries: int = 100) -> List[LogEntry] :async: Get the logs associated with a robot part. :: part_logs = await cloud.get_robot_part_logs( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22", num_log_entries=20) :param robot_part_id: ID of the robot part to get logs from. :type robot_part_id: str :param filter: Only include logs with messages that contain the string `filter`. Defaults to empty string "" (i.e., no filter). :type filter: Optional[str] :param dest: Optional filepath to write the log entries to. :type dest: Optional[str] :param errors_only: Boolean specifying whether or not to only include error logs. Defaults to True. :type errors_only: bool :param num_log_entries: Number of log entries to return. Passing 0 returns all logs. Defaults to 100. All logs or the first `num_log_entries` logs will be returned, whichever comes first. :type num_log_entries: int :raises GRPCError: If an invalid robot part ID is passed. :returns: The list of log entries. :rtype: List[viam.app.app_client.LogEntry] .. py:method:: tail_robot_part_logs(robot_part_id: str, errors_only: bool = True, filter: Optional[str] = None) -> viam.app._logs._LogsStream[List[LogEntry]] :async: Get an asynchronous iterator that receives live robot part logs. :: logs_stream = await cloud.tail_robot_part_logs( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22") :param robot_part_id: ID of the robot part to retrieve logs from. :type robot_part_id: str :param errors_only: Boolean specifying whether or not to only include error logs. Defaults to True. :type errors_only: bool :param filter: Only include logs with messages that contain the string `filter`. Defaults to empty string "" (i.e., no filter). :type filter: Optional[str] :returns: The asynchronous iterator receiving live robot part logs. :rtype: _LogsStream[List[LogEntry]] .. py:method:: get_robot_part_history(robot_part_id: str) -> List[RobotPartHistoryEntry] :async: Get a list containing the history of a robot part. :: part_history = await cloud.get_robot_part_history( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22") :param robot_part_id: ID of the robot part to retrieve history from. :type robot_part_id: str :raises GRPCError: If an invalid robot part ID is provided. :returns: The list of the robot part's history. :rtype: List[viam.app.app_client.RobotPartHistoryEntry] .. py:method:: update_robot_part(robot_part_id: str, name: str, robot_config: Optional[Mapping[str, Any]] = None) -> RobotPart :async: Change the name and assign an optional new configuration to a robot part. :: my_robot_part = await cloud.update_robot_part( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22") :param robot_part_id: ID of the robot part to update. :type robot_part_id: str :param name: New name to be updated on the robot part. :type name: str :param robot_config: Optional new config represented as a dictionary to be updated on the robot part. The robot part's config will remain as is (no change) if one isn't passed. :type robot_config: Mapping[str, Any] :raises GRPCError: If either an invalid robot part ID, name, or config is passed. :returns: The newly updated robot part. :rtype: viam.app.app_client.RobotPart .. py:method:: new_robot_part(robot_id: str, part_name: str) -> str :async: Create a new robot part. :: new_part_id = await cloud.new_robot_part( robot_id="1a123456-x1yz-0ab0-a12xyzabc", part_name="myNewSubPart") :param robot_id: ID of the the robot to create a new part for. :type robot_id: str :param part_name: Name of the new part. :type part_name: str :raises GRPCError: If either an invalid robot ID or name is passed. :returns: The new robot part's ID. :rtype: str .. py:method:: delete_robot_part(robot_part_id: str) -> None :async: Delete the specified robot part. :: await cloud.delete_robot_part( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22") :param robot_part_id: ID of the robot part to delete. Must be specified. :type robot_part_id: str :raises GRPCError: If an invalid robot part ID is passed. .. py:method:: mark_part_as_main(robot_part_id: str) -> None :async: Mark a robot part as the main part of a robot. :: await cloud.mark_part_as_main( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22") :param robot_part_id: ID of the robot part to mark as main. :type robot_part_id: str :raises GRPCError: If an invalid robot part ID is passed. .. py:method:: mark_part_for_restart(robot_part_id: str) -> None :async: Mark the specified robot part for restart. :: await cloud.mark_part_for_restart( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22") :param robot_part_id: ID of the robot part to mark for restart. :type robot_part_id: str :raises GRPCError: If an invalid robot part ID is passed. .. py:method:: create_robot_part_secret(robot_part_id: str) -> RobotPart :async: Create a robot part secret. :: part_with_new_secret = await cloud.create_robot_part_secret( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22") :param robot_part_id: ID of the robot part to create a secret for. :type robot_part_id: str :raises GRPCError: If an invalid robot part ID is passed. :returns: The robot part the new secret was generated for. :rtype: viam.app.app_client.RobotPart .. py:method:: delete_robot_part_secret(robot_part_id: str, secret_id: str) -> None :async: Delete a robot part secret. :: await cloud.delete_robot_part_secret( robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22", secret_id="123xyz12-abcd-4321-12ab-12xy1xyz12xy") :param robot_part_id: ID of the robot part to delete the secret from. :type robot_part_id: str :param secret_id: ID of the secret to delete. :type secret_id: str :raises GRPCError: If an invalid robot part ID or secret ID is passed. .. py:method:: list_robots(location_id: Optional[str] = None) -> List[viam.proto.app.Robot] :async: Get a list of all robots under the specified location. :: list_of_machines = await cloud.list_robots(location_id="123ab12345") :param location_id: ID of the location to retrieve the robots from. Defaults to the location ID provided at `AppClient` instantiation. :type location_id: Optional[str] :raises GRPCError: If an invalid location ID is passed or one isn't passed and there was no location ID provided at `AppClient` instantiation. :returns: The list of robots. :rtype: List[viam.proto.app.Robot] .. py:method:: new_robot(name: str, location_id: Optional[str] = None) -> str :async: Create a new robot. :: new_machine_id = await cloud.new_robot(name="beepboop") :param name: Name of the new robot. :type name: str :param location_id: ID of the location under which to create the robot. Defaults to the current authorized location. :type location_id: Optional[str] :raises GRPCError: If an invalid location ID is passed or one isn't passed and there was no location ID provided at `AppClient` instantiation. :returns: The new robot's ID. :rtype: str .. py:method:: update_robot(robot_id: str, name: str, location_id: Optional[str] = None) -> viam.proto.app.Robot :async: Change the name of an existing robot. :: updated_robot = await cloud.update_robot( robot_id="1a123456-x1yz-0ab0-a12xyzabc", name="Orange-Robot") :param robot_id: ID of the robot to update. :type robot_id: str :param name: New name to be updated on the robot. :type name: str :param location_id: ID of the location under which the robot exists. Defaults to the location ID provided at `AppClient` instantiation :type location_id: Optional[str] :raises GRPCError: If either an invalid robot ID, name, or location ID is passed or a location ID isn't passed and there was no location ID provided at `AppClient` instantiation. :returns: The newly updated robot. :rtype: viam.proto.app.Robot .. py:method:: delete_robot(robot_id: str) -> None :async: Delete the specified robot. :: await cloud.delete_robot(robot_id="1a123456-x1yz-0ab0-a12xyzabc") :param robot_id: ID of the robot to delete. :type robot_id: str :raises GRPCError: If an invalid robot ID is passed. .. py:method:: list_fragments(show_public: bool = True) -> List[Fragment] :async: Get a list of fragments under the currently authed-to organization. :: fragments_list = await cloud.list_fragments(show_public=False) :param show_public: Optional boolean specifying whether or not to only show public fragments. If True, only public fragments will return. If False, only private fragments will return. Defaults to True. :returns: The list of fragments. :rtype: List[viam.app.app_client.Fragment] .. py:method:: get_fragment(fragment_id: str) -> Fragment :async: Get a fragment. :: # Get a fragment and print its name and when it was created. the_fragment = await cloud.get_fragment( fragment_id="12a12ab1-1234-5678-abcd-abcd01234567") print("Name: ", the_fragment.name, "\nCreated on: ", the_fragment.created_on) :param fragment_id: ID of the fragment to get. :type fragment_id: str :raises GRPCError: If an invalid fragment ID is passed. :returns: The fragment. :rtype: viam.app.app_client.Fragment .. py:method:: create_fragment(name: str, config: Optional[Mapping[str, Any]] = None) -> Fragment :async: Create a new private fragment. :: new_fragment = await cloud.create_fragment( name="cool_smart_machine_to_configure_several_of") :param name: Name of the fragment. :type name: str :param config: Optional Dictionary representation of new config to assign to specified fragment. Can be assigned by updating the fragment. :type config: Optional[Mapping[str, Any]] :raises GRPCError: If an invalid name is passed. :returns: The newly created fragment. :rtype: viam.app.app_client.Fragment .. py:method:: update_fragment(fragment_id: str, name: str, config: Optional[Mapping[str, Any]] = None, public: Optional[bool] = None) -> Fragment :async: Update a fragment name AND its config and/or visibility. :: updated_fragment = await cloud.update_fragment( fragment_id="12a12ab1-1234-5678-abcd-abcd01234567", name="better_name") :param fragment_id: ID of the fragment to update. :type fragment_id: str :param name: New name to associate with the fragment. :type name: str :param config: Optional Dictionary representation of new config to assign to specified fragment. Not passing this parameter will leave the fragment's config unchanged. :type config: Optional[Mapping[str, Any]] :param public: Boolean specifying whether the fragment is public. Not passing this parameter will leave the fragment's visibility unchanged. A fragment is private by default when created. :type public: bool :raises GRPCError: if an invalid ID, name, or config is passed. :returns: The newly updated fragment. :rtype: viam.app.app_client.Fragment .. py:method:: delete_fragment(fragment_id: str) -> None :async: Delete a fragment. :: await cloud.delete_fragment( fragment_id="12a12ab1-1234-5678-abcd-abcd01234567") :param fragment_id: ID of the fragment to delete. :type fragment_id: str :raises GRPCError: If an invalid fragment ID is passed. .. py:method:: add_role(identity_id: str, role: Union[Literal[owner], Literal[operator]], resource_type: Union[Literal[organization], Literal[location], Literal[robot]], resource_id: str) -> None :async: Add a role under the currently authed-to organization. :: await cloud.add_role( identity_id="abc01234-0123-4567-ab12-a11a00a2aa22", role="owner", resource_type="location", resource_id="111ab12345") :param identity_id: ID of the entity the role belongs to (e.g., a user ID). :type identity_id: str :param role: The role to add. :type role: Union[Literal["owner"], Literal["operator"]] :param resource_type: Type of the resource to add role to. Must match `resource_id`. :type resource_type: Union[Literal["organization"], Literal["location"], Literal["robot"]] :param resource_id: ID of the resource the role applies to (i.e., either an organization, location, or robot ID). :type resource_id: str :raises GRPCError: If either an invalid identity ID, role ID, resource type, or resource ID is passed. .. py:method:: remove_role(identity_id: str, role: Union[Literal[owner], Literal[operator]], resource_type: Union[Literal[organization], Literal[location], Literal[robot]], resource_id: str) -> None :async: Remove a role under the currently authed-to organization. :: await cloud.remove_role( identity_id="abc01234-0123-4567-ab12-a11a00a2aa22", role="owner", resource_type="location", resource_id="111ab12345") :param identity_id: ID of the entity the role belongs to (e.g., a user ID). :type identity_id: str :param role: The role to add. :type role: Union[Literal["owner"], Literal["operator"]] :param resource_type: Type of the resource to add role to. Must match `resource_id`. :type resource_type: Union[Literal["organization"], Literal["location"], Literal["robot"]] :param resource_id: ID of the resource the role applies to (i.e., either an organization, location, or robot ID). :type resource_id: str :raises GRPCError: If either an invalid identity ID, role ID, resource type, or resource ID or is passed. .. py:method:: list_authorizations(resource_ids: Optional[List[str]] = None) -> List[viam.proto.app.Authorization] :async: List all authorizations under a specific resource (or resources) within the currently authed-to organization. If no resource IDs are provided, all resource authorizations within the organizations are returned. :: list_of_auths = await cloud.list_authorizations( resource_ids=["1a123456-x1yz-0ab0-a12xyzabc"]) :param resource_ids: IDs of the resources to retrieve authorizations from. If None, defaults to all resources. :type resource_ids: Optional[List[str]] :raises GRPCError: If an invalid resource ID is passed. :returns: The list of authorizations. :rtype: List[viam.proto.app.Authorization] .. py:method:: check_permissions(permissions: List[viam.proto.app.AuthorizedPermissions]) -> List[viam.proto.app.AuthorizedPermissions] :async: Checks validity of a list of permissions. :: from viam.proto.app import AuthorizedPermissions # Check whether the entity you're currently authenticated to has permission to control and/or # read logs from robots in the "organization-identifier123" org permissions = [AuthorizedPermissions(resource_type="organization", resource_id="organization-identifier123", permissions=["control_robot", "read_robot_logs"])] filtered_permissions = await cloud.check_permissions(permissions) :param permissions: the permissions to validate (e.g., "read_organization", "control_robot") :type permissions: List[viam.proto.app.AuthorizedPermissions] :raises GRPCError: If the list of permissions to validate is empty. :returns: The permissions argument, with invalid permissions filtered out. :rtype: List[viam.proto.app.AuthorizedPermissions] .. py:method:: create_module(name: str) -> Tuple[str, str] :async: Create a module under the currently authed-to organization. :: new_module = await cloud.create_module(name="cool_new_hoverboard_module") print("Module ID:", new_module[0]) :param name: The name of the module. Must be unique within your organization. :type name: str :raises GRPCError: If an invalid name (e.g., "") is passed. :returns: A tuple containing the ID [0] of the new module and its URL [1]. :rtype: Tuple[str, str] .. py:method:: update_module(module_id: str, url: str, description: str, models: Optional[List[viam.proto.app.Model]], entrypoint: str, organization_id: Optional[str] = None, public: bool = False) -> str :async: Update the documentation URL, description, models, entrypoint, and/or the visibility of a module. :: url_of_my_module = await cloud.update_module( module_id="my-group:cool_new_hoverboard_module", url="https://docsformymodule.viam.com", description="A base to support hoverboards.", entrypoint="exec") :param module_id: ID of the module being updated, containing module name (e.g., "my-module") or namespace and module name (e.g., "my-org:my-module"). :type module_id: str :param url: The url to reference for documentation and code (NOT the url of the module itself). :type url: str :param description: A short description of the module that explains its purpose. :type description: str :param models: list of models that are available in the module. :type models: Optional[List[viam.proto.app.Model]] :param entrypoint: The executable to run to start the module program. :type entrypoint: str :param public: The visibility that should be set for the module. Defaults to False (private). :type public: bool :raises GRPCError: If either an invalid module ID, URL, list of models, or organization ID is passed. :returns: The URL of the newly updated module. :rtype: str .. py:method:: upload_module_file(module_file_info: Optional[viam.proto.app.ModuleFileInfo], file: bytes) -> str :async: Upload a module file :: file_id = await cloud.upload_module_file(file=b"") :param module_file_info: Relevant metadata. :type module_file_info: Optional[viam.proto.app.ModuleFileInfo] :param file: Bytes of file to upload. :type file: bytes :returns: ID of uploaded file. :rtype: str .. py:method:: get_module(module_id: str) -> viam.proto.app.Module :async: Get a module. :: the_module = await cloud.get_module(module_id="my-cool-modular-base") :param module_id: ID of the module being retrieved, containing module name or namespace and module name. :type module_id: str :raises GRPCError: If an invalid module ID is passed. :returns: The module. :rtype: viam.proto.app.Module .. py:method:: list_modules() -> List[viam.proto.app.Module] :async: List the modules under the currently authed-to organization. :: modules_list = await cloud.list_modules() :returns: The list of modules. :rtype: List[viam.proto.app.Module] .. py:method:: create_key(authorizations: List[APIKeyAuthorization], name: Optional[str] = None) -> Tuple[str, str] :async: Creates a new API key. :: from viam.app.app_client import APIKeyAuthorization auth = APIKeyAuthorization( role="owner", resource_type="robot", resource_id="your-robot-id123" ) api_key, api_key_id = cloud.create_key([auth], "my_key") :param authorizations: A list of authorizations to associate with the key. :type authorizations: List[viam.proto.app.Authorization] :param name: A name for the key. If None, defaults to the current timestamp. :type name: Optional[str] :raises GRPCError: If the authorizations list is empty. :returns: The api key and api key ID. :rtype: Tuple[str, str] .. py:method:: create_key_from_existing_key_authorizations(id: str) -> Tuple[str, str] :async: Creates a new API key with an existing key's authorizations :: api_key, api_key_id = cloud.create_key_from_existing_key_authorizations( id="INSERT YOUR API KEY ID") :param id: the ID of the API key to duplication authorizations from :type id: str :returns: The API key and API key id :rtype: Tuple[str, str] .. py:method:: list_keys() -> List[viam.proto.app.APIKeyWithAuthorizations] :async: Lists all keys for the currently-authed-to org. :: keys = cloud.list_keys() :returns: The existing API keys and authorizations. :rtype: List[viam.proto.app.APIKeyWithAuthorizations]