diff --git a/pylabrobot/centrifuge/centrifuge.py b/pylabrobot/centrifuge/centrifuge.py index 2476882e5ad..9a03754b8de 100644 --- a/pylabrobot/centrifuge/centrifuge.py +++ b/pylabrobot/centrifuge/centrifuge.py @@ -134,18 +134,22 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data: dict, allow_marshal: bool = False): - backend = CentrifugeBackend.deserialize(data["backend"]) - buckets = tuple(ResourceHolder.deserialize(bucket) for bucket in data["buckets"]) - assert len(buckets) == 2 + buckets_data = data.get("buckets") + buckets = ( + tuple(ResourceHolder.deserialize(bucket) for bucket in buckets_data) if buckets_data else None + ) + if buckets is not None: + assert len(buckets) == 2 + rotation_data = data.get("rotation") return cls( - backend=backend, + backend=CentrifugeBackend.deserialize(data["backend"]), name=data["name"], size_x=data["size_x"], size_y=data["size_y"], size_z=data["size_z"], - rotation=Rotation.deserialize(data["rotation"]), - category=data["category"], - model=data["model"], + rotation=deserialize(rotation_data) if rotation_data else None, + category=data.get("category"), + model=data.get("model"), buckets=buckets, ) @@ -228,15 +232,18 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data: dict, allow_marshal: bool = False): + resource_data = data.get("resource", {}) + machine_data = data.get("machine", {}) + rotation_data = resource_data.get("rotation") return cls( - backend=LoaderBackend.deserialize(data["machine"]["backend"]), + backend=LoaderBackend.deserialize(machine_data["backend"]), centrifuge=Centrifuge.deserialize(data["centrifuge"]), - name=data["resource"]["name"], - size_x=data["resource"]["size_x"], - size_y=data["resource"]["size_y"], - size_z=data["resource"]["size_z"], - child_location=deserialize(data["resource"]["child_location"]), - rotation=deserialize(data["resource"]["rotation"]), - category=data["resource"]["category"], - model=data["resource"]["model"], + name=resource_data["name"], + size_x=resource_data["size_x"], + size_y=resource_data["size_y"], + size_z=resource_data["size_z"], + child_location=deserialize(resource_data["child_location"]), + rotation=deserialize(rotation_data) if rotation_data else None, + category=resource_data.get("category"), + model=resource_data.get("model"), ) diff --git a/pylabrobot/io/serial.py b/pylabrobot/io/serial.py index 914d4567d19..3b925bf2c35 100644 --- a/pylabrobot/io/serial.py +++ b/pylabrobot/io/serial.py @@ -329,21 +329,6 @@ def serialize(self): "dsrdtr": self.dsrdtr, } - @classmethod - def deserialize(cls, data: dict) -> "Serial": - return cls( - human_readable_device_name=data["human_readable_device_name"], - port=data["port"], - baudrate=data["baudrate"], - bytesize=data["bytesize"], - parity=data["parity"], - stopbits=data["stopbits"], - write_timeout=data["write_timeout"], - timeout=data["timeout"], - rtscts=data["rtscts"], - dsrdtr=data["dsrdtr"], - ) - class SerialValidator(Serial): def __init__( diff --git a/pylabrobot/io/socket.py b/pylabrobot/io/socket.py index 0fcae09a6bd..575cb4d7c1d 100644 --- a/pylabrobot/io/socket.py +++ b/pylabrobot/io/socket.py @@ -99,20 +99,6 @@ def serialize(self): "write_timeout": self._write_timeout, } - @classmethod - def deserialize(cls, data: dict) -> "Socket": - kwargs = {} - if "read_timeout" in data: - kwargs["read_timeout"] = data["read_timeout"] - if "write_timeout" in data: - kwargs["write_timeout"] = data["write_timeout"] - return cls( - human_readable_device_name=data["human_readable_device_name"], - host=data["host"], - port=data["port"], - **kwargs, - ) - async def write(self, data: bytes, timeout: Optional[float] = None) -> None: """Wrapper around StreamWriter.write with lock and io logging. Does not retry on timeouts. diff --git a/pylabrobot/machines/backend.py b/pylabrobot/machines/backend.py index 1dab93ce246..686cd5bbebd 100644 --- a/pylabrobot/machines/backend.py +++ b/pylabrobot/machines/backend.py @@ -27,6 +27,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data: dict): + data = data.copy() class_name = data.pop("type") subclass = find_subclass(class_name, cls=cls) if subclass is None: diff --git a/pylabrobot/pumps/calibration.py b/pylabrobot/pumps/calibration.py index 48a25afb6e8..3a03a57895c 100644 --- a/pylabrobot/pumps/calibration.py +++ b/pylabrobot/pumps/calibration.py @@ -101,13 +101,6 @@ def serialize(self) -> dict: "calibration_mode": self.calibration_mode, } - @classmethod - def deserialize(cls, data: dict) -> PumpCalibration: - return cls( - calibration=data["calibration"], - calibration_mode=data["calibration_mode"], - ) - @classmethod def load_from_json( cls, diff --git a/pylabrobot/pumps/pump.py b/pylabrobot/pumps/pump.py index 9d92f7257ba..41e6b64f696 100644 --- a/pylabrobot/pumps/pump.py +++ b/pylabrobot/pumps/pump.py @@ -34,8 +34,7 @@ def deserialize(cls, data: dict): data_copy = data.copy() calibration_data = data_copy.pop("calibration", None) if calibration_data is not None: - calibration = PumpCalibration.deserialize(calibration_data) - data_copy["calibration"] = calibration + data_copy["calibration"] = PumpCalibration(**calibration_data) return super().deserialize(data_copy) async def run_revolutions(self, num_revolutions: float): diff --git a/pylabrobot/pumps/pumparray.py b/pylabrobot/pumps/pumparray.py index daedb626a46..b9deec65aea 100644 --- a/pylabrobot/pumps/pumparray.py +++ b/pylabrobot/pumps/pumparray.py @@ -50,8 +50,7 @@ def deserialize(cls, data: dict): data_copy = data.copy() calibration_data = data_copy.pop("calibration", None) if calibration_data is not None: - calibration = PumpCalibration.deserialize(calibration_data) - data_copy["calibration"] = calibration + data_copy["calibration"] = PumpCalibration(**calibration_data) return super().deserialize(data_copy) async def run_revolutions( diff --git a/pylabrobot/resources/barcode.py b/pylabrobot/resources/barcode.py index 25b4d1ac361..7f06252b146 100644 --- a/pylabrobot/resources/barcode.py +++ b/pylabrobot/resources/barcode.py @@ -36,13 +36,5 @@ def serialize(self) -> dict: "position_on_resource": self.position_on_resource, } - @staticmethod - def deserialize(data: dict) -> "Barcode": - return Barcode( - data=data["data"], - symbology=data["symbology"], - position_on_resource=data["position_on_resource"], - ) - def __str__(self) -> str: return f'Barcode(data="{self.data}", symbology="{self.symbology}", position_on_resource="{self.position_on_resource}")' diff --git a/pylabrobot/resources/carrier_tests.py b/pylabrobot/resources/carrier_tests.py index 0b704899824..a9dbd05f29a 100644 --- a/pylabrobot/resources/carrier_tests.py +++ b/pylabrobot/resources/carrier_tests.py @@ -221,13 +221,7 @@ def test_serialization(self): "size_x": 135.0, "size_y": 497.0, "size_z": 13.0, - "location": None, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, "category": "tip_carrier", - "model": None, - "barcode": None, - "preferred_pickup_location": None, - "parent_name": None, "children": [ { "name": "tip_car-0", @@ -241,14 +235,9 @@ def test_serialization(self): "y": 20, "z": 30, }, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, "category": "resource_holder", - "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, - "children": [], "parent_name": "tip_car", - "model": None, - "barcode": None, - "preferred_pickup_location": None, + "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, }, { "name": "tip_car-1", @@ -262,14 +251,9 @@ def test_serialization(self): "y": 50, "z": 30, }, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, "category": "resource_holder", - "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, - "children": [], "parent_name": "tip_car", - "model": None, - "barcode": None, - "preferred_pickup_location": None, + "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, }, { "name": "tip_car-2", @@ -283,14 +267,9 @@ def test_serialization(self): "y": 80, "z": 30, }, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, "category": "resource_holder", - "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, - "children": [], "parent_name": "tip_car", - "model": None, - "barcode": None, - "preferred_pickup_location": None, + "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, }, { "name": "tip_car-3", @@ -304,14 +283,9 @@ def test_serialization(self): "y": 130, "z": 30, }, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, "category": "resource_holder", - "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, - "children": [], "parent_name": "tip_car", - "model": None, - "barcode": None, - "preferred_pickup_location": None, + "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, }, { "name": "tip_car-4", @@ -325,14 +299,9 @@ def test_serialization(self): "y": 160, "z": 30, }, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, "category": "resource_holder", - "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, - "children": [], "parent_name": "tip_car", - "model": None, - "barcode": None, - "preferred_pickup_location": None, + "child_location": {"type": "Coordinate", "x": 0, "y": 0, "z": 0}, }, ], }, diff --git a/pylabrobot/resources/container_tests.py b/pylabrobot/resources/container_tests.py index 7d737092c2c..7def0eb7448 100644 --- a/pylabrobot/resources/container_tests.py +++ b/pylabrobot/resources/container_tests.py @@ -32,20 +32,12 @@ def compute_height_from_volume(volume): "size_x": 10, "size_y": 10, "size_z": 10, + "type": "Container", "material_z_thickness": 1, - "category": None, - "model": None, - "barcode": None, - "preferred_pickup_location": None, "max_volume": 1000, "compute_volume_from_height": serialize(compute_volume_from_height), "compute_height_from_volume": serialize(compute_height_from_volume), "height_volume_data": None, - "parent_name": None, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, - "type": "Container", - "children": [], - "location": None, }, ) diff --git a/pylabrobot/resources/deck.py b/pylabrobot/resources/deck.py index f2805bc7038..47e30c9d8c9 100644 --- a/pylabrobot/resources/deck.py +++ b/pylabrobot/resources/deck.py @@ -45,7 +45,7 @@ def __init__( def serialize(self) -> dict: """Serialize this deck.""" super_serialized = super().serialize() - del super_serialized["model"] # deck's don't typically have a model + super_serialized.pop("model", None) # deck's don't typically have a model return super_serialized def _check_naming_conflicts(self, resource: Resource): diff --git a/pylabrobot/resources/hamilton/tip_creators.py b/pylabrobot/resources/hamilton/tip_creators.py index 042052099a6..f51b593ddd8 100644 --- a/pylabrobot/resources/hamilton/tip_creators.py +++ b/pylabrobot/resources/hamilton/tip_creators.py @@ -90,24 +90,13 @@ def __repr__(self) -> str: def serialize(self): super_serialized = super().serialize() - del super_serialized["fitting_depth"] # inferred from tip size + super_serialized.pop("fitting_depth", None) # inferred from tip size return { **super_serialized, "pickup_method": self.pickup_method.name, "tip_size": self.tip_size.name, } - @classmethod - def deserialize(cls, data): - return HamiltonTip( - name=data["name"], - has_filter=data["has_filter"], - total_tip_length=data["total_tip_length"], - maximal_volume=data["maximal_volume"], - tip_size=TipSize[data["tip_size"]], - pickup_method=TipPickupMethod[data["pickup_method"]], - ) - def standard_volume_tip_no_filter(name: Optional[str] = None) -> HamiltonTip: """Deprecated. Use :func:`hamilton_tip_300uL` instead.""" diff --git a/pylabrobot/resources/hamilton/vantage_decks.py b/pylabrobot/resources/hamilton/vantage_decks.py index 56d06d6654b..01797975a69 100644 --- a/pylabrobot/resources/hamilton/vantage_decks.py +++ b/pylabrobot/resources/hamilton/vantage_decks.py @@ -61,5 +61,5 @@ def rails_to_location(self, rails: int) -> Coordinate: def serialize(self) -> dict: super_serialized = super().serialize() for key in ["size_x", "size_y", "size_z", "num_rails"]: - super_serialized.pop(key) + super_serialized.pop(key, None) return {"size": self.size, **super_serialized} diff --git a/pylabrobot/resources/petri_dish.py b/pylabrobot/resources/petri_dish.py index 410c105d1ee..e52052fa398 100644 --- a/pylabrobot/resources/petri_dish.py +++ b/pylabrobot/resources/petri_dish.py @@ -40,7 +40,7 @@ def __init__( def serialize(self): super_serialized = super().serialize() for key in ["size_x", "size_y", "size_z"]: - del super_serialized[key] + super_serialized.pop(key, None) return { **super_serialized, diff --git a/pylabrobot/resources/petri_dish_tests.py b/pylabrobot/resources/petri_dish_tests.py index 956f191a964..ac24ab11deb 100644 --- a/pylabrobot/resources/petri_dish_tests.py +++ b/pylabrobot/resources/petri_dish_tests.py @@ -18,22 +18,15 @@ def test_petri_dish_serialization(self): serialized, { "name": "petri_dish", + "type": "PetriDish", "category": "petri_dish", - "diameter": 90.0, - "height": 15.0, + "max_volume": 121500.0, "material_z_thickness": None, "compute_volume_from_height": None, "compute_height_from_volume": None, "height_volume_data": None, - "parent_name": None, - "type": "PetriDish", - "children": [], - "location": None, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, - "max_volume": 121500.0, - "model": None, - "barcode": None, - "preferred_pickup_location": None, + "diameter": 90.0, + "height": 15.0, }, ) @@ -44,18 +37,11 @@ def test_petri_dish_holder_serialization(self): serialized, { "name": "petri_dish_holder", - "category": "petri_dish_holder", + "type": "PetriDishHolder", "size_x": 127.76, "size_y": 85.48, "size_z": 14.5, - "parent_name": None, - "type": "PetriDishHolder", - "children": [], - "location": None, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, - "model": None, - "barcode": None, - "preferred_pickup_location": None, + "category": "petri_dish_holder", }, ) diff --git a/pylabrobot/resources/plate_adapter.py b/pylabrobot/resources/plate_adapter.py index 164d46d5318..750b4ae7445 100644 --- a/pylabrobot/resources/plate_adapter.py +++ b/pylabrobot/resources/plate_adapter.py @@ -117,25 +117,6 @@ def serialize(self) -> dict: "plate_z_offset": self.plate_z_offset, } - @classmethod - def deserialize(cls, data: dict, allow_marshal: bool = False) -> PlateAdapter: - return cls( - name=data["name"], - size_x=data["size_x"], - size_y=data["size_y"], - size_z=data["size_z"], - dx=data["dx"], - dy=data["dy"], - dz=data["dz"], - adapter_hole_size_x=data["adapter_hole_size_x"], - adapter_hole_size_y=data["adapter_hole_size_y"], - adapter_hole_dx=data["adapter_hole_dx"], - adapter_hole_dy=data["adapter_hole_dy"], - plate_z_offset=data["plate_z_offset"], - category=data.get("category"), - model=data.get("model"), - ) - def compute_plate_location(self, resource: Plate) -> Coordinate: """Compute the location of the `Plate` child resource in relationship to the `PlateAdapter` to align the `Plate` well-grid with the adapter's hole grid.""" diff --git a/pylabrobot/resources/plate_adapter_tests.py b/pylabrobot/resources/plate_adapter_tests.py index 9d3d1f0ce8c..1dd936fe530 100644 --- a/pylabrobot/resources/plate_adapter_tests.py +++ b/pylabrobot/resources/plate_adapter_tests.py @@ -29,14 +29,7 @@ def test_plate_adapter_serialization(self): "size_x": 128.0, "size_y": 86.0, "size_z": 15.0, - "location": None, - "rotation": {"x": 0, "y": 0, "z": 0, "type": "Rotation"}, "category": "plate_adapter", - "model": None, - "barcode": None, - "preferred_pickup_location": None, - "children": [], - "parent_name": None, "dx": 0.0, "dy": 1.0, "dz": 2.0, diff --git a/pylabrobot/resources/resource.py b/pylabrobot/resources/resource.py index 2d03af454f0..9c831e31e07 100644 --- a/pylabrobot/resources/resource.py +++ b/pylabrobot/resources/resource.py @@ -125,21 +125,30 @@ def get_size_z(self) -> float: return self._local_size_z def serialize(self) -> dict: - return { + data: dict = { "name": self.name, "type": self.__class__.__name__, "size_x": self._size_x, "size_y": self._size_y, "size_z": self._size_z, - "location": serialize(self.location), - "rotation": serialize(self.rotation), - "category": self.category, - "model": self.model, - "barcode": self.barcode.serialize() if self.barcode is not None else None, - "preferred_pickup_location": serialize(self.preferred_pickup_location), - "children": [child.serialize() for child in self.children], - "parent_name": self.parent.name if self.parent is not None else None, } + if self.location is not None: + data["location"] = serialize(self.location) + if not (self.rotation.x == 0 and self.rotation.y == 0 and self.rotation.z == 0): + data["rotation"] = serialize(self.rotation) + if self.category is not None: + data["category"] = self.category + if self.model is not None: + data["model"] = self.model + if self.barcode is not None: + data["barcode"] = self.barcode.serialize() + if self.preferred_pickup_location is not None: + data["preferred_pickup_location"] = serialize(self.preferred_pickup_location) + if self.children: + data["children"] = [child.serialize() for child in self.children] + if self.parent is not None: + data["parent_name"] = self.parent.name + return data @property def name(self) -> str: @@ -750,15 +759,16 @@ def deserialize(cls, data: dict, allow_marshal: bool = False) -> Self: "parent_name", "location", ]: # delete meta keys - del data_copy[key] - children_data = data_copy.pop("children") - rotation = data_copy.pop("rotation") + data_copy.pop(key, None) + children_data = data_copy.pop("children", []) + rotation = data_copy.pop("rotation", None) barcode = data_copy.pop("barcode", None) preferred_pickup_location = data_copy.pop("preferred_pickup_location", None) resource = subclass(**deserialize(data_copy, allow_marshal=allow_marshal)) - resource.rotation = Rotation.deserialize(rotation) # not pretty, should be done in init. + if rotation is not None: + resource.rotation = deserialize(rotation) # not pretty, should be done in init. if barcode is not None: - resource.barcode = Barcode.deserialize(barcode) + resource.barcode = Barcode(**barcode) if preferred_pickup_location is not None: resource.preferred_pickup_location = cast(Coordinate, deserialize(preferred_pickup_location)) diff --git a/pylabrobot/resources/resource_tests.py b/pylabrobot/resources/resource_tests.py index 9ef3c987edb..7b393633d0a 100644 --- a/pylabrobot/resources/resource_tests.py +++ b/pylabrobot/resources/resource_tests.py @@ -224,27 +224,15 @@ def test_serialize(self): r.serialize(), { "name": "test", - "location": None, - "rotation": { - "type": "Rotation", - "x": 0, - "y": 0, - "z": 0, - }, "size_x": 10, "size_y": 10, "size_z": 10, "type": "Resource", - "children": [], - "category": None, - "parent_name": None, - "model": None, "barcode": { "data": "1234567890", "symbology": "code128", "position_on_resource": "left", }, - "preferred_pickup_location": None, }, ) @@ -257,13 +245,6 @@ def test_child_serialize(self): r.serialize(), { "name": "test", - "location": None, - "rotation": { - "type": "Rotation", - "x": 0, - "y": 0, - "z": 0, - }, "size_x": 10, "size_y": 10, "size_z": 10, @@ -277,29 +258,13 @@ def test_child_serialize(self): "y": 5, "z": 5, }, - "rotation": { - "type": "Rotation", - "x": 0, - "y": 0, - "z": 0, - }, "size_x": 1, "size_y": 1, "size_z": 1, "type": "Resource", - "children": [], - "category": None, "parent_name": "test", - "model": None, - "barcode": None, - "preferred_pickup_location": None, } ], - "category": None, - "parent_name": None, - "model": None, - "barcode": None, - "preferred_pickup_location": None, }, ) diff --git a/pylabrobot/resources/rotation.py b/pylabrobot/resources/rotation.py index 26cce995477..59b7e822adb 100644 --- a/pylabrobot/resources/rotation.py +++ b/pylabrobot/resources/rotation.py @@ -63,10 +63,6 @@ def __str__(self) -> str: def __add__(self, other) -> "Rotation": return Rotation(x=self.x + other.x, y=self.y + other.y, z=self.z + other.z) - @staticmethod - def deserialize(data) -> "Rotation": - return Rotation(data["x"], data["y"], data["z"]) - def __repr__(self) -> str: return self.__str__() diff --git a/pylabrobot/resources/tip_rack.py b/pylabrobot/resources/tip_rack.py index 149b90c445a..9c0c94eca1b 100644 --- a/pylabrobot/resources/tip_rack.py +++ b/pylabrobot/resources/tip_rack.py @@ -122,7 +122,7 @@ def make_tip(name: str) -> Tip: name=data["name"], size_x=data["size_x"], size_y=data["size_y"], - size_z=data["size_z"], + size_z=data.get("size_z", 0), make_tip=make_tip, category=data.get("category", "tip_spot"), ) diff --git a/pylabrobot/resources/tip_tests.py b/pylabrobot/resources/tip_tests.py index 668c78cbae3..f2a1b15928b 100644 --- a/pylabrobot/resources/tip_tests.py +++ b/pylabrobot/resources/tip_tests.py @@ -61,4 +61,4 @@ def test_deserialize_subclass(self): TipPickupMethod.OUT_OF_RACK, name="test_tip", ) - self.assertEqual(HamiltonTip.deserialize(tip.serialize()), tip) + self.assertEqual(deserialize(tip.serialize()), tip) diff --git a/pylabrobot/resources/well_tests.py b/pylabrobot/resources/well_tests.py index f322d88521b..f42e6120199 100644 --- a/pylabrobot/resources/well_tests.py +++ b/pylabrobot/resources/well_tests.py @@ -23,22 +23,16 @@ def test_serialize(self): "size_x": 1, "size_y": 2, "size_z": 3, - "material_z_thickness": None, - "bottom_type": "flat", - "cross_section_type": "circle", - "max_volume": 10, - "model": "model", - "barcode": None, - "preferred_pickup_location": None, - "category": "well", - "children": [], "type": "Well", - "parent_name": None, - "location": None, - "rotation": {"type": "Rotation", "x": 0, "y": 0, "z": 0}, + "category": "well", + "model": "model", + "max_volume": 10, + "material_z_thickness": None, "compute_volume_from_height": None, "compute_height_from_volume": None, "height_volume_data": None, + "bottom_type": "flat", + "cross_section_type": "circle", }, ) diff --git a/pylabrobot/storage/cytomat/constants.py b/pylabrobot/storage/cytomat/constants.py index 29f68ec0c2e..410f88108ba 100644 --- a/pylabrobot/storage/cytomat/constants.py +++ b/pylabrobot/storage/cytomat/constants.py @@ -137,10 +137,6 @@ class CytomatRack: num_slots: int # number of plate locations in rack pitch: int # distance between 2 plate locations - @classmethod - def deserialize(cls, data: dict): - return cls(num_slots=data["num_slots"], pitch=data["pitch"]) - class CytomatType(Enum): C6000 = "C6000" diff --git a/pylabrobot/storage/cytomat/heraeus_cytomat_backend.py b/pylabrobot/storage/cytomat/heraeus_cytomat_backend.py index a991d55fc59..ec7553d9fb0 100644 --- a/pylabrobot/storage/cytomat/heraeus_cytomat_backend.py +++ b/pylabrobot/storage/cytomat/heraeus_cytomat_backend.py @@ -204,7 +204,3 @@ def serialize(self) -> dict: **super().serialize(), "port": self.io.port, } - - @classmethod - def deserialize(cls, data: dict): - return cls(port=data["port"]) diff --git a/pylabrobot/storage/incubator.py b/pylabrobot/storage/incubator.py index 4a4d6d5fe64..638fe4a376d 100644 --- a/pylabrobot/storage/incubator.py +++ b/pylabrobot/storage/incubator.py @@ -196,16 +196,16 @@ def serialize(self): @classmethod def deserialize(cls, data: dict, allow_marshal: bool = False): - backend = IncubatorBackend.deserialize(data.pop("backend")) + rotation_data = data.get("rotation") return cls( - backend=backend, + backend=IncubatorBackend.deserialize(data["backend"]), name=data["name"], size_x=data["size_x"], size_y=data["size_y"], size_z=data["size_z"], racks=[PlateCarrier.deserialize(rack) for rack in data["racks"]], loading_tray_location=cast(Coordinate, deserialize(data["loading_tray_location"])), - rotation=Rotation.deserialize(data["rotation"]), - category=data["category"], - model=data["model"], + rotation=deserialize(rotation_data) if rotation_data else None, + category=data.get("category"), + model=data.get("model"), ) diff --git a/pylabrobot/storage/inheco/scila/scila_backend.py b/pylabrobot/storage/inheco/scila/scila_backend.py index 4f046ed67ff..e1759bf94a7 100644 --- a/pylabrobot/storage/inheco/scila/scila_backend.py +++ b/pylabrobot/storage/inheco/scila/scila_backend.py @@ -131,7 +131,3 @@ def serialize(self) -> dict[str, Any]: "scila_ip": self._sila_interface.machine_ip, "client_ip": self._sila_interface.client_ip, } - - @classmethod - def deserialize(cls, data: dict[str, Any]) -> "SCILABackend": - return cls(scila_ip=data["scila_ip"], client_ip=data.get("client_ip")) diff --git a/pylabrobot/storage/inheco/scila/scila_backend_tests.py b/pylabrobot/storage/inheco/scila/scila_backend_tests.py index 03cad4dd5f7..b1955a20e7a 100644 --- a/pylabrobot/storage/inheco/scila/scila_backend_tests.py +++ b/pylabrobot/storage/inheco/scila/scila_backend_tests.py @@ -2,6 +2,7 @@ import xml.etree.ElementTree as ET from unittest.mock import AsyncMock, patch +from pylabrobot.machines.backend import MachineBackend from pylabrobot.storage.inheco.scila.inheco_sila_interface import InhecoSiLAInterface from pylabrobot.storage.inheco.scila.scila_backend import SCILABackend @@ -220,15 +221,15 @@ def test_serialize_no_client_ip(self): self.assertIsNone(data["client_ip"]) def test_deserialize(self): - data = {"scila_ip": "169.254.1.117", "client_ip": "192.168.1.10"} - SCILABackend.deserialize(data) + data = {"type": "SCILABackend", "scila_ip": "169.254.1.117", "client_ip": "192.168.1.10"} + MachineBackend.deserialize(data) self.MockInhecoSiLAInterface.assert_called_with( client_ip="192.168.1.10", machine_ip="169.254.1.117" ) def test_deserialize_no_client_ip(self): - data = {"scila_ip": "169.254.1.117"} - SCILABackend.deserialize(data) + data = {"type": "SCILABackend", "scila_ip": "169.254.1.117"} + MachineBackend.deserialize(data) self.MockInhecoSiLAInterface.assert_called_with(client_ip=None, machine_ip="169.254.1.117") diff --git a/pylabrobot/tests/serializer_tests.py b/pylabrobot/tests/serializer_tests.py index 356ae12cafd..8b8e3510816 100644 --- a/pylabrobot/tests/serializer_tests.py +++ b/pylabrobot/tests/serializer_tests.py @@ -1,6 +1,9 @@ import math -from pylabrobot.serializer import deserialize, serialize +from pylabrobot.serializer import ( + deserialize, + serialize, +) def test_serialize_deserialize_closure():