Ticket #9289: django_localflavor_se_r3.diff

File django_localflavor_se_r3.diff, 23.5 KB (added by Andreas Pelme, 16 years ago)

Updated patch which works when the checksum digit is 0, tests updated.

  • AUTHORS

    diff --git a/AUTHORS b/AUTHORS
    index 7bbec38..558f0ff 100644
    a b answer newbie questions, and generally made Django that much better:  
    297297    Carlos Eduardo de Paula <carlosedp@gmail.com>
    298298    pavithran s <pavithran.s@gmail.com>
    299299    Barry Pederson <bp@barryp.org>
     300    Andreas Pelme <andreas@pelme.se>
    300301    permonik@mesias.brnonet.cz
    301302    peter@mymart.com
    302303    pgross@thoughtworks.com
  • new file django/contrib/localflavor/se/forms.py

    diff --git a/django/contrib/localflavor/se/__init__.py b/django/contrib/localflavor/se/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/django/contrib/localflavor/se/forms.py b/django/contrib/localflavor/se/forms.py
    new file mode 100644
    index 0000000..84233c8
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3Swedish specific Form helpers
     4"""
     5
     6from django import forms
     7from django.utils.translation import ugettext_lazy as _
     8from django.forms.fields import EMPTY_VALUES
     9
     10from utils import *
     11
     12__all__ = ('SECountySelect', 'SEOrganisationNumberField', 'SEPersonalIdentityNumberField', 'SEPostalCodeField')
     13
     14class SECountySelect(forms.Select):
     15    """
     16    A Select form widget that uses a list of the Swedish counties (län)
     17    as its choices.
     18
     19    The cleaned value is the official county code -- see
     20    http://en.wikipedia.org/wiki/Counties_of_Sweden for a list.
     21    """
     22
     23    def __init__(self, attrs=None):
     24        from se_counties import COUNTY_CHOICES
     25        super(SECountySelect, self).__init__(attrs=attrs, choices=COUNTY_CHOICES)
     26
     27
     28class SEOrganisationNumberField(forms.CharField):
     29    """
     30    A form field that validates input as a Swedish organisation number
     31    (organisationsnummer).
     32
     33    This fields accepts the same input as SEPersonalIdentityField (for
     34    sole proprietorships (enskild firma)). However, co-ordination numbers are
     35    not accepted.
     36
     37    It also accepts ordinary Swedish organisation numbers with the format
     38    NNNNNNNNNN.
     39
     40    The return value will be YYYYMMDDXXXX for sole proprietors, and NNNNNNNNNN
     41    for other organisations.
     42    """
     43
     44    default_error_messages = {
     45        'invalid': _('Enter a valid Swedish organisation number.'),
     46    }
     47
     48    def clean(self, value):
     49        value = super(SEOrganisationNumberField, self).clean(value)
     50       
     51        if value in EMPTY_VALUES:
     52            return u''
     53       
     54        match = SWEDISH_ID_NUMBER.match(value)
     55        if not match:
     56            raise forms.ValidationError(self.error_messages['invalid'])
     57
     58        gd = match.groupdict()
     59       
     60        # Compare the calculated value with the checksum
     61        if id_number_checksum(gd) != int(gd['checksum']):
     62            raise forms.ValidationError(self.error_messages['invalid'])
     63       
     64        # First: check if this is a real organisation_number
     65        if valid_organisation(gd):
     66            return format_organisation_number(gd)
     67
     68        # Is this a single properitor (enskild firma)?
     69        try:
     70            birth_day = validate_id_birthday(gd, False)
     71            return format_personal_id_number(birth_day, gd)
     72        except ValueError:
     73            raise forms.ValidationError(self.error_messages['invalid'])
     74
     75
     76class SEPersonalIdentityNumberField(forms.CharField):
     77    """
     78    A form field that validates input as a Swedish personal identity number
     79    (personnummer).
     80
     81    The correct formats are YYYYMMDD-XXXX, YYYYMMDDXXXX, YYMMDD-XXXX,
     82    YYMMDDXXXX and YYMMDD+XXXX.
     83
     84    + indicates that the person is older than 100 years, which will be
     85    taken into consideration when the date is validated.
     86   
     87    The checksum will be calculated and checked. The birth date is checked
     88    to be a valid date.
     89
     90    By default, co-ordination numbers (samordningsnummer) will be accepted.
     91    To only allow real personal identity numbers, pass the keyword argument
     92    coordination_number=False to the constructor.
     93
     94    The cleaned value will always have the format YYYYMMDDXXXX.
     95    """
     96
     97    def __init__(self, *args, **kwargs):
     98        self.coordination_number = kwargs.pop('coordination_number', True)
     99        super(SEPersonalIdentityNumberField, self).__init__(*args, **kwargs)
     100
     101    default_error_messages = {
     102        'invalid': _('Enter a valid Swedish personal identity number.'),
     103        'coordination_number': _('Co-ordination numbers are not allowed.'),
     104    }
     105
     106    def clean(self, value):
     107        value = super(SEPersonalIdentityNumberField, self).clean(value)
     108
     109        if value in EMPTY_VALUES:
     110            return u''
     111 
     112        match = SWEDISH_ID_NUMBER.match(value)
     113        if match is None:
     114            raise forms.ValidationError(self.error_messages['invalid'])
     115
     116        gd = match.groupdict()
     117 
     118        # compare the calculated value with the checksum
     119        if id_number_checksum(gd) != int(gd['checksum']):
     120            raise forms.ValidationError(self.error_messages['invalid'])
     121
     122        # check for valid birthday
     123        try:
     124            birth_day = validate_id_birthday(gd)
     125        except ValueError:
     126            raise forms.ValidationError(self.error_messages['invalid'])
     127
     128        # make sure that co-ordination numbers do not pass if not allowed
     129        if not self.coordination_number and int(gd['day']) > 60:
     130            raise forms.ValidationError(self.error_messages['coordination_number'])
     131 
     132        return format_personal_id_number(birth_day, gd)
     133
     134
     135class SEPostalCodeField(forms.RegexField):
     136    """
     137    A form field that validates input as a Swedish postal code (postnummer).
     138    Valid codes consist of five digits (XXXXX). The number can optionally be
     139    formatted with a space after the third digit (XXX XX).
     140
     141    The cleaned value will never contain the space.
     142    """
     143
     144    default_error_messages = {
     145        'invalid': _('Enter a Swedish postal code in the format XXXXX.'),
     146    }
     147
     148    def __init__(self, *args, **kwargs):
     149        super(SEPostalCodeField, self).__init__(SE_POSTAL_CODE, *args, **kwargs)
     150
     151    def clean(self, value):
     152        return super(SEPostalCodeField, self).clean(value).replace(' ', '')
     153
  • new file django/contrib/localflavor/se/se_counties.py

    diff --git a/django/contrib/localflavor/se/se_counties.py b/django/contrib/localflavor/se/se_counties.py
    new file mode 100644
    index 0000000..0944064
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3A alphabetical list of Swedish counties, sorted by county codes.
     4
     5
     6http://en.wikipedia.org/wiki/Counties_of_Sweden
     7
     8This exists in this standalone file so that it's only imported into memory
     9when explicitly needed.
     10
     11"""
     12
     13from django.utils.translation import ugettext_lazy as _
     14
     15COUNTY_CHOICES = (
     16    ('AB', _(u'Stockholm County')),
     17    ('AC', _(u'Västerbotten County')),
     18    ('BD', _(u'Norrbotten County')),
     19    ('C', _(u'Uppsala County')),
     20    ('D', _(u'Södermanland County')),
     21    ('E', _(u'Östergötland County')),
     22    ('F', _(u'Jönköping County')),
     23    ('G', _(u'Kronoberg County')),
     24    ('H', _(u'Kalmar County')),
     25    ('I', _(u'Gotland County')),
     26    ('K', _(u'Blekinge County')),
     27    ('M', _(u'Skåne County')),
     28    ('N', _(u'Halland County')),
     29    ('O', _(u'Västra Götaland County')),
     30    ('S', _(u'Värmland County')),
     31    ('T', _(u'Örebro County')),
     32    ('U', _(u'Västmanland County')),
     33    ('W', _(u'Dalarna County')),
     34    ('X', _(u'Gävleborg County')),
     35    ('Y', _(u'Västernorrland County')),
     36    ('Z', _(u'Jämtland County')),
     37)
  • new file django/contrib/localflavor/se/utils.py

    diff --git a/django/contrib/localflavor/se/utils.py b/django/contrib/localflavor/se/utils.py
    new file mode 100644
    index 0000000..36b22d6
    - +  
     1import re
     2import datetime
     3
     4SWEDISH_ID_NUMBER = re.compile(r'^(?P<century>\d{2})?(?P<year>\d{2})(?P<month>\d{2})(?P<day>\d{2})(?P<sign>[\-+])?(?P<serial>\d{3})(?P<checksum>\d)$')
     5SE_POSTAL_CODE = re.compile(r'^[1-9]\d{2} ?\d{2}$')
     6
     7def id_number_checksum(gd):
     8    """
     9    Calculates a Swedish id number checksum, using the
     10    "Luhn"-algoritm
     11    """
     12
     13    n = s = 0
     14    for c in (gd['year'] + gd['month'] + gd['day'] + gd['serial']):
     15        tmp = ((n % 2) and 1 or 2) * int(c)
     16
     17        if tmp > 9:
     18            tmp = sum([int(i) for i in str(tmp)])
     19 
     20        s += tmp
     21        n += 1
     22
     23    if (s % 10) == 0:
     24        return 0
     25
     26    return (((s / 10) + 1) * 10) - s
     27
     28def validate_id_birthday(gd, fix_coordination_number_day=True):
     29    """
     30    Validates the birth_day and returns the datetime.date object for
     31    the birth_day.
     32
     33    If the date is an invalid birth day, a ValueError will be raised.
     34    """
     35   
     36    today = datetime.date.today()
     37   
     38    day = int(gd['day'])
     39    if fix_coordination_number_day and day > 60:
     40        day -= 60
     41
     42    if gd['century'] is None:
     43
     44        # The century was not specified, and need to be calculated from todays date
     45        current_year = today.year
     46        year = int(today.strftime('%Y')) - int(today.strftime('%y')) + int(gd['year'])
     47   
     48        if ('%s%s%02d' % (gd['year'], gd['month'], day)) > today.strftime('%y%m%d'):
     49            year -= 100
     50
     51        # If the person is older than 100 years
     52        if gd['sign'] == '+':
     53            year -= 100
     54    else:
     55        year = int(gd['century'] + gd['year'])
     56       
     57        # Make sure the year is valid
     58        # There are no swedish personal identity numbers where year < 1800
     59        if year < 1800:
     60            raise ValueError
     61
     62    # ValueError will be raise for invalid dates
     63    birth_day = datetime.date(year, int(gd['month']), day)
     64   
     65    # birth_day must not be in the future
     66    if birth_day > today:
     67        raise ValueError
     68   
     69    return birth_day
     70
     71def format_personal_id_number(birth_day, gd):
     72    # birth_day.strftime cannot be used, since it does not support dates < 1900
     73    return unicode(str(birth_day.year) + gd['month'] + gd['day'] + gd['serial'] + gd['checksum'])
     74
     75def format_organisation_number(gd):
     76    if gd['century'] is None:
     77        century = ''
     78    else:
     79        century = gd['century']
     80
     81    return unicode(century + gd['year'] + gd['month'] + gd['day'] + gd['serial'] + gd['checksum'])
     82
     83def valid_organisation(gd):
     84    return gd['century'] in (None, 16) and \
     85        int(gd['month']) >= 20 and \
     86        gd['sign'] in (None, '-') and \
     87        gd['year'][0] in ('2', '5', '7', '8', '9') # group identifier
     88
  • docs/ref/contrib/localflavor.txt

    diff --git a/docs/ref/contrib/localflavor.txt b/docs/ref/contrib/localflavor.txt
    index 6771efc..93c8f42 100644
    a b Countries currently supported by :mod:`~django.contrib.localflavor` are:  
    6060    * Slovakia_
    6161    * `South Africa`_
    6262    * Spain_
     63    * Sweden_
    6364    * Switzerland_
    6465    * `United Kingdom`_
    6566    * `United States of America`_
    Here's an example of how to use them::  
    99100.. _Slovakia: `Slovakia (sk)`_
    100101.. _South Africa: `South Africa (za)`_
    101102.. _Spain: `Spain (es)`_
     103.. _Sweden: `Sweden (se)`_
    102104.. _Switzerland: `Switzerland (ch)`_
    103105.. _United Kingdom: `United Kingdom (uk)`_
    104106.. _United States of America: `United States of America (us)`_
    Spain (``es``)  
    573575
    574576    A ``Select`` widget that uses a list of Spanish regions as its choices.
    575577
     578Sweden (``se``)
     579===============
     580
     581.. class:: se.forms.SECountySelect
     582
     583    A Select form widget that uses a list of the Swedish counties (län)
     584    as its choices.
     585
     586    The cleaned value is the official county code -- see
     587    http://en.wikipedia.org/wiki/Counties_of_Sweden for a list.
     588
     589.. class:: se.forms.SEOrganisationNumber
     590
     591    A form field that validates input as a Swedish organisation number
     592    (organisationsnummer).
     593
     594    This fields accepts the same input as SEPersonalIdentityField (for
     595    sole proprietorships (enskild firma)). However, co-ordination numbers are
     596    not accepted.
     597
     598    It also accepts ordinary Swedish organisation numbers with the format
     599    NNNNNNNNNN.
     600
     601    The return value will be YYYYMMDDXXXX for sole proprietors, and NNNNNNNNNN
     602    for other organisations.
     603
     604.. class:: se.forms.SEPersonalIdentityNumber
     605
     606    A form field that validates input as a Swedish personal identity number
     607    (personnummer).
     608
     609    The correct formats are YYYYMMDD-XXXX, YYYYMMDDXXXX, YYMMDD-XXXX,
     610    YYMMDDXXXX and YYMMDD+XXXX.
     611
     612    \+ indicates that the person is older than 100 years, which will be
     613    taken into consideration when the date is validated.
     614   
     615    The checksum will be calculated and checked. The birth date is checked
     616    to be a valid date.
     617
     618    By default, co-ordination numbers (samordningsnummer) will be accepted.
     619    To only allow real personal identity numbers, pass the keyword argument
     620    coordination_number=False to the constructor.
     621
     622    The cleaned value will always have the format YYYYMMDDXXXX.
     623
     624.. class:: se.forms.SEPostalCodeField
     625
     626    A form field that validates input as a Swedish postal code (postnummer).
     627    Valid codes consist of five digits (XXXXX). The number can optionally be
     628    formatted with a space after the third digit (XXX XX).
     629
     630    The cleaned value will never contain the space.
     631
    576632Switzerland (``ch``)
    577633====================
    578634
  • new file tests/regressiontests/forms/localflavor/se.py

    diff --git a/tests/regressiontests/forms/localflavor/se.py b/tests/regressiontests/forms/localflavor/se.py
    new file mode 100644
    index 0000000..e73b1e3
    - +  
     1# -*- coding: utf-8 -*-
     2# Tests for the contrib/localflavor/se form fields.
     3
     4tests = r"""
     5# Monkey-patch datetime.date
     6>>> import datetime
     7>>> class MockDate(datetime.date):
     8...     def today(cls):
     9...         return datetime.date(2008, 5, 14)
     10...     today = classmethod(today)
     11...
     12>>> olddate = datetime.date
     13>>> datetime.date = MockDate
     14>>> datetime.date.today()
     15MockDate(2008, 5, 14)
     16
     17
     18# SECountySelect #####################################################
     19>>> from django.contrib.localflavor.se.forms import SECountySelect
     20
     21>>> w = SECountySelect()
     22>>> w.render('swedish_county', 'E')
     23u'<select name="swedish_county">\n<option value="AB">Stockholm County</option>\n<option value="AC">V\xe4sterbotten County</option>\n<option value="BD">Norrbotten County</option>\n<option value="C">Uppsala County</option>\n<option value="D">S\xf6dermanland County</option>\n<option value="E" selected="selected">\xd6sterg\xf6tland County</option>\n<option value="F">J\xf6nk\xf6ping County</option>\n<option value="G">Kronoberg County</option>\n<option value="H">Kalmar County</option>\n<option value="I">Gotland County</option>\n<option value="K">Blekinge County</option>\n<option value="M">Sk\xe5ne County</option>\n<option value="N">Halland County</option>\n<option value="O">V\xe4stra G\xf6taland County</option>\n<option value="S">V\xe4rmland County</option>\n<option value="T">\xd6rebro County</option>\n<option value="U">V\xe4stmanland County</option>\n<option value="W">Dalarna County</option>\n<option value="X">G\xe4vleborg County</option>\n<option value="Y">V\xe4sternorrland County</option>\n<option value="Z">J\xe4mtland County</option>\n</select>'
     24
     25
     26# SEOrganisationNumberField #######################################
     27
     28>>> from django.contrib.localflavor.se.forms import SEOrganisationNumberField
     29
     30>>> f = SEOrganisationNumberField()
     31
     32# Ordinary personal identity numbers for sole proprietors
     33# The same rules as for SEPersonalIdentityField applies here
     34>>> f.clean('870512-1989')
     35u'198705121989'
     36>>> f.clean('19870512-1989')
     37u'198705121989'
     38>>> f.clean('870512-2128')
     39u'198705122128'
     40>>> f.clean('081015-6315')
     41u'190810156315'
     42>>> f.clean('081015+6315')
     43u'180810156315'
     44>>> f.clean('0810156315')
     45u'190810156315'
     46
     47>>> f.clean('081015 6315')
     48Traceback (most recent call last):
     49...
     50ValidationError: [u'Enter a valid Swedish organisation number.']
     51>>> f.clean('950231-4496')
     52Traceback (most recent call last):
     53...
     54ValidationError: [u'Enter a valid Swedish organisation number.']
     55>>> f.clean('6914104499')
     56Traceback (most recent call last):
     57...
     58ValidationError: [u'Enter a valid Swedish organisation number.']
     59>>> f.clean('950d314496')
     60Traceback (most recent call last):
     61...
     62ValidationError: [u'Enter a valid Swedish organisation number.']
     63>>> f.clean('invalid!!!')
     64Traceback (most recent call last):
     65...
     66ValidationError: [u'Enter a valid Swedish organisation number.']
     67>>> f.clean('870514-1111')
     68Traceback (most recent call last):
     69...
     70ValidationError: [u'Enter a valid Swedish organisation number.']
     71
     72
     73# Empty values
     74>>> f.clean('')
     75Traceback (most recent call last):
     76...
     77ValidationError: [u'This field is required.']
     78
     79>>> f.clean(None)
     80Traceback (most recent call last):
     81...
     82ValidationError: [u'This field is required.']
     83
     84# Co-ordination number checking
     85# Co-ordination numbers are not valid organisation numbers
     86>>> f.clean('870574-1315')
     87Traceback (most recent call last):
     88...
     89ValidationError: [u'Enter a valid Swedish organisation number.']
     90
     91>>> f.clean('870573-1311')
     92Traceback (most recent call last):
     93...
     94ValidationError: [u'Enter a valid Swedish organisation number.']
     95
     96# Test some different organisation numbers
     97>>> f.clean('556074-7569') # IKEA Linköping
     98u'5560747569'
     99
     100>>> f.clean('556074-3089') # Volvo Personvagnar
     101u'5560743089'
     102
     103>>> f.clean('822001-5476') # LJS (organisation)
     104u'8220015476'
     105
     106>>> f.clean('8220015476') # LJS (organisation)
     107u'8220015476'
     108
     109>>> f.clean('2120000449') # Katedralskolan Linköping (school)
     110u'2120000449'
     111
     112# Faux organisation number, which tests that the checksum can be 0
     113>>> f.clean('232518-5060')
     114u'2325185060'
     115
     116>>> f.clean('556074+3089') # Volvo Personvagnar, bad format
     117Traceback (most recent call last):
     118...
     119ValidationError: [u'Enter a valid Swedish organisation number.']
     120
     121
     122# Invalid checksum
     123>>> f.clean('2120000441')
     124Traceback (most recent call last):
     125...
     126ValidationError: [u'Enter a valid Swedish organisation number.']
     127
     128# Valid checksum but invalid organisation type
     129f.clean('1120000441')
     130Traceback (most recent call last):
     131...
     132ValidationError: [u'Enter a valid Swedish organisation number.']
     133
     134# Empty values with required=False
     135>>> f = SEOrganisationNumberField(required=False)
     136
     137>>> f.clean(None)
     138u''
     139
     140>>> f.clean('')
     141u''
     142
     143
     144# SEPersonalIdentityNumberField #######################################
     145
     146>>> from django.contrib.localflavor.se.forms import SEPersonalIdentityNumberField
     147
     148>>> f = SEPersonalIdentityNumberField()
     149
     150# Valid id numbers
     151>>> f.clean('870512-1989')
     152u'198705121989'
     153
     154>>> f.clean('870512-2128')
     155u'198705122128'
     156
     157>>> f.clean('19870512-1989')
     158u'198705121989'
     159
     160>>> f.clean('198705121989')
     161u'198705121989'
     162
     163>>> f.clean('081015-6315')
     164u'190810156315'
     165
     166>>> f.clean('0810156315')
     167u'190810156315'
     168
     169# This is a "special-case" in the checksum calculation,
     170# where the sum is divisible by 10 (the checksum digit == 0)
     171>>> f.clean('8705141060')
     172u'198705141060'
     173
     174# + means that the person is older than 100 years
     175>>> f.clean('081015+6315')
     176u'180810156315'
     177
     178# Bogus values
     179>>> f.clean('081015 6315')
     180Traceback (most recent call last):
     181...
     182ValidationError: [u'Enter a valid Swedish personal identity number.']
     183
     184>>> f.clean('950d314496')
     185Traceback (most recent call last):
     186...
     187ValidationError: [u'Enter a valid Swedish personal identity number.']
     188
     189>>> f.clean('invalid!!!')
     190Traceback (most recent call last):
     191...
     192ValidationError: [u'Enter a valid Swedish personal identity number.']
     193
     194
     195# Invalid dates
     196
     197# February 31st does not exist
     198>>> f.clean('950231-4496')
     199Traceback (most recent call last):
     200...
     201ValidationError: [u'Enter a valid Swedish personal identity number.']
     202
     203# Month 14 does not exist
     204>>> f.clean('6914104499')
     205Traceback (most recent call last):
     206...
     207ValidationError: [u'Enter a valid Swedish personal identity number.']
     208
     209# There are no Swedish personal id numbers where year < 1800
     210>>> f.clean('17430309-7135')
     211Traceback (most recent call last):
     212...
     213ValidationError: [u'Enter a valid Swedish personal identity number.']
     214
     215# Invalid checksum
     216>>> f.clean('870514-1111')
     217Traceback (most recent call last):
     218...
     219ValidationError: [u'Enter a valid Swedish personal identity number.']
     220
     221# Empty values
     222>>> f.clean('')
     223Traceback (most recent call last):
     224...
     225ValidationError: [u'This field is required.']
     226
     227>>> f.clean(None)
     228Traceback (most recent call last):
     229...
     230ValidationError: [u'This field is required.']
     231
     232# Co-ordination number checking
     233>>> f.clean('870574-1315')
     234u'198705741315'
     235
     236>>> f.clean('870574+1315')
     237u'188705741315'
     238
     239>>> f.clean('198705741315')
     240u'198705741315'
     241
     242# Co-ordination number with bad checksum
     243>>> f.clean('870573-1311')
     244Traceback (most recent call last):
     245...
     246ValidationError: [u'Enter a valid Swedish personal identity number.']
     247
     248
     249# Check valid co-ordination numbers, that should not be accepted
     250# because of coordination_number=False
     251>>> f = SEPersonalIdentityNumberField(coordination_number=False)
     252
     253>>> f.clean('870574-1315')
     254Traceback (most recent call last):
     255...
     256ValidationError: [u'Co-ordination numbers are not allowed.']
     257
     258>>> f.clean('870574+1315')
     259Traceback (most recent call last):
     260...
     261ValidationError: [u'Co-ordination numbers are not allowed.']
     262
     263>>> f.clean('8705741315')
     264Traceback (most recent call last):
     265...
     266ValidationError: [u'Co-ordination numbers are not allowed.']
     267
     268# Invalid co-ordination numbers should be treated as invalid, and not
     269# as co-ordination numbers
     270>>> f.clean('870573-1311')
     271Traceback (most recent call last):
     272...
     273ValidationError: [u'Enter a valid Swedish personal identity number.']
     274
     275# Empty values with required=False
     276>>> f = SEPersonalIdentityNumberField(required=False)
     277
     278>>> f.clean(None)
     279u''
     280
     281>>> f.clean('')
     282u''
     283
     284# SEPostalCodeField ###############################################
     285>>> from django.contrib.localflavor.se.forms import SEPostalCodeField
     286>>> f = SEPostalCodeField()
     287>>>
     288Postal codes can have spaces
     289>>> f.clean('589 37')
     290u'58937'
     291
     292... but the dont have to
     293>>> f.clean('58937')
     294u'58937'
     295>>> f.clean('abcasfassadf')
     296Traceback (most recent call last):
     297...
     298ValidationError: [u'Enter a Swedish postal code in the format XXXXX.']
     299
     300# Only one space is allowed for separation
     301>>> f.clean('589  37')
     302Traceback (most recent call last):
     303...
     304ValidationError: [u'Enter a Swedish postal code in the format XXXXX.']
     305
     306# The postal code must not start with 0
     307>>> f.clean('01234')
     308Traceback (most recent call last):
     309...
     310ValidationError: [u'Enter a Swedish postal code in the format XXXXX.']
     311
     312# Empty values
     313>>> f.clean('')
     314Traceback (most recent call last):
     315...
     316ValidationError: [u'This field is required.']
     317
     318>>> f.clean(None)
     319Traceback (most recent call last):
     320...
     321ValidationError: [u'This field is required.']
     322
     323# Empty values, required=False
     324>>> f = SEPostalCodeField(required=False)
     325>>> f.clean('')
     326u''
     327>>> f.clean(None)
     328u''
     329
     330# Revert the monkey patching
     331>>> datetime.date = olddate
     332
     333"""
  • tests/regressiontests/forms/tests.py

    diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
    index 6a8b017..f930003 100644
    a b from localflavor.jp import tests as localflavor_jp_tests  
    2121from localflavor.nl import tests as localflavor_nl_tests
    2222from localflavor.pl import tests as localflavor_pl_tests
    2323from localflavor.ro import tests as localflavor_ro_tests
     24from localflavor.se import tests as localflavor_se_tests
    2425from localflavor.sk import tests as localflavor_sk_tests
    2526from localflavor.uk import tests as localflavor_uk_tests
    2627from localflavor.us import tests as localflavor_us_tests
    __test__ = {  
    5455    'localflavor_nl_tests': localflavor_nl_tests,
    5556    'localflavor_pl_tests': localflavor_pl_tests,
    5657    'localflavor_ro_tests': localflavor_ro_tests,
     58    'localflavor_se_tests': localflavor_se_tests,
    5759    'localflavor_sk_tests': localflavor_sk_tests,
    5860    'localflavor_uk_tests': localflavor_uk_tests,
    5961    'localflavor_us_tests': localflavor_us_tests,
Back to Top