[Zope3-checkins] CVS: Zope3/src/zope/app/apidoc/ifacemodule -
browser.py:1.5
Stephan Richter
srichter at cosmos.phy.tufts.edu
Sun Mar 28 18:40:37 EST 2004
Update of /cvs-repository/Zope3/src/zope/app/apidoc/ifacemodule
In directory cvs.zope.org:/tmp/cvs-serv22630/src/zope/app/apidoc/ifacemodule
Modified Files:
browser.py
Log Message:
Added tests.
Improve factory detection and URL computation.
Use new class registry to find a list of all classes that implement the
interface.
Fix factories finder.
Better utility info computation.
=== Zope3/src/zope/app/apidoc/ifacemodule/browser.py 1.4 => 1.5 ===
--- Zope3/src/zope/app/apidoc/ifacemodule/browser.py:1.4 Tue Mar 9 07:39:02 2004
+++ Zope3/src/zope/app/apidoc/ifacemodule/browser.py Sun Mar 28 18:40:36 2004
@@ -15,7 +15,7 @@
$Id$
"""
-
+from types import FunctionType, MethodType, ClassType, TypeType
from zope.component import ComponentLookupError
from zope.interface.declarations import providedBy
from zope.interface.interfaces import IMethod, IInterface
@@ -24,9 +24,32 @@
from zope.app import zapi
from zope.app.apidoc.utilities import getPythonPath, stx2html
+from zope.app.apidoc.classmodule import classRegistry
def _get(iface, type):
- """Return a dictionary containing all the Fields in a schema."""
+ """Return a dictionary containing all the attributes in an interface.
+
+ The type specifies whether we are looking for attributes or methods.
+
+ Example::
+
+ >>> from zope.interface import Interface, Attribute
+ >>> from zope.schema import Field
+
+ >>> class IFoo(Interface):
+ ... foo = Field()
+ ... bar = Field()
+ ... def blah():
+ ... pass
+
+ >>> _get(IFoo, IMethod).keys()
+ ['blah']
+
+ >>> names = _get(IFoo, IField).keys()
+ >>> names.sort()
+ >>> names
+ ['bar', 'foo']
+ """
iface = removeAllProxies(iface)
items = {}
for name in iface:
@@ -35,28 +58,103 @@
items[name] = attr
return items
+
def _getInOrder(iface, type,
_itemsorter=lambda x, y: cmp(x[1].order, y[1].order)):
- """Return a list of (name, value) tuples in native schema order."""
+ """Return a list of (name, value) tuples in native interface order.
+
+ The type specifies whether we are looking for attributes or methods. The
+ '_itemsorter' argument provides the function that is used to order the
+ fields. The default function should be the correct one for 99% of your
+ needs.
+
+ Example::
+
+ >>> from zope.interface import Interface, Attribute
+ >>> from zope.schema import Field
+
+ >>> class IFoo(Interface):
+ ... foo = Field()
+ ... bar = Field()
+ ... def blah():
+ ... pass
+
+ >>> [n for n, a in _getInOrder(IFoo, IMethod)]
+ ['blah']
+
+ >>> [n for n, a in _getInOrder(IFoo, IField)]
+ ['foo', 'bar']
+ """
items = _get(iface, type).items()
items.sort(_itemsorter)
return items
+
def _getFieldInterface(field):
- """Return PT-friendly dict about the field's interface."""
+ """Return PT-friendly dict about the field's interface.
+
+ Examples::
+
+ >>> import pprint
+ >>> from zope.interface import implements, Interface
+
+ >>> class IField(Interface):
+ ... pass
+ >>> class ISpecialField(IField):
+ ... pass
+ >>> class Field:
+ ... implements(IField)
+ >>> class SpecialField:
+ ... implements(ISpecialField)
+ >>> class ExtraField(SpecialField):
+ ... pass
+
+ >>> info = _getFieldInterface(Field()).items()
+ >>> info.sort()
+ >>> pprint.pprint(info)
+ [('id', 'zope.app.apidoc.ifacemodule.browser.IField'), ('name', 'IField')]
+
+ >>> info = _getFieldInterface(SpecialField()).items()
+ >>> info.sort()
+ >>> pprint.pprint(info)
+ [('id', 'zope.app.apidoc.ifacemodule.browser.ISpecialField'),
+ ('name', 'ISpecialField')]
+
+ >>> info = _getFieldInterface(ExtraField()).items()
+ >>> info.sort()
+ >>> pprint.pprint(info)
+ [('id', 'zope.app.apidoc.ifacemodule.browser.ISpecialField'),
+ ('name', 'ISpecialField')]
+ """
field = removeAllProxies(field)
# This is bad, but due to bootstrapping, directlyProvidedBy does
# not work
name = field.__class__.__name__
ifaces = list(providedBy(field))
+ # Usually fields have interfaces with the same name (with an 'I')
for iface in ifaces:
if iface.getName() == 'I' + name:
return {'name': iface.getName(), 'id': getPythonPath(iface)}
# Giving up...
return {'name': ifaces[0].getName(), 'id': getPythonPath(ifaces[0])}
+
def _getRequired(field):
- """Return a string representation of whether the field is required."""
+ """Return a string representation of whether the field is required.
+
+ Examples::
+
+ >>> class Field:
+ ... required = False
+
+ >>> field = Field()
+ >>> _getRequired(field)
+ 'optional'
+ >>> field.required = True
+ >>> _getRequired(field)
+ 'required'
+
+ """
if field.required:
return 'required'
else:
@@ -66,28 +164,69 @@
class InterfaceDetails(object):
"""View class for an Interface."""
- def __init__(self, context, request):
- self.context = context
- self.request = request
-
def getId(self):
- """Return the id of the field as it is defined in the interface
- service."""
+ """Return the id of the field as it is defined for the interface
+ utility.
+
+ Example::
+
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+ >>> details.getId()
+ 'IFoo'
+ """
return zapi.name(self.context)
def getDoc(self):
- """Return the main documentation string of the interface."""
+ """Return the main documentation string of the interface.
+
+ Example::
+
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+ >>> details.getDoc()[:34]
+ '<h1>This is the Foo interface</h1>'
+ """
return stx2html(self.context.getDoc())
def getBases(self):
- """Get all bases of this class"""
+ """Get all bases of this class
+
+ Example::
+
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+ >>> details.getBases()
+ ['zope.interface.Interface']
+ """
return [getPythonPath(base) for base in self.context.__bases__]
def getTypes(self):
"""Return a list of interface types that are specified for this
interface.
- Note that you should only expect one type at a time."""
+ Note that you should only expect one type at a time.
+
+ Example::
+
+ >>> import pprint
+ >>> pprint = pprint.PrettyPrinter(width=69).pprint
+ >>> from tests import getInterfaceDetails
+ >>> from zope.interface import Interface, directlyProvides
+ >>> class IType(Interface):
+ ... pass
+
+ >>> details = getInterfaceDetails()
+ >>> details.getTypes()
+ []
+
+ >>> directlyProvides(removeAllProxies(details.context), IType)
+ >>> type = details.getTypes()[0].items()
+ >>> type.sort()
+ >>> pprint(type)
+ [('name', 'IType'),
+ ('path', 'zope.app.apidoc.ifacemodule.browser.IType')]
+ """
context = removeAllProxies(self.context)
types = list(providedBy(context))
types.remove(IInterface)
@@ -96,7 +235,23 @@
for type in types]
def getAttributes(self):
- """Return a list of attributes in the order they were specified."""
+ r"""Return a list of attributes in the order they were specified.
+
+ Example::
+
+ >>> import pprint
+ >>> pprint = pprint.PrettyPrinter(width=69).pprint
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+
+ >>> attrs = details.getAttributes()
+ >>> attrs = [a.items() for a in attrs]
+ >>> attrs = [a for a in attrs if a.sort() is None]
+ >>> attrs.sort()
+ >>> pprint(attrs)
+ [[('doc', '<p>This is bar.</p>\n'), ('name', 'bar')],
+ [('doc', '<p>This is foo.</p>\n'), ('name', 'foo')]]
+ """
iface = removeAllProxies(self.context)
attrs = []
for name in iface:
@@ -108,7 +263,27 @@
for attr in attrs]
def getMethods(self):
- """Return a list of methods in the order they were specified."""
+ r"""Return a list of methods in the order they were specified.
+
+ Example::
+
+ >>> import pprint
+ >>> pprint = pprint.PrettyPrinter(width=69).pprint
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+
+ >>> methods = details.getMethods()
+ >>> methods = [m.items() for m in methods]
+ >>> methods = [m for m in methods if m.sort() is None]
+ >>> methods.sort()
+ >>> pprint(methods)
+ [[('doc', '<p>This is blah.</p>\n'),
+ ('name', 'blah'),
+ ('signature', '()')],
+ [('doc', '<p>This is get.</p>\n'),
+ ('name', 'get'),
+ ('signature', '(key, default=None)')]]
+ """
methods = []
return [{'name': method.getName(),
'signature': method.getSignatureString(),
@@ -116,61 +291,212 @@
for method in _get(self.context, IMethod).values()]
def getFields(self):
- """Return a list of fields in the order they were specified."""
+ """Return a list of fields in the order they were specified.
+
+ Example::
+
+ >>> import pprint
+ >>> pprint = pprint.PrettyPrinter(width=69).pprint
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+
+ >>> fields = details.getFields()
+
+ Convert all dictionaries to list of tuples and sort them.
+
+ >>> fields = [f.items() for f in fields]
+ >>> fields = [f for f in fields if f.sort() is None]
+ >>> fields = [f[:2] + [(f[2][0], f[2][1].items())] + f[3:]
+ ... for f in fields]
+ >>> fields = [f for f in fields if f[2][1].sort() is None]
+ >>> pprint(fields)
+ [[('default', "u'Foo'"),
+ ('description', u'Title'),
+ ('iface',
+ [('id', 'zope.schema.interfaces.ITextLine'),
+ ('name', 'ITextLine')]),
+ ('name', 'title'),
+ ('required', 'required')],
+ [('default', "u'Foo.'"),
+ ('description', u'Desc'),
+ ('iface',
+ [('id', 'zope.schema.interfaces.IText'), ('name', 'IText')]),
+ ('name', 'description'),
+ ('required', 'optional')]]
+ """
fields = map(lambda x: x[1], _getInOrder(self.context, IField))
return [{'name': field.getName(),
'iface': _getFieldInterface(field),
'required': _getRequired(field),
- 'default': field.default.__repr__,
+ 'default': field.default.__repr__(),
'description': field.description
}
for field in fields]
def getRequiredAdapters(self):
- """Get adapters where this interface is required."""
+ """Get adapters where this interface is required.
+
+ Example::
+
+ >>> import pprint
+ >>> pprint = pprint.PrettyPrinter(width=69).pprint
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+
+ >>> adapters = details.getRequiredAdapters()
+ >>> adapters = [a.items() for a in adapters]
+ >>> adapters = [a for a in adapters if a.sort() is None]
+ >>> adapters.sort()
+ >>> pprint(adapters)
+ [[('factory', 'zope.app.location.LocationPhysicallyLocatable'),
+ ('factory_url', 'zope/app/location/LocationPhysicallyLocatable'),
+ ('name', u''),
+ ('provided',
+ 'zope.app.traversing.interfaces.IPhysicallyLocatable'),
+ ('required', [])]]
+ """
service = zapi.getService(self.context, 'Adapters')
context = removeAllProxies(self.context)
adapters = []
for adapter in service.getRegisteredMatching(required=context):
+ path = getPythonPath(adapter[4])
+ if type(adapter[4]) in (FunctionType, MethodType):
+ url = None
+ else:
+ url = path.replace('.', '/')
adapters.append({
'provided': getPythonPath(adapter[1]),
'required': [getPythonPath(iface) for iface in adapter[2]],
'name': adapter[3],
- 'factory': getPythonPath(adapter[4][0])
+ 'factory': path,
+ 'factory_url': url
})
return adapters
def getProvidedAdapters(self):
- """Get adapters where this interface is provided."""
+ """Get adapters where this interface is provided.
+
+ Example::
+
+ >>> import pprint
+ >>> pprint = pprint.PrettyPrinter(width=69).pprint
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+
+ >>> adapters = details.getProvidedAdapters()
+ >>> adapters = [a.items() for a in adapters]
+ >>> adapters = [a for a in adapters if a.sort() is None]
+ >>> adapters.sort()
+ >>> pprint(adapters)
+ [[('factory', '__builtin__.object'),
+ ('factory_url', '__builtin__/object'),
+ ('name', u''),
+ ('required', ['zope.app.apidoc.ifacemodule.tests.IBar'])]]
+ """
service = zapi.getService(self.context, 'Adapters')
context = removeAllProxies(self.context)
adapters = []
for adapter in service.getRegisteredMatching(provided=context):
+ path = getPythonPath(adapter[4])
+ if type(adapter[4]) in (FunctionType, MethodType):
+ url = None
+ else:
+ url = path.replace('.', '/')
adapters.append({
'required': [getPythonPath(iface)
for iface in adapter[2]+(adapter[0],)],
'name': adapter[3],
- 'factory': getPythonPath(adapter[4][0])
+ 'factory': path,
+ 'factory_url': url
})
return adapters
+ def getClasses(self):
+ """Get the classes that implement this interface.
+
+ Example::
+
+ >>> import pprint
+ >>> pprint = pprint.PrettyPrinter(width=69).pprint
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+
+ >>> classes = details.getClasses()
+ >>> classes = [c.items() for c in classes]
+ >>> classes = [c for c in classes if c.sort() is None]
+ >>> classes.sort()
+ >>> pprint(classes)
+ [[('path', 'zope.app.apidoc.ifacemodule.tests.Foo'),
+ ('url', 'zope/app/apidoc/ifacemodule/tests/Foo')]]
+ """
+ iface = removeAllProxies(self.context)
+ classes = classRegistry.getClassesThatImplement(iface)
+ return [{'path': path, 'url': path.replace('.', '/')}
+ for path, klass in classes]
+
def getFactories(self):
"""Return the factories, who will provide objects implementing this
- interface."""
+ interface.
+
+ Example::
+
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+
+ >>> factories = details.getFactories()
+ >>> factories = [f.items() for f in factories]
+ >>> factories = [f for f in factories if f.sort() is None]
+ >>> factories.sort()
+ >>> factories
+ [[('name', 'FooFactory'), ('title', 'Foo Factory')]]
+ """
iface = removeAllProxies(self.context)
- return [{'name': n, 'factory': f, 'title': f.title} \
- for n, f in zapi.queryUtilitiesFor(IFactory, ()) \
- if ISource in tuple(f.getInterfaces)]
+ return [{'name': n, 'title': f.title} \
+ for n, f in zapi.getFactoriesFor(self.context, iface) \
+ if iface in tuple(f.getInterfaces())]
def getUtilities(self):
- """Return all utilities that provide this interface."""
+ """Return all utilities that provide this interface.
+
+ Example::
+
+ >>> import pprint
+ >>> pprint = pprint.PrettyPrinter(width=69).pprint
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+
+ >>> utils = details.getUtilities()
+ >>> utils = [u.items() for u in utils]
+ >>> utils = [u for u in utils if u.sort() is None]
+ >>> utils.sort()
+ >>> pprint(utils)
+ [[('name', 'The Foo'),
+ ('path', 'zope.app.apidoc.ifacemodule.tests.Foo'),
+ ('url', 'zope/app/apidoc/ifacemodule/tests/Foo')]]
+ """
service = zapi.getService(self.context, 'Utilities')
utils = service.getUtilitiesFor(removeAllProxies(self.context))
- return [{'name': util[0],
- 'path': getPythonPath(util[1].__class__)} for util in utils]
+ info = []
+ for name, util in utils:
+ if type(util) in (ClassType, TypeType):
+ klass = util
+ else:
+ klass = util.__class__
+ path = getPythonPath(klass)
+ info.append({'name': name, 'path': path,
+ 'url': path.replace('.', '/')})
+ return info
def getServices(self):
- """Return all services (at most one) that provide this interface."""
+ """Return all services (at most one) that provide this interface.
+
+ Example::
+
+ >>> from tests import getInterfaceDetails
+ >>> details = getInterfaceDetails()
+ >>> details.getServices()
+ ['Foo']
+ """
iface = removeAllProxies(self.context)
service = zapi.getService(self.context, 'Services')
services = service.getServiceDefinitions()
More information about the Zope3-Checkins
mailing list