international phone number validator

W-Mark Kubacki <public-/[email protected]>
Newsgroups gmane.comp.python.formencode
Message-ID <[email protected]>
Hello group,

I'd like to share my (international) phone number validator with you.
Please see the attachment. Of course, any feedback is welcome.

I've already offered it Ian Bicking, but he didn't answer me whether he
liked it or whether it gets integrated.

As one cannot tell the US phone number 393-555-3939 from a (e.g.,)
german one, those formats are not accepted by the validator.


Es grüßt
W-Mark Kubacki

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

_______________________________________________
FormEncode-discuss mailing list
FormEncode-discuss-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/formencode-discuss
IPhoneNumberValidator.py (text/plain, 3.7 KB)
import re
import string
from gettext import gettext as _

from formencode.api import FancyValidator
from formencode.validators import Invalid

# from dbmanager.intl_util.validators@r313[208:303]
class IPhoneNumberValidator(FancyValidator):

    """
    Validates, and converts phone numbers to +##-###-#######.
    Adapted from RFC 3966

    ::

        >>> p = IPhoneNumberValidator()
        >>> p.to_python('333-3333')
        Traceback (most recent call last):
            ...
        Invalid: Please enter a number, with area code, in the form +##-###-#######.
        >>> p.to_python('0555/4860-300')
        '+49-555-4860-300'
        >>> p.to_python('0555-49924-51')
        '+49-555-49924-51'
        >>> p.to_python('0555/8114100')
        '+49-555-8114100'
        >>> p.to_python('0555 8114100')
        '+49-555-8114100'
        >>> p.to_python(' +49 (0)555 350 60 0')
        '+49-555-35060-0'
        >>> p.to_python('+49 555 350600')
        '+49-555-350600'
        >>> p.to_python('0049/ 555/ 871 82 96')
        '+49-555-87182-96'
        >>> p.to_python('0555-2 50-30')
        '+49-555-250-30'
        >>> p.to_python('(05 55)4 94 33 47')
        '+49-555-49433-47'
        >>> p.to_python('+973-555431')
        '+973-555431'
        >>> p.to_python('1-393-555-3939')
        '+1-393-555-3939'
        >>> p.to_python('+43 (1) 55528/0')
        '+43-1-55528-0'
        >>> p.to_python('+43 5555 429 62-0')
        '+43-5555-42962-0'
        >>> p.to_python('00 218 55 33 50 317 321')
        '+218-55-3350317-321'
        >>> p.to_python('+218 (0)55-3636639/38')
        '+218-55-3636639-38'
    """

    strip = True
    default_cc = 49
    _mark_translation = string.maketrans("_.!~*'/", "-------")
    _preTransformations = [
        (re.compile(r'^\((\d+)\s*(\d+)\)(.+)$'), '%s%s-%s'),
        (re.compile(r'^(?:1-)(\d+.+)$'), '+1-%s'),
        (re.compile(r'^00\s*(\d+.+)$'), '+%s'),
        (re.compile(r'^(\+\d+)\s+\(0\)\s*(\d+.+)$'), '%s-%s'),
        (re.compile(r'^(0\d+)\s(\d+)$'), '%s-%s'),
        ]
    _ccIncluder = [
        (re.compile(r'^0([1-9]\d*)\-(\d+.*)$'), '+%d-%s-%s'),
        ]
    _postTransformations = [
        (re.compile(r'^(\+\d+)[-\s]\(?(\d+)\)?[-\s](\d+.+)$'), '%s-%s-%s'),
        (re.compile(r'^(.+)\s(\d+)$'), '%s-%s'),
        ]
    _phoneIsSane = re.compile(r'^(\+[1-9]\d*)-([\d\-]+)$')

    messages = {
        'phoneFormat': _('Please enter a number, with area code, in the form +##-###-#######.'),
        }

    def _perform_rex_transformation(self, value, transformations):
        for rex, trf in transformations:
            match = rex.search(value)
            if match:
                value = trf % match.groups()
        return value

    def _prepend_country_code(self, value, transformations, country_code):
        for rex, trf in transformations:
            match = rex.search(value)
            if match:
                return trf % ((country_code,)+match.groups())
        return value

    def _to_python(self, value, state):
        self.assert_string(value, state)
        value = self._perform_rex_transformation(value, self._preTransformations)
        value = value.translate(self._mark_translation)
        value = self._prepend_country_code(value, self._ccIncluder, self.default_cc)
        for f, t in [('  ', ' '), ('--', '-'), (' - ', '-'), ('- ', '-'), (' -', '-')]:
            value = value.replace(f, t)
        value = self._perform_rex_transformation(value, self._postTransformations)
        value = value.replace(' ', '')
        # did we successfully transform that phone number? Thus, is it valid?
        if not self._phoneIsSane.search(value):
            raise Invalid(self.message('phoneFormat', state), value, state)
        return value
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.