disguise developers

Designer Plugins

Plugins for Disguise Designer software.

designer-plugin Reference

Table of Contents


Publish

DesignerPlugin

Publish a plugin via DNS-SD so the Disguise Designer application can discover it.

Use as a context manager (sync or async) to register and unregister the service
automatically.

Constructor

init

__init__(name: str, port: int, hostname: str | None = None, url: str | None = None, requires_session: bool = False, is_disguise: bool = False)

Static Methods

default_init

default_init(port: int, hostname: str | None = None) → 'DesignerPlugin'

Initialize the plugin options with the values in d3plugin.json.

Reads name, url, requiresSession, and isDisguise from ./d3plugin.json
in the current working directory.

Parameters:

NameTypeDescription
portintThe port number to publish the plugin on.
hostnamestr | NoneOptional hostname override. Defaults to the machine hostname.

Returns: A DesignerPlugin instance configured from d3plugin.json.

Example:

# Reads name/url from ./d3plugin.json, uses provided port
with DesignerPlugin.default_init(port=9999) as plugin:
    input("Press Enter to stop...")

from_json_file

from_json_file(file_path: str, port: int, hostname: str | None = None) → 'DesignerPlugin'

Load plugin options from a JSON file (d3plugin.json format).

Parameters:

NameTypeDescription
file_pathstrPath to the JSON configuration file.
portintThe port number to publish the plugin on.
hostnamestr | NoneOptional hostname override. Defaults to the machine hostname.

Returns: A DesignerPlugin instance configured from the JSON file.

Example:

with DesignerPlugin.from_json_file("config/my_plugin.json", port=9999) as plugin:
    input("Press Enter to stop...")

Properties

service_info

service_info() → ServiceInfo

Get the ServiceInfo object suitable for DNS-SD service registration.

Context Manager

Supports use as a context manager (with / async with):

enter

__enter__() → 'DesignerPlugin'

exit

__exit__(exc_type, exc_value, traceback)

aenter

async __aenter__() → 'DesignerPlugin'

aexit

async __aexit__(exc_type, exc_value, traceback)

Session

Sync and async session classes for communicating with Designer.

D3Session

Synchronous session for executing plugins on Designer.

Manages connection to a Designer instance and provides synchronous API for
plugin execution, module registration, and generic HTTP requests.

Constructor

init

__init__(hostname: str, port: int = D3_PLUGIN_DEFAULT_PORT, context_modules: set[str] | None = None) → None

Initialize synchronous Designer session.

Parameters:

NameTypeDescription
hostnamestrThe hostname of the Designer instance.
portintThe port number of the Designer instance.
context_modulesset[str] | NoneOptional set of module names to register when entering session context.

Methods

rpc

rpc(payload: PluginPayload[RetType], timeout_sec: float | None = None) → RetType

Execute a remote procedure call and return only the return value.

Parameters:

NameTypeDescription
payloadPluginPayload[RetType]Plugin payload containing script and optional module name.
timeout_secfloat | NoneOptional timeout in seconds for the request.

Returns: The return value from the plugin execution.

Raises:

Example:

with D3Session('localhost', 80) as session:
    time: str = session.rpc(get_time.payload())

execute

execute(payload: PluginPayload[RetType], timeout_sec: float | None = None) → PluginResponse[RetType]

Execute a plugin script on Designer.

Parameters:

NameTypeDescription
payloadPluginPayload[RetType]Plugin payload containing script and optional module name.
timeout_secfloat | NoneOptional timeout in seconds for the request.

Returns: PluginResponse containing status, logs, and return value.

Raises:

Example:

with D3Session('localhost', 80) as session:
    response = session.execute(get_time.payload())
    print(f"Status: {response.status.code}")
    print(f"Python log: {response.pythonLog}")
    print(f"Value: {response.returnValue}")

request

request(method: Method, url_endpoint: str, **kwargs: Any) → Any

Make a generic HTTP request to Designer API.

Parameters:

NameTypeDescription
methodMethodHTTP method to use.
url_endpointstrThe API endpoint path. **kwargs: Additional arguments to pass to requests.request.

Returns: JSON response from the API.

register_module

register_module(module_name: str, timeout_sec: float | None = None) → bool

Register a module with Designer.

Note that session already auto-registers modules in lazy manner on execute.
Call this method directly only when you need to register eagerly.

Parameters:

NameTypeDescription
module_namestrName of the module to register.
timeout_secfloat | NoneOptional timeout in seconds for the request.

Returns: True if module was registered successfully, False if module not found.

Raises:

Example:

with D3Session('localhost', 80) as session:
    success = session.register_module("mymodule")
    print(f"success: {success}")

register_all_modules

register_all_modules(timeout_sec: float | None = None) → dict[str, bool]

Register all modules decorated with @d3function.

Note that session already auto-registers modules in lazy manner on execute.
Call this method directly only when you need to register all modules eagerly.

Parameters:

NameTypeDescription
timeout_secfloat | NoneOptional timeout in seconds for each registration request.

Returns: Dictionary mapping module names to registration success status.

Raises:

Example:

with D3Session('localhost', 80) as session:
    results = session.register_all_modules()
    # {"mymodule": True, "utilities": True}

Context Manager

Supports use as a context manager (with / async with):

enter

__enter__() → 'D3Session'

Enter context manager and register all context modules.

Returns: The session instance.

Raises:

exit

__exit__(_type: Any, _value: Any, _traceback: Any) → None

Exit context manager.

D3AsyncSession

Asynchronous session for executing plugins on Designer.

Manages connection to a Designer instance and provides asynchronous API for
plugin execution, module registration, and generic HTTP requests.

Constructor

init

__init__(hostname: str, port: int = D3_PLUGIN_DEFAULT_PORT, context_modules: set[str] | None = None) → None

Initialize asynchronous Designer session.

Parameters:

NameTypeDescription
hostnamestrThe hostname of the Designer instance.
portintThe port number of the Designer instance.
context_modulesset[str] | NoneOptional set of module names to register when entering session context.

Methods

request

async request(method: Method, url_endpoint: str, **kwargs: Unpack[aiohttp.client._RequestOptions]) → Any

Make a generic HTTP request to Designer API asynchronously.

Parameters:

NameTypeDescription
methodMethodHTTP method to use.
url_endpointstrThe API endpoint path. **kwargs: Additional arguments to pass to aiohttp session.request.

Returns: JSON response from the API.

rpc

async rpc(payload: PluginPayload[RetType], timeout_sec: float | None = None) → RetType

Execute a remote procedure call asynchronously and return only the return value.

Parameters:

NameTypeDescription
payloadPluginPayload[RetType]Plugin payload containing script and optional module name.
timeout_secfloat | NoneOptional timeout in seconds for the request.

Returns: The return value from the plugin execution.

Raises:

Example:

async with D3AsyncSession('localhost', 80) as session:
    time: str = await session.rpc(get_time.payload())

execute

async execute(payload: PluginPayload[RetType], timeout_sec: float | None = None) → PluginResponse[RetType]

Execute a plugin script on Designer asynchronously.

Parameters:

NameTypeDescription
payloadPluginPayload[RetType]Plugin payload containing script and optional module name.
timeout_secfloat | NoneOptional timeout in seconds for the request.

Returns: PluginResponse containing status, logs, and return value.

Raises:

Example:

async with D3AsyncSession('localhost', 80) as session:
    response = await session.execute(get_time.payload())
    print(f"Status: {response.status.code}")
    print(f"Value: {response.returnValue}")

register_module

async register_module(module_name: str, timeout_sec: float | None = None) → bool

Register a module with Designer asynchronously.

Note that session already auto-registers modules in lazy manner on execute.
Call this method directly only when you need to register eagerly.

Parameters:

NameTypeDescription
module_namestrName of the module to register.
timeout_secfloat | NoneOptional timeout in seconds for the request.

Returns: True if module was registered successfully, False if module not found.

Raises:

Example:

async with D3AsyncSession('localhost', 80) as session:
    success = await session.register_module("mymodule")
    print(f"success: {success}")

register_all_modules

async register_all_modules(timeout_sec: float | None = None) → dict[str, bool]

Register all modules decorated with @d3function asynchronously.

Note that session already auto-registers modules in lazy manner on execute.
Call this method directly only when you need to register all modules eagerly.

Parameters:

NameTypeDescription
timeout_secfloat | NoneOptional timeout in seconds for each registration request.

Returns: Dictionary mapping module names to registration success status.

Raises:

Example:

async with D3AsyncSession('localhost', 80) as session:
    results = await session.register_all_modules()
    # {"mymodule": True, "utilities": True}

Context Manager

Supports use as a context manager (with / async with):

aenter

async __aenter__() → 'D3AsyncSession'

Enter async context manager and register all context modules.

Returns: The session instance.

Raises:

aexit

async __aexit__(_exc_type: Any, _exc: Any, _tb: Any) → None

Exit async context manager.


Client

D3PluginClient

Base class for creating Designer plugin clients.

This class provides the foundation for building plugins that execute remotely
on Designer. When you subclass D3PluginClient, the metaclass automatically:

Attributes

instance_code

The code used to instantiate the plugin remotely (set on init)

Constructor

init

__init__() → None

Methods

in_session

in_session() → bool

Check if the client is currently in an active session.

Returns: True if both hostname and port are set, False otherwise.

async_session

async async_session(hostname: str, port: int = D3_PLUGIN_DEFAULT_PORT, register_module: bool = True, module_name: str | None = None)

Async context manager for plugin session with Designer.

Parameters:

NameTypeDescription
hostnamestrThe hostname of the Designer instance.
portintThe port number of the Designer instance.
register_moduleboolWhether to register the module. Set to False when the module has already been registered with Designer.
module_namestr | NoneOptional module name to override the default.

Returns: The plugin client instance with active session.

Example:

import asyncio
from designer_plugin.d3sdk import D3PluginClient
from designer_plugin.pystub import *
class MyPlugin(D3PluginClient):
    async def get_surface_uid(self, surface_name: str) -> str:
        surface: Screen2 = resourceManager.load(
            Path(f'objects/screen2/{surface_name}.apx'), Screen2)
        return str(surface.uid)
async def main():
    plugin = MyPlugin()
    async with plugin.async_session('localhost', 80):
        uid = await plugin.get_surface_uid("surface 1")
asyncio.run(main())

session

session(hostname: str, port: int = D3_PLUGIN_DEFAULT_PORT, register_module: bool = True, module_name: str | None = None)

Sync context manager for plugin session with Designer.

Parameters:

NameTypeDescription
hostnamestrThe hostname of the Designer instance.
portintThe port number of the Designer instance.
register_moduleboolWhether to register the module. Set to False when the module has already been registered with Designer.
module_namestr | NoneOptional module name to override the default.

Returns: The plugin client instance with active session.

Example:

from designer_plugin.d3sdk import D3PluginClient
from designer_plugin.pystub import *
class MyPlugin(D3PluginClient):
    def get_surface_uid(self, surface_name: str) -> str:
        surface: Screen2 = resourceManager.load(
            Path(f'objects/screen2/{surface_name}.apx'), Screen2)
        return str(surface.uid)
plugin = MyPlugin()
with plugin.session('localhost', 80):
    uid = plugin.get_surface_uid("surface 1")

Decorators

Decorators for registering Designer plugin functions.

@d3function

d3function(module_name: str = ”) → Callable[[Callable[P, T]], D3Function[P, T]]

Decorator to wrap a Python function for Designer module registration and execution.

This decorator transforms a regular Python function into a D3Function that can be registered
as a reusable module in Designer and executed remotely. The decorated function is added to
the module’s function registry and can be called by name after module registration.

Unlike @d3pythonscript which inlines the function body, @d3function registers the complete
function definition as part of a module, allowing efficient reuse across multiple executions.

Parameters:

NameTypeDescription
module_namestrThe module name to register this function under. This should be a unique identifier for the module that will contain this function. Multiple functions can share the same module_name to be registered together as a single module.

Returns: A decorator function that wraps the target function in a D3Function instance.

Example:

from designer_plugin.d3sdk import d3function, D3Session
from designer_plugin.pystub import *
@d3function("my_d3module")
def get_camera_uid(cam_name: str) -> str:
    camera = resourceManager.load(
        Path(f'objects/camera/{cam_name}.apx'),
        Camera
    )
    return str(camera.uid)
# Generate payload for execution (calls the function by name)
payload = get_camera_uid.payload("camera1")
# payload.script == "return get_camera_uid('camera1')"
# "my_d3module" is auto-registered when entering the session
with D3Session('localhost', 80, {"my_d3module"}) as session:
    uid = session.rpc(get_camera_uid.payload("camera1"))

@d3pythonscript

d3pythonscript(func: Callable[P, T]) → D3PythonScript[P, T]

Decorator to wrap a Python function for standalone Designer script execution.

This decorator transforms a regular Python function into a D3PythonScript that generates
execution payloads for direct script execution in Designer. Unlike @d3function, this
decorator does not register the function as a module and is intended for one-off script
execution where the function body is inlined with the arguments.

Parameters:

NameTypeDescription
funcCallable[P, T]The Python function to wrap.

Returns: D3PythonScript instance that wraps the function and provides payload generation.

Example:

from designer_plugin.d3sdk import d3pythonscript, D3Session
@d3pythonscript
def my_add(a: int, b: int) -> int:
    return a + b
# Generate payload for execution
payload = my_add.payload(5, 3)
# The payload.script will contain:
# a=5
# b=3
# return a + b
with D3Session('localhost', 80) as session:
    result = session.rpc(my_add.payload(5, 3))
    print(result)  # 8

Models

Pydantic models and types used in the Designer Plugin API.

PluginPayload

Type-safe execution payload for plugin calls.

Attributes

moduleName

Module name to run script on Designer.

script

Script to run on Designer.

Methods

is_module_payload

is_module_payload() → bool

Return True if this payload targets a named module.

Returns: True if moduleName is set, False otherwise.

debug_string

debug_string() → str

Return a human-readable debug representation of this payload.

Returns: A formatted string showing the JSON serialisation and raw script content.

PluginResponse

Response from a plugin API call.

Attributes

status

Status of plugin API call.

d3Log

The d3Log field captures the Designer console log for the time the Python script is executing, recording any output generated by running a Python command, including the time taken to execute the Python command. As this captures the Designer console output, it is possible other threads may write to this output during this period causing additional irrelevant output.

pythonLog

This output field is the pure Python output, recording any print statements or warnings that occur during the execution of the script. This output will also appear in the d3Log field. However, in the d3Log field it will be mixed with other Designer log output.

returnValue

Return value of python plugin execution

Static Methods

parse_returnValue

parse_returnValue(cls, v: Any) → Any

Methods

returnCastValue

returnCastValue(castType: type[RetCastType]) → RetCastType

Validate and cast the return value to the specified type.

Parameters:

NameTypeDescription
castTypetype[RetCastType]The type to validate and cast the return value to.

Returns: The validated return value as the specified type.

Raises:

Example:

response = session.execute(get_surface_info.payload("surface 1"))
info = response.returnCastValue(dict[str, str])
print(info["uid"])

debug_string

debug_string() → str

PluginError

Error response when plugin execution fails.

Attributes

returnValue

Always None for error responses.

PluginRegisterResponse

Response from a plugin module registration API call.

Attributes

status

Status of plugin module registration API call.

PluginStatus

Status information from plugin API calls.

Attributes

code

Return code of plugin API call. 0 if good.

message

Message from plugin API call.

details

List of detailed error information.

PluginStatusDetail

Detail information for plugin status errors.

Attributes

type_url

Type URL identifying the error detail.

value

Error detail value.

RegisterPayload

Payload for registering a Python module with Designer.

Attributes

moduleName

Module name to register contents.

contents

Python code to register with the module name.

Methods

debug_string

debug_string() → str

PluginException

Exception raised when plugin execution fails.

Attributes

status

The status information from the failed plugin call

d3Log

Designer console log output

pythonLog

Python-specific log output