Ticket #16497: mx_localflavors.diff

File mx_localflavors.diff, 26.2 KB (added by Andrés Torres, 13 years ago)

Patch for the lastest trunk - July 28, 2011

  • AUTHORS

    diff --git a/AUTHORS b/AUTHORS
    index 31a3300..d3a1e38 100644
    a b answer newbie questions, and generally made Django that much better:  
    540540    Gasper Zejn <zejn@kiberpipa.org>
    541541    Jarek Zgoda <jarek.zgoda@gmail.com>
    542542    Cheng Zhang
     543    Gerardo Orozco <gerardo.orozco.mosqueda@gmail.com>
     544    Andrés Torres Marroquín <andres.torres.marroquin@gmail.com>
    543545
    544546A big THANK YOU goes to:
    545547
  • django/contrib/localflavor/mx/forms.py

    diff --git a/django/contrib/localflavor/mx/forms.py b/django/contrib/localflavor/mx/forms.py
    index 9581937..ee1530b 100644
    a b  
     1# -*- coding: utf-8 -*-
    12"""
    23Mexican-specific form helpers.
    34"""
    45
    5 from django.forms.fields import Select
     6from django.forms import ValidationError
     7from django.forms.fields import Select, RegexField, CharField
     8from django.utils.translation import ugettext_lazy as _
     9from django.core.validators import EMPTY_VALUES
     10from django.contrib.localflavor.mx.mx_states import STATE_CHOICES
     11import re
     12
     13DATE_RE = r'\d{2}((01|03|05|07|08|10|12)(0[1-9]|[12]\d|3[01])|02(0[1-9]|[12]\d)|(04|06|09|11)(0[1-9]|[12]\d|30))'
     14
     15"""
     16This is the list of inconvenient words according to the `Anexo IV` of the
     17document described in the next link:
     18    http://www.sisi.org.mx/jspsi/documentos/2005/seguimiento/06101/0610100162005_065.doc
     19"""
     20
     21RFC_INCONVENIENT_WORDS = [
     22    u'BUEI', u'BUEY', u'CACA', u'CACO', u'CAGA', u'CAGO', u'CAKA', u'CAKO',
     23    u'COGE', u'COJA', u'COJE', u'COJI', u'COJO', u'CULO', u'FETO', u'GUEY',
     24    u'JOTO', u'KACA', u'KACO', u'KAGA', u'KAGO', u'KOGE', u'KOJO', u'KAKA',
     25    u'KULO', u'MAME', u'MAMO', u'MEAR', u'MEAS', u'MEON', u'MION', u'MOCO',
     26    u'MULA', u'PEDA', u'PEDO', u'PENE', u'PUTA', u'PUTO', u'QULO', u'RATA',
     27    u'RUIN'
     28]
     29
     30"""
     31This is the list of inconvenient words according to the `Anexo 2` of the
     32document described in the next link:
     33    http://portal.veracruz.gob.mx/pls/portal/url/ITEM/444112558A57C6E0E040A8C02E00695C
     34"""
     35CURP_INCONVENIENT_WORDS = [
     36   u'BACA', u'BAKA', u'BUEI', u'BUEY', u'CACA', u'CACO', u'CAGA', u'CAGO',
     37   u'CAKA', u'CAKO', u'COGE', u'COGI', u'COJA', u'COJE', u'COJI', u'COJO',
     38   u'COLA', u'CULO', u'FALO', u'FETO', u'GETA', u'GUEI', u'GUEY', u'JETA',
     39   u'JOTO', u'KACA', u'KACO', u'KAGA', u'KAGO', u'KAKA', u'KAKO', u'KOGE',
     40   u'KOGI', u'KOJA', u'KOJE', u'KOJI', u'KOJO', u'KOLA', u'KULO', u'LILO',
     41   u'LOCA', u'LOCO', u'LOKA', u'LOKO', u'MAME', u'MAMO', u'MEAR', u'MEAS',
     42   u'MEON', u'MIAR', u'MION', u'MOCO', u'MOKO', u'MULA', u'MULO', u'NACA',
     43   u'NACO', u'PEDA', u'PEDO', u'PENE', u'PIPI', u'PITO', u'POPO', u'PUTA',
     44   u'PUTO', u'QULO', u'RATA', u'ROBA', u'ROBE', u'ROBO', u'RUIN', u'SENO',
     45   u'TETA', u'VACA', u'VAGA', u'VAGO', u'VAKA', u'VUEI', u'VUEY', u'WUEI',
     46   u'WUEY'
     47]
    648
    749class MXStateSelect(Select):
    850    """
    951    A Select widget that uses a list of Mexican states as its choices.
    1052    """
    1153    def __init__(self, attrs=None):
    12         from mx_states import STATE_CHOICES
    1354        super(MXStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
    1455
     56class MXZipCodeField(RegexField):
     57    """
     58    A form field that accepts a Mexican Zip Code.
     59
     60    More info about this:
     61        http://en.wikipedia.org/wiki/List_of_postal_codes_in_Mexico
     62    """
     63    default_error_messages = {
     64        'invalid': _(u'Enter a valid zip code in the format XXXXX.'),
     65    }
     66
     67    def __init__(self, *args, **kwargs):
     68        zip_code_re = ur'^(0[1-9]|[1][0-6]|[2-9]\d)(\d{3})$'
     69        super(MXZipCodeField, self).__init__(zip_code_re, *args, **kwargs)
     70
     71class MXRFCField(RegexField):
     72    """
     73    A form field that validates a Mexican *Registro Federal de Contribuyentes* for
     74    either `Persona física` or `Persona moral`.
     75
     76    The Persona física RFC string is integrated by a juxtaposition of characters
     77    following the next pattern:
     78
     79        =====  ======  ===========================================
     80        Index  Format  Accepted Characters
     81        =====  ======  ===========================================
     82        1      X       Any letter
     83        2      X       Any vowel
     84        3-4    XX      Any letter
     85        5-10   YYMMDD  Any valid date
     86        11-12  XX      Any letter or number between 0 and 9
     87        13     X       Any digit between 0 and 9 or the letter *A*
     88        =====  ======  ===========================================
     89
     90    The Persona moral RFC string is integrated by a juxtaposition of characters
     91    following the next pattern:
     92
     93        =====  ======  ============================================
     94        Index  Format  Accepted Characters
     95        =====  ======  ============================================
     96        1-3    XXX     Any letter including *&* and *Ñ* chars
     97        4-9    YYMMDD  Any valid date
     98        10-11  XX      Any letter or number between 0 and 9
     99        12     X       Any number between 0 and 9 or the letter *A*
     100        =====  ======  ============================================
     101
     102    More info about this:
     103        http://es.wikipedia.org/wiki/Registro_Federal_de_Contribuyentes_(M%C3%A9xico)
     104    """
     105    default_error_messages = {
     106        'invalid': _(u'Enter a valid RFC.'),
     107        'invalid_checksum': _(u'Invalid checksum for RFC.'),
     108    }
     109
     110    def __init__(self, min_length=9, max_length=13, *args, **kwargs):
     111        rfc_re = re.compile(ur'^([A-Z&Ññ]{3}|[A-Z][AEIOU][A-Z]{2})%s([A-Z0-9]{2}[0-9A])?$' % DATE_RE,
     112                            re.IGNORECASE)
     113        super(MXRFCField, self).__init__(rfc_re, min_length=min_length,
     114                                         max_length=max_length, *args, **kwargs)
     115
     116    def clean(self, value):
     117        value = super(MXRFCField, self).clean(value)
     118        if value in EMPTY_VALUES:
     119            return u''
     120        value = value.upper()
     121        if self._has_homoclave(value):
     122            if not value[-1] == self._checksum(value[:-1]):
     123                raise ValidationError(self.default_error_messages['invalid_checksum'])
     124        if self._has_inconvenient_word(value):
     125            raise ValidationError(self.default_error_messages['invalid'])
     126        return value
     127
     128    def _has_homoclave(self, rfc):
     129        """
     130        This check is done due to the existance of RFCs without a *homoclave*
     131        since the current algorithm to calculate it had not been created for
     132        the first RFCs ever in Mexico.
     133        """
     134        rfc_without_homoclave_re = re.compile(ur'^[A-Z&Ññ]{3,4}%s$' % DATE_RE,
     135                                              re.IGNORECASE)
     136        return not rfc_without_homoclave_re.match(rfc)
     137
     138    def _checksum(self, rfc):
     139        """
     140        More info about this procedure:
     141            www.sisi.org.mx/jspsi/documentos/2005/seguimiento/06101/0610100162005_065.doc
     142        """
     143        chars = u'0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ-Ñ'
     144        if len(rfc) is 11:
     145            rfc = '-' + rfc
     146
     147        sum_ = sum(i * chars.index(c) for i, c in zip(reversed(xrange(14)), rfc))
     148        checksum = 11 - sum_ % 11
     149
     150        if checksum == 10:
     151            return u'A'
     152        elif checksum == 11:
     153            return u'0'
     154        else:
     155            return unicode(checksum)
     156
     157    def _has_inconvenient_word(self, rfc):
     158        first_four = rfc[:4]
     159        return first_four in RFC_INCONVENIENT_WORDS
     160
     161class MXCURPField(RegexField):
     162    """
     163    A field that validates a Mexican Clave Única de Registro de Población.
     164
     165    The CURP is integrated by a juxtaposition of characters following the next
     166    pattern:
     167
     168        =====  ======  ===================================================
     169        Index  Format  Accepted Characters
     170        =====  ======  ===================================================
     171        1      X       Any letter
     172        2      X       Any vowel
     173        3-4    XX      Any letter
     174        5-10   YYMMDD  Any valid date
     175        11     X       Either `H` or `M`, depending on the person's gender
     176        12-13  XX      Any valid acronym for a state in Mexico
     177        14-16  XXX     Any consonant
     178        17     X       Any number between 0 and 9 or any letter
     179        18     X       Any number between 0 and 9
     180        =====  ======  ===================================================
     181
     182    More info about this:
     183        http://www.condusef.gob.mx/index.php/clave-unica-de-registro-de-poblacion-curp
     184    """
     185    default_error_messages = {
     186        'invalid': _('Enter a valid CURP.'),
     187        'invalid_checksum': _(u'Invalid checksum for CURP.'),
     188    }
     189
     190    def __init__(self, min_length=18, max_length=18, *args, **kwargs):
     191        states_re = r'(AS|BC|BS|CC|CL|CM|CS|CH|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS|NE)'
     192        consonants_re = r'[B-DF-HJ-NP-TV-Z]'
     193        curp_re = ur'^[A-Z][AEIOU][A-Z]{2}%s[HM]%s%s{3}[0-9A-Z]\d$' % (DATE_RE, states_re,
     194                                                      consonants_re)
     195        curp_re = re.compile(curp_re, re.IGNORECASE)
     196        super(MXCURPField, self).__init__(curp_re, min_length=min_length,
     197                                          max_length=max_length, *args, **kwargs)
     198
     199    def clean(self, value):
     200        value = super(MXCURPField, self).clean(value)
     201        if value in EMPTY_VALUES:
     202            return u''
     203        value = value.upper()
     204        if value[-1] != self._checksum(value[:-1]):
     205            raise ValidationError(self.default_error_messages['invalid_checksum'])
     206        if self._has_inconvenient_word(value):
     207            raise ValidationError(self.default_error_messages['invalid'])
     208        return value
     209
     210    def _checksum(self, value):
     211        chars = u'0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ'
     212
     213        s = sum(i * chars.index(c) for i, c in zip(reversed(xrange(19)), value))
     214        checksum = 10 - s % 10
     215
     216        if checksum == 10:
     217            return u'0'
     218        return unicode(checksum)
     219
     220    def _has_inconvenient_word(self, curp):
     221        first_four = curp[:4]
     222        return first_four in CURP_INCONVENIENT_WORDS
  • new file django/contrib/localflavor/mx/models.py

    diff --git a/django/contrib/localflavor/mx/models.py b/django/contrib/localflavor/mx/models.py
    new file mode 100644
    index 0000000..dd9a64b
    - +  
     1from django.utils.translation import ugettext_lazy as _
     2from django.db.models.fields import CharField
     3from django.contrib.localflavor.mx.mx_states import STATE_CHOICES
     4
     5class MXStateField(CharField):
     6    """
     7    A model field that stores the three-letter Mexican state abbreviation in the
     8    database.
     9    """
     10
     11    description = _("Mexico state (three uppercase letters)")
     12
     13    def __init__(self, *args, **kwargs):
     14        kwargs['choices'] = STATE_CHOICES
     15        kwargs['max_length'] = 3
     16        super(MXStateField, self).__init__(*args, **kwargs)
     17
     18class MXZipCodeField(CharField):
     19    """
     20    A model field that forms represent as a forms.MXZipCodeField field and
     21    stores the five-digit Mexican zip code.
     22    """
     23
     24    description = _("Mexico zip code")
     25
     26    def __init__(self, *args, **kwargs):
     27        kwargs['max_length'] = 5
     28        super(MXZipCodeField, self).__init__(*args, **kwargs)
     29
     30    def formfield(self, **kwargs):
     31        from django.contrib.localflavor.mx.forms import MXZipCodeField as Field
     32        defaults = {'form_class': Field}
     33        defaults.update(kwargs)
     34        return super(MXZipCodeField, self).formfield(**defaults)
     35
     36class MXRFCField(CharField):
     37    """
     38    A model field that forms represent as a forms.MXRFCField field and
     39    stores the value of a valid Mexican RFC.
     40    """
     41
     42    description = _("Mexican RFC")
     43
     44    def __init__(self, *args, **kwargs):
     45        kwargs['max_length'] = 13
     46        super(MXRFCField, self).__init__(*args, **kwargs)
     47
     48    def formfield(self, **kwargs):
     49        from django.contrib.localflavor.mx.forms import MXRFCField as Field
     50        defaults = {'form_class': Field}
     51        defaults.update(kwargs)
     52        return super(MXRFCField, self).formfield(**defaults)
     53
     54class MXCURPField(CharField):
     55    """
     56    A model field that forms represent as a forms.MXCURPField field and
     57    stores the value of a valid Mexican CURP.
     58    """
     59
     60    description = _("Mexican CURP")
     61
     62    def __init__(self, *args, **kwargs):
     63        kwargs['max_length'] = 18
     64        super(MXCURPField, self).__init__(*args, **kwargs)
     65
     66    def formfield(self, **kwargs):
     67        from django.contrib.localflavor.mx.forms import MXCURPField as Field
     68        defaults = {'form_class': Field}
     69        defaults.update(kwargs)
     70        return super(MXCURPField, self).formfield(**defaults)
     71 No newline at end of file
  • django/contrib/localflavor/mx/mx_states.py

    diff --git a/django/contrib/localflavor/mx/mx_states.py b/django/contrib/localflavor/mx/mx_states.py
    index eed1700..8632888 100644
    a b when explicitly needed.  
    88
    99from django.utils.translation import ugettext_lazy as _
    1010
    11 STATE_CHOICES = (
     11# All 31 states, plus the `Distrito Federal`.
     12MX_STATES = (
    1213    ('AGU', _(u'Aguascalientes')),
    1314    ('BCN', _(u'Baja California')),
    1415    ('BCS', _(u'Baja California Sur')),
  • docs/ref/contrib/localflavor.txt

    diff --git a/docs/ref/contrib/localflavor.txt b/docs/ref/contrib/localflavor.txt
    index 60539e9..f4bc892 100644
    a b Macedonia (``mk``)  
    774774Mexico (``mx``)
    775775===============
    776776
     777.. class:: mx.forms.MXZipCodeField
     778
     779    A form field that accepts a Mexican Zip Code.
     780
     781    More info about this: List of postal codes in Mexico (zipcodes_)
     782
     783.. _zipcodes: http://en.wikipedia.org/wiki/List_of_postal_codes_in_Mexico
     784
     785.. class:: mx.forms.MXRFCField
     786
     787    A form field that validates a Mexican *Registro Federal de Contribuyentes* for
     788    either **Persona física** or **Persona moral**. This field accepts RFC strings
     789    whether or not it contains a *homoclave*.
     790
     791    More info about this: Registro Federal de Contribuyentes (rfc_)
     792
     793.. _rfc: http://es.wikipedia.org/wiki/Registro_Federal_de_Contribuyentes_(M%C3%A9xico)
     794
     795.. class:: mx.forms.MXCURPField
     796
     797   A field that validates a Mexican *Clave Única de Registro de Población*.
     798
     799   More info about this: Clave Unica de Registro de Poblacion (curp_)
     800
     801.. _curp: http://www.condusef.gob.mx/index.php/clave-unica-de-registro-de-poblacion-curp
     802
    777803.. class:: mx.forms.MXStateSelect
    778804
    779805    A ``Select`` widget that uses a list of Mexican states as its choices.
    780806
     807.. class:: mx.models.MXStateField
     808
     809    A model field that stores the three-letter Mexican state abbreviation in the
     810    database.
     811
     812.. class:: mx.models.MXZipCodeField
     813
     814    A model field that forms represent as a ``forms.MXZipCodeField`` field and
     815    stores the five-digit Mexican zip code.
     816
     817.. class:: mx.models.MXRFCField
     818
     819    A model field that forms represent as a ``forms.MXRFCField`` field and
     820    stores the value of a valid Mexican RFC.
     821
     822.. class:: mx.models.MXCURPField
     823
     824    A model field that forms represent as a ``forms.MXCURPField`` field and
     825    stores the value of a valid Mexican CURP.
     826
     827Additionally, a choice tuple is provided in ``django.contrib.localflavor.mx.mx_states``,
     828allowing customized model and form fields, and form presentations, for subsets of
     829Mexican states abbreviations:
     830
     831.. data:: mx.mx_states.MX_STATES
     832
     833    A tuple of choices of the states abbreviations for all 31 Mexican states,
     834    plus the `Distrito Federal`.
     835
    781836Norway (``no``)
    782837===============
    783838
  • new file tests/regressiontests/forms/localflavor/mx.py

    diff --git a/tests/regressiontests/forms/localflavor/mx.py b/tests/regressiontests/forms/localflavor/mx.py
    new file mode 100644
    index 0000000..1ffc11c
    - +  
     1# -*- coding: utf-8 -*-
     2from django.contrib.localflavor.mx.forms import (MXZipCodeField, MXRFCField,
     3    MXStateSelect, MXCURPField)
     4
     5from utils import LocalFlavorTestCase
     6
     7
     8class MXLocalFlavorTests(LocalFlavorTestCase):
     9    def test_MXStateSelect(self):
     10        f = MXStateSelect()
     11        out = u'''<select name="state">
     12<option value="AGU">Aguascalientes</option>
     13<option value="BCN">Baja California</option>
     14<option value="BCS">Baja California Sur</option>
     15<option value="CAM">Campeche</option>
     16<option value="CHH">Chihuahua</option>
     17<option value="CHP">Chiapas</option>
     18<option value="COA">Coahuila</option>
     19<option value="COL">Colima</option>
     20<option value="DIF">Distrito Federal</option>
     21<option value="DUR">Durango</option>
     22<option value="GRO">Guerrero</option>
     23<option value="GUA">Guanajuato</option>
     24<option value="HID">Hidalgo</option>
     25<option value="JAL">Jalisco</option>
     26<option value="MEX">Estado de México</option>
     27<option value="MIC" selected="selected">Michoacán</option>
     28<option value="MOR">Morelos</option>
     29<option value="NAY">Nayarit</option>
     30<option value="NLE">Nuevo León</option>
     31<option value="OAX">Oaxaca</option>
     32<option value="PUE">Puebla</option>
     33<option value="QUE">Querétaro</option>
     34<option value="ROO">Quintana Roo</option>
     35<option value="SIN">Sinaloa</option>
     36<option value="SLP">San Luis Potosí</option>
     37<option value="SON">Sonora</option>
     38<option value="TAB">Tabasco</option>
     39<option value="TAM">Tamaulipas</option>
     40<option value="TLA">Tlaxcala</option>
     41<option value="VER">Veracruz</option>
     42<option value="YUC">Yucatán</option>
     43<option value="ZAC">Zacatecas</option>
     44</select>'''
     45        self.assertEqual(f.render('state', 'MIC'), out)
     46
     47    def test_MXZipCodeField(self):
     48        error_format = [u'Enter a valid zip code in the format XXXXX.']
     49        valid = {
     50            '58120': u'58120',
     51            '58502': u'58502',
     52            '59310': u'59310',
     53            '99999': u'99999',
     54        }
     55        invalid = {
     56            '17000': error_format,
     57            '18000': error_format,
     58            '19000': error_format,
     59            '00000': error_format,
     60        }
     61        self.assertFieldOutput(MXZipCodeField, valid, invalid)
     62
     63    def test_MXRFCField(self):
     64        error_format = [u'Enter a valid RFC.']
     65        error_checksum = [u'Invalid checksum for RFC.']
     66        valid = {
     67            'MoFN641205eX5': u'MOFN641205EX5',
     68            'ICa060120873': u'ICA060120873',
     69            'eUcG751104rT0': u'EUCG751104RT0',
     70            'GME08100195A': u'GME08100195A',
     71            'AA&060524KX5': u'AA&060524KX5',
     72            'CAÑ0708045P7': u'CAÑ0708045P7',
     73            'aaa000101aa9': u'AAA000101AA9',
     74        }
     75        invalid = {
     76            'MED0000000XA': error_format,
     77            '0000000000XA': error_format,
     78            'AAA000000AA6': error_format,
     79            # Dates
     80            'XXX880002XXX': error_format,
     81            'XXX880200XXX': error_format,
     82            'XXX880132XXX': error_format,
     83            'XXX880230XXX': error_format,
     84            'XXX880431XXX': error_format,
     85            # Incorrect checksum
     86            'MOGR650524E73': error_checksum,
     87            'HVA7810058F1': error_checksum,
     88            'MoFN641205eX2': error_checksum,
     89            'ICa060120871': error_checksum,
     90            'eUcG751104rT7': error_checksum,
     91            'GME081001955': error_checksum,
     92            'AA&060524KX9': error_checksum,
     93            'CAÑ0708045P2': error_checksum,
     94        }
     95        self.assertFieldOutput(MXRFCField, valid, invalid)
     96
     97    def test_MXCURPField(self):
     98        error_format = [u'Enter a valid CURP.']
     99        error_checksum = [u'Invalid checksum for CURP.']
     100        valid = {
     101            'AaMG890608HDFLJL00': u'AAMG890608HDFLJL00',
     102            'BAAd890419HMNRRV07': u'BAAD890419HMNRRV07',
     103            'VIAA900930MMNClL08': u'VIAA900930MMNCLL08',
     104            'HEGR891009HMNRRD09': u'HEGR891009HMNRRD09',
     105            'MARR890512HMNRMN09': u'MARR890512HMNRMN09',
     106            'MESJ890928HMNZNS00': u'MESJ890928HMNZNS00',
     107            'BAAA890317HDFRLL03': u'BAAA890317HDFRLL03',
     108            'TOMA880125HMNRRNO2': u'TOMA880125HMNRRNO2',
     109            'OOMG890727HMNRSR06': u'OOMG890727HMNRSR06',
     110            'AAAA000101HDFCCC09': u'AAAA000101HDFCCC09',
     111        }
     112        invalid = {
     113            'AAAA000000HDFCCC09': error_format,
     114            'AAAA000000HDFAAA03': error_format,
     115            'AAAA000000HXXCCC08': error_format,
     116            'AAAA000000XMNCCC02': error_format,
     117            'HEGR891009HMNRRD0A': error_format,
     118            'MARR890512HMNRMN0A': error_format,
     119            'AaMG890608HDFLJL01': error_checksum,
     120            'BAAd890419HMNRRV08': error_checksum,
     121            'VIAA900930MMNClL09': error_checksum,
     122            'MESJ890928HMNZNS01': error_checksum,
     123            'BAAA890317HDFRLL04': error_checksum,
     124            'TOMA880125HMNRRNO3': error_checksum,
     125            'OOMG890727HMNRSR07': error_checksum,
     126        }
     127        self.assertFieldOutput(MXCURPField, valid, invalid)
  • tests/regressiontests/forms/localflavortests.py

    diff --git a/tests/regressiontests/forms/localflavortests.py b/tests/regressiontests/forms/localflavortests.py
    index 7f29fea..09afad8 100644
    a b from localflavor.it import ITLocalFlavorTests  
    2525from localflavor.jp import JPLocalFlavorTests
    2626from localflavor.kw import KWLocalFlavorTests
    2727from localflavor.mk import MKLocalFlavorTests
     28from localflavor.mx import MXLocalFlavorTests
    2829from localflavor.nl import NLLocalFlavorTests
    2930from localflavor.pl import PLLocalFlavorTests
    3031from localflavor.pt import PTLocalFlavorTests
  • tests/regressiontests/forms/tests/__init__.py

    diff --git a/tests/regressiontests/forms/tests/__init__.py b/tests/regressiontests/forms/tests/__init__.py
    index 6715451..fa947f9 100644
    a b from regressiontests.forms.localflavortests import (  
    3838    JPLocalFlavorTests,
    3939    KWLocalFlavorTests,
    4040    MKLocalFlavorTests,
     41    MXLocalFlavorTests,
    4142    NLLocalFlavorTests,
    4243    PLLocalFlavorTests,
    4344    PTLocalFlavorTests,
  • new file tests/regressiontests/localflavor/mx/forms.py

    diff --git a/tests/regressiontests/localflavor/mx/__init__.py b/tests/regressiontests/localflavor/mx/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/localflavor/mx/forms.py b/tests/regressiontests/localflavor/mx/forms.py
    new file mode 100644
    index 0000000..8a45781
    - +  
     1from django.forms import ModelForm
     2from models import MXPersonProfile
     3
     4class MXPersonProfileForm(ModelForm):
     5    """docstring for MXPersonProfileForm"""
     6    class Meta:
     7        model = MXPersonProfile
  • new file tests/regressiontests/localflavor/mx/models.py

    diff --git a/tests/regressiontests/localflavor/mx/models.py b/tests/regressiontests/localflavor/mx/models.py
    new file mode 100644
    index 0000000..81a5018
    - +  
     1from django.db import models
     2from django.contrib.localflavor.mx.models import (MXStateField,
     3                        MXRFCField, MXCURPField, MXZipCodeField)
     4
     5# When creating models you need to remember to add a app_label as
     6# 'localflavor', so your model can be found
     7
     8class MXPersonProfile(models.Model):
     9    state = MXStateField()
     10    rfc = MXRFCField()
     11    curp = MXCURPField()
     12    zip_code = MXZipCodeField()
     13    class Meta:
     14        app_label = 'localflavor'
  • new file tests/regressiontests/localflavor/mx/tests.py

    diff --git a/tests/regressiontests/localflavor/mx/tests.py b/tests/regressiontests/localflavor/mx/tests.py
    new file mode 100644
    index 0000000..40da38a
    - +  
     1# -*- coding: utf-8 -*-
     2from django.test import TestCase
     3from forms import MXPersonProfileForm
     4
     5class MXLocalFlavorTests(TestCase):
     6    def setUp(self):
     7        self.form = MXPersonProfileForm({
     8            'state': 'MIC',
     9            'rfc': 'toma880125kv3',
     10            'curp': 'toma880125hmnrrn02',
     11            'zip_code': '58120',
     12        })
     13
     14    def test_get_display_methods(self):
     15        """Test that the get_*_display() methods are added to the model instances."""
     16        place = self.form.save()
     17        self.assertEqual(place.get_state_display(), u'Michoacán')
     18
     19    def test_errors(self):
     20        """Test that required MXFields throw appropriate errors."""
     21        form = MXPersonProfileForm({
     22            'state': 'Invalid state',
     23            'rfc': 'invalid rfc',
     24            'curp': 'invalid curp',
     25            'zip_code': 'xxx',
     26        })
     27        self.assertFalse(form.is_valid())
     28        self.assertEqual(form.errors['state'], [u'Select a valid choice. Invalid state is not one of the available choices.'])
     29        self.assertEqual(form.errors['rfc'], [u'Enter a valid RFC.'])
     30        self.assertEqual(form.errors['curp'], [u'Ensure this value has at least 18 characters (it has 12).', u'Enter a valid CURP.'])
     31        self.assertEqual(form.errors['zip_code'], [u'Enter a valid zip code in the format XXXXX.'])
     32
     33    def test_field_blank_option(self):
     34        """Test that the empty option is there."""
     35        state_select_html = """\
     36<select name="state" id="id_state">
     37<option value="">---------</option>
     38<option value="AGU">Aguascalientes</option>
     39<option value="BCN">Baja California</option>
     40<option value="BCS">Baja California Sur</option>
     41<option value="CAM">Campeche</option>
     42<option value="CHH">Chihuahua</option>
     43<option value="CHP">Chiapas</option>
     44<option value="COA">Coahuila</option>
     45<option value="COL">Colima</option>
     46<option value="DIF">Distrito Federal</option>
     47<option value="DUR">Durango</option>
     48<option value="GRO">Guerrero</option>
     49<option value="GUA">Guanajuato</option>
     50<option value="HID">Hidalgo</option>
     51<option value="JAL">Jalisco</option>
     52<option value="MEX">Estado de México</option>
     53<option value="MIC" selected="selected">Michoacán</option>
     54<option value="MOR">Morelos</option>
     55<option value="NAY">Nayarit</option>
     56<option value="NLE">Nuevo León</option>
     57<option value="OAX">Oaxaca</option>
     58<option value="PUE">Puebla</option>
     59<option value="QUE">Querétaro</option>
     60<option value="ROO">Quintana Roo</option>
     61<option value="SIN">Sinaloa</option>
     62<option value="SLP">San Luis Potosí</option>
     63<option value="SON">Sonora</option>
     64<option value="TAB">Tabasco</option>
     65<option value="TAM">Tamaulipas</option>
     66<option value="TLA">Tlaxcala</option>
     67<option value="VER">Veracruz</option>
     68<option value="YUC">Yucatán</option>
     69<option value="ZAC">Zacatecas</option>
     70</select>"""
     71        self.assertEqual(str(self.form['state']), state_select_html)
  • tests/regressiontests/localflavor/tests.py

    diff --git a/tests/regressiontests/localflavor/tests.py b/tests/regressiontests/localflavor/tests.py
    index 6a15d46..95a5f99 100644
    a b  
    11from au.tests import *
    22from mk.tests import *
     3from mx.tests import *
    34from us.tests import *
    45
Back to Top