[Zope3-checkins] CVS: Zope3/src/zope/app/introspector - __init__.py:1.1 browser.py:1.1 configure.zcml:1.1 interfaces.py:1.1 introspector.pt:1.1 marker.pt:1.1

Philipp von Weitershausen philikon at philikon.de
Mon Mar 1 05:18:21 EST 2004


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

Added Files:
	__init__.py browser.py configure.zcml interfaces.py 
	introspector.pt marker.pt 
Log Message:
Moved all introspector code, including interfaces and browser views, to
the zope.app.introspector package.


=== Added File Zope3/src/zope/app/introspector/__init__.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.
#
##############################################################################
"""Introspector

$Id: __init__.py,v 1.1 2004/03/01 10:18:20 philikon Exp $
"""
from zope.component import getService, getAdapter, getServiceDefinitions
from zope.proxy import removeAllProxies

from zope.interface import Interface, implements, implementedBy
from zope.interface import directlyProvides, directlyProvidedBy, providedBy
from zope.interface.interfaces import IInterface
from zope.interface.interface import InterfaceClass

from zope.app.interfaces.services.module import IModuleService
from zope.app.services.servicenames import Interfaces

from zope.app.introspector.interfaces import IIntrospector

class Introspector:
    """Introspects an object"""

    implements(IIntrospector)

    def __init__(self, context):
        self.context = context
        self.request = None
        self.currentclass = None

    def isInterface(self):
        "Checks if the context is class or interface"
        return IInterface.isImplementedBy(self.context)

    def setRequest(self, request):
        """sets the request"""
        self.request = request
        if 'PATH_INFO' in request:
            path = self.request['PATH_INFO']
        else:
            path = ''
        name = path[path.rfind('++module++') + len('++module++'):]
        name = name.split('/')[0]
        if path.find('++module++') != -1:
            if (self.context == Interface and
                name != 'Interface._Interface.Interface'):
                servicemanager = getServiceManager(self.context)
                adapter = getAdapter(servicemanager, IModuleService)
                self.currentclass = adapter.resolve(name)
                self.context = self.currentclass
            else:
                self.currentclass = self.context
        else:
            self.currentclass = self.context.__class__

    def _unpackTuple(self, tuple_obj):
        res = []
        for item in tuple_obj:
            if type(item)==tuple:
                res.extend(self._unpackTuple(item))
            else:
                res.append(item)
        return tuple(res)

    def getClass(self):
        """Returns the class name"""
        return removeAllProxies(self.currentclass).__name__

    def getBaseClassNames(self):
        """Returns the names of the classes"""
        bases = self.getExtends()
        base_names = []
        for base in bases:
            base_names.append(base.__module__+'.'+base.__name__)
        return base_names

    def getModule(self):
        """Returns the module name of the class"""
        return removeAllProxies(self.currentclass).__module__

    def getDocString(self):
        """Returns the description of the class"""
        return removeAllProxies(self.currentclass).__doc__

    def getInterfaces(self):
        """Returns interfaces implemented by this class"""
        return tuple(implementedBy(removeAllProxies(self.currentclass)))

    def getInterfaceNames(self, interfaces=None):
        if interfaces is None:
            interfaces = self.getInterfaces()
        names = []
        for intObj in interfaces:
            names.append(interfaceToName(self.context, intObj))
        names.sort()
        return names

    def getInterfaceDetails(self):
        """Returns the entire documentation in the interface"""
        interface = self.context
        Iname = interfaceToName(self.context, interface).split('.')[-1]
        bases = []
        desc = ''
        methods = []
        attributes = []
        if interface is not None:
            namesAndDescriptions = list(interface.namesAndDescriptions())
            namesAndDescriptions.sort()
            for name, desc in namesAndDescriptions:
                if hasattr(desc, 'getSignatureString'):
                    methods.append((desc.getName(),
                                    desc.getSignatureString(),
                                    desc.getDoc()))
                else:
                    attributes.append((desc.getName(), desc.getDoc()))

            for base in interface.__bases__:
                bases.append(base.__module__+'.'+base.__name__)
            desc = str(interface.getDoc())
        return [Iname, bases, desc, methods, attributes]

    def getExtends(self):
        """Returns all the class extended up to the top most level"""
        bases = self._unpackTuple(
            removeAllProxies(self.currentclass).__bases__)
        return bases

    def getInterfaceRegistration(self):
        """Returns details for a interface configuration"""
        service = []
        for name, interface in getServiceDefinitions(self.context):
            if self.context.extends(interface):
                service.append(str(name))
        return service

    def getDirectlyProvided(self):
        """See IIntrospector"""
        return directlyProvidedBy(removeAllProxies(self.context))

    def getDirectlyProvidedNames(self):
        """See IIntrospector"""
        return self.getInterfaceNames(self.getDirectlyProvided())

    def getMarkerInterfaceNames(self):
        """See IIntrospector"""
        result = list(self.getInterfaceNames(self.getMarkerInterfaces()))
        result.sort()
        return tuple(result)

    def getMarkerInterfaces(self):
        """See IIntrospector"""
        results = []
        todo = list(providedBy(removeAllProxies(self.context)))
        done = []

        while todo:
            interface = todo.pop()
            done.append(interface)
            for base in interface.__bases__:
                if base not in todo and base not in done:
                    todo.append(base)
            markers = self.getDirectMarkersOf(interface)
            for interface in markers:
                if (interface not in results
                    and not interface.isImplementedBy(self.context)):
                    results.append(interface)
            todo += markers
        results.sort()
        return tuple(results)

    def getDirectMarkersOf(self, base):
        """Returns empty interfaces directly inheriting from the given one"""
        results = []
        iservice = getService(self.context, Interfaces)
        for id, interface in iservice.items(base=base):
            # There are things registered with the interface service
            # that are not interfaces. Yay!
            if not IInterface.isImplementedBy(interface):
                continue
            if base in interface.__bases__ and not interface.names():
                results.append(interface)
        results.sort()
        return tuple(results)

def nameToInterface(context, name):
    if name == 'None':
        return None
    service = getService(context, Interfaces)
    iface = service.getInterface(name)
    return iface

def interfaceToName(context, interface):
    interface = removeAllProxies(interface)
    if interface is None:
        return 'None'
    service = getService(context, Interfaces)
    items = service.items(base=interface)
    ids = [id for id, iface in items
           if iface == interface]
    if not ids:
        # XXX Do not fail badly, instead resort to the standard
        # way of getting the interface name, cause not all interfaces
        # may be registered.
        return interface.__module__ + '.' + interface.getName()

    assert len(ids) == 1, "Ambiguous interface names: %s" % ids
    return ids[0]


=== Added File Zope3/src/zope/app/introspector/browser.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.
#
##############################################################################
"""Introspector View class

$Id: browser.py,v 1.1 2004/03/01 10:18:20 philikon Exp $
"""
from zope.proxy import removeAllProxies
from zope.interface import directlyProvides, directlyProvidedBy
from zope.component.exceptions import ComponentLookupError

from zope.app import zapi
from zope.app.publisher.browser import BrowserView
from zope.app.services.servicenames import Interfaces
from zope.app.introspector.interfaces import IIntrospector

class IntrospectorView(BrowserView):

    def getIntrospector(self):
        introspector = zapi.getAdapter(self.context, IIntrospector)
        introspector.setRequest(self.request)
        return introspector

    def getInterfaceURL(self, name):
        interfaces = zapi.getService(self.context, Interfaces)
        try:
            interfaces.getInterface(name)
            url = zapi.getView(interfaces, 'absolute_url', self.request)
            return "%s/detail.html?id=%s" % (url, name)
        except ComponentLookupError:
            return ""

    def update(self):
        if 'ADD' in self.request:
            for interface in self.getIntrospector().getMarkerInterfaceNames():
                if "add_%s" % interface in self.request:
                    interfaces = zapi.getService(self.context, Interfaces)
                    interface = interfaces.getInterface(interface)
                    ob = removeAllProxies(self.context)
                    directlyProvides(ob, directlyProvidedBy(ob), interface)

        if 'REMOVE' in self.request:
            for interface in self.getIntrospector().getDirectlyProvidedNames():
                if "rem_%s" % interface in self.request:
                    interfaces = zapi.getService(self.context, Interfaces)
                    interface = interfaces.getInterface(interface)
                    ob = removeAllProxies(self.context)
                    directlyProvides(ob, directlyProvidedBy(ob)-interface)

    def getServicesFor(self):
        services = []
        #sm = zapi.getServiceManager(self.context)
        #for stype, interface in sm.getServiceDefinitions():
        #    try:
        #        service = zapi.getService(self.context, stype)
        #    except ComponentLookupError:
        #        pass
        #    else:
        #        # XXX IConfigureFor appears to have disappeared at some point
        #        adapter = zapi.queryAdapter(service, IConfigureFor)
        #        if (adapter is not None
        #            and adapter.hasRegistrationFor(self.context)):
        #            search_result = service.getRegisteredMatching(
        #                self.context, None, [], self.context)
        #            directive_path = []
        #            if search_result:
        #                for eachitem in search_result:
        #                    dir_list = eachitem['directives']
        #                    component_path = eachitem['component_path']
        #                    for item in dir_list:
        #                        directives = item[2]
        #                        if directives:
        #                            if directives[0] is None:
        #                                directives = directives[1:]
        #                            for directive in directives:
        #                                for component in component_path:
        #                                    if component['component'] == directive:
        #                                        directive_path.append(component['path'])
        #            services.append({
        #                'type': stype,
        #                'service': service,
        #                'path': directive_path
        #                })
        return services


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

  <adapter
      for='*'
      factory="zope.app.introspector.Introspector"
      permission="zope.View"
      provides="zope.app.introspector.interfaces.IIntrospector"
      />


  <!-- Browser directives -->

  <!--browser:page
      name="classBrowser.html"
      for = "zope.interface.Interface"
      permission="zope.ManageServices"
      template="introspector.pt"
      class="zope.app.introspector.browser.IntrospectorView"
      menu="zmi_views" title="Introspector"
      /-->

  <browser:pages
      for="zope.interface.Interface"
      permission="zope.ManageServices"
      class="zope.app.introspector.browser.IntrospectorView"
      >

    <browser:page
        name="classBrowser.html"
        template="introspector.pt"
        menu="zmi_views" title="Introspector"
        />
    <browser:page
        name="objectMarker.html"
        template="marker.pt"
        />
  </browser:pages>

  <browser:page
      name="index.html"
      for="zope.interface.interfaces.IInterface"
      permission="zope.View"
      template="introspector.pt"
      class="zope.app.introspector.browser.IntrospectorView"
      />

</configure>


=== Added File Zope3/src/zope/app/introspector/interfaces.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.
#
##############################################################################
"""
$Id: interfaces.py,v 1.1 2004/03/01 10:18:20 philikon Exp $
"""
from zope.interface import Interface

class IIntrospector(Interface):
    """An interface for introspecting a component"""

    def isInterface():
        "Checks if the context is class or interface"

    def setRequest(request):
        """sets the request"""

    def getClass():
        """Returns the class name"""

    def getBaseClassNames():
        """Returns the names of the classes"""

    def getModule():
        """Returns the module name of the class"""

    def getDocString():
        """Returns the description of the class"""

    def getInterfaces():
        """Returns interfaces implemented by this class"""

    def getInterfaceNames():
        """Returns the names of the interfaces implemented by this class"""

    def getDirectlyProvided():
        """Returns interfaces directly implemented by an object"""

    def getDirectlyProvidedNames():
        """Returns the names of the interfaces directly implemented by
        an object"""

    def getInterfaceDetails():
        """Returns the entire documentation in the interface"""

    def getExtends():
        """Returns all the class extended up to the top most level"""

    def getInterfaceRegistration():
        """Returns details for a interface configuration"""

    def getMarkerInterfaces():
        """Returns a list of marker interfaces available for this object"""

    def getMarkerInterfaceNames():
        """Returns a list of names of marker interfaces available for this object"""


=== Added File Zope3/src/zope/app/introspector/introspector.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>

  <style type="text/css" metal:fill-slot="style_slot">
    .preclass {
      color : #000066;
      font-family : monospace;
      white-space : pre;
    }
    th.introspector {
      vertical-align: top;
    }
  </style>
</head>

<body>
<div metal:fill-slot="body">
  <tal:block
      tal:define="global introspector view/getIntrospector;
                  global services view/getServicesFor">

    <div tal:condition="python:introspector.isInterface()">

      <table tal:define="global interfacedata introspector/getInterfaceDetails">
        <tr>
          <th colspan="2" i18n:translate="">Interface Browser</th>
        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="interface-component">Interface></tal:span>:
            </th>
          <td tal:content="python:interfacedata[0]">Interface</td>
        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="class-bases">Bases</tal:span>:
          </th>
          <td>
            <div tal:repeat="interface python:interfacedata[1]">
              <a href=""
                 tal:attributes="href
                                 string: ++module++${repeat/interface/item}"
                 tal:content="repeat/interface/item">Interface</a>
            </div>
          </td>
        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="">Description</tal:span>:
          </th>
          <td>
            <!-- the start of all of these preclass spans are carefully
            spatially placed (in terms of whitespace), because they are
            "pre" formatted (i.e., whitespace matters within the span) -->
            <span class="preclass"
                  tal:content="python:interfacedata[2]">
                  Description</span>
          </td>
        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="class-attributes">Attributes</tal:span>:
          </th>
          <td>
            <div tal:repeat="attributes python:interfacedata[4]">
              <tal:block tal:define="details repeat/attributes/item">
                <strong tal:content="python:details[0]">
                  Atttribute Name</strong>
                <div class="preclass" tal:content="python:details[1]">
                  Attribute Description
                </div>
              </tal:block>
            </div>
          </td>
        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="class-methods">Methods</tal:span>:
          </th>
          <td>
            <div tal:repeat="methods python:interfacedata[3]">
              <tal:block tal:define="details repeat/methods/item">
                <strong tal:content="python:details[0]">
                  Method Name</strong>
                <strong tal:content="python:details[1]">
                   Signature</strong>
                <div class="preclass" tal:content="python:details[2]">
                   Method Description
                </div>
              </tal:block>
            </div>
          </td>
        </tr>
        
        <!-- this section is currently not available
        <tr>
          <th class="introspector">
            <tal:span i18n:translate="">Services</tal:span>:
          </th>
          <td>
            <div tal:repeat="servicedic services">
              <span tal:define="dic repeat/servicedic/item">
                <a tal:content="python:dic.keys()[0]"/>
              </span>
            </div>
          </td>
        </tr>
        -->
      </table>
    </div>

    <div tal:condition="python:not introspector.isInterface()">
    
      <table>
        <tr>
          <th colspan="2" i18n:translate="">Class Browser</th>
        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="class-component">Class</tal:span>:
          </th>
          <td><a tal:attributes="href 
                string: /++apidoc++/Class/index.html?path=${introspector/getModule}.${introspector/getClass}" 
                href="">
            <span tal:replace="introspector/getModule">Module</span
            >.<span tal:replace="introspector/getClass">Name</span></a></td>

        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="class-bases">Bases</tal:span>:
          </th>
          <td>
            <div tal:repeat="base introspector/getBaseClassNames">
              <a tal:attributes="href 
                string: /++apidoc++/Class/index.html?path=${repeat/base/item}" 
                href=""><span tal:replace="repeat/base/item" /></a>
            </div>
          </td>
        </tr>

        <tr>
          <th>
            <tal:span i18n:translate="">Description</tal:span>:
          </th>
          <td>
            <span class="preclass"
                    tal:content="introspector/getDocString">
                    Description</span>
          </td>
        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="">Interfaces from Class</tal:span>:
          </th>
          <td>
            <div tal:repeat="interface introspector/getInterfaceNames">
              <div tal:define="url string: /++apidoc++/Class/index.html?path=${interface}">
                <a href=""
                    tal:attributes="href url"
                    tal:content="interface"
                    tal:condition="url">Interface</a>
                  <span tal:condition="python: not url" 
                        tal:content="interface" />
              </div>
            </div>
          </td>
        </tr>

        <tr>
          <th class="introspector">
            <tal:span i18n:translate="">Interfaces from Object</tal:span>:
          </th>
          <td>
            <div tal:repeat="interface introspector/getDirectlyProvidedNames"
                  tal:condition="introspector/getDirectlyProvided">
              <div tal:define="url string: /++apidoc++/Class/index.html?path=${interface}">
                <a href=""
                    tal:attributes="href url"
                    tal:content="interface"
                    tal:condition="url">Interface</a>
                  <span tal:condition="python: not url"
                        tal:content="interface" />
              </div>
            </div>
            <form tal:attributes=" 
                      action string:${request/URL/-1}/@@objectMarker.html"
                  method="POST">
              <input type="submit" value="Modify" 
                     i18n:attributes="value modify-button"/>
            </form>
          </td>
        </tr>

      </table>
    </div>

  </tal:block>

</div>
</body>
</html>



=== Added File Zope3/src/zope/app/introspector/marker.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>

  <style type="text/css" metal:fill-slot="style_slot">
    .preclass {
        color : #000066;
        font-family : monospace;
        white-space : pre;
        }
    th.introspector {
        vertical-align: top;
        }
  </style>
</head>

<body>
<div metal:fill-slot="body">
  <tal:block
      tal:define ="global introspector view/getIntrospector;
                   global services view/getServicesFor;
                   global status view/update">

  <form action="" tal:attributes="action request/URL" method="POST">

    <table>
      <tr>
        <th colspan="2" i18n:translate="">Class Browser</th>
      </tr>

      <tr>
        <th class="introspector">
          <span tal:omit-tag="" i18n:translate="class-component">Class</span>:
        </th>
        <td><span tal:content="introspector/getClass">Name</span></td>
      </tr>

      <tr>
        <th class="introspector">
          <span omit-tag="" i18n:translate="class-bases">Bases</span>:
        </th>
        <td>
          <div tal:repeat="base introspector/getBaseClassNames">
            <span tal:replace="repeat/base/item" />
              <!--
              <a href=""
                  tal:attributes="href
                      string: ++module++${repeat/base/item}"
                  tal:content="repeat/base/item">Base</a>
               -->
          </div>
        </td>
      </tr>

      <tr>
        <th class="introspector">
          <span tal:omit-tag="" i18n:translate="python-module">Module</span>:
        </th>
        <td><span tal:content="introspector/getModule">Module</span></td>
      </tr>

      <tr>
        <th>
          <span tal:omit-tag="" i18n:translate="">Description</span>:
        </th>
        <td>
          <span class="preclass"
              tal:content="introspector/getDocString">
            Description</span>
        </td>
      </tr>

      <tr>
        <th class="introspector">
          <span tal:omit-tag="" i18n:translate="">Interfaces from Class</span>:
        </th>
        <td>
          <div tal:repeat="interface introspector/getInterfaceNames">
            <div tal:define="url python: view.getInterfaceURL(interface)">
              <a href=""
                 tal:attributes="href url"
                 tal:content="interface"
                 tal:condition="url">Interface</a>
              <span tal:condition="python: not url"
                    tal:content="interface" />
            </div>
          </div>
        </td>
      </tr>

      <tr tal:condition="introspector/getDirectlyProvided">
        <th class="introspector">
          <span tal:omit-tag="" i18n:translate="">Interfaces from Object</span>:
        </th>
        <td>
          <div tal:repeat="interface introspector/getDirectlyProvidedNames">
            <div tal:define="url python: view.getInterfaceURL(interface)">
              <a href=""
                  tal:attributes="href url"
                  tal:content="interface"
                  tal:condition="url">Interface</a>
                <span tal:condition="python: not url"
                    tal:content="interface" />
            </div>
          </div>
        </td>
      </tr>
    
      <tr tal:condition="introspector/getDirectlyProvided">
        <th class="introspector" i18n:translate="">Remove Interfaces:</th>
        <td>
          <div tal:repeat="interface introspector/getDirectlyProvidedNames">
            <label>
              <input type="checkbox"
                  tal:attributes="name string:rem_${interface}"/>
              <span tal:replace="interface" />
            </label>
          </div>
          <input type="submit" name="REMOVE" value="Remove" 
              i18n:attributes="value remove-button"/>
        </td>
      </tr>
    
      <tr tal:condition="introspector/getMarkerInterfaceNames">
        <th class="introspector" i18n:translate="">Add Interfaces:</th>
        <td>
          <div tal:repeat="interface introspector/getMarkerInterfaceNames">
            <label>
              <input type="checkbox"
                  tal:attributes="name string:add_${interface}"/>
              <span tal:replace="interface" />
            </label>
          </div>
          <input type="submit" name="ADD" value="Add" 
              i18n:attributes="value add-button"/>
        </td>
      </tr>
    
    </table>
  </form>

  </tal:block>

</div>
</body>
</html>





More information about the Zope3-Checkins mailing list