Ticket #5475: ticket_5475__revision_6218.diff

File ticket_5475__revision_6218.diff, 2.4 KB (added by Ben Slavin, 17 years ago)

Added django.utils.checksums, which contains an implementation of the Luhn algorithm. Tests included.

  • django/utils/checksums.py

     
     1__all__ = ['luhn',]
     2
     3LUHN_ODD_LOOKUP = (0, 2, 4, 6, 8, 1, 3, 5, 7, 9) # sum_of_digits(index * 2)
     4
     5def luhn(candidate):
     6    """
     7    Checks a candidate number for validity according to the Luhn
     8    algorithm (used in validation of, for example, credit cards).
     9    Both numeric and string candidates are accepted.
     10    """
     11    if not isinstance(candidate, basestring):
     12        candidate = str(candidate)
     13    try:
     14        evens = sum([int(c) for c in candidate[-1::-2]])
     15        odds = sum([LUHN_ODD_LOOKUP[int(c)] for c in candidate[-2::-2]])
     16        return ((evens + odds) % 10 == 0)
     17    except ValueError:  # Raised if an int conversion fails
     18        return False
     19 No newline at end of file
  • tests/regressiontests/utils/tests.py

     
    44
    55from unittest import TestCase
    66
    7 from django.utils import html
     7from django.utils import html, checksums
    88
    99class TestUtilsHtml(TestCase):
    1010
     
    113113        )
    114114        for value, output in items:
    115115            self.check_output(f, value, output)
     116
     117class TestUtilsChecksums(TestCase):
     118   
     119    def check_output(self, function, value, output=None):
     120        """
     121        Check that function(value) equals output.  If output is None,
     122        check that function(value) equals value.
     123        """
     124        if output is None:
     125            output = value
     126        self.assertEqual(function(value), output)
     127   
     128    def test_luhn(self):
     129        f = checksums.luhn
     130        items = (
     131            (4111111111111111, True), ('4111111111111111', True),
     132            (4222222222222, True), (378734493671000, True),
     133            (5424000000000015, True), (5555555555554444, True),
     134            (1008, True), ('0000001008', True), ('000000001008', True),
     135            (4012888888881881, True), (1234567890123456789012345678909, True),
     136            (4111111111211111, False), (42222222222224, False),
     137            (100, False), ('100', False), ('0000100', False),
     138            ('abc', False), (None, False), (object(), False),
     139        )
     140        for value, output in items:
     141            self.check_output(f, value, output)
Back to Top