U
    x^]}                     @   s  d Z ddlZddl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 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 a a!dd Z"dd Z#dd Z$d2dd Z%d!d" Z&d#d$ Z'G d%d& d&e(Z)G d'd( d(e)Z*d)d* Z+d+d, Z,d-d. Z-d/e-_.d0d1 Z/dS )3z(Internal implementation for declarative.    N)instrumentation   )clsregistry   )event)exc)util)class_mapper)mapper)	mapperlib)synonym)QueryableAttribute)_is_mapped_class)InspectionAttr)MapperProperty)ColumnProperty)CompositeProperty)Column)Table)
expression)topologicalc                 C   s0   t | rt | S t| r(t| ddS d S d S )NF)	configure)_DeferredMapperConfighas_clsconfig_for_clsr   r	   cls r   G/tmp/pip-install-dq5v43_d/SQLAlchemy/sqlalchemy/ext/declarative/base.py_declared_mapping_info%   s
    

r   c                 C   s^   | t krd S t| dddrB| jD ]}t|}|d k	r |  S q d S t| }|d k	rV|S | S d S )N__abstract__Tstrict)object_get_immediate_cls_attr	__bases__"_resolve_for_abstract_or_classical"_dive_for_classically_mapped_class)r   supZ	classicalr   r   r   r&   0   s    

r&   c                 C   sP   t | drd S t| }|d k	r$| S | jD ]}t|}|d k	r*|  S q*d S d S )N_decl_class_registry)hasattrr   Zmanager_of_classr%   r'   )r   managerr(   r
   r   r   r   r'   C   s    



r'   Fc                 C   sr   t | tsdS | jD ]X}t|d}| o2t|dk	}||jkr|| ks^|rV|| jkrn |s|st||  S qdS )a  return an attribute of the class that is either present directly
    on the class, e.g. not on a superclass, or is from a superclass but
    this superclass is a non-mapped mixin, that is, not a descendant of
    the declarative base and is also not classically mapped.

    This is used to detect attributes that indicate something about
    a mapped class independently from any mapped classes that it may
    inherit from.

    Nr)   T)
issubclassr#   __mro__r*   r'   __dict__r%   getattr)r   attrnamer"   baseZ_is_declarative_inheritsZ_is_classicial_inheritsr   r   r   r$   W   s,    




  r$   c                 C   sB   t d krddlm a  t tjfat| dddr0d S t| || d S )Nr   )declared_attrr    Tr!   )r2   apir   classpropertydeclarative_propsr$   _MapperConfigsetup_mapping)r   	classnamedict_r   r   r   _as_declarativey   s    
r:   c                 C   s4   t | tr,t| ddr(td||f  dS dS d S )N
_cascadingFz~@declared_attr.cascading is not supported on the %s attribute on class %s.  This attribute invokes for subclasses in any case.T)
isinstancer5   r/   r   warn)objnamer   r   r   r   _check_declared_props_nocascade   s    
r@   c                   @   sx   e Zd Zedd Zdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd ZdS )r6   c                 C   s6   t |dddpt|d}|r"t}nt}|||| d S )N_sa_decl_prepare_nocascadeTr!   Z_sa_decl_prepare)r$   r*   r   r6   )r   cls_r8   r9   Z	defer_mapZcfg_clsr   r   r   r7      s      z_MapperConfig.setup_mappingc                 C   s   || _ t|| _|| _d | _t | _t | _	i | _
|   i | j _|   tj  z<t| j| j  |   |   |   |   |   W 5 tj  X d S N)r   dictr9   r8   persist_selectabler   OrderedDict
propertiessetdeclared_columnscolumn_copies_setup_declared_events_sa_declared_attr_reg_scan_attributesr   Z_CONFIGURE_MUTEXacquirereleaser   Z	add_class_extract_mappable_attributes_extract_declared_columns_setup_table_setup_inheritance_early_mapping)selfrB   r8   r9   r   r   r   __init__   s&    


z_MapperConfig.__init__c                 C   s   |    d S rC   )maprU   r   r   r   rT      s    z_MapperConfig._early_mappingc                    sL   t  jdr$ttd fdd}t  jdrHttd fdd}d S )	N__declare_last__after_configuredc                      s    j   d S rC   )r   rY   r   rX   r   r   rZ      s    z>_MapperConfig._setup_declared_events.<locals>.after_configured__declare_first__before_configuredc                      s    j   d S rC   )r   r[   r   rX   r   r   r\      s    z?_MapperConfig._setup_declared_events.<locals>.before_configured)r$   r   r   Zlistens_forr
   )rU   rZ   r\   r   rX   r   rK      s    

z$_MapperConfig._setup_declared_eventsc              	      s  | j  | j}| j}d }d  }}d } jD ]V}| k	oPt|d k	oPt|ddd }|sh| k	rh| | t| D ]\}	}
|	dkrt	|
|	 }|s|r|r fdd}qt|	dkrt	|
|	 }|s|r|r҈ j
}qt|	dkr0t	|
|	 }|s~|r|r~ j}t|tttd fs td	| k	r~d}qt|r\t|
trttd
|j|	| f  qtqt| k	rtt|
trtqtqtt|
trtdqtt|
trpt|
tj}|s|
jr|	|krtd|	 f  |
|
  ||	<  ||
< }t |	| nR|rtd t |	}t|tr:|j r:t|j!ts:|j"}| ||	< ||
< t|ttfr~|j#d kr~|
j$|_#qt| %||	|
 qtq(|r|sd }|| _&|| _'|| _(d S )NrA   Tr!   __mapper_args__c                      s
   t  jS rC   )rD   r]   r   r   r   r   mapper_args_fn   s    z6_MapperConfig._scan_attributes.<locals>.mapper_args_fn__tablename____table_args__z3__table_args__ value must be a tuple, dict, or NonezRegular (i.e. not __special__) attribute '%s.%s' uses @declared_attr, but owning class %s is mapped - not applying to subclass %s.zMapper properties (i.e. deferred,column_property(), relationship(), etc.) must be declared as @declared_attr callables on declarative mixin classes.zXAttribute '%s' on class %s cannot be processed due to @declared_attr.cascading; skippingzJUse of sqlalchemy.util.classproperty on declarative classes is deprecated.))r   r9   rJ   r-   r   r$   _produce_column_copiesvarsitemsr@   r_   r`   r<   tuplerD   typer   ArgumentErrorr5   r   r=   __name__r   r   InvalidRequestErrorr4   r;   __get__setattrZwarn_deprecatedr/   r   Z_is_internal_proxyZoriginal_propertyZ
descriptordoc__doc___warn_for_decl_attributes
table_args	tablenamer^   )rU   r9   rJ   r^   rn   Zinherited_table_argsro   r1   Zclass_mappedr?   r>   Z
check_declZoldclasspropretr   r   r   rM      s    
  
    
   




 
z_MapperConfig._scan_attributesc                 C   s"   t |tjrtd||f  d S )NzAttribute '%s' on class %s appears to be a non-schema 'sqlalchemy.sql.column()' object; this won't be part of the declarative mapping)r<   r   ZColumnClauser   r=   )rU   r   keycr   r   r   rm   c  s    z'_MapperConfig._warn_for_decl_attributesc                 C   s   | j }| j}| j}t| D ]\}}t|trt|||k	rBqq|jrTt	
dq||krd|krx|jpl||d jks|  ||< }|j|_t||| |||< qd S )NzvColumns with foreign keys to other columns must be declared as @declared_attr callables on declarative mixin classes. 	__table__)r   r9   rJ   rb   rc   r<   r   r/   Zforeign_keysr   rh   r?   rr   copy_creation_orderrj   )rU   r1   r   r9   rJ   r?   r>   Zcopy_r   r   r   ra   l  s(    
z$_MapperConfig._produce_column_copiesc                 C   sX  | j }| j}| j}t|ddd}t|D ](}|dkr8q(|| }t|trvt|trj|jrjt	
d| j   t||}n4t|tr|j|k	r|j|krt|j}t||| t|trt|dkrt|d ttfrt	
d|  q(nZt|ttfs*|d	s(|| | ||| |s(t||| q(n|d
kr>tdt||}|||< q(d S )NrA   Tr!   )rs   r_   r]   zUse of @declared_attr.cascading only applies to Declarative 'mixin' and 'abstract' classes.  Currently, this flag is ignored on mapped class %sr   r   zIgnoring declarative-like tuple value of attribute '%s': possibly a copy-and-paste error with a comma accidentally placed at the end of the line?__metadatazdAttribute name 'metadata' is reserved for the MetaData instance when using a declarative base class.)r   r9   rG   r$   listr<   r5   r2   r;   r   r=   r/   r   class_rq   r   rj   rd   lenr   r   
startswithpoprm   r   rh   r   _deferred_relationship)rU   r   r9   	our_stuffZlate_mappedkvaluepropr   r   r   rP     sj      





z*_MapperConfig._extract_mappable_attributesc              
      s  | j   j fddd | j}tt}t  D ]\}}t|t	t
fr|jD ]F}t|trR|jd krRt|| t|t
s||j | || qRq6t|tr6t|| ||j | || ||jkr6 |= q6| D ]4\}}t|dkrtd| j|dt|f  qd S )Nc                    s
    |  j S rC   ru   rq   r~   r   r   <lambda>      z9_MapperConfig._extract_declared_columns.<locals>.<lambda>r   r   zzOn class %r, Column object %r named directly multiple times, only one will be used: %s. Consider using orm.synonym insteadz, )rG   sortrI   collectionsdefaultdictrH   rx   rc   r<   r   r   columnsr   table_undefer_column_namer?   addrq   rz   r   r=   r8   joinsorted)rU   rI   Zname_to_prop_keyrq   rr   colr?   keysr   r   r   rQ     s2    







z'_MapperConfig._extract_declared_columnsc                 C   s4  | j }| j}| j}| j}| j}t|dd d }| _d }t|drPt|j	}nt
}d|kr|d k	rdi  }}	|rt|tr|}	n4t|trt|d tr|dd |d  }}	n|}|d	}
|
rd
|	d< |||jft|t| |	 |_}n6|j}|r*|D ]$}|j|std|j q|| _d S )Nc                 S   s   | j S rC   r   )rr   r   r   r   r     r   z,_MapperConfig._setup_table.<locals>.<lambda>r   __table_cls__rs   r   r   Z__autoload__Tautoloadz8Can't add additional column %r when specifying __table__)r   ro   rn   r9   rI   r   r*   r   unbound_method_to_callabler   r   r<   rD   rd   getrw   rs   rr   Zcontains_columnr   rf   rq   local_table)rU   r   ro   rn   r9   rI   r   Z	table_clsargsZtable_kwr   rr   r   r   r   rR     sX     




z_MapperConfig._setup_tablec           
      C   sv  | j }| j}| j}| j}g }|jD ]:}t|}|d kr8q"t|d k	r"t|ddds"|| q"|rt	|dkrt
d||f |d | _nd | _|d kr| jd krt|dst
d| n| jrrt| j}|j }|j}	|d krr|rt
d	|D ]x}|j|jkr:|j|j |krqt
d
|||j|j f |jrLt
d|| |	d k	r|	|k	r|	| qd S )NrA   Tr!   r   z&Class %s has multiple mapped bases: %rr   Z__no_table__zwClass %r does not have a __table__ or __tablename__ specified and does not inherit from an existing table-mapped class.z?Can't place __table_args__ on an inherited class with no table.z;Column '%s' on class %s conflicts with existing column '%s'zDCan't place primary key columns on an inherited class with no table.)r   r   rn   rI   r%   r&   r   r$   appendrz   r   rh   inheritsrE   rf   r?   rr   Zprimary_keyappend_columnZ_refresh_for_new_column)
rU   r   r   rn   rI   r   rr   inherited_mapperinherited_tableZinherited_persist_selectabler   r   r   rS   '  s    
  



z _MapperConfig._setup_inheritancec           
         sB  | j }| jr|  }ni }dD ]&}||kr|| }| j||||< qd|ksVtd| jrf| j|d< | jr(|dds(t| j  j}d|krt fdd|j	D 
 jpd	 |d< }|d
d | jD  t| D ]D\}}t|tjsq| jkr j| }t|tr|g|j ||< q| }	||	d< |	| _d S )N)Zversion_id_colZpolymorphic_onr   z=Can't specify 'inherits' explicitly with declarative mappingsZconcreteFexclude_propertiesc                    s   g | ]}| j kr|jqS r   )Z_columntopropertyrq   .0rr   r   r   r   
<listcomp>  s   
z;_MapperConfig._prepare_mapper_arguments.<locals>.<listcomp>r   c                 S   s   g | ]
}|j qS r   r   r   r   r   r   r     s     rG   )rG   r^   rJ   r   AssertionErrorr   r   r   rH   rr   unionr   difference_updaterI   rx   rc   r<   r   ZColumnElementZ_propsr   r   rt   mapper_args)
rU   rG   r   r   vr   r   r   pZresult_mapper_argsr   r   r   _prepare_mapper_argumentsr  sL    







z'_MapperConfig._prepare_mapper_argumentsc                 C   sN   |    t| jdr$t| jj}nt}|| j| jf| j | j_	}| j`
|S )N__mapper_cls__)r   r*   r   r   r   r   r
   r   r   
__mapper__rL   )rU   Z
mapper_clsZmp_r   r   r   rW     s     z_MapperConfig.mapN)rg   
__module____qualname__classmethodr7   rV   rT   rK   rM   rm   ra   rP   rQ   rR   rS   r   rW   r   r   r   r   r6      s   
$ 	F'3K<r6   c                       s   e Zd Ze Zdd Zedd Zej	dd Ze
dd Ze
dd	 Ze
d
d Ze
dd Ze
dddZ fddZ  ZS )r   c                 C   s   d S rC   r   rX   r   r   r   rT     s    z$_DeferredMapperConfig._early_mappingc                 C   s   |   S rC   )_clsrX   r   r   r   r     s    z_DeferredMapperConfig.clsc                 C   s    t || j| _| | j| j< d S rC   )weakrefref_remove_config_clsr   _configs)rU   ry   r   r   r   r     s    c                 C   s   | j |d  d S rC   )r   r|   )r   r   r   r   r   r     s    z(_DeferredMapperConfig._remove_config_clsc                 C   s   t |tot|| jkS rC   )r<   re   r   r   r   r   ry   r   r   r   r     s    z_DeferredMapperConfig.has_clsc                 C   s.   t |dr|  tj|dt| dd S )N_sa_raise_deferred_configzOClass %s has a deferred mapping on it.  It is not yet usable as a mapped class.)msg)r*   r   orm_excZUnmappedClassErrorZ_safe_cls_namer   r   r   r   raise_unmapped_for_cls  s    
z,_DeferredMapperConfig.raise_unmapped_for_clsc                 C   s   | j t| S rC   )r   r   r   r   r   r   r   r     s    z$_DeferredMapperConfig.config_for_clsTc                    sv   fdddd | j  D D }|s*|S tdd |D  g } D ] | fddjD  qDtt||S )Nc                    s&   g | ]\}}|d k	rt | r|qS rC   )r,   )r   mrB   )base_clsr   r   r     s    
z:_DeferredMapperConfig.classes_for_base.<locals>.<listcomp>c                 S   s   g | ]}||j fqS r   r   r   r   r   r   r   r     s     c                 s   s   | ]}|j |fV  qd S rC   r   r   r   r   r   	<genexpr>  s     z9_DeferredMapperConfig.classes_for_base.<locals>.<genexpr>c                 3   s&   | ]}| kr |   fV  qd S rC   r   )r   r   )all_m_by_clsm_clsr   r   r     s   )r   valuesrD   extendr%   rx   r   r   )r   r   r   classes_for_baseZtuplesr   )r   r   r   r   r     s    

z&_DeferredMapperConfig.classes_for_basec                    s   | j | jd  tt|  S rC   )r   r|   r   superr   rW   rX   	__class__r   r   rW     s    z_DeferredMapperConfig.map)T)rg   r   r   r   rF   r   rT   propertyr   setterr   r   r   r   r   r   rW   __classcell__r   r   r   r   r     s"   






r   c                 C   s  d| j krt|tr:t|| | j| | j|| nt|tr|j	D ].}t|trJ|j
dkrJt|| | j| qJ| j|| npt|tr| j|t| | nNt|tr|j|krt|j}| j|t| | nt| || | j  nt| || dS )zadd an attribute to an existing declarative class.

    This runs through the logic to determine MapperProperty,
    adds it to the Mapper, adds a column to the mapped Table, etc.

    r   N)r.   r<   r   r   rs   r   r   Zadd_propertyr   r   r   r   r   r}   r   rq   r   re   __setattr___expire_memoizations)r   rq   r   r   r   r   r   _add_attribute   s2    






 

 
r   c                 C   sj   d| j krZ|| j krZ| jjsZ| j | }t|ttttfrBtdqft	
| | | j  nt	
| | d S )Nr   z<Can't un-map individual mapped attributes on a mapped class.)r.   r   Z_dispose_calledr<   r   r   r   r   NotImplementedErrorre   __delattr__r   )r   rq   r   r   r   r   _del_attribute%  s"    
 
r   c                 K   sB   t | }|D ]0}t||s,td||jf t| |||  qdS )a=  A simple constructor that allows initialization from kwargs.

    Sets attributes on the constructed instance using the names and
    values in ``kwargs``.

    Only keys that are present as
    attributes of the instance's class are allowed. These could be,
    for example, any mapped columns or relationships.
    z(%r is an invalid keyword argument for %sN)re   r*   	TypeErrorrg   rj   )rU   kwargsrB   r   r   r   r   _declarative_constructor:  s    

r   rV   c                 C   s$   |j d kr| |_ |jd kr | |_d S rC   )rq   r?   )rq   columnr   r   r   r   P  s    

r   )F)0rl   r   r   Zsqlalchemy.ormr    r   r   r   r   Zormr	   r   r
   r   r   Zorm.attributesr   Zorm.baser   r   Zorm.interfacesr   Zorm.propertiesr   r   Zschemar   r   Zsqlr   r   r2   r5   r   r&   r'   r$   r:   r@   r#   r6   r   r   r   r   rg   r   r   r   r   r   <module>   sP   
"    .B%