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
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1import re
2import string
4from math import ceil
5from string import ascii_uppercase
6from typing import Dict, Optional
8from .. import BaseProvider
10localized = True
11default_locale = "en_GB"
14class Provider(BaseProvider):
15 """Implement default bank provider for Faker.
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.
24 Sources:
26 - https://en.wikipedia.org/wiki/International_Bank_Account_Number
27 - https://www.theswiftcodes.com/swift-code-checker/
28 """
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"
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}"
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
45 return f"{aba}{chk_digit}"
47 def bank_country(self) -> str:
48 """Generate the bank provider's ISO 3166-1 alpha-2 country code."""
49 return self.country_code
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)
56 def iban(self) -> str:
57 """Generate an International Bank Account Number (IBAN)."""
58 bban = self.bban()
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)
65 return self.country_code + check + bban
67 def swift8(self, use_dataset: bool = False) -> str:
68 """Generate an 8-digit SWIFT code.
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.
74 :sample:
75 :sample: use_dataset=True
76 """
77 return self.swift(length=8, use_dataset=use_dataset)
79 def swift11(self, primary: bool = False, use_dataset: bool = False) -> str:
80 """Generate an 11-digit SWIFT code.
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.
87 :sample:
88 :sample: use_dataset=True
89 """
90 return self.swift(length=11, primary=primary, use_dataset=use_dataset)
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.
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.
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.
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.
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")
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)
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)
145 if length == 8:
146 return bank_code + self.country_code + location_code
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)
155 return bank_code + self.country_code + location_code + branch_code