o znhF@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 jddZdZddZdZddZddZddZddZ 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[dBdCZ4dDdEZ5edFdGZ6dZdHdIZ7dZdJdKZ8dLdMZ9dNdOZ:dPdQZ;dRdSZe>Z?dXdYZ@dS)\ ClassManagerz,tracks state information at the class level.NcCs||_i|_d|_i|_i|_dddd|jjDD|_|jD]}||q!|jj |||j D]}t |}|durE|j |jq4||d|jvr\td|dSdS)NcSsg|]}|dur|qSN).0mgrr r I/usr/local/lib/python3.10/dist-packages/sqlalchemy/orm/instrumentation.py As z)ClassManager.__init__..cSsg|] }t|trt|qSr ) isinstancetypemanager_of_class)r rr r rrCs __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___basesupdatedispatch_events_new_classmanager_instance__mro__r_updatemanage_instrument_init__dict__rwarn)selfrbase_baseclsr r r r__init__:s6   zClassManager.__init__cCt|Sr )idr%r r r__hash__`zClassManager.__hash__cCs||uSr r )r%otherr r r__eq__cr-zClassManager.__eq__cCs d|jvS)Nmapper)r#r+r r r is_mappedfs zClassManager.is_mappedcCr)r ) frozensetr+r r r _all_key_setjszClassManager._all_key_setcCtdd|DS)NcSsg|] }|jjr|jqSr )impl collectionkeyr attrr r rrqsz6ClassManager._collection_impl_keys..r2valuesr+r r r_collection_impl_keysnsz"ClassManager._collection_impl_keyscCr4)NcSsg|] }|jjr|jqSr )r5accepts_scalar_loaderr8r r rrws z5ClassManager._scalar_loader_impls..r:r+r r r_scalar_loader_implsts z!ClassManager._scalar_loader_implscCs t|jr )rUnmappedClassErrorrr+r r rr0~s zClassManager.mapperccsh|durt}|jjD]%}t|j|D]}|||j|}t|tjr0|j r0||fVqq dS)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# differenceaddrrInspectionAttr is_attribute)r%excludesuperclsr7valr r r_all_sqla_attributess      z!ClassManager._all_sqla_attributescCs*|jjD]}||jvr|j|Sq|S)z5return an attribute on the class without tripping it.)rrr#)r%r7defaultrFr r r_get_class_attr_mros  z ClassManager._get_class_attr_mrocCs||vo ||jduS)z\Return True if the given attribute is fully initialized. i.e. has an impl. Nr5r%r7r r r_attr_has_implszClassManager._attr_has_implcCst|}|dur t|}|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. Nr_instrumentation_factorycreate_manager_for_cls)r%clsmanagerr r r_subclass_managers  zClassManager._subclass_managercCs*|jj|_t|j||_|d|jdSNr()rr( original_init_generate_initrinstall_memberr+r r rr"s zClassManager._instrument_initcCs|jr |dd|_dSdSrT)runinstall_memberr+r r r_uninstrument_inits  zClassManager._uninstrument_initcCs|j||jtjSr )r first_initrr InstanceStater+r r r_state_constructorszClassManager._state_constructorcCst|j|j|dS)z0Mark this instance as the manager for its class.N)setattrr MANAGER_ATTRr+r r rr!szClassManager.managecCst|j|jdS)z)Dissasociate this manager from its class.N)delattrrr^r+r r rdisposeszClassManager.disposecCtSr )_default_manager_getterr+r r rmanager_getterzClassManager.manager_gettercCra)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_getterr+r r r state_getters zClassManager.state_gettercCrar )_default_dict_getterr+r r r dict_getterrdzClassManager.dict_getterFcCsh|r ||jvr dSn ||j|<|||t||||<|jD]}||}|||dq#dSNT)rinstall_descriptor_memoized_key_collectionexpire_instancer__subclasses__rSinstrument_attribute)r%r7inst propagatedrQrRr r rrns     z!ClassManager.instrument_attributeccsN|jD]}t|}|dur$||ur$|V|r$|dD]}|VqqdSri)rrmrsubclass_managers)r% recursiverQr mr r rrqszClassManager.subclass_managerscCstj|j|||dSr )rOrattribute_instrumentrrLr r rpost_configure_attributes z%ClassManager.post_configure_attributecCsn||vrdS|r||jvrdSn |j|=||t|||=|jD]}t|}|r4||dq&dSri)runinstall_descriptorrkrlrrmruninstrument_attribute)r%r7rprQrRr r rrws     z#ClassManager.uninstrument_attributecCsD|d|_|_|jt|D] }||jvr||qdS)zs  z"ClassManager.initialize_collectioncCs|r||vS||jvSr )r)r%r7searchr r ris_instrumentedEs zClassManager.is_instrumentedcCs ||jSr rKrLr r rrKrzClassManager.get_implcCs t|Sr )iterr;r+r r r attributesNs zClassManager.attributescCs2|j|j}|dur|||}||||Sr )r__new__r\ _state_setter)r%rinstancer r r new_instanceTs   zClassManager.new_instancecCs$|dur |||}|||dSr )r\rr%rrr r rsetup_instance[s zClassManager.setup_instancecCst||jdSr )r_r|r%rr r rteardown_instance`r~zClassManager.teardown_instancecCs t||Sr )_SerializeManager)r%r state_dictr r r _serializecrzClassManager._serializecCsPt||jrdS|j|jur|jr||j|S|||}||||S)zInstall a default InstanceState if none is present. A private convenience method used by the __init__ decorator. F) hasattrr|r __class__r1rS_new_state_if_noner\rrr r rrfs   zClassManager._new_state_if_nonecCs t||jSr )rr|rr r r has_state|s zClassManager.has_statecCs||j||dS)TODO) optimistic)r hasparent)r%rr7rr r r has_parentszClassManager.has_parentcCdS)z=All ClassManagers are non-zero regardless of attribute state.Tr r+r r r__bool__rdzClassManager.__bool__cCsd|jj|jt|fS)Nz<%s of %r at %x>)r__name__rr*r+r r r__repr__s zClassManager.__repr__r )F)Ar __module__ __qualname____doc__rDEFAULT_MANAGER_ATTRr^DEFAULT_STATE_ATTRr| staticmethodr attrsetterrdeferred_scalar_loaderobjectr(rUrr,r/propertyr1rkr3r<r>memoized_propertyr0rHrJrMrSr"rYr\r!r` hybridmethodrcrfrhrnrqrurwrzrjrvrWrXrrrrrrrrrrrrr __nonzero__rr r r rr ,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 )rrRrpickle)r%rdrRr r rr(sz_SerializeManager.__init__cCsht|j|_}|durt|d|j|jr!|jjs!|j|dur+| |||j ||dS)NzxCannot deserialize object of type %r - no mapper() has been configured for this class within the current Python process!) rrrRrUnmappedInstanceErrorr1r0 configured_configure_allrrunpickle)r%rrorrRr r r__call__s  z_SerializeManager.__call__N)rrrrr(rr r r rrs rc@s0eZdZdZddZddZddZdd Zd S) InstrumentationFactoryz'Factory for new ClassManager instances.cCs`|dusJt|dusJ||\}}|durt}||}|||||_|j||Sr )r_locate_extended_factoryr _check_conflictsrrclass_instrument)r%rrRrr r rrPs   z-InstrumentationFactory.create_manager_for_clscCr)z2Overridden by a subclass to do an extended lookup.)NNr )r%rr r rrrdz/InstrumentationFactory._locate_extended_factorycCr)z;Overridden by a subclass to test for conflicting factories.Nr )r%rrr r rrrdz'InstrumentationFactory._check_conflictscCsDt|}|||j|tj|jvr t|tjdSdSr ) rrzr`rclass_uninstrumentr r^r#r_)r%rrRr r rrzs  z!InstrumentationFactory.unregisterN)rrrrrPrrrzr r r rrs  rcCst|}|dur t|}|S)z_Register class instrumentation. Returns the existing or newly created class manager. NrN)rrRr r rregister_classs rcCst|dS)z!Unregister class instrumentation.N)rOrz)rr r runregister_classsrcCst|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)rr7r r rrs rc Cs|j}|sJd}tj|dd}||}tjr$t|d|}t|dd}n t|dd}t|dd}t} t|| | d } |j| _|| _ |rJ|| _ tjsR|rR|| _ | S) z>Build 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)groupedim_func func_defaultsN __defaults____kwdefaults__r() r(rformat_argspec_initpy2krlocalscopyexecr_sa_original_initrr) r class_manageroriginal__init__ func_body func_vars func_textfuncrfunc_kw_defaultsenvr(r r rrVs(      rVN)rrrrrrr!group_expirable_memoized_propertyrkdictr rrrrOinstance_statere instance_dictrgrrbrrrrVr r r rs*      g")