o
    Rclh                     @   s   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	 dd	lm
Z dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ G dd deZG dd deZG dd deZG dd deZdS )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$   e Zd ZdZdZdZdZdd ZdS )DescriptorPropertyzO:class:`.MapperProperty` which proxies access to a
    user-defined descriptor.NFc                    s   G fdddt }jd u r#t jjd } j|r#|_jd u rBfdd}fdd}fdd}t|||d	_tjj	jjj fd
dj
d}|j|_ jj| d S )Nc                       sP   e Zd ZdZdZdZe fddZdd Ze	 dr&e
jf fdd		Zd
S d
S )z7DescriptorProperty.instrument_class.<locals>._ProxyImplFTc                    s    j S N)uses_objectsselfprop AD:\Flask\env\Lib\site-packages\sqlalchemy/orm/descriptor_props.pyr   -   s   zDDescriptorProperty.instrument_class.<locals>._ProxyImpl.uses_objectsc                 S   s
   || _ d S r   key)r   r   r   r   r   __init__1      
z@DescriptorProperty.instrument_class.<locals>._ProxyImpl.__init__get_historyc                    s     |||S r   )r   )r   statedict_passiver   r   r   r   6   s   zCDescriptorProperty.instrument_class.<locals>._ProxyImpl.get_historyN)__name__
__module____qualname__Zaccepts_scalar_loaderZload_on_unexpireZ
collectionpropertyr   r   hasattrr   PASSIVE_OFFr   r   r   r   r   
_ProxyImpl(   s    
r&   c                    s   t |  j| d S r   )setattrname)objvaluer   r   r   fsetB   s   z1DescriptorProperty.instrument_class.<locals>.fsetc                    s   t |  j d S r   )delattrr(   r)   r   r   r   fdelE      z1DescriptorProperty.instrument_class.<locals>.fdelc                    s   t |  jS r   )getattrr(   r-   r   r   r   fgetH      z1DescriptorProperty.instrument_class.<locals>.fget)r1   r+   r.   c                      s
     S r   )_comparator_factoryr   )mapperr   r   r   <lambda>Q   s   
 z5DescriptorProperty.instrument_class.<locals>.<lambda>)docZoriginal_property)object
descriptorr0   class_r   Z_is_userland_descriptorr#   r   Zcreate_proxied_attributeparentr6   implZclass_managerZinstrument_attribute)r   r4   r&   descr+   r.   r1   Z
proxy_attrr   )r4   r   r   r   instrument_class%   s*   


z#DescriptorProperty.instrument_class)r    r!   r"   __doc__r6   r   Z_links_to_entityr=   r   r   r   r   r      s    r   c                       s   e Zd ZdZ fddZ fddZdd Ze Zdd	 Z	e
jd
d Ze
jdd Zedd Zdd Zdd Ze
jdd ZejfddZdd ZG dd dejZG dd deZdd Z  ZS ) 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`

    c                    s   t t|   || _|| _|dd| _|dd| _|dd| _|	d| j
j| _d|v r5|	d| _t|  |   dS )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_historyFdeferredgroupNcomparator_factoryinfo)superr?   r   attrscomposite_classgetr@   rA   rB   pop	__class__
ComparatorrC   rD   r   set_creation_order_create_descriptor)r   r9   rF   kwargsrJ   r   r   r   f   s   +
zCompositeProperty.__init__c                    s   t t| | |   d S r   )rE   r?   r=   _setup_event_handlersr   r4   rO   r   r   r=      s   z"CompositeProperty.instrument_classc                 C   s   |    dS )zInitialization which occurs after the :class:`.CompositeProperty`
        has been associated with its parent mapper.

        N)_setup_arguments_on_columnsr   r   r   r   do_init   s   zCompositeProperty.do_initc                    s6    fdd} fdd} fdd}t ||| _dS )ztCreate the Python descriptor that will serve as
        the access point on instances of the mapped class.

        c                    s   t  }t  }j|vr< fddjD }j|vr<|jd us(t|s<j| |j< |jj	
|jjg |jd S )Nc                    s   g | ]}t  |qS r   )r0   .0r   instancer   r   
<listcomp>   s    
zFCompositeProperty._create_descriptor.<locals>.fget.<locals>.<listcomp>)r   instance_dictinstance_stater   _attribute_keysr   
issupersetrG   managerdispatchrefresh_COMPOSITE_FGETrH   )rW   r   r   valuesr   rV   r   r1      s    




	z2CompositeProperty._create_descriptor.<locals>.fgetc                    s   t | }t | }|j j }| jt j}|jjD ]
}|||||j	}q|| j< |d u r> j
D ]}t| |d  q3d S t j
| D ]
\}}t| || qFd S r   )r   rY   rZ   r]   r   rH   NO_VALUEr^   setr;   r[   r'   zip__composite_values__)rW   r*   r   r   attrpreviousfnr   r   r   r   r+      s    




z2CompositeProperty._create_descriptor.<locals>.fsetc                    s^   t | }t | }| jt j}|j j }|j|||j	  j
D ]}t| |d  q$d S r   )r   rZ   rY   rI   r   rb   r]   r^   remover;   r[   r'   )rW   r   r   rg   rf   r   r   r   r   r.      s   


z2CompositeProperty._create_descriptor.<locals>.fdelN)r#   r8   )r   r1   r+   r.   r   r   r   rM      s   	z$CompositeProperty._create_descriptorc                    s    fdd j D S )Nc                       g | ]
}t  jj|jqS r   )r0   r:   r9   r   rU   r   r   r   r   rX          z:CompositeProperty._comparable_elements.<locals>.<listcomp>propsr   r   r   r   _comparable_elements      z&CompositeProperty._comparable_elementsc                 C   sx   g }| j D ]4}t|tr| jj|dd}nt|tjr"| jj| }nt|tj	r,|j
}ntd|f || q|S )NF)Z_configure_mappersz[Composite expects Column objects or mapped attributes/attribute names as arguments, got: %r)rF   
isinstancestrr:   Zget_propertyr
   Column_columntopropertyr   ZInstrumentedAttributer#   sa_excArgumentErrorappend)r   rn   rf   r   r   r   r   rn      s   

zCompositeProperty.propsc                 C      dd | j D S )Nc                 S   s   g | ]
}t |tjr|qS r   )rq   r
   rs   )rU   ar   r   r   rX     rl   z-CompositeProperty.columns.<locals>.<listcomp>)rF   r   r   r   r   columns     zCompositeProperty.columnsc                 C   s4   | j D ]}| j|_| jr| j|_d|_| j|_qdS )zwPropagate configuration arguments made on this composite
        to the target columns, for those that apply.

        ))rA   T)Z
instrumentTN)rn   r@   rA   Zstrategy_keyrB   )r   r   r   r   r   rR     s   

z-CompositeProperty._setup_arguments_on_columnsc                    s    fdd} fdd}fdd fdd}fd	d
}t jjd|dd t jjd|dd t jjd|ddd t jjd|ddd t jjd|ddd dS )z>Establish events that populate/expire the composite attribute.c                    s    | |d dd d S )NF
is_refreshr   )r   context)_load_refresh_handlerr   r   load_handler  s   z=CompositeProperty._setup_event_handlers.<locals>.load_handlerc                    s2   |rj hj|r | ||dd d S d S )NTr|   )r   unionr[   intersection)r   r~   to_loadr   r   r   r   refresh_handler  s   z@CompositeProperty._setup_event_handlers.<locals>.refresh_handlerc                    s`    j }|r
|ju rj|v rd S jD ]	}||vr d S qj fddjD  |j< d S )Nc                    s   g | ]} j | qS r   )dictrT   r   r   r   rX   9      zZCompositeProperty._setup_event_handlers.<locals>._load_refresh_handler.<locals>.<listcomp>)r   r`   r   r[   rG   )r   r~   r   r}   r   kr   r   r   r      s   
zFCompositeProperty._setup_event_handlers.<locals>._load_refresh_handlerc                    s0   |d u st  j|r| j jd  d S d S r   )rc   r[   r   r   rI   r   )r   keysr   r   r   expire_handler<  s   z?CompositeProperty._setup_event_handlers.<locals>.expire_handlerc                    s   |j  jd dS )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)r   rI   r   )r4   
connectionr   r   r   r   insert_update_handler@  s   zFCompositeProperty._setup_event_handlers.<locals>.insert_update_handlerZafter_insertT)rawZafter_updateload)r   	propagater_   ZexpireN)r   listenr:   )r   r   r   r   r   r   r   r   rP     s(   



z'CompositeProperty._setup_event_handlersc                 C   rx   )Nc                 S   s   g | ]}|j qS r   r   rk   r   r   r   rX   ^  s    z5CompositeProperty._attribute_keys.<locals>.<listcomp>rm   r   r   r   r   r[   \  r{   z!CompositeProperty._attribute_keysc                 C   s   g }g }d}| j D ]5}|j}|j| j||}	|	 rd}|	 }
|
r*||
 n|d |	j	r9||	j	 q	|d q	|rPt
| j| gd| j| gS t
d| j| gdS )z>Provided for userland code that uses attributes.get_history().FTNr   )rn   r   r]   r;   r   Zhas_changesnon_deletedextendrw   deletedr   ZHistoryrG   )r   r   r   r   addedr   Zhas_historyr   r   histr   r   r   r   r   `  s,   



zCompositeProperty.get_historyc                 C   s   |  | |S r   )rC   rQ   r   r   r   r3     r2   z%CompositeProperty._comparator_factoryc                       s$   e Zd Z fddZdd Z  ZS )z!CompositeProperty.CompositeBundlec                    s&   || _ ttj| j|jg|R   d S r   )r#   rE   r?   CompositeBundler   r   )r   Z	property_exprrO   r   r   r     s   z*CompositeProperty.CompositeBundle.__init__c                    s    fdd}|S )Nc                    s   j j fddD  S )Nc                    s   g | ]}| qS r   r   )rU   procrowr   r   rX     s    zXCompositeProperty.CompositeBundle.create_row_processor.<locals>.proc.<locals>.<listcomp>)r#   rG   r   procsr   r   r   r     s   zDCompositeProperty.CompositeBundle.create_row_processor.<locals>.procr   )r   queryr   labelsr   r   r   r   create_row_processor  s   z6CompositeProperty.CompositeBundle.create_row_processor)r    r!   r"   r   r   __classcell__r   r   rO   r   r     s    r   c                   @   s^   e Zd ZdZdZejdd Zdd Zejdd Z	d	d
 Z
ejdd Zdd Zdd ZdS )zCompositeProperty.Comparatora  Produce 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`

        Nc                 C   s   t j| jddiS )NrB   F)r   Z
ClauseListro   r   r   r   r   clauses  s
   z$CompositeProperty.Comparator.clausesc                 C   s   | j S r   r   r   r   r   r   __clause_element__  s   z/CompositeProperty.Comparator.__clause_element__c                 C   s*   | j | j| j| jjd}t| j|S )N)ZparententityZparentmapper	proxy_key)r   Z	_annotateZ_parententityr   r   r?   r   )r   r   r   r   r   r     s   z'CompositeProperty.Comparator.expressionc                 C   sh   t |tjjr
|j}|d u rdd | jjD }nt || jjr$| }n
t	
d| j|f t| j|S )Nc                 S   s   g | ]}d qS r   r   rT   r   r   r   rX     s    zDCompositeProperty.Comparator._bulk_update_tuples.<locals>.<listcomp>z)Can't UPDATE composite attribute %s to %r)rq   r   elementsZBindParameterr*   r   r[   rG   re   ru   rv   rd   ro   )r   r*   ra   r   r   r   _bulk_update_tuples  s   
z0CompositeProperty.Comparator._bulk_update_tuplesc                    s$    j r fdd jjD S  jjS )Nc                    rj   r   )r0   _adapt_to_entityentityr   rk   r   r   r   rX     s    zECompositeProperty.Comparator._comparable_elements.<locals>.<listcomp>)r   r   ro   r   r   r   r   ro     s
   
z1CompositeProperty.Comparator._comparable_elementsc                    s^   |d u rd gt  jj }n| }dd t jj|D } jr* fdd|D }tj| S )Nc                 S   s   g | ]\}}||kqS r   r   )rU   ry   br   r   r   rX     s    z7CompositeProperty.Comparator.__eq__.<locals>.<listcomp>c                    s   g | ]}  |qS r   )adapter)rU   xr   r   r   rX     r   )lenr   ro   re   rd   r   r   and_)r   otherra   Zcomparisonsr   r   r   __eq__  s   
z#CompositeProperty.Comparator.__eq__c                 C   s   t | |S r   )r   not_r   )r   r   r   r   r   __ne__  r/   z#CompositeProperty.Comparator.__ne__)r    r!   r"   r>   __hash__r   memoized_propertyr   r   r   r   ro   r   r   r   r   r   r   rK     s    



	rK   c                 C   s   t | jjjd | j S )N.)rr   r:   r9   r    r   r   r   r   r   __str__  s   zCompositeProperty.__str__)r    r!   r"   r>   r   r=   rS   r7   r`   rM   r   r   ro   rn   r#   rz   rR   rP   r[   r   r%   r   r3   orm_utilZBundler   r   rK   r   r   r   r   rO   r   r?   Y   s,    ;=


J
 Rr?   c                       s(   e Zd ZdZdd Z fddZ  ZS )ConcreteInheritedPropertya4  A '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.

    c                 C   s:   d }| j  D ]}|j| j }t|ts|j} |S q|S r   )r:   Ziterate_to_rootZ_propsr   rq   r   rC   )r   r4   Zcomparator_callablempr   r   r   r3     s   
z-ConcreteInheritedProperty._comparator_factoryc                    s<   t t    fddG  fdddt}|  _d S )Nc                      s   t d j j jf )NzgConcrete %s does not implement attribute %r at the instance level.  Add this property explicitly to %s.)AttributeErrorr:   r   r   r   r   r   warn  s
   z0ConcreteInheritedProperty.__init__.<locals>.warnc                       s2   e Zd ZfddZfddZ fddZdS )zDConcreteInheritedProperty.__init__.<locals>.NoninheritedConcretePropc                    
      d S r   r   )sr)   r*   r   r   r   __set__  r   zLConcreteInheritedProperty.__init__.<locals>.NoninheritedConcreteProp.__set__c                    r   r   r   )r   r)   r   r   r   
__delete__  r   zOConcreteInheritedProperty.__init__.<locals>.NoninheritedConcreteProp.__delete__c                    s   |d u r j S   d S r   )r8   )r   r)   ownerr   r   r   r   __get__  s   
zLConcreteInheritedProperty.__init__.<locals>.NoninheritedConcreteProp.__get__N)r    r!   r"   r   r   r   r   r   r   r   NoninheritedConcreteProp  s    r   )rE   r   r   r7   r8   )r   r   rO   r   r   r     s   z"ConcreteInheritedProperty.__init__)r    r!   r"   r>   r3   r   r   r   r   rO   r   r     s    
r   c                       sd   e Zd Z					d fdd	Zedd Zejdd Zdd	 Z	d
d Z
eddd Z  ZS )SynonymPropertyNc                    sR   t t|   || _|| _|| _|| _|p|r|jpd| _|r"|| _	t
|  dS )a  Denote 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 <mapper_hybrids>` 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)rE   r   r   r(   
map_columnr8   rC   r>   r6   rD   r   rL   )r   r(   r   r8   rC   r6   rD   rO   r   r   r     s   pzSynonymProperty.__init__c                 C   s   t | jj| jjjS r   )r0   r:   r9   r(   r;   r   r   r   r   r   r     rp   zSynonymProperty.uses_objectsc                 C   sj   t | jj| j}t|drt|jts2t|tj	r|j
S t|tjr$|S td| jjj| j|f |jS )Nr#   zGsynonym() attribute "%s.%s" only supports ORM mapped attributes, got %r)r0   r:   r9   r(   r$   rq   r#   r   r   ZQueryableAttributeZ
comparatorr   ZColumnOperatorsru   ZInvalidRequestErrorr    )r   rf   r   r   r   _proxied_object  s   zSynonymProperty._proxied_objectc                 C   s:   | j }t|tr| jr| ||}|S |||}|S |S r   )r   rq   r   rC   )r   r4   r   compr   r   r   r3     s   
z#SynonymProperty._comparator_factoryc                 O   s"   t | jj| j}|jj|i |S r   )r0   r:   r9   r(   r;   r   )r   argkwrf   r   r   r   r     s   zSynonymProperty.get_historyzsqlalchemy.orm.propertiesc                 C   s   t jj}| jr[| j|jjvrtd| j	|jj
| jf |jj| j |jv rC|j|jj| j  j| j	krCtd| j| j	| j	| jf ||jj| j }|j| j	||dd | j|_|| _d S )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)r   Z	preloadedZorm_propertiesr   r   Zpersist_selectablecru   rv   r(   descriptionrt   ZColumnPropertyZ_configure_propertyZ_mapped_by_synonymr:   )r   r:   r   
propertiesr   r   r   r   
set_parent  sB   

zSynonymProperty.set_parent)NNNNN)r    r!   r"   r   r#   r   r   r   r   r3   r   Zpreload_moduler   r   r   r   rO   r   r     s    |

r   N)r>    r   r   r   Z
interfacesr   r   r   r   r	   ru   r
   r   r   r   r   r?   r   r   r   r   r   r   <module>   s(   =   5