Ticket #11517: patch_clpatentefield-16716.diff

File patch_clpatentefield-16716.diff, 6.0 KB (added by alej0, 4 years ago)

Patch for django 16716

  • django/contrib/localflavor/cl/forms.py

     
    44
    55from django.core.validators import EMPTY_VALUES
    66from django.forms import ValidationError
    7 from django.forms.fields import RegexField, Select
     7from django.forms.fields import RegexField, Select, CharField
    88from django.utils.translation import ugettext_lazy as _
    99from django.utils.encoding import smart_unicode
    1010
     11OLD_CAR_PLATE_STYLE = 0
     12NEW_CAR_PLATE_STYLE = 1
    1113
     14
    1215class CLRegionSelect(Select):
    1316    """
    1417    A Select widget that uses a list of Chilean Regions (Regiones)
     
    9396            code = code[:new_dot] + '.' + code[new_dot:]
    9497        return u'%s-%s' % (code, verifier)
    9598
     99
     100class CLPatenteField(CharField):
     101    """
     102    Chilean "Patente", Placa Patente Field, support old LL-NNNN and new LLLL-NN
     103    type, where L in new can't be vowel or m,n and q.
     104    """
     105    default_error_messages = {
     106        'invalid': _("Enter a valid Chilean Car Plate."),
     107    }
     108
     109    def __init__(self, *args, **kwargs):
     110        kwargs['max_length'] = 7
     111        kwargs['min_length'] = 6
     112        if not kwargs.has_key('label'):
     113            kwargs['label'] = _("Car plate")
     114        if not kwargs.has_key('help_text'):
     115            kwargs['help_text'] = _("Chilean car plate as LL-NNNN or LLLL-NN")
     116
     117        super(CLPatenteField, self).__init__(*args, **kwargs)
     118
     119    def clean(self, value):
     120        """
     121        Check and clean the field for length and type.
     122        """
     123        super(CLPatenteField, self).clean(value)
     124
     125        if value in EMPTY_VALUES:
     126            return u''
     127
     128        value = smart_unicode(value.lower())
     129        value_length = len(value)
     130
     131        if self.max_length is not None and value_length > self.max_length:
     132            raise ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length})
     133        if self.min_length is not None and value_length < self.min_length:
     134            raise ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length})
     135
     136        value = self._canonify(value)
     137        _type = self._algorithm(value)
     138
     139        if _type not in (OLD_CAR_PLATE_STYLE, NEW_CAR_PLATE_STYLE):
     140            raise ValidationError(self.error_messages['invalid'])
     141
     142        return self._format(value.upper(), _type)
     143
     144    def _algorithm(self, value):
     145        """
     146        Takes Car Plate in canonical form and verify if it is valid.
     147        Returns the type or None if it is not valid.
     148        """
     149        import re
     150        # Old card plate patern
     151        op = '^[a-z]{2,2}\d{4,4}$'
     152        op = re.compile(op)
     153        # New card plate patern
     154        np = '^[bcdfghjklprstvwxyz]{4,4}\d{2,2}$'
     155        np = re.compile(np)
     156        if re.search(op, value):
     157            return OLD_CAR_PLATE_STYLE
     158        elif re.search(np, value):
     159            return NEW_CAR_PLATE_STYLE
     160        else:
     161            return None
     162
     163    def _canonify(self, patente):
     164        """
     165        Turns the Car Plate into one normalized format.
     166        """
     167        return patente.replace(' ', '').replace('-', '')
     168
     169    def _format(self, value, _type):
     170        """
     171        Formats the Car Plate from canonical form to the common string
     172        representation. LL-DDDD or LLLL-DD
     173        """
     174        if _type == OLD_CAR_PLATE_STYLE:
     175            return u'-'.join((value[:2], value[2:]))
     176        if _type == NEW_CAR_PLATE_STYLE:
     177            return u'-'.join((value[:4], value[4:]))
  • tests/regressiontests/localflavor/cl/tests.py

     
    1 from django.contrib.localflavor.cl.forms import CLRutField, CLRegionSelect
     1from django.contrib.localflavor.cl.forms import CLRutField, CLRegionSelect, CLPatenteField
    22
     3from django.core.validators import MinLengthValidator, MaxLengthValidator
     4
     5
    36from django.test import SimpleTestCase
    47
    58
     
    5457        self.assertFieldOutput(CLRutField,
    5558            {}, invalid, field_kwargs={"strict": True}
    5659        )
     60
     61    def test_CLPatente(self):
     62        """ Tests that the field validates input"""
     63        invalid_min_length_data = 'p'
     64        invalid_max_length_data = 'pcpcpcpc'
     65
     66        error_invalid =  [CLPatenteField().default_error_messages['invalid']]
     67
     68        error_min_length = [MinLengthValidator.message % {'limit_value': CLPatenteField().min_length, 'show_value' :len(invalid_min_length_data)}]
     69        error_max_length = [MaxLengthValidator.message % {'limit_value': CLPatenteField().max_length, 'show_value' :len(invalid_max_length_data)}]
     70
     71        valid = {
     72        # Valid new style
     73            'rrwr56': 'RRWR-56',
     74            'rrwr-56': 'RRWR-56',
     75        # Valid old style
     76            'aa6056': 'AA-6056',
     77            'aa-6056':'AA-6056'
     78        }
     79        invalid = {
     80            invalid_min_length_data: error_min_length,
     81            invalid_max_length_data: error_max_length,
     82            'ppppcpc': error_invalid,
     83            'cpcpcp': error_invalid,
     84            'cpcpc0': error_invalid,
     85            'cpc606': error_invalid,
     86            'c60606': error_invalid,
     87            '606060': error_invalid,
     88            # Can't contain 'm'
     89            'mttt12': error_invalid,
     90            # Can't contain 'n'
     91            'nttt34': error_invalid,
     92            # Can't contain 'q'
     93            'qttt56': error_invalid,
     94            # Can't contain vowel
     95            # 'a'
     96            'attt67': error_invalid,
     97            # 'e'
     98            'ettt67': error_invalid,
     99            # 'i'
     100            'ittt89': error_invalid,
     101            # 'o'
     102            'ottt01': error_invalid,
     103            # 'u'
     104            'uttt23': error_invalid
     105        }
     106
     107        self.assertFieldOutput(CLPatenteField, valid, invalid)
Back to Top