From f0aea758efa9fab31a25f849532ece8e79c845a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Mon, 4 Nov 2024 13:28:36 +0100 Subject: [PATCH 1/6] Apply the factory pattern and the class registration for serialization. Still deserialization to do --- .mu_repo | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .mu_repo diff --git a/.mu_repo b/.mu_repo new file mode 100644 index 00000000..37f46ae7 --- /dev/null +++ b/.mu_repo @@ -0,0 +1,4 @@ +repo=. +repo=../pymodaq_data +repo=../pymodaq_utils +serial=True \ No newline at end of file From 959b8cea3e7f22de6f6a5075d993441239793ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Mon, 4 Nov 2024 23:01:13 +0100 Subject: [PATCH 2/6] Revert "Apply the factory pattern and the class registration for serialization. Still deserialization to do" This reverts commit f0aea758efa9fab31a25f849532ece8e79c845a7. --- .mu_repo | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .mu_repo diff --git a/.mu_repo b/.mu_repo deleted file mode 100644 index 37f46ae7..00000000 --- a/.mu_repo +++ /dev/null @@ -1,4 +0,0 @@ -repo=. -repo=../pymodaq_data -repo=../pymodaq_utils -serial=True \ No newline at end of file From 12e66c4a7303e646907f7cc611d2b7faee30b1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Mon, 4 Nov 2024 23:01:36 +0100 Subject: [PATCH 3/6] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8f569723..9854f6c4 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,4 @@ venv.bak/ *yacctab.py *lextab.py +.mu_repo \ No newline at end of file From d3e374b30bb2a2ee6232effc53732cde9668f579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Tue, 5 Nov 2024 21:01:09 +0100 Subject: [PATCH 4/6] Apply a decorator on the ParameterWithPath object to make it serializable --- src/pymodaq_gui/parameter/utils.py | 37 +++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/pymodaq_gui/parameter/utils.py b/src/pymodaq_gui/parameter/utils.py index 881fe648..d879104e 100644 --- a/src/pymodaq_gui/parameter/utils.py +++ b/src/pymodaq_gui/parameter/utils.py @@ -1,16 +1,20 @@ from __future__ import annotations -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING, List, Tuple, Any from dataclasses import Field, fields import numpy as np from collections import OrderedDict from dataclasses import dataclass from pymodaq_utils.utils import find_keys_from_val - +from pymodaq_data.serialize.factory import SerializableFactory, SerializableBase +from pymodaq_gui.parameter import ioxml if TYPE_CHECKING: from pymodaq_gui.parameter import Parameter +ser_factory = SerializableFactory() + -class ParameterWithPath: +@SerializableFactory.register_decorator() +class ParameterWithPath(SerializableBase): """ holds together a Parameter object and its full path To be used when communicating between TCPIP to reconstruct properly the Parameter @@ -22,6 +26,7 @@ class ParameterWithPath: path: full path of the parameter, if None it is constructed from the parameter parents """ def __init__(self, parameter: Parameter, path: List[str] = None): + super().__init__() self._parameter = parameter if path is None: path = get_param_path(parameter) @@ -35,6 +40,32 @@ def parameter(self) -> Parameter: def path(self) -> List[str]: return self._path + @staticmethod + def serialize(param: 'ParameterWithPath') -> bytes: + """ + + """ + bytes_string = b'' + path = param.path + param_as_xml = ioxml.parameter_to_xml_string(param.parameter) + bytes_string += ser_factory.get_apply_serializer(path) + bytes_string += ser_factory.get_apply_serializer(param_as_xml) + + @classmethod + def deserialize(cls, bytes_str: bytes) -> Tuple[Any, bytes]: + """Convert bytes into a ParameterWithPath object + + Returns + ------- + ParameterWithPath: the decoded object + bytes: the remaining bytes string if any + """ + path, remaining_bytes = ser_factory.get_apply_deserializer(bytes_str) + param_as_xml, remaining_bytes = ser_factory.get_apply_deserializer(remaining_bytes) + param_dict = ioxml.XML_string_to_parameter(param_as_xml) + param_obj = Parameter(**param_dict[0]) + return ParameterWithPath(param_obj, path), remaining_bytes + def get_widget_from_tree(parameter_tree, widget_instance): widgets = [] From ab673cc9ab40d2f8bb98a38d12ed4fe21308f513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Tue, 5 Nov 2024 21:41:14 +0100 Subject: [PATCH 5/6] Test serialization of ParameterWithPath --- src/pymodaq_gui/parameter/utils.py | 11 +++++++---- tests/parameter_test/param_utils_test.py | 15 +++++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/pymodaq_gui/parameter/utils.py b/src/pymodaq_gui/parameter/utils.py index d879104e..b666dfd0 100644 --- a/src/pymodaq_gui/parameter/utils.py +++ b/src/pymodaq_gui/parameter/utils.py @@ -7,8 +7,8 @@ from pymodaq_utils.utils import find_keys_from_val from pymodaq_data.serialize.factory import SerializableFactory, SerializableBase from pymodaq_gui.parameter import ioxml -if TYPE_CHECKING: - from pymodaq_gui.parameter import Parameter + +from pymodaq_gui.parameter import Parameter ser_factory = SerializableFactory() @@ -50,6 +50,7 @@ def serialize(param: 'ParameterWithPath') -> bytes: param_as_xml = ioxml.parameter_to_xml_string(param.parameter) bytes_string += ser_factory.get_apply_serializer(path) bytes_string += ser_factory.get_apply_serializer(param_as_xml) + return bytes_string @classmethod def deserialize(cls, bytes_str: bytes) -> Tuple[Any, bytes]: @@ -135,8 +136,10 @@ def getValues(param:Parameter,) -> OrderedDict: """ return param.getValues() -def compareParameters(param1:Parameter,param2:Parameter,opts:list=[])-> bool: - """Compare the structure and the opts of two parameters with their children, return True if structure and all opts are identical + +def compareParameters(param1:Parameter, param2:Parameter, opts: list = [])-> bool: + """Compare the structure and the opts of two parameters with their children, + return True if structure and all opts are identical Parameters ---------- param1: Parameter diff --git a/tests/parameter_test/param_utils_test.py b/tests/parameter_test/param_utils_test.py index 73eacbb4..4e29c3dc 100644 --- a/tests/parameter_test/param_utils_test.py +++ b/tests/parameter_test/param_utils_test.py @@ -136,10 +136,6 @@ def test_compareValuesParameter(): putils.compareValuesParameter(param1=P1,param2=P3) == False, putils.compareValuesParameter(param1=P1,param2=P4) == False] - - - - class TestScroll: def test_scroll_log(self): @@ -214,3 +210,14 @@ def test_set_param_from_param(qtbot): assert settings_old.child('main_settings', 'axis').value() == 2 assert dict_widget.currentText() == 'DAQ2D' + +def test_ParameterWithPath_serialize(): + + p1_with_path = putils.ParameterWithPath(P1.child('numbers', 'afloat', 'aint')) + assert isinstance(putils.ser_factory.get_apply_serializer(p1_with_path), bytes) + + param_back: putils.ParameterWithPath = putils.ser_factory.get_apply_deserializer( + putils.ser_factory.get_apply_serializer(p1_with_path))[0] + assert param_back.path == p1_with_path.path + assert putils.compareParameters(param_back.parameter, p1_with_path.parameter) + From d86c5f6c617c231f522d6e59b09174b8188e3d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Wed, 6 Nov 2024 22:52:18 +0100 Subject: [PATCH 6/6] All tests pass. Legacy Serializer object still working --- docs/src/user_folder/tcpip.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/src/user_folder/tcpip.rst b/docs/src/user_folder/tcpip.rst index 8eddd9a4..474651c2 100644 --- a/docs/src/user_folder/tcpip.rst +++ b/docs/src/user_folder/tcpip.rst @@ -58,7 +58,14 @@ They both implements specific methods applicable to a given object but also a ge .. code-block:: - >>> from pymodaq.utils.tcp_ip.serializer import Serializer, DeSerializer + >>> from pymodaq.utils.tcp_ip.serializer import DeSerializer + from pymodaq_data.serialize.serializer_legacy import Serializer + >>> string = 'Hello' + >>> ser = Serializer(string) + >>> print(ser.string_serialization(string)) + b'\x00\x00\x00\x05Hello' + + In this example, the serializer first send 4 bytes encoding the length of the >>> string = 'Hello' >>> ser = Serializer(string) >>> print(ser.string_serialization(string))