U aNh@sdZddlmZddlmZddlmZddlmZddlmZddlm Z dd lm Z dd lm Z dd lm Z ddlmZdd l mZdd l mZGdddeZGdddeZGdddeZGdddeZdS)zDescriptor properties are more "auxiliary" properties that exist as configurational elements, but don't participate as actively in the load/persist ORM loop. ) attributes)util)MapperProperty)PropComparator) _none_set)event)exc)schema)sql expression) operatorsc@s eZdZdZdZdZddZdS)DescriptorPropertyzO:class:`.MapperProperty` which proxies access to a user-defined descriptor.NFcsGfdddt}jdkrFtjjd}j|rF|_jdkrfdd}fdd}fdd}t|||d _tjj jjjfd d j d }|j|_ j j|dS) NcsLeZdZdZdZdZefddZddZe drHe j ffdd Z d S) z7DescriptorProperty.instrument_class.._ProxyImplFTcsjSN) uses_objectsselfprop`C:\Users\vtejo\AppData\Local\Temp\pip-unpacked-wheel-nyjtotrf\sqlalchemy\orm\descriptor_props.pyr,szDDescriptorProperty.instrument_class.._ProxyImpl.uses_objectscSs ||_dSrkey)rrrrr__init__0sz@DescriptorProperty.instrument_class.._ProxyImpl.__init__ get_historycs|||Sr)r)rstatedict_passiverrrr5szCDescriptorProperty.instrument_class.._ProxyImpl.get_historyN) __name__ __module__ __qualname__Zaccepts_scalar_loaderZload_on_unexpireZ collectionpropertyrrhasattrr PASSIVE_OFFrrrrr _ProxyImpl's r%cst|j|dSr)setattrname)objvaluerrrfsetAsz1DescriptorProperty.instrument_class..fsetcst|jdSr)delattrr'r(rrrfdelDsz1DescriptorProperty.instrument_class..fdelcs t|jSr)getattrr'r,rrrfgetGsz1DescriptorProperty.instrument_class..fget)r/r*r-cs Sr)_comparator_factoryr)mapperrrrPz5DescriptorProperty.instrument_class..)docZoriginal_property)object descriptorr.class_rZ_is_userland_descriptorr"rZcreate_proxied_attributeparentr4implZ class_managerZinstrument_attribute)rr1r%descr*r-r/Z proxy_attrr)r1rrrinstrument_class$s*        z#DescriptorProperty.instrument_class)rr r!__doc__r4rr;rrrrrsrcseZdZdZfddZfddZddZeZdd Z e j d d Z e j d d Z eddZddZddZe j ddZejfddZddZGdddejZGdddeZddZZS) CompositePropertyzDefines a "composite" mapped attribute, representing a collection of columns as one attribute. :class:`.CompositeProperty` is constructed using the :func:`.composite` function. .. seealso:: :ref:`mapper_composite` cstt|||_||_|dd|_|dd|_|dd|_| d|j j |_ d|krj| d|_ t||dS)a`Return a composite column-based property for use with a Mapper. See the mapping documentation section :ref:`mapper_composite` for a full usage example. The :class:`.MapperProperty` returned by :func:`.composite` is the :class:`.CompositeProperty`. :param class\_: The "composite type" class, or any classmethod or callable which will produce a new instance of the composite object given the column values in order. :param \*cols: List of Column objects to be mapped. :param active_history=False: When ``True``, indicates that the "previous" value for a scalar attribute should be loaded when replaced, if not already loaded. See the same flag on :func:`.column_property`. :param group: A group name for this property when marked as deferred. :param deferred: When True, the column property is "deferred", meaning that it does not load immediately, and is instead loaded when the attribute is first accessed on an instance. See also :func:`~sqlalchemy.orm.deferred`. :param comparator_factory: a class which extends :class:`.CompositeProperty.Comparator` which provides custom SQL clause generation for comparison operations. :param doc: optional string that will be applied as the doc on the class-bound descriptor. :param info: Optional data dictionary which will be populated into the :attr:`.MapperProperty.info` attribute of this object. active_historyFdeferredgroupNcomparator_factoryinfo)superr=rattrscomposite_classgetr>r?r@pop __class__ ComparatorrArBrset_creation_order_create_descriptor)rr7rDkwargsrHrrres+  zCompositeProperty.__init__cstt|||dSr)rCr=r;_setup_event_handlersrr1rMrrr;sz"CompositeProperty.instrument_classcCs |dS)zInitialization which occurs after the :class:`.CompositeProperty` has been associated with its parent mapper. N)_setup_arguments_on_columnsrrrrdo_initszCompositeProperty.do_initcs6fdd}fdd}fdd}t|||_dS)ztCreate the Python descriptor that will serve as the access point on instances of the mapped class. cst}t}j|krxfddjD}j|krx|jdk sPt|sxj||j<|jj |j jg| jdS)Ncsg|]}t|qSr)r..0rinstancerr szFCompositeProperty._create_descriptor..fget..) r instance_dictinstance_stater_attribute_keysr issupersetrEmanagerdispatchrefresh_COMPOSITE_FGETrF)rUrrvaluesrrTrr/s$     z2CompositeProperty._create_descriptor..fgetcst|}t|}|jj}|jtj}|jjD]}|||||j }q8||j<|dkrzj D]}t ||dqfn&t j | D]\}}t |||qdSr)rrWrXr[rrFNO_VALUEr\setr9rYr&zip__composite_values__)rUr)rrattrpreviousfnrrrrr*s       z2CompositeProperty._create_descriptor..fsetcs^t|}t|}|jtj}|jj}|j|||j j D]}t ||dqHdSr) rrXrWrGrr`r[r\remover9rYr&)rUrrrerdrrrrr-s    z2CompositeProperty._create_descriptor..fdelN)r"r6)rr/r*r-rrrrKs   z$CompositeProperty._create_descriptorcsfddjDS)Ncsg|]}tjj|jqSr)r.r8r7rrSrrrrrVsz:CompositeProperty._comparable_elements..propsrrrr_comparable_elementssz&CompositeProperty._comparable_elementscCsxg}|jD]h}t|tr*|jj|dd}n>t|tjrD|jj|}n$t|tj rX|j }nt d|f| |q |S)NF)Z_configure_mappersz[Composite expects Column objects or mapped attributes/attribute names as arguments, got: %r)rD isinstancestrr8Z get_propertyr Column_columntopropertyrZInstrumentedAttributer"sa_exc ArgumentErrorappend)rrjrdrrrrrjs     zCompositeProperty.propscCsdd|jDS)NcSsg|]}t|tjr|qSr)rlr rn)rSarrrrVs z-CompositeProperty.columns..)rDrrrrcolumnsszCompositeProperty.columnscCs4|jD](}|j|_|jr&|j|_d|_|j|_qdS)zwPropagate configuration arguments made on this composite to the target columns, for those that apply. ))r?T)Z instrumentTN)rjr>r?Z strategy_keyr@)rrrrrrPs  z-CompositeProperty._setup_arguments_on_columnscsfdd}fdd}fddfdd}fd d }tjjd |d d tjjd|d d tjjd|d d dtjjd|d d dtjjd|d d ddS)z>Establish events that populate/expire the composite attribute.cs||ddddS)NF is_refreshr)rcontext)_load_refresh_handlerrr load_handlersz=CompositeProperty._setup_event_handlers..load_handlercs.|rjhj|r*|||dddS)NTru)runionrY intersection)rrwto_loadrxrrrrefresh_handlers z@CompositeProperty._setup_event_handlers..refresh_handlercs`j}|r|jkr"j|kr"dSjD]}||kr(dSq(jfddjD|j<dS)Ncsg|]}j|qSr)dictrRrrrrV8szZCompositeProperty._setup_event_handlers.._load_refresh_handler..)rr^rrYrE)rrwr|rvrkrrrrxs  zFCompositeProperty._setup_event_handlers.._load_refresh_handlercs,|dkstj|r(|jjddSr)rarYr{rrGr)rkeysrrrexpire_handler;sz?CompositeProperty._setup_event_handlers..expire_handlercs|jjddS)zAfter an insert or update, some columns may be expired due to server side defaults, or re-populated due to client side defaults. Pop out the composite value here so that it recreates. N)rrGr)r1 connectionrrrrinsert_update_handler?szFCompositeProperty._setup_event_handlers..insert_update_handlerZ after_insertT)rawZ after_updateload)r propagater]ZexpireN)rlistenr8)rryr~rrrr}rrNsL    z'CompositeProperty._setup_event_handlerscCsdd|jDS)NcSsg|] }|jqSrrrhrrrrV]sz5CompositeProperty._attribute_keys..rirrrrrY[sz!CompositeProperty._attribute_keysc Csg}g}d}|jD]j}|j}|j|j||} | rProvided for userland code that uses attributes.get_history().FTNr) rjrr[r9rZ has_changes non_deletedextendrrdeletedrZHistoryrE) rrrraddedrZ has_historyrrhistrrrrr_s,      zCompositeProperty.get_historycCs |||Sr)rArOrrrr0sz%CompositeProperty._comparator_factorycs$eZdZfddZddZZS)z!CompositeProperty.CompositeBundlecs$||_ttj|j|jf|dSr)r"rCr=CompositeBundlerr)rZ property_exprrMrrrs  z*CompositeProperty.CompositeBundle.__init__csfdd}|S)NcsjjfddDS)Ncsg|] }|qSrr)rSprocrowrrrVszXCompositeProperty.CompositeBundle.create_row_processor..proc..)r"rErprocsrrrrszDCompositeProperty.CompositeBundle.create_row_processor..procr)rqueryrlabelsrrrrcreate_row_processorsz6CompositeProperty.CompositeBundle.create_row_processor)rr r!rr __classcell__rrrMrrs rc@s^eZdZdZdZejddZddZejddZ d d Z ejd d Z d dZ ddZ dS)zCompositeProperty.ComparatoraProduce boolean, comparison, and other operators for :class:`.CompositeProperty` attributes. See the example in :ref:`composite_operations` for an overview of usage , as well as the documentation for :class:`.PropComparator`. .. seealso:: :class:`.PropComparator` :class:`.ColumnOperators` :ref:`types_operators` :attr:`.TypeEngine.comparator_factory` NcCstj|jddiS)Nr@F)r Z ClauseListrkrrrrclausess z$CompositeProperty.Comparator.clausescCs|jSrr rrrr__clause_element__sz/CompositeProperty.Comparator.__clause_element__cCs*|j|j|j|jjd}t|j|S)N)Z parententityZ parentmapper proxy_key)rZ _annotateZ _parententityrrr=r)rrrrrr sz'CompositeProperty.Comparator.expressioncCsht|tjjr|j}|dkr0dd|jjD}n,t||jjrH|}nt d|j|ft |j |S)NcSsg|]}dqSrrrRrrrrVszDCompositeProperty.Comparator._bulk_update_tuples..z)Can't UPDATE composite attribute %s to %r) rlr elementsZ BindParameterr)rrYrErcrprqrbrk)rr)r_rrr_bulk_update_tupless z0CompositeProperty.Comparator._bulk_update_tuplescs(jrfddjjDSjjSdS)Ncsg|]}tjj|jqSr)r._adapt_to_entityentityrrhrrrrVszECompositeProperty.Comparator._comparable_elements..)rrrkrrrrrks  z1CompositeProperty.Comparator._comparable_elementscs^|dkrdgtjj}n|}ddtjj|D}jrTfdd|D}tj|S)NcSsg|]\}}||kqSrr)rSrsbrrrrVsz7CompositeProperty.Comparator.__eq__..csg|]}|qSr)adapter)rSxrrrrVs)lenrrkrcrbrr and_)rotherr_Z comparisonsrrr__eq__s z#CompositeProperty.Comparator.__eq__cCst||Sr)r not_r)rrrrr__ne__sz#CompositeProperty.Comparator.__ne__)rr r!r<__hash__rmemoized_propertyrrr rrkrrrrrrrIs    rIcCst|jjjd|jS)N.)rmr8r7rrrrrr__str__szCompositeProperty.__str__)rr r!r<rr;rQr5r^rKrrrkrjr"rtrPrNrYrr$rr0orm_utilZBundlerrrIrrrrrMrr=Xs* ; =    J  Rr=cs(eZdZdZddZfddZZS)ConcreteInheritedPropertya4A 'do nothing' :class:`.MapperProperty` that disables an attribute on a concrete subclass that is only present on the inherited mapper, not the concrete classes' mapper. Cases where this occurs include: * When the superclass mapper is mapped against a "polymorphic union", which includes all attributes from all subclasses. * When a relationship() is configured on an inherited mapper, but not on the subclass mapper. Concrete mappers require that relationship() is configured explicitly on each subclass. cCs8d}|jD]$}|j|j}t|ts|j}q4q|Sr)r8Ziterate_to_rootZ_propsrrlrrA)rr1Zcomparator_callablemprrrr0s  z-ConcreteInheritedProperty._comparator_factorycs<ttfddGfdddt}|_dS)NcstdjjjfdS)NzgConcrete %s does not implement attribute %r at the instance level. Add this property explicitly to %s.)AttributeErrorr8rrrrrwarns z0ConcreteInheritedProperty.__init__..warncs2eZdZfddZfddZfddZdS)zDConcreteInheritedProperty.__init__..NoninheritedConcretePropcs dSrr)sr(r)rrr__set__szLConcreteInheritedProperty.__init__..NoninheritedConcreteProp.__set__cs dSrr)rr(rrr __delete__szOConcreteInheritedProperty.__init__..NoninheritedConcreteProp.__delete__cs|dkrjSdSr)r6)rr(ownerrrrr__get__szLConcreteInheritedProperty.__init__..NoninheritedConcreteProp.__get__N)rr r!rrrrrrrNoninheritedConcreteProp s  r)rCrrr5r6)rrrMrrrs  z"ConcreteInheritedProperty.__init__)rr r!r<r0rrrrrMrrs rcsZeZdZdfdd ZeddZejddZdd Z d d Z e d d dZ Z S)SynonymPropertyNcsRtt|||_||_||_||_|p6|r4|jp6d|_|rD||_ t |dS)aDenote an attribute name as a synonym to a mapped property, in that the attribute will mirror the value and expression behavior of another attribute. e.g.:: class MyClass(Base): __tablename__ = 'my_table' id = Column(Integer, primary_key=True) job_status = Column(String(50)) status = synonym("job_status") :param name: the name of the existing mapped property. This can refer to the string name ORM-mapped attribute configured on the class, including column-bound attributes and relationships. :param descriptor: a Python :term:`descriptor` that will be used as a getter (and potentially a setter) when this attribute is accessed at the instance level. :param map_column: **For classical mappings and mappings against an existing Table object only**. if ``True``, the :func:`.synonym` construct will locate the :class:`_schema.Column` object upon the mapped table that would normally be associated with the attribute name of this synonym, and produce a new :class:`.ColumnProperty` that instead maps this :class:`_schema.Column` to the alternate name given as the "name" argument of the synonym; in this way, the usual step of redefining the mapping of the :class:`_schema.Column` to be under a different name is unnecessary. This is usually intended to be used when a :class:`_schema.Column` is to be replaced with an attribute that also uses a descriptor, that is, in conjunction with the :paramref:`.synonym.descriptor` parameter:: my_table = Table( "my_table", metadata, Column('id', Integer, primary_key=True), Column('job_status', String(50)) ) class MyClass(object): @property def _job_status_descriptor(self): return "Status: %s" % self._job_status mapper( MyClass, my_table, properties={ "job_status": synonym( "_job_status", map_column=True, descriptor=MyClass._job_status_descriptor) } ) Above, the attribute named ``_job_status`` is automatically mapped to the ``job_status`` column:: >>> j1 = MyClass() >>> j1._job_status = "employed" >>> j1.job_status Status: employed When using Declarative, in order to provide a descriptor in conjunction with a synonym, use the :func:`sqlalchemy.ext.declarative.synonym_for` helper. However, note that the :ref:`hybrid properties ` feature should usually be preferred, particularly when redefining attribute behavior. :param info: Optional data dictionary which will be populated into the :attr:`.InspectionAttr.info` attribute of this object. .. versionadded:: 1.0.0 :param comparator_factory: A subclass of :class:`.PropComparator` that will provide custom comparison behavior at the SQL expression level. .. note:: For the use case of providing an attribute which redefines both Python-level and SQL-expression level behavior of an attribute, please refer to the Hybrid attribute introduced at :ref:`mapper_hybrids` for a more effective technique. .. seealso:: :ref:`synonyms` - Overview of synonyms :func:`.synonym_for` - a helper oriented towards Declarative :ref:`mapper_hybrids` - The Hybrid Attribute extension provides an updated approach to augmenting attribute behavior more flexibly than can be achieved with synonyms. N) rCrrr' map_columnr6rAr<r4rBrrJ)rr'rr6rAr4rBrMrrrspzSynonymProperty.__init__cCst|jj|jjjSr)r.r8r7r'r9rrrrrrszSynonymProperty.uses_objectscCsjt|jj|j}t|dr&t|jtsdt|tj r8|j St|t j rH|St d|jjj|j|f|jS)Nr"zGsynonym() attribute "%s.%s" only supports ORM mapped attributes, got %r)r.r8r7r'r#rlr"rrZQueryableAttributeZ comparatorrZColumnOperatorsrpZInvalidRequestErrorr)rrdrrr_proxied_objects   zSynonymProperty._proxied_objectcCs<|j}t|tr4|jr$|||}n |||}|S|SdSr)rrlrrA)rr1rcomprrrr0s  z#SynonymProperty._comparator_factorycOst|jj|j}|jj||Sr)r.r8r7r'r9r)rargkwrdrrrrszSynonymProperty.get_historyzsqlalchemy.orm.propertiescCstjj}|jr|j|jjkr:td|j |jj |jfnN|jj|j|j kr|j |jj|jj|j krtd|j|j |j |jf| |jj|j}|j |j ||dd|j|_||_dS)Nz>Can't compile synonym '%s': no column on table '%s' named '%s'zpCan't call map_column=True for synonym %r=%r, a ColumnProperty already exists keyed to the name %r for column %rT)initZ setparent)rZ preloadedZorm_propertiesrrZpersist_selectablecrprqr' descriptionroZColumnPropertyZ_configure_propertyZ_mapped_by_synonymr8)rr8rZ propertiesrrrr set_parents@   zSynonymProperty.set_parent)NNNNN)rr r!rr"rrrrr0rZpreload_modulerrrrrMrrs|   rN)r<rrrZ interfacesrrrrr rpr r r rrr=rrrrrrs&            <5