Commits

Allan Crooks  committed beb3493

Fix for recent commits which were causing a number of tests to fail in Python 3.

  • Participants
  • Parent commits a119711

Comments (0)

Files changed (3)

File cherrypy/_cperror.py

                 # The caller function may be setting headers manually,
                 # so we delegate to it completely. We may be returning
                 # an iterator as well as a string here.
-                return error_page(**kwargs)
+                #
+                # We *must* make sure any content is not unicode.
+                result = error_page(**kwargs)
+                if cherrypy.lib.is_iterator(result):
+                    from cherrypy.lib.encoding import UTF8StreamEncoder
+                    return UTF8StreamEncoder(result)
+                elif isinstance(result, cherrypy._cpcompat.unicodestr):
+                    return result.encode('utf-8')
+                else:
+                    if not isinstance(result, cherrypy._cpcompat.bytestr):
+                        raise ValueError('error page function did not '
+                            'return a bytestring, unicodestring or an '
+                            'iterator - returned object of type %s.'
+                            % (type(result).__name__))
+                    return result
             else:
                 # Load the template from this path.
                 template = tonative(open(error_page, 'rb').read())
     return result.encode('utf-8')
 
 
+
 _ie_friendly_error_sizes = {
     400: 512, 403: 256, 404: 512, 405: 256,
     406: 512, 408: 512, 409: 512, 410: 256,

File cherrypy/lib/encoding.py

         if not isinstance(default_encoding, list):
             default_encoding = [default_encoding]
         body.attempt_charsets = body.attempt_charsets + default_encoding
+        
+class UTF8StreamEncoder:
+    def __init__(self, iterator):
+        self._iterator = iterator
+        
+    def __iter__(self):
+        return self
+        
+    def next(self):
+        return self.__next__()
+        
+    def __next__(self):
+        res = next(self._iterator)
+        if isinstance(res, unicodestr):
+            res = res.encode('utf-8')
+        return res
+        
+    def __getattr__(self, attr):
+        if attr.startswith('__'):
+            raise AttributeError(self, attr)
+        return getattr(self._iterator, attr)
 
 
 class ResponseEncoder:

File cherrypy/test/helper.py

 
         # First, test the response body without checking the traceback.
         # Stick a match-all group (.*) in to grab the traceback.
-        esc = re.escape
-        epage = esc(page)
+        def esc(text):
+            return re.escape(ntob(text))
+        epage = re.escape(page)
         epage = epage.replace(
             esc('<pre id="traceback"></pre>'),
-            esc('<pre id="traceback">') + '(.*)' + esc('</pre>'))
-        m = re.match(ntob(epage, self.encoding), self.body, re.DOTALL)
+            esc('<pre id="traceback">') + ntob('(.*)') + esc('</pre>'))
+        m = re.match(epage, self.body, re.DOTALL)
         if not m:
             self._handlewebError(
                 'Error page does not match; expected:\n' + page)