Skip to content

Commit

Permalink
First cut at adapter-registry refactoring. The refactoring makes
Browse files Browse the repository at this point in the history
adapter lookup work more like method lookup.  This provides:

- a much simpler algorithm,

- a basis for super-like adapter lookup, and

- a fix for a bug in multi-adapter lookup.

These changes also remove the distinction between objects with no
interface declarations and objects that declare that they provide
Interface.

Unfortunately, these version is *much* too slow.  I'm checking this
version in to save it before trying some variations.
  • Loading branch information
Jim Fulton committed Sep 8, 2005
0 parents commit 3b672ba
Show file tree
Hide file tree
Showing 5 changed files with 3,009 additions and 0 deletions.
133 changes: 133 additions & 0 deletions adapter.py
@@ -0,0 +1,133 @@
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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.
#
##############################################################################
"""Local/Persistent Adapter Registry
$Id$
"""
__docformat__ = 'restructuredtext'
import persistent

import zope.interface
from zope.security.proxy import removeSecurityProxy

from zope.app.component import registration
from zope.app.component import interfaces


class LocalAdapterRegistry(zope.interface.adapter.AdapterRegistry,
persistent.Persistent):
"""Local/persistent surrogate registry"""
zope.interface.implements(interfaces.ILocalAdapterRegistry)

# See interfaces.registration.ILocatedRegistry
next = None
subs = ()

def __init__(self, base, next=None):
# Base registry. This is always a global registry
self.base = base
# `adapters` is simple dict, since it is populated during every load
self.adapters = {}
self._registrations = ()
super(LocalAdapterRegistry, self).__init__()
self.setNext(next)

def addSub(self, sub):
"""See interfaces.registration.ILocatedRegistry"""
self.subs += (sub, )

def removeSub(self, sub):
"""See interfaces.registration.ILocatedRegistry"""
self.subs = tuple(
[s for s in self.subs if s is not sub] )

def setNext(self, next, base=None):
"""See interfaces.registration.ILocatedRegistry"""
if base is not None:
self.base = base

if next != self.next:
if self.next is not None:
self.next.removeSub(self)
if next is not None:
next.addSub(self)
self.next = next

self.__bases__ = tuple([b for b in (next, self.base) if b is not None])

for sub in self.subs:
sub.setNext(self)


def register(self, registration):
"""See zope.app.component.interfaces.registration.IRegistry"""
self._registrations += (registration,)

zope.interface.adapter.AdapterRegistry.register(
self,
(registration.required, ) + registration.with,
registration.provided, registration.name,
registration.component,
)

def unregister(self, registration):
"""See zope.app.component.interfaces.registration.IRegistry"""
self._registrations = tuple([reg for reg in self._registrations
if reg is not registration])

zope.interface.adapter.AdapterRegistry.unregister(
self,
(registration.required, ) + registration.with,
registration.provided, registration.name,
registration.component,
)

def registered(self, registration):
"""See zope.app.component.interfaces.registration.IRegistry"""
return registration in self._registrations

def registrations(self):
"""See zope.app.component.interfaces.registration.IRegistry"""
return self._registrations

class AdapterRegistration(registration.ComponentRegistration):
"""A simple implementation of the adapter registration interface."""
zope.interface.implements(interfaces.IAdapterRegistration)

def __init__(self, required, provided, factory,
name='', permission=None, registry=None):
if not isinstance(required, (tuple, list)):
self.required = required
self.with = ()
else:
self.required = required[0]
self.with = tuple(required[1:])
self.provided = provided
self.name = name
self.component = factory
self.permission = permission
self.registry = registry

def getRegistry(self):
return self.registry

def __repr__(self):
return ('<%s: ' %self.__class__.__name__ +
'required=%r, ' %self.required +
'with=' + `self.with` + ', ' +
'provided=%r, ' %self.provided +
'name=%r, ' %self.name +
'component=%r, ' %self.component +
'permission=%r' %self.permission +
'>')
169 changes: 169 additions & 0 deletions interfaces/__init__.py
@@ -0,0 +1,169 @@
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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 the Local Component Architecture
$Id$
"""
import zope.interface
import zope.schema
import zope.component
from zope.app.container.interfaces import IContainer
from zope.app.container.constraints import ContainerTypesConstraint
from zope.app.container.constraints import ItemTypePrecondition
from zope.app.i18n import ZopeMessageIDFactory as _
import registration

class ILocalAdapterRegistry(registration.IRegistry,
registration.ILocatedRegistry):
pass

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

def setSiteManager(sitemanager):
"""Sets the site manager for this object.
"""

def getSiteManager():
"""Returns the site manager contained in this object.
If there isn't a site manager, raise a component lookup.
"""

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

class ILocalSiteManager(zope.component.interfaces.ISiteManager,
registration.ILocatedRegistry,
registration.IRegistry):
"""Site Managers act as containers for registerable components.
If a Site Manager is asked for an adapter or utility, it checks for those
it contains before using a context-based lookup to find another site
manager to delegate to. If no other site manager is found they defer to
the global site manager which contains file based utilities and adapters.
"""

class INewLocalSite(zope.interface.Interface):

manager = zope.interface.Attribute("The new site manager")

class NewLocalSite:
zope.interface.implements(INewLocalSite)

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


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

__parent__ = zope.schema.Field(
constraint = ContainerTypesConstraint(
ILocalSiteManager,
registration.IRegisterableContainer,
),
)

class ILocalUtility(registration.IRegisterable):
"""Local utility marker.
A marker interface that indicates that a component can be used as
a local utility.
Utilities should usually also declare they implement
IAttributeAnnotatable, so that the standard adapter to
IRegistered can be used; otherwise, they must provide
another way to be adaptable to IRegistered.
"""


class IAdapterRegistration(registration.IComponentRegistration):
"""Local Adapter Registration for Local Adapter Registry
The adapter registration is used to provide local adapters via the
adapter registry. It is an extended component registration, whereby the
component is the adapter factory in this case.
"""
required = zope.schema.Choice(
title = _("For interface"),
description = _("The interface of the objects being adapted"),
vocabulary="Interfaces",
readonly = True,
required=False,
default=None)

with = zope.schema.Tuple(
title = _("With interfaces"),
description = _("Additionally required interfaces"),
readonly=True,
value_type = zope.schema.Choice(vocabulary='Interfaces'),
required=False,
default=())

provided = zope.schema.Choice(
title = _("Provided interface"),
description = _("The interface provided"),
vocabulary="Interfaces",
readonly = True,
required = True)

name = zope.schema.TextLine(
title=_(u"Name"),
readonly=False,
required=True,
default=u''
)

permission = zope.schema.Choice(
title=_("The permission required for use"),
vocabulary="Permission Ids",
readonly=False,
required=False,
)

# TODO: for now until we figure out a way to specify the factory directly
factoryName = zope.schema.TextLine(
title=_(u"Factory Name"),
readonly=False,
required=False,
)


class IUtilityRegistration(IAdapterRegistration):
"""Utility registration object.
Adapter registries are also used to to manage utilities, since utilities
are adapters that are instantiated and have no required interfaces. Thus,
utility registrations must fulfill all requirements of an adapter
registration as well.
"""

name = zope.schema.TextLine(
title=_("Register As"),
description=_("The name under which the utility will be known."),
readonly=False,
required=True,
default=u''
)

provided = zope.schema.Choice(
title=_("Provided interface"),
description=_("The interface provided by the utility"),
vocabulary="Utility Component Interfaces",
readonly=True,
required=True,
)

0 comments on commit 3b672ba

Please sign in to comment.