Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
zope.interface / docs / _build / doctrees / adapter.doctree
Size: Mime:
€cdocutils.nodes
document
q)q}q(UtagnameqUdocumentqUreporterqNU
attributesq}q(Udupnamesq	]Ubackrefsq
]UsourceX>/home/tseaver/projects/Zope/Z3/zope.interface/docs/adapter.rstqUidsq]Uclassesq
]Unamesq]uUparse_messagesq]qcdocutils.nodes
system_message
q)q}q(hhhUsystem_messageqh}q(h	]h
]qUid1qaUlineMªh
]h]UlevelKUsourcehh]UtypeUINFOquUlineqMªUsourceqhU	rawsourceqUUparentqcdocutils.nodes
section
q)q}q(hhhUsectionq h}q!(h
]h	]q"Xdefault adaptersq#ah]h]q$hah
]uhMªhhhUhh)q%}q&(hhhh h}q'(h
]h	]h]q(Xmulti-adaptersq)ah]q*Umulti-adaptersq+ah
]uhMahhhUhh)q,}q-(hhhh h}q.(h
]h	]h]q/Xadapter registryq0ah]q1Uadapter-registryq2ah
]uhKhhhUhhUchildrenq3]q4(cdocutils.nodes
title
q5)q6}q7(hhhUtitleq8h}q9(h
]h	]h]h]h
]uhKhhhXAdapter Registryq:hh,h3]q;cdocutils.nodes
Text
q<XAdapter Registryq=…q>}q?(hh:hh6ubaubcdocutils.nodes
paragraph
q@)qA}qB(hhhU	paragraphqCh}qD(h
]h	]h]h]h
]uhKhhhXAdapter registries provide a way to register objects that depend on
one or more interface specifications and provide (perhaps indirectly)
some interface.  In addition, the registrations have names. (You can
think of the names as qualifiers of the provided interfaces.)qEhh,h3]qFh<XAdapter registries provide a way to register objects that depend on
one or more interface specifications and provide (perhaps indirectly)
some interface.  In addition, the registrations have names. (You can
think of the names as qualifiers of the provided interfaces.)qG…qH}qI(hhEhhAubaubh@)qJ}qK(hhhhCh}qL(h
]h	]h]h]h
]uhK
hhhX–The term "interface specification" refers both to interfaces and to
interface declarations, such as declarations of interfaces implemented
by a class.qMhh,h3]qNh<X–The term "interface specification" refers both to interfaces and to
interface declarations, such as declarations of interfaces implemented
by a class.qO…qP}qQ(hhMhhJubaubh)qR}qS(hhhh h}qT(h
]h	]h]qUXsingle adaptersqVah]qWUsingle-adaptersqXah
]uhKhhhUhh,h3]qY(h5)qZ}q[(hhhh8h}q\(h
]h	]h]h]h
]uhKhhhXSingle Adaptersq]hhRh3]q^h<XSingle Adaptersq_…q`}qa(hh]hhZubaubh@)qb}qc(hhhhCh}qd(h
]h	]h]h]h
]uhKhhhXFLet's look at a simple example, using a single required specification:qehhRh3]qfh<XFLet's look at a simple example, using a single required specification:qg…qh}qi(hhehhbubaubcdocutils.nodes
literal_block
qj)qk}ql(hhhU
literal_blockqmh}qn(h	]U	xml:spaceqoUpreserveqph
]UtestnodetypeXdoctesth
]Ugroups]qqUdefaultqrah]Uoptionsqs}h]uhKhhhX>>> from zope.interface.adapter import AdapterRegistry
>>> import zope.interface

>>> class IR1(zope.interface.Interface):
...     pass
>>> class IP1(zope.interface.Interface):
...     pass
>>> class IP2(IP1):
...     pass

>>> registry = AdapterRegistry()hhRh3]qth<X>>> from zope.interface.adapter import AdapterRegistry
>>> import zope.interface

>>> class IR1(zope.interface.Interface):
...     pass
>>> class IP1(zope.interface.Interface):
...     pass
>>> class IP2(IP1):
...     pass

>>> registry = AdapterRegistry()qu…qv}qw(hUhhkubaubh@)qx}qy(hhhhCh}qz(h
]h	]h]h]h
]uhK"hhhX@We'll register an object that depends on IR1 and "provides" IP2:q{hhRh3]q|h<X@We'll register an object that depends on IR1 and "provides" IP2:q}…q~}q(hh{hhxubaubhj)q€}q(hhhhmh}q‚(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]qƒhrah]hs}h]uhK$hhhX)>>> registry.register([IR1], IP2, '', 12)hhRh3]q„h<X)>>> registry.register([IR1], IP2, '', 12)q……q†}q‡(hUhh€ubaubh@)qˆ}q‰(hhhhCh}qŠ(h
]h	]h]h]h
]uhK(hhhX0Given the registration, we can look it up again:q‹hhRh3]qŒh<X0Given the registration, we can look it up again:q…qŽ}q(hh‹hhˆubaubhj)q}q‘(hhhhmh}q’(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]q“hrah]hs}h]uhK*hhhX&>>> registry.lookup([IR1], IP2, '')
12hhRh3]q”h<X&>>> registry.lookup([IR1], IP2, '')
12q•…q–}q—(hUhhubaubh@)q˜}q™(hhhhCh}qš(h
]h	]h]h]h
]uhK/hhhXdNote that we used an integer in the example.  In real applications,
one would use some objects that actually depend on or provide
interfaces. The registry doesn't care about what gets registered, so
we'll use integers and strings to keep the examples simple. There is
one exception.  Registering a value of None unregisters any
previously-registered value.q›hhRh3]qœh<XdNote that we used an integer in the example.  In real applications,
one would use some objects that actually depend on or provide
interfaces. The registry doesn't care about what gets registered, so
we'll use integers and strings to keep the examples simple. There is
one exception.  Registering a value of None unregisters any
previously-registered value.q…qž}qŸ(hh›hh˜ubaubh@)q }q¡(hhhhCh}q¢(h
]h	]h]h]h
]uhK6hhhX„If an object depends on a specification, it can be looked up with a
specification that extends the specification that it depends on:q£hhRh3]q¤h<X„If an object depends on a specification, it can be looked up with a
specification that extends the specification that it depends on:q¥…q¦}q§(hh£hh ubaubhj)q¨}q©(hhhhmh}qª(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]q«hrah]hs}h]uhK9hhhXG>>> class IR2(IR1):
...     pass
>>> registry.lookup([IR2], IP2, '')
12hhRh3]q¬h<XG>>> class IR2(IR1):
...     pass
>>> registry.lookup([IR2], IP2, '')
12q­…q®}q¯(hUhh¨ubaubh@)q°}q±(hhhhCh}q²(h
]h	]h]h]h
]uhK@hhhXFWe can use a class implementation specification to look up the object:q³hhRh3]q´h<XFWe can use a class implementation specification to look up the object:qµ…q¶}q·(hh³hh°ubaubhj)q¸}q¹(hhhhmh}qº(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]q»hrah]hs}h]uhKBhhhXy>>> class C2:
...     zope.interface.implements(IR2)

>>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
12hhRh3]q¼h<Xy>>> class C2:
...     zope.interface.implements(IR2)

>>> registry.lookup([zope.interface.implementedBy(C2)], IP2, '')
12q½…q¾}q¿(hUhh¸ubaubh@)qÀ}qÁ(hhhhCh}qÂ(h
]h	]h]h]h
]uhKKhhhXKand it can be looked up for interfaces that its provided interface
extends:qÃhhRh3]qÄh<XKand it can be looked up for interfaces that its provided interface
extends:qҁqÆ}qÇ(hhÃhhÀubaubhj)qÈ}qÉ(hhhhmh}qÊ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]qËhrah]hs}h]uhKNhhhXM>>> registry.lookup([IR1], IP1, '')
12
>>> registry.lookup([IR2], IP1, '')
12hhRh3]qÌh<XM>>> registry.lookup([IR1], IP1, '')
12
>>> registry.lookup([IR2], IP1, '')
12qͅqÎ}qÏ(hUhhÈubaubh@)qÐ}qÑ(hhhhCh}qÒ(h
]h	]h]h]h
]uhKUhhhXwBut if you require a specification that doesn't extend the specification the
object depends on, you won't get anything:qÓhhRh3]qÔh<XwBut if you require a specification that doesn't extend the specification the
object depends on, you won't get anything:qՅqÖ}q×(hhÓhhÐubaubhj)qØ}qÙ(hhhhmh}qÚ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]qÛhrah]hs}h]uhKXhhhX8>>> registry.lookup([zope.interface.Interface], IP1, '')hhRh3]qÜh<X8>>> registry.lookup([zope.interface.Interface], IP1, '')q݅qÞ}qß(hUhhØubaubh@)qà}qá(hhhhCh}qâ(h
]h	]h]h]h
]uhK\hhhX3By the way, you can pass a default value to lookup:qãhhRh3]qäh<X3By the way, you can pass a default value to lookup:q允qæ}qç(hhãhhàubaubhj)qè}qé(hhhhmh}qê(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]qëhrah]hs}h]uhK^hhhX?>>> registry.lookup([zope.interface.Interface], IP1, '', 42)
42hhRh3]qìh<X?>>> registry.lookup([zope.interface.Interface], IP1, '', 42)
42q텁qî}qï(hUhhèubaubh@)qð}qñ(hhhhCh}qò(h
]h	]h]h]h
]uhKchhhXWIf you try to get an interface the object doesn't provide, you also
won't get anything:qóhhRh3]qôh<XWIf you try to get an interface the object doesn't provide, you also
won't get anything:qõ…qö}q÷(hhóhhðubaubhj)qø}qù(hhhhmh}qú(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]qûhrah]hs}h]uhKfhhhXD>>> class IP3(IP2):
...     pass
>>> registry.lookup([IR1], IP3, '')hhRh3]qüh<XD>>> class IP3(IP2):
...     pass
>>> registry.lookup([IR1], IP3, '')qý…qþ}qÿ(hUhhøubaubh@)r}r(hhhhCh}r(h
]h	]h]h]h
]uhKlhhhX6You also won't get anything if you use the wrong name:rhhRh3]rh<X6You also won't get anything if you use the wrong name:r…r}r(hjhjubaubhj)r}r	(hhhhmh}r
(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rhrah]hs}h]uhKnhhhX>>> registry.lookup([IR1], IP1, 'bob')
>>> registry.register([IR1], IP2, 'bob', "Bob's 12")
>>> registry.lookup([IR1], IP1, 'bob')
"Bob's 12"hhRh3]rh<X>>> registry.lookup([IR1], IP1, 'bob')
>>> registry.register([IR1], IP2, 'bob', "Bob's 12")
>>> registry.lookup([IR1], IP1, 'bob')
"Bob's 12"r
…r}r(hUhjubaubh@)r}r(hhhhCh}r(h
]h	]h]h]h
]uhKuhhhX/You can leave the name off when doing a lookup:rhhRh3]rh<X/You can leave the name off when doing a lookup:r…r}r(hjhjubaubhj)r}r(hhhhmh}r(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rhrah]hs}h]uhKwhhhX">>> registry.lookup([IR1], IP1)
12hhRh3]rh<X">>> registry.lookup([IR1], IP1)
12r…r}r(hUhjubaubh@)r }r!(hhhhCh}r"(h
]h	]h]h]h
]uhK|hhhX+If we register an object that provides IP1:r#hhRh3]r$h<X+If we register an object that provides IP1:r%…r&}r'(hj#hj ubaubhj)r(}r)(hhhhmh}r*(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r+hrah]hs}h]uhK~hhhX)>>> registry.register([IR1], IP1, '', 11)hhRh3]r,h<X)>>> registry.register([IR1], IP1, '', 11)r-…r.}r/(hUhj(ubaubh@)r0}r1(hhhhCh}r2(h
]h	]h]h]h
]uhK‚hhhX-then that object will be prefered over O(12):r3hhRh3]r4h<X-then that object will be prefered over O(12):r5…r6}r7(hj3hj0ubaubhj)r8}r9(hhhhmh}r:(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r;hrah]hs}h]uhK„hhhX&>>> registry.lookup([IR1], IP1, '')
11hhRh3]r<h<X&>>> registry.lookup([IR1], IP1, '')
11r=…r>}r?(hUhj8ubaubh@)r@}rA(hhhhCh}rB(h
]h	]h]h]h
]uhK‰hhhXRAlso, if we register an object for IR2, then that will be prefered
when using IR2:rChhRh3]rDh<XRAlso, if we register an object for IR2, then that will be prefered
when using IR2:rE…rF}rG(hjChj@ubaubhj)rH}rI(hhhhmh}rJ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rKhrah]hs}h]uhKŒhhhXP>>> registry.register([IR2], IP1, '', 21)
>>> registry.lookup([IR2], IP1, '')
21hhRh3]rLh<XP>>> registry.register([IR2], IP1, '', 21)
>>> registry.lookup([IR2], IP1, '')
21rM…rN}rO(hUhjHubaubh)rP}rQ(hhhh h}rR(h
]h	]h]rSX,finding out what, if anything, is registeredrTah]rUU*finding-out-what-if-anything-is-registeredrVah
]uhK“hhhUhhRh3]rW(h5)rX}rY(hhhh8h}rZ(h
]h	]h]h]h
]uhK“hhhX,Finding out what, if anything, is registeredr[hjPh3]r\h<X,Finding out what, if anything, is registeredr]…r^}r_(hj[hjXubaubh@)r`}ra(hhhhCh}rb(h
]h	]h]h]h
]uhK•hhhXWe can ask if there is an adapter registered for a collection of
interfaces. This is different than lookup, because it looks for an
exact match:rchjPh3]rdh<XWe can ask if there is an adapter registered for a collection of
interfaces. This is different than lookup, because it looks for an
exact match:re…rf}rg(hjchj`ubaubhj)rh}ri(hhhhmh}rj(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rkhrah]hs}h]uhK™hhhXô>>> print registry.registered([IR1], IP1)
11

>>> print registry.registered([IR1], IP2)
12

>>> print registry.registered([IR1], IP2, 'bob')
Bob's 12


>>> print registry.registered([IR2], IP1)
21

>>> print registry.registered([IR2], IP2)
NonehjPh3]rlh<Xô>>> print registry.registered([IR1], IP1)
11

>>> print registry.registered([IR1], IP2)
12

>>> print registry.registered([IR1], IP2, 'bob')
Bob's 12


>>> print registry.registered([IR2], IP1)
21

>>> print registry.registered([IR2], IP2)
Nonerm…rn}ro(hUhjhubaubh@)rp}rq(hhhhCh}rr(h
]h	]h]h]h
]uhK«hhhXgIn the last example, None was returned because nothing was registered
exactly for the given interfaces.rshjPh3]rth<XgIn the last example, None was returned because nothing was registered
exactly for the given interfaces.ru…rv}rw(hjshjpubaubeubh)rx}ry(hhhh h}rz(h
]h	]h]r{Xlookup1r|ah]r}Ulookup1r~ah
]uhK¯hhhUhhRh3]r(h5)r€}r(hhhh8h}r‚(h
]h	]h]h]h
]uhK¯hhhXlookup1rƒhjxh3]r„h<Xlookup1r……r†}r‡(hjƒhj€ubaubh@)rˆ}r‰(hhhhCh}rŠ(h
]h	]h]h]h
]uhK±hhhX€Lookup of single adapters is common enough that there is a specialized
version of lookup that takes a single required interface:r‹hjxh3]rŒh<X€Lookup of single adapters is common enough that there is a specialized
version of lookup that takes a single required interface:r…rŽ}r(hj‹hjˆubaubhj)r}r‘(hhhhmh}r’(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r“hrah]hs}h]uhK´hhhXG>>> registry.lookup1(IR2, IP1, '')
21
>>> registry.lookup1(IR2, IP1)
21hjxh3]r”h<XG>>> registry.lookup1(IR2, IP1, '')
21
>>> registry.lookup1(IR2, IP1)
21r•…r–}r—(hUhjubaubeubh)r˜}r™(hhhh h}rš(h
]h	]h]r›Xactual adaptationrœah]rUactual-adaptationržah
]uhK¼hhhUhhRh3]rŸ(h5)r }r¡(hhhh8h}r¢(h
]h	]h]h]h
]uhK¼hhhXActual Adaptationr£hj˜h3]r¤h<XActual Adaptationr¥…r¦}r§(hj£hj ubaubh@)r¨}r©(hhhhCh}rª(h
]h	]h]h]h
]uhK¾hhhXThe adapter registry is intended to support adaptation, where one
object that implements an interface is adapted to another object that
supports a different interface.  The adapter registry supports the
computation of adapters. In this case, we have to register adapter
factories:r«hj˜h3]r¬h<XThe adapter registry is intended to support adaptation, where one
object that implements an interface is adapted to another object that
supports a different interface.  The adapter registry supports the
computation of adapters. In this case, we have to register adapter
factories:r­…r®}r¯(hj«hj¨ubaubhj)r°}r±(hhhhmh}r²(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r³hrah]hs}h]uhKÄhhhX >>> class IR(zope.interface.Interface):
 ...     pass

 >>> class X:
 ...     zope.interface.implements(IR)

 >>> class Y:
 ...     zope.interface.implements(IP1)
 ...     def __init__(self, context):
 ...         self.context = context

>>> registry.register([IR], IP1, '', Y)hj˜h3]r´h<X >>> class IR(zope.interface.Interface):
 ...     pass

 >>> class X:
 ...     zope.interface.implements(IR)

 >>> class Y:
 ...     zope.interface.implements(IP1)
 ...     def __init__(self, context):
 ...         self.context = context

>>> registry.register([IR], IP1, '', Y)rµ…r¶}r·(hUhj°ubaubh@)r¸}r¹(hhhhCh}rº(h
]h	]h]h]h
]uhKÓhhhXmIn this case, we registered a class as the factory. Now we can call
`queryAdapter` to get the adapted object:hj˜h3]r»(h<XDIn this case, we registered a class as the factory. Now we can call
r¼…r½}r¾(hXDIn this case, we registered a class as the factory. Now we can call
hj¸ubcdocutils.nodes
title_reference
r¿)rÀ}rÁ(hX`queryAdapter`hUtitle_referencerÂh}rÃ(h
]h	]h]h]h
]uhj¸h3]rÄh<XqueryAdapterrÅ…rÆ}rÇ(hUhjÀubaubh<X to get the adapted object:rÈ…rÉ}rÊ(hX to get the adapted object:hj¸ubeubhj)rË}rÌ(hhhhmh}rÍ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rÎhrah]hs}h]uhKÖhhhXf>>> x = X()
>>> y = registry.queryAdapter(x, IP1)
>>> y.__class__.__name__
'Y'
>>> y.context is x
Truehj˜h3]rÏh<Xf>>> x = X()
>>> y = registry.queryAdapter(x, IP1)
>>> y.__class__.__name__
'Y'
>>> y.context is x
TruerÐ…rÑ}rÒ(hUhjËubaubh@)rÓ}rÔ(hhhhCh}rÕ(h
]h	]h]h]h
]uhKßhhhX'We can register and lookup by name too:rÖhj˜h3]r×h<X'We can register and lookup by name too:rØ…rÙ}rÚ(hjÖhjÓubaubhj)rÛ}rÜ(hhhhmh}rÝ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rÞhrah]hs}h]uhKáhhhX­>>> class Y2(Y):
...     pass

>>> registry.register([IR], IP1, 'bob', Y2)
>>> y = registry.queryAdapter(x, IP1, 'bob')
>>> y.__class__.__name__
'Y2'
>>> y.context is x
Truehj˜h3]rßh<X­>>> class Y2(Y):
...     pass

>>> registry.register([IR], IP1, 'bob', Y2)
>>> y = registry.queryAdapter(x, IP1, 'bob')
>>> y.__class__.__name__
'Y2'
>>> y.context is x
Truerà…rá}râ(hUhjÛubaubh@)rã}rä(hhhhCh}rå(h
]h	]h]h]h
]uhKíhhhXWhen the adapter factory produces `None`, then this is treated as if no
adapter has been found. This allows us to prevent adaptation (when desired)
and let the adapter factory determine whether adaptation is possible based on
the state of the object being adapted:hj˜h3]ræ(h<X"When the adapter factory produces r煁rè}ré(hX"When the adapter factory produces hjãubj¿)rê}rë(hX`None`hjÂh}rì(h
]h	]h]h]h
]uhjãh3]ríh<XNonerrï}rð(hUhjêubaubh<Xà, then this is treated as if no
adapter has been found. This allows us to prevent adaptation (when desired)
and let the adapter factory determine whether adaptation is possible based on
the state of the object being adapted:rñ…rò}ró(hXà, then this is treated as if no
adapter has been found. This allows us to prevent adaptation (when desired)
and let the adapter factory determine whether adaptation is possible based on
the state of the object being adapted:hjãubeubhj)rô}rõ(hhhhmh}rö(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r÷hrah]hs}h]uhKòhhhXõ>>> def factory(context):
...     if context.name == 'object':
...         return 'adapter'
...     return None

>>> class Object(object):
...     zope.interface.implements(IR)
...     name = 'object'

>>> registry.register([IR], IP1, 'conditional', factory)
>>> obj = Object()
>>> registry.queryAdapter(obj, IP1, 'conditional')
'adapter'
>>> obj.name = 'no object'
>>> registry.queryAdapter(obj, IP1, 'conditional') is None
True
>>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
'default'hj˜h3]røh<Xõ>>> def factory(context):
...     if context.name == 'object':
...         return 'adapter'
...     return None

>>> class Object(object):
...     zope.interface.implements(IR)
...     name = 'object'

>>> registry.register([IR], IP1, 'conditional', factory)
>>> obj = Object()
>>> registry.queryAdapter(obj, IP1, 'conditional')
'adapter'
>>> obj.name = 'no object'
>>> registry.queryAdapter(obj, IP1, 'conditional') is None
True
>>> registry.queryAdapter(obj, IP1, 'conditional', 'default')
'default'rù…rú}rû(hUhjôubaubh@)rü}rý(hhhhCh}rþ(h
]h	]h]h]h
]uhMhhhX\An alternate method that provides the same function as `queryAdapter()` is
`adapter_hook()`:hj˜h3]rÿ(h<X7An alternate method that provides the same function as r…r}r(hX7An alternate method that provides the same function as hjüubj¿)r}r(hX`queryAdapter()`hjÂh}r(h
]h	]h]h]h
]uhjüh3]rh<XqueryAdapter()r…r}r	(hUhjubaubh<X is
r
…r}r(hX is
hjüubj¿)r
}r(hX`adapter_hook()`hjÂh}r(h
]h	]h]h]h
]uhjüh3]rh<Xadapter_hook()r…r}r(hUhj
ubaubh<X:…r}r(hX:hjüubeubhj)r}r(hhhhmh}r(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rhrah]hs}h]uhM
hhhX½>>> y = registry.adapter_hook(IP1, x)
>>> y.__class__.__name__
'Y'
>>> y.context is x
True
>>> y = registry.adapter_hook(IP1, x, 'bob')
>>> y.__class__.__name__
'Y2'
>>> y.context is x
Truehj˜h3]rh<X½>>> y = registry.adapter_hook(IP1, x)
>>> y.__class__.__name__
'Y'
>>> y.context is x
True
>>> y = registry.adapter_hook(IP1, x, 'bob')
>>> y.__class__.__name__
'Y2'
>>> y.context is x
Truer…r}r(hUhjubaubh@)r}r(hhhhCh}r (h
]h	]h]h]h
]uhMhhhXŒThe `adapter_hook()` simply switches the order of the object and
interface arguments.  It is used to hook into the interface call
mechanism.hj˜h3]r!(h<XThe r"…r#}r$(hXThe hjubj¿)r%}r&(hX`adapter_hook()`hjÂh}r'(h
]h	]h]h]h
]uhjh3]r(h<Xadapter_hook()r)…r*}r+(hUhj%ubaubh<Xx simply switches the order of the object and
interface arguments.  It is used to hook into the interface call
mechanism.r,…r-}r.(hXx simply switches the order of the object and
interface arguments.  It is used to hook into the interface call
mechanism.hjubeubeubh)r/}r0(hhhh h}r1(h
]h	]r2h#ah]h]r3Udefault-adaptersr4ah
]uhMhhhUhhRU
referencedr5Kh3]r6(h5)r7}r8(hhhh8h}r9(h
]h	]h]h]h
]uhMhhhXDefault Adaptersr:hj/h3]r;h<XDefault Adaptersr<…r=}r>(hj:hj7ubaubh@)r?}r@(hhhhCh}rA(h
]h	]h]h]h
]uhMhhhXuSometimes, you want to provide an adapter that will adapt anything.
For that, provide None as the required interface:rBhj/h3]rCh<XuSometimes, you want to provide an adapter that will adapt anything.
For that, provide None as the required interface:rD…rE}rF(hjBhj?ubaubhj)rG}rH(hhhhmh}rI(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rJhrah]hs}h]uhM"hhhX)>>> registry.register([None], IP1, '', 1)hj/h3]rKh<X)>>> registry.register([None], IP1, '', 1)rL…rM}rN(hUhjGubaubh@)rO}rP(hhhhCh}rQ(h
]h	]h]h]h
]uhM&hhhXPthen we can use that adapter for interfaces we don't have specific
adapters for:rRhj/h3]rSh<XPthen we can use that adapter for interfaces we don't have specific
adapters for:rT…rU}rV(hjRhjOubaubhj)rW}rX(hhhhmh}rY(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rZhrah]hs}h]uhM)hhhXY>>> class IQ(zope.interface.Interface):
...     pass
>>> registry.lookup([IQ], IP1, '')
1hj/h3]r[h<XY>>> class IQ(zope.interface.Interface):
...     pass
>>> registry.lookup([IQ], IP1, '')
1r\…r]}r^(hUhjWubaubh@)r_}r`(hhhhCh}ra(h
]h	]h]h]h
]uhM0hhhX<Of course, specific adapters are still used when applicable:rbhj/h3]rch<X<Of course, specific adapters are still used when applicable:rd…re}rf(hjbhj_ubaubhj)rg}rh(hhhhmh}ri(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rjhrah]hs}h]uhM2hhhX&>>> registry.lookup([IR2], IP1, '')
21hj/h3]rkh<X&>>> registry.lookup([IR2], IP1, '')
21rl…rm}rn(hUhjgubaubeubh)ro}rp(hhhh h}rq(h
]h	]h]rrXclass adaptersrsah]rtUclass-adaptersruah
]uhM9hhhUhhRh3]rv(h5)rw}rx(hhhh8h}ry(h
]h	]h]h]h
]uhM9hhhXClass adaptersrzhjoh3]r{h<XClass adaptersr|…r}}r~(hjzhjwubaubh@)r}r€(hhhhCh}r(h
]h	]h]h]h
]uhM;hhhXkYou can register adapters for class declarations, which is almost the
same as registering them for a class:r‚hjoh3]rƒh<XkYou can register adapters for class declarations, which is almost the
same as registering them for a class:r„…r…}r†(hj‚hjubaubhj)r‡}rˆ(hhhhmh}r‰(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rŠhrah]hs}h]uhM>hhhX>>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
>>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
'C21'hjoh3]r‹h<X>>> registry.register([zope.interface.implementedBy(C2)], IP1, '', 'C21')
>>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
'C21'rŒ…r}rŽ(hUhj‡ubaubeubh)r}r(hhhh h}r‘(h
]h	]h]r’X
dict adaptersr“ah]r”U
dict-adaptersr•ah
]uhMEhhhUhhRh3]r–(h5)r—}r˜(hhhh8h}r™(h
]h	]h]h]h
]uhMEhhhX
Dict adaptersršhjh3]r›h<X
Dict adaptersrœ…r}rž(hjšhj—ubaubh@)rŸ}r (hhhhCh}r¡(h
]h	]h]h]h
]uhMGhhhXpAt some point it was impossible to register dictionary-based adapters due a
bug. Let's make sure this works now:r¢hjh3]r£h<XpAt some point it was impossible to register dictionary-based adapters due a
bug. Let's make sure this works now:r¤…r¥}r¦(hj¢hjŸubaubhj)r§}r¨(hhhhmh}r©(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rªhrah]hs}h]uhMJhhhXk>>> adapter = {}
>>> registry.register((), IQ, '', adapter)
>>> registry.lookup((), IQ, '') is adapter
Truehjh3]r«h<Xk>>> adapter = {}
>>> registry.register((), IQ, '', adapter)
>>> registry.lookup((), IQ, '') is adapter
Truer¬…r­}r®(hUhj§ubaubeubh)r¯}r°(hhhh h}r±(h
]h	]h]r²X
unregisteringr³ah]r´U
unregisteringrµah
]uhMRhhhUhhRh3]r¶(h5)r·}r¸(hhhh8h}r¹(h
]h	]h]h]h
]uhMRhhhX
Unregisteringrºhj¯h3]r»h<X
Unregisteringr¼…r½}r¾(hjºhj·ubaubh@)r¿}rÀ(hhhhCh}rÁ(h
]h	]h]h]h
]uhMThhhX>You can unregister by registering None, rather than an object:rÂhj¯h3]rÃh<X>You can unregister by registering None, rather than an object:rÄ…rÅ}rÆ(hjÂhj¿ubaubhj)rÇ}rÈ(hhhhmh}rÉ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rÊhrah]hs}h]uhMVhhhXŒ>>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
>>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
21hj¯h3]rËh<XŒ>>> registry.register([zope.interface.implementedBy(C2)], IP1, '', None)
>>> registry.lookup([zope.interface.implementedBy(C2)], IP1, '')
21rÌ…rÍ}rÎ(hUhjÇubaubh@)rÏ}rÐ(hhhhCh}rÑ(h
]h	]h]h]h
]uhM\hhhXžOf course, this means that None can't be registered. This is an
exception to the statement, made earlier, that the registry doesn't
care what gets registered.rÒhj¯h3]rÓh<XžOf course, this means that None can't be registered. This is an
exception to the statement, made earlier, that the registry doesn't
care what gets registered.rÔ…rÕ}rÖ(hjÒhjÏubaubeubeubh%h)r×}rØ(hhhh h}rÙ(h
]h	]h]rÚX
null adaptersrÛah]rÜU
null-adaptersrÝah
]uhM¶hhhUhh,h3]rÞ(h5)rß}rà(hhhh8h}rá(h
]h	]h]h]h
]uhM¶hhhX
Null Adaptersrâhj×h3]rãh<X
Null Adaptersr䅁rå}ræ(hjâhjßubaubh@)rç}rè(hhhhCh}ré(h
]h	]h]h]h
]uhM¸hhhX$You can also adapt no specification:rêhj×h3]rëh<X$You can also adapt no specification:r셁rí}rî(hjêhjçubaubhj)rï}rð(hhhhmh}rñ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]ròhrah]hs}h]uhMºhhhXk>>> registry.register([], IP2, '', 2)
>>> registry.lookup([], IP2, '')
2
>>> registry.lookup([], IP1, '')
2hj×h3]róh<Xk>>> registry.register([], IP2, '', 2)
>>> registry.lookup([], IP2, '')
2
>>> registry.lookup([], IP1, '')
2rô…rõ}rö(hUhjïubaubh)r÷}rø(hhhh h}rù(h
]h	]h]rúXlisting named adaptersrûah]rüUlisting-named-adaptersrýah
]uhMÃhhhUhj×h3]rþ(h5)rÿ}r(hhhh8h}r(h
]h	]h]h]h
]uhMÃhhhXListing named adaptersrhj÷h3]rh<XListing named adaptersr…r}r(hjhjÿubaubh@)r}r(hhhhCh}r	(h
]h	]h]h]h
]uhMÅhhhXaAdapters are named. Sometimes, it's useful to get all of the named
adapters for given interfaces:r
hj÷h3]rh<XaAdapters are named. Sometimes, it's useful to get all of the named
adapters for given interfaces:r…r
}r(hj
hjubaubhj)r}r(hhhhmh}r(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rhrah]hs}h]uhMÈhhhX€>>> adapters = list(registry.lookupAll([IR1], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]hj÷h3]rh<X€>>> adapters = list(registry.lookupAll([IR1], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', 11), (u'bob', "Bob's 12")]r…r}r(hUhjubaubh@)r}r(hhhhCh}r(h
]h	]h]h]h
]uhMÎhhhX"This works for multi-adapters too:rhj÷h3]rh<X"This works for multi-adapters too:r…r}r(hjhjubaubhj)r}r (hhhhmh}r!(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r"hrah]hs}h]uhMÐhhhXÉ>>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
>>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]hj÷h3]r#h<XÉ>>> registry.register([IR1, IQ2], IP2, 'bob', '1q2 for bob')
>>> adapters = list(registry.lookupAll([IR2, IQ2], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', '1q22'), (u'bob', '1q2 for bob')]r$…r%}r&(hUhjubaubh@)r'}r((hhhhCh}r)(h
]h	]h]h]h
]uhM×hhhXAnd even null adapters:r*hj÷h3]r+h<XAnd even null adapters:r,…r-}r.(hj*hj'ubaubhj)r/}r0(hhhhmh}r1(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r2hrah]hs}h]uhMÙhhhXœ>>> registry.register([], IP2, 'bob', 3)
>>> adapters = list(registry.lookupAll([], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', 2), (u'bob', 3)]hj÷h3]r3h<Xœ>>> registry.register([], IP2, 'bob', 3)
>>> adapters = list(registry.lookupAll([], IP1))
>>> adapters.sort()
>>> assert adapters == [(u'', 2), (u'bob', 3)]r4…r5}r6(hUhj/ubaubeubeubh)r7}r8(hhhh h}r9(h
]h	]h]r:X
subscriptionsr;ah]r<U
subscriptionsr=ah
]uhMáhhhUhh,h3]r>(h5)r?}r@(hhhh8h}rA(h
]h	]h]h]h
]uhMáhhhX
SubscriptionsrBhj7h3]rCh<X
SubscriptionsrD…rE}rF(hjBhj?ubaubh@)rG}rH(hhhhCh}rI(h
]h	]h]h]h
]uhMãhhhXNormally, we want to look up an object that most-closely matches a
specification.  Sometimes, we want to get all of the objects that
match some specification.  We use subscriptions for this.  We
subscribe objects against specifications and then later find all of
the subscribed objects:rJhj7h3]rKh<XNormally, we want to look up an object that most-closely matches a
specification.  Sometimes, we want to get all of the objects that
match some specification.  We use subscriptions for this.  We
subscribe objects against specifications and then later find all of
the subscribed objects:rL…rM}rN(hjJhjGubaubhj)rO}rP(hhhhmh}rQ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rRhrah]hs}h]uhMéhhhX`>>> registry.subscribe([IR1], IP2, 'sub12 1')
>>> registry.subscriptions([IR1], IP2)
['sub12 1']hj7h3]rSh<X`>>> registry.subscribe([IR1], IP2, 'sub12 1')
>>> registry.subscriptions([IR1], IP2)
['sub12 1']rT…rU}rV(hUhjOubaubh@)rW}rX(hhhhCh}rY(h
]h	]h]h]h
]uhMïhhhX>Note that, unlike regular adapters, subscriptions are unnamed.rZhj7h3]r[h<X>Note that, unlike regular adapters, subscriptions are unnamed.r\…r]}r^(hjZhjWubaubh@)r_}r`(hhhhCh}ra(h
]h	]h]h]h
]uhMñhhhX=You can have multiple subscribers for the same specification:rbhj7h3]rch<X=You can have multiple subscribers for the same specification:rd…re}rf(hjbhj_ubaubhj)rg}rh(hhhhmh}ri(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rjhrah]hs}h]uhMóhhhXk>>> registry.subscribe([IR1], IP2, 'sub12 2')
>>> registry.subscriptions([IR1], IP2)
['sub12 1', 'sub12 2']hj7h3]rkh<Xk>>> registry.subscribe([IR1], IP2, 'sub12 2')
>>> registry.subscriptions([IR1], IP2)
['sub12 1', 'sub12 2']rl…rm}rn(hUhjgubaubh@)ro}rp(hhhhCh}rq(h
]h	]h]h]h
]uhMùhhhXmIf subscribers are registered for the same required interfaces, they
are returned in the order of definition.rrhj7h3]rsh<XmIf subscribers are registered for the same required interfaces, they
are returned in the order of definition.rt…ru}rv(hjrhjoubaubh@)rw}rx(hhhhCh}ry(h
]h	]h]h]h
]uhMühhhX?You can register subscribers for all specifications using None:rzhj7h3]r{h<X?You can register subscribers for all specifications using None:r|…r}}r~(hjzhjwubaubhj)r}r€(hhhhmh}r(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r‚hrah]hs}h]uhMþhhhXs>>> registry.subscribe([None], IP1, 'sub_1')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']hj7h3]rƒh<Xs>>> registry.subscribe([None], IP1, 'sub_1')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']r„…r…}r†(hUhjubaubh@)r‡}rˆ(hhhhCh}r‰(h
]h	]h]h]h
]uhMhhhX¦Note that the new subscriber is returned first.  Subscribers defined
for less general required interfaces are returned before subscribers
for more general interfaces.rŠhj7h3]r‹h<X¦Note that the new subscriber is returned first.  Subscribers defined
for less general required interfaces are returned before subscribers
for more general interfaces.rŒ…r}rŽ(hjŠhj‡ubaubh@)r}r(hhhhCh}r‘(h
]h	]h]h]h
]uhMhhhXFSubscriptions may be combined over multiple compatible specifications:r’hj7h3]r“h<XFSubscriptions may be combined over multiple compatible specifications:r”…r•}r–(hj’hjubaubhj)r—}r˜(hhhhmh}r™(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]ršhrah]hs}h]uhM
hhhXŽ>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']
>>> registry.subscribe([IR1], IP1, 'sub11')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2', 'sub11']
>>> registry.subscribe([IR2], IP2, 'sub22')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
>>> registry.subscriptions([IR2], IP2)
['sub12 1', 'sub12 2', 'sub22']hj7h3]r›h<XŽ>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2']
>>> registry.subscribe([IR1], IP1, 'sub11')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2', 'sub11']
>>> registry.subscribe([IR2], IP2, 'sub22')
>>> registry.subscriptions([IR2], IP1)
['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
>>> registry.subscriptions([IR2], IP2)
['sub12 1', 'sub12 2', 'sub22']rœ…r}rž(hUhj—ubaubh@)rŸ}r (hhhhCh}r¡(h
]h	]h]h]h
]uhMhhhX0Subscriptions can be on multiple specifications:r¢hj7h3]r£h<X0Subscriptions can be on multiple specifications:r¤…r¥}r¦(hj¢hjŸubaubhj)r§}r¨(hhhhmh}r©(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rªhrah]hs}h]uhMhhhXf>>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
>>> registry.subscriptions([IR1, IQ], IP2)
['sub1q2']hj7h3]r«h<Xf>>> registry.subscribe([IR1, IQ], IP2, 'sub1q2')
>>> registry.subscriptions([IR1, IQ], IP2)
['sub1q2']r¬…r­}r®(hUhj§ubaubh@)r¯}r°(hhhhCh}r±(h
]h	]h]h]h
]uhMhhhXˆAs with single subscriptions and non-subscription adapters, you can
specify None for the first required interface, to specify a default:r²hj7h3]r³h<XˆAs with single subscriptions and non-subscription adapters, you can
specify None for the first required interface, to specify a default:r´…rµ}r¶(hj²hj¯ubaubhj)r·}r¸(hhhhmh}r¹(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rºhrah]hs}h]uhM"hhhX¦>>> registry.subscribe([None, IQ], IP2, 'sub_q2')
>>> registry.subscriptions([IS, IQ], IP2)
['sub_q2']
>>> registry.subscriptions([IR1, IQ], IP2)
['sub_q2', 'sub1q2']hj7h3]r»h<X¦>>> registry.subscribe([None, IQ], IP2, 'sub_q2')
>>> registry.subscriptions([IS, IQ], IP2)
['sub_q2']
>>> registry.subscriptions([IR1, IQ], IP2)
['sub_q2', 'sub1q2']r¼…r½}r¾(hUhj·ubaubh@)r¿}rÀ(hhhhCh}rÁ(h
]h	]h]h]h
]uhM*hhhXEYou can have subscriptions that are indepenent of any specifications:rÂhj7h3]rÃh<XEYou can have subscriptions that are indepenent of any specifications:rÄ…rÅ}rÆ(hjÂhj¿ubaubhj)rÇ}rÈ(hhhhmh}rÉ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rÊhrah]hs}h]uhM,hhhX>>> list(registry.subscriptions([], IP1))
[]

>>> registry.subscribe([], IP2, 'sub2')
>>> registry.subscriptions([], IP1)
['sub2']
>>> registry.subscribe([], IP1, 'sub1')
>>> registry.subscriptions([], IP1)
['sub2', 'sub1']
>>> registry.subscriptions([], IP2)
['sub2']hj7h3]rËh<X>>> list(registry.subscriptions([], IP1))
[]

>>> registry.subscribe([], IP2, 'sub2')
>>> registry.subscriptions([], IP1)
['sub2']
>>> registry.subscribe([], IP1, 'sub1')
>>> registry.subscriptions([], IP1)
['sub2', 'sub1']
>>> registry.subscriptions([], IP2)
['sub2']rÌ…rÍ}rÎ(hUhjÇubaubh)rÏ}rÐ(hhhh h}rÑ(h
]h	]h]rÒXunregistering subscribersrÓah]rÔUunregistering-subscribersrÕah
]uhM;hhhUhj7h3]rÖ(h5)r×}rØ(hhhh8h}rÙ(h
]h	]h]h]h
]uhM;hhhXUnregistering subscribersrÚhjÏh3]rÛh<XUnregistering subscribersrÜ…rÝ}rÞ(hjÚhj×ubaubh@)rß}rà(hhhhCh}rá(h
]h	]h]h]h
]uhM=hhhXiWe can unregister subscribers.  When unregistering a subscriber, we
can unregister a specific subscriber:râhjÏh3]rãh<XiWe can unregister subscribers.  When unregistering a subscriber, we
can unregister a specific subscriber:r䅁rå}ræ(hjâhjßubaubhj)rç}rè(hhhhmh}ré(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rêhrah]hs}h]uhM@hhhXt>>> registry.unsubscribe([IR1], IP1, 'sub11')
>>> registry.subscriptions([IR1], IP1)
['sub_1', 'sub12 1', 'sub12 2']hjÏh3]rëh<Xt>>> registry.unsubscribe([IR1], IP1, 'sub11')
>>> registry.subscriptions([IR1], IP1)
['sub_1', 'sub12 1', 'sub12 2']r셁rí}rî(hUhjçubaubh@)rï}rð(hhhhCh}rñ(h
]h	]h]h]h
]uhMFhhhXeIf we don't specify a value, then all subscribers matching the given
interfaces will be unsubscribed:ròhjÏh3]róh<XeIf we don't specify a value, then all subscribers matching the given
interfaces will be unsubscribed:rô…rõ}rö(hjòhjïubaubhj)r÷}rø(hhhhmh}rù(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rúhrah]hs}h]uhMIhhhXU>>> registry.unsubscribe([IR1], IP2)
>>> registry.subscriptions([IR1], IP1)
['sub_1']hjÏh3]rûh<XU>>> registry.unsubscribe([IR1], IP2)
>>> registry.subscriptions([IR1], IP1)
['sub_1']rü…rý}rþ(hUhj÷ubaubeubh)rÿ}r(hhhh h}r(h
]h	]h]rXsubscription adaptersrah]rUsubscription-adaptersrah
]uhMQhhhUhj7h3]r(h5)r}r(hhhh8h}r	(h
]h	]h]h]h
]uhMQhhhXSubscription adaptersr
hjÿh3]rh<XSubscription adaptersr…r
}r(hj
hjubaubh@)r}r(hhhhCh}r(h
]h	]h]h]h
]uhMShhhXµWe normally register adapter factories, which then allow us to compute
adapters, but with subscriptions, we get multiple adapters.  Here's an
example of multiple-object subscribers:rhjÿh3]rh<XµWe normally register adapter factories, which then allow us to compute
adapters, but with subscriptions, we get multiple adapters.  Here's an
example of multiple-object subscribers:r…r}r(hjhjubaubhj)r}r(hhhhmh}r(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rhrah]hs}h]uhMWhhhXL>>> registry.subscribe([IR, IQ], IM, M)
>>> registry.subscribe([IR, IQ], IM, M2)

>>> subscribers = registry.subscribers((x, q), IM)
>>> len(subscribers)
2
>>> class_names = [s.__class__.__name__ for s in subscribers]
>>> class_names.sort()
>>> class_names
['M', 'M2']
>>> [(s.x is x and s.q is q) for s in subscribers]
[True, True]hjÿh3]rh<XL>>> registry.subscribe([IR, IQ], IM, M)
>>> registry.subscribe([IR, IQ], IM, M2)

>>> subscribers = registry.subscribers((x, q), IM)
>>> len(subscribers)
2
>>> class_names = [s.__class__.__name__ for s in subscribers]
>>> class_names.sort()
>>> class_names
['M', 'M2']
>>> [(s.x is x and s.q is q) for s in subscribers]
[True, True]r…r}r(hUhjubaubh@)r}r (hhhhCh}r!(h
]h	]h]h]h
]uhMfhhhX4adapter factory subcribers can't return None values:r"hjÿh3]r#h<X4adapter factory subcribers can't return None values:r$…r%}r&(hj"hjubaubhj)r'}r((hhhhmh}r)(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r*hrah]hs}h]uhMhhhhX™>>> def M3(x, y):
...     return None

>>> registry.subscribe([IR, IQ], IM, M3)
>>> subscribers = registry.subscribers((x, q), IM)
>>> len(subscribers)
2hjÿh3]r+h<X™>>> def M3(x, y):
...     return None

>>> registry.subscribe([IR, IQ], IM, M3)
>>> subscribers = registry.subscribers((x, q), IM)
>>> len(subscribers)
2r,…r-}r.(hUhj'ubaubeubh)r/}r0(hhhh h}r1(h
]h	]h]r2Xhandlersr3ah]r4Uhandlersr5ah
]uhMshhhUhj7h3]r6(h5)r7}r8(hhhh8h}r9(h
]h	]h]h]h
]uhMshhhXHandlersr:hj/h3]r;h<XHandlersr<…r=}r>(hj:hj7ubaubh@)r?}r@(hhhhCh}rA(h
]h	]h]h]h
]uhMuhhhXµA handler is a subscriber factory that doesn't produce any normal
output.  It returns None.  A handler is unlike adapters in that it does
all of its work when the factory is called.rBhj/h3]rCh<XµA handler is a subscriber factory that doesn't produce any normal
output.  It returns None.  A handler is unlike adapters in that it does
all of its work when the factory is called.rD…rE}rF(hjBhj?ubaubh@)rG}rH(hhhhCh}rI(h
]h	]h]h]h
]uhMyhhhXETo register a handler, simply provide None as the provided interface:rJhj/h3]rKh<XETo register a handler, simply provide None as the provided interface:rL…rM}rN(hjJhjGubaubhj)rO}rP(hhhhmh}rQ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rRhrah]hs}h]uhM{hhhXž>>> def handler(event):
...     print 'handler', event

>>> registry.subscribe([IR1], None, handler)
>>> registry.subscriptions([IR1], None) == [handler]
Truehj/h3]rSh<Xž>>> def handler(event):
...     print 'handler', event

>>> registry.subscribe([IR1], None, handler)
>>> registry.subscriptions([IR1], None) == [handler]
TruerT…rU}rV(hUhjOubaubeubeubeubh3]rW(h5)rX}rY(hhhh8h}rZ(h
]h	]h]h]h
]uhMahhhXMulti-adaptersr[hh%h3]r\h<XMulti-adaptersr]…r^}r_(hj[hjXubaubh@)r`}ra(hhhhCh}rb(h
]h	]h]h]h
]uhMchhhX&You can adapt multiple specifications:rchh%h3]rdh<X&You can adapt multiple specifications:re…rf}rg(hjchj`ubaubhj)rh}ri(hhhhmh}rj(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rkhrah]hs}h]uhMehhhXŸ>>> registry.register([IR1, IQ], IP2, '', '1q2')
>>> registry.lookup([IR1, IQ], IP2, '')
'1q2'
>>> registry.lookup([IR2, IQ], IP1, '')
'1q2'

>>> class IS(zope.interface.Interface):
...     pass
>>> registry.lookup([IR2, IS], IP1, '')

>>> class IQ2(IQ):
...     pass

>>> registry.lookup([IR2, IQ2], IP1, '')
'1q2'

>>> registry.register([IR1, IQ2], IP2, '', '1q22')
>>> registry.lookup([IR2, IQ2], IP1, '')
'1q22'hh%h3]rlh<XŸ>>> registry.register([IR1, IQ], IP2, '', '1q2')
>>> registry.lookup([IR1, IQ], IP2, '')
'1q2'
>>> registry.lookup([IR2, IQ], IP1, '')
'1q2'

>>> class IS(zope.interface.Interface):
...     pass
>>> registry.lookup([IR2, IS], IP1, '')

>>> class IQ2(IQ):
...     pass

>>> registry.lookup([IR2, IQ2], IP1, '')
'1q2'

>>> registry.register([IR1, IQ2], IP2, '', '1q22')
>>> registry.lookup([IR2, IQ2], IP1, '')
'1q22'rm…rn}ro(hUhjhubaubh)rp}rq(hhhh h}rr(h
]h	]h]rsXmulti-adaptationrtah]ruUmulti-adaptationrvah
]uhM|hhhUhh%h3]rw(h5)rx}ry(hhhh8h}rz(h
]h	]h]h]h
]uhM|hhhXMulti-adaptationr{hjph3]r|h<XMulti-adaptationr}…r~}r(hj{hjxubaubh@)r€}r(hhhhCh}r‚(h
]h	]h]h]h
]uhM~hhhXYou can adapt multiple objects:rƒhjph3]r„h<XYou can adapt multiple objects:r……r†}r‡(hjƒhj€ubaubhj)rˆ}r‰(hhhhmh}rŠ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r‹hrah]hs}h]uhM€hhhX2>>> class Q:
...     zope.interface.implements(IQ)hjph3]rŒh<X2>>> class Q:
...     zope.interface.implements(IQ)r…rŽ}r(hUhjˆubaubh@)r}r‘(hhhhCh}r’(h
]h	]h]h]h
]uhM…hhhXGAs with single adapters, we register a factory, which is often a class:r“hjph3]r”h<XGAs with single adapters, we register a factory, which is often a class:r•…r–}r—(hj“hjubaubhj)r˜}r™(hhhhmh}rš(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]r›hrah]hs}h]uhM‡hhhXÖ>>> class IM(zope.interface.Interface):
...     pass
>>> class M:
...     zope.interface.implements(IM)
...     def __init__(self, x, q):
...         self.x, self.q = x, q
>>> registry.register([IR, IQ], IM, '', M)hjph3]rœh<XÖ>>> class IM(zope.interface.Interface):
...     pass
>>> class M:
...     zope.interface.implements(IM)
...     def __init__(self, x, q):
...         self.x, self.q = x, q
>>> registry.register([IR, IQ], IM, '', M)r…rž}rŸ(hUhj˜ubaubh@)r }r¡(hhhhCh}r¢(h
]h	]h]h]h
]uhM‘hhhX?And then we can call `queryMultiAdapter` to compute an adapter:r£hjph3]r¤(h<XAnd then we can call r¥…r¦}r§(hXAnd then we can call hj ubj¿)r¨}r©(hX`queryMultiAdapter`hjÂh}rª(h
]h	]h]h]h
]uhj h3]r«h<XqueryMultiAdapterr¬…r­}r®(hUhj¨ubaubh<X to compute an adapter:r¯…r°}r±(hX to compute an adapter:hj ubeubhj)r²}r³(hhhhmh}r´(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rµhrah]hs}h]uhM“hhhXv>>> q = Q()
>>> m = registry.queryMultiAdapter((x, q), IM)
>>> m.__class__.__name__
'M'
>>> m.x is x and m.q is q
Truehjph3]r¶h<Xv>>> q = Q()
>>> m = registry.queryMultiAdapter((x, q), IM)
>>> m.__class__.__name__
'M'
>>> m.x is x and m.q is q
Truer·…r¸}r¹(hUhj²ubaubh@)rº}r»(hhhhCh}r¼(h
]h	]h]h]h
]uhMœhhhX!and, of course, we can use names:r½hjph3]r¾h<X!and, of course, we can use names:r¿…rÀ}rÁ(hj½hjºubaubhj)rÂ}rÃ(hhhhmh}rÄ(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]rÅhrah]hs}h]uhMžhhhX¿>>> class M2(M):
...     pass
>>> registry.register([IR, IQ], IM, 'bob', M2)
>>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
>>> m.__class__.__name__
'M2'
>>> m.x is x and m.q is q
Truehjph3]rÆh<X¿>>> class M2(M):
...     pass
>>> registry.register([IR, IQ], IM, 'bob', M2)
>>> m = registry.queryMultiAdapter((x, q), IM, 'bob')
>>> m.__class__.__name__
'M2'
>>> m.x is x and m.q is q
TruerÇ…rÈ}rÉ(hUhjÂubaubeubheubj5Kh3]rÊ(h5)rË}rÌ(hhhh8h}rÍ(h
]h	]h]h]h
]uhMªhhhXDefault AdaptersrÎhhh3]rÏh<XDefault AdaptersrÐ…rÑ}rÒ(hjÎhjËubaubh@)rÓ}rÔ(hhhhCh}rÕ(h
]h	]h]h]h
]uhM¬hhhXjAs with single adapters, you can define default adapters by specifying
None for the *first* specification:hhh3]rÖ(h<XTAs with single adapters, you can define default adapters by specifying
None for the r×…rØ}rÙ(hXTAs with single adapters, you can define default adapters by specifying
None for the hjÓubcdocutils.nodes
emphasis
rÚ)rÛ}rÜ(hX*first*hUemphasisrÝh}rÞ(h
]h	]h]h]h
]uhjÓh3]rßh<Xfirstrà…rá}râ(hUhjÛubaubh<X specification:rㅁrä}rå(hX specification:hjÓubeubhj)ræ}rç(hhhhmh}rè(h	]hohph
]UtestnodetypeXdoctesth
]Ugroups]réhrah]hs}h]uhM¯hhhX\>>> registry.register([None, IQ], IP2, '', 'q2')
>>> registry.lookup([IS, IQ], IP2, '')
'q2'hhh3]rêh<X\>>> registry.register([None, IQ], IP2, '', 'q2')
>>> registry.lookup([IS, IQ], IP2, '')
'q2'r녁rì}rí(hUhjæubaubeubh3]rîh@)rï}rð(hUhhCh}rñ(h
]h	]h]h]h
]uhhh3]ròh<X3Duplicate implicit target name: "default adapters".ró…rô}rõ(hUhjïubaubaubaU
decorationröNU	citationsr÷]røhUU	nametypesrù}rú(jsNj;Nh0Nj“Nj³Nj|Nh)NjœNjÛNj3NjûNjTNjNXdefault adaptersrûNjtNjÓNhVNuUsettingsrü(cdocutils.frontend
Values
rýorþ}rÿ(Upep_referencesrNUoutput_encoding_error_handlerrUstrictrU
halt_levelrKU
source_urlrNU
dump_settingsrNUdoctitle_xformr‰Udump_pseudo_xmlrNU	tab_widthrKU	id_prefixr	Uh8NUembed_stylesheetr
‰U
docinfo_xformrKUfootnote_backlinksrKUerror_encodingr
UUTF-8rUauto_id_prefixrUidrU
language_coderUenrU	datestamprNUdump_transformsrNUoutput_encodingrUutf-8rUexit_status_levelrKUstrict_visitorrNU_disable_configrNUfile_insertion_enabledrˆU	tracebackrˆUrecord_dependenciesrNUstrip_commentsrNUdebugrNU	generatorrNUgettext_compactr ˆUenvr!NU
strip_classesr"NUpep_file_url_templater#Upep-%04dr$Uinput_encoding_error_handlerr%jUexpose_internalsr&NUrfc_referencesr'NU
toc_backlinksr(Uentryr)Utrim_footnote_reference_spacer*‰U_sourcer+hUwarning_streamr,NUinput_encodingr-U	utf-8-sigr.Usectsubtitle_xformr/‰Usource_linkr0NUconfigr1NU
sectnum_xformr2KUerror_encoding_error_handlerr3Ubackslashreplacer4U
_config_filesr5]Udump_internalsr6NUsmart_quotesr7‰Ucloak_email_addressesr8ˆUraw_enabledr9KUstrip_elements_with_classesr:NUpep_base_urlr;U https://www.python.org/dev/peps/r<Ureport_levelr=KUrfc_base_urlr>Uhttps://tools.ietf.org/html/r?U_destinationr@NUsyntax_highlightrAUlongrBubUautofootnote_refsrC]rDU
footnote_refsrE}rFUid_startrGKU
citation_refsrH}rIUsymbol_footnote_refsrJ]rKUtransform_messagesrL]rMU	footnotesrN]rOUnameidsrP}rQ(jsjuj;j=h0h2j“j•j³jµj|j~h)h+jœjžjÛjÝj3j5jûjýjTjVjjjûNjtjvjÓjÕhVhXuUrefnamesrR}rSUtransformerrTNUidsrU}rV(h2h,j5j/hXhRjžj˜j~jxjýj÷jµj¯h+h%j4j/jÕjÏjujojVjPjÝj×hhj=j7j•jjvjpjjÿuUsymbol_footnotesrW]rXhhUindirect_targetsrY]rZUsubstitution_namesr[}r\Ucurrent_liner]NUsubstitution_defsr^}r_Usymbol_footnote_startr`KUautofootnote_startraKU
autofootnotesrb]rch3]rdh,aUcurrent_sourcereNUrefidsrf}rgub.