Skip to content
Snippets Groups Projects

Changes to rm-refactor-overloaded-assets-operators

3 files
+ 83
13
Compare changes
  • Side-by-side
  • Inline
Files
3
from decimal import Decimal
from decimal import Decimal
from typing import Optional, Union
from typing import NoReturn, Optional, Union
import warnings
import warnings
class DecimalConverter:
class DecimalConverter:
@classmethod
@classmethod
def convert(cls, amount: Union[int, float, str], *, precision: Optional[int] = None) -> Decimal:
def convert(cls, amount: Union[int, float, str], *, precision: Optional[int] = None) -> Decimal:
if precision is not None:
cls.__warn_if_precision_might_be_lost(amount, precision)
# We could not pass float variable directly to Decimal initializer as from the nature of floats it won't result
# We could not pass float variable directly to Decimal initializer as from the nature of floats it won't result
# in the exact decimal value. We need to convert float to string first like https://stackoverflow.com/a/18886013
# in the exact decimal value. We need to convert float to string first like https://stackoverflow.com/a/18886013
@@ -15,21 +13,32 @@ class DecimalConverter:
@@ -15,21 +13,32 @@ class DecimalConverter:
if isinstance(amount, float):
if isinstance(amount, float):
amount = repr(amount)
amount = repr(amount)
if precision is None:
converted = Decimal(amount)
return Decimal(amount).normalize()
exponent = Decimal(10) ** (-1 * precision)
if precision is not None:
return Decimal(amount).quantize(exponent).normalize()
cls.__assert_precision_is_positive(precision)
 
cls.__warn_if_precision_might_be_lost(converted, precision)
 
converted = cls.__round_to_precision(converted, precision)
 
 
return converted.normalize()
@staticmethod
@staticmethod
def __warn_if_precision_might_be_lost(amount: Union[int, float], precision: int) -> None:
def __assert_precision_is_positive(precision: int) -> Optional[NoReturn]:
rounded_value = round(amount, precision)
if precision < 0:
acceptable_error = 0.1**10
raise ValueError("Precision must be a positive integer.")
if abs(amount - rounded_value) > acceptable_error:
@staticmethod
 
def __round_to_precision(amount: Decimal, precision: int) -> Decimal:
 
exponent = Decimal(10) ** (-1 * precision)
 
return amount.quantize(exponent)
 
 
@classmethod
 
def __warn_if_precision_might_be_lost(cls, amount: Decimal, precision: int) -> None:
 
rounded_amount = cls.__round_to_precision(amount, precision)
 
if rounded_amount != amount:
warnings.warn(
warnings.warn(
f"Precision lost during asset creation.\n"
f"Precision lost during value creation.\n"
f"\n"
f"\n"
f"Asset with amount {amount} was requested, but this value was rounded to {rounded_value},\n"
f"Value of {amount} was requested, but this was rounded to {rounded_amount},\n"
f"because precision of this asset is {precision} ({pow(0.1, precision):.3f})."
f"because precision of this asset is {precision} ({pow(0.1, precision):.3f})."
)
)
Loading