B 4]2@sdZddlmZddlmZddlZddlmZddlZddlm Z ddlm Z d d lm Z d d lm Z d d l m Z Gd dde jZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZdS)aAttribute implementation for _Dispatch classes. The various listener targets for a particular event class are represented as attributes, which refer to collections of listeners to be fired off. These collections can exist at the class level as well as at the instance level. An event is fired off using code like this:: some_object.dispatch.first_connect(arg1, arg2) Above, ``some_object.dispatch`` would be an instance of ``_Dispatch`` and ``first_connect`` is typically an instance of ``_ListenerCollection`` if event listeners are present, or ``_EmptyListener`` if none are present. The attribute mechanics here spend effort trying to ensure listener functions are available with a minimum of function call overhead, that unnecessary objects aren't created (i.e. many empty per-instance listener collections), as well as that everything is garbage collectable when owning references are lost. Other features such as "propagation" of listener functions across many ``_Dispatch`` instances, "joining" of multiple ``_Dispatch`` instances, as well as support for subclass propagation (e.g. events assigned to ``Pool`` vs. ``QueuePool``) are all implemented here. )absolute_import)with_statementN)chain)legacy)registry)exc)util) threadingc@seZdZdZddZdS) RefCollection)refcCst|tjS)N)weakrefr rZ_collection_gced)selfrH/opt/alt/python37/lib64/python3.7/site-packages/sqlalchemy/event/attr.py_memoized_attr_ref1sz RefCollection._memoized_attr_refN)__name__ __module__ __qualname__ __slots__rrrrrr .sr c@s4eZdZddZddZddZddZd d Zd S) _empty_collectioncCsdS)Nr)relementrrrappend6sz_empty_collection.appendcCsdS)Nr)rotherrrrextend9sz_empty_collection.extendcCsdS)Nr)rrrrrremove<sz_empty_collection.removecCstgS)N)iter)rrrr__iter__?sz_empty_collection.__iter__cCsdS)Nr)rrrrclearBsz_empty_collection.clearN)rrrrrrrrrrrrr5s rc@sdeZdZdZdZddZddZddZd d Zd d Z d dZ ddZ ddZ ddZ ddZdS)_ClsLevelDispatchz2Class-level events on :class:`._Dispatch` classes.)name arg_nameshas_kwlegacy_signatures _clslevel __weakref__cCsn|j|_t|}|jdd|_t|j|_t t t t |dgddd|_ t||||_t|_dS)NrZ_legacy_signaturescSs|dS)Nrr)srrrZz,_ClsLevelDispatch.__init__..)key)rr!r Zinspect_getfullargspecargsr"boolZvarkwr#listreversedsortedgetattrr$rZ_augment_fn_docs__doc__rWeakKeyDictionaryr%)rZparent_dispatch_clsfnargspecrrr__init__Rs  z_ClsLevelDispatch.__init__cCsN|r||}|jrJytj|dd}Wntk r:YnXt|||}|S)NT)Zno_self)_wrap_fn_for_kwr$r Zget_callable_argspec TypeErrorrZ_wrap_fn_for_legacy)rr3namedr4rrr_adjust_fn_specbs z!_ClsLevelDispatch._adjust_fn_speccsfdd}|S)Ncs$ttj|}||f|S)N)dictzipr"update)r+kwZargdict)r3rrrwrap_kwos z2_ClsLevelDispatch._wrap_fn_for_kw..wrap_kwr)rr3r>r)r3rrr6nsz!_ClsLevelDispatch._wrap_fn_for_kwcCs|j}t|tstdt|dds2td||g}xd|r|d}|| ||k rt||j krt| |q:||j kr| ||j | |jq:Wt||dS)Nz*Class-level Event targets must be classes._sa_propagate_class_eventsTz.Can't assign an event directly to the %s classr)dispatch_target isinstancetypeAssertionErrorr0r InvalidRequestErrorpopr__subclasses__r%update_subclass_assign_cls_collection appendleft _listen_fnr_stored_in_collection)r event_key propagatetargetstackclsrrrinsertvs"       z_ClsLevelDispatch.insertcCs|j}t|tstdt|dds2td||g}xd|r|d}|| ||k rt||j krt| |q:||j kr| ||j | |jq:Wt||dS)Nz*Class-level Event targets must be classes.r?Tz.Can't assign an event directly to the %s classr)r@rArBrCr0r rDrErrFr%rGrHrrJrrK)rrLrMrNrOrPrrrrs"       z_ClsLevelDispatch.appendcCs,t|ddrt|j|<n t|j|<dS)Nr?T)r0 collectionsdequer%r)rrNrrrrHs z(_ClsLevelDispatch._assign_cls_collectioncsb||jkr|||j|x>|jddD],}||jkr.fdd|j|Dq.WdS)Nrcsg|]}|kr|qSrr).0r3)clslevelrr sz5_ClsLevelDispatch.update_subclass..)r%rH__mro__r)rrNrPr)rUrrGs    z!_ClsLevelDispatch.update_subclasscCsZ|j}|g}x<|rH|d}||||jkr|j||jqWt||dS)Nr) r@rErrFr%rrJr_removed_from_collection)rrLrNrOrPrrrrs  z_ClsLevelDispatch.removecCs<t}x$|jD]}|||qWt||dS)zClear all class level listenersN)setr%valuesr<rr_clear)rZto_clearZ dispatcherrrrrs   z_ClsLevelDispatch.clearcCs|S)zReturn an event collection which can be modified. For _ClsLevelDispatch at the class level of a dispatcher, this returns self. r)robjrrr for_modifysz_ClsLevelDispatch.for_modifyN)rrrr1rr5r9r6rQrrHrGrrr]rrrrr Fs    r c@seZdZdZddZdS)_InstanceLevelDispatchrcCs|j||S)N)parentr9)rr3r8rrrr9sz&_InstanceLevelDispatch._adjust_fn_specN)rrrrr9rrrrr^sr^c@sneZdZdZeZdZdZddZddZ dd Z e Z Z Z ZZd d Zd d ZddZddZeZdS)_EmptyListenerzServes as a proxy interface to the events served by a _ClsLevelDispatch, when there are no instance-level events present. Is replaced by _ListenerCollection when instance-level events are added. r)r_parent_listenersr!cCs2||jkr||||_|j||_|j|_dS)N)r%rGr_rar!)rr_ target_clsrrrr5s    z_EmptyListener.__init__cCsHt|j|j}t||j|kr.t||j|ntt||jtsDt|S)zReturn an event collection which can be modified. For _EmptyListener at the instance level of a dispatcher, this generates a new _ListenerCollection, applies it to the instance, and returns it. ) _ListenerCollectionr_Z _instance_clsr0r!setattrrA_JoinedListenerrC)rr\resultrrrr]s z_EmptyListener.for_modifycOs tddS)Nzneed to call for_modify())NotImplementedError)rr+r=rrr _needs_modifysz_EmptyListener._needs_modifycOsx|jD]}|||qWdS)zExecute this event.N)ra)rr+r=r3rrr__call__s z_EmptyListener.__call__cCs t|jS)N)lenra)rrrr__len__sz_EmptyListener.__len__cCs t|jS)N)rra)rrrrrsz_EmptyListener.__iter__cCs t|jS)N)r,ra)rrrr__bool__ sz_EmptyListener.__bool__N)rrrr1 frozensetrM listenersrr5r]rh exec_oncerQrrrrirkrrl __nonzero__rrrrr`sr`c@sDeZdZdZddZddZddZdd Zd d Zd d Z e Z dS)_CompoundListener)_exec_once_mutex _exec_oncecCstS)N)r ZLock)rrrr_memoized_attr__exec_once_mutexsz1_CompoundListener._memoized_attr__exec_once_mutexc Os:|js6|j$|js,z|||Wdd|_XWdQRXdS)z]Execute this event, but only if it has not been executed already for this collection.NT)rsrr)rr+r=rrrros z_CompoundListener.exec_oncecOs8x|jD]}|||qWx|jD]}|||q"WdS)zExecute this event.N)rarn)rr+r=r3rrrri#s  z_CompoundListener.__call__cCst|jt|jS)N)rjrarn)rrrrrk+sz_CompoundListener.__len__cCst|j|jS)N)rrarn)rrrrr.sz_CompoundListener.__iter__cCst|jp |jS)N)r,rnra)rrrrrl1sz_CompoundListener.__bool__N) rrrrrtrorirkrrlrprrrrrqs rqc@sNeZdZdZdZddZddZddd Zd d Zd d Z ddZ ddZ dS)rczInstance-level attributes on instances of :class:`._Dispatch`. Represents a collection of listeners. As of 0.7.9, _ListenerCollection is only first created via the _EmptyListener.for_modify() method. )rar_r!rnrMr&cCsJ||jkr||d|_|j||_||_|j|_t|_t |_ dS)NF) r%rGrsrar_r!rRrSrnrYrM)rr_rbrrrr5Js    z_ListenerCollection.__init__cCs|S)zReturn an event collection which can be modified. For _ListenerCollection at the instance level of a dispatcher, this returns self. r)rr\rrrr]Tsz_ListenerCollection.for_modifyTcs\j}t|j|jfdd|jD}|||j|}t||dS)zMPopulate from the listeners in another :class:`_Dispatch` object.cs&g|]}|krr|jkr|qSr)rM)rTl)existing_listener_setonly_propagaterrrrVesz/_ListenerCollection._update..N)rnrYrMr<runionrZ_stored_in_collection_multi)rrrwZexisting_listenersZother_listenersZ to_associater)rvrwrr_update]s   z_ListenerCollection._updatecCs$|||jr |r |j|jdS)N)Zprepend_to_listrnrMaddrJ)rrLrMrrrrQqsz_ListenerCollection.insertcCs$|||jr |r |j|jdS)N)Zappend_to_listrnrMrzrJ)rrLrMrrrrvsz_ListenerCollection.appendcCs,|j|j|j|jt||dS)N)rnrrJrMdiscardrrX)rrLrrrr{sz_ListenerCollection.removecCs&t||j|j|jdS)N)rr[rnrMr)rrrrrs z_ListenerCollection.clearN)T) rrrr1rr5r]ryrQrrrrrrrrc7s  rcc@sTeZdZdZddZeddZddZdd Zd d Z d d Z ddZ ddZ dS)re)r_r!localracCs$d|_||_||_||_|j|_dS)NF)rsr_r!r|ra)rr_r!r|rrrr5s z_JoinedListener.__init__cCst|j|jS)N)r0r_r!)rrrrrnsz_JoinedListener.listenerscCs|j||S)N)r|r9)rr3r8rrrr9sz_JoinedListener._adjust_fn_speccCs|j||_|_|S)N)r|r]ra)rr\rrrr]sz_JoinedListener.for_modifycCs|j||dS)N)r|rQ)rrLrMrrrrQsz_JoinedListener.insertcCs|j||dS)N)r|r)rrLrMrrrrsz_JoinedListener.appendcCs|j|dS)N)r|r)rrLrrrrsz_JoinedListener.removecCs tdS)N)rg)rrrrrsz_JoinedListener.clearN) rrrrr5propertyrnr9r]rQrrrrrrrres re)r1Z __future__rrrR itertoolsrrrrr r r Z MemoizedSlotsr objectrr r^r`rqrcrerrrrs&        =&O