[Checkins] SVN: five.pt/trunk/ Continued work on CMF bindings.
Malthe Borch
mborch at gmail.com
Sat Nov 15 20:18:27 EST 2008
Log message for revision 92996:
Continued work on CMF bindings.
Changed:
U five.pt/trunk/CHANGES.txt
U five.pt/trunk/src/five/pt/__init__.py
A five.pt/trunk/src/five/pt/cmf.py
U five.pt/trunk/src/five/pt/configure.zcml
A five.pt/trunk/src/five/pt/expressions.py
U five.pt/trunk/src/five/pt/pagetemplate.py
-=-
Modified: five.pt/trunk/CHANGES.txt
===================================================================
--- five.pt/trunk/CHANGES.txt 2008-11-16 00:27:21 UTC (rev 92995)
+++ five.pt/trunk/CHANGES.txt 2008-11-16 01:18:27 UTC (rev 92996)
@@ -4,6 +4,12 @@
HEAD
----
+- Register custom file-system page template class for use with CMF
+ form controllers. [malthe]
+
+- Register custom file-system page template class for use with CMF
+ directory views. [malthe]
+
- Added meta-directives to register browser views, viewlets and
viewlet managers using Chameleon templates. [malthe]
Modified: five.pt/trunk/src/five/pt/__init__.py
===================================================================
--- five.pt/trunk/src/five/pt/__init__.py 2008-11-16 00:27:21 UTC (rev 92995)
+++ five.pt/trunk/src/five/pt/__init__.py 2008-11-16 01:18:27 UTC (rev 92996)
@@ -1 +1 @@
-#
\ No newline at end of file
+#
Added: five.pt/trunk/src/five/pt/cmf.py
===================================================================
--- five.pt/trunk/src/five/pt/cmf.py (rev 0)
+++ five.pt/trunk/src/five/pt/cmf.py 2008-11-16 01:18:27 UTC (rev 92996)
@@ -0,0 +1,111 @@
+import sys
+import Globals
+
+from Products.CMFCore.FSObject import FSObject
+from Products.CMFCore import DirectoryView
+from Products.CMFCore import permissions
+
+from Products.CMFFormController.BaseControllerPageTemplate import \
+ BaseControllerPageTemplate as BaseCPT
+from Products.CMFFormController.FSControllerBase import FSControllerBase
+
+from Shared.DC.Scripts.Script import Script
+from AccessControl import ClassSecurityInfo
+from RestrictedPython import Utilities
+
+from pagetemplate import PageTemplateFile
+from pagetemplate import FiveTemplateFile
+
+_marker = object()
+
+class EContext(object):
+ vars = None
+
+ def setLocal(self, name, value):
+ if self.vars is None:
+ frame = sys._getframe()
+ vars = _marker
+ while vars is _marker and frame is not None:
+ vars = frame.f_locals.get('_scope', _marker)
+ frame = frame.f_back
+ if vars is _marker:
+ raise RuntimeError, 'Context not found'
+ self.vars = vars
+ self.vars[name] = value
+
+class CMFTemplateFile(FiveTemplateFile):
+ @property
+ def utility_builtins(self):
+ builtins = dict(
+ econtext=EContext())
+ builtins.update(
+ Utilities.utility_builtins)
+ return builtins
+
+class CMFPageTemplateFile(PageTemplateFile):
+ template_class = CMFTemplateFile
+
+class FSPageTemplate(FSObject, Script):
+ meta_type = 'Filesystem Page Template'
+
+ security = ClassSecurityInfo()
+ security.declareObjectProtected(permissions.View)
+
+ _default_bindings = {'name_subpath': 'traverse_subpath'}
+
+ template = None
+
+ def __init__(self, id, filepath, fullname=None, properties=None):
+ FSObject.__init__(self, id, filepath, fullname, properties)
+ self.ZBindings_edit(self._default_bindings)
+
+ # instantiate page template
+ self.template = CMFPageTemplateFile(filepath)
+
+ def _readFile(self, reparse):
+ # templates are lazy
+ if reparse:
+ self.template.read()
+
+ def __call__(self, *args, **kwargs):
+ kwargs['args'] = args
+ return self.template(self, **kwargs)
+
+ @property
+ def macros(self):
+ return self.template.macros
+
+class FSControllerPageTemplate(FSControllerBase, FSPageTemplate, BaseCPT):
+ def __init__(self, id, filepath, fullname=None, properties=None):
+ FSPageTemplate.__init__(self, id, filepath, fullname, properties)
+ self.filepath = filepath
+
+ self._read_action_metadata(self.getId(), filepath)
+ self._read_validator_metadata(self.getId(), filepath)
+
+ def _readFile(self, reparse):
+ FSPageTemplate._readFile(self, reparse)
+ self._readMetadata()
+
+ def _updateFromFS(self):
+ # workaround for Python 2.1 multiple inheritance lameness
+ return self._baseUpdateFromFS()
+
+ def _readMetadata(self):
+ # workaround for Python 2.1 multiple inheritance lameness
+ return self._baseReadMetadata()
+
+ def __call__(self, *args, **kwargs):
+ return self._call(FSControllerPageTemplate.__call__, *args, **kwargs)
+
+Globals.InitializeClass(FSPageTemplate)
+Globals.InitializeClass(FSControllerPageTemplate)
+
+DirectoryView.registerFileExtension('pt', FSPageTemplate)
+DirectoryView.registerFileExtension('zpt', FSPageTemplate)
+DirectoryView.registerFileExtension('html', FSPageTemplate)
+DirectoryView.registerFileExtension('htm', FSPageTemplate)
+DirectoryView.registerFileExtension('cpt', FSControllerPageTemplate)
+
+DirectoryView.registerMetaType('Page Template', FSPageTemplate)
+DirectoryView.registerMetaType('Controller Page Template', FSControllerPageTemplate)
Modified: five.pt/trunk/src/five/pt/configure.zcml
===================================================================
--- five.pt/trunk/src/five/pt/configure.zcml 2008-11-16 00:27:21 UTC (rev 92995)
+++ five.pt/trunk/src/five/pt/configure.zcml 2008-11-16 01:18:27 UTC (rev 92996)
@@ -1,5 +1,16 @@
<configure xmlns="http://namespaces.zope.org/zope">
+ <include package="five.pt" file="meta.zcml" />
+ <include package="five.pt.cmf" />
+
<include package="z3c.pt" />
+ <utility
+ name="path"
+ component=".expressions.path_translator" />
+
+ <utility
+ name="exists"
+ component=".expressions.exists_translator" />
+
</configure>
Added: five.pt/trunk/src/five/pt/expressions.py
===================================================================
--- five.pt/trunk/src/five/pt/expressions.py (rev 0)
+++ five.pt/trunk/src/five/pt/expressions.py 2008-11-16 01:18:27 UTC (rev 92996)
@@ -0,0 +1,57 @@
+from z3c.pt.expressions import PathTranslator
+from z3c.pt.expressions import ExistsTranslator
+from z3c.pt.expressions import ZopeExistsTraverser
+
+from zExceptions import NotFound, Unauthorized
+
+from zope.traversing.adapters import traversePathElement
+from zope.traversing.interfaces import TraversalError
+
+from Products.PageTemplates.Expressions import render
+
+_marker = object()
+
+class FiveTraverser(object):
+ def __call__(self, base, request, call, *path_items):
+ """See ``zope.app.pagetemplate.engine``."""
+
+ ob = base
+
+ length = len(path_items)
+ if length:
+ i = 0
+ while i < length:
+ name = path_items[i]
+ i += 1
+ next = getattr(base, name, _marker)
+ if next is not _marker:
+ base = next
+ continue
+ else:
+ # special-case dicts for performance reasons
+ if isinstance(base, dict):
+ base = base[name]
+ else:
+ base = traversePathElement(
+ base, name, path_items[i:], request=request)
+
+ if call and getattr(base, '__call__', _marker) is not _marker:
+ # here's where we're different from the standard path
+ # traverser
+ return render(base, ob)
+
+ return base
+
+class PathTranslator(PathTranslator):
+ path_traverse = FiveTraverser()
+
+path_translator = PathTranslator()
+
+class FiveExistsTraverser(ZopeExistsTraverser):
+ exceptions = AttributeError, LookupError, TypeError, \
+ NotFound, Unauthorized, TraversalError
+
+class ExistsTranslator(ExistsTranslator):
+ path_traverse = FiveExistsTraverser()
+
+exists_translator = ExistsTranslator()
Modified: five.pt/trunk/src/five/pt/pagetemplate.py
===================================================================
--- five.pt/trunk/src/five/pt/pagetemplate.py 2008-11-16 00:27:21 UTC (rev 92995)
+++ five.pt/trunk/src/five/pt/pagetemplate.py 2008-11-16 01:18:27 UTC (rev 92996)
@@ -5,22 +5,72 @@
from Acquisition import aq_get
from Acquisition import aq_inner
+from Acquisition import aq_parent
from Products.PageTemplates.Expressions import SecureModuleImporter
from z3c.pt import pagetemplate
+def get_physical_root(context):
+ method = aq_get(context, 'getPhysicalRoot', None)
+ if method is not None:
+ return method()
+
+class FiveTemplateFile(pagetemplate.PageTemplateFile.template_class):
+ utility_builtins = {}
+
+ def prepare_builtins(self, kwargs):
+ for key, value in self.utility_builtins.items():
+ kwargs.setdefault(key, value)
+
+ def render_macro(self, macro, global_scope=False, parameters=None):
+ if parameters is None:
+ parameters = {}
+ self.prepare_builtins(parameters)
+ return super(FiveTemplateFile, self).render_macro(
+ macro, global_scope=global_scope, parameters=parameters)
+
+class PageTemplateFile(pagetemplate.PageTemplateFile):
+ template_class = FiveTemplateFile
+
+ def bind(self, parent, macro=None, global_scope=True):
+ context = aq_parent(parent)
+ request = aq_get(parent, 'REQUEST')
+ root = get_physical_root(context)
+
+ template = self.template
+
+ def render(**kwargs):
+ parameters = dict(
+ context=context,
+ request=request,
+ template=parent,
+ here=context,
+ container=context,
+ nothing=None,
+ root=root,
+ modules=SecureModuleImporter,
+ options=kwargs)
+
+ template.prepare_builtins(parameters)
+
+ if macro is None:
+ return template.render(**parameters)
+ else:
+ return template.render_macro(
+ macro, global_scope=global_scope, parameters=parameters)
+
+ return render
+
+ def __call__(self, parent, **kwargs):
+ template = self.bind(parent)
+ return template(**kwargs)
+
class ViewPageTemplate(pagetemplate.ViewPageTemplate):
def bind(self, view, request=None, macro=None, global_scope=True):
context = aq_inner(view.context)
request = view.request
-
- # locate physical root
- method = aq_get(context, 'getPhysicalRoot', None)
- if method is not None:
- root = method()
- else:
- root = None
+ root = get_physical_root(context)
def render(**kwargs):
parameters = dict(
@@ -47,3 +97,8 @@
class ViewPageTemplateFile(ViewPageTemplate, pagetemplate.ViewPageTemplateFile):
"""If ``filename`` is a relative path, the module path of the
class where the instance is used to get an absolute path."""
+
+ def getId(self):
+ return os.path.basename(self.filename)
+
+ id = property(getId)
More information about the Checkins
mailing list