B
    S\z                 @   s  d Z ddl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 e ZdYddZeej_eej_eej_eej_eej_eej_dZddZe	jd[ddZeej_eej_eej _d\ddZ!dd Z"dd Z#e!ej$_dd Z%d]ddZ&e	e	'e&ej(_e&ej)_*e	je	j'd^ddZ+e+ej,_e	je	j'd_d d!Z-e-ej._e	je	j'd`d"d#Z/e/ej0_dad$d%Z1e	e	'e1ej2_e	e1ej3_*e	je	j'dbd&d'Z4e4ej5_e6 Z7e	jdcd(d)Z8e	'e8ej9_e8ej9_*e	je	j'ddd*d+Z:e:ej;_d,d- Z<ded.d/Z=e	je	j'dfd0d1Z>e=ej?_=e>ej?_d2d3 Z@d4d5 ZAdgd7d8ZBdhd9d:ZCd;d< ZDd=d> ZEd?d@ ZFdAdB ZGdCdD ZHdEdF ZIe	jJe	j'didGdHZKeIejL_IeKejL_djdIdJZMe	je	j'dkdKdLZNeMejO_MeNejO_e	jdldMdNZPePejQ_e	je	j'dmdOdPZReRej)_eRej3_e	je	j'dndQdRZSeSejT_e	jdodSdTZUeUejV_dpdUdVZWeWejX_YdWdX ZZdS )qzMthis module contains a set of functions to handle inference on astroid trees
    N)bases)context)
exceptions)
decorators)helpers)manager)nodes)dunder_lookup)	protocols)utilc             c   s
   | V  dS )zRinference's end for node such as Module, ClassDef, FunctionDef,
    Const...

    N )selfr   r   r   0lib/python3.7/site-packages/astroid/inference.py	infer_end.   s    r   c             C   sv   g }xl| j D ]b}t|tjrdt|j|}|s<tj| |dt	|dsTtj| |d|
t| q|| qW |S )z-Infer all values based on _BaseContainer.elts)noder   elts)r   
isinstancer   Starredr   
safe_infervaluer   InferenceErrorhasattrextend_infer_sequence_helperappend)r   r   valuesZeltZstarredr   r   r   r   >   s    
r   c             c   sR   t dd | jD s| V  n2t| |}t| | j| j| jd}|| |V  d S )Nc             s   s   | ]}t |tjV  qd S )N)r   r   r   ).0er   r   r   	<genexpr>Q   s    z!infer_sequence.<locals>.<genexpr>)lineno
col_offsetparent)anyr   r   typer   r    r!   postinit)r   r   r   new_seqr   r   r   infer_sequenceO   s    

r&   c             c   sX   t dd | jD s| V  n8t| |}t| | j| j| j}|t|  |V  d S )Nc             s   s   | ]\}}t |tjV  qd S )N)r   r   
DictUnpack)r   k_r   r   r   r   c   s    zinfer_map.<locals>.<genexpr>)	r"   items
_infer_mapr#   r   r    r!   r$   list)r   r   r*   r%   r   r   r   	infer_mapb   s    
r-   c             C   s.   t |  | }dd |D }t| S )ab  Delete nodes that equate to duplicate keys

    Since an astroid node doesn't 'equal' another node with the same value,
    this function uses the as_string method to make sure duplicate keys
    don't get through

    Note that both the key and the value are astroid nodes

    Fixes issue with DictUnpack causing duplicte keys
    in inferred Dict items

    :param dict(nodes.NodeNG, nodes.NodeNG) lhs_dict: Dictionary to 'merge' nodes into
    :param dict(nodes.NodeNG, nodes.NodeNG) rhs_dict: Dictionary with nodes to pull from
    :return dict(nodes.NodeNG, nodes.NodeNG): merged dictionary of nodes
    c             S   s   i | ]\}}||f|  qS r   )Z	as_string)r   keyr   r   r   r   
<dictcomp>~   s    z,_update_with_replacement.<locals>.<dictcomp>)	itertoolschainr*   dictr   )Zlhs_dictZrhs_dictZcombined_dictZ
string_mapr   r   r   _update_with_replacementl   s    r3   c             C   s   i }x| j D ]\}}t|tjrft||}|s6tjt|tjsPtj| |dt	||}t
||}qtj||d}tj||d}tdd ||fD rtj| |dt
|||i}qW |S )z$Infer all values based on Dict.items)r   r   )r   c             s   s   | ]}| V  qd S )Nr   )r   elemr   r   r   r      s    z_infer_map.<locals>.<genexpr>)r*   r   r   r'   r   r   r   r   Dictr+   r3   r"   )r   r   r   namer   Zdouble_starredZunpack_itemsr.   r   r   r   r+      s     
r+   c             C   s8   | }x|j r"t|j tjs"|j }qW |r4|j r4|j S dS )a   Search for the first function which encloses the given
    scope. This can be used for looking up in that function's
    scope, in case looking up in a lower scope for a particular
    name fails.

    :param node: A scope node.
    :returns:
        ``None``, if no parent function scope was found,
        otherwise an instance of :class:`astroid.scoped_nodes.Function`,
        which encloses the given node.
    N)r!   r   r   FunctionDef)r   Zcurrentr   r   r   _higher_function_scope   s    

r8   c             C   sn   |  | j\}}|sNt|  }|r4| | j\}}|sNtj| j|  |dt|}| j|_t	
|||S )z#infer a Name: use name lookup rules)r6   scoper   )lookupr6   r8   r9   r   ZNameInferenceError
contextmodcopy_context
lookupnamer   _infer_stmts)r   r   framestmtsZparent_functionr)   r   r   r   
infer_name   s    
rA   c          	   c   s   t |}t j| j| jd|_d|_|dk	r<t| | |_	xb| j
|D ]R}|tjkr`|V  qJy"t|dr|j| |dE dH  W qJ tjk
r   wJY qJX qJW t| |dS )z>infer a Call node by trying to guess what the function returns)argskeywordsNinfer_call_result)Zcallerr   )r   r   )r;   r<   CallContextrB   rC   callcontext	boundnode_populate_context_lookupcloneZextra_contextfuncinferr   Uninferabler   rD   r   r   r2   )r   r   rF   Zcalleer   r   r   
infer_call   s     


rM   Tc          
   c   s~   |j }|dkrtj| |dy(|r6| | |V  n| |V  W n4 tjk
rx } ztj| |d|W dd}~X Y nX dS )z7infer an Import node: return the imported module/objectN)r   r   )r=   r   r   do_import_module	real_nameAstroidBuildingError)r   r   asnamer6   excr   r   r   infer_import   s    rS   c          
   C   s   |j }|dkrtj| |d|r*| |}y|  }W n4 tjk
rj } ztj| |d|W dd}~X Y nX y2t|}||_ |j||| 	 kd}t
||S  tjk
r } ztj|j| ||d|W dd}~X Y nX dS )z:infer a ImportFrom node: return the imported module/objectN)r   r   )Zignore_locals)target	attributer   )r=   r   r   rO   rN   rP   r;   r<   getattrrootr   r>   AttributeInferenceErrormessage)r   r   rQ   r6   modulerR   r@   errorr   r   r   infer_import_from   s$    
"
r\   c          
   c   s   x| j |D ]}|tjkr$|V  q|r|jrt|tjrt|jtjry$t	t
|jt
|rj|j}W n tjk
r   Y nX y$||_|| j|E dH  d|_W q tjtjfk
r   d|_Y q tk
r   d|_Y qX qW t| |dS )zAinfer an Attribute node by using getattr on the associated objectN)r   r   )exprrK   r   rL   rG   r   r   Instancer   
is_subtypeobject_typer   _NonDeducibleTypeHierarchyigetattrZattrnamerX   r   AttributeErrorr2   )r   r   ownerr   r   r   infer_attribute  s.    





re   c          
   C   sr   |j d krtj| |dyt|  |j |S  tjk
rl } ztj|j| |j |d|W d d }~X Y nX d S )N)r   r   )rT   rU   r   )	r=   r   r   r   r>   rW   rV   rX   rY   )r   r   r[   r   r   r   infer_global@  s    
rf   c       	      c   sP  d}x2| j |D ] }|tjkr0tjV  dS x| j|D ]}|tjkrZtjV  dS t}|jtjkrp|}n$|jtjkrt	
|}|r|}n|}|tkrtj| |dy|||}W n@ tjtjtjtfk
r } ztj| |d|W dd}~X Y nX | |ks|tjkrtjV  dS ||E dH  d}q@W qW |rLt| |dS dS )zInference for subscripts

    We're understanding if the index is a Const
    or a slice, passing the result of inference
    to the value's `getitem` method, which should
    handle each supported index type accordingly.
    FN)r   r   T)r   rK   r   rL   slice_SUBSCRIPT_SENTINEL	__class__r   r^   r   Zclass_instance_as_indexr   r   getitemZAstroidTypeErrorZAstroidIndexErrorrX   rc   r2   )	r   r   Z	found_oner   indexZindex_valueZinstance_as_indexassignedrR   r   r   r   infer_subscriptS  sF    



"rm   c             #   s   | j }| jdkrtj}ntj}y fdd|D }W n tjk
rR   tjV  dS X xt	j
| D ]~}tdd |D rtjV  q`dd |D }tdd |D rtjV  q`tj}x,t||D ]\}}||r|V  P qW |V  q`W t|  d	S )
zInfer a boolean operation (and / or / not).

    The function will calculate the boolean operation
    for all pairs generated through inference for each component
    node.
    orc                s   g | ]}|j  d qS ))r   )rK   )r   r   )r   r   r   
<listcomp>  s    z!_infer_boolop.<locals>.<listcomp>Nc             s   s   | ]}|t jkV  qd S )N)r   rL   )r   itemr   r   r   r     s    z _infer_boolop.<locals>.<genexpr>c             S   s   g | ]}|  qS r   )
bool_value)r   rp   r   r   r   ro     s    c             s   s   | ]}|t jkV  qd S )N)r   rL   )r   rp   r   r   r   r     s    )r   r   )r   opoperatortruthnot_r   r   r   rL   r0   productr"   zipr2   )r   r   r   Z	predicateZpairZbool_valuesr   rq   r   )r   r   _infer_boolop  s0    	

rx   c             c   s2   x,|| |D ]}t ||r$tjV  q|V  qW d S )N)r   r   rL   )r   Zinfer_callabler   r[   resultr   r   r   _filter_operation_errors  s    

rz   c       
      c   s  x| j |D ]}y|| jV  W q tk
r\ } zt|| j|V  W dd}~X Y q tk
r } ztj	| j }|dkr|
 }|tjk	rt| V  ntjV  n:t|tjtjfst|| j|V  wyyt||}W n, tjk
r   t|| j|V  wY nX |d }t|j|d}|tjksF| sHwt|}tj|gd|_|j| |d}t|d}	|	dkr|V  n|	V  W nV tjk
r } zt|| j|V  W dd}~X Y n  tjk
r   tjV  Y nX W dd}~X Y qX qW dS )z3Infer what an UnaryOp should return when evaluated.Nr   )r   )rB   )operandrK   Zinfer_unary_oprr   	TypeErrorr   BadUnaryOperationMessagerc   r
   ZUNARY_OP_METHODrq   rL   r   Zconst_factoryr   r   r^   ClassDefr	   r:   r   rX   nextcallabler;   r<   rE   rF   rD   r   )
r   r   r{   rR   methrq   methodsinferredZcall_resultsry   r   r   r   _infer_unaryop  sH    "




"r   c             c   s"   t | t|tjE dH  t| |dS )z3Infer what an UnaryOp should return when evaluated.N)r   r   )rz   r   r   r}   r2   )r   r   r   r   r   infer_unaryop  s    r   c             C   s   t | tjo| jtkS )z0Check if the given const node is NotImplemented.)r   r   Constr   NotImplemented)Zconstr   r   r   _is_not_implemented  s    r   c       	      C   sR   t | |}t|| }|d }t|j|d}|tjkr@tj	| 
|||||S )z8Invoke binary operation inference on the given instance.r   )r   )r	   r:   r;   bind_context_to_noder   rK   r   rL   r   r   Zinfer_binary_op)	instanceopnoderr   otherr   method_namer   methodr   r   r   r   _invoke_binop_inference  s    
r   Fc          	   C   s"   t j| }tjt| |||||dS )z<Get an inference callable for an augmented binary operation.)r   rr   r   r   r   r   )r
   ZAUGMENTED_OP_METHOD	functoolspartialr   )r   r   rr   r   r   reverser   r   r   r   _aug_op*  s    
r   c          	   C   s2   |rt j| }n
t j| }tjt| |||||dS )zGet an inference callable for a normal binary operation.

    If *reverse* is True, then the reflected method will be used instead.
    )r   rr   r   r   r   r   )r
   ZREFLECTED_BIN_OP_METHODZBIN_OP_METHODr   r   r   )r   r   rr   r   r   r   r   r   r   r   _bin_op8  s    
r   c             c   s:   x4||fD ](}|   }tj|gd|_d|_|V  q
W dS )zGet contexts for binary operations.

    This will return two inference contexts, the first one
    for x.__op__(y), the other one for y.__rop__(x), where
    only the arguments are inversed.
    )rB   N)rI   r;   rE   rF   rG   )r   leftrightargnew_contextr   r   r   _get_binop_contextsL  s
    	r   c             C   s   |   |  kS )z$Check if type1 is the same as type2.)Zqname)Ztype1Ztype2r   r   r   
_same_type\  s    r   c       	   	   C   s   |j }t||r$t| ||||g}nvt||rDt| ||||g}nVt||rvt|||| |ddt| ||||g}n$t| ||||t|||| |ddg}|S )aV  Get the flow for binary operations.

    The rules are a bit messy:

        * if left and right have the same type, then only one
          method will be called, left.__op__(right)
        * if left and right are unrelated typewise, then first
          left.__op__(right) is tried and if this does not exist
          or returns NotImplemented, then right.__rop__(left) is tried.
        * if left is a subtype of right, then only left.__op__(right)
          is tried.
        * if left is a supertype of right, then right.__rop__(left)
          is first tried and then left.__op__(right)
    T)r   )rr   r   r   r   r_   is_supertype)	r   	left_typebinary_opnoder   
right_typer   reverse_contextrr   r   r   r   r   _get_binop_flowa  s    
r   c       
   
   C   s   |j d}|j }t||r>t| ||||t| ||||g}	nt||rlt| ||||t| ||||g}	nrt||rt| ||||t|||| |ddt| ||||g}	n2t| ||||t| ||||t|||| |ddg}	|	S )a  Get the flow for augmented binary operations.

    The rules are a bit messy:

        * if left and right have the same type, then left.__augop__(right)
          is first tried and then left.__op__(right).
        * if left and right are unrelated typewise, then
          left.__augop__(right) is tried, then left.__op__(right)
          is tried and then right.__rop__(left) is tried.
        * if left is a subtype of right, then left.__augop__(right)
          is tried and then left.__op__(right).
        * if left is a supertype of right, then left.__augop__(right)
          is tried, then right.__rop__(left) and then
          left.__op__(right)
    =T)r   )rr   stripr   r   r   r   r_   r   )
r   r   Z
aug_opnoder   r   r   r   Zbin_opZaug_opr   r   r   r   _get_aug_flow  s     
r   c          	   c   s  t || |\}}t| }t|}|| ||||||}x|D ]}	yt|	 }
W nH tk
rf   w>Y q> tjk
r|   w>Y q> tjk
r   tj	V  dS X t
dd |
D rtj	V  dS ttt|
rq>tdd |
D }|r|t|
krtj	V  dS |
E dH  dS q>W t||j|V  dS )zInfer a binary operation between a left operand and a right operand

    This is used by both normal binary operations and augmented binary
    operations, the only difference is the flow factory used.
    Nc             s   s   | ]}|t jkV  qd S )N)r   rL   )r   ry   r   r   r   r     s    z*_infer_binary_operation.<locals>.<genexpr>c             s   s   | ]}t |rd V  qdS )   N)r   )r   ry   r   r   r   r     s    )r   r   r`   r,   rc   r   rX   r   r   rL   r"   allmapr   sumlenBadBinaryOperationMessagerr   )r   r   r   r   flow_factoryr   r   r   r   r   ZresultsZnot_implementedr   r   r   _infer_binary_operation  s8    



r   c       
   	   c   s   | j }| j}|pt }t|}t|}|j|d}|j|d}xtt||D ]d\}}	tdd |	|fD r|t	j
V  dS yt||	| |tE dH  W qR tjk
r   t	j
V  Y qRX qRW dS )z!Binary operation inference logic.)r   c             s   s   | ]}|t jkV  qd S )N)r   rL   )r   r   r   r   r   r     s    z_infer_binop.<locals>.<genexpr>N)r   r   r;   InferenceContextr<   rK   r0   rv   r"   r   rL   r   r   r   ra   )
r   r   r   r   Zlhs_contextrhs_contextlhs_iterrhs_iterlhsrhsr   r   r   _infer_binop  s    

r   c             C   s   t | t|tjS )N)rz   r   r   r   )r   r   r   r   r   infer_binop  s    r   c          	   c   s   |dkrt  }| }| jj|d}| jj|d}xvt||D ]f\}}t	dd ||fD rlt
jV  dS yt||| |tdE dH  W qB tjk
r   t
jV  Y qBX qBW dS )z0Inference logic for augmented binary operations.N)r   c             s   s   | ]}|t jkV  qd S )N)r   rL   )r   r   r   r   r   r     s    z#_infer_augassign.<locals>.<genexpr>)r   r   r   r   r   )r;   r   rI   rT   	infer_lhsr   rK   r0   rv   r"   r   rL   r   r   r   ra   )r   r   r   r   r   r   r   r   r   r   _infer_augassign  s$    r   c             C   s   t | t|tjS )N)rz   r   r   r   )r   r   r   r   r   infer_augassign  s    r   c             C   s*   |j }|d krtj| |dt| ||S )N)r   r   )r=   r   r   r
   Z_arguments_infer_argname)r   r   r6   r   r   r   infer_arguments+  s    r   c             C   s:   |   }t|tjr||S t| j|d}t||S )zWinfer a AssignName/AssignAttr: need to inspect the RHS part of the
    assign node
    )r   )	Z	statementr   r   	AugAssignrK   r,   Zassigned_stmtsr   r>   )r   r   Zstmtr@   r   r   r   infer_assign6  s
    
r   c             c   sP   |   stjV  n:ytj| j|dE d H  W n tjk
rJ   tjV  Y nX d S )N)r   )Zhas_underlying_objectr   rL   MANAGERZinfer_ast_from_somethingobjectr   ZAstroidError)r   r   r   r   r   infer_empty_nodeH  s    
r   c             C   s   | j |S )N)r   rK   )r   r   r   r   r   infer_indexW  s    r   c             C   sd   t || }|s|}t j|gd|_t| jd|dd }t|tjsTt	j
d| |dt|| |S )N)rB   __getitem__)r   z(Could not find __getitem__ for {node!r}.)r   r   )r;   r   rE   rF   r   rb   r   r   ZBoundMethodr   r   rD   )r   rk   r   r   r   r   r   r   instance_getitem`  s    r   c             C   sp   i }|d kr|S x.| j D ]$}t|tjr4|||j< q|||< qW | jd k	rP| jng }x|D ]}|||j< qZW |S )N)rB   r   r   r   r   rC   )Zcallr   Zcontext_lookupr   rC   keywordr   r   r   rH   u  s    
rH   )N)N)N)N)N)N)NT)NT)N)N)N)N)N)N)F)F)N)N)N)N)N)N)N)N)[__doc__r   r0   rs   Zastroidr   r   r;   r   r   r   r   r   Zastroid.interpreterr	   r
   r   ZAstroidManagerr   r   ZModuleZ_inferr~   r7   ZLambdar   ZSlicer   Zraise_if_nothing_inferredr&   ZListZTupleSetr-   r3   r+   r5   r8   rA   Zpath_wrapperNameZ
AssignNamer   rM   ZCallrS   ZImportr\   Z
ImportFromre   Z	AttributeZ
AssignAttrrf   ZGlobalr   rh   rm   Z	Subscriptrx   ZBoolOprz   r   r   ZUnaryOpr   r   r   r   r   r   r   r   r   r   Zyes_if_nothing_inferredr   ZBinOpr   r   r   r   Z	Argumentsr   r   Z	EmptyNoder   ZIndexr   r^   rj   rH   r   r   r   r   <module>   s   





$83
6

#-,


