B
    a8                 @   s   d Z ddlZddlZddlmZ ddlmZmZ ddlm	Z	 ddl
mZmZmZmZmZmZmZ ddlmZ dZd	d
 ZG dd dZdS )zastroid manager: avoid multiple astroid build of a same module when
possible by providing a class responsible to get astroid representation
from various source and using a cache of built modules)
    N)ClassVar)AstroidBuildingErrorAstroidImportError)spec)NoSourceFilefile_info_from_modpathget_source_fileis_python_sourceis_standard_moduleload_module_from_namemodpath_from_file)TransformVisitor)z.zipz.eggz.whlc             C   s"   yt | S  tk
r   dS X d S )Nz???)repr	Exception)obj r   3/tmp/pip-unpacked-wheel-mm06h1t3/astroid/manager.py	safe_repr2   s    r   c               @   s   e Zd ZU dZdZi ZdZee e	d< dd Z
edd Zed	d
 Zedd Zdd Zd1ddZd2ddZdd Zdd Zdd Zd3ddZdd  Zd!d" Zd4d#d$Zd5d%d&Zd6d'd(Zd)d* Zd+d, Zd-d. Zd/d0 ZdS )7AstroidManagerz_Responsible to build astroid from files or modules.

    Use the Borg (singleton) pattern.
    zastroid loaderd   max_inferable_valuesc             C   s@   t j| _| js<i | _i | _g | _d| _d| _t | _	t
 | _d S )NF)r   brain__dict__astroid_cache_mod_file_cache_failed_import_hooksalways_load_extensionsZoptimize_astsetextension_package_whitelistr   
_transform)selfr   r   r   __init__C   s    zAstroidManager.__init__c             C   s   | j jS )N)r   register_transform)r    r   r   r   r"   O   s    z!AstroidManager.register_transformc             C   s   | j jS )N)r   unregister_transform)r    r   r   r   r#   T   s    z#AstroidManager.unregister_transformc             C   s
   | j d S )Nbuiltins)r   )r    r   r   r   builtins_moduleX   s    zAstroidManager.builtins_modulec             C   s   | j |S )z8Visit the transforms and apply them to the given *node*.)r   visit)r    noder   r   r   visit_transforms\   s    zAstroidManager.visit_transformsNTFc             C   s   yt |dd}d}W n tk
r(   Y nX |dkr^ydt|}W n tk
r\   |}Y nX || jkr| j| j|kr| j| S |rddlm} || 	||S |r|r| 
|S td|ddS )	z.given a module name, return the astroid objectT)Zinclude_no_extN.r   )AstroidBuilderz"Unable to build an AST for {path}.)path)r   r   joinr   ImportErrorr   fileastroid.builderr*   Z
file_buildast_from_module_namer   )r    filepathmodnamefallbacksourcer*   r   r   r   ast_from_file`   s&    



zAstroidManager.ast_from_file c             C   s   ddl m} || |||S )zKGiven some source code as a string, return its corresponding astroid objectr   )r*   )r/   r*   string_build)r    datar2   r1   r*   r   r   r   ast_from_stringz   s    zAstroidManager.ast_from_stringc             C   s   ddl m} || d|S )Nr   )r*   r6   )r/   r*   r7   )r    r2   r*   r   r   r   _build_stub_module   s    z!AstroidManager._build_stub_modulec             C   s   ddl m} |||S )Nr   )build_namespace_package_module)r/   r;   )r    r2   r+   r;   r   r   r   _build_namespace_module   s    z&AstroidManager._build_namespace_modulec                sF   j r
dS t|rdS |d t fddtdt d D S )NTr)   c             3   s&   | ]}d   d| jkV  qdS )r)   N)r,   r   ).0x)partsr    r   r   	<genexpr>   s   z5AstroidManager._can_load_extension.<locals>.<genexpr>   )r   r
   splitanyrangelen)r    r2   r   )r?   r    r   _can_load_extension   s    
z"AstroidManager._can_load_extensionc             C   s   || j kr| j | S |dkr&| |S |rDt }ttj| zy@| ||}|jt	j
jkr| |j}|dk	r~|S n|jt	j
jt	j
jfkr|jt	j
jkr| |s| |S yt|}W n4 tk
r } ztd||jd|W dd}~X Y nX | ||S |jt	j
jkr*td||jdn8|jt	j
jkrH| ||jS |jt	j
jkrb| |S |jdkrztd|d| j|j|dd	S  tk
r } z:x0| jD ]&}y||S  tk
r   Y nX qW |W dd}~X Y nX W d|rt| X dS )
z.given a module name, return the astroid object__main__Nz&Loading {modname} failed with:
{error})r2   r+   z)Unable to load compiled module {modname}.z'Can't find a file for module {modname}.)r2   F)r3   )r   r:   osgetcwdchdirr+   dirnamefile_from_module_nametyper   
ModuleTypeZPY_ZIPMODULEzip_import_datalocationZ	C_BUILTINC_EXTENSIONrF   r   r   r   ast_from_modulePY_COMPILEDZPY_NAMESPACEr<   submodule_search_locationsZ	PY_FROZENr5   r   r   )r    r2   context_fileZold_cwdZ
found_specmoduleehookr   r   r   r0      sf    







z#AstroidManager.ast_from_module_namec       
   	   C   s   t d krd S ddlm} || }xtD ]}y||tjj d\}}W n tk
r\   w&Y nX yHt 	|| }|
tjjd}||r|d }|||||}	|	S  tk
r   w&Y q&X q&W d S )Nr   )r*   rA   r)   z	.__init__)	zipimportr/   r*   ZIP_IMPORT_EXTSrsplitrH   r+   sep
ValueErrorzipimporterreplace
is_packager7   
get_sourcer   )
r    r1   r*   builderextZeggpathresourceimporterZzmodnamerV   r   r   r   rO      s(    

zAstroidManager.zip_import_datac             C   s   y| j ||f }W np tk
r   yt|d|d}W n6 tk
rn } ztd||d d}W d d }~X Y nX || j ||f< Y nX t|tr|d |S )Nr)   )rU   z6Failed to import module {modname} with error:
{error}.)r2   error)	r   KeyErrorr   rB   r-   r   with_traceback
isinstancer   )r    r2   ZcontextfilevaluerW   r   r   r   rL      s     

z$AstroidManager.file_from_module_namec             C   sn   |p|j }|| jkr| j| S y|j}t|r:| ||S W n tk
rP   Y nX ddlm} || ||S )z3given an imported module, return the astroid objectr   )r*   )	__name__r   __file__r	   r5   AttributeErrorr/   r*   Zmodule_build)r    rV   r2   r1   r*   r   r   r   rR     s    


zAstroidManager.ast_from_modulec          
   C   sf   |dkrLy
|j }W n8 tk
rJ } ztd|t||d|W dd}~X Y nX | |}||jd S )zget astroid for the given classNz,Unable to get module for class {class_name}.)cls
class_reprr2   r   )
__module__rm   r   r   r0   getattrrk   )r    klassr2   exc
modastroidr   r   r   ast_from_class  s    

zAstroidManager.ast_from_classc       	   
   c   sh  t |drt|ts|j}n|}y
|j}W nj tk
r` } ztd|t|d|W dd}~X Y n6 tk
r } zt	d|t|d|W dd}~X Y nX y
|j
}W nl tk
r } ztd|t|d|W dd}~X Y n8 tk
r } zt	d|t|d|W dd}~X Y nX | |}||krBx@|||D ]}|V  q0W n"x |||D ]}| V  qPW dS )z!infer astroid for the given class	__class__z&Unable to get module for {class_repr}.)rn   ro   NzBUnexpected error while retrieving module for {class_repr}:
{error}z%Unable to get name for {class_repr}:
z@Unexpected error while retrieving name for {class_repr}:
{error})hasattrri   rM   rv   rp   rm   r   r   r   r   rk   r0   ZigetattrZinstantiate_class)	r    r   contextrr   r2   rs   namert   inferredr   r   r   infer_ast_from_something,  sJ    







z'AstroidManager.infer_ast_from_somethingc             C   s   | j | dS )a}  Registers a hook to resolve imports that cannot be found otherwise.

        `hook` must be a function that accepts a single argument `modname` which
        contains the name of the module or package that could not be imported.
        If `hook` can resolve the import, must return a node of type `astroid.Module`,
        otherwise, it must raise `AstroidBuildingError`.
        N)r   append)r    rX   r   r   r   register_failed_import_hookX  s    z*AstroidManager.register_failed_import_hookc             C   s   | j |j| dS )z<Cache a module if no module with the same name is known yet.N)r   
setdefaultry   )r    rV   r   r   r   cache_moduleb  s    zAstroidManager.cache_modulec             C   s   ddl m} |  dS )zBootstrap the required AST modules needed for the manager to work

        The bootstrap usually involves building the AST for the builtins
        module, which is required by the rest of astroid to work correctly.
        r   )raw_buildingN)Zastroidr   Z_astroid_bootstrapping)r    r   r   r   r   	bootstrapf  s    zAstroidManager.bootstrapc             C   s   | j   |   dS )z@Clear the underlying cache. Also bootstraps the builtins module.N)r   clearr   )r    r   r   r   clear_cachep  s    
zAstroidManager.clear_cache)NTF)r6   N)N)N)N)N)rk   rp   __qualname____doc__ry   r   r   r   int__annotations__r!   propertyr"   r#   r%   r(   r5   r9   r:   r<   rF   r0   rO   rL   rR   ru   r{   r}   r   r   r   r   r   r   r   r   9   s0   



B


,

r   )r   rH   rY   typingr   Zastroid.exceptionsr   r   Zastroid.interpreter._importr   Zastroid.modutilsr   r   r   r	   r
   r   r   Zastroid.transformsr   rZ   r   r   r   r   r   r   <module>   s   $	