|
From: <sub...@co...> - 2009-03-12 16:59:54
|
Author: chrisz
Date: 2009-03-12 10:59:49 -0600 (Thu, 12 Mar 2009)
New Revision: 3805
Modified:
FormEncode/trunk/formencode/validators.py
Log:
Allow None (with the meaning "do not decode/encode" as input or output decoding for UnicodeString. This is useful if you're sending output to a templating engine which usually expect unicode objects instead of encoded strings.
Modified: FormEncode/trunk/formencode/validators.py
===================================================================
--- FormEncode/trunk/formencode/validators.py 2009-03-09 18:15:44 UTC (rev 3804)
+++ FormEncode/trunk/formencode/validators.py 2009-03-12 16:59:49 UTC (rev 3805)
@@ -1154,10 +1154,16 @@
'badEncoding' : _("Invalid data or incorrect encoding"),
}
- def __init__(self, inputEncoding=None, outputEncoding=None, **kw):
+ def __init__(self, inputEncoding=NoDefault, outputEncoding=NoDefault, **kw):
String.__init__(self, **kw)
- self.inputEncoding = inputEncoding or self.encoding
- self.outputEncoding = outputEncoding or self.encoding
+ if inputEncoding is NoDefault:
+ self.inputEncoding = self.encoding
+ else:
+ self.inputEncoding = inputEncoding
+ if outputEncoding is NoDefault:
+ self.outputEncoding = self.encoding
+ else:
+ self.outputEncoding = outputEncoding
def _to_python(self, value, state):
if not value:
@@ -1170,12 +1176,15 @@
return value
else:
value = str(value)
- try:
- return unicode(value, self.inputEncoding)
- except UnicodeDecodeError:
- raise Invalid(self.message('badEncoding', state), value, state)
- except TypeError:
- raise Invalid(self.message('badType', state, type=type(value), value=value), value, state)
+ if self.inputEncoding:
+ try:
+ value = unicode(value, self.inputEncoding)
+ except UnicodeDecodeError:
+ raise Invalid(self.message('badEncoding', state), value, state)
+ except TypeError:
+ raise Invalid(self.message('badType', state, type=type(value),
+ value=value), value, state)
+ return value
def _from_python(self, value, state):
if not isinstance(value, unicode):
@@ -1183,7 +1192,7 @@
value = unicode(value)
else:
value = str(value)
- if isinstance(value, unicode):
+ if self.outputEncoding and isinstance(value, unicode):
value = value.encode(self.outputEncoding)
return value
@@ -1534,16 +1543,16 @@
self.message('status', state, status=res.status),
state, url)
-
+
class XRI(FancyValidator):
r"""
Validator for XRIs.
-
+
It supports both i-names and i-numbers, of the first version of the XRI
standard.
-
+
::
-
+
>>> inames = XRI(xri_type="i-name")
>>> inames.to_python(" =John.Smith ")
'=John.Smith'
@@ -1573,9 +1582,9 @@
'!!1000!de21.4536.2cb2.8074'
>>> inumbers.to_python("@!1000.9554.fabd.129c!2847.df3c")
'@!1000.9554.fabd.129c!2847.df3c'
-
+
"""
-
+
iname_valid_pattern = re.compile(r"""
^
[\w]+ # A global alphanumeric i-name
@@ -1583,11 +1592,11 @@
(\*[\w]+(\.[\w]+)*)* # A community i-name
$
""", re.VERBOSE|re.UNICODE)
-
-
+
+
iname_invalid_start = re.compile(r"^[\d\.-]", re.UNICODE)
"""@cvar: These characters must not be at the beggining of the i-name"""
-
+
inumber_pattern = re.compile(r"""
^
(
@@ -1599,7 +1608,7 @@
(![\dA-F]{1,4}(\.[\dA-F]{1,4}){0,3})* # Zero or more sub i-numbers
$
""", re.VERBOSE|re.IGNORECASE)
-
+
messages = {
'noType': _("The type of i-name is not defined; it may be either individual or organizational"),
'repeatedChar': _("Dots and dashes may not be repeated consecutively"),
@@ -1610,24 +1619,24 @@
'badType': _("The XRI must be a string (not a %(type)s: %(value)r)"),
'badXri': _('"%(xri_type)s" is not a valid type of XRI')
}
-
+
def __init__(self, add_xri=False, xri_type="i-name", **kwargs):
"""Create an XRI validator.
-
+
@param add_xri: Should the schema be added if not present? Officially
it's optional.
@type add_xri: C{bool}
@param xri_type: What type of XRI should be validated? Possible values:
C{i-name} or C{i-number}.
@type xri_type: C{str}
-
+
"""
self.add_xri = add_xri
assert xri_type in ('i-name', 'i-number'), \
('xri_type must be "i-name" or "i-number"')
self.xri_type = xri_type
super(XRI, self).__init__(**kwargs)
-
+
def _to_python(self, value, state):
"""Prepend the 'xri://' schema if necessary and then remove trailing
spaces"""
@@ -1635,35 +1644,35 @@
if self.add_xri and not value.startswith("xri://"):
value = "xri://" + value
return value
-
+
def validate_python(self, value, state=None):
"""Validate an XRI
-
+
@raise Invalid: If at least one of the following conditions in met:
- C{value} is not a string.
- The XRI is not a personal, organizational or network one.
- The relevant validator (i-name or i-number) considers the XRI
is not valid.
-
+
"""
if not (isinstance(value, str) or isinstance(value, unicode)):
raise Invalid(self.message("badType", state, type=str(type(value)),
value=value),
value, state)
-
+
# Let's remove the schema, if any
if value.startswith("xri://"):
value = value[6:]
-
+
if not value[0] in ('@', '=') and not (self.xri_type == "i-number" \
and value[0] == '!'):
raise Invalid(self.message("noType", state), value, state)
-
+
if self.xri_type == "i-name":
self._validate_iname(value, state)
else:
self._validate_inumber(value, state)
-
+
def _validate_iname(self, iname, state):
"""Validate an i-name"""
# The type is not required here:
@@ -1675,7 +1684,7 @@
if not self.iname_valid_pattern.match(iname) or "_" in iname:
raise Invalid(self.message("badIname", state, iname=iname), iname,
state)
-
+
def _validate_inumber(self, inumber, state):
"""Validate an i-number"""
if not self.__class__.inumber_pattern.match(inumber):
@@ -1687,7 +1696,7 @@
class OpenId(FancyValidator):
r"""
OpenId validator.
-
+
::
>>> v = OpenId(add_schema=True)
>>> v.to_python(' example.net ')
@@ -1705,24 +1714,24 @@
Traceback (most recent call last):
...
Invalid: "lo...@me..." is not a valid OpenId (it is neither an URL nor an XRI)
-
+
"""
-
+
messages = {
'badId': _('"%(id)s" is not a valid OpenId (it is neither an URL nor an XRI)')
}
-
+
def __init__(self, add_schema=False, **kwargs):
"""Create an OpenId validator.
-
+
@param add_schema: Should the schema be added if not present?
@type add_schema: C{bool}
-
+
"""
self.url_validator = URL(add_http=add_schema)
self.iname_validator = XRI(add_schema, xri_type="i-name")
self.inumber_validator = XRI(add_schema, xri_type="i-number")
-
+
def _to_python(self, value, state):
value = value.strip()
try:
@@ -1737,7 +1746,7 @@
pass
# It's not an OpenId!
raise Invalid(self.message("badId", state, id=value), value, state)
-
+
def validate_python(self, value, state):
self._to_python(value, state)
|