Back to index

plone3  3.1.7
InterfaceTool.py
Go to the documentation of this file.
00001 from types import ModuleType, ListType, TupleType
00002 from Products.CMFPlone.interfaces.InterfaceTool import IInterfaceTool \
00003      as z2IInterfaceTool
00004 from Products.CMFPlone.interfaces import IInterfaceTool
00005 from Acquisition import aq_base
00006 from Products.CMFCore.utils import registerToolInterface
00007 from Products.CMFCore.utils import UniqueObject
00008 
00009 from OFS.SimpleItem import SimpleItem
00010 from Globals import InitializeClass
00011 from AccessControl import ClassSecurityInfo
00012 from Products.CMFPlone.PloneBaseTool import PloneBaseTool
00013 
00014 from Interface.Implements import getImplements, flattenInterfaces
00015 from Interface import Interface
00016 from Interface.IMethod import IMethod
00017 
00018 from zope.interface import implements
00019 
00020 _marker = ('module_finder',)
00021 
00022 class InterfaceTool(PloneBaseTool, UniqueObject, SimpleItem):
00023     """ This tool exposes the interface package for TTW applications,
00024     by accepting a dotted name of an interface and exporting the
00025     IInterface API """
00026 
00027     __implements__ = (PloneBaseTool.__implements__, z2IInterfaceTool,
00028                       SimpleItem.__implements__, )
00029 
00030     implements(IInterfaceTool)
00031 
00032     id = 'portal_interface'
00033     meta_type= 'Portal Interface Tool'
00034     security = ClassSecurityInfo()
00035 
00036     security.declarePublic('objectImplements')
00037     def objectImplements(self, obj, dotted_name):
00038         """ Asserts if an object implements a given interface """
00039         obj = aq_base(obj)
00040         iface = resolveInterface(dotted_name)
00041         return iface.isImplementedBy(obj)
00042 
00043     security.declarePublic('classImplements')
00044     def classImplements(self, obj, dotted_name):
00045         """ Asserts if an object's class implements a given interface """
00046         klass = aq_base(obj).__class__
00047         iface = resolveInterface(dotted_name)
00048         return iface.isImplementedBy(klass)
00049 
00050     security.declarePublic('namesAndDescriptions')
00051     def namesAndDescriptions(self, dotted_name, all=0):
00052         """ Returns a list of pairs (name, description) for a given
00053         interface"""
00054         iface = resolveInterface(dotted_name)
00055         nd = iface.namesAndDescriptions(all=all)
00056         return [(n, d.getDoc()) for n, d in nd]
00057 
00058     security.declarePublic('getInterfacesOf')
00059     def getInterfacesOf(self, object):
00060         """Returns the list of interfaces which are implemented by the object
00061         """
00062         impl = getImplements(object)
00063         if impl:
00064             if type(impl) in (ListType, TupleType):
00065                 result = flattenInterfaces(impl)
00066             else:
00067                 result = (impl, )
00068             return [ iface for iface in result if iface is not Interface ]
00069 
00070     def getBaseInterfacesOf(self, object):
00071         """Returns all base interfaces of an object but no direct interfaces
00072 
00073         Base interfaces are the interfaces which are the super interfaces of the
00074         direct interfaces
00075         """
00076         ifaces = self.getInterfacesOf(object)
00077         bases = []
00078         for iface in ifaces:
00079             visitBaseInterfaces(iface, bases)
00080         return [biface for biface in bases if biface not in ifaces ]
00081 
00082     def getInterfaceInformations(self, iface):
00083         """Gets all useful informations from an iface
00084 
00085         * name
00086         * dotted name
00087         * trimmed doc string
00088         * base interfaces
00089         * methods with signature and trimmed doc string
00090         * attributes with trimemd doc string
00091         """
00092         bases = [ base for base in iface.getBases() if base is not Interface ]
00093 
00094         attributes = []
00095         methods = []
00096         for name, desc in iface.namesAndDescriptions():
00097             if IMethod.isImplementedBy(desc):
00098                 methods.append({'signature' : desc.getSignatureString(),
00099                                 'name' : desc.getName(),
00100                                 'doc' : _trim_doc_string(desc.getDoc()),
00101                                })
00102             else:
00103                 attributes.append({'name' : desc.getName(),
00104                                    'doc' : _trim_doc_string(desc.getDoc()),
00105                                   })
00106 
00107         result = {
00108             'name' : iface.getName(),
00109             'dotted_name' : getDottedName(iface),
00110             'doc' : _trim_doc_string(desc.getDoc()),
00111             'bases' : bases,
00112             'base_names' : [getDottedName(iface) for base in bases ],
00113             'attributes' : attributes,
00114             'methods' : methods,
00115             }
00116 
00117         return result
00118 
00119 def resolveInterface(dotted_name):
00120     parts = dotted_name.split('.')
00121     m_name = '.'.join(parts[:-1])
00122     k_name = parts[-1]
00123     module = __import__(m_name, globals(), locals(), [k_name])
00124     klass = getattr(module, k_name)
00125     if not issubclass(klass, Interface):
00126         raise ValueError, '%r is not a valid Interface.' % dotted_name
00127     return klass
00128 
00129 def getDottedName(iface):
00130     return "%s.%s" % (iface.__module__, iface.__name__)
00131 
00132 def _trim_doc_string(text):
00133     """
00134     Trims a doc string to make it format
00135     correctly with structured text.
00136     """
00137     text = text.strip().replace('\r\n', '\n')
00138     lines = text.split('\n')
00139     nlines = [lines[0]]
00140     if len(lines) > 1:
00141         min_indent=None
00142         for line in lines[1:]:
00143             indent=len(line) - len(line.lstrip())
00144             if indent < min_indent or min_indent is None:
00145                 min_indent=indent
00146         for line in lines[1:]:
00147             nlines.append(line[min_indent:])
00148     return '\n'.join(nlines)
00149 
00150 def visitBaseInterfaces(iface, lst):
00151     bases = iface.getBases()
00152     for base in bases:
00153         if base is Interface or base in lst:
00154             return
00155         lst.append(base)
00156         visitBaseInterfaces(iface, lst)
00157 
00158 class InterfaceFinder:
00159 
00160     _visited = {}
00161     _found = {}
00162 
00163     def findInterfaces(self, n=None, module=_marker):
00164         # return class reference info
00165         dict={}
00166         pairs = []
00167         if module is _marker:
00168             import Products
00169             module = Products
00170         self._visited[module] = None
00171         for sym in dir(module):
00172             ob=getattr(module, sym)
00173             if type(ob) is type(Interface) and \
00174                issubclass(ob, Interface) and \
00175                ob is not Interface:
00176                 self.found(ob)
00177             elif type(ob) is ModuleType and ob not in self._visited.keys():
00178                 self.findInterfaces(module=ob)
00179 
00180         ifaces = self._found.keys()
00181         ifaces.sort()
00182         ifaces.reverse()
00183         if n is not None:
00184             ifaces = ifaces[:n]
00185         return ifaces
00186 
00187     def found(self, iface):
00188         self._found[getDottedName(iface)] = iface
00189 
00190 InitializeClass(InterfaceTool)
00191 registerToolInterface('portal_interface', IInterfaceTool)