Source code for aergo.herapy.obj.aer

# -*- coding: utf-8 -*-

import decimal
from typing import Union

from ..errors.conversion_exception import ConversionException
from ..utils.converter import bigint_to_bytes

UNITS_SIZE = {
    'aergo': 18,
    'gaer': 9,
    'aer': 0
}
AERGO_UNIT_PRECISION = UNITS_SIZE['aergo']


[docs]class Aer: """Return Aergo Unit, AER(/ˈɛəɹ/).""" def __init__(self, value: Union[bytes, str, int, float] = '0 aer'): if isinstance(value, bytes): value = int.from_bytes(value, byteorder='big') self.__aer = self._parsing_value(value) def _parsing_value(self, v): try: decimal.Decimal(v) v = self._decimal_to_str(v) + ' aer' except decimal.InvalidOperation: v = v.strip().lower() unit = '' size = -1 for u, s in UNITS_SIZE.items(): if v.endswith(u): unit = u size = s break if size < 0: raise ConversionException('cannot recognize aergo unit: ' + v) v = v[:len(v) - len(unit)].strip() if '.' not in v: zero_padding = UNITS_SIZE[unit] else: number, below = v.split('.') if len(below) > UNITS_SIZE[unit]: raise ConversionException( 'too small value below decimal point: ' + v) v = number + below zero_padding = UNITS_SIZE[unit] - len(below) v = v + '0' * zero_padding try: decimal.getcontext().prec = AERGO_UNIT_PRECISION v = decimal.Decimal(v) except decimal.InvalidOperation: raise ConversionException('cannot recognize value: ' + v) return v @staticmethod def _decimal_to_str(d): s = str(d).lower() if 'e' in s: digits, exp = s.split('e') exp = int(exp) if exp > 0 and '.' in digits: exp = exp - len(digits.split('.')[1]) + 1 digits = digits.replace('.', '').replace('-', '') # minus 1 for decimal point in the sci notation zero_padding = '0' * (abs(exp) - 1) sign = '-' if d < 0 else '' if exp > 0: s = '{}{}{}'.format(sign, digits, zero_padding) else: s = '{}0.{}{}'.format(sign, zero_padding, digits) return s @property def aer(self) -> str: return self._decimal_to_str(self.__aer) + ' aer' @property def gaer(self) -> str: with decimal.localcontext() as ctx: ctx.prec = len(str(self.__aer)) v = self.__aer / decimal.Decimal(10 ** UNITS_SIZE['gaer']) s = self._decimal_to_str(v) + ' gaer' return s @property def aergo(self) -> str: with decimal.localcontext() as ctx: ctx.prec = len(str(self.__aer)) v = self.__aer / decimal.Decimal(10 ** UNITS_SIZE['aergo']) s = self._decimal_to_str(v) + ' aergo' return s @property def dec(self) -> decimal.Decimal: return self.__aer @dec.setter def dec(self, v: Union[bytes, str, int, float]) -> None: self.__aer = self._parsing_value(v) def __str__(self) -> str: return self.aer def __int__(self) -> int: return int(self.dec) def __bytes__(self) -> bytes: return bigint_to_bytes(int(self)) def __add__(self, other: 'Aer') -> 'Aer': with decimal.localcontext(): decimal.setcontext(decimal.DefaultContext) v = self.dec + other.dec return Aer(str(v)) def __sub__(self, other: 'Aer') -> 'Aer': with decimal.localcontext(): decimal.setcontext(decimal.DefaultContext) v = self.dec - other.dec return Aer(str(v)) def __mul__(self, other: 'Aer') -> 'Aer': with decimal.localcontext() as ctx: ctx.prec = decimal.MAX_PREC v = self.dec * other.dec return Aer(str(v)) def __floordiv__(self, other: 'Aer') -> 'Aer': with decimal.localcontext(): decimal.setcontext(decimal.DefaultContext) v = self.dec // other.dec return Aer(str(v)) def __truediv__(self, other: 'Aer') -> 'Aer': with decimal.localcontext(): decimal.setcontext(decimal.DefaultContext) v = self.dec / other.dec return Aer(str(v))