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

Added:
   django/trunk/django/contrib/localflavor/ru/
   django/trunk/django/contrib/localflavor/ru/__init__.py
   django/trunk/django/contrib/localflavor/ru/forms.py
   django/trunk/django/contrib/localflavor/ru/ru_regions.py
   django/trunk/tests/regressiontests/forms/localflavor/ru.py
Modified:
   django/trunk/docs/ref/contrib/localflavor.txt
   django/trunk/tests/regressiontests/forms/localflavortests.py
   django/trunk/tests/regressiontests/forms/tests/__init__.py
Log:
Fixed #15013 -- Added Russian (ru) localflavor package. Thanks, blackraven and 
Julien Phalip.

Added: django/trunk/django/contrib/localflavor/ru/__init__.py
===================================================================
Added: django/trunk/django/contrib/localflavor/ru/forms.py
===================================================================
--- django/trunk/django/contrib/localflavor/ru/forms.py                         
(rev 0)
+++ django/trunk/django/contrib/localflavor/ru/forms.py 2011-04-22 12:03:30 UTC 
(rev 16076)
@@ -0,0 +1,68 @@
+"""
+Russian-specific forms helpers
+"""
+import re
+
+from django.core.validators import EMPTY_VALUES
+from django.forms import ValidationError
+from django.forms.fields import CharField, Select, RegexField
+from django.utils.translation import ugettext_lazy as _
+
+phone_digits_re = re.compile(r'^(?:[78]-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$')
+
+
+class RUCountySelect(Select):
+    """
+    A Select widget that uses a list of Russian Counties as its choices.
+    """
+    def __init__(self, attrs=None):
+        from ru_regions import RU_COUNTY_CHOICES
+        super(RUCountySelect, self).__init__(attrs, choices=RU_COUNTY_CHOICES)
+
+
+class RURegionSelect(Select):
+    """
+    A Select widget that uses a list of Russian Regions as its choices.
+    """
+    def __init__(self, attrs=None):
+        from ru_regions import RU_REGIONS_CHOICES
+        super(RURegionSelect, self).__init__(attrs, choices=RU_REGIONS_CHOICES)
+
+
+class RUPostalCodeField(RegexField):
+    """
+    Russian Postal code field.
+    Format: XXXXXX, where X is any digit, and first digit is not zero.
+    """
+    default_error_messages = {
+        'invalid': _(u'Enter a postal code in the format XXXXXX.'),
+    }
+    def __init__(self, *args, **kwargs):
+        super(RUPostalCodeField, self).__init__(r'^\d{6}$',
+            max_length=None, min_length=None, *args, **kwargs)
+
+
+class RUPassportNumberField(RegexField):
+    """
+    Russian internal passport number format:
+    XXXX XXXXXX where X - any digit.
+    """
+    default_error_messages = {
+        'invalid': _(u'Enter a passport number in the format XXXX XXXXXX.'),
+    }
+    def __init__(self, *args, **kwargs):
+        super(RUPassportNumberField, self).__init__(r'^\d{4} \d{6}$',
+            max_length=None, min_length=None, *args, **kwargs)
+
+
+class RUAlienPassportNumberField(RegexField):
+    """
+    Russian alien's passport number format:
+    XX XXXXXXX where X - any digit.
+    """
+    default_error_messages = {
+        'invalid': _(u'Enter a passport number in the format XX XXXXXXX.'),
+    }
+    def __init__(self, *args, **kwargs):
+        super(RUAlienPassportNumberField, self).__init__(r'^\d{2} \d{7}$',
+            max_length=None, min_length=None, *args, **kwargs)

Added: django/trunk/django/contrib/localflavor/ru/ru_regions.py
===================================================================
--- django/trunk/django/contrib/localflavor/ru/ru_regions.py                    
        (rev 0)
+++ django/trunk/django/contrib/localflavor/ru/ru_regions.py    2011-04-22 
12:03:30 UTC (rev 16076)
@@ -0,0 +1,104 @@
+# -*- encoding: utf-8 -*-
+"""
+Sources:
+    http://ru.wikipedia.org/wiki/Коды_субъектов_Российской_Федерации
+    http://ru.wikipedia.org/wiki/Федеральные_округа_Российской_Федерации
+"""
+from django.utils.translation import ugettext_lazy as _
+
+RU_COUNTY_CHOICES = (
+    ("Central Federal County", _("Central Federal County")),
+    ("South Federal County", _("South Federal County")),
+    ("North-West Federal County", _("North-West Federal County")),
+    ("Far-East Federal County", _("Far-East Federal County")),
+    ("Siberian Federal County", _("Siberian Federal County")),
+    ("Ural Federal County", _("Ural Federal County")),
+    ("Privolzhsky Federal County", _("Privolzhsky Federal County")),
+    ("North-Caucasian Federal County", _("North-Caucasian Federal County"))
+)
+
+RU_REGIONS_CHOICES = (
+    ("77", _("Moskva")),
+    ("78", _("Saint-Peterburg")),
+    ("50", _("Moskovskaya oblast'")),
+    ("01", _("Adygeya, Respublika")),
+    ("02", _("Bashkortostan, Respublika")),
+    ("03", _("Buryatia, Respublika")),
+    ("04", _("Altay, Respublika")),
+    ("05", _("Dagestan, Respublika")),
+    ("06", _("Ingushskaya Respublika")),
+    ("07", _("Kabardino-Balkarskaya Respublika")),
+    ("08", _("Kalmykia, Respublika")),
+    ("09", _("Karachaevo-Cherkesskaya Respublika")),
+    ("10", _("Karelia, Respublika")),
+    ("11", _("Komi, Respublika")),
+    ("12", _("Mariy Ehl, Respublika")),
+    ("13", _("Mordovia, Respublika")),
+    ("14", _("Sakha, Respublika (Yakutiya)")),
+    ("15", _("Severnaya Osetia, Respublika (Alania)")),
+    ("16", _("Tatarstan, Respublika")),
+    ("17", _("Tyva, Respublika (Tuva)")),
+    ("18", _("Udmurtskaya Respublika")),
+    ("19", _("Khakassiya, Respublika")),
+    ("95", _("Chechenskaya Respublika")),
+    ("21", _("Chuvashskaya Respublika")),
+    ("22", _("Altayskiy Kray")),
+    ("80", _("Zabaykalskiy Kray")),
+    ("82", _("Kamchatskiy Kray")),
+    ("23", _("Krasnodarskiy Kray")),
+    ("24", _("Krasnoyarskiy Kray")),
+    ("81", _("Permskiy Kray")),
+    ("25", _("Primorskiy Kray")),
+    ("26", _("Stavropol'siyy Kray")),
+    ("27", _("Khabarovskiy Kray")),
+    ("28", _("Amurskaya oblast'")),
+    ("29", _("Arkhangel'skaya oblast'")),
+    ("30", _("Astrakhanskaya oblast'")),
+    ("31", _("Belgorodskaya oblast'")),
+    ("32", _("Bryanskaya oblast'")),
+    ("33", _("Vladimirskaya oblast'")),
+    ("34", _("Volgogradskaya oblast'")),
+    ("35", _("Vologodskaya oblast'")),
+    ("36", _("Voronezhskaya oblast'")),
+    ("37", _("Ivanovskaya oblast'")),
+    ("38", _("Irkutskaya oblast'")),
+    ("39", _("Kaliningradskaya oblast'")),
+    ("40", _("Kaluzhskaya oblast'")),
+    ("42", _("Kemerovskaya oblast'")),
+    ("43", _("Kirovskaya oblast'")),
+    ("44", _("Kostromskaya oblast'")),
+    ("45", _("Kurganskaya oblast'")),
+    ("46", _("Kurskaya oblast'")),
+    ("47", _("Leningradskaya oblast'")),
+    ("48", _("Lipeckaya oblast'")),
+    ("49", _("Magadanskaya oblast'")),
+    ("51", _("Murmanskaya oblast'")),
+    ("52", _("Nizhegorodskaja oblast'")),
+    ("53", _("Novgorodskaya oblast'")),
+    ("54", _("Novosibirskaya oblast'")),
+    ("55", _("Omskaya oblast'")),
+    ("56", _("Orenburgskaya oblast'")),
+    ("57", _("Orlovskaya oblast'")),
+    ("58", _("Penzenskaya oblast'")),
+    ("60", _("Pskovskaya oblast'")),
+    ("61", _("Rostovskaya oblast'")),
+    ("62", _("Rjazanskaya oblast'")),
+    ("63", _("Samarskaya oblast'")),
+    ("64", _("Saratovskaya oblast'")),
+    ("65", _("Sakhalinskaya oblast'")),
+    ("66", _("Sverdlovskaya oblast'")),
+    ("67", _("Smolenskaya oblast'")),
+    ("68", _("Tambovskaya oblast'")),
+    ("69", _("Tverskaya oblast'")),
+    ("70", _("Tomskaya oblast'")),
+    ("71", _("Tul'skaya oblast'")),
+    ("72", _("Tyumenskaya oblast'")),
+    ("73", _("Ul'ianovskaya oblast'")),
+    ("74", _("Chelyabinskaya oblast'")),
+    ("76", _("Yaroslavskaya oblast'")),
+    ("79", _("Evreyskaya avtonomnaja oblast'")),
+    ("83", _("Neneckiy autonomnyy okrug")),
+    ("86", _("Khanty-Mansiyskiy avtonomnyy okrug - Yugra")),
+    ("87", _("Chukotskiy avtonomnyy okrug")),
+    ("89", _("Yamalo-Neneckiy avtonomnyy okrug"))
+)

Modified: django/trunk/docs/ref/contrib/localflavor.txt
===================================================================
--- django/trunk/docs/ref/contrib/localflavor.txt       2011-04-22 12:03:18 UTC 
(rev 16075)
+++ django/trunk/docs/ref/contrib/localflavor.txt       2011-04-22 12:03:30 UTC 
(rev 16076)
@@ -63,6 +63,7 @@
     * Poland_
     * Portugal_
     * Romania_
+    * Russia_
     * Slovakia_
     * `South Africa`_
     * Spain_
@@ -113,6 +114,7 @@
 .. _Poland: `Poland (pl)`_
 .. _Portugal: `Portugal (pt)`_
 .. _Romania: `Romania (ro)`_
+.. _Russia: `Russia (ru)`_
 .. _Slovakia: `Slovakia (sk)`_
 .. _South Africa: `South Africa (za)`_
 .. _Spain: `Spain (es)`_
@@ -190,6 +192,8 @@
 Australia (``au``)
 =============================================
 
+.. versionadded:: 1.4
+
 .. class:: au.forms.AUPostCodeField
 
     A form field that validates input as an Australian postcode.
@@ -342,6 +346,8 @@
 China (``cn``)
 ==============
 
+.. versionadded:: 1.4
+
 .. class:: cn.forms.CNProvinceSelect
 
     A ``Select`` widget that uses a list of Chinese regions as its choices.
@@ -756,6 +762,34 @@
 
     A form field that validates Romanian postal codes.
 
+Russia (``ru``)
+===============
+
+.. versionadded:: 1.4
+
+.. class:: ru.forms.RUPostalCodeField
+
+    Russian Postal code field. The valid format is XXXXXX, where X is any
+    digit and the first digit is not zero.
+
+.. class:: ru.forms.RUCountySelect
+
+    A ``Select`` widget that uses a list of Russian Counties as its choices.
+
+.. class:: ru.forms.RURegionSelect
+
+    A ``Select`` widget that uses a list of Russian Regions as its choices.
+
+.. class:: ru.forms.RUPassportNumberField
+
+    Russian internal passport number. The valid format is XXXX XXXXXX, where X
+    is any digit.
+
+.. class:: ru.forms.RUAlienPassportNumberField
+
+    Russian alien's passport number. The valid format is XX XXXXXXX, where X
+    is any digit.
+
 Slovakia (``sk``)
 =================
 

Added: django/trunk/tests/regressiontests/forms/localflavor/ru.py
===================================================================
--- django/trunk/tests/regressiontests/forms/localflavor/ru.py                  
        (rev 0)
+++ django/trunk/tests/regressiontests/forms/localflavor/ru.py  2011-04-22 
12:03:30 UTC (rev 16076)
@@ -0,0 +1,148 @@
+from django.contrib.localflavor.ru.forms import *
+ 
+from utils import LocalFlavorTestCase
+
+
+class RULocalFlavorTests(LocalFlavorTestCase):
+
+    def test_RUPassportNumberField(self):
+        error = [u'Enter a passport number in the format XXXX XXXXXX.']
+        valid = {
+            '1981 211204': '1981 211204',
+            '0305 967876': '0305 967876',
+        }
+        invalid = {
+            '1981 2112044': error,
+            '1981 23220': error,
+            '9981211201': error,
+        }
+        self.assertFieldOutput(RUPassportNumberField, valid, invalid)
+
+    def test_RUAlienPassportNumberField(self):
+        error = [u'Enter a passport number in the format XX XXXXXXX.']
+        valid = {
+            '19 8111204': '19 8111204',
+            '03 0567876': '03 0567876',
+        }
+        invalid = {
+            '198 1112044': error,
+            '19 81123220': error,
+            '99 812112': error,
+        }
+        self.assertFieldOutput(RUAlienPassportNumberField, valid, invalid)
+
+    def test_RUPostalCodeField(self):
+        error = [u'Enter a postal code in the format XXXXXX.']
+        valid = {
+            '987654': '987654',
+            '123456': '123456'
+        }
+        invalid = {
+            '123 34': error,
+            '1234567': error,
+            '12345': error
+        }
+        self.assertFieldOutput(RUPostalCodeField, valid, invalid)
+
+    def test_RUCountySelect(self):
+        f = RUCountySelect()
+        out = u'''<select name="county">
+<option value="Central Federal County">Central Federal County</option>
+<option value="South Federal County">South Federal County</option>
+<option value="North-West Federal County">North-West Federal County</option>
+<option value="Far-East Federal County">Far-East Federal County</option>
+<option value="Siberian Federal County">Siberian Federal County</option>
+<option value="Ural Federal County">Ural Federal County</option>
+<option value="Privolzhsky Federal County">Privolzhsky Federal County</option>
+<option value="North-Caucasian Federal County">North-Caucasian Federal 
County</option>
+</select>'''
+        self.assertEqual(f.render('county', None), out)
+
+    def test_RURegionSelect(self):
+        f = RURegionSelect()
+        out = u'''<select name="region">
+<option value="77">Moskva</option>
+<option value="78">Saint-Peterburg</option>
+<option value="50">Moskovskaya oblast&#39;</option>
+<option value="01">Adygeya, Respublika</option>
+<option value="02">Bashkortostan, Respublika</option>
+<option value="03">Buryatia, Respublika</option>
+<option value="04">Altay, Respublika</option>
+<option value="05">Dagestan, Respublika</option>
+<option value="06">Ingushskaya Respublika</option>
+<option value="07">Kabardino-Balkarskaya Respublika</option>
+<option value="08">Kalmykia, Respublika</option>
+<option value="09">Karachaevo-Cherkesskaya Respublika</option>
+<option value="10">Karelia, Respublika</option>
+<option value="11">Komi, Respublika</option>
+<option value="12">Mariy Ehl, Respublika</option>
+<option value="13">Mordovia, Respublika</option>
+<option value="14">Sakha, Respublika (Yakutiya)</option>
+<option value="15">Severnaya Osetia, Respublika (Alania)</option>
+<option value="16">Tatarstan, Respublika</option>
+<option value="17">Tyva, Respublika (Tuva)</option>
+<option value="18">Udmurtskaya Respublika</option>
+<option value="19">Khakassiya, Respublika</option>
+<option value="95">Chechenskaya Respublika</option>
+<option value="21">Chuvashskaya Respublika</option>
+<option value="22">Altayskiy Kray</option>
+<option value="80">Zabaykalskiy Kray</option>
+<option value="82">Kamchatskiy Kray</option>
+<option value="23">Krasnodarskiy Kray</option>
+<option value="24">Krasnoyarskiy Kray</option>
+<option value="81">Permskiy Kray</option>
+<option value="25">Primorskiy Kray</option>
+<option value="26">Stavropol&#39;siyy Kray</option>
+<option value="27">Khabarovskiy Kray</option>
+<option value="28">Amurskaya oblast&#39;</option>
+<option value="29">Arkhangel&#39;skaya oblast&#39;</option>
+<option value="30">Astrakhanskaya oblast&#39;</option>
+<option value="31">Belgorodskaya oblast&#39;</option>
+<option value="32">Bryanskaya oblast&#39;</option>
+<option value="33">Vladimirskaya oblast&#39;</option>
+<option value="34">Volgogradskaya oblast&#39;</option>
+<option value="35">Vologodskaya oblast&#39;</option>
+<option value="36">Voronezhskaya oblast&#39;</option>
+<option value="37">Ivanovskaya oblast&#39;</option>
+<option value="38">Irkutskaya oblast&#39;</option>
+<option value="39">Kaliningradskaya oblast&#39;</option>
+<option value="40">Kaluzhskaya oblast&#39;</option>
+<option value="42">Kemerovskaya oblast&#39;</option>
+<option value="43">Kirovskaya oblast&#39;</option>
+<option value="44">Kostromskaya oblast&#39;</option>
+<option value="45">Kurganskaya oblast&#39;</option>
+<option value="46">Kurskaya oblast&#39;</option>
+<option value="47">Leningradskaya oblast&#39;</option>
+<option value="48">Lipeckaya oblast&#39;</option>
+<option value="49">Magadanskaya oblast&#39;</option>
+<option value="51">Murmanskaya oblast&#39;</option>
+<option value="52">Nizhegorodskaja oblast&#39;</option>
+<option value="53">Novgorodskaya oblast&#39;</option>
+<option value="54">Novosibirskaya oblast&#39;</option>
+<option value="55">Omskaya oblast&#39;</option>
+<option value="56">Orenburgskaya oblast&#39;</option>
+<option value="57">Orlovskaya oblast&#39;</option>
+<option value="58">Penzenskaya oblast&#39;</option>
+<option value="60">Pskovskaya oblast&#39;</option>
+<option value="61">Rostovskaya oblast&#39;</option>
+<option value="62">Rjazanskaya oblast&#39;</option>
+<option value="63">Samarskaya oblast&#39;</option>
+<option value="64">Saratovskaya oblast&#39;</option>
+<option value="65">Sakhalinskaya oblast&#39;</option>
+<option value="66">Sverdlovskaya oblast&#39;</option>
+<option value="67" selected="selected">Smolenskaya oblast&#39;</option>
+<option value="68">Tambovskaya oblast&#39;</option>
+<option value="69">Tverskaya oblast&#39;</option>
+<option value="70">Tomskaya oblast&#39;</option>
+<option value="71">Tul&#39;skaya oblast&#39;</option>
+<option value="72">Tyumenskaya oblast&#39;</option>
+<option value="73">Ul&#39;ianovskaya oblast&#39;</option>
+<option value="74">Chelyabinskaya oblast&#39;</option>
+<option value="76">Yaroslavskaya oblast&#39;</option>
+<option value="79">Evreyskaya avtonomnaja oblast&#39;</option>
+<option value="83">Neneckiy autonomnyy okrug</option>
+<option value="86">Khanty-Mansiyskiy avtonomnyy okrug - Yugra</option>
+<option value="87">Chukotskiy avtonomnyy okrug</option>
+<option value="89">Yamalo-Neneckiy avtonomnyy okrug</option>
+</select>'''
+        self.assertEqual(f.render('region', '67'), out)

Modified: django/trunk/tests/regressiontests/forms/localflavortests.py
===================================================================
--- django/trunk/tests/regressiontests/forms/localflavortests.py        
2011-04-22 12:03:18 UTC (rev 16075)
+++ django/trunk/tests/regressiontests/forms/localflavortests.py        
2011-04-22 12:03:30 UTC (rev 16076)
@@ -24,6 +24,7 @@
 from localflavor.pl import PLLocalFlavorTests
 from localflavor.pt import PTLocalFlavorTests
 from localflavor.ro import ROLocalFlavorTests
+from localflavor.ru import RULocalFlavorTests
 from localflavor.se import SELocalFlavorTests
 from localflavor.sk import SKLocalFlavorTests
 from localflavor.tr import TRLocalFlavorTests

Modified: django/trunk/tests/regressiontests/forms/tests/__init__.py
===================================================================
--- django/trunk/tests/regressiontests/forms/tests/__init__.py  2011-04-22 
12:03:18 UTC (rev 16075)
+++ django/trunk/tests/regressiontests/forms/tests/__init__.py  2011-04-22 
12:03:30 UTC (rev 16076)
@@ -38,6 +38,7 @@
     PLLocalFlavorTests,
     PTLocalFlavorTests,
     ROLocalFlavorTests,
+    RULocalFlavorTests,
     SELocalFlavorTests,
     SKLocalFlavorTests,
     TRLocalFlavorTests,

-- 
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