Skip to content

Commit

Permalink
Merge pull request #372 from nada-ben-ali/NaBe/add_pickle_support
Browse files Browse the repository at this point in the history
Add Pickle support
  • Loading branch information
nada-ben-ali authored Dec 19, 2024
2 parents fa67369 + af72b9d commit 03a096f
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
10 changes: 10 additions & 0 deletions odxtools/nameditemlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ def __deepcopy__(self, memo: Dict[int, Any]) -> Any:

return result

def __reduce__(self) -> Tuple[Any, ...]:
"""Support for Python's pickle protocol.
This method ensures that the object can be reconstructed with its current state,
using its class and the list of items it contains.
It returns a tuple containing the reconstruction function (the class)
and its arguments necessary to recreate the object.
"""
return self.__class__, (list(self),)


class NamedItemList(ItemAttributeList[T]):

Expand Down
9 changes: 7 additions & 2 deletions odxtools/tablerow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: MIT
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from dataclasses import dataclass, fields
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
from xml.etree import ElementTree

from .basicstructure import BasicStructure
Expand Down Expand Up @@ -157,3 +157,8 @@ def structure(self) -> Optional[BasicStructure]:
def dop(self) -> Optional[DataObjectProperty]:
"""The data object property object resolved by dop_ref."""
return self._dop

def __reduce__(self) -> Tuple[Any, ...]:
"""This ensures that the object can be correctly reconstructed during unpickling."""
state = self.__dict__.copy()
return self.__class__, tuple([getattr(self, x.name) for x in fields(self)]), state
7 changes: 7 additions & 0 deletions tests/test_decoding.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: MIT
import pickle
import unittest

from odxtools.compumethods.compuinternaltophys import CompuInternalToPhys
Expand Down Expand Up @@ -2447,6 +2448,12 @@ def test_decode_response(self) -> None:
self.assertEqual(expected_message.coding_object, decoded_message.coding_object)
self.assertEqual(expected_message.param_dict, decoded_message.param_dict)

# check object serialization and deserialization using pickle
pickled_ecu_var = pickle.dumps(ecu_variant)
unpickled_ecu_var = pickle.loads(pickled_ecu_var)

self.assertEqual(ecu_variant, unpickled_ecu_var)

def test_code_dtc(self) -> None:
odxlinks = OdxLinkDatabase()
diag_coded_type = StandardLengthType(
Expand Down
21 changes: 16 additions & 5 deletions tests/test_odxtools.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: MIT
import pickle
import unittest
from dataclasses import dataclass
from typing import List
Expand Down Expand Up @@ -90,16 +91,26 @@ def test_encode_response_with_matching_request_param_and_structure(self) -> None
self.assertEqual(bytes(coded_response), bytes.fromhex("faba03"))


@dataclass
class X:
short_name: str
value: int


class TestNamedItemList(unittest.TestCase):

def test_NamedItemList(self) -> None:
foo = NamedItemList([X("hello", 0), X("world", 1)])

@dataclass
class X:
short_name: str
value: int
pickled_foo = pickle.dumps(foo)
unpickled_foo = pickle.loads(pickled_foo)

foo = NamedItemList([X("hello", 0), X("world", 1)])
# Test with the original object
self._test_NamedItemList_functionality(foo)
# Test with the pickled object
self._test_NamedItemList_functionality(unpickled_foo)

def _test_NamedItemList_functionality(self, foo: NamedItemList[X]) -> None:
self.assertEqual(foo.hello, X("hello", 0))
self.assertEqual(foo[0], X("hello", 0))
self.assertEqual(foo[1], X("world", 1))
Expand Down

0 comments on commit 03a096f

Please sign in to comment.