Django

Code

Ticket #5475: ticket_5475__revision_6218.diff

File ticket_5475__revision_6218.diff, 2.4 kB (added by __hawkeye__, 1 year ago)

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

  • django/utils/checksums.py

    old new  
     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 
  • tests/regressiontests/utils/tests.py

    old new  
    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)