[Zope3-checkins] CVS: Zope3/lib/python/Interface/Registry - AdapterRegistry.py:1.1 IAdapterRegistry.py:1.1 IImplementorRegistry.py:1.1 ITypeRegistry.py:1.1 ImplementorRegistry.py:1.1 TypeRegistry.py:1.1 __init__.py:1.1 _flatten.py:1.1

Jim Fulton jim@zope.com
Thu, 1 Aug 2002 11:33:44 -0400


Update of /cvs-repository/Zope3/lib/python/Interface/Registry
In directory cvs.zope.org:/tmp/cvs-serv4877/lib/python/Interface/Registry

Added Files:
	AdapterRegistry.py IAdapterRegistry.py IImplementorRegistry.py 
	ITypeRegistry.py ImplementorRegistry.py TypeRegistry.py 
	__init__.py _flatten.py 
Log Message:
Refactored and moved Zope.ComponentArchitecture.IToIRegistry into
Interface.Registry. This is only the first step. The tests pass and
Zope 3 runs, but there are a bunch of wrong dependencies that still
need to get cleaned up, which is my next task.



=== Added File Zope3/lib/python/Interface/Registry/AdapterRegistry.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.
# 
##############################################################################
"""Adapter-style interface registry

See Adapter class.

$Id: AdapterRegistry.py,v 1.1 2002/08/01 15:33:43 jim Exp $
"""
__metaclass__ = type # All classes are new style when run with Python 2.2+

from Interface import Interface
from _flatten import _flatten
from IAdapterRegistry import IAdapterRegistry

class AdapterRegistry:
    """Adapter-style interface registry
    """

    __implements__ = IAdapterRegistry

    # The implementation uses a mapping:
    #
    #  { (required_interface, provided_interface) ->
    #                             (registered_provides, component) }
    #
    # Where the registered provides is what was registered and
    # provided may be some base interface
    
    def __init__(self):
        self._reg = {}
        
    def _registerAllProvided(self, require, primary_provide, object, provide):
        # Registers a component using (require, provide) as a key.
        # Also registers superinterfaces of the provided interface,
        # stopping when the registry already has a component
        # that provides a more general interface or when the Base is Interface.
        
        reg = self._reg
        reg[(require, provide)] = (primary_provide, object)
        bases = getattr(provide, '__bases__', ())
        for base in bases:
            if base is Interface:
                # Never register the say-nothing Interface.
                continue
            existing = reg.get((require, base), None)
            if existing is not None:
                existing_provide = existing[0]
                if existing_provide is not primary_provide:
                    if not existing_provide.extends(primary_provide):
                        continue
                    # else we are registering a general component
                    # after a more specific component.
            self._registerAllProvided(require, primary_provide, object, base)


    def register(self, require, provide, object):        
        self._registerAllProvided(require, provide, object, provide)

    def get(self, (ob_interface, provide), default=None):
        """
        Finds a registered component that provides the given interface.
        Returns None if not found.
        """
        for interface in _flatten(ob_interface):
            c = self._reg.get((interface, provide))
            if c:
                return c[1]

        c = self._reg.get((None, provide), default)
        if c:
            return c[1]

        return c

    def getForObject(self, object, interface):
        return self.get((getattr(object, '__implements__', None), interface))


=== Added File Zope3/lib/python/Interface/Registry/IAdapterRegistry.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.
# 
##############################################################################
"""

$Id: IAdapterRegistry.py,v 1.1 2002/08/01 15:33:43 jim Exp $
"""

from Interface import Interface

class IAdapterRegistry(Interface):
    """Adapter-style registry

    This registry stores objects registered to convert (or participate
    in the conversion from) one interface to another. The interface
    converted is the "required" interface. We say that the interface
    converted to is the "provided" interface.

    The objects registered here don't need to be adapters. What's
    important is that they are registered according to a required and
    a provided interface.

    The provided interface may not be None.

    The required interface may be None. Adapters with a required
    interface of None adapt non-components. An adapter that adapts all
    components should specify a required interface of
    Interface.Interface.
    
    """

    def register(require, provide, object):
        """Register an object for a required and provided interface.

        There are no restrictions on what the object might be.
        Any restrictions (e.g. callability, or interface
        implementation) must be enforced by higher-level code.

        The require argument may be None.

        """

    def get((implements, provides), default=None):
        """Return a registered object

        The registered object is one that was registered to require an
        interface that one of the interfaces in the 'implements'
        specification argument extends or equals and that provides an
        interface that extends or equals the 'provides' argument.  An
        attempt will be made to find the component that most closely
        matches the input arguments.

        The object returned could have been registred to require None.

        Note that the implements may be None, it which case a
        component will be returned only if it was registered with a
        require of None.
        """
    


=== Added File Zope3/lib/python/Interface/Registry/IImplementorRegistry.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.
# 
##############################################################################
"""

$Id: IImplementorRegistry.py,v 1.1 2002/08/01 15:33:43 jim Exp $
"""

from Interface import Interface

class IImplementorRegistry(Interface):
    """Implementor registry

    This registry stores objects registered to implement (or help
    implement) an interface. For example, this registry could be used
    to register utilities.

    The objects registered here don't need to be implementors. (They
    might just be useful to implementation.) What's important is that
    they are registered according to a provided interface.
    
    """

    def register(provide, object):
        """Register an object for a required and provided interface.

        There are no restrictions on what the object might be.
        Any restrictions (e.g. callability, or interface
        implementation) must be enforced by higher-level code.

        The require argument may be None.

        """

    def get(provides, default=None):
        """Return a registered object

        The registered object is one that was registered that provides an
        interface that extends or equals the 'provides' argument.

        """
    



=== Added File Zope3/lib/python/Interface/Registry/ITypeRegistry.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.
# 
##############################################################################
"""

$Id: ITypeRegistry.py,v 1.1 2002/08/01 15:33:43 jim Exp $
"""

from Interface import Interface

class ITypeRegistry(Interface):
    """Type-specific registry

    This registry stores objects registered for objects that implement
    a required interface.    
    """

    def register(require, object):
        """Register an object for a required interface.

        The require argument may be None.  This effectively defines a
        default object.

        """

    def get(implements, default=None):
        """Return a registered object

        The registered object is one that was registered to require an
        interface that one of the interfaces in the 'implements'
        specification argument extends or equals.  An attempt will be
        made to find the component that most closely matches the input
        arguments.

        The object returned could have been registred to require None.

        Note that the implements may be None, it which case a
        component will be returned only if it was registered with a
        require of None.
        
        """
        
    def getDefinitions(implements=None):
        """Get meta-data about registered objects

        Return meta data for all objects registered with a require
        interfaces such that if the 'implements' argumennt is not
        None, it is an implementation specification such that some of
        the interfaces in the specification extend or equal the
        require interface (or the require interface was None).

        The meta-data returned is a sequence of mapping objects with
        the following keys:

        require -- The required interface

        object -- The registered object

        """

    def getAll(implements=None):
        """Get registered objects

        Return all objects registered with a require interfaces such
        that if the 'implements' argumennt is not None, it is an
        implementation specification such that some of the interfaces
        in the specification extend or equal the require interface (or
        the require interface was None).

        """
    


=== Added File Zope3/lib/python/Interface/Registry/ImplementorRegistry.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.
# 
##############################################################################
"""Adapter-style interface registry

See Adapter class.

$Id: ImplementorRegistry.py,v 1.1 2002/08/01 15:33:43 jim Exp $
"""
__metaclass__ = type # All classes are new style when run with Python 2.2+

from Interface import Interface
from IImplementorRegistry import IImplementorRegistry

class ImplementorRegistry:
    """Implementor-style interface registry
    """

    __implements__ = IImplementorRegistry

    # The implementation uses a mapping:
    #
    #  { provided_interface -> (registered_provides, component) }
    #
    # Where the registered provides is what was registered and
    # provided may be some base interface
    
    def __init__(self):
        self._reg = {}
        
    def _registerAllProvided(self, primary_provide, object, provide):
        # Registers a component using (require, provide) as a key.
        # Also registers superinterfaces of the provided interface,
        # stopping when the registry already has a component
        # that provides a more general interface or when the Base is Interface.
        
        reg = self._reg
        reg[provide] = (primary_provide, object)
        bases = getattr(provide, '__bases__', ())
        for base in bases:
            if base is Interface:
                # Never register the say-nothing Interface.
                continue
            existing = reg.get(base, None)
            if existing is not None:
                existing_provide = existing[0]
                if existing_provide is not primary_provide:
                    if not existing_provide.extends(primary_provide):
                        continue
                    # else we are registering a general component
                    # after a more specific component.
            self._registerAllProvided(primary_provide, object, base)


    def register(self, provide, object):        
        self._registerAllProvided(provide, object, provide)

    def get(self, provide, default=None):
        """
        Finds a registered component that provides the given interface.
        Returns None if not found.
        """
        c = self._reg.get(provide)
        if c is not None:
            return c[1]

        return default


=== Added File Zope3/lib/python/Interface/Registry/TypeRegistry.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.
# 
##############################################################################
"""Adapter-style interface registry

See Adapter class.

$Id: TypeRegistry.py,v 1.1 2002/08/01 15:33:43 jim Exp $
"""
__metaclass__ = type # All classes are new style when run with Python 2.2+

from Interface import Interface
from _flatten import _flatten
from ITypeRegistry import ITypeRegistry

class TypeRegistry:
    """Type registry
    """

    __implements__ = ITypeRegistry

    # The implementation uses a mapping:
    #
    #  { (required_interface, provided_interface) ->
    #                             (registered_provides, component) }
    #
    # Where the registered provides is what was registered and
    # provided may be some base interface
    
    def __init__(self):
        self._reg = {}

    def register(self, interface, object):
        self._reg[interface] = object

    def get(self, interface, default=None):
        """
        Finds a registered component that provides the given interface.
        Returns None if not found.
        """
        return self._reg.get(interface, default)

    def getAll(self, interface_spec):
        result = []
        for interface in _flatten(interface_spec):
            object = self._reg.get(interface)
            if object is not None:
                result.append(object)

        if interface_spec is not None:
            object = self._reg.get(None)
            if object is not None:
                result.append(object)

        return result

    def getAllForObject(self, object):
        # XXX This isn't quite right, since it doesn't take into
        # account implementation registries for objects that can't
        # have '__implements__' attributes.
        return self.getAll(getattr(object, '__implements__', None))


=== Added File Zope3/lib/python/Interface/Registry/__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.
# 
##############################################################################



=== Added File Zope3/lib/python/Interface/Registry/_flatten.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.
# 
##############################################################################
"""Adapter-style interface registry

See Adapter class.

$Id: _flatten.py,v 1.1 2002/08/01 15:33:43 jim Exp $
"""
__metaclass__ = type # All classes are new style when run with Python 2.2+

from Interface import Interface

def _flatten(implements):
    """Flatten an implements spec to a list of interfaces

    The list includes all base interfaces of the interface(s) in
    implements. Each interface is listed only once and more
    specific interfaces are listed before less specific
    interfaces. This is similar to Python 2.2's MRO.
    """
    interfaces = []
    _flatten_recurse(implements, interfaces)
    interfaces.reverse()
    seen = {}
    flattened = []
    for interface in interfaces:
        if interface not in seen:
            seen[interface] = 1
            flattened.append(interface)
    flattened.reverse()

    return flattened
        
def _flatten_recurse(implements, list):
    if implements.__class__ == tuple:
        for i in implements:
            _flatten_recurse(i, list)
    else:
        _flatten_recurse_interface(implements, list)
    
def _flatten_recurse_interface(interface, list):
    list.append(interface)
    if interface is None:
        return
    for i in interface.__bases__:
        _flatten_recurse_interface(i, list)