o
    y¬´\Al  ã                   @   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ejjddd�G dd„ deƒƒZejjddd�G dd„ deƒƒZejjddd�G dd„ deƒƒZejjddd�G dd„ deƒƒZdS )zŸDescriptor properties are more "auxiliary" properties
that exist as configurational elements, but don't participate
as actively in the load/persist ORM loop.

é   )Ú
attributes)Ú
properties)Úquery)ÚMapperProperty)ÚPropComparator)Ú	_none_seté   )Úevent)Úexc)Úschema)Úsql)Úutil)Ú
expressionc                   @   s   e Zd ZdZdZdd„ ZdS )ÚDescriptorPropertyzS:class:`.MapperProperty` which proxies access to a
        user-defined descriptor.Nc                    sÐ   ˆ‰G ‡fdd„dt ƒ}ˆjd u r!tˆ jˆjd ƒ}ˆ  |¡r!|ˆ_ˆjd u r@‡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                       s@   e Zd ZdZdZ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   s
   || _ d S ©N©Úkey)Úselfr   © r   úQ/var/www/html/env/lib/python3.10/site-packages/sqlalchemy/orm/descriptor_props.pyÚ__init__*   ó   
z@DescriptorProperty.instrument_class.<locals>._ProxyImpl.__init__Úget_historyc                    s   ˆ   |||¡S r   )r   )r   ÚstateÚdict_Úpassive©Úpropr   r   r   /   s   zCDescriptorProperty.instrument_class.<locals>._ProxyImpl.get_historyN)Ú__name__Ú
__module__Ú__qualname__Úaccepts_scalar_loaderÚexpire_missingÚ
collectionr   Úhasattrr   ÚPASSIVE_OFFr   r   r   r   r   Ú
_ProxyImpl%   s    
ÿþr&   c                    s   t | ˆ j|ƒ d S r   )ÚsetattrÚname)ÚobjÚvalue©r   r   r   Úfset;   ó   z1DescriptorProperty.instrument_class.<locals>.fsetc                    s   t | ˆ jƒ d S r   )Údelattrr(   ©r)   r+   r   r   Úfdel>   ó   z1DescriptorProperty.instrument_class.<locals>.fdelc                    s   t | ˆ jƒS r   )Úgetattrr(   r/   r+   r   r   ÚfgetA   ó   z1DescriptorProperty.instrument_class.<locals>.fget)r3   r,   r0   c                      s
   ˆ  ˆ ¡S r   )Ú_comparator_factoryr   )Úmapperr   r   r   Ú<lambda>J   s   
 z5DescriptorProperty.instrument_class.<locals>.<lambda>)ÚdocÚoriginal_property)ÚobjectÚ
descriptorr2   Úclass_r   Ú_is_userland_descriptorÚpropertyr   Úcreate_proxied_attributeÚparentr8   ÚimplÚclass_managerÚinstrument_attribute)r   r6   r&   Údescr,   r0   r3   Ú
proxy_attrr   )r6   r   r   r   Úinstrument_class"   s*   



úz#DescriptorProperty.instrument_class)r   r   r    Ú__doc__r8   rF   r   r   r   r   r      s    r   zsqlalchemy.orm.propertiesT)Ú
add_to_allc                       sÂ   e Zd ZdZ‡ fdd„Z‡ fdd„Zdd„ 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 ) ÚCompositePropertyzöDefines 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 )ap  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.

        :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.

           .. deprecated:: 0.7

                :class:`.AttributeExtension` is deprecated in favor of the
                :class:`.AttributeEvents` listener interface.  The
                :paramref:`.composite.extension` parameter will be
                removed in a future release.

        Úactive_historyFÚdeferredÚgroupNÚcomparator_factoryÚinfo)ÚsuperrI   r   ÚattrsÚcomposite_classÚgetrJ   rK   rL   ÚpopÚ	__class__Ú
ComparatorrM   rN   r   Úset_creation_orderÚ_create_descriptor)r   r<   rP   Úkwargs©rT   r   r   r   `   s   8ÿ
zCompositeProperty.__init__c                    s   t t| ƒ |¡ |  ¡  d S r   )rO   rI   rF   Ú_setup_event_handlers©r   r6   rY   r   r   rF   ¨   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	 
|d ˆjg¡ | ˆjd ¡S )Nc                    s   g | ]}t ˆ |ƒ‘qS r   )r2   ©Ú.0r   ©Úinstancer   r   Ú
<listcomp>Á   s    
ÿzFCompositeProperty._create_descriptor.<locals>.fget.<locals>.<listcomp>)r   Úinstance_dictÚinstance_stater   Ú_attribute_keysr   Ú
issupersetrQ   ÚmanagerÚdispatchÚrefreshrR   )ra   r   r   Úvaluesr+   r`   r   r3   ¹   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   rc   rd   rg   r   rR   ÚNO_VALUErh   ÚsetrA   re   r'   ÚzipÚ__composite_values__)ra   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   rd   rc   rS   r   rk   rg   rh   ÚremoverA   re   r'   )ra   r   r   rp   ro   r   r+   r   r   r0   ã   s   


ÿz2CompositeProperty._create_descriptor.<locals>.fdelN)r>   r;   )r   r3   r,   r0   r   r+   r   rW   ³   s   	z$CompositeProperty._create_descriptorc                    s   ‡ fdd„ˆ j D ƒS )Nc                    ó   g | ]
}t ˆ jj|jƒ‘qS r   )r2   r@   r<   r   ©r_   r   r+   r   r   rb   ð   ó    z:CompositeProperty._comparable_elements.<locals>.<listcomp>©Úpropsr+   r   r+   r   Ú_comparable_elementsî   s   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)Ú_configure_mappersz[Composite expects Column objects or mapped attributes/attribute names as arguments, got: %r)rP   Ú
isinstanceÚstrr@   Úget_propertyr   ÚColumnÚ_columntopropertyr   ÚInstrumentedAttributer>   Úsa_excÚArgumentErrorÚappend)r   rw   ro   r   r   r   r   rw   ò   s   

þÿzCompositeProperty.propsc                 C   ó   dd„ | j D ƒS )Nc                 S   s   g | ]
}t |tjƒr|‘qS r   )rz   r   r}   )r_   Úar   r   r   rb     ru   z-CompositeProperty.columns.<locals>.<listcomp>)rP   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.

        ))rK   T)Ú
instrumentTN)rw   rJ   rK   Ústrategy_keyrL   )r   r   r   r   r   r\   	  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                    ó   ˆ | |dd� d S )NF©Ú
is_refreshr   ©r   Úargs©Ú_load_refresh_handlerr   r   Úload_handler  r-   z=CompositeProperty._setup_event_handlers.<locals>.load_handlerc                    r‰   )NTrŠ   r   rŒ   rŽ   r   r   Úrefresh_handler  r-   z@CompositeProperty._setup_event_handlers.<locals>.refresh_handlerc                    sV   ˆ j }|sˆ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   )Údictr^   ©r   r   r   rb   ,  ó    zZCompositeProperty._setup_event_handlers.<locals>._load_refresh_handler.<locals>.<listcomp>)r’   r   re   rQ   )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   )rl   re   Úintersectionr’   rS   r   )r   Úkeysr+   r   r   Úexpire_handler/  s   ÿz?CompositeProperty._setup_event_handlers.<locals>.expire_handlerc                    s   |j  ˆ jd¡ dS )zêAfter 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’   rS   r   )r6   Ú
connectionr   r+   r   r   Úinsert_update_handler3  s   zFCompositeProperty._setup_event_handlers.<locals>.insert_update_handlerÚafter_insertT)ÚrawÚafter_updateÚload)rœ   Ú	propagateri   ÚexpireN)r	   Úlistenr@   )r   r�   r‘   r˜   rš   r   )r�   r   r   rZ     s(   

ÿ
ÿÿÿ
ÿz'CompositeProperty._setup_event_handlersc                 C   rƒ   )Nc                 S   s   g | ]}|j ‘qS r   r   rt   r   r   r   rb   Q  s    z5CompositeProperty._attribute_keys.<locals>.<listcomp>rv   r+   r   r   r   re   O  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   )rw   r   rg   rA   r   Úhas_changesÚnon_deletedÚextendr‚   Údeletedr   ÚHistoryrQ   )r   r   r   r   Úaddedr¥   Úhas_historyr   r   Úhistr£   r   r   r   r   S  s,   



ýzCompositeProperty.get_historyc                 C   ó   |   | |¡S r   ©rM   r[   r   r   r   r5   s  r4   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>   rO   rI   ÚCompositeBundler   r   )r   Ú	property_ÚexprrY   r   r   r   w  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   )r_   Úproc©Úrowr   r   rb   €  s    zXCompositeProperty.CompositeBundle.create_row_processor.<locals>.proc.<locals>.<listcomp>)r>   rQ   r°   ©Úprocsr   r°   r   r¯   ~  s   ÿzDCompositeProperty.CompositeBundle.create_row_processor.<locals>.procr   )r   r   r³   Úlabelsr¯   r   r²   r   Úcreate_row_processor}  s   z6CompositeProperty.CompositeBundle.create_row_processor)r   r   r    r   rµ   Ú__classcell__r   r   rY   r   r¬   v  s    r¬   c                   @   sV   e Zd ZdZdZedd„ ƒZdd„ Z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   |   ¡ S r   )Ú__clause_element__r+   r   r   r   Úclausesš  s   z$CompositeProperty.Comparator.clausesc                 C   s   t j| jddiŽS )NrL   F)r   Ú
ClauseListrx   r+   r   r   r   r·   ž  s
   ÿÿz/CompositeProperty.Comparator.__clause_element__c                 C   s   t  | j|  ¡ ¡S r   )rI   r¬   r   r·   r+   r   r   r   Ú_query_clause_element£  s   
ÿz2CompositeProperty.Comparator._query_clause_elementc                 C   sT   |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   r^   r   r   r   rb   ª  s    zDCompositeProperty.Comparator._bulk_update_tuples.<locals>.<listcomp>z)Can't UPDATE composite attribute %s to %r)	r   re   rz   rQ   rn   r€   r�   rm   rx   )r   r*   rj   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                    rs   r   )r2   Ú_adapt_to_entityÚentityr   rt   r+   r   r   rb   ¸  s    ÿÿzECompositeProperty.Comparator._comparable_elements.<locals>.<listcomp>)r¼   r   rx   r+   r   r+   r   rx   µ  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   )r_   r„   Úbr   r   r   rb   Ä  s    ÿz7CompositeProperty.Comparator.__eq__.<locals>.<listcomp>c                    s   g | ]}ˆ   |¡‘qS r   )Úadapter)r_   Úxr+   r   r   rb   È  r”   )Úlenr   rx   rn   rm   r¼   r   Úand_)r   Úotherrj   Úcomparisonsr   r+   r   Ú__eq__¿  s   ÿ
z#CompositeProperty.Comparator.__eq__c                 C   s   t  |  |¡¡S r   )r   Únot_rÅ   )r   rÃ   r   r   r   Ú__ne__Ë  r1   z#CompositeProperty.Comparator.__ne__)r   r   r    rG   Ú__hash__r>   r¸   r·   rº   r»   r   Úmemoized_propertyrx   rÅ   rÇ   r   r   r   r   rU   …  s    

	rU   c                 C   s   t | jjjƒd | j S )NÚ.)r{   r@   r<   r   r   r+   r   r   r   Ú__str__Î  s   zCompositeProperty.__str__)r   r   r    rG   r   rF   r]   rW   r   rÉ   rx   rw   r>   r…   r\   rZ   re   r   r%   r   r5   r   ÚBundler¬   r   rU   rË   r¶   r   r   rY   r   rI   R   s*    H;


:
 IrI   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@   Úiterate_to_rootÚ_propsr   rz   rÍ   rM   )r   r6   Úcomparator_callableÚmÚpr   r   r   r5   ä  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   )r;   )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Ý   )rO   rÍ   r   r:   r;   )r   rÝ   rY   rÛ   r   r   î  s   z"ConcreteInheritedProperty.__init__)r   r   r    rG   r5   r   r¶   r   r   rY   r   rÍ   Ò  s    
rÍ   c                       sF   e Zd Z					d
‡ fdd„	Zejdd„ ƒZdd„ Z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:`.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:`.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:`.Column` to be under a different name is
          unnecessary. This is usually intended to be used when a
          :class:`.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)rO   rÞ   r   r(   Ú
map_columnr;   rM   rG   r8   rN   r   rV   )r   r(   rß   r;   rM   r8   rN   rY   r   r   r   
  s   lzSynonymProperty.__init__c                 C   sH   t | jj| jƒ}t|dƒrt|jtƒs!t 	d| jjj
| j|f ¡‚|jS )Nr>   zGsynonym() attribute "%s.%s" only supports ORM mapped attributes, got %r)r2   r@   r<   r(   r$   rz   r>   r   r€   ÚInvalidRequestErrorr   )r   ro   r   r   r   Ú_proxied_property…  s   ÿþÿz!SynonymProperty._proxied_propertyc                 C   s,   | j }| jr|  ||¡}|S | ||¡}|S r   )rá   rM   )r   r6   r   Úcompr   r   r   r5   ’  s   ÿz#SynonymProperty._comparator_factoryc                 C   s¸   | j rW| j|jjvrt d| j|jj| jf ¡‚|jj| j |jv r?|j|jj| j  j| jkr?t d| j| j| j| jf ¡‚t	 
|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)ÚinitÚ	setparent)rß   r   Úmapped_tableÚcr€   r�   r(   Údescriptionr~   r   ÚColumnPropertyÚ_configure_propertyÚ_mapped_by_synonymr@   )r   r@   rã   rÒ   r   r   r   Ú
set_parent›  s.   þÿÿýýÿ
zSynonymProperty.set_parent)NNNNN)
r   r   r    r   r   rÉ   rá   r5   rë   r¶   r   r   rY   r   rÞ     s    ù{
	rÞ   c                       s,   e Zd ZdZ	d‡ fdd„	Zdd„ Z‡  ZS )ÚComparablePropertyz;Instruments a Python property for use in query expressions.Nc                    sF   t t| ƒ ¡  || _|| _|p|r|jpd| _|r|| _t 	| ¡ dS )ak
  Provides a method of applying a :class:`.PropComparator`
        to any Python descriptor attribute.

        .. deprecated:: 0.7
            :func:`.comparable_property` is superseded by
            the :mod:`~sqlalchemy.ext.hybrid` extension.  See the example
            at :ref:`hybrid_custom_comparators`.

        Allows any Python descriptor to behave like a SQL-enabled
        attribute when used at the class level in queries, allowing
        redefinition of expression operator behavior.

        In the example below we redefine :meth:`.PropComparator.operate`
        to wrap both sides of an expression in ``func.lower()`` to produce
        case-insensitive comparison::

            from sqlalchemy.orm import comparable_property
            from sqlalchemy.orm.interfaces import PropComparator
            from sqlalchemy.sql import func
            from sqlalchemy import Integer, String, Column
            from sqlalchemy.ext.declarative import declarative_base

            class CaseInsensitiveComparator(PropComparator):
                def __clause_element__(self):
                    return self.prop

                def operate(self, op, other):
                    return op(
                        func.lower(self.__clause_element__()),
                        func.lower(other)
                    )

            Base = declarative_base()

            class SearchWord(Base):
                __tablename__ = 'search_word'
                id = Column(Integer, primary_key=True)
                word = Column(String)
                word_insensitive = comparable_property(lambda prop, mapper:
                                CaseInsensitiveComparator(
                                    mapper.c.word, mapper)
                            )


        A mapping like the above allows the ``word_insensitive`` attribute
        to render an expression like::

            >>> print SearchWord.word_insensitive == "Trucks"
            lower(search_word.word) = lower(:lower_1)

        :param comparator_factory:
          A PropComparator subclass or factory that defines operator behavior
          for this property.

        :param descriptor:
          Optional when used in a ``properties={}`` declaration.  The Python
          descriptor or property to layer comparison behavior on top of.

          The like-named descriptor will be automatically retrieved from the
          mapped class if left blank in a ``properties`` declaration.

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

            .. versionadded:: 1.0.0

        N)
rO   rì   r   r;   rM   rG   r8   rN   r   rV   )r   rM   r;   r8   rN   rY   r   r   r   ¼  s   FzComparableProperty.__init__c                 C   rª   r   r«   r[   r   r   r   r5   
  r4   z&ComparableProperty._comparator_factory)NNN)r   r   r    rG   r   r5   r¶   r   r   rY   r   rì   ¸  s
    ÿNrì   N)rG   Ú r   r   r   Ú
interfacesr   r   r   r   r	   r
   r€   r   r   r   r   ÚlanghelpersÚdependency_forrI   rÍ   rÞ   rì   r   r   r   r   Ú<module>   s4   6   5 0