simplified deserialisation
All checks were successful
Python CI / test (push) Successful in 1m40s
Lint / lint (push) Successful in 1m29s
Tests / test (3.11) (push) Successful in 1m48s
Tests / test (3.12) (push) Successful in 1m51s
Tests / test (3.13) (push) Successful in 1m46s
Tests / test (3.14) (push) Successful in 1m29s

This commit is contained in:
Duncan Tourolle 2026-01-01 14:17:16 +01:00
parent 3a2d8b05db
commit 293b568772
2 changed files with 48 additions and 126 deletions

View File

@ -27,6 +27,34 @@ def _normalize_asset_path(image_path: str, asset_manager) -> str:
return image_path
def _deserialize_element(elem_data: Dict[str, Any]) -> BaseLayoutElement:
"""
Deserialize element data into the appropriate element type.
Args:
elem_data: Dictionary containing serialized element data with 'type' key
Returns:
Deserialized element instance (ImageData, PlaceholderData, or TextBoxData)
Raises:
ValueError: If element type is unknown
"""
elem_type = elem_data.get("type")
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
raise ValueError(f"Unknown element type: {elem_type}")
element.deserialize(elem_data)
return element
class Command(ABC):
"""Abstract base class for all commands"""
@ -94,24 +122,8 @@ class AddElementCommand(Command):
@staticmethod
def deserialize(data: Dict[str, Any], project) -> "AddElementCommand":
"""Deserialize from dictionary"""
# Reconstruct element from serialized data
elem_data = data["element"]
elem_type = elem_data.get("type")
element: BaseLayoutElement
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
raise ValueError(f"Unknown element type: {elem_type}")
element.deserialize(elem_data)
# Note: We need to find the correct page_layout
# This will be handled by the CommandHistory deserializer
element = _deserialize_element(data["element"])
# Note: page_layout will be handled by the CommandHistory deserializer
cmd = AddElementCommand(None, element)
cmd.executed = data.get("executed", False)
return cmd
@ -154,21 +166,7 @@ class DeleteElementCommand(Command):
@staticmethod
def deserialize(data: Dict[str, Any], project) -> "DeleteElementCommand":
"""Deserialize from dictionary"""
elem_data = data["element"]
elem_type = elem_data.get("type")
element: BaseLayoutElement
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
raise ValueError(f"Unknown element type: {elem_type}")
element.deserialize(elem_data)
element = _deserialize_element(data["element"])
cmd = DeleteElementCommand(None, element)
cmd.executed = data.get("executed", False)
return cmd
@ -206,21 +204,7 @@ class MoveElementCommand(Command):
@staticmethod
def deserialize(data: Dict[str, Any], project) -> "MoveElementCommand":
"""Deserialize from dictionary"""
elem_data = data["element"]
elem_type = elem_data.get("type")
element: BaseLayoutElement
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
raise ValueError(f"Unknown element type: {elem_type}")
element.deserialize(elem_data)
element = _deserialize_element(data["element"])
return MoveElementCommand(element, tuple(data["old_position"]), tuple(data["new_position"]))
@ -264,21 +248,7 @@ class ResizeElementCommand(Command):
@staticmethod
def deserialize(data: Dict[str, Any], project) -> "ResizeElementCommand":
"""Deserialize from dictionary"""
elem_data = data["element"]
elem_type = elem_data.get("type")
element: BaseLayoutElement
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
raise ValueError(f"Unknown element type: {elem_type}")
element.deserialize(elem_data)
element = _deserialize_element(data["element"])
return ResizeElementCommand(
element,
tuple(data["old_position"]),
@ -389,21 +359,7 @@ class RotateElementCommand(Command):
@staticmethod
def deserialize(data: Dict[str, Any], project) -> "RotateElementCommand":
"""Deserialize from dictionary"""
elem_data = data["element"]
elem_type = elem_data.get("type")
element: BaseLayoutElement
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
raise ValueError(f"Unknown element type: {elem_type}")
element.deserialize(elem_data)
element = _deserialize_element(data["element"])
return RotateElementCommand(element, data["old_rotation"], data["new_rotation"])
@ -487,23 +443,12 @@ class AlignElementsCommand(Command):
"""Deserialize from dictionary"""
changes = []
for change_data in data.get("changes", []):
elem_data = change_data["element"]
elem_type = elem_data.get("type")
element: BaseLayoutElement
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
try:
element = _deserialize_element(change_data["element"])
old_position = tuple(change_data["old_position"])
changes.append((element, old_position))
except ValueError:
continue
element.deserialize(elem_data)
old_position = tuple(change_data["old_position"])
changes.append((element, old_position))
return AlignElementsCommand(changes)
@ -549,24 +494,13 @@ class ResizeElementsCommand(Command):
"""Deserialize from dictionary"""
changes = []
for change_data in data.get("changes", []):
elem_data = change_data["element"]
elem_type = elem_data.get("type")
element: BaseLayoutElement
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
try:
element = _deserialize_element(change_data["element"])
old_position = tuple(change_data["old_position"])
old_size = tuple(change_data["old_size"])
changes.append((element, old_position, old_size))
except ValueError:
continue
element.deserialize(elem_data)
old_position = tuple(change_data["old_position"])
old_size = tuple(change_data["old_size"])
changes.append((element, old_position, old_size))
return ResizeElementsCommand(changes)
@ -609,21 +543,7 @@ class ChangeZOrderCommand(Command):
@staticmethod
def deserialize(data: Dict[str, Any], project) -> "ChangeZOrderCommand":
"""Deserialize from dictionary"""
elem_data = data["element"]
elem_type = elem_data.get("type")
element: BaseLayoutElement
if elem_type == "image":
element = ImageData()
elif elem_type == "placeholder":
element = PlaceholderData()
elif elem_type == "textbox":
element = TextBoxData()
else:
raise ValueError(f"Unknown element type: {elem_type}")
element.deserialize(elem_data)
element = _deserialize_element(data["element"])
return ChangeZOrderCommand(
None, element, data["old_index"], data["new_index"] # page_layout will be set by CommandHistory
)

View File

@ -734,6 +734,7 @@ class TestCommandHistory:
"""Test deserializing unknown command type returns None and continues"""
history = CommandHistory()
mock_project = Mock()
mock_project.pages = []
data = {
"undo_stack": [
@ -797,6 +798,7 @@ class TestCommandHistory:
# Deserialize
mock_project = Mock()
mock_project.pages = []
new_history = CommandHistory()
new_history.deserialize(data, mock_project)