U aR@sdZddlmZddlmZddlmZddlmZddlmZddlmZdd lmZe d Z Gd d d ee Z Gd dde ZGddde ZeZejZZejZZejZZdddZddZddZddZdS)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)util) HasMemoizedDEL_ATTRc@s,eZdZdZejZejZe e eZ dZ dZdZdZdZdZee jdddddZeje jdddddZd d Zdbd d ZddZddZddZeddZejddZejddZ ejddZ!ejddZ"e j#ddZdcd d!Z$ddd"d#Z%d$d%Z&d&d'Z'd(d)Z(e j#d*d+Z)d,d-Z*e j+d.d/Z,e j+d0d1Z-e j+d2d3Z.ded4d5Z/d6d7Z0d8d9Z1dfd:d;Z2dd?Z4d@dAZ5dBdCZ6dDdEZ7dFdGZ8dHdIZ9dgdJdKZ:dLdMZ;edNdOZdTdUZ?dVdWZ@dXdYZAdZd[ZBdjd\d]ZCd^d_ZDeDZEd`daZFdS)k ClassManagerz,Tracks state information at the class level.Nz1.4zWThe ClassManager.deferred_scalar_loader attribute is now named expired_attribute_loader)messagecCs|jSNexpired_attribute_loaderselfr_C:\Users\vtejo\AppData\Local\Temp\pip-unpacked-wheel-nyjtotrf\sqlalchemy\orm\instrumentation.pydeferred_scalar_loader?sz#ClassManager.deferred_scalar_loadercCs ||_dSr r)robjrrrrHscCs||_i|_d|_i|_i|_d|_dddd|jjDD|_|jD]}||qH|j j |||j D]"}t |}|dk rn|j |j qn|d|jkrtd|dS)NFcSsg|]}|dk r|qSr r).0mgrrrr Ysz)ClassManager.__init__..cSsg|]}t|trt|qSr) isinstancetypemanager_of_class)rrrrrr[s __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 _finalized __bases__Z_basesupdatedispatchZ_eventsZ_new_classmanager_instance__mro__r_updatemanage__dict__rwarn)rrZbase_Zbaseclsrrrr__init__Qs2    zClassManager.__init__FcCs|r ||_|r|||r"||_|r,||_|rH|jrBtd|||_|jsv|jdk rl|jjt jkrl|jn|jj|_ |r|js| dS)Nz>class is already instrumented, init_method %s can't be applied) mapperZ _add_managerdeclarative_scanrr"AssertionError init_methodrr+object original_init _finalize)rfinalizer,registryr-rr/rrr _update_statews0    zClassManager._update_statecCs*|jr dSd|_|tj|jdSNT)r"_instrument_init_instrumentation_factoryr%Zclass_instrumentrrrrrr2s zClassManager._finalizecCst|Sr )idrrrr__hash__szClassManager.__hash__cCs||kSr r)rotherrrr__eq__szClassManager.__eq__cCs d|jkS)Nr,)r)rrrr is_mappedszClassManager.is_mappedcCst|Sr ) frozensetrrrr _all_key_setszClassManager._all_key_setcCstdd|DS)NcSsg|]}|jjr|jqSr)implZ collectionkeyrattrrrrrsz6ClassManager._collection_impl_keys..r>valuesrrrr_collection_impl_keyssz"ClassManager._collection_impl_keyscCstdd|DS)NcSsg|]}|jjr|jqSr)r@Zaccepts_scalar_loaderrBrrrrsz5ClassManager._scalar_loader_impls..rDrrrr_scalar_loader_implss z!ClassManager._scalar_loader_implscCstdd|DS)NcSsg|] }|jqSrr@rBrrrrsz.ClassManager._loader_impls..rDrrrr _loader_implsszClassManager._loader_implscCst|jdSr )rZUnmappedClassErrorrrrrrr,szClassManager.mapperccsvi}|jjddD]\}|jd}|jD]F}|||||jkrDq(||j|}t|tjr(|jr(||fVq(qdS)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`. rN)rr&r) setdefaultrrZInspectionAttrZ is_attribute)rexcludefoundsuperclsZinheritsrAvalrrr_all_sqla_attributess       z!ClassManager._all_sqla_attributescCs*|jjD]}||jkr|j|Sq|S)z5return an attribute on the class without tripping it.N)rr&r))rrAdefaultrOrrr_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. NrHrrArrr_attr_has_implszClassManager._attr_has_implcCs t|ddS)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. F)r3)register_class)rclsrrr_subclass_managers zClassManager._subclass_managercCs$t|j||j|_|d|jdS)Nr+)_generate_initrr1rinstall_memberrrrrr7 szClassManager._instrument_initcCs|j||jtjSr )r%Z first_initrrZ InstanceStaterrrr_state_constructorszClassManager._state_constructorcCst|j|j|dS)z0Mark this instance as the manager for its class.N)setattrr MANAGER_ATTRrrrrr(szClassManager.managecCstSr )_default_manager_getterrrrrmanager_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_getterrrrr state_getters zClassManager.state_gettercCstSr )_default_dict_getterrrrr dict_getter(szClassManager.dict_gettercCsf|r||jkr*dSn||j|<|||||||<|jD]}||}|||dqDdSr6)r install_descriptor_reset_memoizationsr__subclasses__rXinstrument_attribute)rrAinst propagatedrWmanagerrrrrg,s    z!ClassManager.instrument_attributeccsL|jD]<}t|}|dk r ||k r |V|r |dD] }|Vq:q dSr6)rrfrsubclass_managers)r recursiverWrmrrrrk:szClassManager.subclass_managerscCstj|j|||dSr )r8r%Zattribute_instrumentrrTrrrpost_configure_attributeCs z%ClassManager.post_configure_attributecCsl||kr dS|r ||jkr2dSn|j|=|||||=|jD]}t|}|rJ||dqJdSr6)r uninstall_descriptorrerrfruninstrument_attribute)rrArirWrjrrrrpHs  z#ClassManager.uninstrument_attributecCsxt|jD]}||q d|_|_|_|jt|D]}||jkr>| |q>|j |j j krtt |j |j dS)z)r__name__rr9rrrr__repr__s zClassManager.__repr__)FNNNNN)N)N)F)F)F)N)N)F)Gr __module__ __qualname____doc__rZDEFAULT_MANAGER_ATTRr]ZDEFAULT_STATE_ATTRrw staticmethodrZ attrsetterrrr/rr,r-r4property deprecatedrsetterr+r5r2r:r<r=r Zmemoized_attributer?rFrGrIZmemoized_propertyrQrSrUrXr7r[r(Z hybridmethodr_rarcrgrkrnrprurdrorZrrr}rrr~rrrrrrrrr __nonzero__rrrrrr -s  ( %        !               r c@s eZdZdZddZddZdS)rzProvide serialization of a :class:`.ClassManager`. The :class:`.InstanceState` uses ``__init__()`` on serialize and ``__call__()`` on deserialize. cCs |j|_|j}|j||dSr )rrjr%pickle)rrdrjrrrr+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!) rrrjrZUnmappedInstanceErrorr=r,Z configuredZ_check_configurerr%Zunpickle)rrrhrrjrrr__call__s  z_SerializeManager.__call__N)rrrrr+rrrrrrsrc@s0eZdZdZddZddZddZdd Zd S) InstrumentationFactoryz'Factory for new ClassManager instances.cCsT|dk s tt|dkst||\}}|dkr>t}||}|||||_|Sr )r.r_locate_extended_factoryr _check_conflictsr)rrrjrrrrcreate_manager_for_clss  z-InstrumentationFactory.create_manager_for_clscCsdS)z2Overridden by a subclass to do an extended lookup.)NNr)rrrrrrsz/InstrumentationFactory._locate_extended_factorycCsdS)z;Overridden by a subclass to test for conflicting factories.Nr)rrrrrrrsz'InstrumentationFactory._check_conflictscCs t|}||j|dSr )rrur%Zclass_uninstrument)rrrjrrrrusz!InstrumentationFactory.unregisterN)rrrrrrrrurrrrrs rTNcCs4t|}|dkrt|}|j||||||d|S)z_Register class instrumentation. Returns the existing or newly created class manager. N)r,r4r-rr/r3)rr8rr5)rr3r,r4r-rr/rjrrrrV,s  rVcCst|dS)z!Unregister class instrumentation.N)r8ru)rrrrunregister_classJsrcCst|jj|ddS)zReturn True if the given attribute on the given instance is instrumented by the attributes package. This function may be used regardless of instrumentation applied directly to the class, i.e. no descriptors are required. T)r)rrr)rrArrrrPs rc Cs|dkr|j}d}tj|dd}||}tjrHt|d|}t|dd}nt|dd}t|dd}t} t| d <t|| | d } |j | _ || _ |r|| _ tjs|r|| _ | S) z>Build an __init__ decorator that triggers ClassManager events.Nzdef __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_defaults __defaults____kwdefaults__rr+) r+rZformat_argspec_initZpy2kgetattrlocalscopyrexecrZ_sa_original_initrr) rZ class_managerr1Z func_bodyZ func_varsZ func_textfuncrZfunc_kw_defaultsenvr+rrrrY]s*      rY)TNNNNN)rrrrrrrr symbolr dictr r0rrr8Zinstance_stater` instance_dictrbrr^rVrrrYrrrrs8        /"%