-
Notifications
You must be signed in to change notification settings - Fork 289
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add local flavor for Ukraine. (#273)
- Loading branch information
1 parent
0f4aa82
commit ecbcff4
Showing
12 changed files
with
271 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
Ukraine (``ua``) | ||
================ | ||
|
||
Forms | ||
----- | ||
|
||
.. automodule:: localflavor.ua.forms | ||
:members: | ||
|
||
Models | ||
------ | ||
|
||
.. automodule:: localflavor.ua.models | ||
:members: | ||
|
||
Data | ||
---- | ||
|
||
.. autodata:: localflavor.ua.ua_regions.UA_REGION_CHOICES |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from django.forms.fields import RegexField, Select | ||
from django.utils.translation import ugettext_lazy as _ | ||
|
||
from .ua_regions import UA_REGION_CHOICES | ||
|
||
|
||
class UARegionSelect(Select): | ||
""" | ||
A Select widget that uses a list of Ukrainian regions as its choices. | ||
.. versionadded:: 1.5 | ||
""" | ||
|
||
def __init__(self, *args, **kwargs): | ||
kwargs['choices'] = UA_REGION_CHOICES | ||
super(UARegionSelect, self).__init__(*args, **kwargs) | ||
|
||
|
||
class UAVatNumberField(RegexField): | ||
""" | ||
A form field that validates input as a Ukrainian analog of a VAT number. | ||
Valid format is XXXXXXXXXX. | ||
Whitespace around a VAT number is accepted and automatically trimmed. | ||
.. versionadded:: 1.5 | ||
""" | ||
|
||
default_error_messages = { | ||
'invalid': _('Enter a valid VAT number.'), | ||
} | ||
|
||
def __init__(self, *args, **kwargs): | ||
kwargs['max_length'] = kwargs['min_length'] = 10 | ||
super(UAVatNumberField, self).__init__(r'^\d{10}$', *args, **kwargs) | ||
|
||
def to_python(self, value): | ||
value = super(UAVatNumberField, self).to_python(value) | ||
return value.strip() | ||
|
||
|
||
class UAPostalCodeField(RegexField): | ||
""" | ||
A form field that validates input as a Ukrainian postal code. | ||
Valid format is XXXXX. Note: first two numbers cannot be '00'. | ||
Whitespace around a postal code is accepted and automatically trimmed. | ||
.. versionadded:: 1.5 | ||
""" | ||
|
||
default_error_messages = { | ||
'invalid': _('Enter a valid postal code.'), | ||
} | ||
|
||
def __init__(self, *args, **kwargs): | ||
kwargs['max_length'] = kwargs['min_length'] = 5 | ||
super(UAPostalCodeField, self).__init__(r'^(?!00)\d{5}$', *args, **kwargs) | ||
|
||
def to_python(self, value): | ||
value = super(UAPostalCodeField, self).to_python(value) | ||
return value.strip() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from django.core.validators import RegexValidator | ||
from django.db.models import CharField | ||
from django.utils.translation import ugettext_lazy as _ | ||
|
||
from .ua_regions import UA_REGION_CHOICES | ||
|
||
|
||
class UARegionField(CharField): | ||
""" | ||
A model field which stores a Ukrainian region. | ||
This field is represented by forms as | ||
a :class:`~localflavor.ua.forms.UARegionSelect` field. | ||
.. versionadded:: 1.5 | ||
""" | ||
|
||
description = _('Ukrainian region') | ||
|
||
def __init__(self, *args, **kwargs): | ||
kwargs['choices'] = UA_REGION_CHOICES | ||
kwargs['max_length'] = 5 | ||
super(UARegionField, self).__init__(*args, **kwargs) | ||
|
||
def deconstruct(self): | ||
name, path, args, kwargs = super(UARegionField, self).deconstruct() | ||
del kwargs['choices'] | ||
return name, path, args, kwargs | ||
|
||
|
||
class UAVatNumberField(CharField): | ||
""" | ||
A model field which stores a Ukrainian analog of a VAT number. | ||
This field is represented by forms as | ||
a :class:`~localflavor.ua.forms.UAVatNumberField` field. | ||
.. versionadded:: 1.5 | ||
""" | ||
|
||
description = _('Ukrainian VAT number') | ||
validators = [RegexValidator(r'^\d{10}$', 'Enter a valid VAT number.')] | ||
|
||
def __init__(self, *args, **kwargs): | ||
kwargs['max_length'] = 10 | ||
super(UAVatNumberField, self).__init__(*args, **kwargs) | ||
|
||
|
||
class UAPostalCodeField(CharField): | ||
""" | ||
A model field which stores a Ukrainian postal code. | ||
This field is represented by forms as | ||
a :class:`~localflavor.ua.forms.UAPostalCodeField` field. | ||
.. versionadded:: 1.5 | ||
""" | ||
|
||
description = _('Ukrainian postal code') | ||
validators = [RegexValidator(r'^(?!00)\d{5}$', 'Enter a valid postal code.')] | ||
|
||
def __init__(self, *args, **kwargs): | ||
kwargs['max_length'] = 5 | ||
super(UAPostalCodeField, self).__init__(*args, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
from django.utils.translation import ugettext_lazy as _ | ||
|
||
#: 24 oblasts, Avtonomna Respublika Krym and 2 cities with special status | ||
# Codes were gotten from ISO 3166-2:UA | ||
UA_REGION_CHOICES = ( | ||
('UA-71', _('Cherkasy Oblast')), | ||
('UA-74', _('Chernihiv Oblast')), | ||
('UA-77', _('Chernivtsi Oblast')), | ||
('UA-12', _('Dnipropetrovsk Oblast')), | ||
('UA-14', _('Donetsk Oblast')), | ||
('UA-26', _('Ivano-Frankivsk Oblast')), | ||
('UA-63', _('Kharkiv Oblast')), | ||
('UA-65', _('Kherson Oblast')), | ||
('UA-68', _('Khmelnytskyi Oblast')), | ||
('UA-35', _('Kirovohrad Oblast')), | ||
('UA-32', _('Kiev Oblast')), | ||
('UA-09', _('Luhansk Oblast')), | ||
('UA-46', _('Lviv Oblast')), | ||
('UA-48', _('Mykolaiv Oblast')), | ||
('UA-51', _('Odessa Oblast')), | ||
('UA-53', _('Poltava Oblast')), | ||
('UA-56', _('Rivne Oblast')), | ||
('UA-59', _('Sumy Oblast')), | ||
('UA-61', _('Ternopil Oblast')), | ||
('UA-05', _('Vinnytsia Oblast')), | ||
('UA-07', _('Volyn Oblast')), | ||
('UA-21', _('Zakarpattia Oblast')), | ||
('UA-23', _('Zaporizhia Oblast')), | ||
('UA-18', _('Zhytomyr Oblast')), | ||
('UA-43', _('Autonomous Republic of Crimea')), | ||
('UA-30', _('Kiev')), | ||
('UA-40', _('Sevastopol')) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from django.forms import ModelForm | ||
|
||
from .models import UAFlavorTestModel | ||
|
||
|
||
class UAFlavorTestForm(ModelForm): | ||
|
||
class Meta: | ||
model = UAFlavorTestModel | ||
fields = '__all__' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
from django.db import models | ||
|
||
from localflavor.ua.models import UAPostalCodeField, UARegionField, UAVatNumberField | ||
|
||
|
||
class UAFlavorTestModel(models.Model): | ||
postal_code = UAPostalCodeField() | ||
region = UARegionField() | ||
vat_number = UAVatNumberField() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
from django.test import TestCase | ||
|
||
from localflavor.ua.forms import UAPostalCodeField, UARegionSelect, UAVatNumberField | ||
from localflavor.ua.ua_regions import UA_REGION_CHOICES | ||
from .forms import UAFlavorTestForm | ||
|
||
|
||
class UALocalFlavorTests(TestCase): | ||
@classmethod | ||
def setUpTestData(cls): | ||
cls.form = UAFlavorTestForm({ | ||
'postal_code': '76000', | ||
'region': 'UA-26', | ||
'vat_number': '0000000000' | ||
}) | ||
|
||
def test_get_display_methods(self): | ||
flavor = self.form.save() | ||
self.assertEqual(flavor.get_region_display(), 'Ivano-Frankivsk Oblast') | ||
|
||
def test_errors(self): | ||
form = UAFlavorTestForm({ | ||
'postal_code': False, | ||
'region': False, | ||
'vat_number': False | ||
}) | ||
self.assertFalse(form.is_valid()) | ||
self.assertEqual(form.errors['postal_code'], ['Enter a valid postal code.']) | ||
self.assertEqual( | ||
form.errors['region'], ['Select a valid choice. False is not one of the available choices.'] | ||
) | ||
self.assertEqual(form.errors['vat_number'], ['Enter a valid VAT number.']) | ||
|
||
def test_UARegionSelect(self): | ||
out = '<select name="region">\n' | ||
for choice in UA_REGION_CHOICES: | ||
out += '<option value="{}">{}</option>\n'.format(choice[0], choice[1]) | ||
out += '</select>' | ||
self.assertHTMLEqual(UARegionSelect().render('region', None), out) | ||
|
||
def test_UAVatNumberField(self): | ||
error_format = ['Enter a valid VAT number.'] | ||
valid = { | ||
'1111111111': '1111111111', | ||
1234567890: '1234567890', | ||
' 0987654321 ': '0987654321' | ||
} | ||
invalid = { | ||
'abcdefghij': error_format, | ||
'123': ['Ensure this value has at least 10 characters (it has 3).'] + error_format, | ||
'98765432100': ['Ensure this value has at most 10 characters (it has 11).'] + error_format | ||
} | ||
self.assertFieldOutput(UAVatNumberField, valid, invalid) | ||
|
||
def test_UAPostalCodeField(self): | ||
error_format = ['Enter a valid postal code.'] | ||
valid = { | ||
'76000': '76000', | ||
10101: '10101', | ||
' 09876 ': '09876' | ||
} | ||
invalid = { | ||
'abcde': error_format, | ||
'00000': error_format, | ||
'123': ['Ensure this value has at least 5 characters (it has 3).'] + error_format, | ||
'987654': ['Ensure this value has at most 5 characters (it has 6).'] + error_format | ||
} | ||
self.assertFieldOutput(UAPostalCodeField, valid, invalid) |