ezdZddlZddlZddlmZddlmZddlmZddlmZddlm Z ddl m Z dd l m Z d d gZ Gd d ZeZe GddZe GddeZGddZGddeeZee Gdd eZGddeeZee Gdd eZdZdZdZdZy)zAdapter management N) implementer) providedBy Interface)ro)IAdapterRegistry)_normalize_name) _use_c_implAdapterRegistryVerifyingAdapterRegistryceZdZdZdZdZddZdZeddZ dZ e Z e ZeZeZd Zd Zd Zd Zd ZddZeddZdZdZddZdZdZdZddZ dZ!dZ"y)BaseAdapterRegistrya A basic implementation of the data storage and algorithms required for a :class:`zope.interface.interfaces.IAdapterRegistry`. Subclasses can set the following attributes to control how the data is stored; in particular, these hooks can be helpful for ZODB persistence. They can be class attributes that are the named (or similar) type, or they can be methods that act as a constructor for an object that behaves like the types defined here; this object will not assume that they are type objects, but subclasses are free to do so: _sequenceType = list This is the type used for our two mutable top-level "byorder" sequences. Must support mutation operations like ``append()`` and ``del seq[index]``. These are usually small (< 10). Although at least one of them is accessed when performing lookups or queries on this object, the other is untouched. In many common scenarios, both are only required when mutating registrations and subscriptions (like what :meth:`zope.interface.interfaces.IComponents.registerUtility` does). This use pattern makes it an ideal candidate to be a :class:`~persistent.list.PersistentList`. _leafSequenceType = tuple This is the type used for the leaf sequences of subscribers. It could be set to a ``PersistentList`` to avoid many unnecessary data loads when subscribers aren't being used. Mutation operations are directed through :meth:`_addValueToLeaf` and :meth:`_removeValueFromLeaf`; if you use a mutable type, you'll need to override those. _mappingType = dict This is the mutable mapping type used for the keyed mappings. A :class:`~persistent.mapping.PersistentMapping` could be used to help reduce the number of data loads when the registry is large and parts of it are rarely used. Further reductions in data loads can come from using a :class:`~BTrees.OOBTree.OOBTree`, but care is required to be sure that all required/provided values are fully ordered (e.g., no required or provided values that are classes can be used). _providedType = dict This is the mutable mapping type used for the ``_provided`` mapping. This is separate from the generic mapping type because the values are always integers, so one might choose to use a more optimized data structure such as a :class:`~BTrees.OIBTree.OIBTree`. The same caveats regarding key types apply as for ``_mappingType``. It is possible to also set these on an instance, but because of the need to potentially also override :meth:`_addValueToLeaf` and :meth:`_removeValueFromLeaf`, this may be less useful in a persistent scenario; using a subclass is recommended. .. versionchanged:: 5.3.0 Add support for customizing the way internal data structures are created. .. versionchanged:: 5.3.0 Add methods :meth:`rebuild`, :meth:`allRegistrations` and :meth:`allSubscriptions`. ) lookupqueryMultiAdapterlookup1 queryAdapter adapter_hook lookupAllnames subscriptions subscribersrc|j|_|j|_|j|_|j ||_yN) _sequenceType _adapters _subscribers _providedType _provided _createLookup __bases__selfbasess 8/usr/lib/python3/dist-packages/zope/interface/adapter.py__init__zBaseAdapterRegistry.__init__sP++-!..0++-  cx||jd<tj||_|j|y)z If subclasses need to track when ``__bases__`` changes, they can override this method. Subclasses must still call this method. r N)__dict__rchangedr!s r$ _setBaseszBaseAdapterRegistry._setBasess-&+ k"%%+ Tr&c |jdS)Nr )r(r"s r$zBaseAdapterRegistry.sdmmK&@r&c$|j|Sr)r*r!s r$r-zBaseAdapterRegistry.sT^^E-Br&c|j||_|jD]%}t|j||j|<'yr) LookupClass _v_lookup _delegatedgetattrr()r"names r$rz!BaseAdapterRegistry._createLookupsB))$/OO @D")$..$"?DMM$  @r&c||fS||fzS)a Add the value *new_item* to the *existing_leaf_sequence*, which may be ``None``. Subclasses that redefine `_leafSequenceType` should override this method. :param existing_leaf_sequence: If *existing_leaf_sequence* is not *None*, it will be an instance of `_leafSequenceType`. (Unless the object has been unpickled from an old pickle and the class definition has changed, in which case it may be an instance of a previous definition, commonly a `tuple`.) :return: This method returns the new value to be stored. It may mutate the sequence in place if it was not ``None`` and the type is mutable, but it must also return it. .. versionadded:: 5.3.0 )r"existing_leaf_sequencenew_items r$_addValueToLeafz#BaseAdapterRegistry._addValueToLeafs( " ); % 33r&cJt|Dcgc] }||k7s | c}Scc}w)aa Remove the item *to_remove* from the (non-``None``, non-empty) *existing_leaf_sequence* and return the mutated sequence. If there is more than one item that is equal to *to_remove* they must all be removed. Subclasses that redefine `_leafSequenceType` should override this method. Note that they can call this method to help in their implementation; this implementation will always return a new tuple constructed by iterating across the *existing_leaf_sequence* and omitting items equal to *to_remove*. :param existing_leaf_sequence: As for `_addValueToLeaf`, probably an instance of `_leafSequenceType` but possibly an older type; never `None`. :return: A version of *existing_leaf_sequence* with all items equal to *to_remove* removed. Must not return `None`. However, returning an empty object, even of another type such as the empty tuple, ``()`` is explicitly allowed; such an object will never be stored. .. versionadded:: 5.3.0 )tuple)r"r7 to_removevs r$_removeValueFromLeafz(BaseAdapterRegistry._removeValueFromLeafs$4!7JA1 >aJKKJs  cd|xjdz c_|jj|yN) _generationr1r))r"originally_changeds r$r)zBaseAdapterRegistry.changeds& A 12r&ct|ts td||j||||yt |Dcgc] }t |c}}t |}t|}|j}t||kr.|j|jt||kr.||}||fz} | D],} |j| } | |j} | || <| }.|j||ury|||<|jj|ddz} | |j|<| dk(r|jj||j|ycc}w)Nname is not a stringrrA) isinstancestr ValueError unregisterr;_convert_None_to_Interfacer lenrappend _mappingTypegetrr1 add_extendorr)) r"requiredprovidedr4valuerorderbyorder componentskeykdns r$registerzBaseAdapterRegistry.registers_$$34 4 = OOHhe < JA4Q7JKt$H ..'le# NN4,,. /'le#U^ ($ Aq!Ay%%' ! 1 J   >>$ 5 (  4 NN  x +a /#$x 6 NN ' ' 1 T5KsE(ct|Dcgc] }t|c}}t|}t||kry||}||fz}|D]} |j| } | y| }|j|Scc}wr)r;rJrKrN) r"rUrPrQr4rSrTrVrWrXrYs r$ _find_leafzBaseAdapterRegistry._find_leaf*s JA4Q7JKH  w<5 U^ ($ Aq!AyJ   ~~d##KsA7cP|j|j||t|Sr)r]rr )r"rPrQr4s r$ registeredzBaseAdapterRegistry.registered@s( NN   D !   r&c#K|dk(r#|jD]\}}||fz|fy|jD])\}}||fz}|j||dz |Ed{+y7w)NrrA)items_allKeys)clsrViparent_krXr= new_parent_ks r$rbzBaseAdapterRegistry._allKeysHs 6"((* )1!oq(( )#((* @1'1$ <<1q5,??? @?sAA* A(!A*c#Kt|D]L\}}|j||dzD]/\}}t||dzk(sJ|d|}|d}|d}||||f1Nyw)NrA) enumeraterbrK) r"rUrdrVrWrRrPrQr4s r$ _all_entriesz BaseAdapterRegistry._all_entriesRs'w/ 8MAz#mmJA> 8 U3x1q5(((r7r72w477  8 8sAAc#VK|j|jEd{y7w)aT Yields tuples ``(required, provided, name, value)`` for all the registrations that this object holds. These tuples could be passed as the arguments to the :meth:`register` method on another adapter registry to duplicate the registrations this object holds. .. versionadded:: 5.3.0 N)rlrr,s r$allRegistrationsz$BaseAdapterRegistry.allRegistrationsds $$T^^444s )')Nc|t|Dcgc] }t|c}}t|}|j}|t|k\ry||}||fz} g} | D],} |j | } | y| j || f| }.|j |} | y|| |ury||=|s1t | D]\}} || } | rn|| =|r|ds |d=|r|ds |j|dz }|dk(r)|j|=|jj|n||j|<|j|ycc}w)NFrjrAr) r;rJrKrrNrLreversedrr1remove_extendorr))r"rPrQr4rRrSrTrUrVrWlookupsrXrYoldcomprZs r$rIzBaseAdapterRegistry.unregisterqsmJA4Q7JKH .. CL U^ ($ Aq!Ay NNJ? +J  nnT" ;   Cu$4  t  $G, aGQ  '"+BK'"+ NN8 $q ( 6x( NN * *8 4'(DNN8 $ T[KsD9c~t|Dcgc] }t|c}}d}t|}|j}t||kr.|j |j t||kr.||}||fz} | D],} |j | } | |j } | || <| }.|j|j ||||<|N|jj |ddz} | |j|<| dk(r|jj||j|ycc}w)NrrA) r;rJrKrrLrMrNr9rr1rOr)) r"rPrQrRrSr4rTrUrVrWrXrYrZs r$ subscribezBaseAdapterRegistry.subscribes4JA4Q7JKH ##'le# NN4,,. /'le#U^ ($ Aq!Ay%%' ! 1 J   // t0DeL 4  ""8Q/!3A'(DNN8 $Av++H5 T1KsD:cV|j|j||dxsd}||vr|SdS)Nrvr6)r]r)r"rPrQ subscriberrs r$ subscribedzBaseAdapterRegistry.subscribedsCoo           (;6z@D@r&c#rK|j|jD]\}}}}|D] }|||f yw)aM Yields tuples ``(required, provided, value)`` for all the subscribers that this object holds. These tuples could be passed as the arguments to the :meth:`subscribe` method on another adapter registry to duplicate the registrations this object holds. .. versionadded:: 5.3.0 N)rlr)r"rPrQ_namerRr=s r$allSubscriptionsz$BaseAdapterRegistry.allSubscriptionssM150A0A$BSBS0T . ,Hhu .1-- . .s57ct|Dcgc] }t|c}}t|}|j}|t|k\ry||}||fz}g} |D],} |j | } | y| j || f| }.|j d} | syt| } |d}n|j | |}~ t|| k(ry|r||d<n4|d=t| D]\}} || } | rn|| =|r|ds |d=|r|ds |[|j|t|z| z }|dk(r)|j|=|jj|n||j|<|j|ycc}w)Nrvr6rjr) r;rJrKrrNrLr>rprr1rqr))r"rPrQrRrSrTrUrVrWrrrXrYrslen_oldnewrtrZs r$ unsubscribezBaseAdapterRegistry.unsubscribesJA4Q7JKH ## CL U^ ($ Aq!Ay NNJ? +J  nnR  c( = C++C7C  s8w    JrN2#G, aGQ  '"+BK'"+  x(3s83g=AAvNN8,..x8+,x( TEKsE8c|j}|j}d}||}||}|j|j|D]}|j||D]}|j |y)aE Rebuild (and replace) all the internal data structures of this object. This is useful, especially for persistent implementations, if you suspect an issue with reference counts keeping interfaces alive even though they are no longer used. It is also useful if you or a subclass change the data types (``_mappingType`` and friends) that are to be used. This method replaces all internal data structures with new objects; it specifically does not re-use any storage. .. versionadded:: 5.3.0 c| t|}tj|f|S#t$rtdcYSwxYwNr6)next StopIterationiter itertoolschain)itfirsts r$bufferz+BaseAdapterRegistry.rebuild..buffer/s? R??E8R0 0! Bx s $;;N)rnr}r%r r[rw)r" registrationsrrargss r$rebuildzBaseAdapterRegistry.rebuilds&--/ --/  1}- }-  dnn%" !D DMM4  !! "D DNND ! "r&cGdd}|S)NceZdZiZy)2BaseAdapterRegistry.get..XXXTwistedFakeOutN)__name__ __module__ __qualname__ selfImpliedr6r&r$XXXTwistedFakeOutrQsKr&rr6)r"_rs r$rNzBaseAdapterRegistry.getPs    r&r6rvr)#rrr__doc__r2rBr%r*propertyr rlistrr;_leafSequenceTypedictrMrr9r>r)r[r]r_ classmethodrbrlrnrIrwrzr}rrrNr6r&r$rr@s6r2J K-^ @BI@MLM40L83!F$, @@8$ 5.`6A .CJ3"n!r&rcXeZdZdZd dZdZd dZd dZd dZd fd Z dZ d Z xZ S) LookupBasec.i|_i|_i|_yr)_cache_mcache_scacher,s r$r%zLookupBase.__init__[s   r&c|jj|jj|jjyr)rclearrr)r"ignoreds r$r)zLookupBase.changed`s2   r&c|jj|}|i}||j|<|r|j|}|i}|||<|}|Sr)rrN)r"rQr4cachecs r$ _getcachezLookupBase._getcacheesY ) =E$)DKK !  $Ayd E r&ct|ts td|j||}t |}t |dk(r|j |dt}n|j t |t}|tur8|j|||}t |dk(r |||d<n||t |<||S|S)NrErAr) rFrGrHrr;rKrN_not_in_mapping_uncached_lookupr"rPrQr4defaultrresults r$rzLookupBase.lookuprs$$34 4x.? x=A YYx{ON r&ct|ts td|j||}|j |t }|t ur|j |f|||S||S|SNrE)rFrGrHrrNrrrs r$rzLookupBase.lookup1sf$$34 4x.8_5 _ $;;|XtWE E >N r&c*|j||||Sr)r)r"objectrQr4rs r$rzLookupBase.queryAdapters  64AAr&c0t|ts tdt|}|j ||}|j |t }|t ur|j|f||}|(t|tr |j}||}||S|Sr) rFrGrHrrrNrrsuper__self__) r"rQrr4rrPrfactoryr __class__s r$rzLookupBase.adapter_hooks$$34 4f%x.))Ho6 o %kk8,$?G  &%(V_F! r&c|jj|}|i}||j|<t|}|j|t}|tur|j ||}|||<|Sr)rrNr;r_uncached_lookupAllr"rPrQrrs r$rzLookupBase.lookupAllso   * =E%*DLL "?8_5 _ $--hAF$E(O r&c|jj|}|i}||j|<t|}|j|t}|tur|j ||}|||<|Sr)rrNr;r_uncached_subscriptionsrs r$rzLookupBase.subscriptionsso   * =E%*DLL "?8_5 _ $11(HEF$E(O r&rrvN) rrrr%r)rrrrrrr __classcell__rs@r$rrXs1  , B$  r&rc*eZdZdZdZdZdZdZy) VerifyingBasectj|||jjdd|_|jDcgc]}|j c}|_ycc}wr@)LookupBaseFallbackr) _registryr _verify_rorB_verify_generations)r"rCrSs r$r)zVerifyingBase.changedsI""4);<..++AB/;???#KaAMM#K #KsAc|jDcgc]}|jc}|jk7r|jdyycc}wr)rrBrr)r"rSs r$_verifyzVerifyingBase._verifys:$(OO 4qQ]] 4'' ( LL  ( 4sAcP|jtj|||Sr)rrr)r"rQr4s r$rzVerifyingBase._getcaches  !++D(DAAr&cP|jtj|||Sr)rrrr"rPrQs r$rzVerifyingBase.lookupAlls  !++D(HEEr&cP|jtj|||Sr)rrrrs r$rzVerifyingBase.subscriptionss  !//hIIr&N)rrrr)rrrrr6r&r$rrsL  BFJr&rcneZdZfdZd fd ZdZdZdZdZddZ dfd Z d Z d Z d Z d ZxZS)AdapterLookupBasec^||_i|_|jt|yr)r _requiredinit_extendorsrr%)r"registryrs r$r%zAdapterLookupBase.__init__s(!  r&ct|d|jjD]}|}| |j ||jj yr)rr)rkeysrr)r"rrSrs r$r)zAdapterLookupBase.changedsU $$& $AA} d# $ r&cji|_|jjD]}|j|yr) _extendorsrrrO)r"ps r$rz AdapterLookupBase.init_extendors s0)) !A   a  !r&c|j}|jD]`}|j|d}|Dcgc]}|j|s|c}|gz|Dcgc]}|j|r|c}z||<bycc}wcc}wr)r__iro__rN isOrExtends)r"rQrrd extendorses r$rOzAdapterLookupBase.add_extendors__ !! A"q"-I%Aq)=)=a)@A &EqX-A-A!-DE F qM BFsA= A=B.Bc|j}|jD]*}|j|dDcgc] }||k7r| c}||<,ycc}wr)rrrN)r"rQrrdrs r$rqz!AdapterLookupBase.remove_extendorsR__ !! /A(2q"(=/1 !X /JqM //sAc|j}|D]-}|j}||vs|j|d||</yr@)rweakrefrw)r"rP_refsrSrefs r$ _subscribezAdapterLookupBase._subscribe%sB A))+C% D!c  r&c Bt|}d}t|}|jjD]^}|j}|t|k\r|j j j|}|sF||} t| |||d|}|^n|j||SNr) r;rKrrrr1rrN_lookupr) r"rPrQr4rrTrrUrrVs r$rz"AdapterLookupBase._uncached_lookup-s?H )) H((GG $ **5599(CI JZ9dA"$F!  " r&c |j|Dcgc] }t|c}||}||S||Dcgc] }t|tr |jn|"c}}||S|Scc}wcc}wr)rrrFrr) r"objectsrQr4rorrrs r$rz#AdapterLookupBase.queryMultiAdapterDso++g>z!}>$O ?NgVAu)=1::1DVW >N ?Ws A%%A*c zt|}t|}i}t|jjD]Z}|j }|t|k\r|j jj|}|sF||}t||||d|\|j|t|jSr) r;rKrprrrr1rrN _lookupAllrra) r"rPrQrTrrrUrrVs r$rz%AdapterLookupBase._uncached_lookupAllOs?H  !2!23 JH((GG $ **5599(CI J z8Y5 I J "V\\^$$r&cR|j||Dcgc]}|d c}Scc}wr)r)r"rPrQrs r$rzAdapterLookupBase.namesas%"nnXx@A!AAAs $c Vt|}t|}g}t|jjD]_}|j }|t|k\r||f}n(|j jj|}|Lt||||d|d|a|j||S)Nrvr) r;rKrprrrr1rrN_subscriptionsr)r"rPrQrTrrrUrs r$rz)AdapterLookupBase._uncached_subscriptionsds?H  !2!23 -H++GG $%L $..99==hG $ 75>8Y!1e - - " r&c|j|Dcgc] }t|c}|}|d}|D]}|| |Sg}|D]}||}| |j||Scc}wr)rrrL)r"rrQrrr subscriptionrys r$rzAdapterLookupBase.subscribers{s**7+KaJqM+KXV  F - ' g& ' F - . )73 )MM*- . ,LsA rrr)rrrr%r)rrOrqrrrrrrrrrs@r$rrs@ >! /. %$B. r&rc eZdZy) AdapterLookupNrrrr6r&r$rrr&rcHeZdZdZeZdfd ZdZdZfdZ fdZ xZ S)r za A full implementation of ``IAdapterRegistry`` that adds support for sub-registries. cVtj|_t||yr)rWeakKeyDictionary_v_subregistriesrr%)r"r#rs r$r%zAdapterRegistry.__init__s#!( 9 9 ; r&c"d|j|<yr@rrs r$_addSubregistryzAdapterRegistry._addSubregistrys#$a r&c<||jvr|j|=yyrrrs r$_removeSubregistryz"AdapterRegistry._removeSubregistrys# %% %%%a( &r&c|jjdd}|D]}||vs|j||D]}||vs|j|t||y)Nr r6)r(rNrrrr*)r"r#rsrSrs r$r*zAdapterRegistry._setBasessrmm R0 +A~$$T* + (A|!!$' ( % r&ct|||jjD]}|j|yr)rr)rr)r"rCsubrs r$r)zAdapterRegistry.changeds; *+((--/ ,C KK* + ,r&r) rrrrrr0r%rrr*r)rrs@r$r r s-  K %) !,,r&c eZdZy)VerifyingAdapterLookupNrr6r&r$rrrr&rceZdZdZeZy)r z2 The most commonly-used adapter registry. N)rrrrrr0r6r&r$r r s)Kr&c|tS|Srr)xs r$rJrJsyr&c |j}||kr9||jD]&}||}|st|||||dz|} | $| cSy|D]$} || }|s|j|} | "| cSyr@)rN__sro__r) rVspecsrQr4rdlcomponents_getspeccompsrSifaces r$rrs  ^^N1u!H$$ D"4(EE5(D!A#qA=H    E"5)EIIdO=H   r&c |j}||krrs &%$62. HS!S!l( ll l^ J&J J:aaF %z  %,)%,%,P .   )2)) . % )r&