mirror of
https://github.com/tiqi-group/pydase.git
synced 2026-02-14 06:18:41 +01:00
Merge pull request #249 from tiqi-group/feat/improve-client-proxy-serialization
chore: improve client proxy serialization
This commit is contained in:
@@ -240,12 +240,11 @@ class Client:
|
|||||||
self.proxy, serialized_object=serialized_object
|
self.proxy, serialized_object=serialized_object
|
||||||
)
|
)
|
||||||
serialized_object["type"] = "DeviceConnection"
|
serialized_object["type"] = "DeviceConnection"
|
||||||
if self.proxy._service_representation is not None:
|
# need to use object.__setattr__ to not trigger an observer notification
|
||||||
# need to use object.__setattr__ to not trigger an observer notification
|
object.__setattr__(self.proxy, "_service_representation", serialized_object)
|
||||||
object.__setattr__(self.proxy, "_service_representation", serialized_object)
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
self.proxy._service_representation = serialized_object # type: ignore
|
self.proxy._service_representation = serialized_object # type: ignore
|
||||||
self.proxy._notify_changed("", self.proxy)
|
self.proxy._notify_changed("", self.proxy)
|
||||||
self.proxy._connected = True
|
self.proxy._connected = True
|
||||||
|
|
||||||
|
|||||||
@@ -65,19 +65,31 @@ class ProxyClass(ProxyClassMixin, pydase.components.DeviceConnection):
|
|||||||
self.reconnect = reconnect
|
self.reconnect = reconnect
|
||||||
|
|
||||||
def serialize(self) -> SerializedObject:
|
def serialize(self) -> SerializedObject:
|
||||||
if self._service_representation is None:
|
current_loop = asyncio.get_event_loop()
|
||||||
serialization_future = cast(
|
|
||||||
|
if not self.connected or current_loop == self._loop:
|
||||||
|
logger.debug(
|
||||||
|
"Client not connected, or called from within client event loop - using "
|
||||||
|
"fallback serialization"
|
||||||
|
)
|
||||||
|
if self._service_representation is None:
|
||||||
|
serialized_service = pydase.components.DeviceConnection().serialize()
|
||||||
|
else:
|
||||||
|
serialized_service = self._service_representation
|
||||||
|
|
||||||
|
else:
|
||||||
|
future = cast(
|
||||||
"asyncio.Future[SerializedDataService]",
|
"asyncio.Future[SerializedDataService]",
|
||||||
asyncio.run_coroutine_threadsafe(
|
asyncio.run_coroutine_threadsafe(
|
||||||
self._sio.call("service_serialization"), self._loop
|
self._sio.call("service_serialization"), self._loop
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
result = future.result()
|
||||||
# need to use object.__setattr__ to not trigger an observer notification
|
# need to use object.__setattr__ to not trigger an observer notification
|
||||||
object.__setattr__(
|
object.__setattr__(self, "_service_representation", result)
|
||||||
self, "_service_representation", serialization_future.result()
|
|
||||||
)
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
self._service_representation = serialization_future.result()
|
self._service_representation = result
|
||||||
|
serialized_service = result
|
||||||
|
|
||||||
device_connection_value = cast(
|
device_connection_value = cast(
|
||||||
"dict[str, SerializedObject]",
|
"dict[str, SerializedObject]",
|
||||||
@@ -93,7 +105,7 @@ class ProxyClass(ProxyClassMixin, pydase.components.DeviceConnection):
|
|||||||
"dict[str, SerializedObject]",
|
"dict[str, SerializedObject]",
|
||||||
# need to deepcopy to not overwrite the _service_representation dict
|
# need to deepcopy to not overwrite the _service_representation dict
|
||||||
# when adding a prefix with add_prefix_to_full_access_path
|
# when adding a prefix with add_prefix_to_full_access_path
|
||||||
deepcopy(self._service_representation["value"]),
|
deepcopy(serialized_service["value"]),
|
||||||
),
|
),
|
||||||
**device_connection_value,
|
**device_connection_value,
|
||||||
}
|
}
|
||||||
|
|||||||
22
tests/client/test_proxy_class.py
Normal file
22
tests/client/test_proxy_class.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import asyncio
|
||||||
|
from unittest.mock import AsyncMock, call, patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from pydase import components
|
||||||
|
from pydase.client.proxy_class import ProxyClass
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_serialize_fallback_inside_event_loop() -> None:
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
mock_sio = AsyncMock()
|
||||||
|
proxy = ProxyClass(sio_client=mock_sio, loop=loop, reconnect=lambda: None)
|
||||||
|
|
||||||
|
with patch.object(
|
||||||
|
components.DeviceConnection, "serialize", return_value={"value": {}}
|
||||||
|
) as mock_fallback:
|
||||||
|
result = proxy.serialize()
|
||||||
|
|
||||||
|
mock_fallback.assert_has_calls(calls=[call(), call()])
|
||||||
|
assert isinstance(result, dict)
|
||||||
Reference in New Issue
Block a user