lists.arthurdejong.org
RSS feed

python-stdnum branch master updated. 1.1-19-g5ab8d24

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

python-stdnum branch master updated. 1.1-19-g5ab8d24



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  5ab8d24c44924de2a3d4e61469f2cefa98378cdf (commit)
       via  714fa6091957742f7f59c121bb37573e5c280b4b (commit)
      from  b93909974b29edb375523d9790068a5e364f3285 (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 -----------------------------------------------------------------
http://arthurdejong.org/git/python-stdnum/commit/?id=5ab8d24c44924de2a3d4e61469f2cefa98378cdf

commit 5ab8d24c44924de2a3d4e61469f2cefa98378cdf
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Aug 16 23:45:13 2015 +0200

    Add Russioan ИНН (INN) tax ID
    
    This adds a basic implementation of the Russian Идентификационный номер
    налогоплательщика (tax identification number). This currently only
    checks the format, length and check digits but not whether each of the
    parts of the number are valid (e.g. valid region specified).

diff --git a/stdnum/ru/__init__.py b/stdnum/ru/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/stdnum/ru/inn.py b/stdnum/ru/inn.py
new file mode 100644
index 0000000..1f27bb0
--- /dev/null
+++ b/stdnum/ru/inn.py
@@ -0,0 +1,93 @@
+# inn.py - functions for handling Russian VAT numbers
+# coding: utf-8
+#
+# Copyright (C) 2015 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
+
+"""ИНН (Идентификационный номер налогоплательщика, Russian tax identifier).
+
+The Indentifikatzionny nomer nalogoplatel'shchika is a Russian tax
+identification number that consists 10 digits for companies and 12 digits for
+persons.
+
+>>> validate('123456789047')
+'123456789047'
+>>> validate('1234567894')
+'1234567894'
+>>> validate('123456789037')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> validate('1234567895')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+"""
+
+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."""
+    return clean(number, ' ').strip()
+
+
+def calc_company_check_digit(number):
+    """Calculate the check digit for the 10-digit ИНН for organisations."""
+    weights = (2, 4, 10, 3, 5, 9, 4, 6, 8)
+    return str(sum(weights[i] * int(n)
+                   for i, n in enumerate(number[:9])) % 11 % 10)
+
+
+def calc_personal_check_digits(number):
+    """Calculate the check digits for the 12-digit personal ИНН."""
+    weights = (7, 2, 4, 10, 3, 5, 9, 4, 6, 8)
+    d1 = str(sum(weights[i] * int(n)
+                 for i, n in enumerate(number[:10])) % 11 % 10)
+    weights = (3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8)
+    d2 = str(sum(weights[i] * int(n)
+                 for i, n in enumerate(number[:10] + d1)) % 11 % 10)
+    return d1 + d2
+
+
+def validate(number):
+    """Checks to see if the number provided is a valid ИНН. This checks the
+    length, formatting and check digit."""
+    number = compact(number)
+    if not number.isdigit():
+        raise InvalidFormat()
+    if len(number) == 10:
+        if calc_company_check_digit(number) != number[-1]:
+            raise InvalidChecksum()
+    elif len(number) == 12:
+        # persons
+        if calc_personal_check_digits(number) != number[-2:]:
+            raise InvalidChecksum()
+    else:
+        raise InvalidLength()
+    return number
+
+
+def is_valid(number):
+    """Checks to see if the number provided is a valid ИНН. This checks the
+    length, formatting and check digit."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
diff --git a/tests/test_ru_inn.doctest b/tests/test_ru_inn.doctest
new file mode 100644
index 0000000..86ac88e
--- /dev/null
+++ b/tests/test_ru_inn.doctest
@@ -0,0 +1,59 @@
+test_ru_inn.doctest - more detailed doctests for the stdnum.ru.inn module
+
+Copyright (C) 2015 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
+
+
+This file contains more detailed doctests for the stdnum.ru.inn module. It
+tries to validate a number of numbers that have been found online.
+
+>>> from stdnum.ru import inn
+>>> from stdnum.exceptions import *
+
+
+These have been found online and should all be valid numbers.
+
+>>> numbers = '''
+...
+... 005826107187
+... 0108003670
+... 0273074555
+... 0279111370
+... 0716007984
+... 5190187770
+... 6223002330
+... 6440019934
+... 6672238301
+... 6903022126
+... 6908012650
+... 6911001698
+... 7609000881
+... 7709442668
+... 7716450028
+... 7724051595
+... 7726485118
+... 7727705694
+... 7728127936
+... 7813045547
+... 7825498171
+... 8614008550
+... 8906008726
+... 8906008740
+...
+... '''
+>>> [x for x in numbers.splitlines() if x and not inn.is_valid(x)]
+[]

http://arthurdejong.org/git/python-stdnum/commit/?id=714fa6091957742f7f59c121bb37573e5c280b4b

commit 714fa6091957742f7f59c121bb37573e5c280b4b
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Aug 16 21:18:33 2015 +0200

    Add Brazillian CNPJ business identifier
    
    Add module for Cadastro Nacional da Pessoa Jurídica, the Brazillian
    company identifier.

diff --git a/stdnum/br/cnpj.py b/stdnum/br/cnpj.py
new file mode 100644
index 0000000..3d34ed6
--- /dev/null
+++ b/stdnum/br/cnpj.py
@@ -0,0 +1,86 @@
+# cnpj.py - functions for handling CNPJ numbers
+# coding: utf-8
+#
+# Copyright (C) 2015 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
+
+"""CNPJ (Cadastro Nacional da Pessoa Jurídica, Brazillian company identifier).
+
+Numbers from the national register of legal entities have 14 digits. The
+first 8 digits identify the company, the following 4 digits identify a
+business unit and the last 2 digits are check digits.
+
+>>> validate('16.727.230/0001-97')
+'16727230000197'
+>>> validate('16.727.230.0001-98')
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> validate('16.727.230/0001=97')  # invalid delimiter
+Traceback (most recent call last):
+    ...
+InvalidFormat: ...
+>>> format('16727230000197')
+'16.727.230/0001-97'
+"""
+
+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."""
+    return clean(number, ' -./').strip()
+
+
+def calc_check_digits(number):
+    """Calculate the check digits for the number."""
+    d1 = (11 - sum(((3 - i) % 8 + 2) * int(n)
+                   for i, n in enumerate(number[:12]))) % 11 % 10
+    d2 = (11 - sum(((4 - i) % 8 + 2) * int(n)
+                   for i, n in enumerate(number[:12])) -
+          2 * d1) % 11 % 10
+    return '%d%d' % (d1, d2)
+
+
+def validate(number):
+    """Checks to see if the number provided is a valid CNPJ. This checks the
+    length and whether the check digits are correct."""
+    number = compact(number)
+    if not number.isdigit() or int(number) <= 0:
+        raise InvalidFormat()
+    if len(number) != 14:
+        raise InvalidLength()
+    if calc_check_digits(number) != number[-2:]:
+        raise InvalidChecksum()
+    return number
+
+
+def is_valid(number):
+    """Checks to see if the number provided is a valid CNPJ. This checks the
+    length and whether the check digits are correct."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
+
+
+def format(number):
+    number = compact(number)
+    return (number[0:2] + '.' + number[2:5] + '.' + number[5:8] + '/' +
+            number[8:12] + '-' + number[12:])
diff --git a/tests/test_br_cnpj.doctest b/tests/test_br_cnpj.doctest
new file mode 100644
index 0000000..2a0d605
--- /dev/null
+++ b/tests/test_br_cnpj.doctest
@@ -0,0 +1,60 @@
+test_br_cnpj.doctest - more detailed doctests for the stdnum.br.cnpj module
+
+Copyright (C) 2015 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
+
+
+This file contains more detailed doctests for the stdnum.br.cnpj module. It
+tries to validate a number of numbers that have been found online.
+
+>>> from stdnum.br import cnpj
+>>> from stdnum.exceptions import *
+
+
+These have been found online and should all be valid numbers.
+
+>>> numbers = '''
+...
+... 07.195.358/0001-66
+... 08.807.432/0001-10
+... 11.015.248/0001-42
+... 11.017.153/0001-68
+... 11.017.153/0002-49
+... 11.017.153/0003-20
+... 11.017.153/0005-91
+... 11.980.459/0001-15
+... 14.847.283/0001-16
+... 14.847.283/0002-05
+... 14.847.283/0003-88
+... 14.847.283/0004-69
+... 14.847.283/0005-40
+... 16.727.230.0001-97
+... 18.090.575/0001-08
+... 18.090.575/0002-99
+... 18.090.575/0003-70
+... 18.090.575/0004-50
+... 18.090.575/0005-31
+... 22.610.961/0001-50
+... 44.407.989/0001-28
+... 47.080.619/0001-17
+... 53.612.734/0001-98
+... 61882613000194
+... 69.435.154/0001-02
+...
+... '''
+>>> [x for x in numbers.splitlines() if x and not cnpj.is_valid(x)]
+[]

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

Summary of changes:
 stdnum/br/{cpf.py => cnpj.py}                      |   51 ++++++-----
 stdnum/ru/inn.py                                   |   93 ++++++++++++++++++++
 tests/test_br_cnpj.doctest                         |   60 +++++++++++++
 ...st_is_kennitala.doctest => test_ru_inn.doctest} |   47 ++++++----
 4 files changed, 210 insertions(+), 41 deletions(-)
 copy stdnum/br/{cpf.py => cnpj.py} (54%)
 create mode 100644 stdnum/ru/__init__.py
 create mode 100644 stdnum/ru/inn.py
 create mode 100644 tests/test_br_cnpj.doctest
 copy tests/{test_is_kennitala.doctest => test_ru_inn.doctest} (56%)


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