============================== Interface Inspection Utilities ============================== This document is a presentation of the utility functions provided by >>> from zope.app.apidoc import interface For the following demonstrations, we need a nice interface that we can inspect: >>> from zope.interface import Interface, Attribute >>> from zope.schema import Field, TextLine >>> class IFoo(Interface): ... foo = Field(title=u"Foo") ... ... bar = TextLine(title=u"Bar", ... description=u"The Bar", ... required=True, ... default=u"My Bar") ... ... baz = Attribute('baz', ... 'This is the baz attribute') ... ... def blah(one, two, three=None, *args, **kwargs): ... """This is the `blah` method.""" `getElements(iface, type=IElement)` ----------------------------------- Return a dictionary containing all elements in an interface. The type specifies whether we are looking for attributes, fields or methods. So let's look at an example. First, let's get the methods of an interface: >>> from zope.interface.interfaces import IMethod >>> interface.getElements(IFoo, type=IMethod).keys() ['blah'] and now the fields: >>> from zope.schema.interfaces import IField >>> names = interface.getElements(IFoo, type=IField).keys() >>> names.sort() >>> names ['bar', 'foo'] We can also get all attributes of course. >>> from zope.interface.interfaces import IAttribute >>> names = interface.getElements(IFoo, type=IAttribute).keys() >>> names.sort() >>> names ['bar', 'baz', 'blah', 'foo'] You might be surprised by the above result, since the fields and methods are again included. However, fields and methods are just attributes and thus extend the simple attribute implementation. If you want to get a list of attributes that does not include fields and methods, see the `getAttributes(iface)` function. The default type is `IElement` which will simply return all elements of the interface: >>> names = interface.getElements(IFoo).keys() >>> names.sort() >>> names ['bar', 'baz', 'blah', 'foo'] Note: The interface you pass to this function *cannot* be proxied! Presentation code often like to wrap interfaces in security proxies and apidoc even uses location proxies for interface. `getFieldsInOrder(iface, _itemsorter=...)` ----------------------------------------------------------- For presentation purposes we often want fields to have the a certain order, most comonly the order they have in the interface. This function returns a list of (name, field) tuples in a specified order. The `_itemsorter` argument provides the function that is used to order the fields. The default function, which sorts by the fields' `order` attribute, should be the correct one for 99% of your needs. Reusing the interface created above, we check the output: >>> [n for n, a in interface.getFieldsInOrder(IFoo)] ['foo', 'bar'] By changing the sort method to sort by names, we get: >>> [n for n, a in interface.getFieldsInOrder( ... IFoo, _itemsorter=lambda x, y: cmp(x[0], y[0]))] ['bar', 'foo'] `getAttributes(iface)` ---------------------- This function returns a (name, attr) tuple for every attribute in the interface. Note that this function will only return pure attributes; it ignores methods and fields. >>> attrs = interface.getAttributes(IFoo) >>> attrs.sort() >>> attrs #doctest: +ELLIPSIS [('baz', )] `getMethods(iface)` ------------------- This function returns a (name, method) tuple for every declared method in the interface. >>> methods = interface.getMethods(IFoo) >>> methods.sort() >>> methods #doctest: +ELLIPSIS [('blah', )] `getFields(iface)` ------------------ This function returns a (name, field) tuple for every declared field in the interface. >>> interface.getFields(IFoo) #doctest: +ELLIPSIS [('foo', ), ('bar', )] Note that this returns the same result as `getFieldsInOrder()` with the fields sorted by their `order` attribute, except that you cannot specify the sort function here. This function was mainly provided for symmetry with the other functions. `getInterfaceTypes(iface)` -------------------------- Interfaces can be categorized/grouped by using interface types. Interface types simply extend `zope.interface.interfaces.IInterface`, which are basically meta-interfaces. The interface types are then provided by particular interfaces. The `getInterfaceTypes()` function returns a list of interface types that are provided for the specified interface. Note that you commonly expect only one type per interface, though. Before we assign any type to our `IFoo` interface, there are no types declared. >>> interface.getInterfaceTypes(IFoo) [] Now we define a new type called `IContentType` >>> from zope.interface.interfaces import IInterface >>> class IContentType(IInterface): ... pass and have our interface provide it: >>> from zope.interface import directlyProvides >>> directlyProvides(IFoo, IContentType) Note that ZCML has some more convenient methods of doing this. Now let's get the interface types again: >>> interface.getInterfaceTypes(IFoo) [] Again note that the interface passed to this function *cannot* be proxied, otherwise this method will pick up the proxy's interfaces as well. `getFieldInterface(field)` -------------------------- This function tries pretty hard to determine the best-matching interface that represents the field. Commonly the field class has the same name as the field interface (minus an "I"). So this is our first choice: >>> from zope.schema import Text, Int >>> interface.getFieldInterface(Text()) >>> interface.getFieldInterface(Int()) If the name matching method fails, it picks the first interface that extends `IField`: >>> from zope.schema.interfaces import IField >>> class ISpecialField(IField): ... pass >>> class ISomething(Interface): ... pass >>> from zope.interface import implements >>> class MyField: ... implements(ISomething, ISpecialField) >>> interface.getFieldInterface(MyField()) `getAttributeInfoDictionary(attr, format='restructuredtext')` ------------------------------------------------------------- This function returns a page-template-friendly dictionary for a simple attribute: >>> pprint(interface.getAttributeInfoDictionary(IFoo['baz'])) {'doc': u'

This is the baz attribute

\n', 'name': 'baz'} `getMethodInfoDictionary(method, format='restructuredtext')` ------------------------------------------------------------- This function returns a page-template-friendly dictionary for a method: >>> pprint(interface.getMethodInfoDictionary(IFoo['blah'])) #doc {'doc': u'

This is the blah method.

\n', 'name': 'blah', 'signature': '(one, two, three=None, *args, **kwargs)'} `getFieldInfoDictionary(field, format='restructuredtext')` ---------------------------------------------------------- This function returns a page-template-friendly dictionary for a field: >>> pprint(interface.getFieldInfoDictionary(IFoo['bar'])) {'class': {'name': 'TextLine', 'path': 'zope/schema/_bootstrapfields/TextLine'}, 'default': "u'My Bar'", 'description': u'

The Bar

\n', 'iface': {'id': 'zope.schema.interfaces.ITextLine', 'name': 'ITextLine'}, 'name': 'bar', 'required': True, 'required_string': u'required', 'title': u'Bar'}