##############################################################################
#
# 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.
#
##############################################################################
"""Interface object implementation
Revision information:
$Id: _InterfaceClass.py,v 1.6 2002/08/14 21:35:32 mj Exp $
"""
from inspect import currentframe
import sys
from Method import Method,fromFunction
from Attribute import Attribute
from types import FunctionType
import Exceptions
from _Element import Element
from _object import isInstance
class Interface(Element):
"""Prototype (scarecrow) Interfaces Implementation
"""
# We can't say this yet because we don't have enough
# infrastructure in place.
#
#__implements__ = IInterface
def __init__(self, name, bases=(), attrs=None, __doc__=None,
__module__=None):
if __module__ is None:
if attrs is not None and attrs.has_key('__module__'):
__module__ = attrs['__module__']
del attrs['__module__']
else:
try:
# Figure out what module defined the interface.
# This is how cPython figures out the module of
# a class, but of course it does it in C. :-/
__module__ = currentframe().f_back.f_globals['__name__']
except (AttributeError, KeyError):
pass
self.__module__ = __module__
for b in bases:
if not isInstance(b, Interface):
raise TypeError, 'Expected base interfaces'
self.__bases__=bases
if attrs is None: attrs={}
if attrs.has_key('__doc__'):
if __doc__ is None: __doc__=attrs['__doc__']
del attrs['__doc__']
if __doc__ is not None:
self.__doc__=__doc__
else:
self.__doc__ = ""
Element.__init__(self, name, __doc__)
for k, v in attrs.items():
if isInstance(v, Attribute):
v.interface=name
if not v.__name__:
v.__name__ = k
elif isinstance(v, FunctionType):
attrs[k]=fromFunction(v, name)
else:
raise Exceptions.InvalidInterface(
"Concrete attribute, %s" % k)
self.__attrs = attrs
def getBases(self):
return self.__bases__
def extends(self, other, strict=1):
"""Does an interface extend another?
"""
if not strict and self is other:
return 1
for b in self.__bases__:
if b == other: return 1
if b.extends(other): return 1
return 0
def isEqualOrExtendedBy(self, other):
"""Same interface or extends?
"""
if self == other:
return 1
return other.extends(self)
def isImplementedBy(self, object):
"""Does the given object implement the interface?
"""
i = getImplements(object)
if i is not None:
return visitImplements(
i, object, self.isEqualOrExtendedBy, self._getInterface)
return 0
def isImplementedByInstancesOf(self, klass):
"""Do instances of the given class implement the interface?
"""
i = getImplementsOfInstances(klass)
if i is not None:
return visitImplements(
i, klass, self.isEqualOrExtendedBy, self._getInterface)
return 0
def names(self, all=0):
"""Return the attribute names defined by the interface
"""
if not all:
return self.__attrs.keys()
r = {}
for name in self.__attrs.keys():
r[name] = 1
for base in self.__bases__:
for name in base.names(all):
r[name] = 1
return r.keys()
def namesAndDescriptions(self, all=0):
"""Return the attribute names and descriptions defined by the interface
"""
if not all:
return self.__attrs.items()
r = {}
for name, d in self.__attrs.items():
r[name] = d
for base in self.__bases__:
for name, d in base.namesAndDescriptions(all):
if not r.has_key(name):
r[name] = d
return r.items()
def getDescriptionFor(self, name):
"""Return the attribute description for the given name
"""
r = self.queryDescriptionFor(name)
if r is not None:
return r
raise KeyError, name
def queryDescriptionFor(self, name, default=None):
"""Return the attribute description for the given name
"""
r = self.__attrs.get(name, self)
if r is not self:
return r
for base in self.__bases__:
r = base.queryDescriptionFor(name, self)
if r is not self:
return r
return default
def deferred(self):
"""Return a defered class corresponding to the interface
"""
if hasattr(self, "_deferred"): return self._deferred
klass={}
exec "class %s: pass" % self.__name__ in klass
klass=klass[self.__name__]
self.__d(klass.__dict__)
self._deferred=klass
return klass
def _getInterface(self, ob, name):
'''
Retrieve a named interface.
'''
return None
def __d(self, dict):
for k, v in self.__attrs.items():
if isInstance(v, Method) and not dict.has_key(k):
dict[k]=v
for b in self.__bases__: b.__d(dict)
def __repr__(self):
name = self.__name__
m = self.__module__
if m:
name = '%s.%s' % (m, name)
return "<%s %s at %x>" % (self.__class__.__name__, name, id(self))
def __reduce__(self):
return self.__name__
def __hash__(self):
""" interface instances need to be hashable, and inheriting
from extensionclass makes instances unhashable unless we declare
a __hash__ method here"""
return id(self)
# We import this here to deal with module dependencies.
from Implements import getImplementsOfInstances,visitImplements,getImplements
from Implements import instancesOfObjectImplements
|