From: <sub...@co...> - 2009-03-12 20:19:06
|
Author: chrisz Date: 2009-03-12 14:18:59 -0600 (Thu, 12 Mar 2009) New Revision: 3811 Modified: FormEncode/trunk/docs/news.txt FormEncode/trunk/formencode/validators.py FormEncode/trunk/tests/test_validators.py Log: Slightly simplified the r3806 patch; added tests and documentation. Modified: FormEncode/trunk/docs/news.txt =================================================================== --- FormEncode/trunk/docs/news.txt 2009-03-12 18:22:16 UTC (rev 3810) +++ FormEncode/trunk/docs/news.txt 2009-03-12 20:18:59 UTC (rev 3811) @@ -3,13 +3,24 @@ .. contents:: +svn trunk +--------- + +* Allowed :class:`formencode.validators.UnicodeString` to use different + encoding of input and output, or no encoding/decoding at all. + +* Fixes `#2666139 DateValidator bug happening only in March under Windows in Germany :) + <http://sourceforge.net/tracker/index.php?func=detail&aid=2666139&group_id=91231&atid=596418>`_ + +* Really updated German translation + 1.2.2 ----- * Added keyword argument ``force_defaults`` to :func:`formencode.htmlfill.render`; when this is True (the default) this will uncheck checkboxes, unselect select boxes, etc., when a - value is missing from the default dictionary. + value is missing from the default dictionary. * Updated German translation @@ -50,7 +61,7 @@ * :class:`formencode.validators.Number` works with ``inf`` float values (before it would raise a OverflowError). - + * The ``tw`` locale has been renamed to the more standard ``zh_TW``. * Added Japanese and Turkish translations. @@ -63,7 +74,7 @@ --- * Fixed the ``is_empty()`` method in - :class:`formencode.validators.FieldStorageUploadConverter`; + :class:`formencode.validators.FieldStorageUploadConverter`; previously it returned the opposite of the intended result. * Added a parameter to ``htmlfill.render()``: ``prefix_error``. If @@ -129,7 +140,7 @@ chained validators get run even when there are previous errors (to detect all the errors). -* While something like ``Int.to_python()`` worked, other methods like +* While something like ``Int.to_python()`` worked, other methods like ``Int.message(...)`` didn't work. Now it does. * Added Italian, Finnish, and Norwegian translations. Modified: FormEncode/trunk/formencode/validators.py =================================================================== --- FormEncode/trunk/formencode/validators.py 2009-03-12 18:22:16 UTC (rev 3810) +++ FormEncode/trunk/formencode/validators.py 2009-03-12 20:18:59 UTC (rev 3811) @@ -1135,7 +1135,10 @@ the String class. In addition to the String arguments, an encoding argument is also - accepted. By default the encoding will be utf-8. + accepted. By default the encoding will be utf-8. You can overwrite + this using the encoding parameter. You can also set inputEncoding + and outputEncoding differently. An inputEncoding of None means + "do not decode", an outputEncoding of None means "do not encode". All converted strings are returned as Unicode strings. @@ -1156,18 +1159,12 @@ 'badEncoding' : _("Invalid data or incorrect encoding"), } - def __init__(self, inputEncoding=NoDefault, outputEncoding=NoDefault, **kw): + def __init__(self, **kw): String.__init__(self, **kw) - if inputEncoding is NoDefault: - if self.inputEncoding is NoDefault: - self.inputEncoding = self.encoding - else: - self.inputEncoding = inputEncoding - if outputEncoding is NoDefault: - if self.outputEncoding is NoDefault: - self.outputEncoding = self.encoding - else: - self.outputEncoding = outputEncoding + if self.inputEncoding is NoDefault: + self.inputEncoding = self.encoding + if self.outputEncoding is NoDefault: + self.outputEncoding = self.encoding def _to_python(self, value, state): if not value: Modified: FormEncode/trunk/tests/test_validators.py =================================================================== --- FormEncode/trunk/tests/test_validators.py 2009-03-12 18:22:16 UTC (rev 3810) +++ FormEncode/trunk/tests/test_validators.py 2009-03-12 20:18:59 UTC (rev 3811) @@ -53,7 +53,41 @@ un = UnicodeString() assert un.to_python(12) == u'12' assert type(un.to_python(12)) is unicode + assert un.from_python(12) == '12' + assert type(un.from_python(12)) is str + +def test_unicode_encoding(): + uv = UnicodeString() + us = u'käse' + u7s, u8s = us.encode('utf-7'), us.encode('utf-8') + assert uv.to_python(u8s) == us + assert type(uv.to_python(u8s)) is unicode + assert uv.from_python(us) == u8s + assert type(uv.from_python(us)) is str + uv = UnicodeString(encoding='utf-7') + assert uv.to_python(u7s) == us + assert type(uv.to_python(u7s)) is unicode + assert uv.from_python(us) == u7s + assert type(uv.from_python(us)) is str + uv = UnicodeString(inputEncoding='utf-7') + assert uv.to_python(u7s) == us + assert type(uv.to_python(u7s)) is unicode + uv = UnicodeString(outputEncoding='utf-7') + assert uv.from_python(us) == u7s + assert type(uv.from_python(us)) is str + uv = UnicodeString(inputEncoding=None) + assert uv.to_python(us) == us + assert type(uv.to_python(us)) is unicode + assert uv.from_python(us) == u8s + assert type(uv.from_python(us)) is str + uv = UnicodeString(outputEncoding=None) + assert uv.to_python(u8s) == us + assert type(uv.to_python(u8s)) is unicode + assert uv.from_python(us) == us + assert type(uv.from_python(us)) is unicode + + def test_unicode_empty(): iv = UnicodeString() for input in [None, "", u""]: @@ -137,7 +171,7 @@ class TestXRIValidator(unittest.TestCase): """Generic tests for the XRI validator""" - + def test_creation_valid_params(self): """The creation of an XRI validator with valid parameters must succeed""" @@ -146,33 +180,33 @@ XRI(True, "i-number") XRI(False, "i-name") XRI(False, "i-number") - + def test_creation_invalid_xri(self): """Only "i-name" and "i-number" are valid XRIs""" self.assertRaises(AssertionError, XRI, True, 'i-something') - + def test_valid_simple_individual_iname_without_type(self): """XRIs must start with either an equals sign or an at sign""" validator = XRI(True, "i-name") self.assertRaises(Invalid, validator.validate_python, 'Gustavo') - + def test_valid_iname_with_schema(self): """XRIs may have their schema in the beggining""" validator = XRI() self.assertEqual(validator.to_python('xri://=Gustavo'), 'xri://=Gustavo') - + def test_schema_is_added_if_asked(self): """The schema must be added to an XRI if explicitly asked""" validator = XRI(True) self.assertEqual(validator.to_python('=Gustavo'), 'xri://=Gustavo') - + def test_schema_not_added_if_not_asked(self): """The schema must not be added to an XRI unless explicitly asked""" validator = XRI() self.assertEqual(validator.to_python('=Gustavo'), '=Gustavo') - + def test_spaces_are_trimmed(self): """Spaces at the beggining or end of the XRI are removed""" validator = XRI() @@ -181,90 +215,90 @@ class TestINameValidator(unittest.TestCase): """Tests for the XRI i-names validator""" - + def setUp(self): self.validator = XRI(xri_type="i-name") - + def test_valid_global_individual_iname(self): """Global & valid individual i-names must pass validation""" self.validator.validate_python('=Gustavo') - + def test_valid_global_organizational_iname(self): """Global & valid organizational i-names must pass validation""" self.validator.validate_python('@Canonical') - + def test_invalid_iname(self): """Non-string i-names are rejected""" self.assertRaises(Invalid, self.validator.validate_python, None) - + def test_exclamation_in_inames(self): """Exclamation marks at the beggining of XRIs is something specific to i-numbers and must be rejected in i-names""" self.assertRaises(Invalid, self.validator.validate_python, "!!1000!de21.4536.2cb2.8074") - + def test_repeated_characters(self): """Dots and dashes must not be consecutively repeated in i-names""" self.assertRaises(Invalid, self.validator.validate_python, "=Gustavo--Narea") self.assertRaises(Invalid, self.validator.validate_python, "=Gustavo..Narea") - + def test_punctuation_marks_at_beggining(self): """Punctuation marks at the beggining of i-names are forbidden""" self.assertRaises(Invalid, self.validator.validate_python, "=.Gustavo") self.assertRaises(Invalid, self.validator.validate_python, "=-Gustavo.Narea") - + def test_numerals_at_beggining(self): """Numerals at the beggining of i-names are forbidden""" self.assertRaises(Invalid, self.validator.validate_python, "=1Gustavo") - + def test_non_english_inames(self): """i-names with non-English characters are valid""" self.validator.validate_python(u'=Gustavo.Narea.García') self.validator.validate_python(u'@名前.例') - + def test_inames_plus_paths(self): """i-names with paths are valid but not supported""" self.assertRaises(Invalid, self.validator.validate_python, "=Gustavo/(+email)") - + def test_communities(self): """i-names may have so-called 'communities'""" self.validator.validate_python(u'=María*Yolanda*Liliana*Gustavo') self.validator.validate_python(u'=Gustavo*Andreina') self.validator.validate_python(u'@IBM*Lenovo') - - + + class TestINumberValidator(unittest.TestCase): """Tests for the XRI i-number validator""" - + def setUp(self): self.validator = XRI(xri_type="i-number") - + def test_valid_global_personal_inumber(self): """Global & valid personal i-numbers must pass validation""" self.validator.validate_python('=!1000.a1b2.93d2.8c73') - + def test_valid_global_organizational_inumber(self): """Global & valid organizational i-numbers must pass validation""" self.validator.validate_python('@!1000.a1b2.93d2.8c73') - + def test_valid_global_network_inumber(self): """Global & valid network i-numbers must pass validation""" self.validator.validate_python('!!1000') - + def test_valid_community_personal_inumbers(self): """Community & valid personal i-numbers must pass validation""" self.validator.validate_python('=!1000.a1b2.93d2.8c73!3ae2!1490') - + def test_valid_community_organizational_inumber(self): """Community & valid organizational i-numbers must pass validation""" self.validator.validate_python('@!1000.9554.fabd.129c!2847.df3c') - + def test_valid_community_network_inumber(self): """Community & valid network i-numbers must pass validation""" self.validator.validate_python('!!1000!de21.4536.2cb2.8074') @@ -272,25 +306,25 @@ class TestOpenIdValidator(unittest.TestCase): """Tests for the OpenId validator""" - + def setUp(self): self.validator = OpenId(add_schema=False) - + def test_url(self): self.assertEqual(self.validator.to_python('http://example.org'), 'http://example.org') - + def test_iname(self): self.assertEqual(self.validator.to_python('=Gustavo'), '=Gustavo') - + def test_inumber(self): self.assertEqual(self.validator.to_python('!!1000'), '!!1000') - + def test_email(self): """Email addresses are not valid OpenIds!""" self.assertRaises(Invalid, self.validator.to_python, "wa...@bu...") - + def test_prepending_schema(self): validator = OpenId(add_schema=True) self.assertEqual(validator.to_python("example.org"), |