U
    cc%                     @   s  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 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$ e	eeeef ee"j% d d!d"d#Z&e	eee"j% d d$d%d&Z'eeeee ee d d'd(d)Z(e	eee"j% d d$d*d+Z)ee	e*e*d d,d-d.Z+d S )/    )List)Optional)Union)ARG_NAMED_OPT)Argument)AssignmentStmt)CallExpr)ClassDef)MDEF)
MemberExpr)NameExpr)RefExpr)StrExpr)SymbolTableNode)TempNode)TypeInfo)Var)SemanticAnalyzerPluginInterface)add_method_to_class)AnyType)get_proper_type)Instance)NoneTyp)
ProperType)	TypeOfAny)UnboundType)	UnionType   )infer)util)NAMED_TYPE_SQLA_MAPPEDN)clsapiitem
attributesreturnc              	   C   s   t |tr|j}nt |tr$|j}nd S | jjD ]2}t |tr0t |jd tr0|jd j|kr0 q|q0t	
|d||  d S |jd krt	
|d| d S t|j}t |tttfst|t	j||j|j|| jd t|||jd |d  d S )Nr   zCan't find mapped attribute {}zBStatement linked from _mypy_mapped_attrs has no typing information)namelinecolumntypinfo)
isinstancer   r&   r   valuedefsbodyr   lvaluesr   Zfailformattyper   r   r   r   AssertionErrorappendSQLAlchemyAttributer'   r(   r*   apply_type_to_mapped_statement)r!   r"   r#   r$   r&   stmtleft_hand_explicit_type r8   =/tmp/pip-unpacked-wheel-8u86ls_i/sqlalchemy/ext/mypy/apply.pyapply_mypy_mapped_attr*   sV    



 
    r:   )r!   r"   r$   r%   c           	   	   C   s  dd |D }d}| j jD ]p}t|trt|jd tr|jd j|krt|jd jtr|jd j}||jd j j	}t
|j	}t|trtt|tstt|jtrtt|jjtrtt|jjjtrt|jjjjdk	rt|jjjjjtkrt|jjjdkrtt|jjd trtt|jjd jtrtt|||||jjd j}|dkst|tr^q|||jd j _	d}|dk	r|t|g|_	q|rt| j| dS )zlFor multiple class passes, re-apply our left-hand side types as mypy
    seems to reset them in place.

    c                 S   s   i | ]}|j |qS r8   )r&   .0attrr8   r8   r9   
<dictcomp>h   s      z4re_apply_declarative_assignments.<locals>.<dictcomp>Fr   NZ_empty_constructorT)r-   r.   r+   r   r/   r   r&   noder   r1   r   r   rvaluer   Zcalleer   exprfullnamer    argsr   r   Z#infer_type_from_right_hand_nameexpr
named_typer   Zset_mapped_attributesr*   )	r!   r"   r$   Zmapped_attr_lookupZupdate_cls_metadatar6   	left_nodepython_type_for_typeZleft_node_proper_typer8   r8   r9    re_apply_declarative_assignments_   s~    	





 
 rG   )r"   r6   lvaluer7   rF   r%   c                 C   sb   |j }t|tst|dk	r.| t|g|_n"d|_| t|dkrFg n|g|_t	|j
|_
dS )a  Apply the Mapped[<type>] annotation and right hand object to a
    declarative assignment statement.

    This converts a Python declarative class statement such as::

        class User(Base):
            # ...

            attrname = Column(Integer)

    To one that describes the final Python behavior to Mypy::

        class User(Base):
            # ...

            attrname : Mapped[Optional[int]] = <meaningless temp node>

    NF)r?   r+   r   r2   rD   r    r1   Zis_inferred_defr   Zexpr_to_mapped_constructorr@   )r"   r6   rH   r7   rF   rE   r8   r8   r9   r5      s     r5   c              	   C   s&  t | |}|dkrdS t |}d|jkr|sdd |D }|jdd D ]@}d|jkr\qLt ||}|dkrrqL|D ]}||j|j	 qvqLg }	|
 D ]:\}
}|dkrttj}|	tt|
||t|td qt|| d|	t  d	|jkrt |rt|| d
d	 |s"t|| dd dS )zCApply __init__, __table__ and other attributes to the mapped class.N__init__c                 S   s   i | ]}|j |jqS r8   )r&   r1   r;   r8   r8   r9   r>      s      z1add_additional_orm_attributes.<locals>.<dictcomp>r   Z
sqlalchemy)variableZtype_annotationZinitializerkindZ	__table__zsqlalchemy.sql.schema.Tablezsqlalchemy.orm.mapper.MapperZ
__mapper__)r   Zinfo_for_clsZget_is_basenamesmrometadataZget_mapped_attributes
setdefaultr&   r1   itemsr   r   special_formr3   r   r   r   r   r   r   Zget_has_table _apply_placeholder_attr_to_class)r!   r"   r$   r*   is_baseZmapped_attr_namesbaseZbase_cls_attributesr=   	argumentsr&   r)   r8   r8   r9   add_additional_orm_attributes   sR    


	      rW   )r"   r!   qualified_nameattrnamer%   c                 C   sr   |  |}|r,t|jtstt|jg }n
ttj}t	|}|j
d | |_|j|_||_tt||jj|< d S )N.)Zlookup_fully_qualified_or_noner+   r?   r   r2   r   r   r   rR   r   rB   Z	_fullnamer*   r1   r   r
   rM   )r"   r!   rX   rY   symtype_varr8   r8   r9   rS     s    

rS   ),typingr   r   r   Z
mypy.nodesr   r   r   r   r	   r
   r   r   r   r   r   r   r   r   Zmypy.pluginr   Zmypy.plugins.commonr   Z
mypy.typesr   r   r   r   r   r   r   r    r   r   rM   r    r4   r:   rG   r5   rW   strrS   r8   r8   r8   r9   <module>   st   
6R76