==============================
Component Inspection Utilities
==============================

Once you have an interface, you really want to discover on how this interface
interacts with other components in Zope 3. The functions in

  >>> from zope.app.apidoc import component
 
provide you with utilities to make those discoveries. The functions are
explained in detail in this document. Before we start though, we have to have
some interfaces to work with:

  >>> from zope.interface import Interface
  >>> class IFoo(Interface):
  ...     pass

  >>> class IBar(Interface):
  ...     pass

  >>> class IFooBar(IFoo, IBar):
  ...     pass

  >>> class IResult(Interface):
  ...     pass

  >>> class ISpecialResult(IResult):
  ...     pass


`getRequiredAdapters(iface, withViews=False)`
---------------------------------------------

This function returns adapter registrations for adapters that require the
specified interface. So let's create some adapter registrations:

  >>> from zope.publisher.interfaces import IRequest
  >>> from zope.app.testing import ztapi
  >>> ztapi.provideAdapter((IFoo,), IResult, None)
  >>> ztapi.provideAdapter((IFoo, IBar), ISpecialResult, None)
  >>> ztapi.provideAdapter((IFoo, IRequest), ISpecialResult, None)
  >>> ztapi.subscribe((IFoo,), None, 'stubFactory')

  >>> regs = list(component.getRequiredAdapters(IFoo))
  >>> regs.sort()
  >>> regs
  [AdapterRegistration(('IFoo', 'IBar'), 'ISpecialResult', '', None, ''), 
   AdapterRegistration(('IFoo',), 'IResult', '', None, ''),
   SubscriptionRegistration(('IFoo',), None, 'stubFactory', '')]

Note how the adapter requiring an `IRequest` at the end of the required
interfaces is neglected. This is because it is recognized as a view and views
are not returned by default. But you can simply turn this flag on:

  >>> regs = list(component.getRequiredAdapters(IFoo, withViews=True))
  >>> regs.sort()
  >>> regs
  [AdapterRegistration(('IFoo', 'IBar'), 'ISpecialResult', '', None, ''), 
   AdapterRegistration(('IFoo', 'IRequest'), 'ISpecialResult', '', None, ''), 
   AdapterRegistration(('IFoo',), 'IResult', '', None, ''),
   SubscriptionRegistration(('IFoo',), None, 'stubFactory', '')]

The function will also pick up registrations that have required interfaces the
specified interface extends:

  >>> regs = list(component.getRequiredAdapters(IFoo))
  >>> regs.sort()
  >>> regs
  [AdapterRegistration(('IFoo', 'IBar'), 'ISpecialResult', '', None, ''), 
   AdapterRegistration(('IFoo',), 'IResult', '', None, ''),
   SubscriptionRegistration(('IFoo',), None, 'stubFactory', '')]

And all of the required interfaces are considered, of course:

  >>> regs = list(component.getRequiredAdapters(IBar))
  >>> regs.sort()
  >>> regs
  [AdapterRegistration(('IFoo', 'IBar'), 'ISpecialResult', '', None, '')]


`getProvidedAdapters(iface, withViews=False)`
---------------------------------------------

Of course, we are also interested in the adapters that provide a certain
interface. This function returns those adapter registrations, again ignoring
views by default.

  >>> regs = list(component.getProvidedAdapters(ISpecialResult))
  >>> regs.sort()
  >>> regs
  [AdapterRegistration(('IFoo', 'IBar'), 'ISpecialResult', '', None, '')]

And by specifying the `withView` flag, we get views as well:

  >>> regs = list(component.getProvidedAdapters(ISpecialResult, withViews=True))
  >>> regs.sort()
  >>> regs
  [AdapterRegistration(('IFoo', 'IBar'), 'ISpecialResult', '', None, ''),
   AdapterRegistration(('IFoo', 'IRequest'), 'ISpecialResult', '', None, '')]

We can of course also ask for adapters specifying `IResult`:

  >>> regs = list(component.getProvidedAdapters(IResult, withViews=True))
  >>> regs.sort()
  >>> regs
  [AdapterRegistration(('IFoo', 'IBar'), 'ISpecialResult', '', None, ''),
   AdapterRegistration(('IFoo', 'IRequest'), 'ISpecialResult', '', None, ''),
   AdapterRegistration(('IFoo',), 'IResult', '', None, '')]


`getClasses(iface)`
-------------------

This package comes with a little tool called the class registry
(see `classregistry.txt`). It provides a dictionary of all classes in the
visible packages. This function utilizes the registry to retrieve all classes
that implement the specified interface.

Let's start by creating and registering some classes:

  >>> from zope.interface import implements
  >>> from zope.app.apidoc.classregistry import classRegistry

  >>> class MyFoo(object):
  ...     implements(IFoo)
  >>> classRegistry['MyFoo'] = MyFoo

  >>> class MyBar(object):
  ...     implements(IBar)
  >>> classRegistry['MyBar'] = MyBar

  >>> class MyFooBar(object):
  ...     implements(IFooBar)
  >>> classRegistry['MyFooBar'] = MyFooBar

Let's now see whether what results we get:

  >>> classes = component.getClasses(IFooBar)
  >>> classes.sort()
  >>> classes
  [('MyFooBar', <class 'MyFooBar'>)]

  >>> classes = component.getClasses(IFoo)
  >>> classes.sort()
  >>> classes
  [('MyFoo', <class 'MyFoo'>), ('MyFooBar', <class 'MyFooBar'>)]


`getFactories(ifaces)`
----------------------

Return the factory registrations of the factories that will return objects
providing this interface.

Again, the first step is to create some factories:

  >>> from zope.component.factory import Factory
  >>> from zope.component.interfaces import IFactory
  >>> ztapi.provideUtility(IFactory, Factory(MyFoo), 'MyFoo')
  >>> ztapi.provideUtility(IFactory, Factory(MyBar), 'MyBar')
  >>> ztapi.provideUtility(IFactory, 
  ...     Factory(MyFooBar, 'MyFooBar', 'My Foo Bar'), 'MyFooBar')

Let's see whether we will be able to get them:

  >>> regs = list(component.getFactories(IFooBar))
  >>> regs.sort()
  >>> regs
  [UtilityRegistration('IFactory', 'MyFooBar', 
                       <Factory for <class 'MyFooBar'>>, '')]

  >>> regs = list(component.getFactories(IFoo))
  >>> regs.sort()
  >>> regs
  [UtilityRegistration('IFactory', 'MyFoo', 
                       <Factory for <class 'MyFoo'>>, ''),
   UtilityRegistration('IFactory', 'MyFooBar', 
                       <Factory for <class 'MyFooBar'>>, '')]


`getUtilities(iface)`
---------------------

Return all utility registrations for utilities that provide the specified
interface.

As usual, we have to register some utilities first:

  >>> ztapi.provideUtility(IFoo, MyFoo())
  >>> ztapi.provideUtility(IBar, MyBar())
  >>> ztapi.provideUtility(IFooBar, MyFooBar())

Now let's have a look what we have:

  >>> regs = list(component.getUtilities(IFooBar))
  >>> regs.sort()
  >>> regs #doctest:+ELLIPSIS
  [UtilityRegistration('IFooBar', '', <MyFooBar object at ...>, '')]

  >>> regs = list(component.getUtilities(IFoo))
  >>> regs.sort()
  >>> regs #doctest:+ELLIPSIS
  [UtilityRegistration('IFoo', '', <MyFoo object at ...>, ''), 
   UtilityRegistration('IFooBar', '', <MyFooBar object at ...>, '')]


`getInterfaceInfoDictionary(iface)`
-----------------------------------

This function returns a small info dictionary for an interface. It only
reports the module and the name. This is useful for cases when we only want to
list interfaces in the context of other components, like adapters and
utilities.

  >>> pprint(component.getInterfaceInfoDictionary(IFoo))
  {'module': '__builtin__', 'name': 'IFoo'}

The functions using this function use it with little care and can also
sometimes pass in `None`. In these cases we want to return `None`:

  >>> component.getInterfaceInfoDictionary(None) is None
  True


`getAdapterInfoDictionary(reg)`
-------------------------------

This function returns a page-template-friendly dictionary representing the
data of an adapter registration in an output-friendly format.

Let's first create an adapter registration:

  >>> class MyResult(object):
  ...     implements(IResult)

  >>> from zope.component.site import AdapterRegistration
  >>> reg = AdapterRegistration((IFoo, IBar), IResult, 'FooToResult',
  ...                            MyResult, 'doc info')

And now get the info dictionary:

  >>> pprint(component.getAdapterInfoDictionary(reg))
  {'doc': 'doc info',
   'factory': '__builtin__.MyResult',
   'factory_url': '__builtin__/MyResult',
   'name': 'FooToResult',
   'provided': {'module': '__builtin__', 'name': 'IResult'},
   'required': [{'module': '__builtin__', 'name': 'IFoo'},
                {'module': '__builtin__', 'name': 'IBar'}],
   'zcml': None}

This function can also handle subscription registrations, which are pretty
much like adapter registrations, except that they do not have name. So let's
see how the function handles subscriptions:

  >>> from zope.component.site import SubscriptionRegistration
  >>> reg = SubscriptionRegistration((IFoo, IBar), None, MyResult, 'doc info')

  >>> pprint(component.getAdapterInfoDictionary(reg))
  {'doc': 'doc info',
   'factory': '__builtin__.MyResult',
   'factory_url': '__builtin__/MyResult',
   'name': '<subscription>',
   'provided': None,
   'required': [{'module': '__builtin__', 'name': 'IFoo'},
                {'module': '__builtin__', 'name': 'IBar'}],
   'zcml': None}


`getFactoryInfoDictionary(reg)`
-------------------------------

This function returns a page-template-friendly dictionary representing the
data of a factory (utility) registration in an output-friendly format.

Luckily we have already registered some factories, so we just reuse their
registrations:

  >>> pprint(component.getFactoryInfoDictionary(
  ...     component.getFactories(IFooBar).next()))
  {'description': u'<div class="document">\nMy Foo Bar</div>\n',
   'name': 'MyFooBar',
   'title': 'MyFooBar',
   'url': '__builtin__/MyFooBar'}


`getUtilityInfoDictionary(name, factory)`
-----------------------------------------

This function returns a page-template-friendly dictionary representing the
data of a utility registration in an output-friendly format.

Luckily we have already registered some utilities, so we just reuse their
registrations:

  >>> pprint(component.getUtilityInfoDictionary(
  ...     component.getUtilities(IFooBar).next()))
  {'name': '<i>no name</i>',
   'path': '__builtin__.MyFooBar',
   'url': '__builtin__/MyFooBar',
   'url_name': '__noname__'}