projects
/
python_utils.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Try another tactic to figure out entry point.
[python_utils.git]
/
type
/
centcount.py
diff --git
a/type/centcount.py
b/type/centcount.py
index 4181721bbc0d4ab7efe38608b821faa26ecf5bae..4529695cd92174fe7e6aaff60df63dcad999d296 100644
(file)
--- a/
type/centcount.py
+++ b/
type/centcount.py
@@
-1,26
+1,21
@@
#!/usr/bin/env python3
#!/usr/bin/env python3
+"""An amount of money (USD) represented as an integral count of
+cents."""
+
import re
import re
-from typing import Optional, T
ypeVar, T
uple
+from typing import Optional, Tuple
import math_utils
import math_utils
-T = TypeVar('T', bound='CentCount')
-
-
class CentCount(object):
"""A class for representing monetary amounts potentially with
class CentCount(object):
"""A class for representing monetary amounts potentially with
- different currencies.
+ different currencies meant to avoid floating point rounding
+ issues by treating amount as a simple integral count of cents.
"""
"""
- def __init__ (
- self,
- centcount,
- currency: str = 'USD',
- *,
- strict_mode = False
- ):
+ def __init__(self, centcount, currency: str = 'USD', *, strict_mode=False):
self.strict_mode = strict_mode
if isinstance(centcount, str):
ret = CentCount._parse(centcount)
self.strict_mode = strict_mode
if isinstance(centcount, str):
ret = CentCount._parse(centcount)
@@
-36,7
+31,7
@@
class CentCount(object):
if not currency:
self.currency: Optional[str] = None
else:
if not currency:
self.currency: Optional[str] = None
else:
- self.currency
: Optional[str]
= currency
+ self.currency = currency
def __repr__(self):
a = float(self.centcount)
def __repr__(self):
a = float(self.centcount)
@@
-44,9
+39,9
@@
class CentCount(object):
a = round(a, 2)
s = f'{a:,.2f}'
if self.currency is not None:
a = round(a, 2)
s = f'{a:,.2f}'
if self.currency is not None:
- return
'%s %s' % (s, self.currency)
+ return
f'{s} {self.currency}'
else:
else:
- return
'$%s' % s
+ return
f'${s}'
def __pos__(self):
return CentCount(centcount=self.centcount, currency=self.currency)
def __pos__(self):
return CentCount(centcount=self.centcount, currency=self.currency)
@@
-58,8
+53,8
@@
class CentCount(object):
if isinstance(other, CentCount):
if self.currency == other.currency:
return CentCount(
if isinstance(other, CentCount):
if self.currency == other.currency:
return CentCount(
- centcount
=
self.centcount + other.centcount,
- currency
= self.currency
+ centcount
=
self.centcount + other.centcount,
+ currency
=self.currency,
)
else:
raise TypeError('Incompatible currencies in add expression')
)
else:
raise TypeError('Incompatible currencies in add expression')
@@
-73,8
+68,8
@@
class CentCount(object):
if isinstance(other, CentCount):
if self.currency == other.currency:
return CentCount(
if isinstance(other, CentCount):
if self.currency == other.currency:
return CentCount(
- centcount
=
self.centcount - other.centcount,
- currency
= self.currency
+ centcount
=
self.centcount - other.centcount,
+ currency
=self.currency,
)
else:
raise TypeError('Incompatible currencies in add expression')
)
else:
raise TypeError('Incompatible currencies in add expression')
@@
-89,8
+84,8
@@
class CentCount(object):
raise TypeError('can not multiply monetary quantities')
else:
return CentCount(
raise TypeError('can not multiply monetary quantities')
else:
return CentCount(
- centcount
=
int(self.centcount * float(other)),
- currency
= self.currency
+ centcount
=
int(self.centcount * float(other)),
+ currency
=self.currency,
)
def __truediv__(self, other):
)
def __truediv__(self, other):
@@
-98,8
+93,8
@@
class CentCount(object):
raise TypeError('can not divide monetary quantities')
else:
return CentCount(
raise TypeError('can not divide monetary quantities')
else:
return CentCount(
- centcount
=
int(float(self.centcount) / float(other)),
- currency
= self.currency
+ centcount
=
int(float(self.centcount) / float(other)),
+ currency
=self.currency,
)
def __int__(self):
)
def __int__(self):
@@
-124,8
+119,8
@@
class CentCount(object):
if isinstance(other, CentCount):
if self.currency == other.currency:
return CentCount(
if isinstance(other, CentCount):
if self.currency == other.currency:
return CentCount(
- centcount
=
other.centcount - self.centcount,
- currency
= self.currency
+ centcount
=
other.centcount - self.centcount,
+ currency
=self.currency,
)
else:
raise TypeError('Incompatible currencies in sub expression')
)
else:
raise TypeError('Incompatible currencies in sub expression')
@@
-134,8
+129,8
@@
class CentCount(object):
raise TypeError('In strict_mode only two moneys can be added')
else:
return CentCount(
raise TypeError('In strict_mode only two moneys can be added')
else:
return CentCount(
- centcount
=
int(other) - self.centcount,
- currency
= self.currency
+ centcount
=
int(other) - self.centcount,
+ currency
=self.currency,
)
__rmul__ = __mul__
)
__rmul__ = __mul__
@@
-147,10
+142,7
@@
class CentCount(object):
if other is None:
return False
if isinstance(other, CentCount):
if other is None:
return False
if isinstance(other, CentCount):
- return (
- self.centcount == other.centcount and
- self.currency == other.currency
- )
+ return self.centcount == other.centcount and self.currency == other.currency
if self.strict_mode:
raise TypeError("In strict mode only two CentCounts can be compared")
else:
if self.strict_mode:
raise TypeError("In strict mode only two CentCounts can be compared")
else:
@@
-192,11
+184,11
@@
class CentCount(object):
def __ge__(self, other):
return self > other or self == other
def __ge__(self, other):
return self > other or self == other
- def __hash__(self):
- return
self.__repr__
+ def __hash__(self)
-> int
:
+ return
hash(self.__repr__)
- CENTCOUNT_RE = re.compile("^([+|-]?)(\d+)(\.\d+)$")
- CURRENCY_RE = re.compile("^[A-Z][A-Z][A-Z]$")
+ CENTCOUNT_RE = re.compile(
r
"^([+|-]?)(\d+)(\.\d+)$")
+ CURRENCY_RE = re.compile(
r
"^[A-Z][A-Z][A-Z]$")
@classmethod
def _parse(cls, s: str) -> Optional[Tuple[int, str]]:
@classmethod
def _parse(cls, s: str) -> Optional[Tuple[int, str]]:
@@
-210,7
+202,7
@@
class CentCount(object):
centcount = int(float(chunk) * 100.0)
elif CentCount.CURRENCY_RE.match(chunk) is not None:
currency = chunk
centcount = int(float(chunk) * 100.0)
elif CentCount.CURRENCY_RE.match(chunk) is not None:
currency = chunk
- except:
+ except
Exception
:
pass
if centcount is not None and currency is not None:
return (centcount, currency)
pass
if centcount is not None and currency is not None:
return (centcount, currency)
@@
-219,7
+211,7
@@
class CentCount(object):
return None
@classmethod
return None
@classmethod
- def parse(cls, s: str) ->
T
:
+ def parse(cls, s: str) ->
'CentCount'
:
chunks = CentCount._parse(s)
if chunks is not None:
return CentCount(chunks[0], chunks[1])
chunks = CentCount._parse(s)
if chunks is not None:
return CentCount(chunks[0], chunks[1])