From 1eed62ffd2128e4f8e7e9e58c185380b3eea8e36 Mon Sep 17 00:00:00 2001 From: Andreas Pedersen <48797331+andped10@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:25:37 +0200 Subject: [PATCH 1/4] Added `deepcopy` functionality for `ComponentSerializer` (#77) --- src/easyscience/Objects/core.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/easyscience/Objects/core.py b/src/easyscience/Objects/core.py index a3206022..0754040f 100644 --- a/src/easyscience/Objects/core.py +++ b/src/easyscience/Objects/core.py @@ -32,6 +32,9 @@ class ComponentSerializer: _CORE = True + def __deepcopy__(self, memo): + return self.from_dict(self.as_dict()) + def encode(self, skip: Optional[List[str]] = None, encoder: Optional[EC] = None, **kwargs) -> Any: """ Use an encoder to covert an EasyScience object into another format. Default is to a dictionary using `DictSerializer`. @@ -41,7 +44,6 @@ def encode(self, skip: Optional[List[str]] = None, encoder: Optional[EC] = None, :param kwargs: Any additional key word arguments to be passed to the encoder :return: encoded object containing all information to reform an EasyScience object. """ - if encoder is None: encoder = DictSerializer encoder_obj = encoder() From 6c44d077d97906403f01d53298351b0ae534689a Mon Sep 17 00:00:00 2001 From: Andreas Pedersen <48797331+andped10@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:58:03 +0200 Subject: [PATCH 2/4] unique name when created from dict (#80) --- src/easyscience/Utils/io/template.py | 6 +----- tests/unit_tests/Objects/test_BaseObj.py | 17 +++++++++++++++++ tests/unit_tests/utils/io_tests/test_core.py | 4 ++-- tests/unit_tests/utils/io_tests/test_dict.py | 8 ++++---- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/easyscience/Utils/io/template.py b/src/easyscience/Utils/io/template.py index 3424ddf7..031d3466 100644 --- a/src/easyscience/Utils/io/template.py +++ b/src/easyscience/Utils/io/template.py @@ -257,11 +257,7 @@ def _convert_from_dict(d): mod = __import__(modname, globals(), locals(), [classname], 0) if hasattr(mod, classname): cls_ = getattr(mod, classname) - data = { - k: BaseEncoderDecoder._convert_from_dict(v) - for k, v in d.items() - if not (k.startswith('@') or k == 'unique_name') - } + data = {k: BaseEncoderDecoder._convert_from_dict(v) for k, v in d.items() if not k.startswith('@')} return cls_(**data) elif np is not None and modname == 'numpy' and classname == 'array': if d['dtype'].startswith('complex'): diff --git a/tests/unit_tests/Objects/test_BaseObj.py b/tests/unit_tests/Objects/test_BaseObj.py index 15d12fdf..c545e6bc 100644 --- a/tests/unit_tests/Objects/test_BaseObj.py +++ b/tests/unit_tests/Objects/test_BaseObj.py @@ -236,6 +236,23 @@ def check_dict(check, item): check_dict(expected, obtained) +def test_baseobj_dict_roundtrip(clear, setup_pars: dict): + # When + name = setup_pars["name"] + del setup_pars["name"] + obj = BaseObj(name, **setup_pars, unique_name='special_name') + obj_dict = obj.as_dict() + + global_object.map._clear() + + # Then + new_obj = BaseObj.from_dict(obj_dict) + + # Expect + new_obj_dict = new_obj.as_dict() + assert obj_dict == new_obj_dict + + def test_baseobj_dir(setup_pars): name = setup_pars["name"] del setup_pars["name"] diff --git a/tests/unit_tests/utils/io_tests/test_core.py b/tests/unit_tests/utils/io_tests/test_core.py index fd0153b5..c49f5f1d 100644 --- a/tests/unit_tests/utils/io_tests/test_core.py +++ b/tests/unit_tests/utils/io_tests/test_core.py @@ -131,8 +131,8 @@ def __init__(self, name: str = "A", **kwargs): class B(BaseObj): - def __init__(self, a, b): - super(B, self).__init__("B", a=a) + def __init__(self, a, b, unique_name): + super(B, self).__init__("B", a=a, unique_name=unique_name) self.b = b diff --git a/tests/unit_tests/utils/io_tests/test_dict.py b/tests/unit_tests/utils/io_tests/test_dict.py index 476298d2..6a456581 100644 --- a/tests/unit_tests/utils/io_tests/test_dict.py +++ b/tests/unit_tests/utils/io_tests/test_dict.py @@ -207,8 +207,8 @@ def test_custom_class_encode_data(dp_kwargs: dict, dp_cls: Type[DescriptorNumber def test_custom_class_full_encode_with_numpy(): class B(BaseObj): - def __init__(self, a, b): - super(B, self).__init__("B", a=a) + def __init__(self, a, b, unique_name): + super(B, self).__init__("B", a=a, unique_name=unique_name) self.b = b # Same as in __init__.py for easyscience try: @@ -216,7 +216,7 @@ def __init__(self, a, b): except metadata.PackageNotFoundError: version = '0.0.0' - obj = B(DescriptorNumber("a", 1.0, unique_name="a"), np.array([1.0, 2.0, 3.0])) + obj = B(DescriptorNumber("a", 1.0, unique_name="a"), np.array([1.0, 2.0, 3.0]), unique_name="B_0") full_enc = obj.encode(encoder=DictSerializer, full_encode=True) expected = { "@module": "tests.unit_tests.utils.io_tests.test_dict", @@ -248,7 +248,7 @@ def __init__(self, a, b): def test_custom_class_full_decode_with_numpy(): global_object.map._clear() - obj = B(DescriptorNumber("a", 1.0), np.array([1.0, 2.0, 3.0])) + obj = B(DescriptorNumber("a", 1.0), np.array([1.0, 2.0, 3.0]), unique_name="B_0") full_enc = obj.encode(encoder=DictSerializer, full_encode=True) global_object.map._clear() obj2 = B.decode(full_enc, decoder=DictSerializer) From 5b63227dde40a6e75f8bd054a40ce0adb01b143c Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 29 Oct 2024 13:32:52 +0100 Subject: [PATCH 3/4] Add the property `free` to the class `Parameter` as an alias for `not fixed` (#82) --- src/easyscience/Objects/Variable.py | 8 ++++++++ src/easyscience/Objects/new_variable/parameter.py | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/easyscience/Objects/Variable.py b/src/easyscience/Objects/Variable.py index 10362ba9..3de9bef0 100644 --- a/src/easyscience/Objects/Variable.py +++ b/src/easyscience/Objects/Variable.py @@ -721,6 +721,14 @@ def fixed(self, value: bool): raise ValueError self._fixed = value + @property + def free(self) -> bool: + return not self.fixed + + @free.setter + def free(self, value: bool) -> None: + self.fixed = not value + @property def error(self) -> float: """ diff --git a/src/easyscience/Objects/new_variable/parameter.py b/src/easyscience/Objects/new_variable/parameter.py index 26992c04..ebad24b4 100644 --- a/src/easyscience/Objects/new_variable/parameter.py +++ b/src/easyscience/Objects/new_variable/parameter.py @@ -301,6 +301,14 @@ def fixed(self, fixed: bool) -> None: raise ValueError(f'{fixed=} must be a boolean. Got {type(fixed)}') self._fixed = fixed + @property + def free(self) -> bool: + return not self.fixed + + @free.setter + def free(self, value: bool) -> None: + self.fixed = not value + @property def bounds(self) -> Tuple[numbers.Number, numbers.Number]: """ From 8b2e5fb858c23ed29233196c14a0c18fe4a9c923 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 29 Oct 2024 15:06:06 +0100 Subject: [PATCH 4/4] Update the release version to 1.1.1 --- src/easyscience/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/easyscience/__version__.py b/src/easyscience/__version__.py index 1a72d32e..b3ddbc41 100644 --- a/src/easyscience/__version__.py +++ b/src/easyscience/__version__.py @@ -1 +1 @@ -__version__ = '1.1.0' +__version__ = '1.1.1'