Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added missing files from [6202] - sorry.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@6203 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 725716b5f5de01e374c9015d02baf25029a0f3c7 1 parent 7e4da4e
@jacobian jacobian authored
View
0  django/contrib/localflavor/ca/__init__.py
No changes.
View
57 django/contrib/localflavor/ca/ca_provinces.py
@@ -0,0 +1,57 @@
+"""
+An alphabetical list of provinces and territories for use as `choices`
+in a formfield., and a mapping of province misspellings/abbreviations to
+normalized abbreviations
+
+Source: http://www.canada.gc.ca/othergov/prov_e.html
+
+This exists in this standalone file so that it's only imported into memory
+when explicitly needed.
+"""
+
+PROVINCE_CHOICES = (
+ ('AB', 'Alberta'),
+ ('BC', 'British Columbia'),
+ ('MB', 'Manitoba'),
+ ('NB', 'New Brunswick'),
+ ('NF', 'Newfoundland and Labrador'),
+ ('NT', 'Northwest Territories'),
+ ('NS', 'Nova Scotia'),
+ ('NU', 'Nunavut'),
+ ('ON', 'Ontario'),
+ ('PE', 'Prince Edward Island'),
+ ('QC', 'Quebec'),
+ ('SK', 'Saskatchewan'),
+ ('YK', 'Yukon')
+)
+
+PROVINCES_NORMALIZED = {
+ 'ab': 'AB',
+ 'alberta': 'AB',
+ 'bc': 'BC',
+ 'b.c.': 'BC',
+ 'british columbia': 'BC',
+ 'mb': 'MB',
+ 'manitoba': 'MB',
+ 'nf': 'NF',
+ 'newfoundland': 'NF',
+ 'newfoundland and labrador': 'NF',
+ 'nt': 'NT',
+ 'northwest territories': 'NT',
+ 'ns': 'NS',
+ 'nova scotia': 'NS',
+ 'nu': 'NU',
+ 'nunavut': 'NU',
+ 'on': 'ON',
+ 'ontario': 'ON',
+ 'pe': 'PE',
+ 'pei': 'PE',
+ 'p.e.i.': 'PE',
+ 'prince edward island': 'PE',
+ 'qc': 'QC',
+ 'quebec': 'QC',
+ 'sk': 'SK',
+ 'saskatchewan': 'SK',
+ 'yk': 'YK',
+ 'yukon': 'YK',
+}
View
112 django/contrib/localflavor/ca/forms.py
@@ -0,0 +1,112 @@
+"""
+Canada-specific Form helpers
+"""
+
+from django.newforms import ValidationError
+from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
+from django.newforms.util import smart_unicode
+from django.utils.translation import gettext, ugettext
+import re
+
+phone_digits_re = re.compile(r'^(?:1-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$')
+sin_re = re.compile(r"^(\d{3})-(\d{3})-(\d{3})$")
+
+class CAPostalCodeField(RegexField):
+ """Canadian postal code field."""
+ def __init__(self, *args, **kwargs):
+ super(CAPostalCodeField, self).__init__(r'^[ABCEGHJKLMNPRSTVXYZ]\d[A-Z] \d[A-Z]\d$',
+ max_length=None, min_length=None,
+ error_message=gettext(u'Enter a postal code in the format XXX XXX.'),
+ *args, **kwargs)
+
+class CAPhoneNumberField(Field):
+ """Canadian phone number field."""
+ def clean(self, value):
+ """Validate a phone number.
+ """
+ super(CAPhoneNumberField, self).clean(value)
+ if value in EMPTY_VALUES:
+ return u''
+ value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
+ m = phone_digits_re.search(value)
+ if m:
+ return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
+ raise ValidationError(u'Phone numbers must be in XXX-XXX-XXXX format.')
+
+class CAProvinceField(Field):
+ """
+ A form field that validates its input is a Canadian province name or abbreviation.
+ It normalizes the input to the standard two-leter postal service
+ abbreviation for the given province.
+ """
+ def clean(self, value):
+ from ca_provinces import PROVINCES_NORMALIZED
+ super(CAProvinceField, self).clean(value)
+ if value in EMPTY_VALUES:
+ return u''
+ try:
+ value = value.strip().lower()
+ except AttributeError:
+ pass
+ else:
+ try:
+ return PROVINCES_NORMALIZED[value.strip().lower()].decode('ascii')
+ except KeyError:
+ pass
+ raise ValidationError(u'Enter a Canadian province or territory.')
+
+class CAProvinceSelect(Select):
+ """
+ A Select widget that uses a list of Canadian provinces and
+ territories as its choices.
+ """
+ def __init__(self, attrs=None):
+ from ca_provinces import PROVINCE_CHOICES # relative import
+ super(CAProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
+
+class CASocialInsuranceNumberField(Field):
+ """
+ A Canadian Social Insurance Number (SIN).
+
+ Checks the following rules to determine whether the number is valid:
+
+ * Conforms to the XXX-XXX-XXXX format.
+ * Passes the check digit process "Luhn Algorithm"
+ See: http://en.wikipedia.org/wiki/Social_Insurance_Number
+ """
+ def clean(self, value):
+ super(CASocialInsuranceNumberField, self).clean(value)
+ if value in EMPTY_VALUES:
+ return u''
+ msg = ugettext('Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.')
+ match = re.match(sin_re, value)
+ if not match:
+ raise ValidationError(msg)
+
+ number = u'%s-%s-%s' % (match.group(1), match.group(2), match.group(3))
+ check_number = u'%s%s%s' % (match.group(1), match.group(2), match.group(3))
+ if not self.luhn_checksum_is_valid(check_number):
+ raise ValidationError(msg)
+ return number
+
+ def luhn_checksum_is_valid(self, number):
+ """
+ Checks to make sure that the SIN passes a luhn mod-10 checksum
+ See: http://en.wikipedia.org/wiki/Luhn_algorithm
+ """
+
+ sum = 0
+ num_digits = len(number)
+ oddeven = num_digits & 1
+
+ for count in range(0, num_digits):
+ digit = int(number[count])
+
+ if not (( count & 1 ) ^ oddeven ):
+ digit = digit * 2
+ if digit > 9:
+ digit = digit - 9
+
+ sum = sum + digit
+
+ return ( (sum % 10) == 0 )
Please sign in to comment.
Something went wrong with that request. Please try again.