Skip to content
Snippets Groups Projects

Changes to rm-refactor-overloaded-assets-operators

1 file
+ 67
67
Compare changes
  • Side-by-side
  • Inline
@@ -21,38 +21,28 @@ class AssetBase(acp.Abstract):
@@ -21,38 +21,28 @@ class AssetBase(acp.Abstract):
def __init__(self, amount: Union[int, float]) -> None:
def __init__(self, amount: Union[int, float]) -> None:
self.amount = self.__convert_amount_to_internal_representation(amount)
self.amount = self.__convert_amount_to_internal_representation(amount)
def __convert_amount_to_internal_representation(self, amount: Union[int, float]) -> int:
def __str__(self) -> str:
amount_decimal = DecimalConverter.convert(amount, precision=self.precision)
return f"{self.amount / (10 ** self.precision):.{self.precision}f} {self.token}"
return int(amount_decimal * Decimal(10) ** self.precision)
@classmethod
def __repr__(self) -> str:
def __template(cls) -> dict:
return f"Asset({self.as_nai()})"
return {
"amount": None,
"precision": cls.precision,
"nai": cls.nai,
}
def as_nai(self) -> dict:
def __eq__(self, other: Any) -> bool:
template = self.__template().copy()
other: AssetBase = self.__convert_to_asset(other, error_detail="compare")
template["amount"] = str(self.amount)
return self.amount == other.amount
return template
def __combine_with(self, other: Any, operator_: Union[operator.add, operator.sub]) -> AssetBase:
def __lt__(self, other: Any) -> bool:
other: AssetBase = self.__convert_to_asset(other, error_detail=operator_.__name__)
other: AssetBase = self.__convert_to_asset(other, error_detail="compare")
 
return self.amount < other.amount
 
def __neg__(self) -> AssetBase:
result = deepcopy(self)
result = deepcopy(self)
result.amount = operator_(result.amount, other.amount)
result.amount = -self.amount
return result
return result
def __add__(self, other: Any) -> AssetBase:
def __add__(self, other: Any) -> AssetBase:
return self.__combine_with(other, operator.add)
return self.__combine_with(other, operator.add)
def __neg__(self) -> AssetBase:
result = deepcopy(self)
result.amount = -self.amount
return result
def __sub__(self, other: Any) -> AssetBase:
def __sub__(self, other: Any) -> AssetBase:
return self.__combine_with(other, operator.sub)
return self.__combine_with(other, operator.sub)
@@ -67,33 +57,40 @@ class AssetBase(acp.Abstract):
@@ -67,33 +57,40 @@ class AssetBase(acp.Abstract):
return self
return self
@classmethod
@classmethod
def __assert_same_template(cls, other: dict) -> Optional[NoReturn]:
def __template(cls) -> dict:
if cls.__template().keys() != other.keys():
return {
raise ParseError(f"Asset dict keys differ: {other.keys()}, when expected {cls.__template().keys()}.")
"amount": None,
 
"precision": cls.precision,
 
"nai": cls.nai,
 
}
if cls.nai != other["nai"]:
def as_nai(self) -> dict:
raise ParseError(f"Asset dict nai differ: `{other['nai']}`, when expected `{cls.nai}`.")
template = self.__template().copy()
 
template["amount"] = str(self.amount)
 
return template
if cls.precision != other["precision"]:
@classmethod
raise ParseError(f"Asset dict precision differ: `{other['precision']}`, when expected `{cls.precision}`.")
def _from_dict(cls, asset_as_dict: dict) -> AssetBase:
 
cls.__assert_same_template(asset_as_dict)
def __assert_same_token(self, other: AssetBase, *, error_detail: str) -> Optional[NoReturn]:
try:
if self.token != other.token:
amount = int(asset_as_dict["amount"])
raise TypeError(f"Can't {error_detail} assets with different tokens: `{self.token}` and `{other.token}`.")
precision = int(asset_as_dict["precision"])
 
except ValueError as exception:
 
raise ParseError("Amount and precision have to be integers.") from exception
def __lt__(self, other: Any) -> bool:
return cls(amount / 10**precision)
other: AssetBase = self.__convert_to_asset(other, error_detail="compare")
return self.amount < other.amount
def __eq__(self, other: Any) -> bool:
def __convert_amount_to_internal_representation(self, amount: Union[int, float]) -> int:
other: AssetBase = self.__convert_to_asset(other, error_detail="compare")
amount_decimal = DecimalConverter.convert(amount, precision=self.precision)
return self.amount == other.amount
return int(amount_decimal * Decimal(10) ** self.precision)
def __str__(self) -> str:
def __combine_with(self, other: Any, operator_: Union[operator.add, operator.sub]) -> AssetBase:
return f"{self.amount / (10 ** self.precision):.{self.precision}f} {self.token}"
other: AssetBase = self.__convert_to_asset(other, error_detail=operator_.__name__)
def __repr__(self) -> str:
result = deepcopy(self)
return f"Asset({self.as_nai()})"
result.amount = operator_(result.amount, other.amount)
 
return result
def __convert_to_asset(self, other: Any, *, error_detail: Optional[str] = None) -> AssetBase:
def __convert_to_asset(self, other: Any, *, error_detail: Optional[str] = None) -> AssetBase:
error_detail = "operate on" if error_detail is None else error_detail
error_detail = "operate on" if error_detail is None else error_detail
@@ -117,16 +114,19 @@ class AssetBase(acp.Abstract):
@@ -117,16 +114,19 @@ class AssetBase(acp.Abstract):
return other
return other
@classmethod
@classmethod
def _from_dict(cls, asset_as_dict: dict) -> AssetBase:
def __assert_same_template(cls, other: dict) -> Optional[NoReturn]:
cls.__assert_same_template(asset_as_dict)
if cls.__template().keys() != other.keys():
 
raise ParseError(f"Asset dict keys differ: {other.keys()}, when expected {cls.__template().keys()}.")
try:
if cls.nai != other["nai"]:
amount = int(asset_as_dict["amount"])
raise ParseError(f"Asset dict nai differ: `{other['nai']}`, when expected `{cls.nai}`.")
precision = int(asset_as_dict["precision"])
except ValueError as exception:
raise ParseError("Amount and precision have to be integers.") from exception
return cls(amount / 10**precision)
if cls.precision != other["precision"]:
 
raise ParseError(f"Asset dict precision differ: `{other['precision']}`, when expected `{cls.precision}`.")
 
 
def __assert_same_token(self, other: AssetBase, *, error_detail: str) -> Optional[NoReturn]:
 
if self.token != other.token:
 
raise TypeError(f"Can't {error_detail} assets with different tokens: `{self.token}` and `{other.token}`.")
class Asset:
class Asset:
@@ -155,6 +155,23 @@ class Asset:
@@ -155,6 +155,23 @@ class Asset:
precision: Final[int] = 6
precision: Final[int] = 6
nai: Final[str] = "@@000000037"
nai: Final[str] = "@@000000037"
 
@classmethod
 
def from_(cls, data: Union[str, dict], *, treat_dict_as_testnet_currencies: bool = True) -> AssetBase:
 
"""
 
This function allows you to convert an asset from string or JSON format to the appropriate object of Asset type.
 
 
* In case of dict:
 
Nai dictionary does not hold the information about token type.
 
 
By default, treat_dict_as_testnet_currencies parameter is set to True. As a result, an Asset object will be
 
created in the testnet format. If you want to create an object in mainnet form, set it to False.
 
"""
 
if isinstance(data, str):
 
return cls.__from_sting(data)
 
if isinstance(data, dict):
 
return cls.__from_dict(data, testnet_currencies=treat_dict_as_testnet_currencies)
 
raise ParseError(f"Can't convert `{type(data)}` to Asset object.")
 
@classmethod
@classmethod
def __from_sting(cls, asset_as_string: str) -> AssetBase:
def __from_sting(cls, asset_as_string: str) -> AssetBase:
amount, token = asset_as_string.split()
amount, token = asset_as_string.split()
@@ -183,20 +200,3 @@ class Asset:
@@ -183,20 +200,3 @@ class Asset:
f"Asset with nai `{asset_as_dict['nai']}` does not exist.\n"
f"Asset with nai `{asset_as_dict['nai']}` does not exist.\n"
f"Supported nai's are: {[asset.nai for asset in assets]}."
f"Supported nai's are: {[asset.nai for asset in assets]}."
)
)
@classmethod
def from_(cls, data: Union[str, dict], *, treat_dict_as_testnet_currencies: bool = True) -> AssetBase:
"""
This function allows you to convert an asset from string or JSON format to the appropriate object of Asset type.
* In case of dict:
Nai dictionary does not hold the information about token type.
By default, treat_dict_as_testnet_currencies parameter is set to True. As a result, an Asset object will be
created in the testnet format. If you want to create an object in mainnet form, set it to False.
"""
if isinstance(data, str):
return cls.__from_sting(data)
if isinstance(data, dict):
return cls.__from_dict(data, testnet_currencies=treat_dict_as_testnet_currencies)
raise ParseError(f"Can't convert `{type(data)}` to Asset object.")
Loading