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|dds td||g}xd|r|d}||||k rb||jkrb||q(||jkrv| ||j| |j q(Wt ||dS)N_sa_propagate_class_eventsTz.Can't assign an event directly to the %s classr)dispatch_targetr0r InvalidRequestErrorpopr__subclasses__r%update_subclass_assign_cls_collection appendleft _listen_fnr_stored_in_collection)r event_key propagatetargetstackclsrrrinsertvs      z_ClsLevelDispatch.insertcCs|j}t|dds td||g}xd|r|d}||||k rb||jkrb||q(||jkrv| ||j| |j q(Wt ||dS)Nr?Tz.Can't assign an event directly to the %s classr)r@r0r rArBrrCr%rDrErrGrrH)rrIrJrKrLrMrrrrs      z_ClsLevelDispatch.appendcCs,t|ddrt|j|<n t|j|<dS)Nr?T)r0 collectionsdequer%r)rrKrrrrEs z(_ClsLevelDispatch._assign_cls_collectioncsb||jkr|||j|x>|jddD],}||jkr.fdd|j|Dq.WdS)Nrcsg|]}|kr|qSrr).0r3)clslevelrr sz5_ClsLevelDispatch.update_subclass..)r%rE__mro__r)rrKrMr)rRrrDs    z!_ClsLevelDispatch.update_subclasscCsZ|j}|g}x<|rH|d}||||jkr|j||jqWt||dS)Nr) r@rBrrCr%rrGr_removed_from_collection)rrIrKrLrMrrrrs  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)rrrr1rr5r9r6rNrrErDrrrZrrrrr 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%rDr\r^r!)rr\ target_clsrrrr5s    z_EmptyListener.__init__cCs2t|j|j}t||j|kr.t||j|n|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!setattr)rrYresultrrrrZs 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)r^)rr+r=r3rrr__call__s z_EmptyListener.__call__cCs t|jS)N)lenr^)rrrr__len__sz_EmptyListener.__len__cCs t|jS)N)rr^)rrrrrsz_EmptyListener.__iter__cCs t|jS)N)r,r^)rrrr__bool__ sz_EmptyListener.__bool__N)rrrr1 frozensetrJ listenersrr5rZrd exec_oncerNrrrrergrrh __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)rorn)rr+r=rrrrks z_CompoundListener.exec_oncecOs8x|jD]}|||qWx|jD]}|||q"WdS)zExecute this event.N)r^rj)rr+r=r3rrrre#s  z_CompoundListener.__call__cCst|jt|jS)N)rfr^rj)rrrrrg+sz_CompoundListener.__len__cCst|j|jS)N)rr^rj)rrrrr.sz_CompoundListener.__iter__cCst|jp |jS)N)r,rjr^)rrrrrh1sz_CompoundListener.__bool__N) rrrrrprkrergrrhrlrrrrrms rmc@sNeZdZdZdZddZddZddd Zd d Zd d Z ddZ ddZ dS)r`zInstance-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. )r^r\r!rjrJr&cCsJ||jkr||d|_|j||_||_|j|_t|_t |_ dS)NF) r%rDror^r\r!rOrPrjrVrJ)rr\r_rrrr5Js    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)rrYrrrrZTsz_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)rJ)rQl)existing_listener_setonly_propagaterrrrSesz/_ListenerCollection._update..N)rjrVrJr<runionrZ_stored_in_collection_multi)rrrsZexisting_listenersZother_listenersZ to_associater)rrrsrr_update]s   z_ListenerCollection._updatecCs$|||jr |r |j|jdS)N)Zprepend_to_listrjrJaddrG)rrIrJrrrrNqsz_ListenerCollection.insertcCs$|||jr |r |j|jdS)N)Zappend_to_listrjrJrvrG)rrIrJrrrrvsz_ListenerCollection.appendcCs,|j|j|j|jt||dS)N)rjrrGrJdiscardrrU)rrIrrrr{sz_ListenerCollection.removecCs&t||j|j|jdS)N)rrXrjrJr)rrrrrs z_ListenerCollection.clearN)T) rrrr1rr5rZrurNrrrrrrrr`7s  r`c@sTeZdZdZddZeddZddZdd Zd d Z d d Z ddZ ddZ dS)_JoinedListener)r\r!localr^cCs$d|_||_||_||_|j|_dS)NF)ror\r!ryr^)rr\r!ryrrrr5s z_JoinedListener.__init__cCst|j|jS)N)r0r\r!)rrrrrjsz_JoinedListener.listenerscCs|j||S)N)ryr9)rr3r8rrrr9sz_JoinedListener._adjust_fn_speccCs|j||_|_|S)N)ryrZr^)rrYrrrrZsz_JoinedListener.for_modifycCs|j||dS)N)ryrN)rrIrJrrrrNsz_JoinedListener.insertcCs|j||dS)N)ryr)rrIrJrrrrsz_JoinedListener.appendcCs|j|dS)N)ryr)rrIrrrrsz_JoinedListener.removecCs tdS)N)rc)rrrrrsz_JoinedListener.clearN) rrrrr5propertyrjr9rZrNrrrrrrrrxs rx)r1Z __future__rrrO itertoolsrrrrr r r Z MemoizedSlotsr objectrr r[r]rmr`rxrrrrs&        =&O