B
    \|                 @   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 aa dd Z!dd Z"dd Z#d1d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,_-d/d0 Z.dS )2z(Internal implementation for declarative.    N)instrumentation   )clsregistry   )event)exc)util)class_mapper)mapper)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)Z	configure)_DeferredMapperConfighas_clsconfig_for_clsr   r	   )cls r   >lib/python3.7/site-packages/sqlalchemy/ext/declarative/base.py_declared_mapping_info$   s
    

r   c             C   s`   | t krd S t| dddrDx@| jD ]}t|}|d k	r"|S q"W d S nt| }|d k	rX|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"   /   s    r"   c             C   sP   t | drd S t| }|d k	r$| S x&| jD ]}t|}|d k	r,|S q,W d S d S )N_decl_class_registry)hasattrr   Zmanager_of_classr!   r#   )r   Zmanagerr$   r
   r   r   r   r#   B   s    

r#   Fc             C   sv   t | tsdS xb| jD ]T}t|d}| o4t|dk	}||jkr|| ks`|rX|| jkrn |s|st||S qW dS 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   Zattrnamer   baseZ_is_declarative_inheritsZ_is_classicial_inheritsr   r   r   r    V   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   T)r   )r,   Zapir   classpropertydeclarative_propsr    _MapperConfigsetup_mapping)r   	classnamedict_r   r   r   _as_declarativex   s    
r3   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)
isinstancer.   r*   r   warn)objnamer   r   r   r   _check_declared_props_nocascade   s    
r9   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 )r/   c             C   s6   t |dddpt|d}|r"t}nt}|||| d S )N_sa_decl_prepare_nocascadeT)r   Z_sa_decl_prepare)r    r&   r   r/   )r   cls_r1   r2   Z	defer_mapZcfg_clsr   r   r   r0      s    
z_MapperConfig.setup_mappingc             C   s   || _ t|| _|| _d | _t | _t | _	i | _
|   i | j _|   t| j| j  |   |   |   |   |   d S )N)r   dictr2   r1   persist_selectabler   OrderedDict
propertiessetdeclared_columnscolumn_copies_setup_declared_events_sa_declared_attr_reg_scan_attributesr   Z	add_class_extract_mappable_attributes_extract_declared_columns_setup_table_setup_inheritance_early_mapping)selfr;   r1   r2   r   r   r   __init__   s     

z_MapperConfig.__init__c             C   s   |    d S )N)map)rK   r   r   r   rJ      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 )N)r   rN   r   )rK   r   r   rO      s    z>_MapperConfig._setup_declared_events.<locals>.after_configured__declare_first__before_configuredc                  s    j   d S )N)r   rP   r   )rK   r   r   rQ      s    z?_MapperConfig._setup_declared_events.<locals>.before_configured)r    r   r   Zlistens_forr
   )rK   rO   rQ   r   )rK   r   rC      s    z$_MapperConfig._setup_declared_eventsc          	      s  | j  | j}| j}d }d  }}d }xj jD ]^}| k	oTt|d k	oTt|ddd }|sl| k	rl| | xt| D ]
\}	}
|	dkrt	|
|	 }|s|r|r fdd}q||	dkrt	|
|	 }|s|r|rڈ j
}q||	dkr:t	|
|	 }|s|r|r j}t|tttd fs*td	| k	rd}q||rft|
tr|td
|j|	| f  q|q|| k	r|t|
tr~q|q|t|
trtdq|t|
trzt|
tj}|s|
jr|	|krtd|	 f  |
|
  ||	<  ||
< }t |	| nR|rtd t |	}t|trD|j rDt|j!tsD|j"}| ||	< ||
< t|ttfr|j#d kr|
j$|_#q|| %||	|
 q|W q,W |r|sd }|| _&|| _'|| _(d S )Nr:   T)r   __mapper_args__c                  s
   t  jS )N)r<   rR   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   r2   rB   r(   r   r    _produce_column_copiesvarsitemsr9   rT   rU   r5   tupler<   typer   ArgumentErrorr.   r   r6   __name__r   r   InvalidRequestErrorr-   r4   __get__setattrZwarn_deprecatedr*   r   Z_is_internal_proxyZoriginal_propertyZ
descriptordoc__doc___warn_for_decl_attributes
table_args	tablenamerS   )rK   r2   rB   rS   rc   Zinherited_table_argsrd   r+   Zclass_mappedr8   r7   Z
check_declZoldclasspropZretr   )r   r   rE      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)r5   r   ZColumnClauser   r6   )rK   r   keycr   r   r   rb   ]  s    z'_MapperConfig._warn_for_decl_attributesc             C   s   | j }| j}| j}xt| D ]\}}t|tr t|||k	rDq q |jrVt	
dq ||kr d|krz|jpn||d jks |  ||< }|j|_t||| |||< q W d S )NzvColumns with foreign keys to other columns must be declared as @declared_attr callables on declarative mixin classes. 	__table__)r   r2   rB   rW   rX   r5   r   r*   Zforeign_keysr   r]   r8   rf   copy_creation_orderr_   )rK   r+   r   r2   rB   r8   r7   Zcopy_r   r   r   rV   f  s"    
z$_MapperConfig._produce_column_copiesc             C   s^  | j }| j}| j}t|ddd}x6t|D ](}|dkr<q,|| }t|trzt|trn|jrnt	
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rBtdt||}|||< q,W d S )Nr:   T)r   )rg   rT   rR   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   r2   r?   r    listr5   r.   r,   r4   r   r6   r*   r   class_re   r   r_   rY   lenr   r   
startswithpoprb   r   r]   r   _deferred_relationship)rK   r   r2   	our_stuffZlate_mappedkvalueZpropr   r   r   rF     sN    









z*_MapperConfig._extract_mappable_attributesc          
      s*  | j   j fddd | j}tt}xt  D ]\}}t|t	t
frx|jD ]F}t|trV|jd krVt|| t|t
s||j | || qVW q8t|tr8t|| ||j | || ||jkr8 |= q8W x@| D ]4\}}t|dkrtd| j|dt|f  qW d S )Nc                s
    |  j S )N)ri   )re   )rr   r   r   <lambda>  s    z9_MapperConfig._extract_declared_columns.<locals>.<lambda>)re   r   zzOn class %r, Column object %r named directly multiple times, only one will be used: %s. Consider using orm.synonym insteadz, )r?   sortrA   collectionsdefaultdictr@   rl   rX   r5   r   r   columnsr   table_undefer_column_namer8   addre   rn   r   r6   r1   joinsorted)rK   rA   Zname_to_prop_keyre   rf   colr8   keysr   )rr   r   rG     s.    







z'_MapperConfig._extract_declared_columnsc             C   s8  | 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| |	 |_}n:|j}|r.x,|D ]$}|j|std|j qW || _d S )Nc             S   s   | j S )N)ri   )rf   r   r   r   ru     s    z,_MapperConfig._setup_table.<locals>.<lambda>)re   __table_cls__rg   r   r   Z__autoload__Tautoloadz8Can't add additional column %r when specifying __table__)r   rd   rc   r2   rA   r~   r&   r   unbound_method_to_callabler   r   r5   r<   rY   getrk   rg   rf   Zcontains_columnr   r[   re   local_table)rK   r   rd   rc   r2   rA   rz   Z	table_clsargsZtable_kwr   rf   r   r   r   rH     sJ    





z_MapperConfig._setup_tablec       
      C   s~  | j }| j}| j}| j}g }xD|jD ]:}t|}|d kr:q$t|d k	r$t|ddds$|| q$W |rt	|dkrt
d||f |d | _nd | _|d kr| jd krt|dst
d| n| jrzt| j}|j }|j}	|d krz|rt
d	x|D ]x}|j|jkr@|j|j |kr$qt
d
|||j|j f |jrRt
d|| |	d k	r|	|k	r|	| qW d S )Nr:   T)r   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   rc   rA   r!   r"   r   r    appendrn   r   r]   inheritsr=   r[   r8   rf   Zprimary_keyappend_columnZ_refresh_for_new_column)
rK   rz   r   rc   rA   r   rf   inherited_mapperinherited_tableZinherited_persist_selectabler   r   r   rI   !  s`    






z _MapperConfig._setup_inheritancec       
         sJ  | j }| jr|  }ni }x.dD ]&}||kr || }| j||||< q W d|ksZtd| jrj| j|d< | jr0|dds0t| j  j}d|krt fdd|j	D 
 jpd	 |d< }|d
d | jD  xTt| D ]D\}}t|tjsq| jkr j| }t|tr|g|j ||< qW | }	||	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_columntopropertyre   ).0rf   )r   r   r   
<listcomp>  s   z;_MapperConfig._prepare_mapper_arguments.<locals>.<listcomp>r   c             S   s   g | ]
}|j qS r   )re   )r   rf   r   r   r   r     s    r?   )r?   rS   rB   r   AssertionErrorr   r   r   r@   rf   unionr   difference_updaterA   rl   rX   r5   r   ZColumnElementZ_propsr   ry   rh   mapper_args)
rK   r?   r   rs   vr   r   r   pZresult_mapper_argsr   )r   r   _prepare_mapper_argumentsl  s@    





	


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__rD   )rK   Z
mapper_clsZmp_r   r   r   rM     s    z_MapperConfig.mapN)r\   
__module____qualname__classmethodr0   rL   rJ   rC   rE   rb   rV   rF   rG   rH   rI   r   rM   r   r   r   r   r/      s     	F'3K<r/   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 )Nr   )rK   r   r   r   rJ     s    z$_DeferredMapperConfig._early_mappingc             C   s   |   S )N)_cls)rK   r   r   r   r     s    z_DeferredMapperConfig.clsc             C   s    t || j| _| | j| j< d S )N)weakrefref_remove_config_clsr   _configs)rK   rm   r   r   r   r     s    c             C   s   | j |d  d S )N)r   rp   )r   r   r   r   r   r     s    z(_DeferredMapperConfig._remove_config_clsc             C   s   t |tot|| jkS )N)r5   rZ   r   r   r   )r   rm   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_name)r   rm   r   r   r   raise_unmapped_for_cls  s    
z,_DeferredMapperConfig.raise_unmapped_for_clsc             C   s   | j t| S )N)r   r   r   )r   rm   r   r   r   r     s    z$_DeferredMapperConfig.config_for_clsTc                sz   fdddd | j  D D }|s*|S tdd |D  g }x( D ] | fddjD  qFW tt||S )Nc                s&   g | ]\}}|d k	rt | r|qS )N)r'   )r   mr;   )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 )N)r   )r   r   r   r   r   	<genexpr>  s    z9_DeferredMapperConfig.classes_for_base.<locals>.<genexpr>c             3   s&   | ]}| kr |   fV  qd S )Nr   )r   r   )all_m_by_clsm_clsr   r   r     s   )r   valuesr<   extendr!   rl   r   rv   )r   r   rv   classes_for_baseZtuplesr   )r   r   r   r   r     s    

z&_DeferredMapperConfig.classes_for_basec                s   | j | jd  tt|  S )N)r   rp   r   superr   rM   )rK   )	__class__r   r   rM     s    z_DeferredMapperConfig.map)T)r\   r   r   r   r>   r   rJ   propertyr   setterr   r   r   r   r   r   rM   __classcell__r   r   )r   r   r     s   r   c             C   s  d| j krt|tr<t|| | j| | j|| nt|trx8|j	D ].}t|trN|j
dkrNt|| | j| qNW | 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)   r5   r   r{   rg   r   r   Zadd_propertyr   ry   rz   r   r   rq   r   re   r   rZ   __setattr___expire_memoizations)r   re   rt   r   r   r   r   _add_attribute  s*    





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_calledr5   r   r   r   r   NotImplementedErrorrZ   __delattr__r   )r   re   rt   r   r   r   _del_attribute  s    


r   c             K   sF   t | }x8|D ]0}t||s.td||jf t| |||  qW 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)rZ   r&   	TypeErrorr\   r_   )rK   kwargsr;   rs   r   r   r   _declarative_constructor4  s    


r   rL   c             C   s$   |j d kr| |_ |jd kr | |_d S )N)re   r8   )re   columnr   r   r   r{   J  s    

r{   )F)/ra   rw   r   Zsqlalchemy.ormr    r   r   r   r   Zormr	   r   r
   r   Zorm.attributesr   Zorm.baser   r   Zorm.interfacesr   Zorm.propertiesr   r   Zschemar   r   Zsqlr   r   r,   r.   r   r"   r#   r    r3   r9   r   r/   r   r   r   r   r\   r{   r   r   r   r   <module>   sN   
"    )B%