From cfaf7a369f4b597b459be864b7041edb3b65a1f4 Mon Sep 17 00:00:00 2001 From: Jerry Date: Sun, 23 Apr 2023 22:39:54 -0700 Subject: [PATCH] Fix deep copy of plutus data copy.deepcopy doesn't work natively for CBORTag, which is frequently used in PlutusData. This commit implements __deepcopy__ methods for PlutusData and RawPlutusData by serializing the object into cbor and deserializing them back to new objects. --- pycardano/plutus.py | 6 ++++++ test/pycardano/test_plutus.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/pycardano/plutus.py b/pycardano/plutus.py index 3f64400b..b52b82a8 100644 --- a/pycardano/plutus.py +++ b/pycardano/plutus.py @@ -666,6 +666,9 @@ def from_json(cls: Type[PlutusData], data: str) -> PlutusData: obj = json.loads(data) return cls.from_dict(obj) + def __deepcopy__(self, memo): + return self.__class__.from_cbor(self.to_cbor()) + @dataclass class RawPlutusData(CBORSerializable): @@ -692,6 +695,9 @@ def _dfs(obj): def from_primitive(cls: Type[RawPlutusData], value: CBORTag) -> RawPlutusData: return cls(value) + def __deepcopy__(self, memo): + return self.__class__.from_cbor(self.to_cbor()) + Datum = Union[PlutusData, dict, int, bytes, IndefiniteList, RawCBOR, RawPlutusData] """Plutus Datum type. A Union type that contains all valid datum types.""" diff --git a/test/pycardano/test_plutus.py b/test/pycardano/test_plutus.py index 4bdaa641..298d5f98 100644 --- a/test/pycardano/test_plutus.py +++ b/test/pycardano/test_plutus.py @@ -1,9 +1,11 @@ +import copy import unittest from dataclasses import dataclass from test.pycardano.util import check_two_way_cbor from typing import Dict, List, Union import pytest +from cbor2 import CBORTag from pycardano.exception import DeserializeException, SerializeException from pycardano.plutus import ( @@ -284,3 +286,33 @@ def test_raw_plutus_data(): raw_plutus_data = RawPlutusData.from_cbor(raw_plutus_cbor) assert raw_plutus_data.to_cbor() == raw_plutus_cbor check_two_way_cbor(raw_plutus_data) + + +def test_clone_raw_plutus_data(): + tag = RawPlutusData(CBORTag(121, [1000])) + + cloned_tag = copy.deepcopy(tag) + assert cloned_tag == tag + assert cloned_tag.to_cbor() == tag.to_cbor() + + tag.data.value = [1001] + + assert cloned_tag != tag + + +def test_clone_plutus_data(): + key_hash = bytes.fromhex("c2ff616e11299d9094ce0a7eb5b7284b705147a822f4ffbd471f971a") + deadline = 1643235300000 + testa = BigTest(MyTest(123, b"1234", IndefiniteList([4, 5, 6]), {1: b"1", 2: b"2"})) + testb = LargestTest() + my_vesting = VestingParam( + beneficiary=key_hash, deadline=deadline, testa=testa, testb=testb + ) + + cloned_vesting = copy.deepcopy(my_vesting) + assert cloned_vesting == my_vesting + assert cloned_vesting.to_cbor() == my_vesting.to_cbor() + + my_vesting.deadline = 1643235300001 + + assert cloned_vesting != my_vesting