[Zope-Checkins] SVN: Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ - cleaned up the code for uploading new content

Andreas Jung andreas at andreas-jung.com
Sat Dec 10 12:00:59 EST 2005


Log message for revision 40676:
  - cleaned up the  code for uploading new content
  - hopefully fixed all encoding problems
  - other fixes
  

Changed:
  U   Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py
  U   Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/pt/ptAdd.pt
  U   Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/pt/ptEdit.pt

-=-
Modified: Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py
===================================================================
--- Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py	2005-12-10 15:54:11 UTC (rev 40675)
+++ Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/ZPT.py	2005-12-10 17:00:59 UTC (rev 40676)
@@ -11,11 +11,11 @@
 #
 ##############################################################################
 
-
 """ Zope Page Template module (wrapper for the Zope 3 ZPT implementation) """
 
 __version__='$Revision: 1.48 $'[11:-2]
 
+import re
 from urllib import quote
 import os, AccessControl, Acquisition 
 from Globals import ImageFile, package_home, InitializeClass
@@ -43,6 +43,9 @@
 from zope.pagetemplate.pagetemplate import PageTemplate 
 #from zope.pagetemplate.pagetemplatefile import PageTemplateFile
 
+# regular expression to extract the encoding from the XML preamble
+encoding_reg= re.compile('<\?xml.*?encoding="(.*?)".*?\?>', re.M)
+
 class Src(Acquisition.Explicit):
     """ I am scary code """
 
@@ -58,8 +61,18 @@
         return self.document_src(REQUEST)
 
 
+def sniffEncoding(text, default_encoding='utf-8'):
+    """ try to determine the encoding from html or xml """
 
+    if text.startswith('<?xml'):
+        mo = encoding_reg.search(text)
+        if mo:
+            return mo.group(1)
+    return default_encoding
 
+_default_content_fn = os.path.join(package_home(globals()), 'pt', 'default.html')
+
+
 class ZPT(Script, PageTemplate, Historical, Cacheable,
                        Traversable, PropertyManager):
     """ Z2 wrapper class for Zope 3 page templates """
@@ -67,14 +80,11 @@
     __implements__ = (WriteLockInterface,)
 
     meta_type = 'ZPT'
-    management_page_charset = 'utf-8'
 
     func_defaults = None
     func_code = FuncCode((), 0)
 
     _default_bindings = {'name_subpath': 'traverse_subpath'}
-    _default_content_fn = os.path.join(package_home(globals()),
-                                       'pt', 'default.html')
 
     manage_options = (
         {'label':'Edit', 'action':'pt_editForm',
@@ -96,34 +106,47 @@
     security.declareProtected(view, '__call__')
 
     def __init__(self, id, text=None, content_type=None, encoding='utf-8'):
-        self.id = str(id)
+        self.id = id
         self.ZBindings_edit(self._default_bindings)
-        if text is None:
-            text = open(self._default_content_fn).read()
         self.pt_edit(text, content_type, encoding)
 
-    def _setPropValue(self, id, value):
-        PropertyManager._setPropValue(self, id, value)
-        self.ZCacheable_invalidate()
+    security.declareProtected(change_page_templates, 'pt_encoding')
+    def pt_encoding(self):
+        encoding = sniffEncoding(self.read())
+        return encoding                
 
+    # Use the encoding of the document as encoding for the ZMI to 
+    # avoid any kind of encoding troubles
+    from ComputedAttribute import ComputedAttribute
+    management_page_charset = ComputedAttribute(pt_encoding, 1)
 
-
     security.declareProtected(change_page_templates, 'pt_edit')
     def pt_edit(self, text, content_type, encoding='utf-8'):
+
+        text = text.strip()
+#        if content_type == 'text/html':
+#            if not text.startswith('<?xml'):
+#                # not XHTML -> convert it to unicode
+#                text = unicode(text, encoding)
+
         if not isinstance(text, unicode):
-            text = unicode(text, encoding, 'strict')
-        assert isinstance(text, unicode)
+            text = unicode(text, encoding)
+
+        print content_type, type(text),repr(text)
         self.ZCacheable_invalidate()
         PageTemplate.pt_edit(self, text, content_type)
 
     security.declareProtected(change_page_templates, 'pt_editAction')
-    def pt_editAction(self, REQUEST, title, text, content_type, expand):
+    def pt_editAction(self, REQUEST, title, text, content_type, encoding, expand):
         """Change the title and document."""
+
         if self.wl_isLocked():
             raise ResourceLockedError("File is locked via WebDAV")
-        self.expand=expand
-        self.pt_setTitle(title)
-        self.pt_edit(text, content_type)
+
+        self.expand = expand
+        self.pt_setTitle(title, encoding)
+
+        self.pt_edit(text, content_type, encoding)
         REQUEST.set('text', self.read()) # May not equal 'text'!
         REQUEST.set('title', self.title)
         message = "Saved changes."
@@ -135,36 +158,41 @@
 
     security.declareProtected(change_page_templates, 'pt_setTitle')
     def pt_setTitle(self, title, encoding='utf-8'):
-        
         if not isinstance(title, unicode):
             title = unicode(title, encoding)
         self._setPropValue('title', title)
 
+
+    def _setPropValue(self, id, value):
+        """ set a property and invalidate the cache """
+        PropertyManager._setPropValue(self, id, value)
+        self.ZCacheable_invalidate()
+
+
     security.declareProtected(change_page_templates, 'pt_upload')
-    def pt_upload(self, REQUEST, file='', charset=None):
+    def pt_upload(self, REQUEST, file='', encoding='utf-8'):
         """Replace the document with the text in file."""
+
         if self.wl_isLocked():
             raise ResourceLockedError("File is locked via WebDAV")
 
-        filename = None
-        if not isinstance(file, str):
-            if not file: raise ValueError('File not specified')
+        if isinstance(file, str):
+            filename = None
+            text = file
+        else:
+            if not file: 
+                raise ValueError('File not specified')
             filename = file.filename
-            file = file.read()
+            text = file.read()
 
-        ct, dummy = guess_content_type(filename, file)   
-        if not ct in ('text/html', 'text/xml'):
-            raise ValueError('Unsupported mimetype: %s' % ct)
+        content_type, dummy = guess_content_type(filename, text)   
+        if not content_type in ('text/html', 'text/xml'):
+            raise ValueError('Unsupported mimetype: %s' % content_type)
 
-        if not isinstance(file, unicode):
-            if not charset:
-                raise ValueError('No encoding specified for non-unicode content')
-            file = unicode(file, charset)
+        encoding = sniffEncoding(text, encoding)
+        self.pt_edit(text, content_type, encoding)
+        return self.pt_editForm(manage_tabs_message='Saved changes')
 
-        self.pt_edit(file, ct)
-        message = 'Saved changes.'
-        return self.pt_editForm(manage_tabs_message=message)
-
     security.declareProtected(change_page_templates, 'pt_changePrefs')
     def pt_changePrefs(self, REQUEST, height=None, width=None,
                        dtpref_cols="100%", dtpref_rows="20"):
@@ -199,7 +227,7 @@
 #            self, rev1, rev2, REQUEST,
 #            historyComparisonResults=html_diff(rev1._text, rev2._text) )
 
-    def pt_getContext(self, **kw):
+    def pt_getContext(self, *args, **kw):
         root = self.getPhysicalRoot()
         context = self._getContext()
         c = {'template': self,
@@ -214,15 +242,9 @@
              }
         return c
 
-#    security.declareProtected(change_page_templates, 'write')
-#    def write(self, text):
-#        PageTemplate.write(self, text)
-
     security.declareProtected(view_management_screens, 'manage_main', 'read',
       'ZScriptHTML_tryForm')
 
-
-
     def _exec(self, bound_names, args, kw):
         """Call a Page Template"""
         if not kw.has_key('args'):
@@ -256,7 +278,6 @@
         try:
             # XXX: check the parameters for pt_render()! (aj)
             result = self.pt_render(self.pt_getContext())
-            assert isinstance(result, unicode)
 
 #            result = self.pt_render(extra_context=bound_names)
             if keyset is not None:
@@ -375,41 +396,31 @@
 #manage_addZPTForm.__name__ = 'manage_addZPTForm'
 
 
-def manage_addZPT(self, id, title=None, text=None,
-                           REQUEST=None, submit=None):
+def manage_addZPT(self, id, title='', file=None, encoding='utf-8', submit=None, RESPONSE=None):
     "Add a Page Template with optional file content."
 
-    id = str(id)
-    if REQUEST is None:
-        self._setObject(id, ZPT(id, text))
-        ob = getattr(self, id)
-        if title:
-            ob.pt_setTitle(title)
-        return ob
+    if file:
+        filename = file.filename
+        text = file.read()
+        encoding = sniffEncoding(text)
+        content_type, dummy = guess_content_type(filename, text) 
     else:
-        file = REQUEST.form.get('file')
-        headers = getattr(file, 'headers', None)
-        if headers is None or not file.filename:
-            zpt = ZPT(id, text) # collector 596
-        else:
-            zpt = ZPT(id, file, headers.get('content_type'))
+        text = open(_default_content_fn).read()
+        encoding = 'utf-8'
+        content_type = 'text/html'
 
-        self._setObject(id, zpt)
+    zpt = ZPT(id, text, content_type, encoding)
+    zpt.pt_setTitle(title, encoding)
+    self._setObject(id, zpt)
+    zpt = getattr(self, id)
 
-        # collector 596
-        if title:
-            ob = getattr(self, id)
-            ob.pt_setTitle(title)
-
-        try:
-            u = self.DestinationURL()
-        except AttributeError:
-            u = REQUEST['URL1']
-
+    if RESPONSE:    
         if submit == " Add and Edit ":
-            u = "%s/%s" % (u, quote(id))
-        REQUEST.RESPONSE.redirect(u+'/manage_main')
-    return ''
+            RESPONSE.redirect(zpt.absolute_url() + '/manage_main')
+        else:
+            RESPONSE.redirect(self.absolute_url() + '/manage_main')
+    else:        
+        return zpt
 
 from Products.PageTemplates import misc_
 misc_['exclamation.gif'] = ImageFile('pt/exclamation.gif', globals())

Modified: Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/pt/ptAdd.pt
===================================================================
--- Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/pt/ptAdd.pt	2005-12-10 15:54:11 UTC (rev 40675)
+++ Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/pt/ptAdd.pt	2005-12-10 17:00:59 UTC (rev 40676)
@@ -35,8 +35,19 @@
   </tr>
   <tr>
     <td align="left" valign="top">
+    <div class="form-optional">
+    Encoding
+    </div>
     </td>
     <td align="left" valign="top">
+      <input type="text" name="encoding" size="25" value="utf-8" />
+      <em>(only used for non-XML and non-HTML content)</em>
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    </td>
+    <td align="left" valign="top">
     <div class="form-element">
     <input class="form-element" type="submit" name="submit" 
      value=" Add " /> 

Modified: Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/pt/ptEdit.pt
===================================================================
--- Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/pt/ptEdit.pt	2005-12-10 15:54:11 UTC (rev 40675)
+++ Zope/branches/ajung-zpt-integration/lib/python/Products/ZPT/pt/ptEdit.pt	2005-12-10 17:00:59 UTC (rev 40676)
@@ -18,30 +18,29 @@
            tal:attributes="value request/title | context/title" />
     </td>
     <td align="left" valign="middle">
-    <div class="form-optional">
-    Content-Type
-    </div>
+    <div class="form-label"> Last Modified </div>
     </td>
     <td align="left" valign="middle">
-    <input type="text" name="content_type" size="14" 
-           tal:attributes="value request/content_type | context/content_type" />
+      <div class="form-text" 
+       tal:content="python:context.bobobase_modification_time().strftime('%Y-%m-%d %I:%M %p')">1/1/2000
+      </div>
     </td>
   </tr>
   <tr>
     <td align="left" valign="middle">
     <div class="form-label">
-    Last Modified
+    Content-Type
     </div>
     </td>
     <td align="left" valign="middle">
-    <div class="form-text" 
-     tal:content="python:context.bobobase_modification_time().strftime('%Y-%m-%d %I:%M %p')">1/1/2000
-    </div>
+      <select name="content_type" size="1" tal:define="ct context/content_type">
+        <option value="text/html" tal:attributes="SELECTED python: ct == 'text/html'">text/html</option>
+        <option value="text/xml" tal:attributes="SELECTED python: ct == 'text/xml'">text/xml</option>
+      </select>
     </td>
     <td align="left" valign="top" colspan=2>
       <a href="source.html" tal:condition="context/html">Browse HTML source</a>
       <a href="source.xml" tal:condition="not:context/html">Browse XML source</a>
-
       <br>
       <input type="hidden" name="expand:int:default" value="0">
       <input type="checkbox" value="1" name="expand:int"
@@ -50,13 +49,21 @@
     </td>
   </tr>
 
+
+  <tr> 
+    <td align="left" valign="middle" class="form-label">Encoding</td>
+    <td>
+      <input type="text" readonly name="encoding" tal:attributes="value context/pt_encoding"/>
+    </td>
+  </tr>
+
   <!-- XXX: check if 'None' is a proper argument for 'namespace' -->
   <tr tal:define="errors python: context.pt_errors(None)" tal:condition="errors">
     <tal:block define="global body python:context.document_src({'raw':1})"/>
     <td align="left" valign="middle" class="form-label">Errors</td>
     <td align="left" valign="middle" style="background-color: #FFDDDD"
     colspan="3">
-<pre tal:content="python:modules['string'].join(errors, '\n')">errors</pre>
+<pre tal:content="python: '\n'.join(errors)">errors</pre>
     </td>
   </tr>
 
@@ -64,10 +71,12 @@
     <td align="left" valign="middle" class="form-label">Warnings</td>
     <td align="left" valign="middle" style="background-color: #FFEEDD"
      colspan="3">
-<pre tal:content="python:modules['string'].join(warnings, '\n')">errors</pre>
+<pre tal:content="python: '\n'.join(warnings)">errors</pre>
     </td>
   </tr>
 
+
+
   <tr>
     <td align="left" valign="top" colspan="4"
       tal:define="width request/dtpref_cols | string:100%;
@@ -120,7 +129,7 @@
   </div>
   </td>
   <td align="left" valign="top">
-  <input type="file" name="file" size="25" value="">
+  <input type="file" name="file" size="40" value="">
   </td>
 </tr>
 <tr>
@@ -129,9 +138,12 @@
       Encoding &nbsp;
     </div>
   </td>
-  <td align="left" valign="top">
-    <input name="charset" value="utf-8"/>
+  <td align="left" valign="top" colspan="2">
+    <input name="encoding" value="utf-8"/>
   </td>
+  <td align="left" valign="top" colspan="1">
+    <em>(only used for non-XML and non-XHTML content)</em>
+  </td>
 </tr>
 <tr>
   <td></td>



More information about the Zope-Checkins mailing list