U
    ovgC                     @  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" 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&d'd(d)d*d+d,Z)d&d'd-d.d/d0d1d2d3Z*d&d'd4d/d0d5d6d7Z+d&d'd8d/d0d5d9d:Z,d&d'd0d;d<d=Z-d>S )@    )annotations)List)Optional)Union)AssignmentStmt)CallExpr)ClassDef)	Decorator)
LambdaExpr)ListExpr)
MemberExpr)NameExpr)PlaceholderNode)RefExpr)StrExpr)
SymbolNode)SymbolTableNode)TempNode)TypeInfo)Var)SemanticAnalyzerPluginInterface)AnyType)CallableType)get_proper_type)Instance)NoneType)
ProperType)Type)	TypeOfAny)UnboundType)	UnionType   )apply)infer)names)utilFr   r   boolz(Optional[List[util.SQLAlchemyAttribute]])clsapiis_mixin_scanreturnc                 C  s   t | |}|d krd S | jdr(d S t ||}t | |d k	r\|sXt| || |S g }| jj	s|j
 D ]\}}t| |||| qrnFt | jj	D ]6}t|trt| ||| qt|trt| ||| qt| | |st| || t || |S )Nbuiltins)r%   info_for_clsfullname
startswithZget_mapped_attributesZestablish_as_sqlalchemyr"   Z re_apply_declarative_assignmentsdefsbodyr$   items_scan_symbol_table_entryZflatten_typechecking
isinstancer   !_scan_declarative_assignment_stmtr	    _scan_declarative_decorator_stmt_scan_for_mapped_basesZadd_additional_orm_attributesZset_mapped_attributes)r'   r(   r)   infoZmapped_attributesZsym_namesymstmt r:   B/tmp/pip-unpacked-wheel-uqd9otp_/sqlalchemy/ext/mypy/decl_class.py,scan_declarative_assignments_and_apply_types0   sT    

    
   
   
r<   strr   zList[util.SQLAlchemyAttribute]None)r'   r(   namevalue
attributesr*   c              	   C  s  t |j}t|tsdS d}t|j}d}|tjtjtjtj	tj
tjhkrh|jrbt |jd }nd}n|tjkr|jsd}nt |jd }	t|	tr|	j}	t|	ttfr||	j|	}
|
dk	rt|
jtrt|
jtjrtt||
jg t g}nt|d|
jj| |rFd}t|||| j|  ttj}|dk	r|jdk	s`t |!tj"||jj#|jj$|| j%d dS )zaExtract mapping information from a SymbolTableNode that's in the
    type.names dictionary.

    NFr   T4Column type should be a TypeEngine subclass not '{}'zCan't infer type from attribute {} on class {}. please specify a return type from this function that is one of: Mapped[<python type>], relationship[<target class>], Column[<TypeEngine>], MapperProperty[<python type>]r?   linecolumntypr7   )&r   typer3   r   r$   type_id_for_named_nodeMAPPEDRELATIONSHIPCOMPOSITE_PROPERTYMAPPER_PROPERTYSYNONYM_PROPERTYCOLUMN_PROPERTYargsCOLUMNr   r   lookup_qualifiedr?   nodehas_base_type_id
TYPEENGINEr    r#   #extract_python_type_from_typeenginer   r%   failformatr-   r   r   special_formAssertionErrorappendSQLAlchemyAttributerD   rE   r7   )r'   r(   r?   r@   rA   Z
value_typeleft_hand_explicit_typetype_iderrtypeengine_argr8   msgr:   r:   r;   r2   r   sz    


  	

r2   r	   )r'   r(   r9   rA   r*   c              	   C  sv  |j D ](}t|tttfrt|tjkr q4qdS | jj	
|}d}t|jrttj}t|jj}|j|_t|gt|}	|jj|	_|	| jj	|< dS t|jjtr|jjj}
t|
trt|
| |}ndS |tjtjtjtjtjtj hkr|
j!rt"|
j!d }n|tj#kr|
j!r|
j!d }t|tr|$|j|}|dk	rt|jt%rt&|jtj'rt(t)*||jg t+ g}nt,|d-|jj.|
 |dkrd}t,||-|jj| ttj}t|jj}|j|_t|trt"t/||}|0tj1|g|j_t2t3|jj4|jj	}t|g|}	|jj|	_|5tj6|j|j7|j8|| j9d |	| jj	|< dS )a  Extract mapping information from a @declared_attr in a declarative
    class.

    E.g.::

        @reg.mapped
        class MyClass:
            # ...

            @declared_attr
            def updated_at(cls) -> Column[DateTime]:
                return Column(DateTime)

    Will resolve in mypy as::

        @reg.mapped
        class MyClass:
            # ...

            updated_at: Mapped[Optional[datetime.datetime]]

    Nr   rB   zCan't infer type from @declared_attr on function '{}';  please specify a return type from this function that is one of: Mapped[<python type>], relationship[<target class>], Column[<TypeEngine>], MapperProperty[<python type>]rC   ):Z
decoratorsr3   r   r   r   r$   rH   ZDECLARED_ATTRr/   r0   indexr%   Zname_is_dunderr?   r   r   rX   varrR   r   r   rG   funcr   Zret_typer   Ztype_id_for_unbound_typerI   rJ   rK   rL   rM   rN   rO   r   rP   rQ   r   rS   rT   r    r#   rU   r   rV   rW   r-   Zunbound_to_instanceZ
named_typeZNAMED_TYPE_SQLA_MAPPEDZexpr_to_mapped_constructorr
   	argumentsrZ   r[   rD   rE   r7   )r'   r(   r9   rA   decZ	dec_indexr\   Zany_Z	left_nodeZnew_stmtZ	func_typer]   r_   r8   r`   rvaluer:   r:   r;   r5      s    






  	


 
	r5   r   c              	   C  s  |j d }t|tsdS | jj|j}|dk	s4t|j}t|t	rHdS ||jksVtt|t
sdt|jdkr||jdkrt| j dS |jdkrt| j nd|jdrdS |jdkr
t|jtst|d| n,|jjD ]"}t|ttfrt| ||| qd}d}	|js&|jdkrt|jtr|j}	|jjd	kr|d	| }
|
dk	r|
jdk	rt|
jtjkrt|jjd }	|j}nFt|j}t|trt|jtjkrt|jd }	|}n|}	d}t|jt r|dk	r|	}nHt|jt!r>t|jj"t#r>t$%||||	|jj"}|dkrBdS ndS |dk	sPt|&tj'|j|j(|j)|| jd
 t*||||	| dS )zZExtract mapping information from an assignment statement in a
    declarative class.

    r   NZ__abstract__TZ__tablename____Z_mypy_mapped_attrsz+_mypy_mapped_attrs is expected to be a listZMappedrC   )+Zlvaluesr3   r   r7   r$   getr?   rY   rR   r   r   Z
parse_boolrf   r%   Zset_is_baseZset_has_tabler.   r   rV   r1   r   r"   Zapply_mypy_mapped_attrZis_inferredrG   r   rQ   rH   rI   r   rO   r   r   r   Zcalleer   r#   Z#infer_type_from_right_hand_nameexprrZ   r[   rD   rE   Zapply_type_to_mapped_statement)r'   r(   r9   rA   Zlvaluer8   rR   itemZleft_hand_mapped_typer\   Z
mapped_symZ	node_typeZpython_type_for_typer:   r:   r;   r4   g  s    








     

r4   )r'   r(   r*   c                 C  sN   t | |}|dkrdS |jdd D ]"}|jdr8q&t|j|dd q&dS )zGiven a class, iterate through its superclass hierarchy to find
    all other classes that are considered as ORM-significant.

    Locates non-mapped mixins and scans them for mapped attributes to be
    applied to subclasses.

    Nr!   r+   T)r)   )r%   r,   mror-   r.   r<   Zdefn)r'   r(   r7   Z	base_infor:   r:   r;   r6     s      r6   N)F).
__future__r   typingr   r   r   Z
mypy.nodesr   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   Zmypy.pluginr   Z
mypy.typesr   r   r   r   r   r   r   r   r   r     r"   r#   r$   r%   r<   r2   r5   r4   r6   r:   r:   r:   r;   <module>   sT    BY  