[Zope3-checkins] CVS: Zope3/src/zope/app/site - __init__.py:1.1 configure.zcml:1.1 folder.py:1.1 interfaces.py:1.1 service.py:1.1 servicecontainer.py:1.1

Stephan Richter srichter at cosmos.phy.tufts.edu
Sat Mar 13 10:21:55 EST 2004


Update of /cvs-repository/Zope3/src/zope/app/site
In directory cvs.zope.org:/tmp/cvs-serv17238/src/zope/app/site

Added Files:
	__init__.py configure.zcml folder.py interfaces.py service.py 
	servicecontainer.py 
Log Message:


Move Local Service Manager and site code to zope.app.site.


=== Added File Zope3/src/zope/app/site/__init__.py ===
# Import this.


=== Added File Zope3/src/zope/app/site/configure.zcml ===
<configure 
    xmlns="http://namespaces.zope.org/zope"
    xmlns:fssync="http://namespaces.zope.org/fssync"
    >

  <!-- For backward compatibility -->

  <modulealias
      module=".interfaces"
      alias="zope.app.interfaces.services.service"
      />

  <modulealias
      module=".interfaces"
      alias="zope.app.interfaces.services.folder"
      />

  <modulealias
      module=".service"
      alias="zope.app.services.service"
      />

  <modulealias
      module=".folder"
      alias="zope.app.services.folder"
      />

  <module module=".interfaces">
    <allow attributes="ISite" />
  </module>

  <!-- Service Manager -->

  <content class=".service.SiteManager">
    <require
        permission="zope.View"
        interface="zope.app.container.interfaces.IReadContainer" />
    <require
        permission="zope.ManageServices"
        interface=".interfaces.ISiteManager
                   zope.app.container.interfaces.IWriteContainer" />
    <implements
        interface="zope.app.interfaces.annotation.IAttributeAnnotatable" />
    </content>

  <content class=".service.ServiceRegistration">
    <require
        permission="zope.ManageServices"
        interface=".interfaces.IServiceRegistration"
        set_attributes="serviceType componentPath permission"
        set_schema="zope.app.interfaces.services.registration.IRegistration"
        />
    <require
        permission="zope.ManageServices"
        interface="zope.app.container.interfaces.IAddNotifiable"
        />
    <require
        permission="zope.ManageServices"
        interface="zope.app.container.interfaces.IRemoveNotifiable"
        />

  </content>

  <!-- SiteManagementFolders -->

  <content class=".folder.SiteManagementFolders">
    <require
        permission="zope.View"
        interface="zope.app.container.interfaces.IReadContainer" />
    <require
        permission="zope.ManageServices"
        interface="zope.app.container.interfaces.IWriteContainer" />
    <require
        permission="zope.ManageServices"
        interface="zope.app.site.interfaces.IComponentManager" />
    <implements
        interface="zope.app.interfaces.annotation.IAttributeAnnotatable" />

    </content>

  <content class=".folder.SiteManagementFolder">
    <factory />
    <require
        permission="zope.View"
        interface="zope.app.container.interfaces.IReadContainer" />
    <require
        permission="zope.ManageServices"
        interface="zope.app.container.interfaces.IWriteContainer"
        attributes="getRegistrationManager resolve" 
        />
    <implements
        interface="zope.app.interfaces.annotation.IAttributeAnnotatable" />

    </content>

  <fssync:adapter
      class=".folder.SiteManagementFolder"
      factory="zope.fssync.server.entryadapter.DirectoryAdapter"
      />
  
  <fssync:adapter
      class=".service.ServiceManager"
      factory=".service.ServiceManagerAdapter"
      />
  
  <fssync:adapter
      class=".service.ServiceRegistration"
      factory="zope.app.services.registration.ComponentRegistrationAdapter"
      />
  
  <adapter 
      for="zope.app.site.interfaces.ISiteManager"
      provides="zope.app.interfaces.file.IDirectoryFactory"
      factory=".folder.SMFolderFactory"
      permission="zope.ManageContent"
      />

</configure>


=== Added File Zope3/src/zope/app/site/folder.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.
#
##############################################################################
"""A site management folder contains components and component registrations.

$Id: folder.py,v 1.1 2004/03/13 15:21:47 srichter Exp $
"""
from zope.interface import implements
from zope.app.component.nextservice import getNextServiceManager
from zope.app.container.btree import BTreeContainer
from zope.app.interfaces.file import IDirectoryFactory
from zope.app.services.registration import RegistrationManagerContainer
from zope.app.traversing import getPath
from zope.app.container.contained import setitem

from interfaces import ISiteManagementFolders, ISiteManagementFolder
from interfaces import IComponentManager


class SiteManagementFolder(RegistrationManagerContainer, BTreeContainer):
    implements(ISiteManagementFolder)

class SMFolderFactory(object):

    implements(IDirectoryFactory)

    def __init__(self, context):
        self.context = context

    def __call__(self, name):
        return SiteManagementFolder()

# XXX Backward compatability. This is needed to support old pickles.
Package = SiteManagementFolder

class SiteManagementFolders(BTreeContainer):
    pass 
Packages = SiteManagementFolders

import sys

sys.modules['zope.app.services.package'
            ] = sys.modules['zope.app.site.folder']


=== Added File Zope3/src/zope/app/site/interfaces.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.
#
##############################################################################
"""Interfaces for folders.

$Id: interfaces.py,v 1.1 2004/03/13 15:21:47 srichter Exp $
"""
from zope.interface import Interface
import zope.schema
from zope.component.interfaces import IServiceService
from zope.app.container.interfaces import IContainer
from zope.app.container.constraints import ContainerTypesConstraint
from zope.app.container.constraints import ItemTypePrecondition
from zope.app.interfaces.services import registration
from zope.app.i18n import ZopeMessageIDFactory as _


class ILocalService(registration.IRegisterable):
    """A local service isn't a local service if it doesn't implement this.

    The contract of a local service includes collaboration with
    services above it.  A local service should also implement
    IRegisterable (which implies that it is adaptable to
    IRegistered).  Implementing ILocalService implies this.
    """


class ISimpleService(ILocalService, registration.IAttributeRegisterable):
    """Most local services should implement this instead of ILocalService.

    It implies a specific way of implementing IRegisterable,
    by subclassing IAttributeRegisterable.
    """

class IComponentManager(Interface):

    def queryComponent(type=None, filter=None, all=0):
        """Return all components that match the given type and filter

        The objects are returned a sequence of mapping objects with keys:

        path -- The component path

        component -- The component

        all -- A flag indicating whether all component managers in
               this place should be queried, or just the local one.

        """


class IPossibleSite(Interface):
    """An object that could be a site
    """

    def setSiteManager(sm):
        """Sets the service manager for this object.
        """

    def getSiteManager():
        """Returns the service manager contained in this object.

        If there isn't a service manager, raise a component lookup.
        """

class ISite(IPossibleSite):
    """Marker interface to indicate that we have a site
    """

class IBindingAware(Interface):

    def bound(name):
        """Inform a service component that it is providing a service

        Called when an immediately-containing service manager binds
        this object to perform the named service.
        """

    def unbound(name):
        """Inform a service component that it is no longer providing a service

        Called when an immediately-containing service manager unbinds
        this object from performing the named service.
        """


class ISiteManager(IServiceService, IComponentManager,
                   registration.IRegistry):
    """Service Managers act as containers for Services.

    If a Service Manager is asked for a service, it checks for those it
    contains before using a context based lookup to find another service
    manager to delegate to.  If no other service manager is found they defer
    to the ComponentArchitecture ServiceManager which contains file based
    services.
    """

    def queryRegistrations(name, default=None):
        """Return an IRegistrationRegistry for the registration name.

        queryRegistrationsFor(cfg, default) is equivalent to
        queryRegistrations(cfg.name, default)
        """

    def createRegistrationsFor(registration):
        """Create and return an IRegistrationRegistry for the registration
        name.

        createRegistrationsFor(cfg, default) is equivalent to
        createRegistrations(cfg.name, default)
        """

    def listRegistrationNames():
        """Return a list of all registered registration names.
        """


    def queryActiveComponent(name, default=None):
        """Finds the registration registry for a given name, checks if it has
        an active registration, and if so, returns its component.  Otherwise
        returns default.
        """

    def queryLocalService(service_type, default=None):
        """Return a local service, if there is one

        A local service is one configured in the local service manager.

        The service must be returned in the context of the service manager.
        """

    def addSubsite(subsite):
        """Add a subsite of the site

        Local sites are connected in a tree. Each site knows about
        its containing sites and its subsites.
        """


class IServiceRegistration(registration.IComponentRegistration):
    """Service Registration

    Service registrations are dependent on the components that they
    configure. They register themselves as component dependents.

    The name of a service registration is used to determine the service
    type.
    """

    name = zope.schema.TextLine(
        title=_("Name"),
        description=_("The name that is registered"),
        readonly=True,
        # Don't allow empty or missing name:
        required=True,
        min_length=1,
        )


class ISiteManagementFolder(
    registration.IRegistrationManagerContainer,
    IContainer,
    ):
    """Component and component registration containers."""

    __parent__ = zope.schema.Field(
        constraint = ContainerTypesConstraint(
            ISiteManager,
            registration.IRegistrationManagerContainer,
            ),
        )

class ISiteManagementFolders(IContainer, IComponentManager):
    """A collection of ISiteManagementFolder objects.

    An ISiteManagementFolders object supports simple containment as
    well as package query and lookup.
    
    """


=== Added File Zope3/src/zope/app/site/service.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.
#
##############################################################################
"""Service manager implementation

A service manager has a number of roles:

  - A service service

  - A place to do TTW development or to manage database-based code

  - A registry for persistent modules.  The Zope import hook uses the
    ServiceManager to search for modules.  (This functionality will
    eventually be replaced by a separate module service.)

$Id: service.py,v 1.1 2004/03/13 15:21:47 srichter Exp $
"""
from transaction import get_transaction
from zodbcode.module import PersistentModuleRegistry
from zope.app.component.nextservice import getNextService
from zope.app.component.nextservice import getNextServiceManager
from zope.app.container.btree import BTreeContainer
from zope.app.container.constraints import ItemTypePrecondition
from zope.app.container.contained import Contained
from zope.app.container.interfaces import IContainer
from zope.app.event.function import Subscriber
from zope.app import zapi
from interfaces import IBindingAware, ILocalService, IServiceRegistration
from interfaces import IPossibleSite, ISite, ISiteManager
from zope.app.interfaces.services.registration import IRegistry
from zope.app.interfaces.traversing import IContainmentRoot
from zope.app.location import inside
from zope.app.site.folder import SiteManagementFolder
from zope.app.services.registration import ComponentRegistration
from zope.app.services.registration import RegistrationStack
from zope.app.traversing import getPath
from zope.component.exceptions import ComponentLookupError
from zope.component import getServiceManager
from zope.fssync.server.entryadapter import AttrMapping, DirectoryAdapter
from zope.proxy import removeAllProxies
import sys
import zope.app.interfaces.services.registration
import zope.interface


class IRegistrationManagerContainerContainer(zope.interface.Interface):

    def __setitem__(name, folder):
        """Add a site-management folder
        """
    __setitem__.precondition = ItemTypePrecondition(
       zope.app.interfaces.services.registration.IRegistrationManagerContainer)


class SiteManager(
    BTreeContainer,
    PersistentModuleRegistry,
    ):

    zope.interface.implements(
        ISiteManager,
        IRegistrationManagerContainerContainer,
        IRegistry,
        )

    def __init__(self, site):
        self._bindings = {}
        self.__parent__ = site
        self.__name__ = '++etc++site'
        BTreeContainer.__init__(self)
        PersistentModuleRegistry.__init__(self)
        self.subSites = ()
        self._setNext(site)
        self['default'] = SiteManagementFolder()

    def _setNext(self, site):
        """Find set the next service manager
        """
        while True:
            if IContainmentRoot.providedBy(site):
                # we're the root site, use the global sm
                self.next = zapi.getServiceManager(None)
                return
            site = site.__parent__
            if site is None:
                raise TypeError("Not enough context information")
            if ISite.providedBy(site):
                self.next = site.getSiteManager()
                self.next.addSubsite(self)
                return

    def addSubsite(self, sub):
        """See ISiteManager interface
        """
        subsite = sub.__parent__

        # Update any sites that are now in the subsite:
        subsites = []
        for s in self.subSites:
            if inside(s, subsite):
                s.next = sub
                sub.addSubsite(s)
            else:
                subsites.append(s)

        subsites.append(sub)
        self.subSites = tuple(subsites)

    def queryRegistrationsFor(self, cfg, default=None):
        """See IRegistry"""
        return self.queryRegistrations(cfg.name, default)

    def queryRegistrations(self, name, default=None):
        """See INameRegistry"""
        return self._bindings.get(name, default)

    def createRegistrationsFor(self, cfg):
        """See IRegistry"""
        return self.createRegistrations(cfg.name)

    def createRegistrations(self, name):
        try:
            registry = self._bindings[name]
        except KeyError:
            registry = RegistrationStack(self)
            self._bindings[name] = registry
            self._p_changed = 1
        return registry

    def listRegistrationNames(self):
        return filter(self._bindings.get,
                      self._bindings.keys())

    def queryActiveComponent(self, name, default=None):
        registry = self.queryRegistrations(name)
        if registry:
            registration = registry.active()
            if registration is not None:
                return registration.getComponent()
        return default

    def getServiceDefinitions(wrapped_self):
        """See IServiceService
        """
        # Get the services defined here and above us, if any (as held
        # in a ServiceInterfaceService, presumably)
        sm = getNextServiceManager(wrapped_self)
        if sm is not None:
            serviceDefs = sm.getServiceDefinitions()
        else: serviceDefs = {}

        return serviceDefs

    def queryService(wrapped_self, name, default=None):
        """See IServiceService
        """
        try:
            return wrapped_self.getService(name)
        except ComponentLookupError:
            return default

    def getService(wrapped_self, name):
        """See IServiceService
        """

        # This is rather tricky. Normally, getting a service requires
        # the use of other services, like the adapter service.  We
        # need to be careful not to get into an infinate recursion by
        # getting out getService to be called while looking up
        # services, so we'll

        if name == 'Services':
            return wrapped_self # We are the service service

        if not getattr(wrapped_self, '_v_calling', 0):

            wrapped_self._v_calling = 1
            try:
                service = wrapped_self.queryActiveComponent(name)
                if service is not None:
                    return service

            finally:
                wrapped_self._v_calling = 0

        return getNextService(wrapped_self, name)


    def queryLocalService(wrapped_self, name, default=None):
        """See ISiteManager
        """

        # This is rather tricky. Normally, getting a service requires
        # the use of other services, like the adapter service.  We
        # need to be careful not to get into an infinate recursion by
        # getting our getService to be called while looking up
        # services, so we'll use _v_calling to prevent recursive
        # getService calls.

        if name == 'Services':
            return wrapped_self # We are the service service

        if not getattr(wrapped_self, '_v_calling', 0):

            wrapped_self._v_calling = 1
            try:
                service = wrapped_self.queryActiveComponent(name)
                if service is not None:
                    return service

            finally:
                wrapped_self._v_calling = 0

        return default

    def getInterfaceFor(wrapped_self, service_type):
        """See IServiceService
        """
        for type, interface in wrapped_self.getServiceDefinitions():
            if type == service_type:
                return interface

        raise NameError(service_type)

    def queryComponent(self, type=None, filter=None, all=0):
        local = []
        path = getPath(self)
        for pkg_name in self:
            package = self[pkg_name]
            for name in package:
                component = package[name]
                if type is not None and not type.providedBy(component):
                    continue
                if filter is not None and not filter(component):
                    continue
                local.append({'path': "%s/%s/%s" % (path, pkg_name, name),
                              'component': component,
                              })

        if all:
            next_service_manager = getNextServiceManager(self)
            if IComponentManager.providedBy(next_service_manager):
                next_service_manager.queryComponent(type, filter, all)

            local += list(all)

        return local

    def findModule(wrapped_self, name):
        # override to pass call up to next service manager
        mod = super(ServiceManager,
                    removeAllProxies(wrapped_self)).findModule(name)
        if mod is not None:
            return mod

        sm = getNextServiceManager(wrapped_self)
        try:
            findModule = sm.findModule
        except AttributeError:
            # The only service manager that doesn't implement this
            # interface is the global service manager.  There is no
            # direct way to ask if sm is the global service manager.
            return None
        return findModule(name)

    def __import(wrapped_self, module_name):

        mod = wrapped_self.findModule(module_name)
        if mod is None:
            mod = sys.modules.get(module_name)
            if mod is None:
                raise ImportError(module_name)

        return mod

ServiceManager = SiteManager # Backward compat

class ServiceRegistration(ComponentRegistration):
    """Registrations for named components.

    This configures components that live in folders, by name.
    """

    serviceType = zapi.servicenames.Services

    zope.interface.implements(IServiceRegistration)

    def __init__(self, name, path, context=None):
        ComponentRegistration.__init__(self, path, None)
        self.name = name

        if context is not None:
            # Check that the object implements stuff we need
            self.__parent__ = context
            service = self.getComponent()
            if not ILocalService.providedBy(service):
                raise TypeError(
                    "service %r doesn't implement ILocalService" %
                    service)
        # Else, this must be a hopeful test invocation

    def getInterface(self):
        service_manager = getServiceManager(self)
        return service_manager.getInterfaceFor(self.name)


    def activated(self):
        service = self.getComponent()
        if IBindingAware.providedBy(service):
            service.bound(self.name)


    def deactivated(self):
        service = self.getComponent()
        if IBindingAware.providedBy(service):
            service.unbound(self.name)


    def usageSummary(self):
        return self.name + " Service"


# XXX Pickle backward compatability
ServiceConfiguration = ServiceRegistration

# Fssync stuff

_smattrs = (
    '_modules',                         # PersistentModuleRegistry
    '_bindings',
)

class ServiceManagerAdapter(DirectoryAdapter):

    def extra(self):
        obj = removeAllProxies(self.context)
        return AttrMapping(obj, _smattrs)

#BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB


def fixup(event):
    database = event.database
    connection = database.open()
    app = connection.root().get('Application')
    if app is None:
        # no old site
        return

    try:
        sm = app.getSiteManager()
    except ComponentLookupError:
        # no old site
        return

    if hasattr(sm, 'next'):
        # already done
        return
    
    print "Fixing up sites that don't have next pointers"
    fixfolder(app)
    get_transaction().commit()
    connection.close()
    
fixup = Subscriber(fixup)

def fixfolder(folder):
    try:
        sm = folder.getSiteManager()
    except ComponentLookupError:
        pass # nothing to do
    else:
        sm._setNext(folder)
        sm.subSites = ()
        for name in ('Views', 'Adapters'):
            if name in sm._bindings:
                del sm._bindings[name]

    for item in folder.values():
        if IPossibleSite.providedBy(item):
            fixfolder(item)


=== Added File Zope3/src/zope/app/site/servicecontainer.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.
#
##############################################################################
"""ServiceManagerContainer implementation.

$Id: servicecontainer.py,v 1.1 2004/03/13 15:21:47 srichter Exp $
"""

import zope.interface

from transaction import get_transaction
from zope.app.container.contained import Contained
from zope.app.event.function import Subscriber
from zope.app import zapi
from zope.app.site.interfaces import IPossibleSite, ISite
from zope.component.exceptions import ComponentLookupError
from zope.component.interfaces import IServiceService
from zope.interface import implements

class ServiceManagerContainer(Contained):

    """Implement access to the service manager (++etc++site).

    This is a mix-in that implements the IPossibleSite
    interface; for example, it is used by the Folder implementation.
    """

    zope.interface.implements(IPossibleSite)

    __sm = None

    def getSiteManager(self):
        if self.__sm is not None:
            return self.__sm
        else:
            raise ComponentLookupError('no site manager defined')

    def setSiteManager(self, sm):
        if ISite.providedBy(self):
            raise TypeError("Already a site")

        if IServiceService.providedBy(sm):
            self.__sm = sm
            sm.__name__ = '++etc++site'
            sm.__parent__ = self
        else:
            raise ValueError('setSiteManager requires an IServiceService')

        zope.interface.directlyProvides(
            self,
            ISite,
            zope.interface.directlyProvidedBy(self))

def fixup(event):
        database = event.database
        connection = database.open()
        app = connection.root().get('Application')
        if app is None or ISite.providedBy(app):
            # No old data
            return
        print "Fixing up sites that don't implement ISite"
        fixfolder(app)
        get_transaction().commit()
        connection.close()

fixup = Subscriber(fixup)

def fixfolder(folder):
    if ISite.providedBy(folder):
        # No need to do more, the conversion already happened!
        return
    try:
        folder.getSiteManager()
    except ComponentLookupError:
        pass # nothing to do
    else:
        zope.interface.directlyProvides(
            folder,
            ISite,
            zope.interface.directlyProvidedBy(folder),
            )

    for item in folder.values():
        if IPossibleSite.providedBy(item):
            fixfolder(item)




More information about the Zope3-Checkins mailing list