[Zope-Checkins] CVS: Zope/lib/python/ZPublisher - BeforeTraverse.py:1.7.32.1 Converters.py:1.14.28.1 HTTPRequest.py:1.62.18.1 HTTPResponse.py:1.53.28.1

Casey Duncan casey@zope.com
Wed, 27 Mar 2002 15:52:02 -0500


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

Modified Files:
      Tag: casey-death_to_index_html-branch
	BeforeTraverse.py Converters.py HTTPRequest.py HTTPResponse.py 
Log Message:
Updating branch to head for testing


=== Zope/lib/python/ZPublisher/BeforeTraverse.py 1.7 => 1.7.32.1 ===
 """BeforeTraverse interface and helper classes"""
 
+from zLOG import LOG, ERROR
+
 # Interface
 
 def registerBeforeTraverse(container, object, app_handle, priority=99):
@@ -96,7 +98,11 @@
         if prior is not None:
             prior(container, request)
         for cob in self._list:
-            cob(container, request)
+            try:
+                cob(container, request)
+            except TypeError:
+                LOG('MultiHook', ERROR, '%s call %s failed.' % (
+                    `self._hookname`, `cob`), error=sys.exc_info())
 
     def add(self, cob):
         self._list.append(cob)


=== Zope/lib/python/ZPublisher/Converters.py 1.14 => 1.14.28.1 ===
     return v
 
+class _unicode_converter:
+    def __call__(self,v):
+        # Convert a regular python string. This probably doesnt do what you want,
+        # whatever that might be. If you are getting exceptions below, you
+        # probably missed the encoding tag from a form field name. Use:
+        #       <input name="description:utf8:ustring" .....
+        # rather than
+        #       <input name="description:ustring" .....
+        if hasattr(v,'read'): v=v.read()
+        v = unicode(v)
+        return self.convert_unicode(v)
+
+    def convert_unicode(self,v):
+        raise NotImplementedError('convert_unicode')
+
+class field2ustring(_unicode_converter):
+    def convert_unicode(self,v):
+        return v
+field2ustring = field2ustring()
+
+class field2utokens(_unicode_converter):
+    def convert_unicode(self,v):
+        return v.split()
+field2utokens = field2utokens()
+
+class field2utext(_unicode_converter):
+    def convert_unicode(self,v):
+        return unicode(field2text(v.encode('utf8')),'utf8')
+field2utext = field2utext()
+
+class field2ulines(_unicode_converter):
+    def convert_unicode(self,v):
+        return field2utext.convert_unicode(v).split('\n')
+field2ulines = field2ulines()
+
 type_converters = {
     'float':    field2float,
     'int':      field2int,
@@ -123,7 +158,11 @@
     'tokens':   field2tokens,
     'lines':    field2lines,
     'text':     field2text,
-    'boolean':     field2boolean,
+    'boolean':  field2boolean,
+    'ustring':  field2ustring,
+    'utokens':  field2utokens,
+    'ulines':   field2ulines,
+    'utext':    field2utext,
     }
 
 get_converter=type_converters.get


=== Zope/lib/python/ZPublisher/HTTPRequest.py 1.62 => 1.62.18.1 ===
 __version__='$Revision$'[11:-2]
 
-import re, sys, os,  urllib, time, whrandom, cgi
+import re, sys, os,  urllib, time, whrandom, cgi, codecs
 from BaseRequest import BaseRequest
 from HTTPResponse import HTTPResponse
 from cgi import FieldStorage, escape
@@ -384,6 +384,7 @@
                         item=item.value
 
                 flags=0
+                character_encoding = ''
 
                 # Loop through the different types and set
                 # the appropriate flags
@@ -431,6 +432,8 @@
                             flags=flags|RECORDS
                         elif type_name == 'ignore_empty':
                             if not item: flags=flags|EMPTY
+                        elif has_codec(type_name):
+                            character_encoding = type_name
     
                         l=key.rfind(':')
                         if l < 0: break
@@ -456,7 +459,17 @@
                     # defer conversion
                     if flags&CONVERTED:
                         try:
-                            item=converter(item)
+                            if character_encoding:
+                                # We have a string with a specified character encoding.
+                                # This gets passed to the converter either as unicode, if it can
+                                # handle it, or crunched back down to latin-1 if it can not.
+                                item = unicode(item,character_encoding)
+                                if hasattr(converter,'convert_unicode'):
+                                    item = converter.convert_unicode(item)
+                                else:
+                                    item = converter(item.encode('latin1'))
+                            else:
+                                item=converter(item)
                         except:
                             if (not item and not (flags&DEFAULT) and
                                 defaults.has_key(key)):
@@ -965,6 +978,13 @@
                 return name, password
 
 
+def has_codec(x):
+    try:
+        codecs.lookup(x)
+    except LookupError:
+        return 0
+    else:
+        return 1
 
 
 base64=None


=== Zope/lib/python/ZPublisher/HTTPResponse.py 1.53 => 1.53.28.1 ===
 __version__='$Revision$'[11:-2]
 
-import  types, sys,  re
+import types, os, 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
 
@@ -92,6 +92,17 @@
 
 accumulate_header={'set-cookie': 1}.has_key
 
+tb_style = os.environ.get('HTTP_TRACEBACK_STYLE', '').lower()
+if tb_style == 'none':
+    tb_delims = None, None
+elif tb_style == 'js':
+    tb_delims = ('''<pre onclick="this.firstChild.data=this.lastChild.data">
+        &sect;<!--''',  '--></pre>')
+elif tb_style == 'plain':
+    tb_delims = '<pre>', '</pre>'
+else:
+    tb_delims = '<!--', '-->'
+
 class HTTPResponse(BaseResponse):
     """\
     An object representation of an HTTP response.
@@ -230,7 +241,16 @@
             if hasattr(body,'asHTML'):
                 body=body.asHTML()
 
-        body=str(body)
+        if type(body) is UnicodeType:
+            body = self._encode_unicode(body)
+        elif type(body) is StringType:
+            pass
+        else:
+            try:
+                body = str(body)
+            except UnicodeError:
+                body = _encode_unicode(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 +285,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:] != '/':
@@ -399,9 +429,9 @@
         tb = '\n'.join(tb)
         tb = self.quoteHTML(tb)
         if self.debug_mode: _tbopen, _tbclose = '<PRE>', '</PRE>'
-        else:               _tbopen, _tbclose = '''<pre
-          onclick="this.firstChild.data=this.lastChild.data">
-        &sect;<!--''',  '--></pre>'
+        else:               _tbopen, _tbclose = tb_delims
+        if _tbopen is None:
+            return ''
         return "\n%s\n%s\n%s" % (_tbopen, tb, _tbclose)
 
     def redirect(self, location, status=302, lock=0):
@@ -583,23 +613,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
 
@@ -693,4 +728,5 @@
             self.stdout.flush()
 
         self.stdout.write(data)
+