amt: pass kwargs to initializer and dunder methods

This commit is contained in:
The MMGen Project 2026-11-09 09:33:33 +00:00
commit e9a5bd4b65
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2

View file

@ -38,7 +38,7 @@ class CoinAmt(Decimal, Hilite, InitErrors): # abstract class
max_amt = None # coin supply if known, otherwise None
units = () # defined unit names, e.g. ('satoshi',...)
def __new__(cls, num, *, from_unit=None, from_decimal=False, decimals=None):
def __new__(cls, num, *, from_unit=None, from_decimal=False, decimals=None, **kwargs):
assert decimals == None
@ -49,13 +49,13 @@ class CoinAmt(Decimal, Hilite, InitErrors): # abstract class
if from_unit:
assert from_unit in cls.units, f'{from_unit!r}: unrecognized coin unit for {cls.__name__}'
assert isinstance(num, int), 'value is not an integer'
me = Decimal.__new__(cls, num * getattr(cls, from_unit))
me = Decimal.__new__(cls, num * getattr(cls, from_unit), **kwargs)
elif from_decimal:
assert isinstance(num, Decimal), f'number must be of type Decimal, not {type(num).__name__})'
me = Decimal.__new__(cls, num.quantize(Decimal(10) ** -cls.max_prec))
me = Decimal.__new__(cls, num.quantize(Decimal(10) ** -cls.max_prec), **kwargs)
else:
assert isinstance(num, str), f'non-string passed to {cls.__name__} initializer'
me = Decimal.__new__(cls, num)
me = Decimal.__new__(cls, num, **kwargs)
assert me.normalize().as_tuple()[-1] >= -cls.max_prec, 'too many decimal places in coin amount'
if cls.max_amt:
assert me <= cls.max_amt, f'{me}: coin amount too large (>{cls.max_amt})'
@ -129,42 +129,45 @@ class CoinAmt(Decimal, Hilite, InitErrors): # abstract class
raise TypeError(
f'operand {other} is of incorrect type ({type(other).__name__} != {type(self).__name__})')
def __add__(self, other, decimals=None):
def __add__(self, other, decimals=None, **kwargs):
"""
we must allow other to be int(0) to use the sum() builtin
"""
if type(other) in (type(self), Decimal) or (other == 0 and isinstance(other, int)):
return type(self)(Decimal.__add__(self, other), from_decimal=True, decimals=decimals)
return type(self)(Decimal.__add__(self, other), from_decimal=True, decimals=decimals, **kwargs)
self.incorrect_type_error(other)
__radd__ = __add__
def __sub__(self, other, decimals=None):
def __sub__(self, other, decimals=None, **kwargs):
if type(other) in (type(self), Decimal):
return type(self)(Decimal.__sub__(self, other), from_decimal=True, decimals=decimals)
return type(self)(Decimal.__sub__(self, other), from_decimal=True, decimals=decimals, **kwargs)
self.incorrect_type_error(other)
def __rsub__(self, other, decimals=None):
def __rsub__(self, other, decimals=None, **kwargs):
if type(other) is type(self):
return type(self)(Decimal.__rsub__(self, other), from_decimal=True, decimals=decimals)
return type(self)(Decimal.__rsub__(self, other), from_decimal=True, decimals=decimals, **kwargs)
self.incorrect_type_error(other)
def __mul__(self, other, decimals=None):
def __mul__(self, other, decimals=None, **kwargs):
return type(self)(
'{:0.{p}f}'.format(Decimal.__mul__(self, Decimal(other)), p=self.max_prec),
decimals = decimals)
decimals = decimals,
**kwargs)
__rmul__ = __mul__
def __truediv__(self, other, decimals=None):
def __truediv__(self, other, decimals=None, **kwargs):
return type(self)(
'{:0.{p}f}'.format(Decimal.__truediv__(self, Decimal(other)), p=self.max_prec),
decimals = decimals)
decimals = decimals,
**kwargs)
def __rtruediv__(self, other, decimals=None):
def __rtruediv__(self, other, decimals=None, **kwargs):
return type(self)(
'{:0.{p}f}'.format(Decimal.__rtruediv__(self, Decimal(other)), p=self.max_prec),
decimals = decimals)
decimals = decimals,
**kwargs)
def __neg__(self):
self.method_not_implemented()
@ -231,38 +234,38 @@ class ETCAmt(ETHAmt):
class TokenAmt(ETHAmt):
units = ('atomic',)
def __new__(cls, num, *, decimals, from_unit=None, from_decimal=False):
def __new__(cls, num, *, decimals, from_unit=None, from_decimal=False, **kwargs):
assert isinstance(decimals, int)
cls.max_prec = decimals
cls.atomic = Decimal(f'{10 ** -decimals:0.{decimals}f}')
return ETHAmt.__new__(cls, num=num, from_unit=from_unit, from_decimal=from_decimal)
return ETHAmt.__new__(cls, num=num, from_unit=from_unit, from_decimal=from_decimal, **kwargs)
def to_unit(self, unit):
if (u := getattr(self, unit)) == self.atomic:
return int(Decimal(self) // u)
raise ValueError('TokenAmt unit must be ‘atomic’')
def __add__(self, other):
return super().__add__(other, decimals=self.max_prec)
def __add__(self, other, **kwargs):
return super().__add__(other, decimals=self.max_prec, **kwargs)
__radd__ = __add__
def __sub__(self, other):
return super().__sub__(other, decimals=self.max_prec)
def __sub__(self, other, **kwargs):
return super().__sub__(other, decimals=self.max_prec, **kwargs)
def __rsub__(self, other):
return super().__rsub__(other, decimals=self.max_prec)
def __rsub__(self, other, **kwargs):
return super().__rsub__(other, decimals=self.max_prec, **kwargs)
def __mul__(self, other):
return super().__mul__(other, decimals=self.max_prec)
def __mul__(self, other, **kwargs):
return super().__mul__(other, decimals=self.max_prec, **kwargs)
__rmul__ = __mul__
def __truediv__(self, other):
return super().__truediv__(other, decimals=self.max_prec)
def __truediv__(self, other, **kwargs):
return super().__truediv__(other, decimals=self.max_prec, **kwargs)
def __rtruediv__(self, other):
return super().__rtruediv__(other, decimals=self.max_prec)
def __rtruediv__(self, other, **kwargs):
return super().__rtruediv__(other, decimals=self.max_prec, **kwargs)
def CoinAmtChk(proto, num):
assert type(num) is proto.coin_amt, f'CoinAmtChk: {type(num)} != {proto.coin_amt}'