Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/validators/finance.py: 15%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Finance."""
3from .utils import validator
6def _cusip_checksum(cusip: str):
7 check, val = 0, None
9 for idx in range(9):
10 c = cusip[idx]
11 if c >= "0" and c <= "9":
12 val = ord(c) - ord("0")
13 elif c >= "A" and c <= "Z":
14 val = 10 + ord(c) - ord("A")
15 elif c >= "a" and c <= "z":
16 val = 10 + ord(c) - ord("a")
17 elif c == "*":
18 val = 36
19 elif c == "@":
20 val = 37
21 elif c == "#":
22 val = 38
23 else:
24 return False
26 if idx & 1:
27 val += val
29 check = check + (val // 10) + (val % 10)
31 return (check % 10) == 0
34def _isin_checksum(value: str):
35 # The check digit (last character) is always numeric.
36 if not value[-1].isdecimal():
37 return False
39 # Expand the code into a string of digits, mapping each letter to its
40 # two-digit value (A=10, ..., Z=35) and leaving digits unchanged.
41 digits = ""
42 for idx in range(12):
43 c = value[idx]
44 if c >= "0" and c <= "9" and idx > 1:
45 digits += c
46 elif c >= "A" and c <= "Z":
47 digits += str(10 + ord(c) - ord("A"))
48 elif c >= "a" and c <= "z":
49 digits += str(10 + ord(c) - ord("a"))
50 else:
51 return False
53 # Luhn checksum over the expanded digit string: starting from the
54 # rightmost digit, double every second digit and sum the resulting digits.
55 check = 0
56 for idx, c in enumerate(reversed(digits)):
57 val = ord(c) - ord("0")
58 if idx & 1:
59 val += val
60 check += (val // 10) + (val % 10)
62 return (check % 10) == 0
65@validator
66def cusip(value: str):
67 """Return whether or not given value is a valid CUSIP.
69 Checks if the value is a valid [CUSIP][1].
70 [1]: https://en.wikipedia.org/wiki/CUSIP
72 Examples:
73 >>> cusip('037833DP2')
74 True
75 >>> cusip('037833DP3')
76 ValidationError(func=cusip, args={'value': '037833DP3'})
78 Args:
79 value: CUSIP string to validate.
81 Returns:
82 (Literal[True]): If `value` is a valid CUSIP string.
83 (ValidationError): If `value` is an invalid CUSIP string.
84 """
85 return len(value) == 9 and value[-1] in "0123456789" and _cusip_checksum(value)
88@validator
89def isin(value: str):
90 """Return whether or not given value is a valid ISIN.
92 Checks if the value is a valid [ISIN][1].
93 [1]: https://en.wikipedia.org/wiki/International_Securities_Identification_Number
95 Examples:
96 >>> isin('037833DP2')
97 ValidationError(func=isin, args={'value': '037833DP2'})
98 >>> isin('037833DP3')
99 ValidationError(func=isin, args={'value': '037833DP3'})
101 Args:
102 value: ISIN string to validate.
104 Returns:
105 (Literal[True]): If `value` is a valid ISIN string.
106 (ValidationError): If `value` is an invalid ISIN string.
107 """
108 return len(value) == 12 and _isin_checksum(value)
111@validator
112def sedol(value: str):
113 """Return whether or not given value is a valid SEDOL.
115 Checks if the value is a valid [SEDOL][1].
116 [1]: https://en.wikipedia.org/wiki/SEDOL
118 Examples:
119 >>> sedol('2936921')
120 True
121 >>> sedol('29A6922')
122 ValidationError(func=sedol, args={'value': '29A6922'})
124 Args:
125 value: SEDOL string to validate.
127 Returns:
128 (Literal[True]): If `value` is a valid SEDOL string.
129 (ValidationError): If `value` is an invalid SEDOL string.
130 """
131 if len(value) != 7 or value[-1] not in "0123456789":
132 return False
134 weights = [1, 3, 1, 7, 3, 9, 1]
135 check = 0
136 for idx in range(7):
137 c = value[idx]
138 if c in "AEIOU":
139 return False
141 val = None
142 if c >= "0" and c <= "9":
143 val = ord(c) - ord("0")
144 elif c >= "A" and c <= "Z":
145 val = 10 + ord(c) - ord("A")
146 else:
147 return False
148 check += val * weights[idx]
150 return (check % 10) == 0