[Zope-Checkins] SVN: Zope/branches/ajung-final-zpt-integration/lib/python/Products/PageTemplates/PageTemplateFile.py This version of PageTemplateFile seems to work fine although

Andreas Jung andreas at andreas-jung.com
Wed Mar 1 11:03:27 EST 2006


Log message for revision 65667:
  This version of PageTemplateFile seems to work fine although
  it requires further testing.
  
  The implementation uses its own Engine and traverse since browser 
  pages configured through ZCML are looked up by a bobo_traverse()
  hack. However the standdard simpleTraverse() method of zope.tales.
  expressions only performs the traversal using __getitem__(). So we
  define our own traverser that also tries a traversal using 
  restrictedTraverse().
  
  The code is still ugly, needs some more cleanup and renaming.
  
  

Changed:
  U   Zope/branches/ajung-final-zpt-integration/lib/python/Products/PageTemplates/PageTemplateFile.py

-=-
Modified: Zope/branches/ajung-final-zpt-integration/lib/python/Products/PageTemplates/PageTemplateFile.py
===================================================================
--- Zope/branches/ajung-final-zpt-integration/lib/python/Products/PageTemplates/PageTemplateFile.py	2006-03-01 14:22:51 UTC (rev 65666)
+++ Zope/branches/ajung-final-zpt-integration/lib/python/Products/PageTemplates/PageTemplateFile.py	2006-03-01 16:03:26 UTC (rev 65667)
@@ -10,35 +10,97 @@
 # FOR A PARTICULAR PURPOSE
 #
 ##############################################################################
-"""Filesystem Page Template module
 
-Zope object encapsulating a Page Template from the filesystem.
-"""
+import os
 
-__version__ = '$Revision: 1.30 $'[11:-2]
+from Globals import package_home, InitializeClass
+from App.config import getConfiguration
+from ZopePageTemplate import ZopePageTemplate
+from zope.app.content_types import guess_content_type
+import AccessControl
 
-import os, AccessControl
-from logging import getLogger
-from Globals import package_home, DevelopmentMode
+from ComputedAttribute import ComputedAttribute
+from OFS.SimpleItem import SimpleItem
+from Expressions import SecureModuleImporter
+from OFS.Traversable import Traversable
+from zope.pagetemplate.pagetemplatefile import PageTemplateFile as PTF
+from zope.pagetemplate.pagetemplate import PageTemplate as PT
+
 from Shared.DC.Scripts.Script import Script
+
+from OFS.SimpleItem import Item_w__name__
 from Shared.DC.Scripts.Signature import FuncCode
-from AccessControl import getSecurityManager
-from OFS.Traversable import Traversable
-from PageTemplate import PageTemplate
-from Expressions import SecureModuleImporter
-from ComputedAttribute import ComputedAttribute
-from Acquisition import aq_parent, aq_inner
-from App.config import getConfiguration
-from OFS.SimpleItem import Item_w__name__
 
 
-LOG = getLogger('PageTemplateFile')
+from zope.tales.tales import ExpressionEngine
+from zope.tales.expressions import PathExpr, StringExpr, NotExpr, DeferExpr, SubPathExpr
+from zope.tales.tales import _valid_name, _parse_expr, NAME_RE, Undefined 
+from zope.tales.expressions import SimpleModuleImporter
+from zope.tales.pythonexpr import PythonExpr
 
-class PageTemplateFile(Item_w__name__, Script, PageTemplate, Traversable):
-    "Zope wrapper for filesystem Page Template using TAL, TALES, and METAL"
+from zope.tales.expressions import PathExpr
 
-    meta_type = 'Page Template (File)'
+_marker = object()
 
+def extendedSimpleTraverse(object, path_items, econtext):
+    """Traverses a sequence of names, first trying attributes then items.
+    """
+
+    for name in path_items:
+        next = getattr(object, name, _marker)
+        if next is not _marker:
+            object = next
+        elif hasattr(object, '__getitem__'):
+            try:
+                object = object[name]
+            except:
+                # FIX bare try..except
+                object = object.restrictedTraverse(name)
+        else:
+            # Allow AttributeError to propagate
+            object = getattr(object, name)
+    return object
+
+
+
+class MyPathExpr(PathExpr):
+
+    def __init__(self, name, expr, engine, traverser=extendedSimpleTraverse):
+        self._s = expr
+        self._name = name
+        paths = expr.split('|')
+        self._subexprs = []
+        add = self._subexprs.append
+        for i in range(len(paths)):
+            path = paths[i].lstrip()
+            if _parse_expr(path):
+                # This part is the start of another expression type,
+                # so glue it back together and compile it.
+                add(engine.compile('|'.join(paths[i:]).lstrip()))
+                break
+            add(SubPathExpr(path, traverser, engine)._eval)
+
+
+
+def Engine():
+    e = ExpressionEngine()
+    reg = e.registerType
+    for pt in MyPathExpr._default_type_names:
+        reg(pt, MyPathExpr)
+    reg('string', StringExpr)
+    reg('python', PythonExpr)
+    reg('not', NotExpr)
+    reg('defer', DeferExpr)
+    e.registerBaseName('modules', SimpleModuleImporter())
+    return e
+
+Engine = Engine()
+
+
+
+class PageTemplateFile(SimpleItem, Script, PT, Traversable):
+
+
     func_defaults = None
     func_code = FuncCode((), 0)
     _v_last_read = 0
@@ -53,32 +115,44 @@
     security.declareProtected('View management screens',
       'read', 'document_src')
 
+    _default_bindings = {'name_subpath': 'traverse_subpath'}
+
+
     def __init__(self, filename, _prefix=None, **kw):
-        self.ZBindings_edit(self._default_bindings)
-        if _prefix is None:
-            _prefix = getConfiguration().softwarehome
-        elif not isinstance(_prefix, str):
-            _prefix = package_home(_prefix)
-        name = kw.get('__name__')
+
+        name = None
+        if kw.has_key('__name__'):
+            name = kw['__name__']
+            del kw['__name__'] 
+
         basepath, ext = os.path.splitext(filename)
+
         if name:
-            self._need__name__ = 0
-            self.__name__ = name
+            self.id = self.__name__ = name
         else:
-            self.__name__ = os.path.basename(basepath)
+            self.id = self.__name__ = os.path.basename(basepath)
+
+        if _prefix:
+            if isinstance(_prefix, str):
+                filename = os.path.join(_prefix, filename)
+            else:
+                filename = os.path.join(package_home(_prefix), filename)
+
         if not ext:
-            # XXX This is pretty bogus, but can't be removed since
-            # it's been released this way.
             filename = filename + '.zpt'
-        self.filename = os.path.join(_prefix, filename)
 
-    def getId(self):
-        """return the ID of this object"""
-        return self.__name__
-    
+        self.filename = filename
+
+        content = open(filename).read()
+
+        from ZopePageTemplate import guess_type
+        self.pt_edit( content, guess_type(filename, content))
+
+
     def pt_getContext(self):
         root = self.getPhysicalRoot()
         context = self._getContext()
+        from DateTime.DateTime import DateTime
         c = {'template': self,
              'here': context,
              'context': context,
@@ -86,6 +160,7 @@
              'nothing': None,
              'options': {},
              'root': root,
+             'DateTime' : DateTime,
              'request': getattr(root, 'REQUEST', None),
              'modules': SecureModuleImporter,
              }
@@ -106,11 +181,14 @@
             pass
 
         # Execute the template in a new security context.
-        security = getSecurityManager()
+        security = AccessControl.getSecurityManager()
         bound_names['user'] = security.getUser()
         security.addContext(self)
+
         try:
-            return self.pt_render(extra_context=bound_names)
+            context = self.pt_getContext()
+            context.update(bound_names)
+            return self.pt_render(context)
         finally:
             security.removeContext(self)
 
@@ -118,41 +196,6 @@
         self._cook_check()
         return PageTemplate.pt_macros(self)
 
-    def pt_source_file(self):
-        """Returns a file name to be compiled into the TAL code."""
-        return self.__name__  # Don't reveal filesystem paths
-
-    def _cook_check(self):
-        if self._v_last_read and not DevelopmentMode:
-            return
-        __traceback_info__ = self.filename
-        try:
-            mtime = os.path.getmtime(self.filename)
-        except OSError:
-            mtime = 0
-        if self._v_program is not None and mtime == self._v_last_read:
-            return
-        f = open(self.filename, "rb")
-        try:
-            text = f.read(XML_PREFIX_MAX_LENGTH)
-        except:
-            f.close()
-            raise
-        t = sniff_type(text)
-        if t != "text/xml":
-            # For HTML, we really want the file read in text mode:
-            f.close()
-            f = open(self.filename)
-            text = ''
-        text += f.read()
-        f.close()
-        self.pt_edit(text, t)
-        self._cook()
-        if self._v_errors:
-            LOG.error('Error in template %s' % '\n'.join(self._v_errors))
-            return
-        self._v_last_read = mtime
-
     def document_src(self, REQUEST=None, RESPONSE=None):
         """Return expanded document source."""
 
@@ -182,25 +225,12 @@
         """
         return None
 
+    def pt_getEngine(self):
+        return Engine
+
     def __getstate__(self):
         from ZODB.POSException import StorageError
         raise StorageError, ("Instance of AntiPersistent class %s "
                              "cannot be stored." % self.__class__.__name__)
 
-
-XML_PREFIXES = [
-    "<?xml",                      # ascii, utf-8
-    "\xef\xbb\xbf<?xml",          # utf-8 w/ byte order mark
-    "\0<\0?\0x\0m\0l",            # utf-16 big endian
-    "<\0?\0x\0m\0l\0",            # utf-16 little endian
-    "\xfe\xff\0<\0?\0x\0m\0l",    # utf-16 big endian w/ byte order mark
-    "\xff\xfe<\0?\0x\0m\0l\0",    # utf-16 little endian w/ byte order mark
-    ]
-
-XML_PREFIX_MAX_LENGTH = max(map(len, XML_PREFIXES))
-
-def sniff_type(text):
-    for prefix in XML_PREFIXES:
-        if text.startswith(prefix):
-            return "text/xml"
-    return None
+InitializeClass(PageTemplateFile)



More information about the Zope-Checkins mailing list