File size: 4,201 Bytes
985c397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# SPDX-License-Identifier: LGPL-2.1-or-later

# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# *                                                                         *
# *   Copyright (c) 2025 Samuel Abels <knipknap@gmail.com>                  *
# *                                                                         *
# *   This file is part of FreeCAD.                                         *
# *                                                                         *
# *   FreeCAD is free software: you can redistribute it and/or modify it    *
# *   under the terms of the GNU Lesser General Public License as           *
# *   published by the Free Software Foundation, either version 2.1 of the  *
# *   License, or (at your option) any later version.                       *
# *                                                                         *
# *   FreeCAD is distributed in the hope that it will be useful, but        *
# *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
# *   Lesser General Public License for more details.                       *
# *                                                                         *
# *   You should have received a copy of the GNU Lesser General Public      *
# *   License along with FreeCAD. If not, see                               *
# *   <https://www.gnu.org/licenses/>.                                      *
# *                                                                         *
# ***************************************************************************

import yaml
from typing import List, Optional, Mapping, Type
from ...assets.serializer import AssetSerializer
from ...assets.uri import AssetUri
from ...shape import ToolBitShape
from ..models.base import ToolBit


class YamlToolBitSerializer(AssetSerializer):
    """
    Serializes and deserializes ToolBit instances to and from YAML.
    """

    for_class: Type[ToolBit] = ToolBit
    extensions: tuple[str, ...] = (".yaml", ".yml")
    mime_type: str = "application/x-yaml"
    can_import: bool = True
    can_export: bool = True

    @classmethod
    def get_label(cls) -> str:
        return "YAML ToolBit"

    @classmethod
    def extract_dependencies(cls, data: bytes) -> List[AssetUri]:
        """Extracts URIs of dependencies from serialized data."""
        data_dict = yaml.safe_load(data)
        if isinstance(data_dict, dict):
            shape_id = data_dict.get("shape")
            if shape_id:
                # Assuming shape is identified by its ID/name
                return [ToolBitShape.resolve_name(str(shape_id))]
        return []

    @classmethod
    def serialize(cls, asset: ToolBit) -> bytes:
        """Serializes a ToolBit instance to bytes (shallow)."""
        # Shallow serialization: only serialize direct attributes and shape ID
        data = asset.to_dict()
        return yaml.dump(data, default_flow_style=False).encode("utf-8")

    @classmethod
    def deserialize(
        cls,
        data: bytes,
        id: str | None = None,
        dependencies: Optional[Mapping[AssetUri, ToolBitShape]] = None,
    ) -> ToolBit:
        """
        Creates a ToolBit instance from serialized data and resolved
        dependencies (shallow).
        """
        data_dict = yaml.safe_load(data)
        if not isinstance(data_dict, dict):
            raise ValueError("Invalid YAML data for ToolBit")
        toolbit = ToolBit.from_dict(data_dict)
        if id:
            toolbit.id = id
        return toolbit

    @classmethod
    def deep_deserialize(cls, data: bytes) -> ToolBit:
        """Deep deserialize preserving the original toolbit ID."""
        data_dict = yaml.safe_load(data)
        if not isinstance(data_dict, dict):
            raise ValueError("Invalid YAML data for ToolBit")

        original_id = data_dict.get("id")  # Extract the original ID
        toolbit = ToolBit.from_dict(data_dict)
        if original_id:
            toolbit.id = original_id  # Preserve the original ID
        return toolbit