[Zope-Checkins] CVS: Zope/lib/python/ZPublisher - HTTPResponse.py:1.53.14.1

Toby Dickenson tdickenson@geminidataloggers.com
Thu, 7 Mar 2002 04:32:01 -0500


Update of /cvs-repository/Zope/lib/python/ZPublisher
In directory cvs.zope.org:/tmp/cvs-serv25815/lib/python/ZPublisher

Modified Files:
      Tag: toby-unicode-branch
	HTTPResponse.py 
Log Message:
first phase of dtml unicode support

=== Zope/lib/python/ZPublisher/HTTPResponse.py 1.53 => 1.53.14.1 ===
 import  types, sys,  re
 from string import translate, maketrans
-from types import StringType, InstanceType, LongType
+from types import StringType, InstanceType, LongType, UnicodeType
 from BaseResponse import BaseResponse
 from zExceptions import Unauthorized
 
@@ -230,7 +230,11 @@
             if hasattr(body,'asHTML'):
                 body=body.asHTML()
 
-        body=str(body)
+        body=ustr(body)
+
+        if type(body) is UnicodeType:
+            body = self._encode_unicode(body)
+
         l=len(body)
         if ((l < 200) and body[:1]=='<' and body.find('>')==l-1 and 
             bogus_str_search(body) is not None):
@@ -265,6 +269,16 @@
         self.insertBase()
         return self
 
+    def _encode_unicode(self,body,charset_re=re.compile(r'text/[0-9a-z]+\s*;\s*charset=([-_0-9a-z]+)(?:(?:\s*;)|\Z)',re.IGNORECASE)):
+        # Encode the Unicode data as requested
+        if self.headers.has_key('content-type'):
+            match = charset_re.match(self.headers['content-type'])
+            if match:
+                encoding = match.group(1)
+                return body.encode(encoding)
+        # Use the default character encoding
+        return body.encode('latin1','replace')
+
     def setBase(self,base):
         'Set the base URL for the returned document.'
         if base[-1:] != '/':
@@ -531,7 +545,7 @@
             # Try to capture exception info for bci calls
             et = translate(str(t), nl2sp)
             self.setHeader('bobo-exception-type', et)
-            ev = translate(str(v), nl2sp)
+            ev = translate(ustr(v), nl2sp)
             if ev.find( '<html>') >= 0:
                 ev = 'bobo exception'
             self.setHeader('bobo-exception-value', ev[:255])
@@ -574,7 +588,7 @@
         b = v
         if isinstance(b, Exception):
             try:
-                b = str(b)
+                b = ustr(b)
             except:
                 b = '<unprintable %s object>' % type(b).__name__
 
@@ -583,23 +597,28 @@
                 (str(t),
                  'Zope has exited normally.<p>' + self._traceback(t, v, tb)),
                 is_error=1)
-        elif type(b) is not types.StringType or tag_search(b) is None:
-            body = self.setBody(
-                (str(t),
-                'Sorry, a site error occurred.<p>'
-                 + self._traceback(t, v, tb)),
-                 is_error=1)
-        elif b.strip().lower()[:6]=='<html>' or \
-              b.strip().lower()[:14]=='<!doctype html':
-            # error is an HTML document, not just a snippet of html
-            body = self.setBody(b + self._traceback(t, '(see above)', tb),
-                              is_error=1)
         else:
-            body = self.setBody((str(t),
-                               b + self._traceback(t,'(see above)', tb)),
-                              is_error=1)
-        del tb
-        return body
+            try:
+                match = tag_search(b)
+            except TypeError:
+                match = None
+            if match is None:
+                body = self.setBody(
+                    (str(t),
+                    'Sorry, a site error occurred.<p>'
+                     + self._traceback(t, v, tb)),
+                     is_error=1)
+            elif b.strip().lower()[:6]=='<html>' or \
+                  b.strip().lower()[:14]=='<!doctype html':
+                # error is an HTML document, not just a snippet of html
+                body = self.setBody(b + self._traceback(t, '(see above)', tb),
+                                  is_error=1)
+            else:
+                body = self.setBody((str(t),
+                                   b + self._traceback(t,'(see above)', tb)),
+                                  is_error=1)
+            del tb
+            return body
 
     _wrote=None
 
@@ -694,3 +713,23 @@
 
         self.stdout.write(data)
 
+
+# Duplicated from DocumentTemplate, to avoid the dependency.
+# Is there a better place for it?
+def ustr(v):
+    """convert an object to a string or unicode string
+    """
+    string_types = (StringType,UnicodeType)
+    if type(v) in string_types:
+        return v
+    else:
+        try:
+            fn = v.__str__
+        except AttributeError:
+            return str(v)
+        else:
+            v = fn()
+            if type(v) in string_types:
+                return v
+            else:
+                raise ValueError('__str__ returned wrong type')