Skip to content

Commands

INCOMPLETE DOCUMENTATION

These things are currently missing compared to the existing docs:

  1. Alternate Javascript import (window.__TAURI__.pytauri)
  2. More options for creating the app/ invoke_handler

Commands can be registered using the command handler decorator as seen below.

py
from pytauri import AppHandle, Commands

commands = Commands()


@commands.command()
async def fire_command(body: bytes) -> bytes:
    pass


@commands.command()
async def fire_other_command(body: bytes, app_handle: AppHandle) -> bytes:
    pass

To handle IPC correctly, the function follows strict rules:

  1. They must be asynchronous
  2. There must be a typed body argument of type bytes (more on this later.)
  3. An optional typed app_handle argument of type AppHandle can be used to get access to the current app handle instance.
  4. The command must return type bytes

Deserialization

Sending raw bytes is useful for images or files, however in most cases we want more readable information. Under the hood PyTauri uses Pydantic for deserializing the body of a command. This means that any RootmModel or BaseModel from Pydantic can also be used for typing either the body or return variable.

py
from pydantic import BaseModel, RootModel
from pytauri import AppHandle, Commands

commands = Commands()

class User(BaseModel):
    name: str
    email: str

Roles = RootModel[list[str]]


@commands.command()
async def get_user_roles(body: User) -> Roles:
    pass

Registering the commands

In order to call the commands from the frontend, an async runtime is required. anyio.from_thread.start_blocking_portal is used as an example, but other equivalent functions can be used.

py
from anyio.from_thread import start_blocking_portal
from pytauri import BuilderArgs, Commands, builder_factory, context_factory

commands = Commands()


with start_blocking_portal("asyncio") as portal:  # or "trio"
    builder = builder_factory()
    app = builder.build(
        BuilderArgs(
            context_factory(),
            invoke_handler=commands.generate_handler(portal),
        )
    )
    app.run()

Note that portal should not be closed while the app is running.

Calling from the frontend

PyTauri has two functions for calling a command: pyInvoke and rawPyInvoke. rawPyInvoke allows sending and receiving of binary data.

ts
import {pyInvoke} from "tauri-plugin-pytauri-api";

interface User {
    name: string;
    email: string;
}

const user: User = {name: "John", email: "john@example.com"};

const output = await pyInvoke<string[]>("get_user_roles", user);

Returning errors to the frontend

Any [InvokeException] raised in a command will automatically return the function with the supplied error message.

py
from pytauri import Commands
from pytauri.ipc import InvokeException

commands = Commands()


@commands.command()
async def invalid_user() -> bytes:
    raise InvokeException("User not found")