Skip to content

Commit

Permalink
Add use_registry parameter to IBAN/BBAN.random()
Browse files Browse the repository at this point in the history
  • Loading branch information
mdomke committed May 10, 2024
1 parent 3c974a8 commit 4aa8d80
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 7 deletions.
12 changes: 10 additions & 2 deletions docs/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ will give you a British IBAN. Similarly,
will only give you IBANs from the Lloyds Bank.

Notice that for countries that have a bank registry, the bank code will always be taken from there,
so that the IBAN corresponds to a valid bank. E.g.:
Notice that for countries that have a bank registry, the bank code will be taken from there, so
that the IBAN corresponds to a valid bank. E.g.:

.. code-block:: pycon
Expand All @@ -301,6 +301,14 @@ so that the IBAN corresponds to a valid bank. E.g.:
'country_code': 'DE',
'checksum_algo': '63'}
If you want to generate an IBAN with a truly random bank code use

.. code-block:: pycon
>>> IBAN.random(country_code="DE", use_registry=False).bank
None
Due to the nature of random numbers you might still hit a valid bank code once in a while.

Pydantic integration
---------------------
Expand Down
18 changes: 15 additions & 3 deletions schwifty/bban.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,30 @@ def from_components(cls, country_code: str, **values: str) -> BBAN:
return cls(country_code, bban)

@classmethod
def random(cls, country_code: str = "", random: Random | None = None, **values: str) -> BBAN:
def random(
cls,
country_code: str = "",
random: Random | None = None,
use_registry: bool = True,
**values: str,
) -> BBAN:
"""Generate a random BBAN.
With no further arguments a random bank from the registry will be selected as basis for the
bank code and the BBAN structure. All other components, e.g. the account code will be
generated with the alphabet allowed by the BBAN spec.
If a ``country_code``
If a ``country_code`` is provided the possible values will be limited to banks of the
respective country. Additional components of the IBAN (e.g. the bank code) can be provided
as keyword arguments to further narrow down the genreated values.
If ``use_regsitry`` is set to ``False`` the bank information from schwifty's registry will
be ignored and a completely random bank code will be generated.
Args:
country_code (str): The ISO 3166 alpha-2 country code.
random (Random): An alternative random number generator.
use_registry (bool): Select a random bank from the existing bank registry if available.
values: The country specific BBAN components that should be taken as is and not be
generated.
Raises:
Expand All @@ -178,7 +190,7 @@ def random(cls, country_code: str = "", random: Random | None = None, **values:
rstr = Rstr(random)
spec = _get_bban_spec(country_code)
bank: dict[str, Any] = {}
if (banks := banks_by_country.get(country_code)) is not None:
if (banks := banks_by_country.get(country_code)) is not None and use_registry:
bank = random.choice(banks)

ranges = _get_position_ranges(spec)
Expand Down
33 changes: 31 additions & 2 deletions schwifty/iban.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,37 @@ def generate(
)

@classmethod
def random(cls, country_code: str = "", random: Random | None = None, **values: str) -> IBAN:
bban = BBAN.random(country_code, random=random, **values)
def random(
cls,
country_code: str = "",
random: Random | None = None,
use_registry: bool = True,
**values: str,
) -> IBAN:
"""Generate a random IBAN.
With no further arguments a random bank from the registry will be selected as basis for the
bank code and the BBAN structure. All other components, e.g. the account code will be
generated with the alphabet allowed by the BBAN spec.
If a ``country_code`` is provided the possible values will be limited to banks of the
respective country. Additional components of the IBAN (e.g. the bank code) can be provided
as keyword arguments to further narrow down the genreated values.
If ``use_regsitry`` is set to ``False`` the bank information from schwifty's registry will
be ignored and a completely random bank code will be generated.
Args:
country_code (str): The ISO 3166 alpha-2 country code.
random (Random): An alternative random number generator.
use_registry (bool): Select a random bank from the existing bank registry if available.
values: The country specific BBAN components that should be taken as is and not be
generated.
Raises:
GenerateRandomOverflowError: If no valid random value can be gerated after multiple
tries.
"""
bban = BBAN.random(country_code, random=random, use_registry=use_registry, **values)
return cls.from_bban(bban.country_code, bban)

def validate(self, validate_bban: bool = False) -> bool:
Expand Down
5 changes: 5 additions & 0 deletions tests/test_bban.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ def test_random(country_code: str) -> None:
for bban in bbans:
assert bban.bank is not None
assert bban.country_code == country_code

assert any(
bban.bank is None
for bban in (BBAN.random(country_code, use_registry=False) for _ in range(n))
)

0 comments on commit 4aa8d80

Please sign in to comment.