Source code for zope.app.apidoc.interface

##############################################################################
#
# Copyright (c) 2004 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (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 Inspection Utilities

"""
__docformat__ = 'restructuredtext'

import inspect

from zope.interface import Interface, providedBy
from zope.interface.interfaces import IInterface, ISpecification
from zope.interface.interfaces import IElement, IAttribute, IMethod
from zope.schema.interfaces import IField

from zope.app.apidoc.utilities import getPythonPath, renderText, getDocFormat


[docs]def getElements(iface, type=IElement): """Return a dictionary containing the elements in an interface. The type specifies whether we are looking for attributes or methods.""" items = {} for name in iface: attr = iface[name] if type.providedBy(attr): items[name] = attr return items
[docs]def getFieldsInOrder(iface, _itemkey=lambda x: x[1].order): """Return a list of (name, field) tuples in native interface order.""" items = sorted(getElements(iface, IField).items(), key=_itemkey) return items
[docs]def getAttributes(iface): """Returns a list of attributes specified in the interface.""" return [(name, attr) for name, attr in getElements(iface, IAttribute).items() if not (IField.providedBy(attr) or IMethod.providedBy(attr))]
[docs]def getMethods(iface): """Returns a list of methods specified in the interface.""" return getElements(iface, IMethod).items()
[docs]def getFields(iface): """Returns a list of fields specified in the interface.""" return getFieldsInOrder(iface)
[docs]def getInterfaceTypes(iface): """Return a list of interface types that are specified for this interface. Note that you should only expect one type at a time. """ types = list(providedBy(iface).flattened()) # Remove interfaces provided by every interface instance types.remove(ISpecification) types.remove(IElement) types.remove(Interface) # Remove interface provided by every interface type types.remove(IInterface) return types
[docs]def getFieldInterface(field): """Return the interface representing the field.""" name = field.__class__.__name__ field_iface = None ifaces = tuple(providedBy(field).flattened()) for iface in ifaces: # All field interfaces implement `IField`. In case the name match # below does not work, use the first `IField`-based interface found if field_iface is None and iface.extends(IField): field_iface = iface # Usually fields have interfaces with the same name (with an 'I') if iface.getName() == 'I' + name: return iface # If not even a `IField`-based interface was found, return the first # interface of the implemented interfaces list. return field_iface or ifaces[0]
def _getDocFormat(attr): module = inspect.getmodule(attr.interface) return getDocFormat(module)
[docs]def getAttributeInfoDictionary(attr, format=None): """Return a page-template-friendly information dictionary.""" format = format or _getDocFormat(attr) return {'name': attr.getName(), 'doc': renderText(attr.getDoc() or u'', format=format)}
[docs]def getMethodInfoDictionary(method, format=None): """Return a page-template-friendly information dictionary.""" format = format or _getDocFormat(method) return {'name': method.getName(), 'signature': method.getSignatureString(), 'doc': renderText(method.getDoc() or u'', format=format)}
[docs]def getFieldInfoDictionary(field, format=None): """Return a page-template-friendly information dictionary.""" format = format or _getDocFormat(field) info = {'name': field.getName(), 'required': field.required, 'required_string': field.required and u'required' or u'optional', 'default': repr(field.default), 'title': field.title} # Determine the interface of the field iface = getFieldInterface(field) info['iface'] = {'name': iface.getName(), 'id': getPythonPath(iface)} # Determine the field class class_ = field.__class__ info['class'] = {'name': class_.__name__, 'path': getPythonPath(class_).replace('.', '/')} # Render the field description info['description'] = renderText(field.description or u'', format=format) return info