Ejemplo n.º 1
0
    def __call__(self, value):
        if value is None:
            return value

        value = value.upper()

        # Length is 8 or 11.
        bic_length = len(value)
        if bic_length != 8 and bic_length != 11:
            raise ValidationError(
                _('BIC codes have either 8 or 11 characters.'))

        # First 4 letters are A - Z.
        institution_code = value[:4]
        for x in institution_code:
            if x not in string.ascii_uppercase:
                raise ValidationError(
                    _('%s is not a valid institution code.') %
                    institution_code)

        # Letters 5 and 6 consist of an ISO 3166-1 alpha-2 country code.
        country_code = value[4:6]
        if country_code not in ISO_3166_1_ALPHA2_COUNTRY_CODES:
            raise ValidationError(
                _('%s is not a valid country code.') % country_code)
Ejemplo n.º 2
0
    def __call__(self, value):
        """
        Validates the IBAN value using the official IBAN validation algorithm.

        https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
        """
        if value is None:
            return value

        value = value.upper().replace(' ', '').replace('-', '')

        # Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid.
        country_code = value[:2]
        if country_code in self.validation_countries:

            if self.validation_countries[country_code] != len(value):
                msg_params = {
                    'country_code': country_code,
                    'number': self.validation_countries[country_code]
                }
                raise ValidationError(
                    _('%(country_code)s IBANs must contain %(number)s characters.'
                      ) % msg_params)

        else:
            raise ValidationError(
                _('%s is not a valid country code for IBAN.') % country_code)
        if self.include_countries and country_code not in self.include_countries:
            raise ValidationError(
                _('%s IBANs are not allowed in this field.') % country_code)

        if self.iban_checksum(value) != value[2:4]:
            raise ValidationError(_('Not a valid IBAN.'))
Ejemplo n.º 3
0
class VATINValidator:
    """
    A validator for VAT identification numbers.

    Currently only supports European VIES VAT identification numbers.

    See See https://en.wikipedia.org/wiki/VAT_identification_number
    """

    messages = {
        'country_code': _('%(country_code)s is not a valid country code.'),
        'vatin': _('%(vatin)s is not a valid VAT identification number.'),
    }

    def __call__(self, value):
        country_code, number = self.clean(value)
        try:
            match = re.match(VATIN_PATTERN_MAP[country_code], value)
            if not match:
                raise ValidationError(self.messages['vatin'],
                                      code='vatin',
                                      params={'vatin': value})

        except KeyError:
            raise ValidationError(self.messages['country_code'],
                                  code='country_code',
                                  params={'country_code': country_code})

    def clean(self, value):
        """Return tuple of country code and number."""
        return value[:VATIN_COUNTRY_CODE_LENGTH], value[
            VATIN_COUNTRY_CODE_LENGTH:]
Ejemplo n.º 4
0
class CUProvinceField(CharValidator):
    """
    A form field for a Cuban province.

    The input is validated against a dictionary which includes names and abbreviations.
    It normalizes the input to the standard abbreviation for the given province.

    .. versionadded:: 1.6
    """

    default_error_messages = {
        'invalid': _('Enter a Cuban province.'),
    }
    description = _("Cuban provinces (three uppercase letters)")

    def __init__(self, *args, **kwargs):
        kwargs['choices'] = PROVINCE_CHOICES
        kwargs['max_length'] = 3
        super(CUProvinceField, self).__init__(*args, **kwargs)

    def clean(self, value):
        super(CUProvinceField, self).clean(value)
        if value in self.empty_values:
            return self.empty_value
        try:
            return PROVINCE_NORMALIZED[value.strip().lower()]
        except KeyError:
            pass
        raise ValidationError(self.error_messages['invalid'])
Ejemplo n.º 5
0
class GBPostalCodeField(CharValidator):
    """
    A form field that validates its input is a UK postcode.

    The regular expression used is sourced from the schema for British Standard
    BS7666 address types: http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd

    The value is uppercased and a space added in the correct place, if required.
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code.'),
    }
    outcode_pattern = '[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW])'
    incode_pattern = '[0-9][ABD-HJLNP-UW-Z]{2}'
    postcode_regex = re.compile(r'^(GIR 0AA|%s %s)$' %
                                (outcode_pattern, incode_pattern))
    space_regex = re.compile(r' *(%s)$' % incode_pattern)

    def clean(self, value):
        value = super(GBPostalCodeField, self).clean(value)
        if value in self.empty_values:
            return self.empty_value
        postcode = value.upper().strip()
        # Put a single space before the incode (second part).
        postcode = self.space_regex.sub(r' \1', postcode)
        if not self.postcode_regex.search(postcode):
            raise ValidationError(self.error_messages['invalid'])
        return postcode
Ejemplo n.º 6
0
class USStateField(CharValidator):
    """
    A form field that validates its input is a U.S. state, territory, or COFA territory.

    The input is validated against a dictionary which includes names and abbreviations.
    It normalizes the input to the standard two-letter postal service
    abbreviation for the given state.
    """

    default_error_messages = {
        'invalid': _('Enter a U.S. state or territory.'),
    }

    def clean(self, value):
        from .us_states import STATES_NORMALIZED
        super(USStateField, self).clean(value)
        if value in EMPTY_VALUES:
            return self.empty_value
        try:
            value = value.strip().lower()
        except AttributeError:
            pass
        else:
            try:
                return STATES_NORMALIZED[value.strip().lower()]
            except KeyError:
                pass
        raise ValidationError(self.error_messages['invalid'])
Ejemplo n.º 7
0
class NLPostalCodeField(RegexValidator):
    """
    Validation for Dutch zip codes.

    .. versionadded:: 1.3
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format NNNN XX.')
    }

    def __init__(self):
        super(NLPostalCodeField, self).__init__(regex=r'^\d{4} ?[A-Z]{2}$')

    def clean(self, value):
        value = value.upper()
        value = super(NLPostalCodeField, self).clean(value)

        if int(value[:4]) < 1000:
            raise ValidationError(self.error_messages['invalid'])

        if isinstance(value, six.string_types):
            value = value.upper().replace(' ', '')

            if len(value) == 6:
                value = '%s %s' % (value[:4], value[4:])

        return super(NLPostalCodeField, self).clean(value)
Ejemplo n.º 8
0
class HRPostalCodeField(CharValidator):
    """
    Postal code of Croatia field.

    It consists of exactly five digits ranging from 10000 to possibly less than 60000.

    http://www.posta.hr/main.aspx?id=66
    """

    default_error_messages = {
        'invalid': _('Enter a valid 5 digit postal code.'),
    }

    def clean(self, value):
        super(HRPostalCodeField, self).clean(value)
        if value in EMPTY_VALUES:
            return self.empty_value

        value = value.strip()
        if not postal_code_re.search(value):
            raise ValidationError(self.error_messages['invalid'])

        # Make sure the number is in valid range.
        if not 9999 < int(value) < 60000:
            raise ValidationError(self.error_messages['invalid'])

        return '%s' % value
Ejemplo n.º 9
0
class TRPostalCodeField(RegexValidator):
    """
    A form field that validates input as a Turkish zip code.

    Valid codes consist of five digits.
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XXXXX.'),
    }

    def __init__(self, max_length=5, min_length=5, *args, **kwargs):
        super(TRPostalCodeField, self).__init__(
            r'^\d{5}$', max_length=max_length, min_length=min_length,
            *args, **kwargs
        )

    def clean(self, value):
        value = super(TRPostalCodeField, self).clean(value)
        if value in self.empty_values:
            return self.empty_value
        if len(value) != 5:
            raise ValidationError(self.error_messages['invalid'])
        province_code = int(value[:2])
        if province_code == 0 or province_code > 81:
            raise ValidationError(self.error_messages['invalid'])
        return value
Ejemplo n.º 10
0
class EANValidator(object):
    """
    A generic validator for EAN like codes with the last digit being the checksum.

    http://en.wikipedia.org/wiki/International_Article_Number_(EAN)
    """

    message = _('Not a valid EAN code.')

    def __init__(self, strip_nondigits=False, message=None):
        if message is not None:
            self.message = message
        self.strip_nondigits = strip_nondigits

    def __eq__(self, other):
        return (not hasattr(self, 'message') or self.message == other.message) and \
            self.strip_nondigits == other.strip_nondigits

    def __call__(self, value):
        if value is None:
            return value
        if self.strip_nondigits:
            value = re.compile(r'[^\d]+').sub('', value)
        if not checksums.ean(value):
            raise ValidationError(self.message, code='invalid')
Ejemplo n.º 11
0
class DKPostalCodeField(ChoiceField):
    """An Input widget that uses a list of Danish postal codes as valid input."""

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XXXX.')
    }
    choices = DK_POSTALCODES
Ejemplo n.º 12
0
class SKPostalCodeField(RegexValidator):
    """
    A form field that validates its input as Slovak postal code.

    Valid form is XXXXX or XXX XX, where X represents integer.
    """

    default_error_messages = {
        'invalid':
        _('Enter a valid postal code in the format XXXXX or XXX XX.'),
    }

    def __init__(self, *args, **kwargs):
        super(SKPostalCodeField, self).__init__(r'^\d{5}$|^\d{3} \d{2}$',
                                                *args, **kwargs)

    def clean(self, value):
        """
        Validates the input and returns a string that contains only numbers.

        Returns an empty string for empty values.
        """
        value = super(SKPostalCodeField, self).clean(value)
        if value in self.empty_values:
            return self.empty_value
        return value.replace(' ', '')
Ejemplo n.º 13
0
class ARPostalCodeField(RegexValidator):
    """
    Accepts a 'classic' NNNN Postal Code or a CPA.

    See:

    * http://www.correoargentino.com.ar/cpa/que_es
    * http://www.correoargentino.com.ar/cpa/como_escribirlo
    """

    default_error_messages = {
        'invalid':
        _('Enter a valid postal code in the format NNNN or ANNNNAAA.'),
    }

    def __init__(self, max_length=8, min_length=4, *args, **kwargs):
        super(ARPostalCodeField,
              self).__init__(r'^\d{4}$|^[A-HJ-NP-Za-hj-np-z]\d{4}\D{3}$',
                             max_length=max_length,
                             min_length=min_length,
                             *args,
                             **kwargs)

    def clean(self, value):
        value = super(ARPostalCodeField, self).clean(value)
        if value in self.empty_values:
            return self.empty_value
        if len(value) not in (4, 8):
            raise ValidationError(self.error_messages['invalid'])
        if len(value) == 8:
            return '%s%s%s' % (value[0].upper(), value[1:5], value[5:].upper())
        return value
Ejemplo n.º 14
0
class INStateField(CharValidator):
    """
    A form field that validates its input is a Indian state name or abbreviation.

    It normalizes the input to the standard two-letter vehicle
    registration abbreviation for the given state or union territory

    .. versionchanged:: 1.1

       Added Telangana to list of states. More details at
       https://en.wikipedia.org/wiki/Telangana#Bifurcation_of_Andhra_Pradesh

    """

    default_error_messages = {
        'invalid': _('Enter an Indian state or territory.'),
    }

    def clean(self, value):
        value = super(INStateField, self).clean(value)
        if value in EMPTY_VALUES:
            return self.empty_value
        try:
            value = value.strip().lower()
        except AttributeError:
            pass
        else:
            try:
                return str(STATES_NORMALIZED[value.strip().lower()])
            except KeyError:
                pass
        raise ValidationError(self.error_messages['invalid'])
Ejemplo n.º 15
0
class IDPostalCodeField(CharValidator):
    """
    An Indonesian post code field.

    http://id.wikipedia.org/wiki/Kode_pos
    """

    default_error_messages = {
        'invalid': _('Enter a valid 5 digit postal code.'),
    }

    def clean(self, value):
        super(IDPostalCodeField, self).clean(value)
        if value in EMPTY_VALUES:
            return self.empty_value

        value = value.strip()
        if not postcode_re.search(value):
            raise ValidationError(self.error_messages['invalid'])

        if int(value) < 10110:
            raise ValidationError(self.error_messages['invalid'])

        # 1xxx0
        if value[0] == '1' and value[4] != '0':
            raise ValidationError(self.error_messages['invalid'])

        return '%s' % (value, )
Ejemplo n.º 16
0
class SIPostalCodeField(ChoiceField):
    """Slovenian post codes field."""

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XXXX.'),
    }

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('choices', SI_POSTALCODES_CHOICES)
        super(SIPostalCodeField, self).__init__(*args, **kwargs)
Ejemplo n.º 17
0
class ISPostalCodeField(CharValidator):
    """Validates Icelandic postal codes as its choices."""

    default_error_messages = {
        'invalid': _('Enter a valid 3 digit postal code.'),
    }

    def __init__(self):
        super(ISPostalCodeField, self).__init__(min_length=None,
                                                max_length=None,
                                                choices=IS_POSTALCODES)
Ejemplo n.º 18
0
class CUPostalCodeField(RegexValidator):
    """
    A form field for a Cuban postal Code.

    Taken from : http://mapanet.eu/Postal_Codes/?C=CU

    The Cuban postal code is a combination of 5 digits non begin with 0.

    .. versionadded:: 1.6
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XXXXX.'),
    }
    description = _("Cuban postal code")

    def __init__(self, *args, **kwargs):
        kwargs['max_length'] = 5
        super(CUPostalCodeField, self).__init__(r'^[1-9]\d{4}$', *args,
                                                **kwargs)
Ejemplo n.º 19
0
class SGPostalCodeField(RegexValidator):
    """
    Singapore post code field.

    Assumed to be 6 digits.
    """

    default_error_messages = {
        'invalid': _('Enter a 6-digit postal code.'),
    }

    def __init__(self, *args, **kwargs):
        super(SGPostalCodeField, self).__init__(r'^\d{6}$', *args, **kwargs)
Ejemplo n.º 20
0
class EEPostalCodeField(RegexValidator):
    """
    A form field that validates input as a Estonian zip code.

    Valid codes consist of five digits; first digit cannot be 0.
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XXXXX.'),
    }

    def __init__(self, *args, **kwargs):
        super(EEPostalCodeField, self).__init__(zipcode, *args, **kwargs)
Ejemplo n.º 21
0
class RUPostalCodeField(RegexValidator):
    """
    Russian Postal code field.

    Format: XXXXXX, where X is any digit, and first digit is not zero.
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XXXXXX.'),
    }

    def __init__(self, *args, **kwargs):
        super(RUPostalCodeField, self).__init__(r'^\d{6}$', *args, **kwargs)
Ejemplo n.º 22
0
class ITPostalCodeField(RegexValidator):
    """
    A form field that validates input as an Italian zip code.

    Valid codes must have five digits.
    """

    default_error_messages = {
        'invalid': _('Enter a 5 digit ZIP code.'),
    }

    def __init__(self, *args, **kwargs):
        super(ITPostalCodeField, self).__init__(r'^\d{5}$', *args, **kwargs)
Ejemplo n.º 23
0
class CNPostalCodeField(RegexValidator):
    """
    A form field that validates input as postal codes in mainland China.

    Valid codes are in the format of XXXXXX where X is a digit.
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XXXXXX.'),
    }

    def __init__(self, *args, **kwargs):
        super(CNPostalCodeField, self).__init__(POST_CODE_RE, *args, **kwargs)
Ejemplo n.º 24
0
class PLPostalCodeField(RegexValidator):
    """
    A form field that validates as Polish postal code.

    Valid code is XX-XXX where X is digit.
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XX-XXX.'),
    }

    def __init__(self, *args, **kwargs):
        super(PLPostalCodeField, self).__init__(r'^\d{2}-\d{3}$', *args, **kwargs)
Ejemplo n.º 25
0
class NOPostalCodeField(RegexValidator):
    """
    A form field that validates input as a Norwegian zip code.

    Valid codes have four digits.
    """

    default_error_messages = {
        'invalid': _('Enter a valid postal code in the format XXXX.'),
    }

    def __init__(self, *args, **kwargs):
        super(NOPostalCodeField, self).__init__(r'^\d{4}$', *args, **kwargs)
Ejemplo n.º 26
0
class AUPostalCodeField(RegexValidator):
    """
    Australian post code field.

    Assumed to be 4 digits.
    Northern Territory 3-digit postcodes should have leading zero.
    """

    default_error_messages = {
        'invalid': _('Enter a 4 digit postal code.'),
    }

    def __init__(self, max_length=4, *args, **kwargs):
        super(AUPostalCodeField, self).__init__(r'^\d{4}$', max_length=max_length, *args, **kwargs)