You can subscribe to this list here.
| 2004 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(10) |
Dec
(4) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2005 |
Jan
(1) |
Feb
(8) |
Mar
(8) |
Apr
(4) |
May
(19) |
Jun
(1) |
Jul
(1) |
Aug
(18) |
Sep
(18) |
Oct
(19) |
Nov
(75) |
Dec
(80) |
| 2006 |
Jan
(86) |
Feb
(61) |
Mar
(60) |
Apr
(47) |
May
(39) |
Jun
(16) |
Jul
(30) |
Aug
(13) |
Sep
(13) |
Oct
(21) |
Nov
(1) |
Dec
(10) |
| 2007 |
Jan
(2) |
Feb
(7) |
Mar
(9) |
Apr
(3) |
May
(9) |
Jun
(4) |
Jul
(1) |
Aug
(2) |
Sep
|
Oct
(12) |
Nov
(1) |
Dec
(7) |
| 2008 |
Jan
|
Feb
(2) |
Mar
(14) |
Apr
(9) |
May
(23) |
Jun
(4) |
Jul
|
Aug
(13) |
Sep
(8) |
Oct
(15) |
Nov
(40) |
Dec
(14) |
| 2009 |
Jan
|
Feb
(4) |
Mar
(10) |
Apr
(2) |
May
(2) |
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <sub...@co...> - 2008-08-13 14:28:03
|
Author: mark Date: 2008-08-13 08:28:10 -0600 (Wed, 13 Aug 2008) New Revision: 3557 Modified: FormEncode/trunk/formencode/national.py Log: importing string is not needed anymore Modified: FormEncode/trunk/formencode/national.py =================================================================== --- FormEncode/trunk/formencode/national.py 2008-08-13 14:23:20 UTC (rev 3556) +++ FormEncode/trunk/formencode/national.py 2008-08-13 14:28:10 UTC (rev 3557) @@ -1,5 +1,4 @@ import re -import string from api import FancyValidator from compound import Any from validators import Regex, Invalid, _ |
|
From: <sub...@co...> - 2008-08-13 14:23:10
|
Author: mark
Date: 2008-08-13 08:23:20 -0600 (Wed, 13 Aug 2008)
New Revision: 3556
Modified:
FormEncode/trunk/formencode/national.py
Log:
support callables in InternationalPhoneNumber to provide a default country code dynamically
Modified: FormEncode/trunk/formencode/national.py
===================================================================
--- FormEncode/trunk/formencode/national.py 2008-08-13 14:10:30 UTC (rev 3555)
+++ FormEncode/trunk/formencode/national.py 2008-08-13 14:23:20 UTC (rev 3556)
@@ -504,8 +504,14 @@
Validates, and converts phone numbers to +##-###-#######.
Adapted from RFC 3966
+ @param default_cc country code for prepending if none is provided
+ can be a paramerless callable
+
::
+ >>> c = InternationalPhoneNumber(default_cc=lambda: 49)
+ >>> c.to_python('0555/8114100')
+ '+49-555-8114100'
>>> p = InternationalPhoneNumber(default_cc=49)
>>> p.to_python('333-3333')
Traceback (most recent call last):
@@ -604,7 +610,11 @@
value = value.replace(f, t)
value = self._perform_rex_transformation(value, self._preTransformations)
if self.default_cc:
- value = self._prepend_country_code(value, self._ccIncluder, self.default_cc)
+ if callable(self.default_cc):
+ cc = self.default_cc()
+ else:
+ cc = self.default_cc
+ value = self._prepend_country_code(value, self._ccIncluder, cc)
value = self._perform_rex_transformation(value, self._postTransformations)
value = value.replace(' ', '')
# did we successfully transform that phone number? Thus, is it valid?
|
|
From: <sub...@co...> - 2008-08-13 14:10:20
|
Author: mark
Date: 2008-08-13 08:10:30 -0600 (Wed, 13 Aug 2008)
New Revision: 3555
Modified:
FormEncode/trunk/formencode/national.py
Log:
formatstrings in common format for postal code explanations (in English)
Modified: FormEncode/trunk/formencode/national.py
===================================================================
--- FormEncode/trunk/formencode/national.py 2008-08-13 14:02:09 UTC (rev 3554)
+++ FormEncode/trunk/formencode/national.py 2008-08-13 14:10:30 UTC (rev 3555)
@@ -183,14 +183,14 @@
>>> ArgentinianPostalCode.to_python('5555')
Traceback (most recent call last):
...
- Invalid: Please enter a zip code (CNNNNCCC)
+ Invalid: Please enter a zip code (LnnnnLLL)
"""
regex = re.compile(r'^([a-zA-Z]{1})\s*(\d{4})\s*([a-zA-Z]{3})$')
strip = True
messages = {
- 'invalid': _("Please enter a zip code (%s)") % _("CNNNNCCC"),
+ 'invalid': _("Please enter a zip code (%s)") % _("LnnnnLLL"),
}
def _to_python(self, value, state):
@@ -218,14 +218,14 @@
>>> CanadianPostalCode.to_python('5555')
Traceback (most recent call last):
...
- Invalid: Please enter a zip code (CNC NCN)
+ Invalid: Please enter a zip code (LnL nLn)
"""
regex = re.compile(r'^([a-zA-Z]\d[a-zA-Z])\s?(\d[a-zA-Z]\d)$')
strip = True
messages = {
- 'invalid': _("Please enter a zip code (%s)") % _("CNC NCN"),
+ 'invalid': _("Please enter a zip code (%s)") % _("LnL nLn"),
}
def _to_python(self, value, state):
|
|
From: <sub...@co...> - 2008-08-13 14:02:01
|
Author: mark
Date: 2008-08-13 08:02:09 -0600 (Wed, 13 Aug 2008)
New Revision: 3554
Modified:
FormEncode/trunk/formencode/national.py
Log:
DelimitedDigitsPostalCode to support even more exotic postal codes
Modified: FormEncode/trunk/formencode/national.py
===================================================================
--- FormEncode/trunk/formencode/national.py 2008-08-13 13:12:36 UTC (rev 3553)
+++ FormEncode/trunk/formencode/national.py 2008-08-13 14:02:09 UTC (rev 3554)
@@ -73,8 +73,8 @@
"""
Abstraction of common postal code formats, such as 55555, 55-555 etc.
- With constant amount of digits. You can set the right block to 0 to
- obtain a trivial 'x digits' postal code validator.
+ With constant amount of digits. By providing a single digit as partition you
+ can obtain a trivial 'x digits' postal code validator.
::
@@ -85,7 +85,7 @@
Traceback (most recent call last):
...
Invalid: Please enter a zip code (5 digits)
- >>> polish = DelimitedDigitsPostalCode(2, '-', 3)
+ >>> polish = DelimitedDigitsPostalCode([2, 3], '-')
>>> polish.to_python('55555')
'55-555'
>>> polish.to_python('55-555')
@@ -94,20 +94,39 @@
Traceback (most recent call last):
...
Invalid: Please enter a zip code (nn-nnn)
+ >>> nicaragua = DelimitedDigitsPostalCode([3, 3, 1], '-')
+ >>> nicaragua.to_python('5554443')
+ '555-444-3'
+ >>> nicaragua.to_python('555-4443')
+ '555-444-3'
+ >>> nicaragua.to_python('5555')
+ Traceback (most recent call last):
+ ...
+ Invalid: Please enter a zip code (nnn-nnn-n)
"""
strip = True
- def __init__(self, length_left_block, delimiter = None, length_right_block = 0, \
+ def assembly_formatstring(self, partition_lengths, delimiter):
+ if len(partition_lengths) == 1:
+ return _("%d digits") % partition_lengths[0]
+ else:
+ return delimiter.join(['n'*l for l in partition_lengths])
+
+ def assembly_regex(self, partition_lengths, delimiter):
+ mg = [r"(\d{%d})" % l for l in partition_lengths]
+ rd = r"\%s?" % delimiter
+ return rd.join(mg)
+
+ def __init__(self, partition_lengths, delimiter = None, \
*args, **kw):
- (self.length_left_block, self.delimiter, self.length_right_block) \
- = (length_left_block, delimiter, length_right_block)
- if length_right_block > 0:
- self.format = delimiter.join(['n'*length_left_block, 'n'*length_right_block])
- self.regex = r'^(\d{%d})\%s?(\d{%d})$' % (length_left_block, delimiter, length_right_block)
- else:
- self.format = _("%d digits") % length_left_block
- self.regex = r'^(\d{%d})$' % length_left_block
+ if type(partition_lengths) == type(1):
+ partition_lengths = [partition_lengths]
+ if not delimiter:
+ delimiter = ''
+ self.format = self.assembly_formatstring(partition_lengths, delimiter)
+ self.regex = self.assembly_regex(partition_lengths, delimiter)
+ (self.partition_lengths, self.delimiter) = (partition_lengths, delimiter)
Regex.__init__(self, *args, **kw)
messages = {
@@ -120,10 +139,7 @@
if not match:
raise Invalid(
self.message('invalid', state) % self.format, value, state)
- if self.delimiter:
- return ''.join([match.group(1), self.delimiter, match.group(2)])
- else:
- return match.group(1)
+ return self.delimiter.join(match.groups())
def USPostalCode(*args, **kw):
"""
@@ -141,17 +157,17 @@
...
Invalid: Please enter a zip code (5 digits)
"""
- return Any(DelimitedDigitsPostalCode(5, None, 0, *args, **kw),
- DelimitedDigitsPostalCode(5, '-', 4, *args, **kw))
+ return Any(DelimitedDigitsPostalCode(5, None, *args, **kw),
+ DelimitedDigitsPostalCode([5, 4], '-', *args, **kw))
def GermanPostalCode(*args, **kw):
- return DelimitedDigitsPostalCode(5, None, 0, *args, **kw)
+ return DelimitedDigitsPostalCode(5, None, *args, **kw)
def FourDigitsPostalCode(*args, **kw):
- return DelimitedDigitsPostalCode(4, None, 0, *args, **kw)
+ return DelimitedDigitsPostalCode(4, None, *args, **kw)
def PolishPostalCode(*args, **kw):
- return DelimitedDigitsPostalCode(2, '-', 3, *args, **kw)
+ return DelimitedDigitsPostalCode([2, 3], '-', *args, **kw)
class ArgentinianPostalCode(Regex):
@@ -319,18 +335,38 @@
'AR': ArgentinianPostalCode,
'AT': FourDigitsPostalCode,
'BE': FourDigitsPostalCode,
+ 'BG': FourDigitsPostalCode,
'CA': CanadianPostalCode,
'CL': lambda: DelimitedDigitsPostalCode(7),
+ 'CN': lambda: DelimitedDigitsPostalCode(6),
'CR': FourDigitsPostalCode,
'DE': GermanPostalCode,
'DK': FourDigitsPostalCode,
'DO': lambda: DelimitedDigitsPostalCode(5),
+ 'ES': lambda: DelimitedDigitsPostalCode(5),
+ 'FI': lambda: DelimitedDigitsPostalCode(5),
+ 'FR': lambda: DelimitedDigitsPostalCode(5),
'GB': UKPostalCode,
'GF': lambda: DelimitedDigitsPostalCode(5),
+ 'GR': lambda: DelimitedDigitsPostalCode([2, 3], ' '),
+ 'HN': lambda: DelimitedDigitsPostalCode(5),
'HT': FourDigitsPostalCode,
- 'HN': lambda: DelimitedDigitsPostalCode(5),
+ 'HU': FourDigitsPostalCode,
+ 'IS': lambda: DelimitedDigitsPostalCode(3),
+ 'IT': lambda: DelimitedDigitsPostalCode(5),
+ 'JP': lambda: DelimitedDigitsPostalCode([3, 4], '-'),
+ 'KR': lambda: DelimitedDigitsPostalCode([3, 3], '-'),
+ 'LI': FourDigitsPostalCode,
+ 'LU': FourDigitsPostalCode,
+ 'MC': lambda: DelimitedDigitsPostalCode(5),
+ 'NI': lambda: DelimitedDigitsPostalCode([3, 3, 1], '-'),
+ 'NO': FourDigitsPostalCode,
'PL': PolishPostalCode,
+ 'PT': lambda: DelimitedDigitsPostalCode([4, 3], '-'),
'PY': FourDigitsPostalCode,
+ 'RO': lambda: DelimitedDigitsPostalCode(6),
+ 'SE': lambda: DelimitedDigitsPostalCode([3, 2], ' '),
+ 'SG': lambda: DelimitedDigitsPostalCode(6),
'US': USPostalCode,
'UY': lambda: DelimitedDigitsPostalCode(5),
}
|
|
From: <sub...@co...> - 2008-08-12 15:48:09
|
Author: gh Date: 2008-08-12 09:48:18 -0600 (Tue, 12 Aug 2008) New Revision: 3547 Modified: FormEncode/trunk/formencode/i18n/fr/LC_MESSAGES/FormEncode.mo Log: fr translation patch - missing mo file Modified: FormEncode/trunk/formencode/i18n/fr/LC_MESSAGES/FormEncode.mo =================================================================== (Binary files differ) |
|
From: <sub...@co...> - 2008-08-12 15:45:26
|
Author: gh Date: 2008-08-12 09:45:33 -0600 (Tue, 12 Aug 2008) New Revision: 3546 Modified: FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/FormEncode.po FormEncode/trunk/formencode/i18n/fr/LC_MESSAGES/FormEncode.po Log: apply fr translation patch Modified: FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/FormEncode.po =================================================================== --- FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/FormEncode.po 2008-08-12 14:11:19 UTC (rev 3545) +++ FormEncode/trunk/formencode/i18n/es/LC_MESSAGES/FormEncode.po 2008-08-12 15:45:33 UTC (rev 3546) @@ -1,3 +1,18 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2008-06-24 14:02+0200\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL...@li...>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + # Traduccioón de FormEncode al Castellano. # Copyright (C) 2006 Alberto Valverde Gonzlález, licencia LGPL V2.0 # Alberto Valverde González <al...@to...>, 2006. Modified: FormEncode/trunk/formencode/i18n/fr/LC_MESSAGES/FormEncode.po =================================================================== --- FormEncode/trunk/formencode/i18n/fr/LC_MESSAGES/FormEncode.po 2008-08-12 14:11:19 UTC (rev 3545) +++ FormEncode/trunk/formencode/i18n/fr/LC_MESSAGES/FormEncode.po 2008-08-12 15:45:33 UTC (rev 3546) @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: FormEncode 1.0\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2008-06-24 15:00+0200\n" +"PO-Revision-Date: 2008-08-12 16:38+0200\n" "Last-Translator: Stéphane Raimbault <ste...@gm...>\n" "Language-Team: GNOME French Team <gn...@tr...>\n" "MIME-Version: 1.0\n" @@ -51,7 +51,7 @@ #: validators.py:345 #: validators.py:399 msgid "Invalid value (value with length expected)" -msgstr "Valeur non valide (valeur d'une certaine taille attendue)" +msgstr "Valeur non valide (valeur d'une certaine longueur attendue)" #: validators.py:398 msgid "Enter a value at least %(minLength)i characters long" @@ -131,7 +131,7 @@ #: validators.py:998 msgid "Enter a value less than %(max)i characters long" -msgstr "Saisissez une valeur dont la taille est inférieure à %(max)i caractères" +msgstr "Saisissez une valeur dont la longueur est inférieure à %(max)i caractères" #: validators.py:999 msgid "Enter a value %(min)i characters long or more" |
|
From: <sub...@co...> - 2008-08-12 12:43:38
|
Author: mark
Date: 2008-08-12 06:43:48 -0600 (Tue, 12 Aug 2008)
New Revision: 3544
Modified:
FormEncode/trunk/formencode/compound.py
Log:
first implementation of Pipe() as deviation from All()
Modified: FormEncode/trunk/formencode/compound.py
===================================================================
--- FormEncode/trunk/formencode/compound.py 2008-08-12 12:39:35 UTC (rev 3543)
+++ FormEncode/trunk/formencode/compound.py 2008-08-12 12:43:48 UTC (rev 3544)
@@ -5,7 +5,7 @@
from api import *
# @@ ianb 2005-05: should CompoundValidator be included?
-__all__ = ['Any', 'All']
+__all__ = ['Any', 'All', 'Pipe']
############################################################
## Compound Validators
@@ -169,3 +169,46 @@
def is_empty(self, value):
# sub-validators should handle emptiness.
return False
+
+class Pipe(All):
+ """
+ This class works like 'All', all validators muss pass, but the result
+ of one validation pass is handled over to the next validator. A behaviour
+ known to Unix and GNU users as 'pipe'.
+
+ ::
+
+ >>> from validators import DictConverter
+ >>> pv = Pipe(validators=[DictConverter({1: 2}), DictConverter({2: 3}), DictConverter({3: 4})])
+ >>> pv.to_python(1)
+ 4
+ >>> pv.to_python(1)
+ 4
+ >>> pv.from_python(4)
+ 1
+ >>> pv.from_python(4)
+ 1
+ >>> pv.to_python(1)
+ 4
+
+ """
+
+ def __repr__(self):
+ return '<Pipe %s>' % self.validators
+
+ def attempt_convert(self, value, state, validate):
+ # To preserve the order of the transformations, we do them
+ # differently when we are converting to and from python.
+ if validate is from_python:
+ validators = list(self.validators)
+ validators.reverse()
+ else:
+ validators = self.validators
+ try:
+ for validator in validators:
+ value = validate(validator, value, state)
+ return value
+ except Invalid:
+ if self.if_invalid is NoDefault:
+ raise
+ return self.if_invalid
|
|
From: <sub...@co...> - 2008-08-12 12:39:31
|
Author: mark
Date: 2008-08-12 06:39:35 -0600 (Tue, 12 Aug 2008)
New Revision: 3543
Modified:
FormEncode/trunk/formencode/addressing.py
Log:
warn if no module for country names (such as pycountry) has been found
Modified: FormEncode/trunk/formencode/addressing.py
===================================================================
--- FormEncode/trunk/formencode/addressing.py 2008-08-12 11:41:30 UTC (rev 3542)
+++ FormEncode/trunk/formencode/addressing.py 2008-08-12 12:39:35 UTC (rev 3543)
@@ -54,6 +54,9 @@
def get_country(code):
return dict(get_countries())[code]
+else:
+ from warnings import warn
+ warn('Please easy_install pycountry or validators handling country names will not work.', DeprecationWarning)
#endif
############################################################
|
|
From: <sub...@co...> - 2008-08-12 11:41:21
|
Author: mark Date: 2008-08-12 05:41:30 -0600 (Tue, 12 Aug 2008) New Revision: 3542 Modified: FormEncode/trunk/formencode/addressing.py Log: utilize pycountry in addressing for (localized) country lists Modified: FormEncode/trunk/formencode/addressing.py =================================================================== --- FormEncode/trunk/formencode/addressing.py 2008-08-12 11:08:24 UTC (rev 3541) +++ FormEncode/trunk/formencode/addressing.py 2008-08-12 11:41:30 UTC (rev 3542) @@ -3,8 +3,12 @@ from api import FancyValidator from validators import Regex, Invalid, PostalCode, _ -# @todo utilize pycountry or http://opencountrycodes.appspot.com/python/ try: + import pycountry + has_pycountry = True +except: + has_pycountry = False +try: from turbogears.i18n import format as tgformat has_turbogears = True except: @@ -13,11 +17,11 @@ ############################################################ ## country lists and functions ############################################################ -country_additions = { - 'BY': _("Belarus"), - 'ME': _("Montenegro"), - 'AU': _("Tasmania"), -} +country_additions = [ + ('BY', _("Belarus")), + ('ME', _("Montenegro")), + ('AU', _("Tasmania")), +] fuzzy_countrynames = [ ('US', 'U.S.A'), ('US', 'USA'), @@ -26,12 +30,20 @@ ('CI', _("Cote de Ivoire")), ] -if has_turbogears: +if has_pycountry: def get_countries(): + c1 = [(e.alpha2, e.name) for e in pycountry.countries] + ret = country_additions + c1 + fuzzy_countrynames + return ret + + def get_country(code): + return pycountry.countries.get(alpha2=code).name +elif has_turbogears: + def get_countries(): c1 = tgformat.get_countries('en') c2 = tgformat.get_countries() if len(c1) > len(c2): - d = country_additions.copy() + d = dict(country_additions) d.update(dict(c1)) d.update(dict(c2)) else: @@ -42,7 +54,7 @@ def get_country(code): return dict(get_countries())[code] -#endif has_turbogears +#endif ############################################################ ## Postal Code validators |
|
From: <sub...@co...> - 2008-08-12 11:08:17
|
Author: mark Date: 2008-08-12 05:08:24 -0600 (Tue, 12 Aug 2008) New Revision: 3541 Modified: FormEncode/trunk/formencode/addressing.py Log: import of TurboGears for country lists, missing tests for validators have been added and UKPostalCode does now accept lowercase zip codes Modified: FormEncode/trunk/formencode/addressing.py =================================================================== --- FormEncode/trunk/formencode/addressing.py 2008-08-12 10:19:28 UTC (rev 3540) +++ FormEncode/trunk/formencode/addressing.py 2008-08-12 11:08:24 UTC (rev 3541) @@ -1,11 +1,53 @@ import re import string -from api import FancyValidator, _ -from validators import Regex, Invalid, PostalCode +from api import FancyValidator +from validators import Regex, Invalid, PostalCode, _ # @todo utilize pycountry or http://opencountrycodes.appspot.com/python/ -from dbmanager.util.i18n import get_country, get_countries +try: + from turbogears.i18n import format as tgformat + has_turbogears = True +except: + has_turbogears = False +############################################################ +## country lists and functions +############################################################ +country_additions = { + 'BY': _("Belarus"), + 'ME': _("Montenegro"), + 'AU': _("Tasmania"), +} +fuzzy_countrynames = [ + ('US', 'U.S.A'), + ('US', 'USA'), + ('GB', _("Britain")), + ('GB', _("Great Britain")), + ('CI', _("Cote de Ivoire")), +] + +if has_turbogears: + def get_countries(): + c1 = tgformat.get_countries('en') + c2 = tgformat.get_countries() + if len(c1) > len(c2): + d = country_additions.copy() + d.update(dict(c1)) + d.update(dict(c2)) + else: + d = country_additions.copy() + d.update(dict(c2)) + ret = d.items() + fuzzy_countrynames + return ret + + def get_country(code): + return dict(get_countries())[code] +#endif has_turbogears + +############################################################ +## Postal Code validators +############################################################ + class GermanPostalCode(Regex): """ @@ -97,7 +139,7 @@ >>> ArgentinianPostalCode.to_python('5555') Traceback (most recent call last): ... - Invalid: Please enter a valid postal code (CNNNNCCC) + Invalid: Please enter a zip code (CNNNNCCC) """ regex = re.compile(r'^([a-zA-Z]{1})\s*(\d{4})\s*([a-zA-Z]{3})$') @@ -132,7 +174,7 @@ >>> CanadianPostalCode.to_python('5555') Traceback (most recent call last): ... - Invalid: Please enter a valid postal code (CNC NCN) + Invalid: Please enter a zip code (CNC NCN) """ regex = re.compile(r'^([a-zA-Z]\d[a-zA-Z])\s?(\d[a-zA-Z]\d)$') @@ -170,7 +212,7 @@ Invalid: Please enter a valid postal code (for format see BS 7666) """ - regex = re.compile(r'^((ASCN|BBND|BIQQ|FIQQ|PCRN|SIQQ|STHL|TDCU|TKCA) 1ZZ|BFPO (c\/o )?[1-9]{1,4}|GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})$') + regex = re.compile(r'^((ASCN|BBND|BIQQ|FIQQ|PCRN|SIQQ|STHL|TDCU|TKCA) 1ZZ|BFPO (c\/o )?[1-9]{1,4}|GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})$', re.I) strip = True messages = { @@ -199,13 +241,17 @@ >>> CountryValidator.to_python('Germany') 'DE' >>> CountryValidator.to_python('Finland') - 'FR' + 'FI' >>> CountryValidator.to_python('UNITED STATES') 'US' >>> CountryValidator.to_python('Krakovia') Traceback (most recent call last): ... Invalid: That country is not listed in ISO-3166 + >>> CountryValidator.from_python('DE') + 'Germany' + >>> CountryValidator.from_python('FI') + 'Finland' """ key_ok = True |
|
From: <sub...@co...> - 2008-08-12 10:19:22
|
Author: mark Date: 2008-08-12 04:19:28 -0600 (Tue, 12 Aug 2008) New Revision: 3540 Modified: FormEncode/trunk/formencode/addressing.py Log: doctests in addressing for trivial classes Modified: FormEncode/trunk/formencode/addressing.py =================================================================== --- FormEncode/trunk/formencode/addressing.py 2008-07-31 21:32:17 UTC (rev 3539) +++ FormEncode/trunk/formencode/addressing.py 2008-08-12 10:19:28 UTC (rev 3540) @@ -3,7 +3,7 @@ from api import FancyValidator, _ from validators import Regex, Invalid, PostalCode -# @todo utilize pycountry +# @todo utilize pycountry or http://opencountrycodes.appspot.com/python/ from dbmanager.util.i18n import get_country, get_countries class GermanPostalCode(Regex): @@ -187,7 +187,27 @@ return match.group(1).upper() class CountryValidator(FancyValidator): + """ + Will convert a country's name into its ISO-3166 abbreviation for unified + storage in databases etc. and return a localized country name in the + reverse step. + @See http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm + + :: + + >>> CountryValidator.to_python('Germany') + 'DE' + >>> CountryValidator.to_python('Finland') + 'FR' + >>> CountryValidator.to_python('UNITED STATES') + 'US' + >>> CountryValidator.to_python('Krakovia') + Traceback (most recent call last): + ... + Invalid: That country is not listed in ISO-3166 + """ + key_ok = True messages = { |
|
From: <sub...@co...> - 2008-06-25 16:05:42
|
Author: ianb
Date: 2008-06-25 10:05:45 -0600 (Wed, 25 Jun 2008)
New Revision: 3495
Modified:
FormEncode/trunk/tests/test_schema.py
Log:
fix an unnecessarily broken test
Modified: FormEncode/trunk/tests/test_schema.py
===================================================================
--- FormEncode/trunk/tests/test_schema.py 2008-06-25 16:02:30 UTC (rev 3494)
+++ FormEncode/trunk/tests/test_schema.py 2008-06-25 16:05:45 UTC (rev 3495)
@@ -124,7 +124,7 @@
BadCase(AddressesForm,
'addresses-1.name.fname=&addresses-1.name.lname=x&'
- 'addresses-1.email=x@x.com',
+ 'add...@do...',
addresses=[d(name=d(fname="Please enter a value"))])
BadCase(AddressesForm,
|
|
From: <sub...@co...> - 2008-06-25 16:02:24
|
Author: ianb
Date: 2008-06-25 10:02:30 -0600 (Wed, 25 Jun 2008)
New Revision: 3494
Modified:
FormEncode/trunk/docs/news.txt
FormEncode/trunk/formencode/compound.py
Log:
make All not check emptiness
Modified: FormEncode/trunk/docs/news.txt
===================================================================
--- FormEncode/trunk/docs/news.txt 2008-06-21 19:59:20 UTC (rev 3493)
+++ FormEncode/trunk/docs/news.txt 2008-06-25 16:02:30 UTC (rev 3494)
@@ -26,6 +26,9 @@
* Some adjustments to the URL validator.
+* :class:`formencode.compound.All` does not handle empty values,
+ instead relying on sub-validators to check for emptiness.
+
1.0.1
-----
Modified: FormEncode/trunk/formencode/compound.py
===================================================================
--- FormEncode/trunk/formencode/compound.py 2008-06-21 19:59:20 UTC (rev 3493)
+++ FormEncode/trunk/formencode/compound.py 2008-06-25 16:02:30 UTC (rev 3494)
@@ -165,3 +165,7 @@
not_empty = not_empty or getattr(validator, 'not_empty', False)
return not_empty
not_empty = property(not_empty__get)
+
+ def is_empty(self, value):
+ # sub-validators should handle emptiness.
+ return False
|
|
From: <sub...@co...> - 2008-06-12 13:37:04
|
Author: mark
Date: 2008-06-12 07:37:09 -0600 (Thu, 12 Jun 2008)
New Revision: 3490
Modified:
FormEncode/trunk/formencode/addressing.py
Log:
deletion of code artifacts in addressing
Modified: FormEncode/trunk/formencode/addressing.py
===================================================================
--- FormEncode/trunk/formencode/addressing.py 2008-06-12 13:25:52 UTC (rev 3489)
+++ FormEncode/trunk/formencode/addressing.py 2008-06-12 13:37:09 UTC (rev 3490)
@@ -1,12 +1,10 @@
import re
import string
-from gettext import gettext as _
-from formencode.api import FancyValidator
-from formencode.validators import Regex, Invalid
-from turbogears import identity
+from api import FancyValidator, _
+from validators import Regex, Invalid, PostalCode
-from dbmanager.util.i18n import *
-from dbmanager.util.hurrikane import *
+# @todo utilize pycountry
+from dbmanager.util.i18n import get_country, get_countries
class GermanPostalCode(Regex):
@@ -188,33 +186,6 @@
value, state)
return match.group(1).upper()
-class LanguageValidator(FancyValidator):
-
- key_ok = True
-
- messages = {
- 'valueNotFound': _("That language is not listed in ISO-639-2"),
- }
-
- def _to_python(self, value, state):
- upval = value.upper()
- if self.key_ok:
- try:
- c = get_language(value)
- return value
- except:
- pass
- for k, v in get_languages():
- if v.upper() == upval:
- return k
- raise Invalid(self.message('valueNotFound', state), value, state)
-
- def _from_python(self, value, state):
- try:
- return get_language(value.lower())
- except KeyError:
- return value
-
class CountryValidator(FancyValidator):
key_ok = True
@@ -246,7 +217,6 @@
"""
Makes sure the postal code is in the country's format.
"""
- from formencode.validators import PostalCode
messages = {
'badFormat': _("Given postal code does not match the country's format."),
@@ -272,147 +242,3 @@
raise Invalid(message, fields_dict, state,
error_dict = {'zip' : e.message,
'country': message})
-
-class HsysRegionCompletor(FancyValidator):
- """
- Will add missing region information if possible.
- Does utilize services of Hurrikane Systems GIS.
- """
-
- def validate_python(self, fields_dict, state):
- try:
- queryable_countries = geo_countries_for_zip_info()
- except (ValueError, HurrikaneException):
- return
- if fields_dict['country'] in queryable_countries \
- and fields_dict['zip'] \
- and not fields_dict['region']:
- try:
- result = geo_get_zip_info(fields_dict['country'], fields_dict['zip'])
- fields_dict['region'] = result['Administrative_Name']
- except HurrikaneException, e:
- try:
- fields_dict['region'] = geo_estimate_region(fields_dict['country'], fields_dict['zip'])
- except HurrikaneException, e:
- pass
- except:
- # log warning
- pass
-
-class PhoneNumber(FancyValidator):
-
- """
- Validates, and converts phone numbers to +##-###-#######.
- Adapted from RFC 3966
-
- ::
-
- >>> p = PhoneNumber()
- >>> 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('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('0555 43-1200')
- '+49-555-43-1200'
- >>> p.to_python('(05 55)4 94 33 47')
- '+49-555-49433-47'
- >>> p.to_python('(00 48-555)2 31 72 41')
- '+48-555-23172-41'
- >>> 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'
- >>> p.to_python('032 555555 367')
- '+49-32-555555-367'
- >>> p.to_python('(+86) 555 3876693')
- '+86-555-3876693'
- >>> p.to_python('(0 81 52)93 11 22')
- '+49-8152-9311-22'
- """
-
- strip = True
- # Use if there's a default country code you want to use:
- default_cc = 49
- _mark_chars_re = re.compile(r"[_.!~*'/?]")
- _preTransformations = [
- (re.compile(r'^(\(?)(?:00\s*)(.+)$'), '%s+%s'),
- (re.compile(r'^\(\s*(\+?\d+)\s*(\d+)\s*\)(.+)$'), '(%s%s)%s'),
- (re.compile(r'^\((\+?[-\d]+)\)\s?(\d.+)$'), '%s-%s'),
- (re.compile(r'^(?:1-)(\d+.+)$'), '+1-%s'),
- (re.compile(r'^(\+\d+)\s+\(0\)\s*(\d+.+)$'), '%s-%s'),
- (re.compile(r'^([0+]\d+)[-\s](\d+)$'), '%s-%s'),
- (re.compile(r'^([0+]\d+)[-\s](\d+)[-\s](\d+)$'), '%s-%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 %s") % '+##-###-####...',
- }
-
- 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)
- try:
- value = value.encode('ascii', 'replace')
- except:
- raise Invalid(self.message('phoneFormat', state), value, state)
- value = self._mark_chars_re.sub('-', value)
- for f, t in [(' ', ' '), ('--', '-'), (' - ', '-'), ('- ', '-'), (' -', '-')]:
- value = value.replace(f, t)
- value = self._perform_rex_transformation(value, self._preTransformations)
- try:
- value = self._prepend_country_code(value, self._ccIncluder, identity.current.user.phone_cc)
- except:
- value = self._prepend_country_code(value, self._ccIncluder, self.default_cc)
- 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
|
|
From: <sub...@co...> - 2008-06-12 13:25:48
|
Author: mark
Date: 2008-06-12 07:25:52 -0600 (Thu, 12 Jun 2008)
New Revision: 3489
Added:
FormEncode/trunk/formencode/addressing.py
Log:
copy of first validator set from Instrumentarium to addressing.py
Added: FormEncode/trunk/formencode/addressing.py
===================================================================
--- FormEncode/trunk/formencode/addressing.py (rev 0)
+++ FormEncode/trunk/formencode/addressing.py 2008-06-12 13:25:52 UTC (rev 3489)
@@ -0,0 +1,418 @@
+import re
+import string
+from gettext import gettext as _
+from formencode.api import FancyValidator
+from formencode.validators import Regex, Invalid
+from turbogears import identity
+
+from dbmanager.util.i18n import *
+from dbmanager.util.hurrikane import *
+
+class GermanPostalCode(Regex):
+
+ """
+ German Postal codes (aka Zip Codes).
+
+ ::
+
+ >>> GermanPostalCode.to_python('55555')
+ '55555'
+ >>> GermanPostalCode.to_python('5555')
+ Traceback (most recent call last):
+ ...
+ Invalid: Please enter a zip code (5 digits)
+ """
+
+ regex = r'^\d\d\d\d\d$'
+ strip = True
+
+ messages = {
+ 'invalid': _("Please enter a zip code (%s)") % _("5 digits"),
+ }
+
+class FourDigitsPostalCode(Regex):
+
+ """
+ Postal codes consisting of 4 digits.
+
+ ::
+
+ >>> FourDigitsPostalCode.to_python('5555')
+ '5555'
+ >>> FourDigitsPostalCode.to_python('56655')
+ Traceback (most recent call last):
+ ...
+ Invalid: Please enter a zip code (4 digits)
+ """
+
+ regex = r'^\d\d\d\d$'
+ strip = True
+
+ messages = {
+ 'invalid': _("Please enter a zip code (%s)") % _("4 digits"),
+ }
+
+class PolishPostalCode(Regex):
+
+ """
+ Polish Postal codes (aka Zip Codes).
+
+ ::
+
+ >>> PolishPostalCode.to_python('55555')
+ '55-555'
+ >>> PolishPostalCode.to_python('55-555')
+ '55-555'
+ >>> PolishPostalCode.to_python('5555')
+ Traceback (most recent call last):
+ ...
+ Invalid: Please enter a zip code (5 digits)
+ """
+
+ regex = re.compile(r'^(\d\d)\-?(\d\d\d)$')
+ strip = True
+
+ messages = {
+ 'invalid': _("Please enter a zip code (%s)") % _("5 digits"),
+ }
+
+ def _to_python(self, value, state):
+ self.assert_string(value, state)
+ match = self.regex.search(value)
+ if not match:
+ raise Invalid(
+ self.message('invalid', state),
+ value, state)
+ return '%s-%s' % (match.group(1), match.group(2))
+
+class ArgentinianPostalCode(Regex):
+
+ """
+ Argentinian Postal codes.
+
+ ::
+
+ >>> ArgentinianPostalCode.to_python('C1070AAM')
+ 'C1070AAM'
+ >>> ArgentinianPostalCode.to_python('c 1070 aam')
+ 'C1070AAM'
+ >>> ArgentinianPostalCode.to_python('5555')
+ Traceback (most recent call last):
+ ...
+ Invalid: Please enter a valid postal code (CNNNNCCC)
+ """
+
+ regex = re.compile(r'^([a-zA-Z]{1})\s*(\d{4})\s*([a-zA-Z]{3})$')
+ strip = True
+
+ messages = {
+ 'invalid': _("Please enter a zip code (%s)") % _("CNNNNCCC"),
+ }
+
+ def _to_python(self, value, state):
+ self.assert_string(value, state)
+ match = self.regex.search(value)
+ if not match:
+ raise Invalid(
+ self.message('invalid', state),
+ value, state)
+ return '%s%s%s' % (match.group(1).upper(),
+ match.group(2),
+ match.group(3).upper())
+
+class CanadianPostalCode(Regex):
+
+ """
+ Canadian Postal codes.
+
+ ::
+
+ >>> CanadianPostalCode.to_python('V3H 1Z7')
+ 'V3H 1Z7'
+ >>> CanadianPostalCode.to_python('v3h1z7')
+ 'V3H 1Z7'
+ >>> CanadianPostalCode.to_python('5555')
+ Traceback (most recent call last):
+ ...
+ Invalid: Please enter a valid postal code (CNC NCN)
+ """
+
+ regex = re.compile(r'^([a-zA-Z]\d[a-zA-Z])\s?(\d[a-zA-Z]\d)$')
+ strip = True
+
+ messages = {
+ 'invalid': _("Please enter a zip code (%s)") % _("CNC NCN"),
+ }
+
+ def _to_python(self, value, state):
+ self.assert_string(value, state)
+ match = self.regex.search(value)
+ if not match:
+ raise Invalid(
+ self.message('invalid', state),
+ value, state)
+ return '%s %s' % (match.group(1).upper(), match.group(2).upper())
+
+class UKPostalCode(Regex):
+
+ """
+ UK Postal codes. Please see BS 7666.
+
+ ::
+
+ >>> UKPostalCode.to_python('BFPO 3')
+ 'BFPO 3'
+ >>> UKPostalCode.to_python('LE11 3GR')
+ 'LE11 3GR'
+ >>> UKPostalCode.to_python('l1a 3gr')
+ 'L1A 3GR'
+ >>> UKPostalCode.to_python('5555')
+ Traceback (most recent call last):
+ ...
+ Invalid: Please enter a valid postal code (for format see BS 7666)
+ """
+
+ regex = re.compile(r'^((ASCN|BBND|BIQQ|FIQQ|PCRN|SIQQ|STHL|TDCU|TKCA) 1ZZ|BFPO (c\/o )?[1-9]{1,4}|GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW]) [0-9][ABD-HJLNP-UW-Z]{2})$')
+ strip = True
+
+ messages = {
+ 'invalid': _("Please enter a valid postal code (for format see BS 7666)"),
+ }
+
+ def _to_python(self, value, state):
+ self.assert_string(value, state)
+ match = self.regex.search(value)
+ if not match:
+ raise Invalid(
+ self.message('invalid', state),
+ value, state)
+ return match.group(1).upper()
+
+class LanguageValidator(FancyValidator):
+
+ key_ok = True
+
+ messages = {
+ 'valueNotFound': _("That language is not listed in ISO-639-2"),
+ }
+
+ def _to_python(self, value, state):
+ upval = value.upper()
+ if self.key_ok:
+ try:
+ c = get_language(value)
+ return value
+ except:
+ pass
+ for k, v in get_languages():
+ if v.upper() == upval:
+ return k
+ raise Invalid(self.message('valueNotFound', state), value, state)
+
+ def _from_python(self, value, state):
+ try:
+ return get_language(value.lower())
+ except KeyError:
+ return value
+
+class CountryValidator(FancyValidator):
+
+ key_ok = True
+
+ messages = {
+ 'valueNotFound': _("That country is not listed in ISO-3166"),
+ }
+
+ def _to_python(self, value, state):
+ upval = value.upper()
+ if self.key_ok:
+ try:
+ c = get_country(upval)
+ return upval
+ except:
+ pass
+ for k, v in get_countries():
+ if v.upper() == upval:
+ return k
+ raise Invalid(self.message('valueNotFound', state), value, state)
+
+ def _from_python(self, value, state):
+ try:
+ return get_country(value.upper())
+ except KeyError:
+ return value
+
+class PostalCodeInCountryFormat(FancyValidator):
+ """
+ Makes sure the postal code is in the country's format.
+ """
+ from formencode.validators import PostalCode
+
+ messages = {
+ 'badFormat': _("Given postal code does not match the country's format."),
+ }
+ _vd = {
+ 'DE': GermanPostalCode,
+ 'AT': FourDigitsPostalCode,
+ 'BE': FourDigitsPostalCode,
+ 'DK': FourDigitsPostalCode,
+ 'PL': PolishPostalCode,
+ 'US': PostalCode,
+ 'CA': CanadianPostalCode,
+ 'AR': ArgentinianPostalCode,
+ 'GB': UKPostalCode,
+ }
+
+ def validate_python(self, fields_dict, state):
+ if fields_dict['country'] in self._vd:
+ try:
+ fields_dict['zip'] = self._vd[fields_dict['country']].to_python(fields_dict['zip'])
+ except Invalid, e:
+ message = self.message('badFormat', state)
+ raise Invalid(message, fields_dict, state,
+ error_dict = {'zip' : e.message,
+ 'country': message})
+
+class HsysRegionCompletor(FancyValidator):
+ """
+ Will add missing region information if possible.
+ Does utilize services of Hurrikane Systems GIS.
+ """
+
+ def validate_python(self, fields_dict, state):
+ try:
+ queryable_countries = geo_countries_for_zip_info()
+ except (ValueError, HurrikaneException):
+ return
+ if fields_dict['country'] in queryable_countries \
+ and fields_dict['zip'] \
+ and not fields_dict['region']:
+ try:
+ result = geo_get_zip_info(fields_dict['country'], fields_dict['zip'])
+ fields_dict['region'] = result['Administrative_Name']
+ except HurrikaneException, e:
+ try:
+ fields_dict['region'] = geo_estimate_region(fields_dict['country'], fields_dict['zip'])
+ except HurrikaneException, e:
+ pass
+ except:
+ # log warning
+ pass
+
+class PhoneNumber(FancyValidator):
+
+ """
+ Validates, and converts phone numbers to +##-###-#######.
+ Adapted from RFC 3966
+
+ ::
+
+ >>> p = PhoneNumber()
+ >>> 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('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('0555 43-1200')
+ '+49-555-43-1200'
+ >>> p.to_python('(05 55)4 94 33 47')
+ '+49-555-49433-47'
+ >>> p.to_python('(00 48-555)2 31 72 41')
+ '+48-555-23172-41'
+ >>> 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'
+ >>> p.to_python('032 555555 367')
+ '+49-32-555555-367'
+ >>> p.to_python('(+86) 555 3876693')
+ '+86-555-3876693'
+ >>> p.to_python('(0 81 52)93 11 22')
+ '+49-8152-9311-22'
+ """
+
+ strip = True
+ # Use if there's a default country code you want to use:
+ default_cc = 49
+ _mark_chars_re = re.compile(r"[_.!~*'/?]")
+ _preTransformations = [
+ (re.compile(r'^(\(?)(?:00\s*)(.+)$'), '%s+%s'),
+ (re.compile(r'^\(\s*(\+?\d+)\s*(\d+)\s*\)(.+)$'), '(%s%s)%s'),
+ (re.compile(r'^\((\+?[-\d]+)\)\s?(\d.+)$'), '%s-%s'),
+ (re.compile(r'^(?:1-)(\d+.+)$'), '+1-%s'),
+ (re.compile(r'^(\+\d+)\s+\(0\)\s*(\d+.+)$'), '%s-%s'),
+ (re.compile(r'^([0+]\d+)[-\s](\d+)$'), '%s-%s'),
+ (re.compile(r'^([0+]\d+)[-\s](\d+)[-\s](\d+)$'), '%s-%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 %s") % '+##-###-####...',
+ }
+
+ 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)
+ try:
+ value = value.encode('ascii', 'replace')
+ except:
+ raise Invalid(self.message('phoneFormat', state), value, state)
+ value = self._mark_chars_re.sub('-', value)
+ for f, t in [(' ', ' '), ('--', '-'), (' - ', '-'), ('- ', '-'), (' -', '-')]:
+ value = value.replace(f, t)
+ value = self._perform_rex_transformation(value, self._preTransformations)
+ try:
+ value = self._prepend_country_code(value, self._ccIncluder, identity.current.user.phone_cc)
+ except:
+ value = self._prepend_country_code(value, self._ccIncluder, self.default_cc)
+ 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
Property changes on: FormEncode/trunk/formencode/addressing.py
___________________________________________________________________
Name: from
+ https://svn.hurrikane.de/all/prj/DBManager/trunk/dbmanager/util/i18n/validators.py
|
|
From: <sub...@co...> - 2008-05-20 20:51:56
|
Author: ianb
Date: 2008-05-20 14:51:55 -0600 (Tue, 20 May 2008)
New Revision: 3449
Added:
FormEncode/trunk/docs/conf.py
FormEncode/trunk/docs/modules/
FormEncode/trunk/docs/modules/api.txt
FormEncode/trunk/docs/modules/compound.txt
FormEncode/trunk/docs/modules/declarative.txt
FormEncode/trunk/docs/modules/doctest_xml_compare.txt
FormEncode/trunk/docs/modules/foreach.txt
FormEncode/trunk/docs/modules/htmlfill.txt
FormEncode/trunk/docs/modules/htmlgen.txt
FormEncode/trunk/docs/modules/htmlrename.txt
FormEncode/trunk/docs/modules/schema.txt
FormEncode/trunk/docs/modules/validators.txt
FormEncode/trunk/docs/modules/variabledecode.txt
Modified:
FormEncode/trunk/docs/
FormEncode/trunk/docs/htmlfill.txt
FormEncode/trunk/docs/index.txt
Log:
A basic Sphinx setup for FormEncode
Property changes on: FormEncode/trunk/docs
___________________________________________________________________
Name: svn:ignore
- *.html
html
+ *.html
html
_static
_build
Added: FormEncode/trunk/docs/conf.py
===================================================================
--- FormEncode/trunk/docs/conf.py (rev 0)
+++ FormEncode/trunk/docs/conf.py 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,132 @@
+# -*- coding: utf-8 -*-
+#
+# FormEncode documentation build configuration file, created by
+# sphinx-quickstart on Tue Apr 22 22:08:49 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys
+
+# If your extensions are in another directory, add it here.
+#sys.path.append('some/directory')
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.txt'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'FormEncode'
+copyright = '2008, Ian Bicking and Contributors'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '1.0'
+# The full version, including alpha/beta/rc tags.
+release = '1.0.2'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = ['include/contact.txt', 'include/reference_header.txt']
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'default.css'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Content template for the index page.
+#html_index = ''
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'FormEncode_doc'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+#latex_documents = []
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
Property changes on: FormEncode/trunk/docs/conf.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: FormEncode/trunk/docs/htmlfill.txt
===================================================================
--- FormEncode/trunk/docs/htmlfill.txt 2008-05-20 15:18:38 UTC (rev 3448)
+++ FormEncode/trunk/docs/htmlfill.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -7,8 +7,6 @@
++++++++
:author: Ian Bicking <ia...@co...>
-:revision: $Rev$
-:date: $LastChangedDate$
.. contents::
Modified: FormEncode/trunk/docs/index.txt
===================================================================
--- FormEncode/trunk/docs/index.txt 2008-05-20 15:18:38 UTC (rev 3448)
+++ FormEncode/trunk/docs/index.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -1,6 +1,20 @@
FormEncode
==========
+Contents:
+
+.. toctree::
+ :maxdepth: 1
+
+ news
+ Validator
+ i18n
+ htmlfill
+ history
+ Design
+ download
+ community
+
Introduction
------------
@@ -29,14 +43,6 @@
* `Community (mailing list, etc) <community.html>`_
* `Download <download.html>`_
-Projects that use FormEncode:
-
-* `SQLObject <http://sqlobject.org>`_
-* `Subway <http://subway.python-hosting.com>`_
-* `TurboGears <http://turbogears.org>`_
-* `Pylons <http://pylons.groovie.org>`_
-* More? `Email me <ia...@co...>`_
-
.. image:: http://sourceforge.net/sflogo.php?group_id=91231&type=4
:height: 37
:width: 125
Added: FormEncode/trunk/docs/modules/api.txt
===================================================================
--- FormEncode/trunk/docs/modules/api.txt (rev 0)
+++ FormEncode/trunk/docs/modules/api.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,9 @@
+:mod:`formencode.htmlfill_schemabuilder` -- Read a Schema from an HTML Form
+===========================================================================
+
+.. automodule:: formencode.htmlfill_schemabuilder
+
+Module Contents
+---------------
+
+.. autofunction:: parse_schema
Property changes on: FormEncode/trunk/docs/modules/api.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/compound.txt
===================================================================
--- FormEncode/trunk/docs/modules/compound.txt (rev 0)
+++ FormEncode/trunk/docs/modules/compound.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,10 @@
+:mod:`formencode.compound` -- Validate with multiple validators
+===============================================================
+
+.. automodule:: formencode.compound
+
+Module Contents
+---------------
+
+.. autoclass:: All
+.. autoclass:: Any
Property changes on: FormEncode/trunk/docs/modules/compound.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/declarative.txt
===================================================================
--- FormEncode/trunk/docs/modules/declarative.txt (rev 0)
+++ FormEncode/trunk/docs/modules/declarative.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,10 @@
+:mod:`formencode.declarative` -- Base class for Validators
+==========================================================
+
+.. automodule:: formencode.declarative
+
+Module Contents
+---------------
+
+.. autoclass:: Declarative
+.. autofunction:: classinstancemethod
Property changes on: FormEncode/trunk/docs/modules/declarative.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/doctest_xml_compare.txt
===================================================================
--- FormEncode/trunk/docs/modules/doctest_xml_compare.txt (rev 0)
+++ FormEncode/trunk/docs/modules/doctest_xml_compare.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,11 @@
+:mod:`formencode.doctest_xml_compare` -- XML-based comparison of Doctest output
+===============================================================================
+
+.. automodule:: formencode.doctest_xml_compare
+
+Module Contents
+---------------
+
+.. autofunction:: xml_compare
+.. autofunction:: install
+
Property changes on: FormEncode/trunk/docs/modules/doctest_xml_compare.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/foreach.txt
===================================================================
--- FormEncode/trunk/docs/modules/foreach.txt (rev 0)
+++ FormEncode/trunk/docs/modules/foreach.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,10 @@
+:mod:`formencode.foreach` -- Validate items in a list
+=====================================================
+
+.. automodule:: formencode.foreach
+
+Module Contents
+---------------
+
+.. autoclass:: ForEach
+
Property changes on: FormEncode/trunk/docs/modules/foreach.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/htmlfill.txt
===================================================================
--- FormEncode/trunk/docs/modules/htmlfill.txt (rev 0)
+++ FormEncode/trunk/docs/modules/htmlfill.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,14 @@
+:mod:`formencode.htmlfill` -- Fill in HTML forms
+================================================
+
+.. automodule:: formencode.htmlfill
+
+Module Contents
+---------------
+
+.. autofunction:: render
+.. autoclass:: html
+.. autofunction:: default_formatter
+.. autofunction: none_formatter
+.. autofunction:: escape_formatter
+
Property changes on: FormEncode/trunk/docs/modules/htmlfill.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/htmlgen.txt
===================================================================
--- FormEncode/trunk/docs/modules/htmlgen.txt (rev 0)
+++ FormEncode/trunk/docs/modules/htmlgen.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,11 @@
+:mod:`formencode.htmlgen` -- Convenient building of ElementTree nodes
+=====================================================================
+
+.. automodule:: formencode.htmlgen
+
+Module Contents
+---------------
+
+.. autoclass:: _HTML
+.. autoclass:: Element
+
Property changes on: FormEncode/trunk/docs/modules/htmlgen.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/htmlrename.txt
===================================================================
--- FormEncode/trunk/docs/modules/htmlrename.txt (rev 0)
+++ FormEncode/trunk/docs/modules/htmlrename.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,11 @@
+:mod:`formencode.htmlrename` -- Rename fields in an HTML form
+=============================================================
+
+.. automodule:: formencode.htmlrename
+
+Module Contents
+---------------
+
+.. autofunction:: rename
+.. autofunction:: add_prefix
+
Property changes on: FormEncode/trunk/docs/modules/htmlrename.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/schema.txt
===================================================================
--- FormEncode/trunk/docs/modules/schema.txt (rev 0)
+++ FormEncode/trunk/docs/modules/schema.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,10 @@
+:mod:`formencode.schema` -- Validate complete forms
+===================================================
+
+.. automodule:: formencode.schema
+
+Module Contents
+---------------
+
+.. autoclass:: Schema
+
Property changes on: FormEncode/trunk/docs/modules/schema.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/validators.txt
===================================================================
--- FormEncode/trunk/docs/modules/validators.txt (rev 0)
+++ FormEncode/trunk/docs/modules/validators.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,86 @@
+:mod:`formencode.validators` -- lots of useful validators
+====================================================================
+
+.. automodule:: formencode.validators
+
+.. contents::
+
+Module Contents
+---------------
+
+Basic Types
+~~~~~~~~~~~
+
+.. autoclass:: StringBool
+.. autoclass:: Bool
+.. autoclass:: Int
+.. autoclass:: Number
+.. autoclass:: UnicodeString
+.. autoclass:: Set
+.. autoclass:: String
+
+Basic Validator/Converters
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. autoclass:: ConfirmType
+.. autoclass:: Wrapper
+.. autoclass:: Constant
+.. autoclass:: StripField
+.. autoclass:: OneOf
+.. autoclass:: DictConverter
+.. autoclass:: IndexListConverter
+
+Simple Validators
+~~~~~~~~~~~~~~~~~
+
+.. autoclass:: MaxLength
+.. autoclass:: MinLength
+.. autoclass:: NotEmpty
+.. autoclass:: Empty
+.. autoclass:: Regex
+.. autoclass:: PlainText
+
+Dates and Times
+~~~~~~~~~~~~~~~
+
+.. autoclass:: DateValidator
+.. autoclass:: DateConverter
+.. autoclass:: TimeConverter
+
+
+Phones and Addresses
+~~~~~~~~~~~~~~~~~~~~
+
+.. autoclass:: PhoneNumber
+.. autoclass:: IPhoneNumberValidator
+.. autoclass:: StateProvince
+.. autoclass:: PostalCode
+
+HTML Form Helpers
+~~~~~~~~~~~~~~~~~
+
+.. autoclass:: SignedString
+.. autoclass:: FieldStorageUploadConverter
+.. autoclass:: FileUploadKeeper
+
+URLs, Email, etc.
+~~~~~~~~~~~~~~~~~
+
+.. autoclass:: Email
+.. autoclass:: URL
+.. autoclass:: CIDR
+.. autoclass:: MACAddress
+
+Form-wide Validation
+~~~~~~~~~~~~~~~~~~~~
+
+.. autoclass:: FormValidator
+.. autoclass:: RequireIfMissing
+.. autoclass:: FieldsMatch
+
+Credit Cards
+~~~~~~~~~~~~
+
+.. autoclass:: CreditCardValidator
+.. autoclass:: CreditCardExpires
+.. autoclass:: CreditCardSecurityCode
Property changes on: FormEncode/trunk/docs/modules/validators.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
Added: FormEncode/trunk/docs/modules/variabledecode.txt
===================================================================
--- FormEncode/trunk/docs/modules/variabledecode.txt (rev 0)
+++ FormEncode/trunk/docs/modules/variabledecode.txt 2008-05-20 20:51:55 UTC (rev 3449)
@@ -0,0 +1,12 @@
+:mod:`formencode.variabledecode` -- Turn flat HTML form submissions into nested structures
+==========================================================================================
+
+.. automodule:: formencode.variabledecode
+
+Module Contents
+---------------
+
+.. autofunction:: variable_decode
+.. autofunction:: variable_encode
+.. autofunction:: NestedVariables
+
Property changes on: FormEncode/trunk/docs/modules/variabledecode.txt
___________________________________________________________________
Name: svn:keywords
+ LastChangedDate LastChangedRevision
Name: svn:eol-style
+ native
|
|
From: <sub...@co...> - 2008-05-20 15:18:33
|
Author: ianb
Date: 2008-05-20 09:18:38 -0600 (Tue, 20 May 2008)
New Revision: 3448
Modified:
FormEncode/trunk/tests/non_empty.txt
Log:
minor tweak to some foreach doctests
Modified: FormEncode/trunk/tests/non_empty.txt
===================================================================
--- FormEncode/trunk/tests/non_empty.txt 2008-05-20 15:17:59 UTC (rev 3447)
+++ FormEncode/trunk/tests/non_empty.txt 2008-05-20 15:18:38 UTC (rev 3448)
@@ -53,7 +53,9 @@
>>> from formencode.validators import Int
>>> foreach = ForEach(Int())
>>> foreach.to_python('')
+[]
>>> foreach.to_python(None)
+[]
>>> foreach.to_python('1')
[1]
>>> foreach.to_python('2')
|
|
From: <sub...@co...> - 2008-05-20 15:18:00
|
Author: ianb
Date: 2008-05-20 09:17:59 -0600 (Tue, 20 May 2008)
New Revision: 3447
Modified:
FormEncode/trunk/formencode/validators.py
Log:
Make the tld optional in URL
Modified: FormEncode/trunk/formencode/validators.py
===================================================================
--- FormEncode/trunk/formencode/validators.py 2008-05-20 14:18:29 UTC (rev 3446)
+++ FormEncode/trunk/formencode/validators.py 2008-05-20 15:17:59 UTC (rev 3447)
@@ -1384,7 +1384,7 @@
>>> u.to_python('http://test')
Traceback (most recent call last):
...
- Invalid: That is not a valid URL
+ Invalid: You must provide a full domain name (like test.com)
>>> u.to_python('http://test..com')
Traceback (most recent call last):
...
@@ -1404,18 +1404,24 @@
Traceback (most recent call last):
...
Invalid: An error occured when trying to connect to the server: ...
+
+ If you want to allow addresses without a TLD (e.g., ``localhost``) you can do::
+
+ >>> URL(require_tld=False).to_python('http://localhost')
+ 'http://localhost'
"""
check_exists = False
add_http = True
+ require_tld = True
url_re = re.compile(r'''
^(http|https)://
- (?:[%:\w]*@)? # authenticator
- (?:[a-z0-9][a-z0-9\-]{1,62}\.)+ # (sub)domain - alpha followed by 62max chars (63 total)
- [a-z]{2,} # TLD
- (?:[0-9]+)? # port
+ (?:[%:\w]*@)? # authenticator
+ (?P<domain>[a-z0-9][a-z0-9\-]{1,62}\.)* # (sub)domain - alpha followed by 62max chars (63 total)
+ (?P<tld>[a-z]{2,}) # TLD
+ (?:[0-9]+)? # port
# files/delims/etc
(?:/[
@@ -1439,6 +1445,7 @@
'socketError': _('An error occured when trying to connect to the server: %(error)s'),
'notFound': _('The server responded that the page could not be found'),
'status': _('The server responded with a bad status code (%(status)s)'),
+ 'noTLD': _('You must provide a full domain name (like %(domain)s.com)'),
}
def _to_python(self, value, state):
@@ -1452,10 +1459,15 @@
self.message('noScheme', state),
value, state)
value = match.group(0).lower() + value[len(match.group(0)):]
- if not self.url_re.search(value):
+ match = self.url_re.search(value)
+ if not match:
raise Invalid(
self.message('badURL', state),
value, state)
+ if self.require_tld and not match.group('domain'):
+ raise Invalid(
+ self.message('noTLD', state, domain=match.group('tld')),
+ value, state)
if self.check_exists and (value.startswith('http://')
or value.startswith('https://')):
self._check_url_exists(value, state)
|
|
From: <sub...@co...> - 2008-05-20 13:51:34
|
Author: mark
Date: 2008-05-20 07:51:18 -0600 (Tue, 20 May 2008)
New Revision: 3442
Modified:
FormEncode/trunk/formencode/validators.py
Log:
in Email and URL, require a TLD as documented but not implemented
Modified: FormEncode/trunk/formencode/validators.py
===================================================================
--- FormEncode/trunk/formencode/validators.py 2008-05-20 13:50:55 UTC (rev 3441)
+++ FormEncode/trunk/formencode/validators.py 2008-05-20 13:51:18 UTC (rev 3442)
@@ -1253,6 +1253,10 @@
Traceback (most recent call last):
...
Invalid: An email address must contain a single @
+ >>> e.to_python('test@foobar')
+ Traceback (most recent call last):
+ ...
+ Invalid: The domain portion of the email address is invalid (the portion after the @: foobar)
>>> e.to_python('te...@fo....5')
Traceback (most recent call last):
...
@@ -1265,10 +1269,6 @@
Traceback (most recent call last):
...
Invalid: The domain portion of the email address is invalid (the portion after the @: .foo.bar.com)
- >>> e.to_python('te...@fo...')
- Traceback (most recent call last):
- ...
- Invalid: The domain portion of the email address is invalid (the portion after the @: foo-.bar.com)
>>> e.to_python('no...@xn...')
'no...@xn...'
>>> e.to_python('o*re...@te...')
@@ -1293,7 +1293,10 @@
resolve_domain = False
usernameRE = re.compile(r"^[^ \t\n\r@<>()]+$", re.I)
- domainRE = re.compile(r"^((?![.-])[a-z0-9_\-]{1,63}(?<!-)\.?)+((?<!\.)\.[a-z]{2,})$", re.I)
+ domainRE = re.compile(r'''
+ ^(?:[a-z0-9][a-z0-9\-]{1,62}\.)+ # (sub)domain - alpha followed by 62max chars (63 total)
+ [a-z]{2,}$ # TLD
+ ''', re.I | re.VERBOSE)
messages = {
'empty': _('Please enter an email address'),
@@ -1372,12 +1375,16 @@
>>> u = URL(add_http=True)
>>> u.to_python('foo.com')
'http://foo.com'
- >>> u.to_python('http://hahaha/bar.html')
- 'http://hahaha/bar.html'
+ >>> u.to_python('http://hahaha.ha/bar.html')
+ 'http://hahaha.ha/bar.html'
>>> u.to_python('http://xn--m7r7ml7t24h.com')
'http://xn--m7r7ml7t24h.com'
>>> u.to_python('https://test.com')
'https://test.com'
+ >>> u.to_python('http://test')
+ Traceback (most recent call last):
+ ...
+ Invalid: That is not a valid URL
>>> u.to_python('http://test..com')
Traceback (most recent call last):
...
@@ -1406,8 +1413,8 @@
url_re = re.compile(r'''
^(http|https)://
(?:[%:\w]*@)? # authenticator
- (?:[a-z0-9][a-z0-9\-]{1,62}\.)* # (sub)domain - alpha followed by 62max chars (63 total)
- [a-z]+ # TLD
+ (?:[a-z0-9][a-z0-9\-]{1,62}\.)+ # (sub)domain - alpha followed by 62max chars (63 total)
+ [a-z]{2,} # TLD
(?:[0-9]+)? # port
# files/delims/etc
|
|
From: <sub...@co...> - 2008-05-20 13:26:53
|
Author: mark
Date: 2008-05-20 07:22:12 -0600 (Tue, 20 May 2008)
New Revision: 3438
Modified:
FormEncode/trunk/formencode/validators.py
Log:
additional tests for URL validator to increase test coverage
Modified: FormEncode/trunk/formencode/validators.py
===================================================================
--- FormEncode/trunk/formencode/validators.py 2008-05-20 12:47:03 UTC (rev 3437)
+++ FormEncode/trunk/formencode/validators.py 2008-05-20 13:22:12 UTC (rev 3438)
@@ -1374,11 +1374,21 @@
'http://foo.com'
>>> u.to_python('http://hahaha/bar.html')
'http://hahaha/bar.html'
+ >>> u.to_python('http://xn--m7r7ml7t24h.com')
+ 'http://xn--m7r7ml7t24h.com'
>>> u.to_python('https://test.com')
'https://test.com'
+ >>> u.to_python('http://test..com')
+ Traceback (most recent call last):
+ ...
+ Invalid: That is not a valid URL
>>> u = URL(add_http=False, check_exists=True)
>>> u.to_python('http://google.com')
'http://google.com'
+ >>> u.to_python('google.com')
+ Traceback (most recent call last):
+ ...
+ Invalid: You must start your URL with http://, https://, etc
>>> u.to_python('http://colorstudy.com/doesnotexist.html')
Traceback (most recent call last):
...
|
|
From: <sub...@co...> - 2008-05-20 12:46:59
|
Author: mark
Date: 2008-05-20 06:47:03 -0600 (Tue, 20 May 2008)
New Revision: 3437
Modified:
FormEncode/trunk/formencode/validators.py
Log:
in Email validator, update of regex for domain names
Modified: FormEncode/trunk/formencode/validators.py
===================================================================
--- FormEncode/trunk/formencode/validators.py 2008-05-20 12:02:07 UTC (rev 3436)
+++ FormEncode/trunk/formencode/validators.py 2008-05-20 12:47:03 UTC (rev 3437)
@@ -1257,6 +1257,20 @@
Traceback (most recent call last):
...
Invalid: The domain portion of the email address is invalid (the portion after the @: foobar.com.5)
+ >>> e.to_python('te...@fo...')
+ Traceback (most recent call last):
+ ...
+ Invalid: The domain portion of the email address is invalid (the portion after the @: foo..bar.com)
+ >>> e.to_python('test@.foo.bar.com')
+ Traceback (most recent call last):
+ ...
+ Invalid: The domain portion of the email address is invalid (the portion after the @: .foo.bar.com)
+ >>> e.to_python('te...@fo...')
+ Traceback (most recent call last):
+ ...
+ Invalid: The domain portion of the email address is invalid (the portion after the @: foo-.bar.com)
+ >>> e.to_python('no...@xn...')
+ 'no...@xn...'
>>> e.to_python('o*re...@te...')
'o*re...@te...'
>>> e = Email(resolve_domain=True)
@@ -1279,7 +1293,7 @@
resolve_domain = False
usernameRE = re.compile(r"^[^ \t\n\r@<>()]+$", re.I)
- domainRE = re.compile(r"^[a-z0-9][a-z0-9\.\-_]*\.[a-z]+$", re.I)
+ domainRE = re.compile(r"^((?![.-])[a-z0-9_\-]{1,63}(?<!-)\.?)+((?<!\.)\.[a-z]{2,})$", re.I)
messages = {
'empty': _('Please enter an email address'),
|
|
From: <sub...@co...> - 2008-05-20 12:02:03
|
Author: mark
Date: 2008-05-20 06:02:07 -0600 (Tue, 20 May 2008)
New Revision: 3436
Modified:
FormEncode/trunk/formencode/validators.py
Log:
update of IPhoneNumberValidator to accept more phone number variations
Modified: FormEncode/trunk/formencode/validators.py
===================================================================
--- FormEncode/trunk/formencode/validators.py 2008-05-19 15:00:23 UTC (rev 3435)
+++ FormEncode/trunk/formencode/validators.py 2008-05-20 12:02:07 UTC (rev 3436)
@@ -1585,7 +1585,7 @@
result = result + " ext.%s" % match.group(4)
return result
-# from dbmanager.intl_util.validators@r313[208:303]
+# from dbmanager.util.i18n.validators@r313[302:417]
class IPhoneNumberValidator(FancyValidator):
"""
@@ -1603,6 +1603,8 @@
'+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('0555 8114100')
@@ -1615,8 +1617,12 @@
'+49-555-87182-96'
>>> p.to_python('0555-2 50-30')
'+49-555-250-30'
+ >>> p.to_python('0555 43-1200')
+ '+49-555-43-1200'
>>> p.to_python('(05 55)4 94 33 47')
'+49-555-49433-47'
+ >>> p.to_python('(00 48-555)2 31 72 41')
+ '+48-555-23172-41'
>>> p.to_python('+973-555431')
'+973-555431'
>>> p.to_python('1-393-555-3939')
@@ -1629,6 +1635,10 @@
'+218-55-3350317-321'
>>> p.to_python('+218 (0)55-3636639/38')
'+218-55-3636639-38'
+ >>> p.to_python('032 555555 367')
+ '+49-32-555555-367'
+ >>> p.to_python('(+86) 555 3876693')
+ '+86-555-3876693'
"""
strip = True
@@ -1636,14 +1646,16 @@
default_cc = None
_mark_chars_re = re.compile(r"[_.!~*'/]")
_preTransformations = [
- (re.compile(r'^\((\d+)\s*(\d+)\)(.+)$'), '%s%s-%s'),
+ (re.compile(r'^(\(?)(?:00\s*)(.+)$'), '%s+%s'),
+ (re.compile(r'^\(\s*(\+?\d+)\s*(\d+)\s*\)(.+)$'), '(%s%s)%s'),
+ (re.compile(r'^\((\+?[-\d]+)\)\s?(\d.+)$'), '%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'),
+ (re.compile(r'^([0+]\d+)[-\s](\d+)$'), '%s-%s'),
+ (re.compile(r'^([0+]\d+)[-\s](\d+)[-\s](\d+)$'), '%s-%s-%s'),
]
_ccIncluder = [
- (re.compile(r'^0([1-9]\d*)\-(\d+.*)$'), '+%d-%s-%s'),
+ (re.compile(r'^\(?0([1-9]\d*)[-)](\d.*)$'), '+%d-%s-%s'),
]
_postTransformations = [
(re.compile(r'^(\+\d+)[-\s]\(?(\d+)\)?[-\s](\d+.+)$'), '%s-%s-%s'),
@@ -1671,12 +1683,16 @@
def _to_python(self, value, state):
self.assert_string(value, state)
+ try:
+ value = value.encode('ascii', 'replace')
+ except:
+ raise Invalid(self.message('phoneFormat', state), value, state)
+ value = self._mark_chars_re.sub('-', value)
+ for f, t in [(' ', ' '), ('--', '-'), (' - ', '-'), ('- ', '-'), (' -', '-')]:
+ value = value.replace(f, t)
value = self._perform_rex_transformation(value, self._preTransformations)
- value = self._mark_chars_re.sub('-', value)
if self.default_cc:
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?
@@ -1684,9 +1700,6 @@
raise Invalid(self.message('phoneFormat', state), value, state)
return value
-
-
-
class FieldStorageUploadConverter(FancyValidator):
"""
Handles cgi.FieldStorage instances that are file uploads.
|
|
From: <sub...@co...> - 2008-05-15 15:42:57
|
Author: ianb
Date: 2008-05-15 09:41:23 -0600 (Thu, 15 May 2008)
New Revision: 3430
Modified:
FormEncode/trunk/formencode/rewritingparser.py
Log:
coerce objects to unicode when they want to be so coerced
Modified: FormEncode/trunk/formencode/rewritingparser.py
===================================================================
--- FormEncode/trunk/formencode/rewritingparser.py 2008-05-14 19:31:18 UTC (rev 3429)
+++ FormEncode/trunk/formencode/rewritingparser.py 2008-05-15 15:41:23 UTC (rev 3430)
@@ -11,8 +11,11 @@
elif isinstance(v, basestring):
return cgi.escape(v, 1)
else:
- # @@: Should this be unicode(v) or str(v)?
- return cgi.escape(str(v), 1)
+ if hasattr(v, '__unicode__'):
+ v = unicode(v)
+ else:
+ v = str(v)
+ return cgi.escape(v, 1)
class RewritingParser(HTMLParser.HTMLParser):
|
|
From: <sub...@co...> - 2008-05-14 19:31:47
|
Author: ianb
Date: 2008-05-14 13:31:18 -0600 (Wed, 14 May 2008)
New Revision: 3429
Modified:
FormEncode/trunk/formencode/foreach.py
Log:
use [] as empty_value for ForEach
Modified: FormEncode/trunk/formencode/foreach.py
===================================================================
--- FormEncode/trunk/formencode/foreach.py 2008-05-14 16:17:03 UTC (rev 3428)
+++ FormEncode/trunk/formencode/foreach.py 2008-05-14 19:31:18 UTC (rev 3429)
@@ -109,6 +109,9 @@
else:
state.full_list = previous_full_list
+ def empty_value(self, value):
+ return []
+
def _convert_to_list(self, value):
if isinstance(value, (str, unicode)):
return [value]
|
|
From: <sub...@co...> - 2008-05-14 16:17:15
|
Author: ianb
Date: 2008-05-14 10:17:03 -0600 (Wed, 14 May 2008)
New Revision: 3428
Modified:
FormEncode/trunk/docs/Validator.txt
Log:
fix self.message call in docs
Modified: FormEncode/trunk/docs/Validator.txt
===================================================================
--- FormEncode/trunk/docs/Validator.txt 2008-05-14 16:14:10 UTC (rev 3427)
+++ FormEncode/trunk/docs/Validator.txt 2008-05-14 16:17:03 UTC (rev 3428)
@@ -496,7 +496,7 @@
}
def validate_python(self, value, state):
- raise Invalid(self.message('key', substitution='apples'),
+ raise Invalid(self.message('key', state, substitution='apples'),
value, state)
Localization of Error Messages (i18n)
|