Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/faker/providers/bank/__init__.py: 29%

55 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1import re 

2import string 

3 

4from math import ceil 

5from string import ascii_uppercase 

6from typing import Dict, Optional 

7 

8from .. import BaseProvider 

9 

10localized = True 

11default_locale = "en_GB" 

12 

13 

14class Provider(BaseProvider): 

15 """Implement default bank provider for Faker. 

16 

17 .. important:: 

18 Bank codes, account numbers, and other ID's generated by this provider 

19 are only valid in form, i.e. they conform to some standard/format, are 

20 of the expected lengths, and have valid checksums (where applicable). 

21 Results generated that turn out to be valid in real life are purely 

22 coincidental. 

23 

24 Sources: 

25 

26 - https://en.wikipedia.org/wiki/International_Bank_Account_Number 

27 - https://www.theswiftcodes.com/swift-code-checker/ 

28 """ 

29 

30 ALPHA: Dict[str, str] = {c: str(ord(c) % 55) for c in string.ascii_uppercase} 

31 bban_format: str = "????#############" 

32 country_code: str = "GB" 

33 

34 def aba(self) -> str: 

35 """Generate an ABA routing transit number.""" 

36 fed_num = self.random_int(min=1, max=12) 

37 rand = self.numerify("######") 

38 aba = f"{fed_num:02}{rand}" 

39 

40 # calculate check digit 

41 d = [int(n) for n in aba] 

42 chk_digit = 3 * (d[0] + d[3] + d[6]) + 7 * (d[1] + d[4] + d[7]) + d[2] + d[5] 

43 chk_digit = ceil(chk_digit / 10) * 10 - chk_digit 

44 

45 return f"{aba}{chk_digit}" 

46 

47 def bank_country(self) -> str: 

48 """Generate the bank provider's ISO 3166-1 alpha-2 country code.""" 

49 return self.country_code 

50 

51 def bban(self) -> str: 

52 """Generate a Basic Bank Account Number (BBAN).""" 

53 temp = re.sub(r"\?", lambda x: self.random_element(ascii_uppercase), self.bban_format) 

54 return self.numerify(temp) 

55 

56 def iban(self) -> str: 

57 """Generate an International Bank Account Number (IBAN).""" 

58 bban = self.bban() 

59 

60 check = bban + self.country_code + "00" 

61 check_ = int("".join(self.ALPHA.get(c, c) for c in check)) 

62 check_ = 98 - (check_ % 97) 

63 check = str(check_).zfill(2) 

64 

65 return self.country_code + check + bban 

66 

67 def swift8(self, use_dataset: bool = False) -> str: 

68 """Generate an 8-digit SWIFT code. 

69 

70 This method uses |swift| under the hood with the ``length`` argument set 

71 to ``8`` and with the ``primary`` argument omitted. All 8-digit SWIFT 

72 codes already refer to the primary branch/office. 

73 

74 :sample: 

75 :sample: use_dataset=True 

76 """ 

77 return self.swift(length=8, use_dataset=use_dataset) 

78 

79 def swift11(self, primary: bool = False, use_dataset: bool = False) -> str: 

80 """Generate an 11-digit SWIFT code. 

81 

82 This method uses |swift| under the hood with the ``length`` argument set 

83 to ``11``. If ``primary`` is set to ``True``, the SWIFT code will always 

84 end with ``'XXX'``. All 11-digit SWIFT codes use this convention to 

85 refer to the primary branch/office. 

86 

87 :sample: 

88 :sample: use_dataset=True 

89 """ 

90 return self.swift(length=11, primary=primary, use_dataset=use_dataset) 

91 

92 def swift( 

93 self, 

94 length: Optional[int] = None, 

95 primary: bool = False, 

96 use_dataset: bool = False, 

97 ) -> str: 

98 """Generate a SWIFT code. 

99 

100 SWIFT codes, reading from left to right, are composed of a 4 alphabet 

101 character bank code, a 2 alphabet character country code, a 2 

102 alphanumeric location code, and an optional 3 alphanumeric branch code. 

103 This means SWIFT codes can only have 8 or 11 characters, so the value of 

104 ``length`` can only be ``None`` or the integers ``8`` or ``11``. If the 

105 value is ``None``, then a value of ``8`` or ``11`` will randomly be 

106 assigned. 

107 

108 Because all 8-digit SWIFT codes already refer to the primary branch or 

109 office, the ``primary`` argument only has an effect if the value of 

110 ``length`` is ``11``. If ``primary`` is ``True`` and ``length`` is 

111 ``11``, the 11-digit SWIFT codes generated will always end in ``'XXX'`` 

112 to denote that they belong to primary branches/offices. 

113 

114 For extra authenticity, localized providers may opt to include SWIFT 

115 bank codes, location codes, and branch codes used in their respective 

116 locales. If ``use_dataset`` is ``True``, this method will generate SWIFT 

117 codes based on those locale-specific codes if included. If those codes 

118 were not included, then it will behave as if ``use_dataset`` were 

119 ``False``, and in that mode, all those codes will just be randomly 

120 generated as per the specification. 

121 

122 :sample: 

123 :sample: length=8 

124 :sample: length=8, use_dataset=True 

125 :sample: length=11 

126 :sample: length=11, primary=True 

127 :sample: length=11, use_dataset=True 

128 :sample: length=11, primary=True, use_dataset=True 

129 """ 

130 if length is None: 

131 length = self.random_element((8, 11)) 

132 if length not in (8, 11): 

133 raise AssertionError("length can only be 8 or 11") 

134 

135 if use_dataset and hasattr(self, "swift_bank_codes"): 

136 bank_code: str = self.random_element(self.swift_bank_codes) # type: ignore[attr-defined] 

137 else: 

138 bank_code = self.lexify("????", letters=string.ascii_uppercase) 

139 

140 if use_dataset and hasattr(self, "swift_location_codes"): 

141 location_code: str = self.random_element(self.swift_location_codes) # type: ignore[attr-defined] 

142 else: 

143 location_code = self.lexify("??", letters=string.ascii_uppercase + string.digits) 

144 

145 if length == 8: 

146 return bank_code + self.country_code + location_code 

147 

148 if primary: 

149 branch_code = "XXX" 

150 elif use_dataset and hasattr(self, "swift_branch_codes"): 

151 branch_code = self.random_element(self.swift_branch_codes) # type: ignore[attr-defined] 

152 else: 

153 branch_code = self.lexify("???", letters=string.ascii_uppercase + string.digits) 

154 

155 return bank_code + self.country_code + location_code + branch_code