Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor json decorator #1482

Merged
merged 15 commits into from
Oct 25, 2023
9 changes: 1 addition & 8 deletions bindings/python/iota_sdk/types/burn.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations # Allow reference to Burn in Burn class
from typing import List, Optional, Dict, Any
from typing import List, Optional
from dataclasses import dataclass
from iota_sdk.types.native_token import NativeToken
from iota_sdk.types.common import HexStr, json
Expand Down Expand Up @@ -57,10 +57,3 @@ def add_native_token(self, native_token: NativeToken) -> Burn:
else:
self.native_tokens.append(native_token)
return self

@staticmethod
def _to_dict_custom(config) -> Dict[str, Any]:
if "nativeTokens" in config:
config["nativeTokens"] = {nativeToken.to_dict()["id"]: nativeToken.to_dict()[
"amount"] for nativeToken in config["nativeTokens"]}
return config
66 changes: 36 additions & 30 deletions bindings/python/iota_sdk/types/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,38 @@
from typing import NewType, Optional
from enum import IntEnum
from dataclasses import dataclass, field
from dataclasses_json import DataClassJsonMixin, dataclass_json, LetterCase, Undefined, config
from dataclasses_json import dataclass_json, LetterCase, Undefined, config

HexStr = NewType("HexStr", str)
EpochIndex = NewType("EpochIndex", int)
SlotIndex = NewType("SlotIndex", int)


def json(cls):
"""Decorator to add custom to_dict and to_json methods to a dataclass."""
# Apply the dataclass_json decorator first to get the default behavior
"""Decorator to add to_dict and to_json methods to a dataclass."""

# Store override methods if they exist
override_to_dict = getattr(cls, "to_dict", None)
override_to_json = getattr(cls, "to_json", None)

# Apply the dataclass_json decorator to get the default behavior
cls = dataclass_json(
letter_case=LetterCase.CAMEL,
undefined=Undefined.RAISE)(cls)

# Store original methods
original_to_dict = cls.to_dict
# Re-apply the original fns if they exist
if override_to_dict:
setattr(cls, "to_dict", override_to_dict)
if override_to_json:
setattr(cls, "to_json", override_to_json)

# Override methods
def custom_to_dict(self, *args, **kwargs):
original_dict = original_to_dict(self, *args, **kwargs)
# Override to_dict to remove None values
def custom_to_dict(cls, *args, **kwargs):
original_dict = cls.to_dict(*args, **kwargs)
result = {k: v for k, v in original_dict.items() if v is not None}
if hasattr(cls, "_to_dict_custom"):
result = getattr(cls, "_to_dict_custom")(result)
return result

def custom_to_json(self, *args, **kwargs):
# Use the custom to_dict method for serialization
return DataClassJsonMixin.to_json(self, *args, **kwargs)

setattr(cls, "to_dict", custom_to_dict)
setattr(cls, "to_json", custom_to_json)

return cls

Expand Down Expand Up @@ -74,21 +75,26 @@ class Node():
password: Optional[str] = None
disabled: Optional[bool] = None

@staticmethod
def _to_dict_custom(encoded):

if 'jwt' in encoded or 'username' in encoded or 'password' in encoded:
encoded['auth'] = {}
if 'jwt' in encoded:
encoded['auth']['jwt'] = encoded.pop('jwt')
if 'username' in encoded or 'password' in encoded:
basic_auth = encoded['auth']['basicAuthNamePwd'] = []
if 'username' in encoded:
basic_auth.append(encoded.pop('username'))
if 'password' in encoded:
basic_auth.append(encoded.pop('password'))

return encoded
def to_dict(self):
"""Custom dict conversion.
"""

res = {
'url': self.url,
'disabled': self.disabled
}
if self.jwt is not None or self.username is not None or self.password is not None:
auth = res['auth'] = {}
if self.jwt is not None:
auth['jwt'] = self.jwt
if self.username is not None or self.password is not None:
basic_auth = auth['basicAuthNamePwd'] = []
if self.username is not None:
basic_auth.append(self.username)
if self.password is not None:
basic_auth.append(self.password)

return res


def opt_int_encoder(value):
Expand Down
17 changes: 7 additions & 10 deletions bindings/python/iota_sdk/types/send_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Optional, List, Dict
from typing import Optional, List
from dataclasses_json import config
from iota_sdk.types.common import HexStr, json
from iota_sdk.types.native_token import NativeToken
Expand Down Expand Up @@ -71,18 +71,15 @@ class CreateNativeTokenParams():
foundry_metadata: The foundry metadata of the native token.
account_id: The ID of the corresponding account.
"""
circulating_supply: int
maximum_supply: int
circulating_supply: int = field(metadata=config(
encoder=str
))
maximum_supply: int = field(metadata=config(
encoder=str
thibault-martinez marked this conversation as resolved.
Show resolved Hide resolved
))
foundry_metadata: Optional[str] = None
account_id: Optional[str] = None

@staticmethod
def _to_dict_custom(cfg: Dict[str, any]) -> Dict[str, any]:
cfg['circulatingSupply'] = hex(cfg['circulatingSupply'])
cfg['maximumSupply'] = hex(cfg['maximumSupply'])

return cfg


@json
@dataclass
Expand Down
15 changes: 0 additions & 15 deletions bindings/python/iota_sdk/types/token_scheme.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,5 @@ class SimpleTokenScheme:
maximum_supply: HexStr
type: int = field(default_factory=lambda: 0, init=False)

@staticmethod
def to_dict_custom(config):
"""
The function converts integer values in the config to hexadecimal strings.
"""

if isinstance(config['mintedTokens'], int):
config['mintedTokens'] = str(hex(config['mintedTokens']))
if isinstance(config['meltedTokens'], int):
config['meltedTokens'] = str(hex(config['meltedTokens']))
if isinstance(config['maximumSupply'], int):
config['maximumSupply'] = str(hex(config['maximumSupply']))

return config


TokenScheme: TypeAlias = SimpleTokenScheme
32 changes: 20 additions & 12 deletions bindings/python/iota_sdk/types/transaction_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

from enum import Enum
from typing import Optional, List, Dict, Union
from typing import Optional, List, Union
from dataclasses import dataclass
from iota_sdk.types.burn import Burn
from iota_sdk.types.common import json
Expand All @@ -27,9 +27,19 @@ class RemainderValueStrategyCustomAddress:
internal: bool
used: bool

@staticmethod
def _to_dict_custom(config: Dict[str, any]) -> Dict[str, any]:
return dict({"strategy": "CustomAddress", "value": config})
def to_dict(self) -> dict:
"""Custom dict conversion.
"""

return {
'strategy': 'CustomAddress',
'value': {
'address': self.address,
'keyIndex': self.key_index,
'internal': self.internal,
'used': self.used
}
}


class RemainderValueStrategy(Enum):
Expand All @@ -42,16 +52,14 @@ class RemainderValueStrategy(Enum):
ChangeAddress = None
ReuseAddress = None

def _to_dict_custom(self):
def to_dict(self):
"""Custom dict conversion.
"""
The function `_to_dict_custom` returns a dictionary with the strategy name and its corresponding value.

Returns:

a dictionary with two key-value pairs. The "strategy" key is assigned the value of self.name,
and the "value" key is assigned the first element of self.value.
"""
return dict({"strategy": self.name, "value": self.value[0]})
return {
'strategy': self.name,
'value': self.value[0]
}


@json
Expand Down
Loading