[z3-checkins] r9209 - z3/Five/trunk
faassen at codespeak.net
faassen at codespeak.net
Mon Feb 14 16:18:37 MET 2005
Author: faassen
Date: Mon Feb 14 16:18:37 2005
New Revision: 9209
Added:
z3/Five/trunk/ReuseUtils.py
z3/Five/trunk/TrustedExpression.py
z3/Five/trunk/pagetemplatefile.py
Modified:
z3/Five/trunk/CHANGES.txt
z3/Five/trunk/COPYING.txt
z3/Five/trunk/CREDITS.txt
z3/Five/trunk/browserconfigure.py
Log:
* Use Zope 2 page templates, along the lines of Lennart's code.
* Integrate pieces of TrustedExecutables into Five, so no more dependency
on TrustedExecutables exists.
Modified: z3/Five/trunk/CHANGES.txt
==============================================================================
--- z3/Five/trunk/CHANGES.txt (original)
+++ z3/Five/trunk/CHANGES.txt Mon Feb 14 16:18:37 2005
@@ -4,10 +4,20 @@
Trunk
-----
-* Five now supports the browser:menu, menuItem and menuItems directives.
+* Five now uses the Zope 2 page template engine, not the Zope 3
+ engine. This allows better integration with Zope 2-based page
+ templates, such as macros.
+
+ It uses TrustedExecutables technology (thanks to Dieter Maurer) to
+ turn off Zope 2 security in page templates, so Five's security
+ behavior is very similar to what it was before.
+
+* Five now supports the browser:menu, menuItem and menuItems
+ directives.
- Also supports the menu parameter for page directives and subdirectives,
- as well as editform directives. [XXX this doesn't seem to work yet]
+ Also supports the menu parameter for page directives and
+ subdirectives, as well as editform directives. [XXX this doesn't
+ seem to work yet]
* A new Five-specific directive has been added:
five:pagesFromDirectory. This adds one page for each .pt file in a
Modified: z3/Five/trunk/COPYING.txt
==============================================================================
--- z3/Five/trunk/COPYING.txt (original)
+++ z3/Five/trunk/COPYING.txt Mon Feb 14 16:18:37 2005
@@ -22,3 +22,6 @@
- metaclass.py is derived from PEAK, copyright (C) 1996-2004 by
Phillip J. Eby and Tyler C. Sarna. PEAK may be used under the same
terms as Zope.
+
+- TrustedExecutables. Dieter Mauer kindly allow licensing this under the
+ ZPL 2.1.
\ No newline at end of file
Modified: z3/Five/trunk/CREDITS.txt
==============================================================================
--- z3/Five/trunk/CREDITS.txt (original)
+++ z3/Five/trunk/CREDITS.txt Mon Feb 14 16:18:37 2005
@@ -17,11 +17,21 @@
- Simon Eisenmann (simon at struktur.de)
+- Dieter Maurer (dieter at handshake.de)
+
Thank you
---------
+Infrae for the initial development and continuing support.
+
Martijn Faassen would like to thank ETH Zurich for their support and
-encouragement during the initial development of Five.
+encouragement during the initial development of Five.
+
+Nuxeo for significant contributions to making Five usable in the real
+world.
+
+Dieter Maurer for use of code from TrustedExecutables within Five
+under the ZPL.
The Five developers would like to thank the Zope 3 developers, in
particular Jim Fulton, for the mountain to stand on.
Added: z3/Five/trunk/ReuseUtils.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/ReuseUtils.py Mon Feb 14 16:18:37 2005
@@ -0,0 +1,17 @@
+# Copyright (C) 2004 by Dr. Dieter Maurer, Eichendorffstr. 23, D-66386 St. Ingbert, Germany
+
+from new import function
+
+def rebindFunction(f,rebindDir=None,**rebinds):
+ '''return *f* with some globals rebound.'''
+ d= {}
+ if rebindDir : d.update(rebindDir)
+ if rebinds: d.update(rebinds)
+ if not d: return f
+ f= getattr(f,'im_func',f)
+ fd= f.func_globals.copy()
+ fd.update(d)
+ nf= function(f.func_code,fd,f.func_name,f.func_defaults or ())
+ nf.__doc__= f.__doc__
+ if f.__dict__ is not None: nf.__dict__= f.__dict__.copy()
+ return nf
Added: z3/Five/trunk/TrustedExpression.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/TrustedExpression.py Mon Feb 14 16:18:37 2005
@@ -0,0 +1,97 @@
+# Copyright (C) 2004 by Dr. Dieter Maurer, Eichendorffstr. 23, D-66386 St. Ingbert, Germany
+
+from sys import modules
+
+from Products.PageTemplates.PythonExpr import PythonExpr
+
+from Products.PageTemplates.Expressions import \
+ SubPathExpr, PathExpr, \
+ StringExpr, \
+ getEngine, installHandlers
+
+from ReuseUtils import rebindFunction
+
+
+class _ModuleImporter:
+ def __getitem__(self, module):
+ __import__(module)
+ return modules[module]
+ModuleImporter = _ModuleImporter()
+
+
+def trustedTraverse(ob, path, ignored,):
+ if not path: return self
+
+ get = getattr
+ has = hasattr
+ N = None
+ M = rebindFunction # artifical marker
+
+ if isinstance(path, str): path = path.split('/')
+ else: path=list(path)
+
+ REQUEST={'TraversalRequestNameStack': path}
+ path.reverse()
+ pop=path.pop
+
+ if len(path) > 1 and not path[0]:
+ # Remove trailing slash
+ path.pop(0)
+
+ if not path[-1]:
+ # If the path starts with an empty string, go to the root first.
+ pop()
+ self=ob.getPhysicalRoot()
+
+ object = ob
+ while path:
+ name=pop()
+ __traceback_info__ = path, name
+
+ if name == '..':
+ o=getattr(object, 'aq_parent', M)
+ if o is not M:
+ object=o
+ continue
+
+ t=get(object, '__bobo_traverse__', M)
+ if t is not M: o=t(REQUEST, name)
+ else:
+ o = get(object, name, M)
+ if o is M:
+ try: o = object[name]
+ except AttributeError: # better exception
+ raise AttributeError(name)
+ object = o
+
+ return object
+
+
+class SubPathExpr(SubPathExpr):
+ _eval = rebindFunction(SubPathExpr._eval.im_func,
+ restrictedTraverse=trustedTraverse,
+ )
+
+class PathExpr(PathExpr):
+ __init__ = rebindFunction(PathExpr.__init__.im_func,
+ SubPathExpr=SubPathExpr,
+ )
+
+class StringExpr(StringExpr):
+ __init__ = rebindFunction(StringExpr.__init__.im_func,
+ PathExpr=PathExpr,
+ )
+
+installHandlers = rebindFunction(installHandlers,
+ PathExpr=PathExpr,
+ StringExpr=StringExpr,
+ PythonExpr=PythonExpr,
+ )
+
+_engine=None
+getEngine = rebindFunction(getEngine,
+ _engine=_engine,
+ installHandlers=installHandlers
+ )
+
+
Modified: z3/Five/trunk/browserconfigure.py
==============================================================================
--- z3/Five/trunk/browserconfigure.py (original)
+++ z3/Five/trunk/browserconfigure.py Mon Feb 14 16:18:37 2005
@@ -20,10 +20,9 @@
from zope.configuration.exceptions import ConfigurationError
from zope.component.servicenames import Presentation
from zope.publisher.interfaces.browser import IBrowserRequest
-from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
-from zope.app.pagetemplate.viewpagetemplatefile import ViewMapper
from zope.app.publisher.browser.viewmeta import pages as zope_app_pages
-from zope.app.publisher.browser.globalbrowsermenuservice import menuItemDirective
+from zope.app.publisher.browser.globalbrowsermenuservice import\
+ menuItemDirective
from zope.app.component.metaconfigure import handler
from zope.app.component.interface import provideInterface
from zope.app.form.browser.metaconfigure import BaseFormDirective
@@ -33,15 +32,9 @@
from resource import DirectoryResourceFactory
from browser import BrowserView, EditView
from metaclass import makeClass
-from security import getSecurityInfo, protectClass, protectName, initializeClass
-
-class FivePageTemplateFile(ViewPageTemplateFile):
-
- def pt_getContext(self, instance, request, **_kw):
- # instance is a View component
- namespace = super(FivePageTemplateFile, self).pt_getContext(instance, request, **_kw)
- namespace['here'] = namespace['context']
- return namespace
+from security import getSecurityInfo, protectClass, protectName,\
+ initializeClass
+from pagetemplatefile import ZopeTwoPageTemplateFile
def page(_context, name, permission, for_,
@@ -339,7 +332,7 @@
class_.fulledit_label = fulledit_label
- class_.generated_form = ViewPageTemplateFile(default_template)
+ class_.generated_form = ZopeTwoPageTemplateFile(default_template)
# Not the prettiest solution, but it works...
class_.__init__ = EditView.__init__
@@ -409,7 +402,7 @@
# XXX needs to deal with security from the bases?
if cdict is None:
cdict = {}
- cdict.update({'index': FivePageTemplateFile(src, template)})
+ cdict.update({'index': ZopeTwoPageTemplateFile(src, template)})
bases += (ViewMixinForTemplates,)
class_ = makeClass("SimpleViewClass from %s" % src, bases, cdict)
Added: z3/Five/trunk/pagetemplatefile.py
==============================================================================
--- (empty file)
+++ z3/Five/trunk/pagetemplatefile.py Mon Feb 14 16:18:37 2005
@@ -0,0 +1,95 @@
+'''A 'PageTemplateFile' without security restrictions.'''
+
+import os, sys
+
+# Zope 2
+from Globals import package_home
+from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+
+# Zope 3
+from zope.app.pagetemplate.viewpagetemplatefile import ViewMapper
+from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+
+# Five
+from ReuseUtils import rebindFunction
+from TrustedExpression import getEngine, ModuleImporter
+
+class ZopeTwoPageTemplateFile(PageTemplateFile):
+ """A strange hybrid between Zope 2 and Zope 3 page template.
+
+ Uses Zope 2's engine, but with security disabled and with some
+ initialization and API from Zope 3.
+ """
+
+ def __init__(self, filename, _prefix=None, content_type=None):
+ # XXX doesn't use content_type yet
+
+ self.ZBindings_edit(self._default_bindings)
+
+ path = self.get_path_from_prefix(_prefix)
+ self.filename = os.path.join(path, filename)
+ if not os.path.isfile(self.filename):
+ raise ValueError("No such file", self.filename)
+
+ basepath, ext = os.path.splitext(self.filename)
+ self.__name__ = os.path.basename(basepath)
+
+ def get_path_from_prefix(self, _prefix):
+ if isinstance(_prefix, str):
+ path = _prefix
+ else:
+ if _prefix is None:
+ _prefix = sys._getframe(2).f_globals
+ path = package_home(_prefix)
+ return path
+
+ _cook = rebindFunction(PageTemplateFile._cook,
+ getEngine=getEngine)
+
+ pt_render = rebindFunction(PageTemplateFile.pt_render,
+ getEngine=getEngine)
+
+ def _pt_getContext(self):
+ view = self._getContext()
+ try:
+ root = self.getPhysicalRoot()
+ here = view.context
+ except AttributeError:
+ # self has no attribute getPhysicalRoot.
+ # This typically happens when the template has
+ # no proper acquisition context. That means it has no view,
+ # since that's the normal context for a template in Five. /regebro
+ root = self.context.getPhysicalRoot()
+ here = self.context
+ view = None
+
+ request = getattr(root, 'REQUEST', None)
+ c = {'template': self,
+ 'here': here,
+ 'context': here,
+ 'container': self._getContainer(),
+ 'nothing': None,
+ 'options': {},
+ 'root': root,
+ 'request': request,
+ 'modules': ModuleImporter,
+ }
+ if view:
+ c['view'] = view
+ c['views'] = ViewMapper(here, request)
+
+ return c
+
+ pt_getContext = rebindFunction(_pt_getContext,
+ SecureModuleImporter=ModuleImporter)
+
+# this is not in use right now, but would be how to integrate Zope 3 page
+# templates instead of Zope 2 page templates
+class FivePageTemplateFile(ViewPageTemplateFile):
+
+ def pt_getContext(self, instance, request, **_kw):
+ # instance is a View component
+ namespace = super(FivePageTemplateFile, self).pt_getContext(
+ instance, request, **_kw)
+ namespace['here'] = namespace['context']
+ return namespace
More information about the z3-checkins
mailing list