Skip to content

Commit 91ea5da

Browse files
committed
Add support for complex dictionary types
1 parent ab01bec commit 91ea5da

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

pycardano/plutus.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,35 @@ def _dfs(obj):
589589
raise DeserializeException(
590590
f"Unexpected data structure: {f}."
591591
)
592+
elif (
593+
hasattr(f_info.type, "__origin__")
594+
and f_info.type.__origin__ is dict
595+
):
596+
t_args = f_info.type.__args__
597+
if len(t_args) != 2:
598+
raise DeserializeException(
599+
"Dict type with wrong number of arguments"
600+
)
601+
if "map" not in f:
602+
raise DeserializeException(
603+
f'Expected type "map" in object but got "{f}"'
604+
)
605+
key_t = t_args[0]
606+
val_t = t_args[1]
607+
if inspect.isclass(key_t) and issubclass(key_t, PlutusData):
608+
key_convert = key_t.from_dict
609+
else:
610+
key_convert = _dfs
611+
if inspect.isclass(val_t) and issubclass(val_t, PlutusData):
612+
val_convert = val_t.from_dict
613+
else:
614+
val_convert = _dfs
615+
converted_fields.append(
616+
{
617+
key_convert(pair["k"]): val_convert(pair["v"])
618+
for pair in f["map"]
619+
}
620+
)
592621
else:
593622
converted_fields.append(_dfs(f))
594623
return cls(*converted_fields)

test/pycardano/test_plutus.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from dataclasses import dataclass
22
from test.pycardano.util import check_two_way_cbor
3-
from typing import Union
3+
from typing import Union, Dict
44

55
import pytest
66

@@ -39,6 +39,13 @@ class LargestTest(PlutusData):
3939
CONSTR_ID = 9
4040

4141

42+
@dataclass
43+
class DictTest(PlutusData):
44+
CONSTR_ID = 3
45+
46+
a: Dict[int, LargestTest]
47+
48+
4249
@dataclass
4350
class VestingParam(PlutusData):
4451
CONSTR_ID = 1
@@ -95,6 +102,19 @@ def test_plutus_data_json():
95102
assert my_vesting == VestingParam.from_json(encoded_json)
96103

97104

105+
def test_plutus_data_json_dict():
106+
test = DictTest({0: LargestTest(), 1: LargestTest()})
107+
108+
encoded_json = test.to_json(separators=(",", ":"))
109+
110+
assert (
111+
'{"constructor":3,"fields":[{"map":[{"v":{"constructor":9,"fields":[]},"k":{"int":0}},{"v":{"constructor":9,"fields":[]},"k":{"int":1}}]}]}'
112+
== encoded_json
113+
)
114+
115+
assert test == DictTest.from_json(encoded_json)
116+
117+
98118
def test_plutus_data_to_json_wrong_type():
99119
test = MyTest(123, b"1234", IndefiniteList([4, 5, 6]), {1: b"1", 2: b"2"})
100120
test.a = "123"

0 commit comments

Comments
 (0)