Skip to content
Open
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.3.0] - 2026-01-06

### Changed
- `d3_api_plugin` has been renamed to `d3_api_execute`.
- `d3_api_aplugin` has been renamed to `d3_api_aexecute`.
- Updated documentation to reflect `pystub` proxy support.

## [1.2.0] - 2025-12-02

### Added
Expand Down
17 changes: 6 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ To enable IDE autocomplete and type checking for Designer's Python API, install
pip install designer-plugin-pystub
```

Once installed, import the stubs using the `TYPE_CHECKING` pattern. This provides type hints in your IDE without affecting runtime execution:
Once installed, import the stubs.
> **Important:** `pystub` provides type hints for Designer's API objects but not their implementations. These objects only exist in Designer's runtime and cannot be used in local Python code. They must only be referenced in code that will be executed remotely in Designer.

```python
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from designer_plugin.pystub.d3 import *
from designer_plugin.pystub import *
```

This allows you to get autocomplete for Designer objects like `resourceManager`, `Screen2`, `Path`, etc., while writing your plugin code.
Expand All @@ -100,9 +100,7 @@ The Client API allows you to define a class with methods that execute remotely o

```python
from designer_plugin.d3sdk import D3PluginClient
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from designer_plugin.pystub.d3 import *
from designer_plugin.pystub import *

# 1. Sync example -----------------------------------
class MySyncPlugin(D3PluginClient):
Expand Down Expand Up @@ -186,9 +184,7 @@ Both `D3AsyncSession` and `D3Session` provide two methods for executing function

```python
from designer_plugin.d3sdk import d3pythonscript, d3function, D3AsyncSession
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from designer_plugin.pystub.d3 import *
from designer_plugin.pystub import *

# 1. @d3pythonscript - simple one-off execution
@d3pythonscript
Expand Down Expand Up @@ -251,4 +247,3 @@ logging.getLogger('designer_plugin').setLevel(logging.DEBUG)
# License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "designer-plugin"
version = "1.2.1"
version = "1.3.0"
description = "Python library for creating Disguise Designer plugins with DNS-SD discovery and remote Python execution"
authors = [
{ name = "Tom Whittock", email = "tom.whittock@disguise.one" },
Expand Down
4 changes: 2 additions & 2 deletions src/designer_plugin/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ async def d3_api_arequest(

###############################################################################
# API async interface
async def d3_api_aplugin(
async def d3_api_aexecute(
hostname: str,
port: int,
payload: PluginPayload[RetType],
Expand Down Expand Up @@ -219,7 +219,7 @@ async def d3_api_aregister_module(

###############################################################################
# API sync interface
def d3_api_plugin(
def d3_api_execute(
hostname: str,
port: int,
payload: PluginPayload[RetType],
Expand Down
8 changes: 4 additions & 4 deletions src/designer_plugin/d3sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
from typing import Any, ParamSpec, TypeVar

from designer_plugin.api import (
d3_api_aplugin,
d3_api_aexecute,
d3_api_aregister_module,
d3_api_plugin,
d3_api_execute,
d3_api_register_module,
)
from designer_plugin.d3sdk.ast_utils import (
Expand Down Expand Up @@ -112,7 +112,7 @@ async def async_wrapper(self, *args, **kwargs): # type: ignore
session_runtime_error_message(self.__class__.__name__)
)
payload = build_payload(self, method_name, positional, keyword)
response: PluginResponse[T] = await d3_api_aplugin(
response: PluginResponse[T] = await d3_api_aexecute(
self._hostname, self._port, payload
)
return response.returnValue
Expand All @@ -130,7 +130,7 @@ def sync_wrapper(self, *args, **kwargs): # type: ignore
session_runtime_error_message(self.__class__.__name__)
)
payload = build_payload(self, method_name, positional, keyword)
response: PluginResponse[T] = d3_api_plugin(
response: PluginResponse[T] = d3_api_execute(
self._hostname, self._port, payload
)
return response.returnValue
Expand Down
8 changes: 4 additions & 4 deletions src/designer_plugin/d3sdk/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@

from designer_plugin.api import (
Method,
d3_api_aplugin,
d3_api_aexecute,
d3_api_aregister_module,
d3_api_arequest,
d3_api_plugin,
d3_api_execute,
d3_api_register_module,
d3_api_request,
)
Expand Down Expand Up @@ -117,7 +117,7 @@ def execute(
Raises:
PluginException: If the plugin execution fails.
"""
return d3_api_plugin(self.hostname, self.port, payload, timeout_sec)
return d3_api_execute(self.hostname, self.port, payload, timeout_sec)

def request(self, method: Method, url_endpoint: str, **kwargs: Any) -> Any:
"""Make a generic HTTP request to Designer API.
Expand Down Expand Up @@ -270,7 +270,7 @@ async def execute(
Raises:
PluginException: If the plugin execution fails.
"""
return await d3_api_aplugin(self.hostname, self.port, payload, timeout_sec)
return await d3_api_aexecute(self.hostname, self.port, payload, timeout_sec)

async def register_module(
self, module_name: str, timeout_sec: float | None = None
Expand Down
12 changes: 6 additions & 6 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def test_method_call_without_session_raises_error(self, plugin):

def test_correct_arguments_sync(self, plugin, mock_response):
"""Test that correct arguments pass through successfully."""
with patch('designer_plugin.d3sdk.client.d3_api_plugin', return_value=mock_response) as mock_api:
with patch('designer_plugin.d3sdk.client.d3_api_execute', return_value=mock_response) as mock_api:
plugin._hostname = "localhost"
plugin._port = 80

Expand Down Expand Up @@ -114,7 +114,7 @@ def test_unexpected_keyword_argument(self, plugin):

def test_method_with_defaults_partial_args(self, plugin, mock_response):
"""Test method with default parameters using partial arguments."""
with patch('designer_plugin.d3sdk.client.d3_api_plugin', return_value=mock_response):
with patch('designer_plugin.d3sdk.client.d3_api_execute', return_value=mock_response):
plugin._hostname = "localhost"
plugin._port = 80

Expand All @@ -124,7 +124,7 @@ def test_method_with_defaults_partial_args(self, plugin, mock_response):

def test_method_with_defaults_override(self, plugin, mock_response):
"""Test method with default parameters overriding defaults."""
with patch('designer_plugin.d3sdk.client.d3_api_plugin', return_value=mock_response):
with patch('designer_plugin.d3sdk.client.d3_api_execute', return_value=mock_response):
plugin._hostname = "localhost"
plugin._port = 80

Expand All @@ -134,7 +134,7 @@ def test_method_with_defaults_override(self, plugin, mock_response):

def test_method_with_defaults_keyword(self, plugin, mock_response):
"""Test method with default parameters using keyword arguments."""
with patch('designer_plugin.d3sdk.client.d3_api_plugin', return_value=mock_response):
with patch('designer_plugin.d3sdk.client.d3_api_execute', return_value=mock_response):
plugin._hostname = "localhost"
plugin._port = 80

Expand All @@ -144,7 +144,7 @@ def test_method_with_defaults_keyword(self, plugin, mock_response):

def test_keyword_only_parameters(self, plugin, mock_response):
"""Test method with keyword-only parameters."""
with patch('designer_plugin.d3sdk.client.d3_api_plugin', return_value=mock_response):
with patch('designer_plugin.d3sdk.client.d3_api_execute', return_value=mock_response):
plugin._hostname = "localhost"
plugin._port = 80

Expand All @@ -162,7 +162,7 @@ def test_keyword_only_parameters_as_positional_fails(self, plugin):

def test_mixed_parameters(self, plugin, mock_response):
"""Test method with mixed parameter types."""
with patch('designer_plugin.d3sdk.client.d3_api_plugin', return_value=mock_response):
with patch('designer_plugin.d3sdk.client.d3_api_execute', return_value=mock_response):
plugin._hostname = "localhost"
plugin._port = 80

Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.