[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