lists.arthurdejong.org
RSS feed

python-stdnum commit: r35 - in python-stdnum: . stdnum/iso7064 tests

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

python-stdnum commit: r35 - in python-stdnum: . stdnum/iso7064 tests



Author: arthur
Date: Fri Aug 27 13:36:42 2010
New Revision: 35
URL: http://arthurdejong.org/viewvc/python-stdnum?view=rev&revision=35

Log:
implement some ISO/IEC 7064 check digit schemes

Added:
   python-stdnum/stdnum/iso7064/
   python-stdnum/stdnum/iso7064/__init__.py
   python-stdnum/stdnum/iso7064/mod_11_10.py
   python-stdnum/stdnum/iso7064/mod_11_2.py
   python-stdnum/stdnum/iso7064/mod_37_2.py
   python-stdnum/stdnum/iso7064/mod_37_36.py
   python-stdnum/stdnum/iso7064/mod_97_10.py
   python-stdnum/tests/test_iso7064.doctest
Modified:
   python-stdnum/README

Modified: python-stdnum/README
==============================================================================
--- python-stdnum/README        Thu Aug 26 23:03:44 2010        (r34)
+++ python-stdnum/README        Fri Aug 27 13:36:42 2010        (r35)
@@ -15,8 +15,13 @@
 - BSN (Burgerservicenummer, the Dutch national identification number)
 - IMEI (International Mobile Equipment Identity)
 - MEID (Mobile Equipment Identifier)
-- Verhoeff (generic functions for the Verhoeff algorithm)
-- Luhn (generic functions for the Luhn and Luhn mod N algorithms)
+
+Furthermore a number of generic check digit algorithms are available:
+
+- the Verhoeff algorithm
+- the Luhn and Luhn mod N algorithms
+- some algorithms described in ISO/IEC 7064: Mod 11, 2, Mod 37, 2, Mod 97, 10,
+  Mod 11, 10 and Mod 37, 36
 
 Basically any number or code that has some validation mechanism available
 or some common formatting is eligible for inclusion into this library.

Added: python-stdnum/stdnum/iso7064/__init__.py
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ python-stdnum/stdnum/iso7064/__init__.py    Fri Aug 27 13:36:42 2010        
(r35)
@@ -0,0 +1,28 @@
+# __init__.py - functions for performing the ISO 7064 algorithms
+#
+# Copyright (C) 2010 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
+
+"""Package containing modules for calculation and verification using a
+number of the ISO 7064 algorithms.
+
+Note that these functions were not implemented using the ISO text itself
+because the text is not available for free. These functions were
+implemented based on information on the algorithms found online and some
+reverse engineering. If anyone can provide a legal copy of the ISO/IEC
+7064 standard these functions can be validated and maybe improved.
+"""

Added: python-stdnum/stdnum/iso7064/mod_11_10.py
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ python-stdnum/stdnum/iso7064/mod_11_10.py   Fri Aug 27 13:36:42 2010        
(r35)
@@ -0,0 +1,54 @@
+# mod_11_10.py - functions for performing the ISO 7064 Mod 11, 10 algorithm
+#
+# Copyright (C) 2010 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
+
+"""Module for calculation and verifying the checksum of a number
+using the ISO 7064 Mod 11, 10 algorithm.
+
+Validation can be done with is_valid(). A valid number can be made by
+calculating the check digit and appending it.
+
+>>> calc_check_digit('79462')
+'3'
+>>> is_valid('794623')
+True
+>>> calc_check_digit('00200667308')
+'5'
+>>> is_valid('002006673085')
+True
+"""
+
+
+def checksum(number):
+    """Calculate the checksum."""
+    check = 5
+    for n in number:
+        check = ( ((check or 10) * 2) % 11 + int(n) ) % 10
+    return check
+
+def calc_check_digit(number):
+    """With the provided number, calculate the extra digit that should be
+    appended to make it a valid number."""
+    return str((1 - ( (checksum(number) or 10) * 2) % 11 ) % 10)
+
+def is_valid(number):
+    """Checks whether the check digit is valid."""
+    try:
+        return bool(number) and checksum(number) == 1
+    except:
+        return False

Added: python-stdnum/stdnum/iso7064/mod_11_2.py
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ python-stdnum/stdnum/iso7064/mod_11_2.py    Fri Aug 27 13:36:42 2010        
(r35)
@@ -0,0 +1,58 @@
+# mod_11_2.py - functions for performing the ISO 7064 Mod 11, 2 algorithm
+#
+# Copyright (C) 2010 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
+
+"""Module for calculation and verifying the checksum of a number
+using the ISO 7064 Mod 11, 2 algorithm.
+
+Validation can be done with is_valid(). A valid number can be made by
+calculating the check digit and appending it.
+
+>>> calc_check_digit('0794')
+'0'
+>>> is_valid('07940')
+True
+>>> calc_check_digit('079')
+'X'
+>>> is_valid('079X')
+True
+>>> checksum('079X')
+1
+"""
+
+
+def checksum(number):
+    """Calculate the checksum."""
+    check = 0
+    for n in number:
+        check = ( 2 * check + int(10 if n == 'X' else n) ) % 11
+    return check
+
+def calc_check_digit(number):
+    """With the provided number, calculate the extra digit that should be
+    appended to make it a valid number."""
+    c = (1 - 2 * checksum(number) ) % 11
+    return 'X' if c == 10 else str(c)
+
+def is_valid(number):
+    """Checks whether the check digit is valid."""
+    try:
+        return bool(number) and checksum(number) == 1
+    except:
+        return False
+

Added: python-stdnum/stdnum/iso7064/mod_37_2.py
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ python-stdnum/stdnum/iso7064/mod_37_2.py    Fri Aug 27 13:36:42 2010        
(r35)
@@ -0,0 +1,64 @@
+# mod_37_2.py - functions for performing the ISO 7064 Mod 37, 2 algorithm
+#
+# Copyright (C) 2010 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
+
+"""Module for calculation and verifying the checksum of a number
+using the ISO 7064 Mod 37, 2 algorithm.
+
+Validation can be done with is_valid(). A valid number can be made by
+calculating the check digit and appending it.
+
+>>> calc_check_digit('G123489654321')
+'Y'
+>>> is_valid('G123489654321Y')
+True
+>>> checksum('G123489654321Y')
+1
+
+By changing the alphabet this can be turned into any Mod x, 2
+algorith. For example Mod 10, 2:
+
+>>> calc_check_digit('079', alphabet='0123456789X')
+'X'
+>>> is_valid('079', alphabet='0123456789X')
+True
+>>> checksum('079', alphabet='0123456789X')
+1
+"""
+
+
+def checksum(number, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*'):
+    """Calculate the checksum."""
+    modulus = len(alphabet)
+    check = 0
+    for n in number:
+        check = ( 2 * check + alphabet.index(n) ) % modulus
+    return check
+
+def calc_check_digit(number, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*'):
+    """With the provided number, calculate the extra digit that should be
+    appended to make it a valid number."""
+    modulus = len(alphabet)
+    return alphabet[(1 - 2 * checksum(number, alphabet) ) % modulus]
+
+def is_valid(number, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*'):
+    """Checks whether the check digit is valid."""
+    try:
+        return bool(number) and checksum(number, alphabet) == 1
+    except:
+        return False

Added: python-stdnum/stdnum/iso7064/mod_37_36.py
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ python-stdnum/stdnum/iso7064/mod_37_36.py   Fri Aug 27 13:36:42 2010        
(r35)
@@ -0,0 +1,62 @@
+# mod_37_36.py - functions for performing the ISO 7064 Mod 37, 36 algorithm
+#
+# Copyright (C) 2010 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
+
+"""Module for calculation and verifying the checksum of a number
+using the ISO 7064 Mod 37, 36 algorithm.
+
+Validation can be done with is_valid(). A valid number can be made by
+calculating the check digit and appending it.
+
+>>> checksum('A12425GABC1234002M')
+1
+>>> calc_check_digit('A12425GABC1234002')
+'M'
+>>> is_valid('A12425GABC1234002M')
+True
+
+By changing the alphabet this can be turned into any Mod x+1, x
+algorith. For example Mod 11, 10:
+
+>>> calc_check_digit('00200667308', alphabet='0123456789')
+'5'
+>>> is_valid('002006673085', alphabet='0123456789')
+True
+"""
+
+
+def checksum(number, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
+    """Calculate the checksum."""
+    modulus = len(alphabet)
+    check = modulus / 2
+    for n in number:
+        check = ( ((check or modulus) * 2) % (modulus + 1) + alphabet.index(n) 
) % modulus
+    return check
+
+def calc_check_digit(number, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
+    """With the provided number, calculate the extra digit that should be
+    appended to make it a valid number."""
+    modulus = len(alphabet)
+    return alphabet[(1 - ( (checksum(number, alphabet) or modulus) * 2) % 
(modulus + 1) ) % modulus]
+
+def is_valid(number, alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
+    """Checks whether the check digit is valid."""
+    try:
+        return bool(number) and checksum(number, alphabet) == 1
+    except:
+        return False

Added: python-stdnum/stdnum/iso7064/mod_97_10.py
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ python-stdnum/stdnum/iso7064/mod_97_10.py   Fri Aug 27 13:36:42 2010        
(r35)
@@ -0,0 +1,53 @@
+# mod_97_10.py - functions for performing the ISO 7064 Mod 97, 10 algorithm
+#
+# Copyright (C) 2010 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
+
+"""Module for calculation and verifying the check digits of a number
+using the ISO 7064 Mod 97, 10 algorithm.
+
+Validation can be done with is_valid(). A valid number can be made by
+calculating the check digits and appending them.
+
+
+>>> calc_check_digits('99991234567890121414')
+'90'
+>>> is_valid('9999123456789012141490')
+True
+>>> calc_check_digits('4354111611551114')
+'31'
+>>> is_valid('08686001256515001121751')
+True
+>>> calc_check_digits('22181321402534321446701611')
+'35'
+"""
+
+def checksum(number):
+    """Calculate the checksum."""
+    return int(number) % 97
+
+def calc_check_digits(number):
+    """With the provided number, calculate the extra digit that should be
+    appended to make it a valid number."""
+    return '%02d' % (( 98 - 100 * checksum(number)) % 97)
+
+def is_valid(number):
+    """Determines whether the number has a valid checksum."""
+    try:
+        return bool(number) and checksum(number) == 1
+    except:
+        return False

Added: python-stdnum/tests/test_iso7064.doctest
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ python-stdnum/tests/test_iso7064.doctest    Fri Aug 27 13:36:42 2010        
(r35)
@@ -0,0 +1,84 @@
+test_iso7064.doctest - more detailed doctests for the stdnum.iso7064 package
+
+Copyright (C) 2010 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.iso7064 package. It
+tries to test more corner cases and detailed functionality that is not
+really useful as module documentation.
+
+>>> from stdnum import iso7064
+
+
+These are normal variations of Mod 11, 10 that should just work.
+
+>>> iso7064.mod_11_10.is_valid('12323')
+True
+>>> iso7064.mod_11_10.is_valid('546794')
+True
+>>> iso7064.mod_11_10.calc_check_digit('0794')
+'5'
+>>> iso7064.mod_11_10.is_valid('07945')
+True
+>>> iso7064.mod_11_10.calc_check_digit('00200667308')
+'5'
+>>> iso7064.mod_11_10.is_valid('002006673085')
+True
+>>> iso7064.mod_11_10.is_valid('002006673084')
+False
+>>> iso7064.mod_11_10.calc_check_digit('00200667309')
+'3'
+>>> iso7064.mod_11_10.calc_check_digit('00200667310')
+'8'
+>>> iso7064.mod_11_10.calc_check_digit('00200667311')
+'6'
+>>> iso7064.mod_11_10.calc_check_digit('00200667312')
+'4'
+
+
+These normal tests of Mod 11, 2 should just work.
+
+>>> iso7064.mod_11_2.calc_check_digit('0794')
+'0'
+>>> iso7064.mod_11_2.is_valid('07940')
+True
+>>> iso7064.mod_11_2.calc_check_digit('079')
+'X'
+>>> iso7064.mod_11_2.is_valid('079')
+True
+
+These normal tests of Mod 37, 2 should just work
+
+>>> iso7064.mod_37_2.calc_check_digit('G123498654321')
+'H'
+
+
+Furthermore the is_valid() method should be fairly robust against invalid
+junk passed:
+
+>>> testvalues = ( None, '*&^%$', False, object() )
+>>> [ x for x in testvalues if iso7064.mod_11_10.is_valid(x) ]
+[]
+>>> [ x for x in testvalues if iso7064.mod_11_2.is_valid(x) ]
+[]
+>>> [ x for x in testvalues if iso7064.mod_37_2.is_valid(x) ]
+[]
+>>> [ x for x in testvalues if iso7064.mod_37_36.is_valid(x) ]
+[]
+>>> [ x for x in testvalues if iso7064.mod_97_10.is_valid(x) ]
+[]
--
To unsubscribe send an email to
python-stdnum-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/python-stdnum-commits