Code

Ticket #14349: be_localflavor.5.diff

File be_localflavor.5.diff, 13.8 KB (added by laurentluce, 4 years ago)

update docs and unit tests for phone number with dots in format as seen in use in Belgium

Line 
1Index: django/contrib/localflavor/be/be_regions.py
2===================================================================
3--- django/contrib/localflavor/be/be_regions.py (revision 0)
4+++ django/contrib/localflavor/be/be_regions.py (revision 0)
5@@ -0,0 +1,10 @@
6+# -*- coding: utf-8 -*-
7+from django.utils.translation import ugettext_lazy as _
8+
9+# ISO codes
10+REGION_CHOICES = (
11+    ('BRU', _('Brussels Capital Region')),
12+    ('VLG', _('Flemish Region')),
13+    ('WAL', _('Wallonia'))
14+)
15+
16Index: django/contrib/localflavor/be/be_provinces.py
17===================================================================
18--- django/contrib/localflavor/be/be_provinces.py       (revision 0)
19+++ django/contrib/localflavor/be/be_provinces.py       (revision 0)
20@@ -0,0 +1,18 @@
21+# -*- coding: utf-8 -*-
22+from django.utils.translation import ugettext_lazy as _
23+
24+# ISO codes
25+PROVINCE_CHOICES = (
26+    ('VAN', _('Antwerp')),
27+    ('BRU', _('Brussels')),
28+    ('VOV', _('East Flanders')),
29+    ('VBR', _('Flemish Brabant')),
30+    ('WHT', _('Hainaut')),
31+    ('WLG', _('Liege')),
32+    ('VLI', _('Limburg')),
33+    ('WLX', _('Luxembourg')),
34+    ('WNA', _('Namur')),
35+    ('WBR', _('Walloon Brabant')),
36+    ('VWV', _('West Flanders'))
37+)
38+
39Index: django/contrib/localflavor/be/__init__.py
40===================================================================
41Index: django/contrib/localflavor/be/forms.py
42===================================================================
43--- django/contrib/localflavor/be/forms.py      (revision 0)
44+++ django/contrib/localflavor/be/forms.py      (revision 0)
45@@ -0,0 +1,73 @@
46+# -*- coding: utf-8 -*-
47+"""
48+Belgium-specific Form helpers
49+"""
50+
51+from django.core.validators import EMPTY_VALUES
52+from django.forms import ValidationError
53+from django.forms.fields import RegexField, Select
54+from django.utils.translation import ugettext_lazy as _
55+import re
56+
57+class BEPostalCodeField(RegexField):
58+    """
59+    A form field that validates its input as a belgium postal code.
60+   
61+    Belgium postal code is a 4 digits string. The first digit indicates
62+    the province (except for the 3ddd numbers that are shared by the
63+    eastern part of Flemish Brabant and Limburg and the and 1ddd that
64+    are shared by the Brussels Capital Region, the western part of
65+    Flemish Brabant and Walloon Brabant)
66+    """
67+    default_error_messages = {
68+        'invalid': _('Enter a valid postal code in the range and format \
69+1XXX - 9XXX.'),
70+    }
71+
72+    def __init__(self, *args, **kwargs):
73+        super(BEPostalCodeField, self).__init__(
74+                r'^[1-9]\d{3}$',
75+                max_length=None, min_length=None, *args, **kwargs)
76+
77+class BEPhoneNumberField(RegexField):
78+    """
79+    A form field that validates its input as a belgium phone number.
80+
81+    Landlines have a seven-digit subscriber number and a one-digit area code,
82+    while smaller cities have a six-digit subscriber number and a two-digit
83+    area code. Cell phones have a six-digit subscriber number and a two-digit
84+    area code preceeded by the number 4.
85+    0d ddd dd dd, 0d/ddd.dd.dd, 0d.ddd.dd.dd,
86+    0dddddddd - dialling a bigger city
87+    0dd dd dd dd, 0dd/dd.dd.dd, 0dd.dd.dd.dd,
88+    0dddddddd - dialling a smaller city
89+    04dd ddd dd dd, 04dd/ddd.dd.dd,
90+    04dd.ddd.dd.dd, 04ddddddddd - dialling a mobile number
91+    """
92+    default_error_messages = {
93+        'invalid': _('Enter a valid phone number in one of the formats \
94+0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx, 0xx/xx.xx.xx, \
95+04xx/xx.xx.xx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx, 0xxxxxxxx, \
96+04xxxxxxxx.'),
97+    }
98+
99+    def __init__(self, *args, **kwargs):
100+        super(BEPhoneNumberField, self).__init__(r'^[0]\d{1}[/. ]?\d{3}[. ]\d{2}[. ]?\d{2}$|^[0]\d{2}[/. ]?\d{2}[. ]?\d{2}[. ]?\d{2}$|^[0][4]\d{2}[/. ]?\d{2}[. ]?\d{2}[. ]?\d{2}$',
101+            max_length=None, min_length=None, *args, **kwargs)
102+
103+class BERegionSelect(Select):
104+    """
105+    A Select widget that uses a list of belgium regions as its choices.
106+    """
107+    def __init__(self, attrs=None):
108+        from be_regions import REGION_CHOICES
109+        super(BERegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
110+
111+class BEProvinceSelect(Select):
112+    """
113+    A Select widget that uses a list of belgium provinces as its choices.
114+    """
115+    def __init__(self, attrs=None):
116+        from be_provinces import PROVINCE_CHOICES
117+        super(BEProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
118+
119Index: tests/regressiontests/forms/tests.py
120===================================================================
121--- tests/regressiontests/forms/tests.py        (revision 13984)
122+++ tests/regressiontests/forms/tests.py        (working copy)
123@@ -40,6 +40,7 @@
124 from fields import FieldsTests
125 from validators import TestFieldWithValidators
126 from widgets import WidgetTests, ClearableFileInputTests
127+from localflavor.be import BETests
128 
129 from input_formats import *
130 
131Index: tests/regressiontests/forms/localflavor/be.py
132===================================================================
133--- tests/regressiontests/forms/localflavor/be.py       (revision 0)
134+++ tests/regressiontests/forms/localflavor/be.py       (revision 0)
135@@ -0,0 +1,97 @@
136+# -*- coding: utf-8 -*-
137+# Tests for the contrib/localflavor/ BE form fields.
138+
139+from django.test import TestCase
140+from django.forms import *
141+
142+from django.contrib.localflavor.be.forms import BEPostalCodeField, BEPhoneNumberField, BERegionSelect, BEProvinceSelect
143+
144+class BETests(TestCase):
145+    """
146+    Test case to validate BE localflavor
147+    """
148+    def assertRaisesErrorWithMessage(self, error, message, callable, *args, **kwargs):
149+        self.assertRaises(error, callable, *args, **kwargs)
150+        try:
151+            callable(*args, **kwargs)
152+        except error, e:
153+            self.assertEqual(message, str(e))
154+
155+    def test_postal_code_field(self):
156+        f = BEPostalCodeField()
157+        self.assertEqual(u'1451', f.clean('1451'))
158+        self.assertEqual(u'2540', f.clean('2540'))
159+        err_message = "[u'Enter a valid postal code in the range and format 1XXX - 9XXX.']"
160+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '0287')
161+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '14309')
162+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '873')
163+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '35 74')
164+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '859A')
165+        err_message = "[u'This field is required.']"
166+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '')
167+        f = BEPostalCodeField(required=False)
168+        self.assertEqual(u'1451', f.clean('1451'))
169+        self.assertEqual(u'2540', f.clean('2540'))
170+        self.assertEqual(u'', f.clean(''))
171+        err_message = "[u'Enter a valid postal code in the range and format 1XXX - 9XXX.']"
172+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '0287')
173+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '14309')
174+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '873')
175+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '35 74')
176+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '859A')
177+
178+    def test_phone_number_field(self):
179+        f = BEPhoneNumberField()
180+        self.assertEqual(u'01 234 56 78', f.clean('01 234 56 78'))
181+        self.assertEqual(u'01/234.56.78', f.clean('01/234.56.78'))
182+        self.assertEqual(u'01.234.56.78', f.clean('01.234.56.78'))
183+        self.assertEqual(u'012 34 56 78', f.clean('012 34 56 78'))
184+        self.assertEqual(u'012/34.56.78', f.clean('012/34.56.78'))
185+        self.assertEqual(u'012.34.56.78', f.clean('012.34.56.78'))
186+        self.assertEqual(u'0412 34 56 78', f.clean('0412 34 56 78'))
187+        self.assertEqual(u'0412/34.56.78', f.clean('0412/34.56.78'))
188+        self.assertEqual(u'0412.34.56.78', f.clean('0412.34.56.78'))
189+        self.assertEqual(u'012345678', f.clean('012345678'))
190+        self.assertEqual(u'0412345678', f.clean('0412345678'))
191+        err_message = "[u'Enter a valid phone number in one of the formats 0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx, 0xx/xx.xx.xx, 04xx/xx.xx.xx, 0xxxxxxxx, 04xxxxxxxx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx.']"
192+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '01234567')
193+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '12/345.67.89')
194+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/345.678.90')
195+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/34.56.789')
196+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '0123/45.67.89')
197+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/345 678 90')
198+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/34 56 789')
199+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012.34 56 789')
200+        err_message = "[u'This field is required.']"
201+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '')
202+        f = BEPhoneNumberField(required=False)
203+        self.assertEqual(u'01 234 56 78', f.clean('01 234 56 78'))
204+        self.assertEqual(u'01/234.56.78', f.clean('01/234.56.78'))
205+        self.assertEqual(u'01.234.56.78', f.clean('01.234.56.78'))
206+        self.assertEqual(u'012 34 56 78', f.clean('012 34 56 78'))
207+        self.assertEqual(u'012/34.56.78', f.clean('012/34.56.78'))
208+        self.assertEqual(u'012.34.56.78', f.clean('012.34.56.78'))
209+        self.assertEqual(u'0412 34 56 78', f.clean('0412 34 56 78'))
210+        self.assertEqual(u'0412/34.56.78', f.clean('0412/34.56.78'))
211+        self.assertEqual(u'0412.34.56.78', f.clean('0412.34.56.78'))
212+        self.assertEqual(u'012345678', f.clean('012345678'))
213+        self.assertEqual(u'0412345678', f.clean('0412345678'))
214+        self.assertEqual(u'', f.clean(''))
215+        err_message = "[u'Enter a valid phone number in one of the formats 0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx, 0xx/xx.xx.xx, 04xx/xx.xx.xx, 0xxxxxxxx, 04xxxxxxxx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx.']"
216+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '01234567')
217+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '12/345.67.89')
218+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/345.678.90')
219+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/34.56.789')
220+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '0123/45.67.89')
221+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/345 678 90')
222+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012/34 56 789')
223+        self.assertRaisesErrorWithMessage(ValidationError, err_message, f.clean, '012.34 56 789')
224+
225+    def test_phone_number_field(self):
226+        w = BERegionSelect()
227+        self.assertEqual(u'<select name="regions">\n<option value="BRU">Brussels Capital Region</option>\n<option value="VLG" selected="selected">Flemish Region</option>\n<option value="WAL">Wallonia</option>\n</select>', w.render('regions', 'VLG'))
228+
229+    def test_phone_number_field(self):
230+        w = BEProvinceSelect()
231+        self.assertEqual(u'<select name="provinces">\n<option value="VAN">Antwerp</option>\n<option value="BRU">Brussels</option>\n<option value="VOV">East Flanders</option>\n<option value="VBR">Flemish Brabant</option>\n<option value="WHT">Hainaut</option>\n<option value="WLG" selected="selected">Liege</option>\n<option value="VLI">Limburg</option>\n<option value="WLX">Luxembourg</option>\n<option value="WNA">Namur</option>\n<option value="WBR">Walloon Brabant</option>\n<option value="VWV">West Flanders</option>\n</select>', w.render('provinces', 'WLG'))
232+
233Index: AUTHORS
234===================================================================
235--- AUTHORS     (revision 13984)
236+++ AUTHORS     (working copy)
237@@ -307,6 +307,7 @@
238     Simon Litchfield <simon@quo.com.au>
239     Daniel Lindsley <polarcowz@gmail.com>
240     Trey Long <trey@ktrl.com>
241+    Laurent Luce <http://www.laurentluce.com>
242     Martin Mahner <http://www.mahner.org/>
243     Matt McClanahan <http://mmcc.cx/>
244     Stanislaus Madueke
245Index: docs/ref/contrib/localflavor.txt
246===================================================================
247--- docs/ref/contrib/localflavor.txt    (revision 13984)
248+++ docs/ref/contrib/localflavor.txt    (working copy)
249@@ -39,6 +39,7 @@
250     * Argentina_
251     * Australia_
252     * Austria_
253+    * Belgium_
254     * Brazil_
255     * Canada_
256     * Chile_
257@@ -85,6 +86,7 @@
258 .. _Argentina: `Argentina (ar)`_
259 .. _Australia: `Australia (au)`_
260 .. _Austria: `Austria (at)`_
261+.. _Belgium: `Belgium (be)`_
262 .. _Brazil: `Brazil (br)`_
263 .. _Canada: `Canada (ca)`_
264 .. _Chile: `Chile (cl)`_
265@@ -182,6 +184,31 @@
266 
267     A form field that validates its input as an Austrian social security number.
268 
269+Belgium (``be``)
270+================
271+
272+.. class:: be.forms.BEPhoneNumberField
273+
274+    A form field that validates input as a Belgium phone number, with one of
275+    the formats 0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, 0x/xxx.xx.xx,
276+    0xx/xx.xx.xx, 04xx/xx.xx.xx, 0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx,
277+    0xxxxxxxx, 04xxxxxxxx.
278+
279+.. class:: be.forms.BEPostalCodeField
280+
281+    A form field that validates input as a Belgium postal code, in the range
282+    and format 1XXX-9XXX.
283+
284+.. class:: be.forms.BEProvinceSelect
285+
286+    A ``Select`` widget that uses a list of Belgium provinces as its
287+    choices.
288+
289+.. class:: be.forms.BERegionSelect
290+
291+    A ``Select`` widget that uses a list of Belgium regions as its
292+    choices.
293+
294 Brazil (``br``)
295 ===============
296