Code

Ticket #14608: 14608.INPhoneNumberField.diff

File 14608.INPhoneNumberField.diff, 7.4 KB (added by julien, 3 years ago)

Actually hooked up tests

Line 
1diff --git a/django/contrib/localflavor/in_/forms.py b/django/contrib/localflavor/in_/forms.py
2index 0597623..8554e07 100644
3--- a/django/contrib/localflavor/in_/forms.py
4+++ b/django/contrib/localflavor/in_/forms.py
5@@ -4,15 +4,15 @@ India-specific Form helpers.
6 
7 from django.core.validators import EMPTY_VALUES
8 from django.forms import ValidationError
9-from django.forms.fields import Field, RegexField, Select
10+from django.forms.fields import Field, RegexField, Select, CharField
11 from django.utils.encoding import smart_unicode
12-from django.utils.translation import gettext
13+from django.utils.translation import ugettext_lazy as _
14 import re
15 
16 
17 class INZipCodeField(RegexField):
18     default_error_messages = {
19-        'invalid': gettext(u'Enter a zip code in the format XXXXXXX.'),
20+        'invalid': _(u'Enter a zip code in the format XXXXXXX.'),
21     }
22 
23     def __init__(self, *args, **kwargs):
24@@ -54,3 +54,47 @@ class INStateSelect(Select):
25         from in_states import STATE_CHOICES
26         super(INStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
27 
28+phone_digits_re = re.compile(r"""
29+     (
30+         (?P<std_code>                   # the std-code group
31+             ^0                          # all std-codes start with 0
32+             (
33+                 (?P<twodigit>\d{2})   | # either two, three or four digits
34+                 (?P<threedigit>\d{3}) | # following the 0
35+                 (?P<fourdigit>\d{4})
36+             )
37+         )
38+         [-\s]                           # space or -
39+         (?P<phone_no>                   # the phone number group
40+             [1-6]                       # first digit of phone number
41+             (
42+                 (?(twodigit)\d{7})   |  # 7 more phone digits for 3 digit stdcode
43+                 (?(threedigit)\d{6}) |  # 6 more phone digits for 4 digit stdcode
44+                 (?(fourdigit)\d{5})     # 5 more phone digits for 5 digit stdcode
45+             )
46+         )
47+     )$""", re.VERBOSE)
48+       
49+class INPhoneNumberField(CharField):
50+    """
51+        INPhoneNumberField validates that the data is a valid Indian phone number,
52+        including the STD code. It's normalised to 0XXX-XXXXXXX or 0XXX XXXXXXX format. The first
53+        string is the STD code which is a '0' followed by 2-4 digits. The second string
54+        is 8 digits if the STD code is 3 digits, 7 digits if the STD code is 4 digits and
55+        6 digits if the STD code is 5 digits. The second string will start with numbers
56+        between 1 and 6. The separator is either a space or a hyphen.
57+        """
58+    default_error_messages = {
59+        'invalid': _('Phone numbers must be in 02X-7X or 03X-6X or 04X-5X format.'),
60+    }
61+
62+    def clean(self, value):
63+        super(INPhoneNumberField, self).clean(value)
64+        if value in EMPTY_VALUES:
65+            return u''
66+        value = smart_unicode(value)
67+        m = phone_digits_re.match(value)
68+        if m:
69+            return u'%s' % (value)
70+        raise ValidationError(self.error_messages['invalid'])
71+
72diff --git a/docs/ref/contrib/localflavor.txt b/docs/ref/contrib/localflavor.txt
73index f54341e..cfdfe20 100644
74--- a/docs/ref/contrib/localflavor.txt
75+++ b/docs/ref/contrib/localflavor.txt
76@@ -440,21 +440,30 @@ Iceland (``is_``)
77 India (``in_``)
78 ===============
79 
80-.. class:: in.forms.INStateField
81+.. class:: in_.forms.INStateField
82 
83     A form field that validates input as an Indian state/territory name or
84     abbreviation. Input is normalized to the standard two-letter vehicle
85     registration abbreviation for the given state or territory.
86 
87-.. class:: in.forms.INZipCodeField
88+.. class:: in_.forms.INZipCodeField
89 
90     A form field that validates input as an Indian zip code, with the
91     format XXXXXXX.
92 
93-.. class:: in.forms.INStateSelect
94+.. class:: in_.forms.INStateSelect
95 
96     A ``Select`` widget that uses a list of Indian states/territories as its
97     choices.
98+   
99+.. class:: in_.forms.INPhoneNumberField
100+
101+    A form field that validates that the data is a valid Indian phone number,
102+    including the STD code. It's normalised to 0XXX-XXXXXXX or 0XXX XXXXXXX format. The first
103+    string is the STD code which is a '0' followed by 2-4 digits. The second string
104+    is 8 digits if the STD code is 3 digits, 7 digits if the STD code is 4 digits and
105+    6 digits if the STD code is 5 digits. The second string will start with numbers
106+    between 1 and 6. The separator is either a space or a hyphen.
107 
108 Ireland (``ie``)
109 ================
110diff --git a/tests/regressiontests/forms/localflavor/in_.py b/tests/regressiontests/forms/localflavor/in_.py
111new file mode 100644
112index 0000000..01eef7d
113--- /dev/null
114+++ b/tests/regressiontests/forms/localflavor/in_.py
115@@ -0,0 +1,24 @@
116+from django.contrib.localflavor.in_.forms import INPhoneNumberField
117+   
118+from utils import LocalFlavorTestCase
119+   
120+   
121+class INLocalFlavorTests(LocalFlavorTestCase):
122+    def test_INPhoneNumberField(self):
123+        error_format = [u'Phone numbers must be in 02X-7X or 03X-6X or 04X-5X format.']
124+        valid = {
125+            '0423-2443667': '0423-2443667',
126+            '0423 2443667': '0423 2443667',
127+            '04236-244366': '04236-244366',
128+            '040-24436678': '040-24436678',
129+        }
130+        invalid = {
131+            '04-2443667': error_format,
132+            '423-2443667': error_format,
133+            '0423-9442667': error_format,
134+            '0423-0443667': error_format,
135+            '0423-244366': error_format,
136+            '04232442667': error_format,
137+            '0423DJANGO': error_format,
138+        }
139+        self.assertFieldOutput(INPhoneNumberField, valid, invalid)
140diff --git a/tests/regressiontests/forms/localflavortests.py b/tests/regressiontests/forms/localflavortests.py
141index 5ee1c32..7ff68cd 100644
142--- a/tests/regressiontests/forms/localflavortests.py
143+++ b/tests/regressiontests/forms/localflavortests.py
144@@ -15,6 +15,7 @@ from localflavor.generic import GenericLocalFlavorTests
145 from localflavor.id import IDLocalFlavorTests
146 from localflavor.ie import IELocalFlavorTests
147 from localflavor.il import ILLocalFlavorTests
148+from localflavor.in_ import INLocalFlavorTests
149 from localflavor.is_ import ISLocalFlavorTests
150 from localflavor.it import ITLocalFlavorTests
151 from localflavor.jp import JPLocalFlavorTests
152diff --git a/tests/regressiontests/forms/tests/__init__.py b/tests/regressiontests/forms/tests/__init__.py
153index 2d96b2f..bc25b8a 100644
154--- a/tests/regressiontests/forms/tests/__init__.py
155+++ b/tests/regressiontests/forms/tests/__init__.py
156@@ -17,10 +17,10 @@ from regressiontests.forms.localflavortests import (
157     CHLocalFlavorTests, CLLocalFlavorTests, CZLocalFlavorTests,
158     DELocalFlavorTests, ESLocalFlavorTests, FILocalFlavorTests,
159     FRLocalFlavorTests, GenericLocalFlavorTests, IDLocalFlavorTests,
160-    IELocalFlavorTests, ILLocalFlavorTests, ISLocalFlavorTests,
161-    ITLocalFlavorTests, JPLocalFlavorTests, KWLocalFlavorTests,
162-    NLLocalFlavorTests, PLLocalFlavorTests, PTLocalFlavorTests,
163-    ROLocalFlavorTests, SELocalFlavorTests, SKLocalFlavorTests,
164-    TRLocalFlavorTests, UKLocalFlavorTests, USLocalFlavorTests,
165-    UYLocalFlavorTests, ZALocalFlavorTests
166+    IELocalFlavorTests, ILLocalFlavorTests, INLocalFlavorTests,
167+    ISLocalFlavorTests, ITLocalFlavorTests, JPLocalFlavorTests,
168+    KWLocalFlavorTests, NLLocalFlavorTests, PLLocalFlavorTests,
169+    PTLocalFlavorTests, ROLocalFlavorTests, SELocalFlavorTests,
170+    SKLocalFlavorTests, TRLocalFlavorTests, UKLocalFlavorTests,
171+    USLocalFlavorTests, UYLocalFlavorTests, ZALocalFlavorTests
172 )