B
    a)                 @   s   d Z ddlmZ ddlmZ ddlmZmZmZmZm	Z	 ddl
mZ ddlmZmZmZmZmZ dd Zd	d
 Zd$ddZd%ddZd&ddZd'ddZd(ddZd)ddZd*ddZdd Zdd Zdd Zd d! Zd+d"d#ZdS ),z
Various helper utilities.
    )bases)context)managernodesraw_buildingscoped_nodesutil)BUILTINS)AstroidTypeErrorAttributeInferenceErrorInferenceErrorMroError_NonDeducibleTypeHierarchyc             C   s   t | }||_|S )N)r   Zbuild_classparent)cls_namebuiltinsproxy r   3/tmp/pip-unpacked-wheel-mm06h1t3/astroid/helpers.py_build_proxy_class"   s    
r   c             C   sR   t | tjr&|  jtkr d}qHd}n"t | tjr8d}nt | tjrHd}t	||S )NZbuiltin_function_or_methodfunctionmethod)

isinstancer   Lambdarootnamer	   r   BoundMethodUnboundMethodr   )r   r   r   r   r   r   _function_type(   s    r   Nc             c   s   t  }|j}|pt }x| j|dD ]}t|tjrh|j	rV|j
|d}|rV|V  q(|dd V  q(t|tjtjfrt||V  q(t|tjrtd|V  q(|jV  q(W d S )N)r   typer   module)r   ZAstroidManagerZbuiltins_module
contextmodInferenceContextinferr   r   ClassDefnewstyle	metaclassgetattrr   r   r   r   Moduler   _proxied)noder   Zastroid_managerr   inferredr&   r   r   r   _object_type5   s     r,   c             C   sL   yt t| |}W n tk
r(   tjS X t|dks:|s@tjS t|d S )aU  Obtain the type of the given node

    This is used to implement the ``type`` builtin, which means that it's
    used for inferring type calls, as well as used in a couple of other places
    in the inference.
    The node will be inferred first, so this function can support all
    sorts of objects, as long as they support inference.
       r   )setr,   r   r   Uninferablelenlist)r*   r   typesr   r   r   object_typeJ   s    
r3   c             C   sz   t |ttfs|f}n|}| tjkr*tjS dd |D }x<|D ]4}|tjkrTtdx|  D ]}||kr^dS q^W q>W dS )Nc             S   s"   g | ]}t |tjs|ntjqS r   )r   r   Instancer   r/   ).0itemr   r   r   
<listcomp>h   s   z,_object_type_is_subclass.<locals>.<listcomp>z&arg 2 must be a type or tuple of typesTF)r   tupler1   r   r/   r
   mro)obj_typeclass_or_seqr   Z	class_seqklassZobj_subclassr   r   r   _object_type_is_subclass]   s    


r=   c             C   s(   t | |}|tjkrtjS t|||dS )zCheck if a node 'isinstance' any node in class_or_seq

    :param node: A given node
    :param class_or_seq: Union[nodes.NodeNG, Sequence[nodes.NodeNG]]
    :rtype: bool

    :raises AstroidTypeError: if the given ``classes_or_seq`` are not types
    )r   )r3   r   r/   r=   )r*   r;   r   r:   r   r   r   object_isinstancex   s    	

r>   c             C   s(   t | tjst|  dt| ||dS )ar  Check if a type is a subclass of any node in class_or_seq

    :param node: A given node
    :param class_or_seq: Union[Nodes.NodeNG, Sequence[nodes.NodeNG]]
    :rtype: bool

    :raises AstroidTypeError: if the given ``classes_or_seq`` are not types
    :raises AstroidError: if the type of the given node cannot be inferred
        or its type's mro doesn't work
    z needs to be a ClassDef node)r   )r   r   r$   	TypeErrorr=   )r*   r;   r   r   r   r   object_issubclass   s    r@   c          	   C   sj   y| j |d}t|}W n ttfk
r0   dS X yt| dS  tk
rR   dS  tk
rd   |S X dS )zReturn the inferred value for the given node.

    Return None if inference failed or if there is some ambiguity (more than
    one node has been inferred).
    )r   N)r#   nextr   StopIteration)r*   r   Zinferitvaluer   r   r   
safe_infer   s    rD   c             C   sl   y| j S  tk
r   Y nX xD| jD ]:}t||d}t|tjrT|| ksTt||ds$d| _ dS q$W d| _ dS )z=Return true if all base classes of a class could be inferred.)r   FT)Z_all_bases_knownAttributeErrorr   rD   r   r   r$   has_known_bases)r<   r   baseresultr   r   r   rF      s    rF   c          
   C   sl   t tt| |fstt | j|jgs*dS y| | d d kS  tk
rf } z
t|W d d }~X Y nX d S )NF)allmaprF   r   r%   r9   r   )type1type2er   r   r   _type_check   s    rO   c             C   s   t || dS )z)Check if *type1* is a subtype of *type2*.)rL   rM   )rO   )rL   rM   r   r   r   
is_subtype   s    rP   c             C   s
   t | |S )z+Check if *type2* is a supertype of *type1*.)rO   )rL   rM   r   r   r   is_supertype   s    rQ   c             C   s   t  }t j| gd|_y^xX| jd|dD ]F}t|tjs<q*x2|j| |dD ] }t|t	j
rLt|jtrL|S qLW q*W W n tk
r   Y nX dS )zGet the value as an index for the given instance.

    If an instance provides an __index__ method, then it can
    be used in some scenarios where an integer is expected,
    for instance when multiplying or subscripting a list.
    )args	__index__)r   N)r!   r"   ZCallContextZcallcontextigetattrr   r   r   infer_call_resultr   ConstrC   intr   )r*   r   r+   rH   r   r   r   class_instance_as_index   s    rX   c          
   C   s  ddl m} t| |d}|  }t|tjrf|jdkrf|dk	rf|j|j	krfd
| j|  j}t||dksx|tjkrt| dt|tjrt|jttfrt|jS t|tjtjtj|frt|jS t|tjrt|jS t||d}|st| dyt|jd|d}W nj t k
rB } zt!t||W dd}~X Y n: t"k
rz } zt!d|#  d	|W dd}~X Y nX |$| |}	|	tjkrt| |d
t|	d}
t|
tjr|
# dkr|
jS |
dkst|
t%j&r|
'drdS t!d|
 ddS )a  Infer length of given node object

    :param Union[nodes.ClassDef, nodes.Instance] node:
    :param node: Node to infer length of

    :raises AstroidTypeError: If an invalid node is returned
        from __len__ method or no __len__ method exists
    :raises InferenceError: If the given node cannot be inferred
        or if multiple nodes are inferred or if the code executed in python
        would result in a infinite recursive check for length
    :rtype int: Integer length of node
    r   )	FrozenSet)r   __len__NzNSelf referential __len__ function will cause a RecursionError on line {} of {})r*   zobject of type 'z' has no len())r*   r   zbuiltins.int'z,' object cannot be interpreted as an integer)(Zastroid.objectsrY   rD   framer   r   ZFunctionDefr   r)   r   formatlinenor   filer   r   r/   r   rV   rC   bytesstrr0   ListSetTupleZeltsDictitemsr3   rA   rT   rB   r
   r   ZpytyperU   r   r4   Zis_subtype_of)r*   r   rY   Zinferred_nodeZ
node_framemessageZ	node_typeZlen_callrN   r+   Zresult_of_lenr   r   r   
object_len   sV    







rh   )N)N)N)N)N)N)N)N) __doc__Zastroidr   r   r!   r   r   r   r   r   Zastroid.constr	   Zastroid.exceptionsr
   r   r   r   r   r   r   r,   r3   r=   r>   r@   rD   rF   rO   rP   rQ   rX   rh   r   r   r   r   <module>   s&   	






