Author: jezdez
Date: 2011-04-22 05:03:42 -0700 (Fri, 22 Apr 2011)
New Revision: 16077

Added:
   django/trunk/django/contrib/localflavor/hr/
   django/trunk/django/contrib/localflavor/hr/__init__.py
   django/trunk/django/contrib/localflavor/hr/forms.py
   django/trunk/django/contrib/localflavor/hr/hr_choices.py
   django/trunk/tests/regressiontests/forms/localflavor/hr.py
Modified:
   django/trunk/AUTHORS
   django/trunk/docs/ref/contrib/localflavor.txt
   django/trunk/tests/regressiontests/forms/localflavortests.py
   django/trunk/tests/regressiontests/forms/tests/__init__.py
Log:
Fixed #15705 -- Added Croatian (hr) localflavor. Thanks, Zlatko Ma?\197?\161ek 
and Julien Phalip.

Modified: django/trunk/AUTHORS
===================================================================
--- django/trunk/AUTHORS        2011-04-22 12:03:30 UTC (rev 16076)
+++ django/trunk/AUTHORS        2011-04-22 12:03:42 UTC (rev 16077)
@@ -531,6 +531,7 @@
     Gasper Zejn <z...@kiberpipa.org>
     Jarek Zgoda <jarek.zg...@gmail.com>
     Cheng Zhang
+    Zlatko Mašek <zlatko.ma...@gmail.com>
 
 A big THANK YOU goes to:
 

Added: django/trunk/django/contrib/localflavor/hr/__init__.py
===================================================================
Added: django/trunk/django/contrib/localflavor/hr/forms.py
===================================================================
--- django/trunk/django/contrib/localflavor/hr/forms.py                         
(rev 0)
+++ django/trunk/django/contrib/localflavor/hr/forms.py 2011-04-22 12:03:42 UTC 
(rev 16077)
@@ -0,0 +1,281 @@
+# -*- coding: utf-8 -*-
+"""
+HR-specific Form helpers
+"""
+import re
+
+from django.forms.fields import Field, Select, RegexField
+from django.core.validators import EMPTY_VALUES
+from django.forms import ValidationError
+from django.utils.translation import ugettext_lazy as _
+from django.utils.encoding import smart_unicode
+
+jmbg_re = re.compile(r'^(?P<dd>\d{2})(?P<mm>\d{2})(?P<yyy>\d{3})' + \
+            r'(?P<rr>\d{2})(?P<bbb>\d{3})(?P<k>\d{1})$')
+oib_re = re.compile(r'^\d{11}$')
+plate_re = re.compile(ur'^(?P<prefix>[A-ZČŠŽ]{2})' + \
+            ur'(?P<number>\d{3,4})(?P<suffix>[ABCDEFGHIJKLMNOPRSTUVZ]{1,2})$')
+postal_code_re = re.compile(r'^\d{5}$')
+phone_re = re.compile(r'^(\+385|00385|0)(?P<prefix>\d{2})(?P<number>\d{6,7})$')
+jmbag_re = re.compile(r'^601983(?P<copy>\d{1})1(?P<jmbag>\d{10})(?P<k>\d{1})$')
+
+
+class HRCountySelect(Select):
+    """
+    A Select widget that uses a list of counties of Croatia as its choices.
+    """
+
+    def __init__(self, attrs=None):
+        from hr_choices import HR_COUNTY_CHOICES
+        super(HRCountySelect, self).__init__(attrs, choices=HR_COUNTY_CHOICES)
+
+
+class HRLicensePlatePrefixSelect(Select):
+    """
+    A Select widget that uses a list of vehicle license plate prefixes of
+    Croatia as its choices.
+    """
+
+    def __init__(self, attrs=None):
+        from hr_choices import HR_LICENSE_PLATE_PREFIX_CHOICES
+        super(HRLicensePlatePrefixSelect, self).__init__(attrs,
+            choices=HR_LICENSE_PLATE_PREFIX_CHOICES)
+
+
+class HRPhoneNumberPrefixSelect(Select):
+    """
+    A Select widget that uses a list of phone number prefixes of Croatia as its
+    choices.
+    """
+
+    def __init__(self, attrs=None):
+        from hr_choices import HR_PHONE_NUMBER_PREFIX_CHOICES
+        super(HRPhoneNumberPrefixSelect, self).__init__(attrs,
+            choices=HR_PHONE_NUMBER_PREFIX_CHOICES)
+
+
+class HRJMBGField(Field):
+    """
+    Unique Master Citizen Number (JMBG) field.
+    The number is still in use in Croatia, but it is being replaced by OIB.
+
+    Source: http://en.wikipedia.org/wiki/Unique_Master_Citizen_Number
+
+    For who might be reimplementing:
+    The "area" regular expression group is used to calculate the region where a
+    person was registered. Additional validation can be implemented in
+    accordance with it, however this could result in exclusion of legit
+    immigrated citizens. Therefore, this field works for any ex-Yugoslavia
+    country.
+    """
+    default_error_messages = {
+        'invalid': _('Enter a valid 13 digit JMBG'),
+        'date': _('Error in date segment'),
+    }
+
+    def clean(self, value):
+        super(HRJMBGField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+
+        value = value.strip()
+
+        matches = jmbg_re.search(value)
+        if matches is None:
+            raise ValidationError(self.error_messages['invalid'])
+
+        # Make sure the date part is correct.
+        dd = int(matches.group('dd'))
+        mm = int(matches.group('mm'))
+        yyy = int(matches.group('yyy'))
+        import datetime
+        try:
+            datetime.date(yyy,mm,dd)
+        except:
+            raise ValidationError(self.error_messages['date'])
+
+        # Validate checksum.
+        k = matches.group('k')
+        checksum = 0
+        for i,j in zip(range(7,1,-1),range(6)):
+            checksum+=i*(int(value[j])+int(value[13-i]))
+        m = 11 - checksum % 11
+        if m == 10:
+            raise ValidationError(self.error_messages['invalid'])
+        if m == 11 and k != '0':
+            raise ValidationError(self.error_messages['invalid'])
+        if not str(m) == k:
+            raise ValidationError(self.error_messages['invalid'])
+
+        return u'%s' % (value, )
+
+
+class HROIBField(RegexField):
+    """
+    Personal Identification Number of Croatia (OIB) field.
+
+    http://www.oib.hr/
+    """
+    default_error_messages = {
+        'invalid': _('Enter a valid 11 digit OIB'),
+    }
+
+    def __init__(self, *args, **kwargs):
+        super(HROIBField, self).__init__(r'^\d{11}$',
+            min_length=11, max_length=11, *args, **kwargs)
+
+    def clean(self, value):
+        super(HROIBField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+
+        return '%s' % (value, )
+
+
+class HRLicensePlateField(Field):
+    """
+    Vehicle license plate of Croatia field. Normalizes to the specific format
+    below. Suffix is constructed from the shared letters of the Croatian and
+    English alphabets.
+
+    Format examples:
+        SB 123-A
+        (but also supports more characters)
+        ZG 1234-AA
+
+    Used for standardized license plates only.
+    """
+    default_error_messages = {
+        'invalid': _('Enter a valid vehicle license plate number'),
+        'area': _('Enter a valid location code'),
+        'number': _('Number part cannot be zero'),
+    }
+
+    def clean(self, value):
+        super(HRLicensePlateField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+
+        value = re.sub(r'[\s\-]+', '', smart_unicode(value.strip())).upper()
+
+        matches = plate_re.search(value)
+        if matches is None:
+            raise ValidationError(self.error_messages['invalid'])
+
+        # Make sure the prefix is in the list of known codes.
+        from hr_choices import HR_LICENSE_PLATE_PREFIX_CHOICES
+        prefix = matches.group('prefix')
+        if prefix not in [choice[0] for choice in 
HR_LICENSE_PLATE_PREFIX_CHOICES]:
+            raise ValidationError(self.error_messages['area'])
+
+        # Make sure the number portion is not zero.
+        number = matches.group('number')
+        if int(number) == 0:
+            raise ValidationError(self.error_messages['number'])
+
+        return u'%s %s-%s' % (prefix,number,matches.group('suffix'), )
+
+
+class HRPostalCodeField(Field):
+    """
+    Postal code of Croatia field.
+    It consists of exactly five digits ranging from 10000 to possibly less than
+    60000.
+
+    http://www.posta.hr/main.aspx?id=66
+    """
+    default_error_messages = {
+        'invalid': _('Enter a valid 5 digit postal code'),
+    }
+
+    def clean(self, value):
+        super(HRPostalCodeField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+
+        value = value.strip()
+        if not postal_code_re.search(value):
+            raise ValidationError(self.error_messages['invalid'])
+
+        # Make sure the number is in valid range.
+        if not 9999<int(value)<60000:
+            raise ValidationError(self.error_messages['invalid'])
+
+        return '%s' % (value, )
+
+
+class HRPhoneNumberField(Field):
+    """
+    Phone number of Croatia field.
+    Format: Complete country code or leading zero, area code prefix, 6 or 7
+    digit number.
+    Validates fixed, mobile and FGSM numbers. Normalizes to a full number with
+    country code (+385 prefix).
+    """
+    default_error_messages = {
+        'invalid': _('Enter a valid phone number'),
+        'area': _('Enter a valid area or mobile network code'),
+        'number': _('The phone nubmer is too long'),
+    }
+
+    def clean(self, value):
+        super(HRPhoneNumberField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+
+        value = re.sub(r'[\-\s\(\)]', '', smart_unicode(value))
+
+        matches = phone_re.search(value)
+        if matches is None:
+            raise ValidationError(self.error_messages['invalid'])
+
+        # Make sure the prefix is in the list of known codes.
+        from hr_choices import HR_PHONE_NUMBER_PREFIX_CHOICES
+        prefix = matches.group('prefix')
+        number = matches.group('number')
+        if prefix[0] == '1':
+            number = prefix[1] + number
+            prefix = prefix[0]
+        if prefix not in [choice[0] for choice in 
HR_PHONE_NUMBER_PREFIX_CHOICES]:
+            raise ValidationError(self.error_messages['area'])
+
+        # Make sure the number is of adequate length.
+        if prefix=='1' and len(number)!=7:
+            raise ValidationError(self.error_messages['number'])
+
+        return '%s%s%s' % ('+385',prefix,number)
+
+
+class HRJMBAGField(Field):
+    """
+    Unique Master Academic Citizen Number of Croatia (JMBAG) field.
+    This number is used by college students and professors in Croatia.
+
+    http://www.cap.srce.hr/IzgledX.aspx
+    """
+    default_error_messages = {
+        'invalid': _('Enter a valid 19 digit JMBAG starting with 601983'),
+        'copy': _('Card issue number cannot be zero'),
+    }
+
+    def clean(self, value):
+        super(HRJMBAGField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+
+        value = re.sub(r'[\-\s]', '', value.strip())
+
+        matches = jmbag_re.search(value)
+        if matches is None:
+            raise ValidationError(self.error_messages['invalid'])
+
+        # Make sure the issue number is not zero.
+        if matches.group('copy')=='0':
+            raise ValidationError(self.error_messages['copy'])
+
+        # Validate checksum using Luhn algorithm.
+        num = [int(x) for x in value]
+        if not sum(num[::-2] + [sum(divmod(d * 2, 10)) for d in num[-2::-2]]) 
% 10 == 0:
+            raise ValidationError(self.error_messages['invalid'])
+
+        return '%s' % (value, )

Added: django/trunk/django/contrib/localflavor/hr/hr_choices.py
===================================================================
--- django/trunk/django/contrib/localflavor/hr/hr_choices.py                    
        (rev 0)
+++ django/trunk/django/contrib/localflavor/hr/hr_choices.py    2011-04-22 
12:03:42 UTC (rev 16077)
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+"""
+Sources:
+    Croatian Counties: http://en.wikipedia.org/wiki/ISO_3166-2:HR
+
+    Croatia doesn't have official abbreviations for counties.
+    The ones provided are in common use.
+"""
+from django.utils.translation import ugettext_lazy as _
+
+HR_COUNTY_CHOICES = (
+    ('GZG', _('Grad Zagreb')),
+    (u'BBŽ', _(u'Bjelovarsko-bilogorska županija')),
+    (u'BPŽ', _(u'Brodsko-posavska županija')),
+    (u'DNŽ', _(u'Dubrovačko-neretvanska županija')),
+    (u'IŽ', _(u'Istarska županija')),
+    (u'KŽ', _(u'Karlovačka županija')),
+    (u'KKŽ', _(u'Koprivničko-križevačka županija')),
+    (u'KZŽ', _(u'Krapinsko-zagorska županija')),
+    (u'LSŽ', _(u'Ličko-senjska županija')),
+    (u'MŽ', _(u'Međimurska županija')),
+    (u'OBŽ', _(u'Osječko-baranjska županija')),
+    (u'PSŽ', _(u'Požeško-slavonska županija')),
+    (u'PGŽ', _(u'Primorsko-goranska županija')),
+    (u'SMŽ', _(u'Sisačko-moslavačka županija')),
+    (u'SDŽ', _(u'Splitsko-dalmatinska županija')),
+    (u'ŠKŽ', _(u'Šibensko-kninska županija')),
+    (u'VŽ', _(u'Varaždinska županija')),
+    (u'VPŽ', _(u'Virovitičko-podravska županija')),
+    (u'VSŽ', _(u'Vukovarsko-srijemska županija')),
+    (u'ZDŽ', _(u'Zadarska županija')),
+    (u'ZGŽ', _(u'Zagrebačka županija')),
+)
+
+"""
+Sources:
+http://hr.wikipedia.org/wiki/Dodatak:Popis_registracijskih_oznaka_za_cestovna_vozila_u_Hrvatskoj
+
+Only common license plate prefixes are provided. Special cases and obsolete 
prefixes are omitted.
+"""
+
+HR_LICENSE_PLATE_PREFIX_CHOICES = (
+    ('BJ', 'BJ'),
+    ('BM', 'BM'),
+    (u'ČK', u'ČK'),
+    ('DA', 'DA'),
+    ('DE', 'DE'),
+    ('DJ', 'DJ'),
+    ('DU', 'DU'),
+    ('GS', 'GS'),
+    ('IM', 'IM'),
+    ('KA', 'KA'),
+    ('KC', 'KC'),
+    ('KR', 'KR'),
+    ('KT', 'KT'),
+    (u'KŽ', u'KŽ'),
+    ('MA', 'MA'),
+    ('NA', 'NA'),
+    ('NG', 'NG'),
+    ('OG', 'OG'),
+    ('OS', 'OS'),
+    ('PU', 'PU'),
+    (u'PŽ', u'PŽ'),
+    ('RI', 'RI'),
+    ('SB', 'SB'),
+    ('SK', 'SK'),
+    ('SL', 'SL'),
+    ('ST', 'ST'),
+    (u'ŠI', u'ŠI'),
+    ('VK', 'VK'),
+    ('VT', 'VT'),
+    ('VU', 'VU'),
+    (u'VŽ', u'VŽ'),
+    ('ZD', 'ZD'),
+    ('ZG', 'ZG'),
+    (u'ŽU', u'ŽU'),
+)
+
+"""
+The list includes county and cellular network phone number prefixes.
+"""
+
+HR_PHONE_NUMBER_PREFIX_CHOICES = (
+    ('1', '01'),
+    ('20', '020'),
+    ('21', '021'),
+    ('22', '022'),
+    ('23', '023'),
+    ('31', '031'),
+    ('32', '032'),
+    ('33', '033'),
+    ('34', '034'),
+    ('35', '035'),
+    ('40', '040'),
+    ('42', '042'),
+    ('43', '043'),
+    ('44', '044'),
+    ('47', '047'),
+    ('48', '048'),
+    ('49', '049'),
+    ('51', '051'),
+    ('52', '052'),
+    ('53', '053'),
+    ('91', '091'),
+    ('92', '092'),
+    ('95', '095'),
+    ('97', '097'),
+    ('98', '098'),
+    ('99', '099'),
+)

Modified: django/trunk/docs/ref/contrib/localflavor.txt
===================================================================
--- django/trunk/docs/ref/contrib/localflavor.txt       2011-04-22 12:03:30 UTC 
(rev 16076)
+++ django/trunk/docs/ref/contrib/localflavor.txt       2011-04-22 12:03:42 UTC 
(rev 16077)
@@ -44,6 +44,7 @@
     * Canada_
     * Chile_
     * China_
+    * Croatia_
     * Czech_
     * Finland_
     * France_
@@ -95,6 +96,7 @@
 .. _Canada: `Canada (ca)`_
 .. _Chile: `Chile (cl)`_
 .. _China: `China (cn)`_
+.. _Croatia: `Croatia (hr)`_
 .. _Czech: `Czech (cz)`_
 .. _Finland: `Finland (fi)`_
 .. _France: `France (fr)`_
@@ -374,6 +376,72 @@
     Valid formats are like 1XXXXXXXXXX, where X is digit.
     The second digit could only be 3, 5 and 8.
 
+Croatia (``hr``)
+==============
+
+.. versionadded:: 1.4
+
+.. class:: hr.forms.HRCountySelect
+
+    A ``Select`` widget that uses a list of counties of Croatia as its choices.
+
+.. class:: hr.forms.HRPhoneNumberPrefixSelect
+
+    A ``Select`` widget that uses a list of phone number prefixes of Croatia as
+    its choices.
+
+.. class:: hr.forms.HRLicensePlatePrefixSelect
+
+    A ``Select`` widget that uses a list of vehicle license plate prefixes of
+    Croatia as its choices.
+
+.. class:: hr.forms.HRPhoneNumberField
+
+    A form field that validates input as a phone number of Croatia.
+    A valid format is a country code or a leading zero, area code prefix, 6 or 
7
+    digit number; e.g. +385XXXXXXXX or 0XXXXXXXX
+    Validates fixed, mobile and FGSM numbers. Normalizes to a full number with
+    country code (+385 prefix).
+
+.. class:: hr.forms.HRLicensePlateField
+
+    A form field that validates input as a vehicle license plate of Croatia.
+    Normalizes to the specific format XX YYYY-XX where X is a letter and Y a
+    digit. There can be three or four digits.
+    Suffix is constructed from the shared letters of the Croatian and English
+    alphabets.
+    It is used for standardized license plates only. Special cases like license
+    plates for oldtimers, temporary license plates, government institution
+    license plates and customized license plates are not covered by this field.
+
+.. class:: hr.forms.HRPostalCodeField
+
+    A form field that validates input as a postal code of Croatia.
+    It consists of exactly five digits ranging from 10000 to 59999 inclusive.
+
+.. class:: hr.forms.HROIBField
+
+    A form field that validates input as a Personal Identification Number (OIB)
+    of Croatia.
+    It consists of exactly eleven digits.
+
+.. class:: hr.forms.HRJMBGField
+
+    A form field that validates input as a Unique Master Citizen Number (JMBG).
+    The number is still in use in Croatia, but it is being replaced by OIB.
+    This field works for other ex-Yugoslavia countries as well where the JMBG 
is
+    still in use.
+    The area segment of the JMBG is not validated because the citizens might
+    have emigrated to another ex-Yugoslavia country.
+    The number consists of exactly thirteen digits.
+
+.. class:: hr.forms.HRJMBAGField
+
+    A form field that validates input as a Unique Master Academic Citizen 
Number
+    (JMBAG) of Croatia.
+    This number is used by college students and professors in Croatia.
+    The number consists of exactly nineteen digits.
+
 Czech (``cz``)
 ==============
 

Added: django/trunk/tests/regressiontests/forms/localflavor/hr.py
===================================================================
--- django/trunk/tests/regressiontests/forms/localflavor/hr.py                  
        (rev 0)
+++ django/trunk/tests/regressiontests/forms/localflavor/hr.py  2011-04-22 
12:03:42 UTC (rev 16077)
@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+from django.contrib.localflavor.hr.forms import (HRCountySelect,
+    HRPhoneNumberPrefixSelect, HRLicensePlatePrefixSelect, HRPhoneNumberField,
+    HRLicensePlateField, HRPostalCodeField, HROIBField, HRJMBGField,
+    HRJMBAGField)
+
+from utils import LocalFlavorTestCase
+
+class HRLocalFlavorTests(LocalFlavorTestCase):
+    def test_HRCountySelect(self):
+        f = HRCountySelect()
+        out = u'''<select name="county">
+<option value="GZG" selected="selected">Grad Zagreb</option>
+<option value="BBŽ">Bjelovarsko-bilogorska županija</option>
+<option value="BPŽ">Brodsko-posavska županija</option>
+<option value="DNŽ">Dubrovačko-neretvanska županija</option>
+<option value="IŽ">Istarska županija</option>
+<option value="KŽ">Karlovačka županija</option>
+<option value="KKŽ">Koprivničko-križevačka županija</option>
+<option value="KZŽ">Krapinsko-zagorska županija</option>
+<option value="LSŽ">Ličko-senjska županija</option>
+<option value="MŽ">Međimurska županija</option>
+<option value="OBŽ">Osječko-baranjska županija</option>
+<option value="PSŽ">Požeško-slavonska županija</option>
+<option value="PGŽ">Primorsko-goranska županija</option>
+<option value="SMŽ">Sisačko-moslavačka županija</option>
+<option value="SDŽ">Splitsko-dalmatinska županija</option>
+<option value="ŠKŽ">Šibensko-kninska županija</option>
+<option value="VŽ">Varaždinska županija</option>
+<option value="VPŽ">Virovitičko-podravska županija</option>
+<option value="VSŽ">Vukovarsko-srijemska županija</option>
+<option value="ZDŽ">Zadarska županija</option>
+<option value="ZGŽ">Zagrebačka županija</option>
+</select>'''
+        self.assertEqual(f.render('county', 'GZG'), out)
+
+    def test_HRPhoneNumberPrefixSelect(self):
+        f = HRPhoneNumberPrefixSelect()
+        out = u'''<select name="phone">
+<option value="1" selected="selected">01</option>
+<option value="20">020</option>
+<option value="21">021</option>
+<option value="22">022</option>
+<option value="23">023</option>
+<option value="31">031</option>
+<option value="32">032</option>
+<option value="33">033</option>
+<option value="34">034</option>
+<option value="35">035</option>
+<option value="40">040</option>
+<option value="42">042</option>
+<option value="43">043</option>
+<option value="44">044</option>
+<option value="47">047</option>
+<option value="48">048</option>
+<option value="49">049</option>
+<option value="51">051</option>
+<option value="52">052</option>
+<option value="53">053</option>
+<option value="91">091</option>
+<option value="92">092</option>
+<option value="95">095</option>
+<option value="97">097</option>
+<option value="98">098</option>
+<option value="99">099</option>
+</select>'''
+        self.assertEqual(f.render('phone', '1'), out)
+
+    def test_HRLicensePlatePrefixSelect(self):
+        f = HRLicensePlatePrefixSelect()
+        out = u'''<select name="license">
+<option value="BJ" selected="selected">BJ</option>
+<option value="BM">BM</option>
+<option value="ČK">ČK</option>
+<option value="DA">DA</option>
+<option value="DE">DE</option>
+<option value="DJ">DJ</option>
+<option value="DU">DU</option>
+<option value="GS">GS</option>
+<option value="IM">IM</option>
+<option value="KA">KA</option>
+<option value="KC">KC</option>
+<option value="KR">KR</option>
+<option value="KT">KT</option>
+<option value="KŽ">KŽ</option>
+<option value="MA">MA</option>
+<option value="NA">NA</option>
+<option value="NG">NG</option>
+<option value="OG">OG</option>
+<option value="OS">OS</option>
+<option value="PU">PU</option>
+<option value="PŽ">PŽ</option>
+<option value="RI">RI</option>
+<option value="SB">SB</option>
+<option value="SK">SK</option>
+<option value="SL">SL</option>
+<option value="ST">ST</option>
+<option value="ŠI">ŠI</option>
+<option value="VK">VK</option>
+<option value="VT">VT</option>
+<option value="VU">VU</option>
+<option value="VŽ">VŽ</option>
+<option value="ZD">ZD</option>
+<option value="ZG">ZG</option>
+<option value="ŽU">ŽU</option>
+</select>'''
+        self.assertEqual(f.render('license', 'BJ'), out)
+
+    def test_HRPhoneNumberField(self):
+        error_invalid = [u'Enter a valid phone number']
+        error_area = [u'Enter a valid area or mobile network code']
+        error_number = [u'The phone nubmer is too long']
+        valid = {
+            '+38511234567': '+38511234567',
+            '0038511234567': '+38511234567',
+            '011234567': '+38511234567',
+            '+38521123456': '+38521123456',
+            '0038521123456': '+38521123456',
+            '021123456': '+38521123456',
+        }
+        invalid = {
+            '123456789': error_invalid,
+            '0811234567': error_area,
+            '0111234567': error_number,
+        }
+        self.assertFieldOutput(HRPhoneNumberField, valid, invalid)
+
+    def test_HRLicensePlateField(self):
+        error_invalid = [u'Enter a valid vehicle license plate number']
+        error_area = [u'Enter a valid location code']
+        error_number = [u'Number part cannot be zero']
+        valid = {
+            'ZG 1234-AA': u'ZG 1234-AA',
+            'ZG 123-A': u'ZG 123-A',
+        }
+        invalid = {
+            'PV12345': error_invalid,
+            'PV1234AA': error_area,
+            'ZG0000CC': error_number,
+        }
+        self.assertFieldOutput(HRLicensePlateField, valid, invalid)
+
+    def test_HRPostalCodeField(self):
+        error_invalid = [u'Enter a valid 5 digit postal code']
+        valid = {
+            '10000': '10000',
+            '35410': '35410',
+        }
+        invalid = {
+            'ABCD': error_invalid,
+            '99999': error_invalid,
+        }
+        self.assertFieldOutput(HRPostalCodeField, valid, invalid)
+
+    def test_HROIBField(self):
+        error_invalid = [u'Enter a valid 11 digit OIB']
+        valid = {
+            '12345678901': '12345678901',
+        }
+        invalid = {
+            '1234567890': error_invalid,
+            'ABCDEFGHIJK': error_invalid,
+        }
+        self.assertFieldOutput(HROIBField, valid, invalid)
+
+    def test_HRJMBGField(self):
+        error_invalid = [u'Enter a valid 13 digit JMBG']
+        error_date = [u'Error in date segment']
+        valid = {
+            '1211984302155': '1211984302155',
+            '2701984307107': '2701984307107',
+        }
+        invalid = {
+            '1211984302156': error_invalid,
+            'ABCDEFG': error_invalid,
+            '9999999123456': error_date,
+        }
+        self.assertFieldOutput(HRJMBGField, valid, invalid)
+
+    def test_HRJMBAGField(self):
+        error_invalid = [u'Enter a valid 19 digit JMBAG starting with 601983']
+        error_copy = [u'Card issue number cannot be zero']
+        valid = {
+            '601983 11 0130185856 4': '6019831101301858564',
+        }
+        invalid = {
+            '601983 11 0130185856 5': error_invalid,
+            '601983 01 0130185856 4': error_copy,
+        }
+        self.assertFieldOutput(HRJMBAGField, valid, invalid)

Modified: django/trunk/tests/regressiontests/forms/localflavortests.py
===================================================================
--- django/trunk/tests/regressiontests/forms/localflavortests.py        
2011-04-22 12:03:30 UTC (rev 16076)
+++ django/trunk/tests/regressiontests/forms/localflavortests.py        
2011-04-22 12:03:42 UTC (rev 16077)
@@ -13,6 +13,7 @@
 from localflavor.fi import FILocalFlavorTests
 from localflavor.fr import FRLocalFlavorTests
 from localflavor.generic import GenericLocalFlavorTests
+from localflavor.hr import HRLocalFlavorTests
 from localflavor.id import IDLocalFlavorTests
 from localflavor.ie import IELocalFlavorTests
 from localflavor.il import ILLocalFlavorTests

Modified: django/trunk/tests/regressiontests/forms/tests/__init__.py
===================================================================
--- django/trunk/tests/regressiontests/forms/tests/__init__.py  2011-04-22 
12:03:30 UTC (rev 16076)
+++ django/trunk/tests/regressiontests/forms/tests/__init__.py  2011-04-22 
12:03:42 UTC (rev 16077)
@@ -27,6 +27,7 @@
     FILocalFlavorTests,
     FRLocalFlavorTests,
     GenericLocalFlavorTests,
+    HRLocalFlavorTests,
     IDLocalFlavorTests,
     IELocalFlavorTests,
     ILLocalFlavorTests,

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to