[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/PageTemplate - Engine.py:1.1.2.1 SimpleViewClass.py:1.1.2.1 ViewPageTemplateFile.py:1.1.2.1 __init__.py:1.1.2.1

Jim Fulton jim@zope.com
Thu, 23 May 2002 14:01:15 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/PageTemplate
In directory cvs.zope.org:/tmp/cvs-serv26429/lib/python/Zope/App/PageTemplate

Added Files:
      Tag: Zope-3x-branch
	Engine.py SimpleViewClass.py ViewPageTemplateFile.py 
	__init__.py 
Log Message:
This all started with wanting to be able to use url;view in a ZPT path. :)

That lead me to:

- Massive traversal refactoring.

  Namespace handling is now centralized in Zope.App.Traversing. 

- ZPT refactoring, including some renaming that touches pretty much everything. :)

  - The application specific ZPT support was moved into
    Zope.App.PageTemplate. 

  - To get page template files (for use in views):

    from Zope.App.PageTemplate import ViewPageTemplateFile

  - Fixed up security so that ZPT expressions only have access to 
    safe builtins and so that modules namespace does imports safely.

  - Got ZPTPage working!

- renaming url to absolute_url and got absolute_url to work in paths.

- Cleaned up the (as yet unused) RestrictedInterpreter module in
  Zope.Security. In particular, changed to use a separate
  RestrictedBuiltins module.



=== Added File Zope3/lib/python/Zope/App/PageTemplate/Engine.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""Expression engine configuration and registration.

Each expression engine can have its own expression types and base names.

$Id: Engine.py,v 1.1.2.1 2002/05/23 18:01:14 jim Exp $
"""
__metaclass__ = type # All classes are new style when run with Python 2.2+

from Zope.PageTemplate.TALES import ExpressionEngine, RegistrationError
from Zope.PageTemplate.Expressions \
     import PathExpr, StringExpr, NotExpr, DeferExpr
from Zope.PageTemplate.PythonExpr import PythonExpr
from Zope.Security.Proxy import ProxyFactory
from Zope.ComponentArchitecture import getAdapter
from Zope.App.Traversing.ITraverser import ITraverser
from Zope.Security.RestrictedBuiltins import RestrictedBuiltins
import sys

def zopeTraverser(object, path_items, econtext):
    """Traverses a sequence of names, first trying attributes then items.
    """
    traverser = getAdapter(object, ITraverser)
    return traverser.traverse(path_items,
                              request=getattr(econtext, 'request', None))


class ZopePathExpr(PathExpr):

    def __init__(self, name, expr, engine):
        super(ZopePathExpr, self).__init__(name, expr, engine, zopeTraverser)

class ZopePythonExpr(PythonExpr):

    def __call__(self, econtext):
        __traceback_info__ = self.text
        vars = self._bind_used_names(econtext, RestrictedBuiltins)
        return eval(self._code, vars)

class ZopeEngine(ExpressionEngine):

    def getContext(self, __namespace=None, **namespace):
        if __namespace:
            if namespace:
                namespace.update(__namespace)
            else:
                namespace = __namespace
                
        context = super(ZopeEngine, self).getContext(namespace)

        # Put request into context so path traversal can find it
        if 'request' in namespace:
            context.request = namespace['request']

        return context

def Engine():
    e = ZopeEngine()
    reg = e.registerType
    for pt in ZopePathExpr._default_type_names:
        reg(pt, ZopePathExpr)
    reg('string', StringExpr)
    reg('python', ZopePythonExpr)
    reg('not', NotExpr)
    reg('defer', DeferExpr)
    e.registerBaseName('modules', ProxyFactory(sys.modules))
    return e

Engine = Engine()

class AppPT:
    
    # Use our special engine
    pt_getEngineContext = Engine.getContext
    
    def pt_getEngine(self):
        return Engine



=== Added File Zope3/lib/python/Zope/App/PageTemplate/SimpleViewClass.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""

$Id: SimpleViewClass.py,v 1.1.2.1 2002/05/23 18:01:14 jim Exp $
"""

import sys
from Zope.Publisher.Browser.IBrowserPublisher import IBrowserPublisher
from ViewPageTemplateFile import ViewPageTemplateFile
from Zope.Security.Checker import defineChecker, NamesChecker

class simple(object):

    __implements__=IBrowserPublisher
    
    # Boiler plate
    def __init__(self, context):
        self._context=context

    def getContext(self):
        return self._context

    def browserDefault(self, request):
        return self, ('index.html',)

    def publishTraverse(self, request, name):
        if name == 'index.html':
            return self.index
        
        raise NotFound(self, name, request)


    # XXX: we need some unittests for this !!!
    def __getitem__(self, name):
        return self.index.macros[name]

    def __call__(self, REQUEST, *args, **kw):
        return self.index(REQUEST, *args, **kw)

def SimpleViewClass(src, offering=None, used_for=None):
    if offering is None:
        offering = sys._getframe(1).f_globals

    class_ = type(src, (simple,),
                  {'index': ViewPageTemplateFile(src, offering)})

    if used_for is not None:
        class_.__used_for__ = used_for

    defineChecker(class_, NamesChecker('index'))

    return class_


=== Added File Zope3/lib/python/Zope/App/PageTemplate/ViewPageTemplateFile.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""
See ViewPageTemplateFile

$Id%
"""
__metaclass__ = type # All classes are new style when run with Python 2.2+

from Zope.PageTemplate.PageTemplateFile import PageTemplateFile
from Zope.ComponentArchitecture import getRequestView
from Engine import AppPT

class ViewPageTemplateFile(AppPT, PageTemplateFile):
    """Page Templates used as methods of views defined as Python classes.
    """

    def pt_getContext(self, instance, request, **_kw):
        # instance is a View component
        namespace = super(ViewPageTemplateFile, self).pt_getContext(**_kw)
        namespace['request'] = request
        namespace['view'] = instance
        namespace['context'] = context = instance.getContext()
        namespace['views'] = ViewMapper(context, request)
        return namespace

    def __call__(self, instance, REQUEST, *args, **keywords):
        namespace = self.pt_getContext(request=REQUEST, instance=instance,
                                       args=args, options=keywords)
        return self.pt_render(namespace)

    def __get__(self, instance, type=None):
        return BoundPageTemplate(self, instance)


class ViewMapper:
    def __init__(self, ob, request):
        self.ob = ob
        self.request = request 

    def __getitem__(self, name):
        return getRequestView(self.ob, name, self.request)


class BoundPageTemplate:
    def __init__(self, pt, ob):
        object.__setattr__(self, 'im_func', pt)
        object.__setattr__(self, 'im_self', ob)

    def __call__(self, REQUEST=None, **kw):
        return self.im_func(self.im_self, REQUEST, **kw)

    def __getattr__(self, name):
        return getattr(self.im_func, name)

    def __setattr__(self, name, v):
        raise AttributeError("Can't set attribute", name)

    def __repr__(self):
        return "<BoundPageTemplateFile of %r>" % self.im_self


=== Added File Zope3/lib/python/Zope/App/PageTemplate/__init__.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
# 
##############################################################################
"""

Revision information:
$Id: __init__.py,v 1.1.2.1 2002/05/23 18:01:14 jim Exp $
"""

from ViewPageTemplateFile import ViewPageTemplateFile
from SimpleViewClass import SimpleViewClass