Ticket #3961: za-localflavor.diff

File za-localflavor.diff, 5.3 KB (added by Russell Cloran <russell@…>, 8 years ago)

Patch to add za localflavor

  • django/utils/checksums.py

     
     1"""Implementations of useful checksum algorithms"""
     2
     3def luhn(s):
     4    """A Luhn checksum is a simplistic checksum designed to catch typing
     5    errors. Takes a string of digits or an int.
     6
     7    This checksum is commonly used with credit card numbers.
     8
     9    http://en.wikipedia.org/wiki/Luhn_algorithm
     10    """
     11
     12    if isinstance(s, int):
     13        s = str(s)
     14
     15    if not (isinstance(s, basestring) and s.isdigit()):
     16        return False
     17
     18    lookup = (0, 2, 4, 6, 8, 1, 3, 5, 7, 9) # sum_of_digits(index * 2)
     19    evens = sum([int(c) for c in s[-1::-2]])
     20    odds = sum([lookup[int(c)] for c in s[-2::-2]])
     21    return ((evens + odds) % 10 == 0)
  • django/contrib/localflavor/za/za_provinces.py

     
     1from django.utils.translation import gettext_lazy as _
     2
     3PROVINCE_CHOICES = (
     4    ('EC', _('Eastern Cape')),
     5    ('FS', _('Free State')),
     6    ('GP', _('Gauteng')),
     7    ('KN', _('KwaZulu-Natal')),
     8    ('LP', _('Limpopo')),
     9    ('MP', _('Mpumalanga')),
     10    ('NC', _('Northern Cape')),
     11    ('NW', _('North West')),
     12    ('WC', _('Western Cape')),
     13)
  • django/contrib/localflavor/za/forms.py

     
     1"""
     2South Africa-specific Form helpers
     3"""
     4
     5from django.newforms import ValidationError
     6from django.newforms.fields import Field, RegexField, EMPTY_VALUES
     7from django.utils.checksums import luhn
     8from django.utils.translation import gettext as _
     9import re
     10from datetime import date
     11
     12id_re = re.compile(r'^(?P<yy>\d\d)(?P<mm>\d\d)(?P<dd>\d\d)(?P<mid>\d{4})(?P<end>\d{3})')
     13
     14class ZAIDField(Field):
     15    """A form field for South African ID numbers -- the checksum is validated
     16    using the Luhn checksum, and uses a simlistic (read: not entirely accurate)
     17    check for the birthdate
     18    """
     19
     20    def __init__(self, *args, **kwargs):
     21        super(ZAIDField, self).__init__()
     22        self.error_message = _(u'Enter a valid South African ID number')
     23
     24    def clean(self, value):
     25        # strip spaces and dashes
     26        value = value.strip().replace(' ', '').replace('-', '')
     27
     28        super(ZAIDField, self).clean(value)
     29
     30        if value in EMPTY_VALUES:
     31            return u''
     32
     33        match = re.match(id_re, value)
     34       
     35        if not match:
     36            raise ValidationError(self.error_message)
     37
     38        g = match.groupdict()
     39
     40        try:
     41            # The year 2000 is conveniently a leapyear.
     42            # This algorithm will break in xx00 years which aren't leap years
     43            # There is no way to guess the century of a ZA ID number
     44            d = date(int(g['yy']) + 2000, int(g['mm']), int(g['dd']))
     45        except ValueError:
     46            raise ValidationError(self.error_message)
     47
     48        if not luhn(value):
     49            raise ValidationError(self.error_message)
     50
     51        return value
     52
     53class ZAPostCodeField(RegexField):
     54    def __init__(self, *args, **kwargs):
     55        super(ZAPostCodeField, self).__init__(r'^\d{4}$',
     56            max_length=None, min_length=None,
     57            error_message=_(u'Enter a valid South African postal code'))
  • tests/regressiontests/forms/localflavor.py

     
    882882Traceback (most recent call last):
    883883...
    884884ValidationError: [u'Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.']
     885
     886# ZAIDField #################################################################
     887
     888ZAIDField validates that the date is a valid birthdate and that the value
     889has a valid checksum. It allows spaces and dashes, and returns a plain
     890string of digits.
     891>>> from django.contrib.localflavor.za.forms import ZAIDField
     892>>> f = ZAIDField()
     893>>> f.clean('0002290001003')
     894'0002290001003'
     895>>> f.clean('000229 0001 003')
     896'0002290001003'
     897>>> f.clean('0102290001001')
     898Traceback (most recent call last):
     899...
     900ValidationError: [u'Enter a valid South African ID number']
     901>>> f.clean('811208')
     902Traceback (most recent call last):
     903...
     904ValidationError: [u'Enter a valid South African ID number']
     905>>> f.clean('0002290001004')
     906Traceback (most recent call last):
     907...
     908ValidationError: [u'Enter a valid South African ID number']
     909
     910# ZAPostCodeField ###########################################################
     911>>> from django.contrib.localflavor.za.forms import ZAPostCodeField
     912>>> f = ZAPostCodeField()
     913>>> f.clean('abcd')
     914Traceback (most recent call last):
     915...
     916ValidationError: [u'Enter a valid South African postal code']
     917>>> f.clean('0000')
     918u'0000'
     919>>> f.clean(' 7530')
     920Traceback (most recent call last):
     921...
     922ValidationError: [u'Enter a valid South African postal code']
    885923"""
Back to Top