lists.arthurdejong.org
RSS feed

python-stdnum branch master updated. 1.9-8-g5af712b

[Date Prev][Date Next] [Thread Prev][Thread Next]

python-stdnum branch master updated. 1.9-8-g5af712b



This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-stdnum".

The branch, master has been updated
       via  5af712b0ff232eec4197635c14aa2342e76ff382 (commit)
      from  ec39d86d1d6a7f47d4c0d9dc70089bdc48e5e7ab (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://arthurdejong.org/git/python-stdnum/commit/?id=5af712b0ff232eec4197635c14aa2342e76ff382

commit 5af712b0ff232eec4197635c14aa2342e76ff382
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Wed Aug 22 22:12:38 2018 +0200

    Add Norwegian bank account number
    
    This includes validation of Norwegian bank account numbers and
    conversion to IBAN.
    
    Closes https://github.com/arthurdejong/python-stdnum/issues/79

diff --git a/stdnum/no/iban.py b/stdnum/no/iban.py
new file mode 100644
index 0000000..34a0ac7
--- /dev/null
+++ b/stdnum/no/iban.py
@@ -0,0 +1,79 @@
+# iban.py - functions for handling Norwegian IBANs
+# coding: utf-8
+#
+# Copyright (C) 2018 Arthur de Jong
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+"""Norwegian IBAN (International Bank Account Number).
+
+The IBAN is used to identify bank accounts across national borders. The
+Norwegian IBAN is built up of the IBAN prefix (NO) and check digits, followed
+by the 11 digit Konto nr. (bank account number).
+
+>>> validate('NO93 8601 1117 947')
+'NO9386011117947'
+>>> to_kontonr('NO93 8601 1117 947')
+'86011117947'
+>>> format('NO9386011117947')
+'NO93 8601 1117 947'
+>>> validate('GR1601101050000010547023795')  # different country
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> validate('NO92 8601 1117 947')  # invalid IBAN check digit
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> validate('NO23 8601 1117 946')  # invalid Konto nr. check digit
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+"""
+
+from stdnum import iban
+from stdnum.exceptions import *
+from stdnum.no import kontonr
+
+
+__all__ = ['compact', 'format', 'to_kontonr', 'validate', 'is_valid']
+
+
+compact = iban.compact
+format = iban.format
+
+
+def to_kontonr(number):
+    """Return the Norwegian bank account number part of the number."""
+    number = compact(number)
+    if not number.startswith('NO'):
+        raise InvalidComponent()
+    return number[4:]
+
+
+def validate(number):
+    """Check if the number provided is a valid Norwegian IBAN."""
+    number = iban.validate(number, check_country=False)
+    kontonr.validate(to_kontonr(number))
+    return number
+
+
+def is_valid(number):
+    """Check if the number provided is a valid Norwegian IBAN."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
diff --git a/stdnum/no/kontonr.py b/stdnum/no/kontonr.py
new file mode 100644
index 0000000..64a7d81
--- /dev/null
+++ b/stdnum/no/kontonr.py
@@ -0,0 +1,105 @@
+# kontonr.py - functions for handling Norwegian bank account numbers
+# coding: utf-8
+#
+# Copyright (C) 2018 Arthur de Jong
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+"""Konto nr. (Norwegian bank account number)
+
+Konto nr. is the country-specific part in Norwegian IBAN codes. The number
+consists of 11 digits, the first 4 are the bank identifier and the last is a
+check digit. This module does not check if the bank identifier exists.
+
+More information:
+
+* https://www.ecbs.org/iban/norway-bank-account-number.html
+
+>>> validate('8601 11 17947')
+'86011117947'
+>>> validate('0000.4090403')  # postgiro bank code
+'4090403'
+>>> validate('8601 11 17949')  # invalid check digits
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> format('86011117947')
+'8601.11.17947'
+>>> to_iban('8601 11 17947')
+'NO93 8601 11 17947'
+"""
+
+from stdnum import luhn
+from stdnum.exceptions import *
+from stdnum.util import clean
+
+
+def compact(number):
+    """Convert the number to the minimal representation. This strips the
+    number of any valid separators and removes surrounding whitespace."""
+    number = clean(number, ' .-').strip()
+    if number.startswith('0000'):
+        number = number[4:]  # strip leading 0000 postgiro bank code
+    return number
+
+
+def _calc_check_digit(number):
+    """Calculate the check digit for the 11-digit number."""
+    weights = (6, 7, 8, 9, 4, 5, 6, 7, 8, 9)
+    return str(sum(w * int(n) for w, n in zip(weights, number)) % 11)
+
+
+def validate(number):
+    """Check if the number provided is a valid bank account number."""
+    number = compact(number)
+    if not number.isdigit():
+        raise InvalidFormat()
+    if len(number) == 7:
+        luhn.validate(number)
+    elif len(number) == 11:
+        if _calc_check_digit(number) != number[-1]:
+            raise InvalidChecksum()
+    else:
+        raise InvalidLength()
+    return number
+
+
+def is_valid(number):
+    """Check if the number provided is a valid bank account number."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
+
+
+def to_iban(number):
+    """Convert the number to an IBAN."""
+    from stdnum import iban
+    separator = ' ' if ' ' in number else ''
+    return separator.join((
+        'NO' + iban.calc_check_digits('NO00' + number),
+        number))
+
+
+def format(number):
+    """Reformat the number to the standard presentation format."""
+    number = compact(number)
+    number = (11 - len(number)) * '0' + number
+    return '.'.join([
+        number[:4],
+        number[4:6],
+        number[6:],
+    ])
diff --git a/tests/test_iban.doctest b/tests/test_iban.doctest
index 9fdcfaa..eef1948 100644
--- a/tests/test_iban.doctest
+++ b/tests/test_iban.doctest
@@ -148,8 +148,53 @@ numbers:
 ... MU17 BOMM0101101030300200000MUR
 ... NL91 ABNA 0417 1643 00
 ... NL91ABNA0417164300
+... NO 02 15037577003
+... NO 05 15030383041
+... NO 0560110516994
+... NO 0571 3905 25162
+... NO 0828014322061
+... NO 1232600465693
+... NO 19 4920 06 96270
+... NO 21 650 405 251 19
+... NO 2342009668904
+... NO 26 7032 0516 038
+... NO 3036245391786
+... NO 31 6018 04 47124
+... NO 33 4270 06 08551
+... NO 35 9650 05 73667
+... NO 39 4750 07 95936
+... NO 39 6318 05 01489
+... NO 39 7874 0597 506
+... NO 40 1503 7355 353
+... NO 402333 06 01019
+... NO 43 651 204 471 94
+... NO 44 1850.05.14562
+... NO 4575600702548
+... NO 5314300642641
+... NO 57 78740655867
+... NO 5997501101463
+... NO 62 650 204 441 20
+... NO 6865040505746
+... NO 6940872430085
+... NO 6947780786090
+... NO 71 7694 05 00903
+... NO 7615030839797
+... NO 89 42004151326
+... NO 91 16024246306
+... NO05 7058 0555 568
+... NO07.8380.08.06006
+... NO1782000193468
+... NO2476940517075
+... NO38 8200 06 10190
+... NO4697500641723
+... NO5876940518888
+... NO71.4202.47.14777
+... NO77 7694 0511 077
+... NO89 4760 5692 776
+... NO8976940512510
 ... NO93 8601 1117 947
 ... NO9386011117947
+... NO9832271000153
 ... PK36SCBL0000001123456702
 ... PL61 1090 1014 0000 0712 1981 2874
 ... PL61109010140000071219812874

-----------------------------------------------------------------------

Summary of changes:
 stdnum/{es => no}/iban.py |  42 +++++++++----------
 stdnum/no/kontonr.py      | 105 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/test_iban.doctest   |  45 ++++++++++++++++++++
 3 files changed, 171 insertions(+), 21 deletions(-)
 copy stdnum/{es => no}/iban.py (59%)
 create mode 100644 stdnum/no/kontonr.py


hooks/post-receive
-- 
python-stdnum
-- 
To unsubscribe send an email to
python-stdnum-commits-unsubscribe@lists.arthurdejong.org or see
https://lists.arthurdejong.org/python-stdnum-commits/