UniteLabs
How-to

SDK upgrade

Breaking changes between SDK versions and how to update your code.

SDK 0.19: actions load at the first call

What changed

In SDK 0.18 and earlier, AsyncApiClient got all modules of a service and all their actions in one request. In SDK 0.19 and later, get_service, get_service_by_name and list_services get only the modules. The SDK gets the actions of a module at the first await or call on that module.

This change applies to AsyncApiClient and to unitelabs.sdk.connect.

Before the first await or call, each module is a ModuleProxy and each action is an ActionProxy. These objects have their names, but they do not know the actions or their schemas.

Calling endpoints is unchanged:

await service.module_name.action_name()

await service["Module Name"]["Action Name"]()

Code to change

Code that reads the actions of a module, or the metadata of an action, must await the module or the action first. To find this code, search for .actions, .parameters, .responses, .type, isinstance( and hasattr(.

SDK 0.18 and earlierSDK 0.19 and later
module.actions(await module).actions
module.actions["move_by" + suffix]getattr(module, "move_by" + suffix) or (await module).actions["move_by" + suffix]
module.action.type, and the same for .id, .parameters and .responses(await module.action).type
isinstance(module, Module)isinstance(await module, Module)
hasattr(module, "move_by")"move_by" in (await module).actions

For example, this code lists the actions of a module and their types:

# SDK 0.18 and earlier
for name, action in shaker.shake_controller.actions.items():
    print(name, action.type)

# SDK 0.19 and later
for name, action in (await shaker.shake_controller).actions.items():
    print(name, action.type)

Write (await module).actions, not await module.actions. Python applies await to all of module.actions, and a ModuleProxy has no actions before the await.

Errors occur at a different time

In SDK 0.18 and earlier, a name that is not an action of the module raised AttributeError or KeyError immediately. In SDK 0.19 and later, module.no_such_action and module["No Such Name"] give an ActionProxy. The error occurs at the call or at the await. Thus, getattr(module, name, None) and hasattr(module, name) cannot show if an action exists.

If your code catches these errors, put the try around the call or the await.

The SDK keeps the actions until the process stops

The SDK keeps the actions of each module until the Python process stops. A new get_service call does not get the actions again.

If a connector gets new or changed actions, restart the Python process, for example the Jupyter kernel. If you do not restart it, the SDK can continue to use the old actions.

Code for SDK 0.18 and SDK 0.19

If your code must operate on the two versions, use these forms:

  • Calls of actions, for example await module.action(...)
  • getattr(module, name) for an action name in a variable
  • await client.list_actions(module.id) for all actions of a module. It returns a list of Action objects with name and type.

Last updated