
    ؄_n                     d   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e          Zej                            dd           G d de                      Zej                            dd           G d de                      Zej                            dd           G d de                      Zej                            dd           ej        dd           G 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)
properties)query)MapperProperty)PropComparator)	_none_set   )event)exc)schema)sql)util)
expressionc                        e Zd ZdZdZdZd ZdS )DescriptorPropertyzO:class:`.MapperProperty` which proxies access to a
    user-defined descriptor.NFc                       G fddt                     } j        7t          j         j        d           }                    |          r| _         j        & fd} fd} fd}t          |||           _         t          j         j                   j	        j         j         j         fd j
                   } | j                  |_        j                             j        |           d S )	Nc                   p    e Zd ZdZdZdZe fd            Zd Z e	 d          re
j        f fd	ZdS dS )7DescriptorProperty.instrument_class.<locals>._ProxyImplFTc                     j         S N)uses_objectsselfprops    d/var/www/book.euthymeo.com/html/venv/lib/python3.11/site-packages/sqlalchemy/orm/descriptor_props.pyr   zDDescriptorProperty.instrument_class.<locals>._ProxyImpl.uses_objects,   s    ((    c                     || _         d S r   key)r   r   s     r   __init__z@DescriptorProperty.instrument_class.<locals>._ProxyImpl.__init__0   s    r   get_historyc                 2                         |||          S r   )r!   )r   statedict_passiver   s       r   r!   zCDescriptorProperty.instrument_class.<locals>._ProxyImpl.get_history5   s      ++E5'BBBr   N)__name__
__module____qualname__accepts_scalar_loaderexpire_missing
collectionpropertyr   r    hasattrr   PASSIVE_OFFr!   )r   s   r   
_ProxyImplr   '   s        $)!!NJ) ) ) ) X)   wt]++ C 1;0FC C C C C C C CC Cr   r/   c                 4    t          | j        |           d S r   )setattrname)objvaluer   s     r   fsetz1DescriptorProperty.instrument_class.<locals>.fsetA   s    TY.....r   c                 2    t          | j                   d S r   )delattrr2   r3   r   s    r   fdelz1DescriptorProperty.instrument_class.<locals>.fdelD   s    TY'''''r   c                 .    t          | j                  S r   )getattrr2   r8   s    r   fgetz1DescriptorProperty.instrument_class.<locals>.fgetG   s    sDI...r   )r<   r5   r9   c                  .                                    S r   )_comparator_factory)mapperr   s   r   <lambda>z5DescriptorProperty.instrument_class.<locals>.<lambda>P   s    D,,V44 r   )docoriginal_property)object
descriptorr;   class_r   _is_userland_descriptorr,   r   create_proxied_attributeparentrA   implclass_managerinstrument_attribute)	r   r?   r/   descr5   r9   r<   
proxy_attrr   s	   ``      @r   instrument_classz#DescriptorProperty.instrument_class$   sq   	C 	C 	C 	C 	C 	C 	C 	C 	C 	C& ?"6=$(D99D--d33 '"&?"/ / / / /( ( ( ( (/ / / / / 'Dt$GGGDOIZ8IIKHO44444"
 
 

 %*TX..
11$(JGGGGGr   )r&   r'   r(   __doc__rA   r   rN    r   r   r   r      s>            CL1H 1H 1H 1H 1Hr   r   zsqlalchemy.orm.propertiesT)
add_to_allc                   J    e Zd ZdZ ej        d           fd            Z fdZd Zd Z	ej
        d             Zej
        d	             Zed
             Zd Zd Zej
        d             Zej        fdZd Z G d dej                  Z G d de          Zd Z x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`

    )0.7z:class:`.AttributeExtension` is deprecated in favor of the :class:`.AttributeEvents` listener interface.  The :paramref:`.composite.extension` parameter will be removed in a future release.)	extensionc                    t          t          |                                            || _        || _        |                    dd          | _        |                    dd          | _        |                    dd          | _        |	                    d| j
        j                  | _        d|v r|	                    d          | _        t          j        |            |                                  dS )aQ  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.

        active_historyFdeferredgroupNcomparator_factoryinfo)superrS   r    attrscomposite_classgetrW   rX   rY   pop	__class__
ComparatorrZ   r[   r   set_creation_order_create_descriptor)r   rE   r]   kwargsra   s       r   r    zCompositeProperty.__init__f   s    t 	&&//111
%$jj)95AA

:u55ZZ..
"(** $.";#
 #
 V

6**DI%%%!!!!!r   c                     t          t          |                               |           |                                  d S r   )r\   rS   rN   _setup_event_handlers)r   r?   ra   s     r   rN   z"CompositeProperty.instrument_class   s:    &&77???""$$$$$r   c                 .    |                                   dS )zInitialization which occurs after the :class:`.CompositeProperty`
        has been associated with its parent mapper.

        N)_setup_arguments_on_columnsr   s    r   do_initzCompositeProperty.do_init   s    
 	((*****r   c                 R      fd} fd} fd}t          |||           _        dS )ztCreate the Python descriptor that will serve as
        the access point on instances of the mapped class.

        c                 ~    t          j                   }t          j                   }j        |vrp fdj        D             }j        |vrT|j        t          j        |          s9 j        | |j        <   |j        j	        
                    |d j        g           |                    j        d           S )Nc                 0    g | ]}t          |          S rP   )r;   ).0r   instances     r   
<listcomp>zFCompositeProperty._create_descriptor.<locals>.fget.<locals>.<listcomp>   s0       /2GHc**  r   )r   instance_dictinstance_stater   _attribute_keysr   
issupersetr^   managerdispatchrefreshr_   )rp   r$   r#   valuesr   s   `   r   r<   z2CompositeProperty._create_descriptor.<locals>.fget   s    ,X66E-h77Exu$$   6:6J   85((I)1Ef1M1M)&:d&:F&CE$(OM*225$
KKK99TXt,,,r   c                    t          j        |           }t          j        |           }|j        j                 }|                    j        t           j                  }|j        j        D ]} |||||j	                  }||j        <   |j
        D ]}t          | |d            d S t          j
        |                                          D ]\  }}t          | ||           d S r   )r   rr   rs   rv   r   r_   NO_VALUErw   setrI   rt   r1   zip__composite_values__)	rp   r4   r$   r#   attrpreviousfnr   r   s	           r   r5   z2CompositeProperty._create_descriptor.<locals>.fset   s   ,X66E-h77E=*Dyy:+>??Hm' > >5%49==#E$(O}/ 1 1CHc400001 1 #&(%*D*D*F*F# # 2 2JC Hc511112 2r   c                 >   t          j        |           }t          j        |           }|                    j        t           j                  }|j        j                 }|j                            |||j	                   j
        D ]}t          | |d            d S r   )r   rs   rr   r`   r   r{   rv   rw   removerI   rt   r1   )rp   r#   r$   r   r   r   r   s         r   r9   z2CompositeProperty._create_descriptor.<locals>.fdel   s    -h77E,X66Eyy:+>??H=*DM  $)<<<+ - -#t,,,,- -r   N)r,   rD   )r   r<   r5   r9   s   `   r   rd   z$CompositeProperty._create_descriptor   sg    	- 	- 	- 	- 	-2	2 	2 	2 	2 	2"	- 	- 	- 	- 	- #4t44r   c                 *      fd j         D             S )Nc                 N    g | ]!}t          j        j        |j                  "S rP   )r;   rH   rE   r   ro   r   r   s     r   rq   z:CompositeProperty._comparable_elements.<locals>.<listcomp>   s*    MMM$*DH55MMMr   propsrj   s   `r   _comparable_elementsz&CompositeProperty._comparable_elements   s    MMMM$*MMMMr   c                 x   g }| j         D ]}t          |t                    r| j                            |d          }nft          |t
          j                  r| j        j        |         }n9t          |t          j	                  r|j
        }nt          j        d|          |                    |           |S )NF)_configure_mapperszYComposite expects Column objects or mapped attributes/attribute names as arguments, got: )r]   
isinstancestrrH   get_propertyr   Column_columntopropertyr   InstrumentedAttributer,   sa_excArgumentErrorappend)r   r   r   r   s       r   r   zCompositeProperty.props   s    J 	 	D$$$ {///OOD&-00 	{4T:D*"BCC }** t  
 LLr   c                 $    d | j         D             S )Nc                 F    g | ]}t          |t          j                  |S rP   )r   r   r   )ro   as     r   rq   z-CompositeProperty.columns.<locals>.<listcomp>  s)    FFFaAv})E)EFFFFr   )r]   rj   s    r   columnszCompositeProperty.columns  s    FF4:FFFFr   c                 ~    | j         D ]4}| j        |_        | j        r| j        |_        d|_        | j        |_        5dS )zwPropagate configuration arguments made on this composite
        to the target columns, for those that apply.

        ))rX   T)
instrumentTN)r   rW   rX   strategy_keyrY   r   s     r   ri   z-CompositeProperty._setup_arguments_on_columns  sQ    
 J 	$ 	$D"&"5D} O $$N!DJJ	$ 	$r   c                 d    fd}fd} fd fd} fd}t          j         j        d|d           t          j         j        d	|d           t          j         j        d
|dd           t          j         j        d|dd           t          j         j        d|dd           dS )z>Establish events that populate/expire the composite attribute.c                 $     | |d           d S )NF
is_refreshrP   r#   args_load_refresh_handlers     r   load_handlerz=CompositeProperty._setup_event_handlers.<locals>.load_handler   s!    !!%%@@@@@@r   c                 $     | |d           d S )NTr   rP   r   s     r   refresh_handlerz@CompositeProperty._setup_event_handlers.<locals>.refresh_handler#  s!    !!%$??????r   c                       j         }|sj        |v rd S j        D ]	}||vr d S 
 j         fdj        D              |j        <   d S )Nc                 *    g | ]}j         |         S rP   )dict)ro   r   r#   s     r   rq   zZCompositeProperty._setup_event_handlers.<locals>._load_refresh_handler.<locals>.<listcomp>4  s    BBBc%*S/BBBr   )r   r   rt   r^   )r#   r   r   r$   kr   s   `    r   r   zFCompositeProperty._setup_event_handlers.<locals>._load_refresh_handler&  s    JE $(e"3"3
 )  E>>FF " 3d2BBBBT-ABBBE$(OOOr   c                     |'t          j                                      |          r"| j                            j        d            d S d S r   )r|   rt   intersectionr   r`   r   )r#   keysr   s     r   expire_handlerz?CompositeProperty._setup_event_handlers.<locals>.expire_handler7  sJ    |s4#788EEdKK|
tx..... |r   c                 H    |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   r`   r   )r?   
connectionr#   r   s      r   insert_update_handlerzFCompositeProperty._setup_event_handlers.<locals>.insert_update_handler;  s#     JNN48T*****r   after_insertT)rawafter_updateload)r   	propagaterx   expireN)r
   listenrH   )r   r   r   r   r   r   s   `    @r   rg   z'CompositeProperty._setup_event_handlers  s[   	A 	A 	A 	A 	A	@ 	@ 	@ 	@ 	@	 	 	 	 	"	/ 	/ 	/ 	/ 	/	+ 	+ 	+ 	+ 	+ 	K)>D	
 	
 	
 	
 	K)>D	
 	
 	
 	
 	K44	
 	
 	
 	
 	KO	
 	
 	
 	
 	K>tt	
 	
 	
 	
 	
 	
r   c                 $    d | j         D             S )Nc                     g | ]	}|j         
S rP   r   )ro   r   s     r   rq   z5CompositeProperty._attribute_keys.<locals>.<listcomp>Y  s    000T000r   r   rj   s    r   rt   z!CompositeProperty._attribute_keysW  s    00TZ0000r   c                 *   g }g }d}| j         D ]}|j        }|j        |         j                            ||          }	|	                                rd}|	                                }
|
r|                    |
           n|                    d           |	j	        r|                    |	j	                   |                    d           |r(t          j         | j        | gd | j        | g          S t          j        d | j        | gd          S )z>Provided for userland code that uses attributes.get_history().FTNrP   )r   r   rv   rI   r!   has_changesnon_deletedextendr   deletedr   Historyr^   )r   r#   r$   r%   addedr   has_historyr   r   histr   s              r   r!   zCompositeProperty.get_history[  s?    J 	% 	%D(C=%*66ueDDD!! #"**,,K #[))))T"""| %t|,,,,t$$$$ 	N%%%u-.%%w/0   %b+?4+?+G*H"MMMr   c                 .    |                      | |          S r   rZ   r   r?   s     r   r>   z%CompositeProperty._comparator_factory{      &&tV444r   c                   $     e Zd Z fdZd Z xZS )!CompositeProperty.CompositeBundlec                 l    || _          t          t          j        |           j        |j        g|R   d S r   )r,   r\   rS   CompositeBundler    r   )r   	property_exprra   s      r   r    z*CompositeProperty.CompositeBundle.__init__  sK    %DMCE#3T::C $     r   c                       fd}|S )Nc                 <      j         j         fdD              S )Nc                 &    g | ]} |          S rP   rP   )ro   procrows     r   rq   zXCompositeProperty.CompositeBundle.create_row_processor.<locals>.proc.<locals>.<listcomp>  s!    222Ddd3ii222r   )r,   r^   )r   procsr   s   `r   r   zDCompositeProperty.CompositeBundle.create_row_processor.<locals>.proc  s/    4t}42222E222 r   rP   )r   r   r   labelsr   s   ` `  r   create_row_processorz6CompositeProperty.CompositeBundle.create_row_processor  s)         
 Kr   )r&   r'   r(   r    r   __classcell__ra   s   @r   r   r   ~  sG        	 	 	 	 		 	 	 	 	 	 	r   r   c                   j    e Zd ZdZdZed             Zd Zd Zd Z	e
j        d             Zd Zd	 ZdS )
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                 *    |                                  S r   )__clause_element__rj   s    r   clausesz$CompositeProperty.Comparator.clauses  s    **,,,r   c                 .    t          j        | j        ddiS )NrY   F)r   
ClauseListr   rj   s    r   r   z/CompositeProperty.Comparator.__clause_element__  s%    ("7  r   c                 f    t                               | j        |                                           S r   )rS   r   r   r   rj   s    r   _query_clause_elementz2CompositeProperty.Comparator._query_clause_element  s-    $44	42244  r   c                     |d | j         j        D             }nNt          || j         j                  r|                                }nt          j        d| j         d|          t          | j        |          S )Nc                     g | ]}d S r   rP   )ro   r   s     r   rq   zDCompositeProperty.Comparator._bulk_update_tuples.<locals>.<listcomp>  s    DDD3$DDDr   z!Can't UPDATE composite attribute z to )	r   rt   r   r^   r~   r   r   r}   r   )r   r4   ry   s      r   _bulk_update_tuplesz0CompositeProperty.Comparator._bulk_update_tuples  s    }DD$)*CDDDE49#<== 3355**yyy%%)  
 t0&999r   c                 Z      j         r fd j        j        D             S  j        j        S )Nc                 N    g | ]!}t          j        j        |j                  "S rP   )r;   _adapt_to_entityentityr   r   s     r   rq   zECompositeProperty.Comparator._comparable_elements.<locals>.<listcomp>  s;        D18$(CC  r   )r   r   r   rj   s   `r   r   z1CompositeProperty.Comparator._comparable_elements  sK    $ 6    $	 >   
 y55r   c                      |d gt           j        j                  z  }n|                                }d t	           j        j        |          D             } j        r fd|D             }t          j        | S )Nc                      g | ]\  }}||k    S rP   rP   )ro   r   bs      r   rq   z7CompositeProperty.Comparator.__eq__.<locals>.<listcomp>  s-       1aQ  r   c                 :    g | ]}                     |          S rP   )adapter)ro   xr   s     r   rq   z7CompositeProperty.Comparator.__eq__.<locals>.<listcomp>  s#    DDD1t||ADDDr   )lenr   r   r~   r}   r   r   and_)r   otherry   comparisonss   `   r   __eq__z#CompositeProperty.Comparator.__eq__  s    }#di&D"E"EE3355 #&ty'Ev#N#N  K $ EDDDDDDD8[))r   c                 P    t          j        |                     |                    S r   )r   not_r   )r   r   s     r   __ne__z#CompositeProperty.Comparator.__ne__  s    8DKK..///r   )r&   r'   r(   rO   __hash__r,   r   r   r   r   r   memoized_propertyr   r   r   rP   r   r   rb   r     s        	 	$ 		- 	- 
	-	 	 	
	 	 	
	: 	: 	: 
		6 	6 
 		6
	* 
	* 
	*	0 	0 	0 	0 	0r   rb   c                 T    t          | j        j        j                  dz   | j        z   S )N.)r   rH   rE   r&   r   rj   s    r   __str__zCompositeProperty.__str__  s$    4;%.//#5@@r   )r&   r'   r(   rO   r   deprecated_paramsr    rN   rk   rd   r   r   r   r,   r   ri   rg   rt   r   r.   r!   r>   r   Bundler   r   rb   r   r   r   s   @r   rS   rS   X   s       
 
 T
  ?" ?" ?" ?" ?"B% % % % %+ + +95 95 95v 
N N N 
  $ G G XG
$ 
$ 
$6
 6
 6
t 
1 1 1 1;0F N N N N@5 5 5    %,   G0 G0 G0 G0 G0^ G0 G0 G0RA A A A A A Ar   rS   c                   (     e Zd ZdZd Z fdZ x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                     d }| j                                         D ]2}|j        | j                 }t	          |t
                    s	|j        } n3|S r   )rH   iterate_to_root_propsr   r   r   rZ   )r   r?   comparator_callablemps        r   r>   z-ConcreteInheritedProperty._comparator_factory  sa    ",,.. 	 	A"Aa!:;; &'&:# #"r   c                      t          t                                                       fd G  fddt                    } |             _        d S )Nc            	      T    t          d j        d j        d j        d          )Nz	Concrete z does not implement attribute z9 at the instance level.  Add this property explicitly to r   )AttributeErrorrH   r   rj   s   r   warnz0ConcreteInheritedProperty.__init__.<locals>.warn  s7     . ;;;$+++7  r   c                   0    e Zd ZfdZfdZ fdZdS )DConcreteInheritedProperty.__init__.<locals>.NoninheritedConcretePropc                                   d S r   rP   )sr3   r4   r  s      r   __set__zLConcreteInheritedProperty.__init__.<locals>.NoninheritedConcreteProp.__set__      r   c                                   d S r   rP   )r  r3   r  s     r   
__delete__zOConcreteInheritedProperty.__init__.<locals>.NoninheritedConcreteProp.__delete__  r  r   c                 .    |j         S               d S r   )rD   )r  r3   ownerr   r  s      r   __get__zLConcreteInheritedProperty.__init__.<locals>.NoninheritedConcreteProp.__get__  s    ;?*r   N)r&   r'   r(   r  r  r  )r   r  s   r   NoninheritedConcretePropr	    se                       r   r  )r\   r   r    rC   rD   )r   r  r  ra   s   ` @r   r    z"ConcreteInheritedProperty.__init__  s    '..77999	 	 	 	 	
	 
	 
	 
	 
	 
	 
	 
	v 
	 
	 
	 3244r   )r&   r'   r(   rO   r>   r    r   r   s   @r   r   r     sQ          # # #5 5 5 5 5 5 5 5 5r   r   c                   r     e Zd Z	 	 	 	 	 d fd	Zed             Zej        d             Zd Z	d Z
d Z xZS )	SynonymPropertyNc                     t          t          |                                            || _        || _        || _        || _        |p
|r|j        pd| _        |r|| _	        t          j        |            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)r\   r  r    r2   
map_columnrD   rZ   rO   rA   r[   r   rc   )r   r2   r  rD   rZ   rA   r[   ra   s          r   r    zSynonymProperty.__init__  s~    ` 	ot$$--///	$$"4E:<**<E 	DI%%%%%r   c                 T    t          | j        j        | j                  j        j        S r   )r;   rH   rE   r2   rI   r   rj   s    r   r   zSynonymProperty.uses_objects  s    t{)4955:GGr   c                    t          | j        j        | j                  }t	          |d          rt          |j        t                    s1t          j	        d| j        j        j
        d| j        d|          |j        S )Nr,   zsynonym() attribute "r   z+" only supports ORM mapped attributes, got )r;   rH   rE   r2   r-   r   r,   r   r   InvalidRequestErrorr&   )r   r   s     r   _proxied_propertyz!SynonymProperty._proxied_property  s    t{)4955tZ(( 	
M>1
 1
 	 ,, ;%...			44A  
 }r   c                 |    | j         }| j        r|                     ||          }n|                    ||          }|S r   )r  rZ   )r   r?   r   comps       r   r>   z#SynonymProperty._comparator_factory  sF    %" 	9**488DD**488Dr   c                 d    t          | j        j        | j                  } |j        j        |i |S r   )r;   rH   rE   r2   rI   r!   )r   argkwr   s       r   r!   zSynonymProperty.get_history  s2    t{)4955$ty$c0R000r   c           
      X   | j         r| j        |j        j        vr2t	          j        d| j        d|j        j        d| j        d          |j        j        | j                 |j        v rd|j        |j        j        | j                          j        | j        k    r4t	          j        d| j        d| j        d| j        d| j                  t          j
        |j        j        | j                           }|                    | j        ||d	
           | j        |_        || _        d S )NzCan't compile synonym 'z': no column on table 'z	' named ''z'Can't call map_column=True for synonym =z4, a ColumnProperty already exists keyed to the name z for column T)init	setparent)r  r   persist_selectablecr   r   r2   descriptionr   r   ColumnProperty_configure_property_mapped_by_synonymrH   )r   rH   r$  r  s       r   
set_parentzSynonymProperty.set_parent  sI   ? 	,xv8:::** 			1===   )+DH5+, ,,-/99 
 ** xxxDIIItxxA   ))+DH5 A &&ty!$$&OOO#'8A r   )NNNNN)r&   r'   r(   r    r,   r   r   r   r  r>   r!   r,  r   r   s   @r   r  r    s        
 z& z& z& z& z& z&x H H XH 

 
 
  1 1 1! ! ! ! ! ! !r   r  rT   z:func:`.comparable_property` is deprecated and will be removed in a future release.  Please refer to the :mod:`~sqlalchemy.ext.hybrid` extension.c                   ,     e Zd ZdZ	 d fd	Zd Z xZS )ComparablePropertyz;Instruments a Python property for use in query expressions.Nc                     t          t          |                                            || _        || _        |p
|r|j        pd| _        |r|| _        t          j	        |            dS )a	  Provides a method of applying a :class:`.PropComparator`
        to any Python descriptor attribute.


        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)
r\   r.  r    rD   rZ   rO   rA   r[   r   rc   )r   rZ   rD   rA   r[   ra   s        r   r    zComparableProperty.__init__  sq    D 	 $''00222$"4E:<**<E 	DI%%%%%r   c                 .    |                      | |          S r   r   r   s     r   r>   z&ComparableProperty._comparator_factory'  r   r   )NNN)r&   r'   r(   rO   r    r>   r   r   s   @r   r.  r.    sc         FE CGH& H& H& H& H& H&T5 5 5 5 5 5 5r   r.  N)rO    r   r   r   
interfacesr   r   r   r   r
   r   r   r   r   r   r   langhelpersdependency_forrS   r   r  deprecated_clsr.  rP   r   r   <module>r6     s                      & & & & & & & & & & & &                                          9H 9H 9H 9H 9H 9H 9H 9Hx   !< NN~A ~A ~A ~A ~A* ~A ~A ON~AB   !< NN25 25 25 25 25 2 25 25 ON25j   !< NN    (   OND   !< NN	 N5 N5 N5 N5 N5+ N5 N5  ONN5 N5 N5r   