B 4]F@sdZddlmZddlmZddlmZddlmZddlmZddlmZeZ Gd d d e Z Gd d d e Z Gd dde ZeZejZZejZZejZZddZddZddZddZdS)aDefines SQLAlchemy's system of class instrumentation. This module is usually not directly visible to user applications, but defines a large part of the ORM's interactivity. instrumentation.py deals with registration of end-user classes for state tracking. It interacts closely with state.py and attributes.py which establish per-instance and per-class-attribute instrumentation, respectively. The class instrumentation system can be customized on a per-class or global basis using the :mod:`sqlalchemy.ext.instrumentation` module, which provides the means to build and specify alternate instrumentation forms. .. versionchanged: 0.8 The instrumentation extension system was moved out of the ORM and into the external :mod:`sqlalchemy.ext.instrumentation` package. When that package is imported, it installs itself within sqlalchemy.orm so that its more comprehensive resolution mechanics take effect. )base) collections)exc) interfaces)state)utilc@seZdZdZejZejZe e eZ dZ ejZdZddZddZddZed d Zed d Zed dZeddZe jddZdZddZd[ddZddZddZddZ ddZ!e jdd Z"d!d"Z#d#d$Z$e j%d%d&Z&e j%d'd(Z'e j%d)d*Z(d\d,d-Z)d.d/Z*d0d1Z+d]d2d3Z,d4d5Z-d6d7Z.d8d9Z/d:d;Z0dd?Z2d@dAZ3d^dBdCZ4dDdEZ5edFdGZ6d_dHdIZ7d`dJdKZ8dLdMZ9dNdOZ:dPdQZ;dRdSZe>Z?dXdYZ@dS)b ClassManagerz,tracks state information at the class level.NcCs||_i|_d|_i|_i|_dddd|jjDD|_x|jD]}||qDW|jj ||x,|j D]"}t |}|dk rn|j |jqnW||d|jkrtd|dS)NcSsg|]}|dk r|qS)N).0mgrr r Q/opt/alt/python37/lib64/python3.7/site-packages/sqlalchemy/orm/instrumentation.py Bsz)ClassManager.__init__..cSsg|]}t|trt|qSr ) isinstancetypemanager_of_class)r rr r r rDs__del__z__del__() method on class %s will cause unreachable cycles and memory leaks, as SQLAlchemy instrumentation often creates reference cycles. Please remove this method.)class_infonew_init local_attrs originals __bases__Z_basesupdatedispatchZ_eventsZ_new_classmanager_instance__mro__rZ_updatemanage_instrument_init__dict__rwarn)selfrZbase_Zbaseclsr r r r __init__:s*   zClassManager.__init__cCst|S)N)id)r r r r __hash__`szClassManager.__hash__cCs||kS)Nr )r otherr r r __eq__cszClassManager.__eq__cCs d|jkS)Nmapper)r)r r r r is_mappedfszClassManager.is_mappedcCst|S)N) frozenset)r r r r _all_key_setjszClassManager._all_key_setcCstdd|DS)NcSsg|]}|jjr|jqSr )implZ collectionkey)r attrr r r rqsz6ClassManager._collection_impl_keys..)r(values)r r r r _collection_impl_keysnsz"ClassManager._collection_impl_keyscCstdd|DS)NcSsg|]}|jjr|jqSr )r*Zaccepts_scalar_loader)r r,r r r rxsz5ClassManager._scalar_loader_impls..)r(r-)r r r r _scalar_loader_implstsz!ClassManager._scalar_loader_implscCst|jdS)N)rZUnmappedClassErrorr)r r r r r&~szClassManager.mapperccsn|dkrt}xZ|jjD]N}xHt|j|D]4}|||j|}t|tjr.|j r.||fVq.WqWdS)areturn an iterator of all classbound attributes that are implement :class:`.InspectionAttr`. This includes :class:`.QueryableAttribute` as well as extension types such as :class:`.hybrid_property` and :class:`.AssociationProxy`. N) setrrr differenceaddrrZInspectionAttrZ is_attribute)r Zexcludesuperclsr+valr r r _all_sqla_attributess    z!ClassManager._all_sqla_attributescCs.x(|jjD]}||jkr |j|Sq W|SdS)z5return an attribute on the class without tripping it.N)rrr)r r+defaultr3r r r _get_class_attr_mros z ClassManager._get_class_attr_mrocCs||ko||jdk S)z\Return True if the given attribute is fully initialized. i.e. has an impl. N)r*)r r+r r r _attr_has_implszClassManager._attr_has_implcCst|}|dkrt|}|S)aCreate a new ClassManager for a subclass of this ClassManager's class. This is called automatically when attributes are instrumented so that the attributes can be propagated to subclasses against their own class-local manager, without the need for mappers etc. to have already pre-configured managers for the full class hierarchy. Mappers can post-configure the auto-generated ClassManager when needed. N)r_instrumentation_factorycreate_manager_for_cls)r clsmanagerr r r _subclass_managers  zClassManager._subclass_managercCs*|jj|_t|j||_|d|jdS)Nr!)rr! original_init_generate_initrinstall_member)r r r r rs zClassManager._instrument_initcCs|jr|dd|_dS)Nr!)runinstall_member)r r r r _uninstrument_inits zClassManager._uninstrument_initcCs|j||jtjS)N)rZ first_initrrZ InstanceState)r r r r _state_constructorszClassManager._state_constructorcCst|j|j|dS)z0Mark this instance as the manager for its class.N)setattrr MANAGER_ATTR)r r r r rszClassManager.managecCst|j|jdS)z)Dissasociate this manager from its class.N)delattrrrE)r r r r disposeszClassManager.disposecCstS)N)_default_manager_getter)r r r r manager_getterszClassManager.manager_gettercCstS)zReturn a (instance) -> InstanceState callable. "state getter" callables should raise either KeyError or AttributeError if no InstanceState could be found for the instance. )_default_state_getter)r r r r state_getters zClassManager.state_gettercCstS)N)_default_dict_getter)r r r r dict_getterszClassManager.dict_getterFcCsl|r||jkr*dSn||j|<|||t||||<x*|jD]}||}|||dqHWdS)NT)rinstall_descriptor_memoized_key_collectionexpire_instancer__subclasses__r=instrument_attribute)r r+inst propagatedr;r<r r r rRs     z!ClassManager.instrument_attributeccsTxN|jD]@}t|}|dk r ||k r |V|r x|dD] }|Vq>Wq WdS)NT)rrQrsubclass_managers)r recursiver;r mr r r rUszClassManager.subclass_managerscCstj|j|||dS)N)r9rZattribute_instrumentr)r r+r r r post_configure_attributesz%ClassManager.post_configure_attributecCsr||kr dS|r ||jkr2dSn|j|=||t|||=x*|jD]}t|}|rN||dqNWdS)NT)runinstall_descriptorrOrPrrQruninstrument_attribute)r r+rTr;r<r r r rZs   z#ClassManager.uninstrument_attributecCsH|d|_|_|jx$t|D]}||jkr(||q(WdS)zsz"ClassManager.initialize_collectioncCs|r ||kS||jkSdS)N)r)r r+searchr r r is_instrumentedEszClassManager.is_instrumentedcCs ||jS)N)r*)r r+r r r reKszClassManager.get_implcCs t|S)N)iterr-)r r r r attributesNszClassManager.attributescCs2|j|j}|dkr"|||}||||S)N)r__new__rC _state_setter)r rinstancer r r new_instanceTs   zClassManager.new_instancecCs$|dkr|||}|||dS)N)rCrm)r rnrr r r setup_instance[s zClassManager.setup_instancecCst||jdS)N)rFr^)r rnr r r teardown_instance`szClassManager.teardown_instancecCs t||S)N)_SerializeManager)r r state_dictr r r _serializecszClassManager._serializecCsTt||jrdS|j|jk r4|jr4||j|S|||}||||SdS)zInstall a default InstanceState if none is present. A private convenience method used by the __init__ decorator. FN) hasattrr^r __class__r'r=_new_state_if_nonerCrm)r rnrr r r rwfs   zClassManager._new_state_if_nonecCs t||jS)N)rur^)r rnr r r has_state|szClassManager.has_statecCs||j||dS)ZTODO) optimistic)reZ hasparent)r rr+ryr r r has_parentszClassManager.has_parentcCsdS)z=All ClassManagers are non-zero regardless of attribute state.Tr )r r r r __bool__szClassManager.__bool__cCsd|jj|jt|fS)Nz<%s of %r at %x>)rv__name__rr")r r r r __repr__szClassManager.__repr__)N)N)F)F)F)N)N)F)Ar| __module__ __qualname____doc__rZDEFAULT_MANAGER_ATTRrEZDEFAULT_STATE_ATTRr^ staticmethodrZ attrsetterrmZdeferred_scalar_loaderobjectr!r>rfr#r%propertyr'rOr)r.r/Zmemoized_propertyr&r5r7r8r=rrBrCrrGZ hybridmethodrIrKrMrRrUrXrZr]rNrYr@rArdrgrirerkrorprqrtrwrxrzr{Z __nonzero__r}r r r r r ,sf&                  r c@s eZdZdZddZddZdS)rrzProvide serialization of a :class:`.ClassManager`. The :class:`.InstanceState` uses ``__init__()`` on serialize and ``__call__()`` on deserialize. cCs |j|_|j}|j||dS)N)rr<rpickle)r rdr<r r r r!sz_SerializeManager.__init__cCsjt|j|_}|dkr,t|d|jn|jrD|jjsD|j|dk rX| |||j ||dS)NzxCannot deserialize object of type %r - no mapper() has been configured for this class within the current Python process!) rrr<rZUnmappedInstanceErrorr'r&Z configuredZ_configure_allrprZunpickle)r rrSrsr<r r r __call__s   z_SerializeManager.__call__N)r|r~rrr!rr r r r rrsrrc@s0eZdZdZddZddZddZdd Zd S) InstrumentationFactoryz'Factory for new ClassManager instances.cCs`|dk s tt|dkst||\}}|dkr>t}||}|||||_|j||S)N)AssertionErrorr_locate_extended_factoryr _check_conflictsrfrZclass_instrument)r rr<rfr r r r:s   z-InstrumentationFactory.create_manager_for_clscCsdS)z2Overridden by a subclass to do an extended lookup.)NNr )r rr r r rsz/InstrumentationFactory._locate_extended_factorycCsdS)z;Overridden by a subclass to test for conflicting factories.Nr )r rrfr r r rsz'InstrumentationFactory._check_conflictscCs@t|}|||j|tj|jkrBuild an __init__ decorator that triggers ClassManager events.zdef __init__(%(apply_pos)s): new_state = class_manager._new_state_if_none(%(self_arg)s) if new_state: return new_state._initialize_instance(%(apply_kw)s) else: return original__init__(%(apply_kw)s) F)ZgroupedZim_func func_defaultsN __defaults____kwdefaults__r!) r!rrZformat_argspec_initZpy2kralocalscopyexecrZ_sa_original_initrr) rZ class_managerZoriginal__init__Z func_bodyZ func_varsZ func_textfuncrZfunc_kw_defaultsenvr!r r r r?s(      r?N)rrrrrrrZ!group_expirable_memoized_propertyrOdictr rrrrr9Zinstance_staterJZ instance_dictrLrrHrrrir?r r r r s(      g")