I forgot to attach the patch file to the original bug report.  Here it is.

--
Dwayne C. Litzenberger <[EMAIL PROTECTED]>
diff -ruN ../pyl.orig/pylons-0.9.5/CHANGELOG pylons-0.9.5/CHANGELOG
--- ../pyl.orig/pylons-0.9.5/CHANGELOG  2007-04-12 17:27:57.000000000 -0600
+++ pylons-0.9.5/CHANGELOG      2007-06-05 11:29:11.000000000 -0600
@@ -1,6 +1,15 @@
 Pylons Changelog
 =================
 
+Backported from SVN repository (Jun 5th, 2007 - Debian)
+* Fixed the validate decorator triggering the following error with
+  FormEncode>=0.7 and non-ascii rendered form content:
+  UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 10:
+  ordinal not in range(128) the form was passed in as an encoded string, but
+  some data or error messages were unicode strings; the form should be passed
+  in as a unicode string
+  Reported by Christoph Haas.
+
 0.9.5 (Apr 11th, 2007)
 * Fixed a Python 2.3 incompatibility with paster shell, causing the
   Exception:
diff -ruN ../pyl.orig/pylons-0.9.5/pylons/decorators/__init__.py 
pylons-0.9.5/pylons/decorators/__init__.py
--- ../pyl.orig/pylons-0.9.5/pylons/decorators/__init__.py      2007-04-12 
17:17:54.000000000 -0600
+++ pylons-0.9.5/pylons/decorators/__init__.py  2007-06-05 11:29:11.000000000 
-0600
@@ -1,7 +1,7 @@
 """Pylons Decorators: ``jsonify``, ``validate``, REST, and Cache decorators"""
 import simplejson as json
 import sys
-from paste.util.multidict import UnicodeMultiDict
+from paste.util.multidict import MultiDict
 
 from decorator import decorator
 
@@ -95,17 +95,35 @@
             pylons.request.environ['pylons.routes_dict']['action'] = form
             response = self._dispatch_call()
             form_content = ''.join(response.content)
-            if isinstance(params, UnicodeMultiDict) and \
-                    not isinstance(form_content, unicode):
+            if isinstance(params, MultiDict):
+                # Passing raw string form values to htmlfill: Ensure
+                # form_content and FormEncode's errors dict are also raw
+                # strings so htmlfill can safely combine them
+                encoding = determine_response_charset(response)
+                # WSGIResponse's content may (unlikely) be unicode
+                if isinstance(form_content, unicode):
+                    form_content = form_content.encode(encoding)
+                # FormEncode>=0.7 error strings are unicode (due to being
+                # localized via ugettext)
+                for key, value in errors.iteritems():
+                    if isinstance(value, unicode):
+                        errors[key] = value.encode(encoding)
+            elif not isinstance(form_content, unicode):
                 # Passing unicode form values to htmlfill: decode the response
                 # to unicode so htmlfill can safely combine the two
-                encoding = response.determine_charset()
-                if encoding is None:
-                    encoding = sys.getdefaultencoding()
+                encoding = determine_response_charset(response)
                 form_content = form_content.decode(encoding, response.errors)
             response.content = [htmlfill.render(form_content, params, errors)]
             return response
         return func(self, *args, **kwargs)
     return decorator(wrapper)
 
+def determine_response_charset(response):
+    """Determine the charset of the specified Response object, returning the
+    default system encoding when none is set"""
+    charset = response.determine_charset()
+    if charset is None:
+        charset = sys.getdefaultencoding()
+    return charset
+
 __all__ = ['jsonify', 'validate']
diff -ruN ../pyl.orig/pylons-0.9.5/tests/test_units/test_decorator_validate.py 
pylons-0.9.5/tests/test_units/test_decorator_validate.py
--- ../pyl.orig/pylons-0.9.5/tests/test_units/test_decorator_validate.py        
1969-12-31 18:00:00.000000000 -0600
+++ pylons-0.9.5/tests/test_units/test_decorator_validate.py    2007-06-05 
11:29:11.000000000 -0600
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+from paste.fixture import TestApp
+from paste.registry import RegistryManager
+
+from pylons import Response
+from pylons.decorators import validate
+
+from pylons.controllers import WSGIController
+
+from __init__ import ControllerWrap, SetupCacheGlobal, TestWSGIController
+
+import formencode
+
+class DhcpZoneForm(formencode.Schema):
+    allow_extra_fields = True
+    filter_extra_fields = True
+    new_network = formencode.validators.URL(not_empty=True)
+
+class ValidatingController(WSGIController):
+    def new(self):
+        return Response("""
+<html>
+  <form action="/dhcp/new_form" method="POST">
+    <table>
+      <tr>
+        <th>Network</th>
+        <td>
+          <input id="new_network" name="new_network" type="text" class="error" 
value="" />
+        </td>
+      </tr>
+    </table>
+    <input name="commit" type="submit" value="Save changes" />
+  </form>
+</html>
+                        """)
+
+    def test_str_params_unicode_fe_errors(self):
+        return Response('Your network is: %s' %
+            self.form_result.get('new_network'))
+    test_str_params_unicode_fe_errors = \
+        validate(schema=DhcpZoneForm, 
form='new')(test_str_params_unicode_fe_errors)
+
+class TestValidateDecorator(TestWSGIController):
+    def setUp(self):
+        TestWSGIController.setUp(self)
+        app = SetupCacheGlobal(ControllerWrap(ValidatingController),
+                               self.environ, setup_cache=False)
+        app = RegistryManager(app)
+        self.app = TestApp(app)
+
+    def test_validated(self):
+        response = 
self.post_response(action='test_str_params_unicode_fe_errors',
+                                      new_network='http://pylonshq.com/')
+        assert 'Your network is: http://pylonshq.com/' in response
+
+    def test_failed_validation_non_ascii(self):
+        response = 
self.post_response(action='test_str_params_unicode_fe_errors',
+                                      new_network='РПссО́я')
+        print response
+        assert 'That is not a valid URL' in response
+        assert 'РПссО́я' in response

Reply via email to