1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
import warnings
from decimal import Decimal
from typing import Any
from pydantic import GetCoreSchemaHandler, NonNegativeInt
from pydantic_core import CoreSchema, core_schema
class USDCent(int):
def __new__(cls, value, *args, **kwargs):
if isinstance(value, float):
warnings.warn(
"USDCent init with a float. Rounding behavior may " "be unexpected"
)
if isinstance(value, Decimal):
warnings.warn(
"USDCent init with a Decimal. Rounding behavior may " "be unexpected"
)
if value < 0:
raise ValueError("USDCent not be less than zero")
return super(cls, cls).__new__(cls, value)
def __add__(self, other):
assert isinstance(other, USDCent)
res = super(USDCent, self).__add__(other)
return self.__class__(res)
def __sub__(self, other):
assert isinstance(other, USDCent)
res = super(USDCent, self).__sub__(other)
return self.__class__(res)
def __mul__(self, other):
assert isinstance(other, USDCent)
res = super(USDCent, self).__mul__(other)
return self.__class__(res)
def __abs__(self):
res = super(USDCent, self).__abs__()
return self.__class__(res)
def __truediv__(self, other):
raise ValueError("Division not allowed for USDCent")
def __str__(self):
return "%d" % int(self)
def __repr__(self):
return "USDCent(%d)" % int(self)
@classmethod
def __get_pydantic_core_schema__(
cls, source_type: Any, handler: GetCoreSchemaHandler
) -> CoreSchema:
"""
https://docs.pydantic.dev/latest/concepts/types/#customizing-validation-with-__get_pydantic_core_schema__
"""
return core_schema.no_info_after_validator_function(
cls, handler(NonNegativeInt)
)
def to_usd(self) -> Decimal:
return Decimal(int(self) / 100).quantize(Decimal(".01"))
def to_usd_str(self) -> str:
return "${:,.2f}".format(float(self.to_usd()))
|