Ticket #3946: ch-localflavor2.diff

File ch-localflavor2.diff, 8.7 KB (added by charly.wilhelm@…, 17 years ago)

Replacement with the suggestions of mtredinnick

  • django/contrib/localflavor/ch/ch_states.py

     
     1# -*- coding: utf-8 -*
     2from django.utils.translation import gettext_lazy as _
     3
     4STATE_CHOICES = (
     5    ('AG', _('Aargau')),
     6    ('AI', _('Appenzell Innerrhoden')),
     7    ('AR', _('Appenzell Ausserrhoden')),
     8    ('BS', _('Basel-Stadt')),
     9    ('BL', _('Basel-Land')),
     10    ('BE', _('Berne')),
     11    ('FR', _('Fribourg')),
     12    ('GE', _('Geneva')),
     13    ('GL', _('Glarus')),
     14    ('GR', _('Graubuenden')),
     15    ('JU', _('Jura')),
     16    ('LU', _('Lucerne')),
     17    ('NE', _('Neuchatel')),
     18    ('NW', _('Nidwalden')),
     19    ('OW', _('Obwalden')),
     20    ('SH', _('Schaffhausen')),
     21    ('SZ', _('Schwyz')),
     22    ('SO', _('Solothurn')),
     23    ('SG', _('St. Gallen')),
     24    ('TG', _('Thurgau')),
     25    ('TI', _('Ticino')),
     26    ('UR', _('Uri')),
     27    ('VS', _('Valais')),
     28    ('VD', _('Vaud')),
     29    ('ZG', _('Zug')),
     30    ('ZH', _('Zurich'))
     31)
  • django/contrib/localflavor/ch/forms.py

     
     1"""
     2Swiss-specific Form helpers
     3"""
     4
     5from django.newforms import ValidationError
     6from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
     7from django.utils.encoding import smart_unicode
     8from django.utils.translation import gettext
     9import re
     10
     11id_re = re.compile(r"^(?P<idnumber>\w{8})(?P<pos9>(\d{1}|<))(?P<checksum>\d{1})$")
     12phone_digits_re = re.compile(r'^0([1-9]{1})\d{8}$')
     13
     14class CHZipCodeField(RegexField):
     15    def __init__(self, *args, **kwargs):
     16        super(CHZipCodeField, self).__init__(r'^\d{4}$',
     17        max_length=None, min_length=None,
     18        error_message=gettext('Enter a zip code in the format XXXX.'),
     19        *args, **kwargs)
     20
     21class CHPhoneNumberField(Field):
     22    """
     23    Validate local Swiss phone number (not international ones)
     24    The correct format is '0XX XXX XX XX'.
     25    '0XX.XXX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
     26    '0XX XXX XX XX'.
     27    """
     28    def clean(self, value):
     29        super(CHPhoneNumberField, self).clean(value)
     30        if value in EMPTY_VALUES:
     31            return u''
     32        value = re.sub('(\.|\s|/|-)', '', smart_unicode(value))
     33        m = phone_digits_re.search(value)
     34        if m:
     35            return u'%s %s %s %s' % (value[0:3], value[3:6], value[6:8], value[8:10])
     36        raise ValidationError('Phone numbers must be in 0XX XXX XX XX format.')
     37   
     38class CHStateSelect(Select):
     39    """
     40    A Select widget that uses a list of CH states as its choices.
     41    """
     42    def __init__(self, attrs=None):
     43        from ch_states import STATE_CHOICES # relative import
     44        super(CHStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
     45
     46class CHIdentityCardNumberField(Field):
     47    """
     48    A Swiss identity card number.
     49
     50    Checks the following rules to determine whether the number is valid:
     51
     52        * Conforms to the X1234567<0 or 1234567890 format.
     53        * Included checksums match calculated checksums
     54
     55    Algorithm is documented at http://adi.kousz.ch/artikel/IDCHE.htm
     56    """
     57   
     58    def has_valid_checksum(self, number):
     59        given_number, given_checksum = number[:-1], number[-1]
     60        new_number = given_number
     61        calculated_checksum = 0
     62        fragment = ""
     63        parameter = 7
     64
     65        first = str(number[:1])
     66        if first.isalpha():
     67            num = ord(first.upper()) - 65
     68            if num < 0 or num > 8:
     69                return False
     70            new_number = str(num) + new_number[1:]
     71            new_number = new_number[:8] + '0'
     72
     73        if not new_number.isdigit():
     74            return False
     75       
     76        for i in range(len(new_number)):
     77          fragment = int(new_number[i])*parameter
     78          calculated_checksum += fragment
     79
     80          if parameter == 1:
     81            parameter = 7
     82          elif parameter == 3:
     83            parameter = 1
     84          elif parameter ==7:
     85            parameter = 3
     86
     87        return str(calculated_checksum)[-1] == given_checksum
     88
     89    def clean(self, value):
     90        super(CHIdentityCardNumberField, self).clean(value)
     91        error_msg = gettext('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format')
     92        if value in EMPTY_VALUES:
     93            return u''
     94       
     95        match = re.match(id_re, value)
     96        if not match:
     97            raise ValidationError(error_msg)
     98
     99        idnumber, pos9, checksum = match.groupdict()['idnumber'], match.groupdict()['pos9'], match.groupdict()['checksum']
     100
     101        if idnumber == '00000000' or \
     102           idnumber == 'A0000000':
     103            raise ValidationError(error_msg)
     104
     105        all_digits = "%s%s%s" % (idnumber, pos9, checksum)
     106        if not self.has_valid_checksum(all_digits):
     107            raise ValidationError(error_msg)
     108
     109        return u'%s%s%s' % (idnumber, pos9, checksum)
  • 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<<<<<<< .mine
    885886
     887# CHZipCodeField ############################################################
     888
     889>>> from django.contrib.localflavor.ch.forms import CHZipCodeField
     890>>> f = CHZipCodeField()
     891>>> f.clean('800x')
     892Traceback (most recent call last):
     893...
     894ValidationError: [u'Enter a zip code in the format XXXX.']
     895>>> f.clean('80 00')
     896Traceback (most recent call last):
     897...
     898ValidationError: [u'Enter a zip code in the format XXXX.']
     899>>> f.clean('8000')
     900u'8000'
     901
     902# CHPhoneNumberField ########################################################
     903
     904>>> from django.contrib.localflavor.ch.forms import CHPhoneNumberField
     905>>> f = CHPhoneNumberField()
     906>>> f.clean('01234567890')
     907Traceback (most recent call last):
     908...
     909ValidationError: [u'Phone numbers must be in 0XX XXX XX XX format.']
     910>>> f.clean('1234567890')
     911Traceback (most recent call last):
     912...
     913ValidationError: [u'Phone numbers must be in 0XX XXX XX XX format.']
     914>>> f.clean('0123456789')
     915u'012 345 67 89'
     916
     917# CHIdentityCardNumberField #################################################
     918
     919>>> from django.contrib.localflavor.ch.forms import CHIdentityCardNumberField
     920>>> f = CHIdentityCardNumberField()
     921>>> f.clean('C1234567<0')
     922u'C1234567<0'
     923>>> f.clean('C1234567<1')
     924Traceback (most recent call last):
     925...
     926ValidationError: [u'Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format']
     927>>> f.clean('2123456700')
     928u'2123456700'
     929>>> f.clean('2123456701')
     930Traceback (most recent call last):
     931...
     932ValidationError: [u'Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format']
     933
     934# CHStateSelect #############################################################
     935
     936>>> from django.contrib.localflavor.ch.forms import CHStateSelect
     937>>> w = CHStateSelect()
     938>>> w.render('state', 'AG')
     939u'<select name="state">\n<option value="AG" selected="selected">Aargau</option>\n<option value="AI">Appenzell Innerrhoden</option>\n<option value="AR">Appenzell Ausserrhoden</option>\n<option value="BS">Basel-Stadt</option>\n<option value="BL">Basel-Land</option>\n<option value="BE">Berne</option>\n<option value="FR">Fribourg</option>\n<option value="GE">Geneva</option>\n<option value="GL">Glarus</option>\n<option value="GR">Graubuenden</option>\n<option value="JU">Jura</option>\n<option value="LU">Lucerne</option>\n<option value="NE">Neuchatel</option>\n<option value="NW">Nidwalden</option>\n<option value="OW">Obwalden</option>\n<option value="SH">Schaffhausen</option>\n<option value="SZ">Schwyz</option>\n<option value="SO">Solothurn</option>\n<option value="SG">St. Gallen</option>\n<option value="TG">Thurgau</option>\n<option value="TI">Ticino</option>\n<option value="UR">Uri</option>\n<option value="VS">Valais</option>\n<option value="VD">Vaud</option>\n<option value="ZG">Zug</option>\n<option value="ZH">Zurich</option>\n</select>'
     940=======
     941
    886942## AUPostCodeField ##########################################################
    887943
    888944A field that accepts a four digit Australian post code.
     
    10121068<option value="VIC">Victoria</option>
    10131069<option value="WA">Western Australia</option>
    10141070</select>
     1071>>>>>>> .r4955
    10151072"""
Back to Top