diff --git a/CHANGELOG.md b/CHANGELOG.md index b4df8d3..de96159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index 3c754f9..4c4874f 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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): @@ -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 @@ -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. - diff --git a/pyproject.toml b/pyproject.toml index db59363..675f8e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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" }, diff --git a/src/designer_plugin/api.py b/src/designer_plugin/api.py index 672d014..65cd9d0 100644 --- a/src/designer_plugin/api.py +++ b/src/designer_plugin/api.py @@ -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], @@ -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], diff --git a/src/designer_plugin/d3sdk/client.py b/src/designer_plugin/d3sdk/client.py index fcf8cc4..5491c47 100644 --- a/src/designer_plugin/d3sdk/client.py +++ b/src/designer_plugin/d3sdk/client.py @@ -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 ( @@ -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 @@ -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 diff --git a/src/designer_plugin/d3sdk/session.py b/src/designer_plugin/d3sdk/session.py index 63992ab..f30dd42 100644 --- a/src/designer_plugin/d3sdk/session.py +++ b/src/designer_plugin/d3sdk/session.py @@ -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, ) @@ -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. @@ -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 diff --git a/tests/test_client.py b/tests/test_client.py index b7c73f1..3e6442c 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/uv.lock b/uv.lock index c69dd25..be4c221 100644 --- a/uv.lock +++ b/uv.lock @@ -348,7 +348,7 @@ wheels = [ [[package]] name = "designer-plugin" -version = "1.2.1" +version = "1.3.0" source = { editable = "." } dependencies = [ { name = "aiohttp" },