3
%^#                 @   s   d 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 ej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.
    N)bases)context)
exceptions)manager)nodes)raw_building)scoped_nodes)utilc             C   s   t j| }||_|S )N)r   Zbuild_classparent)cls_namebuiltinsproxy r   2/tmp/pip-build-8app2_gc/astroid/astroid/helpers.py_build_proxy_class   s    
r   c             C   sR   t | tjr&| j 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nameBUILTINSr   BoundMethodUnboundMethodr   )r   r   r   r   r   r   _function_type"   s    r   c             c   s   t j }|j}|ptj }x| j|dD ]}t|tjrh|j	rV|j
|d}|rV|V  q(|j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   Z_proxied)noder   Zastroid_managerr   inferredr"   r   r   r   _object_type/   s     r'   c             C   sP   yt t| |}W n tjk
r*   tjS X t|dks>| rDt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   InferenceErrorr	   Uninferablelenlist)r%   r   typesr   r   r   object_typeD   s    
r/   c             C   s|   t |ttfs|f}n|}| tjkr*tjS dd |D }x>|D ]6}|tjkrVtjdx| j 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   ZInstancer	   r+   ).0itemr   r   r   
<listcomp>b   s   z,_object_type_is_subclass.<locals>.<listcomp>z&arg 2 must be a type or tuple of typesTF)r   tupler-   r	   r+   r   AstroidTypeErrormro)obj_typeclass_or_seqr   Z	class_seqklassZobj_subclassr   r   r   _object_type_is_subclassW   s    



r9   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   )r/   r	   r+   r9   )r%   r7   r   r6   r   r   r   object_isinstancer   s    	

r:   c             C   s*   t | tjstdj| 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"{node} needs to be a ClassDef node)r%   )r   )r   r   r    	TypeErrorformatr9   )r%   r7   r   r   r   r   object_issubclass   s    r=   c             C   sj   y| j |d}t|}W n tjk
r.   dS X yt| dS  tj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   r*   StopIteration)r%   r   Zinferitvaluer   r   r   
safe_infer   s    rA   c             C   sp   y| j S  tk
r   Y nX xH| jD ]>}t||d}t|tj sX|| ksXt||d r$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   rA   r   r   r    has_known_bases)r8   r   baseresultr   r   r   rC      s    rC   c             C   sb   t tt| |fstjt | j|jgs,dS y| |j d d kS  tjk
r\   tjY nX d S )NFr(   )allmaprC   r   Z_NonDeducibleTypeHierarchyr!   r5   ZMroError)type1type2r   r   r   _type_check   s    rK   c             C   s   t || dS )z)Check if *type1* is a subtype of *type2*.)rI   rJ   )rK   )rI   rJ   r   r   r   
is_subtype   s    rL   c             C   s
   t | |S )z+Check if *type2* is a supertype of *type1*.)rK   )rI   rJ   r   r   r   is_supertype   s    rM   c             C   s   t j }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j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   Constr@   intr   r*   )r%   r   r&   rE   r   r   r   class_instance_as_index   s    rT   c             C   s(  ddl m} t| |d}|dks*|tjkr6tj| dt|tj	r\t|j
ttfr\t|j
S t|tjtjtj|fr~t|jS t|tjrt|jS y"t||d}t|jd|d}W n* tjk
r   tjdj|j Y nX t|j| |}t|tj	r|j dkr|j
S tjd	j|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
    :rtype int: Integer length of node
    r   )	FrozenSet)r   N)r%   __len__z object of type '{}' has no len()zbuiltins.intz/'{}' object cannot be interpreted as an integer)Zastroid.objectsrU   rA   r	   r+   r   r*   r   r   rR   r@   bytesstrr,   ListSetTupleeltsDictitemsr/   r>   rP   ZAttributeInferenceErrorr4   r<   ZpytyperQ   )r%   r   rU   Zinferred_nodeZ	node_typeZlen_callZresult_of_lenr   r   r   
object_len   s.    


r_   )N)N)N)N)N)N)N)N)__doc__r   Zbuiltins_modZastroidr   r   r   r   r   r   r   r   r	   __name__r   r   r   r'   r/   r9   r:   r=   rA   rC   rK   rL   rM   rT   r_   r   r   r   r   <module>   s0   






