[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/OFS/Services - adapter.py:1.2 field.py:1.2 interfaces.py:1.2 view.py:1.2 zpt.py:1.2 ConfigurationInterfaces.py:1.9 configure.zcml:1.18

Jim Fulton jim@zope.com
Thu, 19 Dec 2002 15:38:54 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Services
In directory cvs.zope.org:/tmp/cvs-serv26340/lib/python/Zope/App/OFS/Services

Modified Files:
	ConfigurationInterfaces.py configure.zcml 
Added Files:
	adapter.py field.py interfaces.py view.py zpt.py 
Log Message:
Merged changes made by Albertas and Jim from the AdapterAndView-branch
branch:

- Added TTW adapter service

  Todo: 

    o Named adapters

    o Getting classes in persistent modules working so we can actually
      create TTW adapters.

- Added TTW view service

  o View service

  o View configurations
 
    For configuting views from view factories

  o Page configurations 

    For configuring views based on templates (and optional classes)

  o View (sub)packages.  These get added to packages. You configure
    them with default configuration info and then add page templates
    to them. Added page temlates are automatically added as views with
    the same name.




=== Zope3/lib/python/Zope/App/OFS/Services/adapter.py 1.1 => 1.2 ===
--- /dev/null	Thu Dec 19 15:38:53 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/adapter.py	Thu Dec 19 15:38:21 2002
@@ -0,0 +1,162 @@
+##############################################################################
+#
+# 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.
+# 
+##############################################################################
+"""Adapter Service
+
+
+$Id$
+"""
+__metaclass__ = type
+
+from Interface.Registry.AdapterRegistry import AdapterRegistry
+from Persistence import Persistent
+from Persistence.PersistentDict import PersistentDict
+from Zope.ComponentArchitecture.IAdapterService import IAdapterService
+from Zope.ComponentArchitecture.Exceptions import ComponentLookupError
+from Zope.ComponentArchitecture import getServiceManager
+from Zope.App.OFS.Services.ConfigurationInterfaces import IConfigurable
+from Zope.App.OFS.Services.Configuration import ConfigurationRegistry
+from Zope.App.OFS.Services.Configuration import SimpleConfiguration
+from Zope.Proxy.ContextWrapper import ContextWrapper
+from Zope.ContextWrapper import ContextMethod
+from Zope.App.OFS.Services.Configuration import ConfigurationStatusProperty
+from Zope.App.ComponentArchitecture.NextService import getNextService
+
+from interfaces import IAdapterConfiguration
+
+class PersistentAdapterRegistry(Persistent, AdapterRegistry):
+    
+    def __init__(self):
+        AdapterRegistry.__init__(self, PersistentDict())
+
+
+class AdapterService(Persistent):
+
+    __implements__ = IAdapterService, IConfigurable
+
+    def __init__(self):
+        self._byName = PersistentDict()
+
+    def queryConfigurationsFor(self, configuration, default=None):
+        "See Zope.App.OFS.Services.ConfigurationInterfaces.IConfigurable"
+        # XXX Need to add named adapter support
+        return self.queryConfigurations(
+            configuration.forInterface, configuration.providedInterface, '',
+            default)
+
+    queryConfigurationsFor = ContextMethod(queryConfigurationsFor)
+
+    def queryConfigurations(self,
+                            forInterface, providedInterface, name,
+                            default=None):
+
+        adapters = self._byName.get(name)
+        if adapters is None:
+            return default
+        
+        registry = adapters.getRegistered(forInterface, providedInterface)
+        if registry is None:
+            return default
+
+        return ContextWrapper(registry, self)
+
+    queryConfigurations = ContextMethod(queryConfigurations)
+    
+    def createConfigurationsFor(self, configuration):
+        "See Zope.App.OFS.Services.ConfigurationInterfaces.IConfigurable"
+        # XXX Need to add named adapter support
+        return self.createConfigurations(
+            configuration.forInterface, configuration.providedInterface, '')
+
+    createConfigurationsFor = ContextMethod(createConfigurationsFor)
+
+    def createConfigurations(self, forInterface, providedInterface, name):
+
+        adapters = self._byName.get(name)
+        if adapters is None:
+            adapters = PersistentAdapterRegistry()
+            self._byName[name] = adapters
+
+        registry = adapters.getRegistered(forInterface, providedInterface)
+        if registry is None:
+            registry = ConfigurationRegistry()
+            adapters.register(forInterface, providedInterface, registry)
+
+        return ContextWrapper(registry, self)
+
+    createConfigurations = ContextMethod(createConfigurations)
+
+    def getAdapter(self, object, interface, name=''):
+        "See Zope.ComponentArchitecture.IAdapterService.IAdapterService"
+        adapter = self.queryAdapter(object, interface, None, name)
+        if adapter is None:
+            raise ComponentLookupError(object, interface)
+        return adapter
+
+    getAdapter = ContextMethod(getAdapter)
+
+    def queryAdapter(self, object, interface, default=None, name=''):
+        "See Zope.ComponentArchitecture.IAdapterService.IAdapterService"
+        if not name and interface.isImplementedBy(object):
+            return object
+
+        adapters = self._byName.get(name)
+        if adapters:
+            
+            registry = adapters.getForObject(
+                object, interface,
+                filter = lambda registry:
+                         ContextWrapper(registry, self).active(),
+                )
+
+            if registry is not None:
+                registry = ContextWrapper(registry, self)
+                adapter = registry.active().getAdapter(object)
+                return adapter
+
+        adapters = getNextService(self, 'Adapters')
+
+        return adapters.queryAdapter(object, interface, default)
+
+    queryAdapter = ContextMethod(queryAdapter)
+
+    # XXX need to add name support
+    def getRegisteredMatching(self,
+                              for_interfaces=None,
+                              provided_interfaces=None):
+
+        adapters = self._byName.get('')
+        if adapters is None:
+            return ()
+        
+        return adapters.getRegisteredMatching(for_interfaces,
+                                              provided_interfaces)
+
+class AdapterConfiguration(SimpleConfiguration):
+
+    __implements__ = IAdapterConfiguration
+
+    status = ConfigurationStatusProperty('Adapters')
+
+    def __init__(self, forInterface, providedInterface, factoryName):
+        self.forInterface = forInterface
+        self.providedInterface = providedInterface
+        self.factoryName = factoryName
+
+    def getAdapter(self, object):
+        sm = getServiceManager(self)
+        factory = sm.resolve(self.factoryName)        
+        return factory(object)
+
+    getAdapter = ContextMethod(getAdapter)
+    


=== Zope3/lib/python/Zope/App/OFS/Services/field.py 1.1 => 1.2 ===
--- /dev/null	Thu Dec 19 15:38:53 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/field.py	Thu Dec 19 15:38:21 2002
@@ -0,0 +1,59 @@
+##############################################################################
+#
+# 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.
+# 
+##############################################################################
+"""Component location field.
+
+$Id$
+"""
+__metaclass__ = type
+
+from Zope.Schema.IField import IField
+from Zope.Schema import Field
+from Zope.Schema.Exceptions import ValidationError
+from Zope.App.Traversing import traverse
+from Zope.App.ComponentArchitecture.InterfaceField import InterfaceField
+from Zope.Exceptions import NotFoundError
+
+class IComponentLocation(IField):
+    """A field containing a component path.
+    """
+
+    type = InterfaceField(
+        title = u"An interface that must be implemented by the component.",
+        required = True,
+        readonly = True,
+        )
+
+class ComponentLocation(Field):
+
+    __implements__ = IComponentLocation
+
+    _type = unicode
+
+    def __init__(self, type, *args, **kw):
+        self.type = type
+        super(ComponentLocation, self).__init__(*args, **kw)
+
+    def _validate(self, value):
+        super(ComponentLocation, self)._validate(value)
+        
+        if not value.startswith('/'):
+            raise ValidationError("Not an absolute path", value)
+        
+        try:
+            component = traverse(self.context, value)
+        except NotFoundError:
+            raise ValidationError("Path for non-existent object", value)
+        
+        if not self.type.isImplementedBy(component):
+            raise ValidationError("Wrong component type")


=== Zope3/lib/python/Zope/App/OFS/Services/interfaces.py 1.1 => 1.2 ===
--- /dev/null	Thu Dec 19 15:38:53 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/interfaces.py	Thu Dec 19 15:38:21 2002
@@ -0,0 +1,155 @@
+##############################################################################
+#
+# 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.
+# 
+##############################################################################
+"""Service interfaces
+
+$Id$
+"""
+
+from ConfigurationInterfaces import IConfiguration
+from Zope.App.ComponentArchitecture.InterfaceField import InterfaceField
+from Zope.Schema import BytesLine, TextLine, Text
+from Interface import Interface
+from Zope.App.OFS.Services.field import ComponentLocation
+from Zope.ComponentArchitecture.IPresentation import IPresentation
+
+class IAdapterConfigurationInfo(Interface):
+
+    forInterface = InterfaceField(
+        title = u"For interface",
+        description = u"The interface of the objects being adapted",
+        readonly = True,
+        required = True,
+        )
+
+    providedInterface = InterfaceField(
+        title = u"Provided interface",
+        description = u"The interface provided by the adapter",
+        readonly = True,
+        required = True,
+        )
+
+    factoryName = BytesLine(
+        title=u"The dotted name of a factory for creating the adapter",
+        readonly = True,
+        required = True,
+        )
+
+class IAdapterConfiguration(IConfiguration, IAdapterConfigurationInfo):
+
+    def getAdapter(object):
+        """Return an adapter for the object
+
+        The adapter is computed by passing the object to the
+        registered factory.
+        """
+
+class IViewConfigurationInfo(Interface):
+
+    forInterface = InterfaceField(
+        title = u"For interface",
+        description = u"The interface of the objects being viewed",
+        readonly = True,
+        required = True,
+        )
+
+    presentationType = InterfaceField(
+        title = u"Presentation type",
+        description = u"The presentation type of a view",
+        readonly = True,
+        required = True,
+        type = IPresentation,
+        )
+
+    factoryName = BytesLine(
+        title=u"The dotted name of a factory for creating the view",
+        readonly = True,
+        required = True,
+        min_length = 1,
+        )
+
+    viewName = TextLine(
+        title = u"View name",
+        readonly = True,
+        required = True,
+        min_length = 1,
+        )
+
+    layer = BytesLine(
+        title = u"Layer",
+        description = u"The skin layer the view is registered for",
+        required = False,
+        readonly = True,
+        min_length = 1,
+        default = "default",
+        )
+
+class IViewConfiguration(IConfiguration, IViewConfigurationInfo):
+
+    def getView(object, request):
+        """Return an adapter for the object
+
+        The adapter is computed by passing the object to the
+        registered factory.
+        """
+
+
+class IZPTTemplate(Interface):
+    """ZPT Templates for use in views
+    """
+
+    contentType = BytesLine(
+        title=u'Content type of generated output',
+        required=True,
+        default='text/html'
+        )
+
+    source = Text(
+        title=u"Source",
+        description=u"""The source of the page template.""",
+        required=True)
+
+    def render(context, request, *args, **kw):
+        """Render the page template.
+
+        The context argument is bound to the top-level 'context'
+        variable.  The request argument is bound to the top-level
+        'request' variable. The positional arguments are bound to the
+        'args' variable and the keyword arguments are bound to the
+        'options' variable.
+
+        """
+    
+class IPageConfigurationInfo(IViewConfigurationInfo):
+
+    factoryName = BytesLine(
+        title=u"The dotted name of a factory for creating the view",
+        readonly = True,
+        required = False,
+        min_length = 1,
+        )
+
+    template = ComponentLocation(
+        title = u"Page template",
+        required = False,
+        readonly = True,
+        type = IZPTTemplate,
+        )
+
+class IPageConfiguration(IConfiguration, IPageConfigurationInfo):
+
+    def getView(object, request):
+        """Return a page for the object.
+        """
+
+    


=== Zope3/lib/python/Zope/App/OFS/Services/view.py 1.1 => 1.2 ===
--- /dev/null	Thu Dec 19 15:38:53 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/view.py	Thu Dec 19 15:38:21 2002
@@ -0,0 +1,283 @@
+##############################################################################
+#
+# 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.
+# 
+##############################################################################
+"""View Service
+
+
+$Id$
+"""
+__metaclass__ = type
+
+from Interface.Registry.AdapterRegistry import AdapterRegistry
+from Persistence import Persistent
+from Persistence.PersistentDict import PersistentDict
+from Zope.ComponentArchitecture.IViewService import IViewService
+from Zope.ComponentArchitecture.Exceptions import ComponentLookupError
+from Zope.ComponentArchitecture import getServiceManager
+from Zope.App.OFS.Services.ConfigurationInterfaces import IConfigurable
+from Zope.App.OFS.Services.Configuration import ConfigurationRegistry
+from Zope.App.OFS.Services.Configuration import SimpleConfiguration
+from Zope.Proxy.ContextWrapper import ContextWrapper
+from Zope.ContextWrapper import ContextMethod
+from Zope.App.OFS.Services.Configuration import ConfigurationStatusProperty
+from Zope.App.ComponentArchitecture.NextService import getNextService
+from Zope.ComponentArchitecture import getSkin
+
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from Zope.App.Traversing import getPhysicalRoot, traverse
+from Zope.Exceptions import NotFoundError
+
+from interfaces import IViewConfiguration, IPageConfiguration
+from adapter import PersistentAdapterRegistry
+
+class ViewService(Persistent):
+
+    __implements__ = IViewService, IConfigurable
+
+    def __init__(self):
+        self._layers = PersistentDict()
+
+    def queryConfigurationsFor(self, configuration, default=None):
+        "See Zope.App.OFS.Services.ConfigurationInterfaces.IConfigurable"
+        return self.queryConfigurations(
+            configuration.viewName, configuration.layer,
+            configuration.forInterface, configuration.presentationType,
+            default)
+
+    queryConfigurationsFor = ContextMethod(queryConfigurationsFor)
+
+    def queryConfigurations(self, name, layer, 
+                            forInterface, presentationType, default=None):
+
+        names = self._layers.get(layer)
+        if names is None:
+            return default
+
+        adapter_registry = names.get(name)
+        if adapter_registry is None:
+            return default
+
+        registry = adapter_registry.getRegistered(
+            forInterface, presentationType)
+
+        if registry is None:
+            return default
+
+        return ContextWrapper(registry, self)
+
+    queryConfigurations = ContextMethod(queryConfigurations)
+    
+    def createConfigurationsFor(self, configuration):
+        "See Zope.App.OFS.Services.ConfigurationInterfaces.IConfigurable"
+        return self.createConfigurations(
+            configuration.viewName, configuration.layer,            
+            configuration.forInterface, configuration.presentationType)
+
+    createConfigurationsFor = ContextMethod(createConfigurationsFor)
+
+    def createConfigurations(self,
+                             viewName, layer, forInterface, presentationType):
+
+        names = self._layers.get(layer)
+        if names is None:
+            names = PersistentDict()
+            self._layers[layer] = names
+
+        adapter_registry = names.get(viewName)
+        if adapter_registry is None:
+            adapter_registry = PersistentAdapterRegistry()
+            names[viewName] = adapter_registry
+
+        registry = adapter_registry.getRegistered(
+            forInterface, presentationType)
+
+        if registry is None:
+            registry = ConfigurationRegistry()
+            adapter_registry.register(forInterface, presentationType, registry)
+
+        return ContextWrapper(registry, self)
+
+    createConfigurations = ContextMethod(createConfigurations)
+
+    def getView(self, object, name, request):
+        view = self.queryView(object, name, request)
+        if view is None:
+            raise ComponentLookupError(object, name)
+        return view
+
+    getView = ContextMethod(getView)
+
+    def queryView(self, object, name, request, default=None):
+
+        type = request.getPresentationType()
+        skin = request.getPresentationSkin()
+
+        for layername in getSkin(object, skin, type):
+            layer = self._layers.get(layername)
+            if not layer:
+                continue
+
+            reg = layer.get(name, None)
+            if reg is None:
+                continue
+
+            registry = reg.getForObject(
+                object, type,
+                filter = lambda registry:
+                         ContextWrapper(registry, self).active(),
+                )
+
+            if registry is None:
+                continue
+
+            registry = ContextWrapper(registry, self)
+            view = registry.active().getView(object, request)
+            return view
+
+        views = getNextService(self, 'Views')
+
+        return views.queryView(object, name, request, default)
+
+    queryView = ContextMethod(queryView)
+
+    def getDefaultViewName(self, object, request):
+        "See Zope.ComponentArchitecture.IViewService.IViewService"
+
+        name = self.queryDefaultViewName(object, request)
+
+        if name is None:
+            raise NotFoundError, \
+                  'No default view name found for object %s' % object
+
+        return name
+
+    getDefaultViewName = ContextMethod(getDefaultViewName)
+
+    def queryDefaultViewName(self, object, request, default=None):
+        "See Zope.ComponentArchitecture.IViewService.IViewService"
+
+        # XXX: need to do our own defaults as well.
+        views = getNextService(self, 'Views')
+        return views.queryDefaultViewName(object, request, default)
+
+    queryDefaultViewName = ContextMethod(queryDefaultViewName)
+
+    def getRegisteredMatching(self,
+                              required_interfaces=None,
+                              presentation_type=None,
+                              viewName=None,
+                              layer=None,
+                              ):
+        if layer is None:
+            layers = self._layers.keys()
+        else:
+            layers = (layer, )
+
+        result = []
+        
+        for layer in layers:
+            names_dict = self._layers.get(layer)
+            if names_dict is None:
+                continue
+
+            if viewName is None:
+                viewNames = names_dict.keys()
+            else:
+                viewNames = (viewName, )
+
+            for viewName in viewNames:
+                registry = names_dict.get(viewName)
+
+                if registry is None:
+                    continue
+
+                for match in registry.getRegisteredMatching(
+                    required_interfaces,
+                    presentation_type):
+                    
+                    result.append(match + (layer, viewName))
+            
+        return result
+
+class ViewConfiguration(SimpleConfiguration):
+
+    __implements__ = IViewConfiguration
+
+    status = ConfigurationStatusProperty('Views')
+
+    def __init__(self,
+                 forInterface, viewName, presentationType,
+                 factoryName, layer='default'):
+        self.forInterface = forInterface
+        self.presentationType = presentationType
+        self.factoryName = factoryName
+        self.viewName = viewName
+        self.layer = layer
+
+    def getView(self, object, request):
+        sm = getServiceManager(self)
+        factory = sm.resolve(self.factoryName)        
+        return factory(object, request)
+
+    getView = ContextMethod(getView)
+    
+class PageConfiguration(ViewConfiguration):
+
+    __implements__ = IPageConfiguration
+    
+    def __init__(self,
+                 forInterface, viewName, presentationType,
+                 factoryName=None, template=None,
+                 layer='default'):
+        super(PageConfiguration, self).__init__(
+            forInterface, viewName, presentationType,
+            factoryName, layer)
+
+        self.template = template
+
+    def getView(self, object, request):
+        sm = getServiceManager(self)
+
+        if self.factoryName:
+            factory = sm.resolve(self.factoryName)
+        else:
+            factory = DefaultFactory
+        
+        view = factory(object, request)
+
+        # This is needed because we need to do an unrestricted traverse
+        root = removeAllProxies(getPhysicalRoot(sm))
+        
+        template = traverse(root, self.template)
+
+        return BoundTemplate(template, view)
+
+    getView = ContextMethod(getView)
+
+
+class DefaultFactory:
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+class BoundTemplate:
+
+    def __init__(self, template, view):
+        self.template = template
+        self.view = view
+
+    def __call__(self, *args, **kw):
+        return self.template.render(self.view, *args, **kw)
+
+                 


=== Zope3/lib/python/Zope/App/OFS/Services/zpt.py 1.1 => 1.2 ===
--- /dev/null	Thu Dec 19 15:38:53 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/zpt.py	Thu Dec 19 15:38:21 2002
@@ -0,0 +1,90 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+$Id$
+"""
+
+import re
+
+from Interface import Interface
+from Interface.Attribute import Attribute
+import Zope.Schema
+from Persistence import Persistent
+
+from Zope.ContextWrapper import ContextMethod
+from Zope.Proxy.ContextWrapper import getWrapperContainer
+from Zope.Security.Proxy import ProxyFactory
+
+from Zope.App.OFS.Content.IFileContent import IFileContent
+from Zope.PageTemplate.PageTemplate import PageTemplate
+from Zope.App.PageTemplate.Engine import AppPT
+from interfaces import IZPTTemplate
+
+class ZPTTemplate(AppPT, PageTemplate, Persistent):
+
+    __implements__ = IZPTTemplate
+
+    contentType = 'text/html'
+
+    source = property(
+        # get
+        lambda self: self.read(),
+        # set
+        lambda self, text: self.pt_edit(text.encode('utf-8'), self.contentType)
+        )
+
+    def pt_getContext(self, view, **_kw):
+        # instance is a View component
+        namespace = super(ZPTTemplate, self).pt_getContext(**_kw)
+        namespace['view'] = view
+        namespace['request'] = view.request
+        namespace['context'] = view.context
+        return namespace
+
+    def render(self, view, *args, **keywords):
+        
+        if args:
+            args = ProxyFactory(args)
+        kw = ProxyFactory(keywords)
+
+        namespace = self.pt_getContext(view, args=args, options=kw)
+
+        return self.pt_render(namespace)
+
+# Adapter for ISearchableText
+
+from Zope.App.index.text.interfaces import ISearchableText
+
+tag = re.compile(r"<[^>]+>")
+class SearchableText:
+
+    __implements__ = ISearchableText
+    __used_for__ = IZPTTemplate
+
+    def __init__(self, page):
+        self.page = page
+
+    def getSearchableText(self):
+        text = self.page.source
+        if isinstance(text, str):
+            text = unicode(self.page.source, 'utf-8')
+        # else:
+        #   text was already Unicode, which happens, but unclear how it
+        #   gets converted to Unicode since the ZPTPage stores UTF-8 as
+        #   an 8-bit string.
+        
+        if self.page.contentType.startswith('text/html'):
+            text = tag.sub('', text)
+
+        return [text]


=== Zope3/lib/python/Zope/App/OFS/Services/ConfigurationInterfaces.py 1.8 => 1.9 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ConfigurationInterfaces.py:1.8	Wed Dec 18 15:23:02 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ConfigurationInterfaces.py	Thu Dec 19 15:38:21 2002
@@ -181,6 +181,10 @@
         implement a method named queryConfigurations, which takes
         arguments for each of the parameters needed to specify a set
         of configurations.
+
+        The registry must be returned in the context of the context of
+        the configurable.
+        
         """
 
     def createConfigurationsFor(configuration):


=== Zope3/lib/python/Zope/App/OFS/Services/configure.zcml 1.17 => 1.18 ===
--- Zope3/lib/python/Zope/App/OFS/Services/configure.zcml:1.17	Wed Dec  4 16:46:17 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/configure.zcml	Thu Dec 19 15:38:21 2002
@@ -3,12 +3,101 @@
    xmlns:browser="http://namespaces.zope.org/browser"
    >
 
+<!-- Configuration registries -->
+
 <content class=".Configuration.ConfigurationRegistry">
    <require permission="Zope.ManageServices"
             interface=".ConfigurationInterfaces.IConfigurationRegistry"
             />
 </content>
 
+<!-- Adapter Service -->
+
+<content class=".adapter.AdapterService">
+    <implements interface="Zope.App.OFS.Annotation.IAttributeAnnotatable." />
+    <factory id="Zope.App.OFS.Services.AdapterService"
+             permission="Zope.ManageServices"
+             />
+    <require permission="Zope.ManageServices"
+             interface=".ConfigurationInterfaces.IConfigurable"
+             attributes="getRegisteredMatching"
+             />
+</content>
+
+<content class=".adapter.AdapterConfiguration">
+    <require
+        permission="Zope.ManageServices"
+        interface=".interfaces.IAdapterConfiguration"
+        set_schema=
+            "Zope.App.OFS.Services.ConfigurationInterfaces.IConfiguration"
+        />
+    <require
+        permission="Zope.ManageServices"
+        interface="Zope.App.OFS.Container.IDeleteNotifiable."
+        />
+</content>    
+
+<!-- View Service -->
+
+<content class=".view.ViewService">
+    <implements interface="Zope.App.OFS.Annotation.IAttributeAnnotatable." />
+    <factory id="Zope.App.OFS.Services.ViewService"
+             permission="Zope.ManageServices"
+             />
+    <require permission="Zope.ManageServices"
+             interface=".ConfigurationInterfaces.IConfigurable"
+             attributes="getRegisteredMatching"
+             />
+</content>
+
+<content class=".view.ViewConfiguration">
+    <require
+        permission="Zope.ManageServices"
+        interface=".interfaces.IViewConfiguration"
+        set_schema=
+            "Zope.App.OFS.Services.ConfigurationInterfaces.IConfiguration"
+        />
+    <require
+        permission="Zope.ManageServices"
+        interface="Zope.App.OFS.Container.IDeleteNotifiable."
+        />
+</content>    
+
+<content class=".view.PageConfiguration">
+    <require
+        permission="Zope.ManageServices"
+        interface=".interfaces.IPageConfiguration"
+        set_schema=
+            "Zope.App.OFS.Services.ConfigurationInterfaces.IConfiguration"
+        />
+    <require
+        permission="Zope.ManageServices"
+        interface="Zope.App.OFS.Container.IDeleteNotifiable."
+        />
+</content>    
+
+<!-- Page Templates -->
+
+<content class=".zpt.ZPTTemplate">
+  <factory
+      id="Zope.app.services.zpt.template"
+      permission="Zope.ManageServices"
+      title="ZPT Template"
+      description="Page Template" />
+
+  <require
+      permission="Zope.View"
+      attributes="__call__" />
+
+  <require
+      permission="Zope.ManageServices"
+      interface=".interfaces.IZPTTemplate"
+      set_schema=".interfaces.IZPTTemplate" />
+
+  <implements
+      interface="Zope.App.OFS.Annotation.IAttributeAnnotatable." />
+</content>
+
 <include package=".ServiceManager" />
 <include package=".AuthenticationService" />
 <include package=".LocalEventService" />
@@ -18,8 +107,9 @@
 <include package=".CachingService" />
 <include package=".ObjectHub" />
 <include package=".ErrorReportingService" />
-<include package=".Browser" />
 <include package=".PrincipalAnnotationService" />
 <include package=".SessionService" />
+
+<include package=".Browser" />
 
 </zopeConfigure>