lists.arthurdejong.org
RSS feed

python-stdnum branch master updated. 1.11-2-ge07a0e2

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

python-stdnum branch master updated. 1.11-2-ge07a0e2



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  e07a0e249fa112f722ceae6aa197ee9d5a626e9d (commit)
       via  2e87251b90d47f1b7aa0ed3d6186367613d7b22e (commit)
      from  72cbfb8b14fe734cae210fb4f28b65586ddd34e7 (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=e07a0e249fa112f722ceae6aa197ee9d5a626e9d

commit e07a0e249fa112f722ceae6aa197ee9d5a626e9d
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sun Mar 24 22:06:01 2019 +0100

    Add Peruvian CUI (DNI)

diff --git a/stdnum/pe/cui.py b/stdnum/pe/cui.py
new file mode 100644
index 0000000..b50a46a
--- /dev/null
+++ b/stdnum/pe/cui.py
@@ -0,0 +1,89 @@
+# cui.py - functions for handling Peruvian personal numbers
+# coding: utf-8
+#
+# Copyright (C) 2019 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
+
+"""CUI (Cédula Única de Identidad, Peruvian identity number).
+
+The Cédula Única de Identidad (CUI) is the unique identifier for persons that
+appears on the Documento Nacional de Identidad (DNI), the national identity
+document of Peru. The number consists of 8 digits and an optional extra check
+digit.
+
+More information:
+
+* https://www.gob.pe/235-documento-nacional-de-identidad-dni
+* https://es.wikipedia.org/wiki/Documento_Nacional_de_Identidad_(Perú)
+
+>>> validate('10117410')
+'10117410'
+>>> validate('10117410-2')
+'101174102'
+>>> validate('10117410-3')  # invalid check digit
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> to_ruc('10117410-2')
+'10101174102'
+"""
+
+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().upper()
+
+
+def calc_check_digits(number):
+    """Calculate the possible check digits for the CUI."""
+    number = compact(number)
+    weights = (3, 2, 7, 6, 5, 4, 3, 2)
+    c = sum(w * int(n) for w, n in zip(weights, number)) % 11
+    return '65432110987'[c] + 'KJIHGFEDCBA'[c]
+
+
+def to_ruc(number):
+    """Convert the number to a valid RUC."""
+    from stdnum.pe import ruc
+    number = '10' + compact(number)[:8]
+    return number + ruc.calc_check_digit(number)
+
+
+def validate(number):
+    """Check if the number provided is a valid CUI. This checks the length,
+    formatting and check digit."""
+    number = compact(number)
+    if len(number) not in (8, 9):
+        raise InvalidLength()
+    if not number[:8].isdigit():
+        raise InvalidFormat()
+    if len(number) > 8 and number[-1] not in calc_check_digits(number):
+        raise InvalidChecksum()
+    return number
+
+
+def is_valid(number):
+    """Check if the number provided is a valid CUI. This checks the length,
+    formatting and check digit."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
diff --git a/tests/test_pe_cui.doctest b/tests/test_pe_cui.doctest
new file mode 100644
index 0000000..9ae7dde
--- /dev/null
+++ b/tests/test_pe_cui.doctest
@@ -0,0 +1,89 @@
+test_pe_cui.doctest - more detailed doctests for stdnum.pe.cui module
+
+Copyright (C) 2019 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.pe.ruc module. It
+tries to test more corner cases and detailed functionality that is not really
+useful as module documentation.
+
+>>> from stdnum.pe import cui
+
+
+Tests for some corner cases.
+
+>>> cui.validate('10812543-3')
+'108125433'
+>>> cui.validate('10812543-H')
+'10812543H'
+>>> cui.validate('1081254332')
+Traceback (most recent call last):
+    ...
+InvalidLength: ...
+>>> cui.validate('108125H3-3')
+Traceback (most recent call last):
+    ...
+InvalidFormat: ...
+>>> cui.to_ruc('10812543-3')
+'10108125433'
+
+
+These 9-digit numbers have been found online and should all be valid numbers.
+
+>>> numbers = '''
+...
+...
+... 05209244-8
+... 05337812-4
+... 06009893-5
+... 06224656-7
+... 06416641-2
+... 06477277-1
+... 06770169-6
+... 07750457-1
+... 07881352-6
+... 09482447-3
+... 09537333-5
+... 10117410-2
+... 10123558-6
+... 10586119B
+... 17859853-3
+... 25465832-0
+... 25543680E
+... 25735046-6
+... 32023446H
+... 33562458-6
+... 40812023-9
+... 42189197-0
+... 42388604-3
+... 43381907-7
+... 43451826-7
+... 45055499E
+... 46788632-6
+... 46967914-0
+... 47205319-7
+... 474996072
+... 63109177-1
+... 70025425-4
+... 71347545-4
+... 72641234-6
+... 72859897-8
+...
+... '''
+>>> [x for x in numbers.splitlines() if x and not cui.is_valid(x)]
+[]

https://arthurdejong.org/git/python-stdnum/commit/?id=2e87251b90d47f1b7aa0ed3d6186367613d7b22e

commit 2e87251b90d47f1b7aa0ed3d6186367613d7b22e
Author: Arthur de Jong <arthur@arthurdejong.org>
Date:   Sat Mar 23 22:58:25 2019 +0100

    Add Peruvian RUC

diff --git a/stdnum/pe/__init__.py b/stdnum/pe/__init__.py
new file mode 100644
index 0000000..4d92e64
--- /dev/null
+++ b/stdnum/pe/__init__.py
@@ -0,0 +1,21 @@
+# __init__.py - collection of Peruvian numbers
+# coding: utf-8
+#
+# Copyright (C) 2019 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
+
+"""Collection of Peruvian numbers."""
diff --git a/stdnum/pe/ruc.py b/stdnum/pe/ruc.py
new file mode 100644
index 0000000..6e5ad80
--- /dev/null
+++ b/stdnum/pe/ruc.py
@@ -0,0 +1,88 @@
+# ruc.py - functions for handling Peruvian fiscal numbers
+# coding: utf-8
+#
+# Copyright (C) 2019 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
+
+"""RUC (Registro Único de Contribuyentes, Peruvian company tax number).
+
+The RUC (Registro Único de Contribuyentes) is the tax number of Peru assigned
+to legal and natural persons. The number consists of 11 digits, the first two
+indicate the kind of number, for personal numbers it is followed by the DNI
+and a check digit.
+
+More information:
+
+* http://www.sunat.gob.pe/legislacion/ruc/
+* https://consultarelruc.pe/
+
+>>> validate('20512333797')
+'20512333797'
+>>> validate('20512333798')  # invalid check digit
+Traceback (most recent call last):
+    ...
+InvalidChecksum: ...
+>>> to_dni('10054148289')
+'05414828'
+"""
+
+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_digit(number):
+    """Calculate the check digit."""
+    weights = (5, 4, 3, 2, 7, 6, 5, 4, 3, 2)
+    return str((11 - sum(w * int(n) for w, n in zip(weights, number)) % 11) % 
10)
+
+
+def to_dni(number):
+    """Return the DNI (CUI) part of the number for natural persons."""
+    number = validate(number)
+    if not number.startswith('10'):
+        raise InvalidComponent()  # only for persons
+    return number[2:10]
+
+
+def validate(number):
+    """Check if the number provided is a valid RUC. This checks the length,
+    formatting and check digit."""
+    number = compact(number)
+    if len(number) != 11:
+        raise InvalidLength()
+    if not number.isdigit():
+        raise InvalidFormat()
+    if number[:2] not in ('10', '15', '17', '20'):
+        raise InvalidComponent()  # not person or company
+    if not number.endswith(calc_check_digit(number)):
+        raise InvalidChecksum()
+    return number
+
+
+def is_valid(number):
+    """Check if the number provided is a valid RUC. This checks the length,
+    formatting and check digit."""
+    try:
+        return bool(validate(number))
+    except ValidationError:
+        return False
diff --git a/tests/test_pe_ruc.doctest b/tests/test_pe_ruc.doctest
new file mode 100644
index 0000000..6fe6384
--- /dev/null
+++ b/tests/test_pe_ruc.doctest
@@ -0,0 +1,171 @@
+test_pe_ruc.doctest - more detailed doctests for stdnum.pe.ruc module
+
+Copyright (C) 2019 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.pe.ruc module. It
+tries to test more corner cases and detailed functionality that is not really
+useful as module documentation.
+
+>>> from stdnum.pe import ruc
+
+
+Tests for some corner cases.
+
+>>> ruc.validate('20512333797')
+'20512333797'
+>>> ruc.validate('2051233379')
+Traceback (most recent call last):
+    ...
+InvalidLength: ...
+>>> ruc.validate('99512333792')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+>>> ruc.validate('20A12333797')
+Traceback (most recent call last):
+    ...
+InvalidFormat: ...
+>>> ruc.to_dni('10054148289')
+'05414828'
+>>> ruc.to_dni('20512333797')
+Traceback (most recent call last):
+    ...
+InvalidComponent: ...
+
+
+These have been found online and should all be valid numbers.
+
+>>> numbers = '''
+...
+... 10000655959
+... 10010734121
+... 10040578108
+... 10053358671
+... 10054148289
+... 10058437277
+... 10060535138
+... 10098295343
+... 10103206851
+... 10108344739
+... 10156612001
+... 10164655909
+... 10165791474
+... 10166518861
+... 10167089505
+... 10167323290
+... 10198029632
+... 10214859268
+... 10243761927
+... 10254430752
+... 10266040640
+... 10266906451
+... 10277354981
+... 10411119373
+... 10414493071
+... 10425240311
+... 10427556960
+... 10433604640
+... 10436581772
+... 10452880437
+... 15484032987
+... 15501941597
+... 17155542071
+... 17322796196
+... 20100255325
+... 20109980936
+... 20113732084
+... 20123458444
+... 20131372770
+... 20134636972
+... 20137663474
+... 20139490691
+... 20142529913
+... 20145391076
+... 20154546520
+... 20171312141
+... 20171781648
+... 20172245065
+... 20172284044
+... 20193655492
+... 20198432386
+... 20201571350
+... 20206309815
+... 20209462452
+... 20212025179
+... 20212516661
+... 20222194564
+... 20222955433
+... 20252290029
+... 20253602571
+... 20296742563
+... 20312356776
+... 20347268683
+... 20354374286
+... 20357089795
+... 20382245068
+... 20393125064
+... 20401283952
+... 20406257127
+... 20421551520
+... 20429794146
+... 20438510398
+... 20448098932
+... 20450258882
+... 20450417433
+... 20451063902
+... 20451392710
+... 20451408811
+... 20451420276
+... 20451428170
+... 20453836364
+... 20454368453
+... 20455554617
+... 20462300787
+... 20472972571
+... 20480597754
+... 20480615329
+... 20481149119
+... 20482221450
+... 20489418933
+... 20493238087
+... 20493298900
+... 20493374002
+... 20495188389
+... 20496055285
+... 20498592521
+... 20504684378
+... 20508379049
+... 20510299761
+... 20512525432
+... 20514261262
+... 20514397245
+... 20518376145
+... 20524105501
+... 20524305004
+... 20524354129
+... 20525274226
+... 20525413447
+... 20530815847
+... 20537999731
+... 20541492047
+... 20552756453
+...
+... '''
+>>> [x for x in numbers.splitlines() if x and not ruc.is_valid(x)]
+[]

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

Summary of changes:
 stdnum/{cu => pe}/__init__.py    |   4 +-
 stdnum/{md/idno.py => pe/cui.py} |  56 ++++++++-----
 stdnum/{md/idno.py => pe/ruc.py} |  47 +++++++----
 tests/test_pe_cui.doctest        |  89 ++++++++++++++++++++
 tests/test_pe_ruc.doctest        | 171 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 327 insertions(+), 40 deletions(-)
 copy stdnum/{cu => pe}/__init__.py (90%)
 copy stdnum/{md/idno.py => pe/cui.py} (50%)
 copy stdnum/{md/idno.py => pe/ruc.py} (55%)
 create mode 100644 tests/test_pe_cui.doctest
 create mode 100644 tests/test_pe_ruc.doctest


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/