A providers index indexes the interfaces provided by objects. The index can then be queried by a specification to retrieve the objects providing that specification.
Create an interface for object to provide:
>>> from zope import interface
>>> import zope.component.interface
>>> class IFoo(interface.Interface): pass
>>> zope.component.interface.provideInterface('', IFoo)
Create an object to index:
>>> from zope import component
>>> import zope.app.intid.interfaces
>>> class Content(object):
... def __init__(self, id): self.id = id
>>> foo = Content('foo')
>>> intids = component.getUtility(
... zope.app.intid.interfaces.IIntIds)
>>> foo_intid = intids.register(foo)
Before the object is indexed, the providers index is empty:
>>> from grouparchy.index.provider import interfaces >>> providers = component.getUtility(interfaces.IProvidersIndex) >>> providers.documentCount() 0 >>> providers.wordCount() 0
Index the object:
>>> providers.index_doc(foo_intid, foo) >>> providers.documentCount() 1
zope.interface.Interface is always included:
>>> providers.wordCount() 1
The index is queried with a zope.interface.Declaration:
>>> (foo_intid, ) == tuple(providers.apply( ... interface.Declaration(interface.Interface))) True
Before the object provides an interface, querying on that interface returns an empty set:
>>> len(providers.apply(interface.Declaration(IFoo))) 0
Apply an interface to the object:
>>> import grouparchy.schema.interface >>> foo_provided = ( ... grouparchy.schema.interface.IDirectlyProvided(foo)) >>> foo_provided.directlyProvided = (IFoo,)
Events update the index when changes are made:
>>> providers.wordCount() 2 >>> (foo_intid, ) == tuple( ... providers.apply(interface.Declaration(IFoo))) True
Index another object providing the interface:
>>> bar = Content('bar')
>>> bar_intid = intids.register(bar)
>>> bar_provided = (
... grouparchy.schema.interface.IDirectlyProvided(bar))
>>> bar_provided.directlyProvided = (IFoo,)
>>> providers.index_doc(bar_intid, bar)
>>> providers.documentCount()
2
>>> providers.wordCount()
2
>>> sorted([foo_intid, bar_intid]) == sorted(
... providers.apply(interface.Declaration(IFoo)))
True
The index is updated if objects no longer provide the interface:
>>> foo_provided.directlyProvided = () >>> providers.wordCount() 2 >>> (bar_intid, ) == tuple( ... providers.apply(interface.Declaration(IFoo))) True >>> bar_provided.directlyProvided = () >>> providers.wordCount() 1 >>> len(providers.apply(interface.Declaration(IFoo))) 0
A set also includes objects that provide interfaces that extend the interface:
>>> class IFooFoo(IFoo): pass
>>> zope.component.interface.provideInterface('', IFooFoo)
>>> foo_provided.directlyProvided = (IFooFoo,)
>>> providers.wordCount()
3
>>> (foo_intid, ) == tuple(providers.apply(interface.Declaration(IFoo)))
True
IProviders returns a set which only contains a qualifying provider once if it has multiple declarations which provide the interface:
>>> foo_provided.directlyProvided = (IFoo, IFooFoo) >>> (foo_intid, ) == tuple(providers.apply(interface.Declaration(IFoo))) True
The interfaces implemented by a class behave similarly as long as the events are triggered when changes are made.
Make a new interface that the class implements:
>>> class IBar(interface.Interface): pass >>> interface.classImplements(Content, IBar)
Before the event is notified, the index doesn't include the class interfaces:
>>> providers.wordCount() 3 >>> len(providers.apply(interface.Declaration(IBar))) 0
Notify the event:
>>> from zope import event >>> event.notify( ... grouparchy.schema.interface.InterfacesAdded( ... context=foo, ... added=interface.Declaration(IBar)))
Now the index includes the class interfaces:
>>> providers.wordCount() 4 >>> (foo_intid, ) == tuple( ... providers.apply(interface.Declaration(IBar))) True
Similarly, if a class no longer implements an interface, the interfaces included in the index are only removed when the event is triggered.
Remove the interface implemented by the class:
>>> interface.classImplementsOnly(Content)
Before the event is notified, the index doesn't include the class interfaces:
>>> providers.wordCount() 4 >>> (foo_intid, ) == tuple( ... providers.apply(interface.Declaration(IBar))) True
Notify the event:
>>> event.notify( ... grouparchy.schema.interface.InterfacesRemoved( ... context=foo, ... removed=interface.Declaration(IBar)))
Now the index is updated:
>>> providers.wordCount() 3 >>> len(providers.apply(interface.Declaration(IBar))) 0