B
    \#+                 @   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gZe
jG dd deZdS )z|MapperProperty implementations.

This is a private module which defines the behavior of individual ORM-
mapped attributes.

    )absolute_import   )
attributes)PropComparator)StrategizedProperty)_orm_full_deannotate   )log)util)
expressionColumnPropertyc                   s   e Zd ZdZdZdZejdd fddZe	dd	d
d Z
dd Zedd Zdd Z fddZdd ZejfddZdd ZG dd dejeZdd Z  ZS )r   zDescribes an object attribute that corresponds to a table column.

    Public constructor is the :func:`.orm.column_property` function.

    column)_orig_columnscolumnsgroupdeferred
instrumentcomparator_factory
descriptor	extensionactive_historyexpire_on_flushinfodocstrategy_keyZ_creation_orderZ_is_polymorphic_discriminatorZ_mapped_by_synonymZ_deferred_column_loader)z0.7z:class:`.AttributeExtension` is deprecated in favor of the :class:`.AttributeEvents` listener interface.  The :paramref:`.column_property.extension` parameter will be removed in a future release.)r   c                sN  t t|   dd |D | _dd |D | _|dd| _|dd| _|dd	| _|d
| j	j
| _|dd| _|dd| _|dd| _|dd	| _d|kr|d| _d|kr|d| _n6x4t| jD ] }t|dd}|dk	r|| _P qW d| _|r*td| j	jdt| f t|  d| jfd| jff| _dS )a\  Provide a column-level property for use with a Mapper.

        Column-based properties can normally be applied to the mapper's
        ``properties`` dictionary using the :class:`.Column` element directly.
        Use this function when the given column is not directly present within
        the mapper's selectable; examples include SQL expressions, functions,
        and scalar SELECT queries.

        Columns that aren't present in the mapper's selectable won't be
        persisted by the mapper and are effectively "read-only" attributes.

        :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. Normally, history tracking logic for
          simple non-primary-key scalar values only needs to be
          aware of the "new" value in order to perform a flush. This
          flag is available for applications that make use of
          :func:`.attributes.get_history` or :meth:`.Session.is_modified`
          which also need to know
          the "previous" value of the attribute.

        :param comparator_factory: a class which extends
           :class:`.ColumnProperty.Comparator` which provides custom SQL
           clause generation for comparison operations.

        :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 doc:
              optional string that will be applied as the doc on the
              class-bound descriptor.

        :param expire_on_flush=True:
            Disable expiry on flush.   A column_property() which refers
            to a SQL expression (and not a single table-bound column)
            is considered to be a "read only" property; populating it
            has no effect on the state of data, and it can only return
            database state.   For this reason a column_property()'s value
            is expired whenever the parent object is involved in a
            flush, that is, has any kind of "dirty" state within a flush.
            Setting this parameter to ``False`` will have the effect of
            leaving any existing value present after the flush proceeds.
            Note however that the :class:`.Session` with default expiration
            settings still expires
            all attributes after a :meth:`.Session.commit` call, however.

        :param info: Optional data dictionary which will be populated into the
            :attr:`.MapperProperty.info` attribute of this object.

        :param extension:
            an :class:`.AttributeExtension` instance, or list of extensions,
            which will be prepended to the list of attribute listeners for the
            resulting descriptor placed on the class.

        c             S   s   g | ]}t |qS  )r   _labeled).0cr   r   8lib/python3.7/site-packages/sqlalchemy/orm/properties.py
<listcomp>   s    z+ColumnProperty.__init__.<locals>.<listcomp>c             S   s   g | ]}t t|qS r   )r   r   r   )r   r   r   r   r   r       s    r   Nr   FZ_instrumentTr   r   r   r   r   r   r   z.%s received unexpected keyword argument(s): %sz, r   )superr   __init__r   r   popr   r   r   	__class__
Comparatorr   r   r   r   r   r   r   reversedgetattr	TypeError__name__joinsortedkeysr
   Zset_creation_orderr   )selfr   kwargscolr   )r$   r   r   r"   :   s:    K
zColumnProperty.__init__zsqlalchemy.orm.statezsqlalchemy.orm.strategiesc             C   s   |j | jj|| j| jS )N)ZInstanceStateZ"_instance_level_callable_processorparentZclass_managerZLoadDeferredColumnskey)r-   stateZ
strategiesr   r   r   &_memoized_attr__deferred_column_loader   s    
z5ColumnProperty._memoized_attr__deferred_column_loaderc             C   s   | j S )zsAllow the ColumnProperty to work in expression before it is turned
        into an instrumented attribute.
        )r   )r-   r   r   r   __clause_element__   s    z!ColumnProperty.__clause_element__c             C   s
   | j d S )zJReturn the primary column or expression for this ColumnProperty.

        r   )r   )r-   r   r   r   r      s    zColumnProperty.expressionc             C   s0   | j s
d S tj|j| j| | ||| jd d S )N)Z
comparatorparententityr   )r   r   Zregister_descriptorclass_r1   r   r   )r-   Zmapperr   r   r   instrument_class   s    
zColumnProperty.instrument_classc                sZ   t t|   t| jdkrVt| jj| jrVt	
d| j| jd | jd | jf  d S )Nr   zOn mapper %s, primary key column '%s' is being combined with distinct primary key column '%s' in attribute '%s'. Use explicit properties to give each column its own mapped attribute name.r   )r!   r   do_initlenr   setr0   Zprimary_key
issupersetr
   warnr1   )r-   )r$   r   r   r8      s    zColumnProperty.do_initc             C   s   t | j| j| j| jdS )N)r   r   r   )r   r   r   r   r   )r-   r   r   r   copy   s    zColumnProperty.copyc             C   s   | | jj|||dS )N)passive)get_implr1   Zget_committed_value)r-   r2   Zdict_r   r>   r   r   r   _getcommitted   s    zColumnProperty._getcommittedc	             C   st   | j s
d S | j|krL|| j }	|s.|	|| j< qp|| j}
|
|||	d  n$|jrp| j|krp|j|| jgdd d S )NT)Z	no_loader)r   r1   r?   r:   Zhas_identityZ_expire_attributes)r-   ZsessionZsource_stateZsource_dictZ
dest_stateZ	dest_dictloadZ
_recursiveZ_resolve_conflict_mapvalueimplr   r   r   merge   s    

zColumnProperty.mergec               @   s<   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dS )zColumnProperty.Comparatora  Produce boolean, comparison, and other operators for
        :class:`.ColumnProperty` attributes.

        See the documentation for :class:`.PropComparator` for a brief
        overview.

        .. seealso::

            :class:`.PropComparator`

            :class:`.ColumnOperators`

            :ref:`types_operators`

            :attr:`.TypeEngine.comparator_factory`

        )r4   r   c             C   s8   | j r|  | jjd S | jjd | j| jdS d S )Nr   )r5   Zparentmapper)Zadapterpropr   Z	_annotateZ_parententity)r-   r   r   r   #_memoized_method___clause_element__  s
    z=ColumnProperty.Comparator._memoized_method___clause_element__c             C   s,   |   }y|jS  tk
r&   | jjS X d S )N)r4   r   AttributeErrorrE   )r-   Zcer   r   r   _memoized_attr_info,  s
    z-ColumnProperty.Comparator._memoized_attr_infoc             C   s   t |  |S )zproxy attribute access down to the mapped column.

            this allows user-defined comparison methods to be accessed.
            )r'   r4   )r-   r1   r   r   r   _fallback_getattr3  s    z+ColumnProperty.Comparator._fallback_getattrc             O   s   ||   f||S )N)r4   )r-   opotherr.   r   r   r   operate:  s    z!ColumnProperty.Comparator.operatec             K   s   |   }|||||f|S )N)r4   Z_bind_param)r-   rJ   rK   r.   r/   r   r   r   reverse_operate=  s    z)ColumnProperty.Comparator.reverse_operateN)
r)   
__module____qualname____doc__	__slots__rF   rH   rI   rL   rM   r   r   r   r   r%   
  s   r%   c             C   s   t | jjjd | j S )N.)strr0   r6   r)   r1   )r-   r   r   r   __str__A  s    zColumnProperty.__str__)r)   rN   rO   rP   Zstrategy_wildcard_keyrQ   r
   Zdeprecated_paramsr"   Zdependenciesr3   r4   propertyr   r7   r8   r=   r   ZPASSIVE_OFFr@   rD   ZMemoizedSlotsr   r%   rT   __classcell__r   r   )r$   r   r      s   t	7N)rP   Z
__future__r    r   Z
interfacesr   r   r
   r   r	   Zsqlr   __all__Zclass_loggerr   r   r   r   r   <module>   s   