B
    a%W                 @   sD  d Z ddlZddlZddlZddl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mZ ejdrzdZdZnd	Zd
Zy(edejdedejdeddhZW n e	k
r   e ZY nX ejdkrLeejejd yeejejd W nH ek
rJ   yeejejd W n ek
rD   Y nX Y nX e dkreedejd ejejdZee yeejejd W n ek
r   Y nX [ejdkr y
ejZW n ek
r   ejZY nX dd Z ee d ej!dkr ee d e edhZ"e dkZ#e$%ej&dZ'G dd de(Z)dd Z*dd Z+e#fdd Z,d!d" Z-i Z.d#d$ Z/d%d& Z0d'd( Z1e2d)d*d+Z3d,d- Z4d.d/ Z5dOd0d1Z6dPd2d3Z7dQd4d5Z8dRd6d7Z9dSd8d9Z:dTd;d<Z;dUd=d>Z<d?d@ Z=dVdAdBZ>dCdD Z?dWdEdFZ@dGdH ZAdIdJ ZBdKdL ZCdMdN ZDdS )XaV  Python modules manipulation utility functions.

:type PY_SOURCE_EXTS: tuple(str)
:var PY_SOURCE_EXTS: list of possible python source file extension

:type STD_LIB_DIRS: set of str
:var STD_LIB_DIRS: directories where standard modules are located

:type BUILTIN_MODULES: dict
:var BUILTIN_MODULES: dictionary with builtin module names has key
    N)DistutilsPlatformError)get_python_lib)specutilwin)pypyw)dllZpyd)r   )soT)standard_libprefix)r   ntZdllsPyPyZlib_pypyposixc             C   s"   dt jd d  }tjt| |S )Nzpython%d.%d   )sysversion_infoospathjoinr   )r   Zbase_python r   4/tmp/pip-unpacked-wheel-mm06h1t3/astroid/modutils.py_posix_path   s    r   libl        Zlib64Jythonc               @   s   e Zd ZdZdS )NoSourceFilezaexception raised when we are not able to get a python
    source file for a precompiled file
    N)__name__
__module____qualname____doc__r   r   r   r   r      s   r   c             C   s   t jt j| S )N)r   r   normcaseabspath)r   r   r   r   _normalize_path   s    r"   c             C   s   t jt j| S )N)r   r   realpath
expanduser)r   r   r   r   _canonicalize_path   s    r%   c             C   s(   |s| S |  d\}}}|r$|d S | S )Nz	$py.classz.py)	partition)filenameZ	is_jythonheadZhas_pyclass_r   r   r   _path_from_filename   s    r*   c             C   s8   x2| D ]*}||kr| | q||kr| | qW dS )z`remove files/directories in the black list

    dirnames/filenames are usually from os.walk
    N)remove)	blacklistdirnames	filenamesZnorecursr   r   r   _handle_blacklist   s
    
r/   c             C   s>   yt |  S  tk
r8   | s$t| S t|  }t | < |S X dS )zabspath with cachingN)_NORM_PATH_CACHEKeyErrorr"   )r   resultr   r   r   _cache_normalize_path   s    r3   c             C   s*   y
t j|  S  tk
r   Y nX t| S )zLoad a Python module from its name.

    :type dotted_name: str
    :param dotted_name: python name of a module or package

    :raise ImportError: if the module or package is not found

    :rtype: module
    :return: the loaded module
    )r   modulesr1   	importlibimport_module)dotted_namer   r   r   load_module_from_name   s
    
r8   c             C   s   t d| S )a  Load a python module from its split name.

    :type parts: list(str) or tuple(str)
    :param parts:
      python name of a module or package split on '.'

    :raise ImportError: if the module or package is not found

    :rtype: module
    :return: the loaded module
    .)r8   r   )partsr   r   r   load_module_from_modpath   s    r;   )filepathc             C   s   t | }t|S )zLoad a Python module from it's path.

    :type filepath: str
    :param filepath: path to the python module or package

    :raise ImportError: if the module or package is not found

    :rtype: module
    :return: the loaded module
    )modpath_from_filer;   )r<   modpathr   r   r   load_module_from_file   s    r?   c             C   sN   g }xD|D ]<}| | tj| |} t| s
td|}|s
dS q
W dS )z2check there are some __init__.py all along the wayr9   FT)appendr   r   r   	_has_initr   is_namespace)r   Zmod_pathr>   partZold_namespacer   r   r   check_modpath_has_init   s    

rD   c             C   s   d}t j|}t j| }t j||r2|}t j| }t j||rT|}|rt j|d }|t|d }dd |t j	D S dS )a=  Extracts the relative mod path of the file to import from

    Check if a file is within the passed in path and if so, returns the
    relative mod path from the one passed in.

    If the filename is no in path_to_check, returns None

    Note this function will look for both abs and realpath of the file,
    this allows to find the relative base path even if the file is a
    symlink of a file in the passed in path

    Examples:
        _get_relative_base_path("/a/b/c/d.py", "/a/b") ->  ["c","d"]
        _get_relative_base_path("/a/b/c/d.py", "/dev") ->  None
    Nr   c             S   s   g | ]}|r|qS r   r   ).0pkgr   r   r   
<listcomp>#  s    z+_get_relative_base_path.<locals>.<listcomp>)
r   r   r    r!   
startswithr#   splitextlensplitsep)r'   Zpath_to_checkZimportable_pathZabs_filenameZreal_filename	base_pathZrelative_base_pathr   r   r   _get_relative_base_path  s    rN   c             C   s   t jt| } xXt|pg tttjtjD ]8}t	|}|s@q.t
| |}|sPq.|||d d r.|S q.W td| dtjd S )Nz"Unable to find module for {} in {}z, 
)r   r   r$   r*   	itertoolschainmapr%   r   r3   rN   ImportErrorformatr   )r'   r   Zis_package_cbpathnamer>   r   r   r   modpath_from_file_with_callback(  s    
rV   c             C   s   t | |tS )a)  Get the corresponding split module's name from a filename

    This function will return the name of a module or package split on `.`.

    :type filename: str
    :param filename: file's path for which we want the module's name

    :type Optional[List[str]] path:
      Optional list of path where the module or package should be
      searched (use sys.path if nothing or None is given)

    :raise ImportError:
      if the corresponding module's name has not been found

    :rtype: list(str)
    :return: the corresponding split module's name
    )rV   rD   )r'   r   r   r   r   r=   ;  s    r=   c             C   s   t | ||jS )N)file_info_from_modpathlocation)r>   r   context_filer   r   r   file_from_modpathP  s    rZ   c             C   s   |dk	rt j|}n|}| d dkr`ytdg| dd  ||S  tk
r\   t| ||S X n$| ddgkrtjdt jjtjj	d	S t| ||S )
a  given a mod path (i.e. split module / package name), return the
    corresponding file, giving priority to source file over precompiled
    file if it exists

    :type modpath: list or tuple
    :param modpath:
      split module's name (i.e name of a module or package split
      on '.')
      (this means explicit relative imports that start with dots have
      empty strings in this list!)

    :type path: list or None
    :param path:
      optional list of path where the module or package should be
      searched (use sys.path if nothing or None is given)

    :type context_file: str or None
    :param context_file:
      context file to consider, necessary if the identifier has been
      introduced using a relative import unresolvable in the actual
      context (i.e. modutils)

    :raise ImportError: if there is no such module in the directory

    :rtype: (str or None, import type)
    :return:
      the path to the module's file or None if it's an integrated
      builtin module such as 'sys'
    Nr   xmlZ_xmlplus   r   r   zos.path)namerX   module_type)
r   r   dirname_spec_from_modpathrS   r   
ModuleSpec__file__
ModuleType	PY_SOURCE)r>   r   rY   contextr   r   r   rW   T  s    rW   c          	   C   s  |  drdS | d}|dk	rH|d tkrHt|dkr@t| |d S d}d}|d dkrt|dk	sltdg }d}x$|| dkr|d7 }tj|}qvW xrt	|t|D ]`}yt
|||d  ||d	 W q tk
r   |tdt|d k r d|d| S X qW | S )
a  given a dotted name return the module part of the name :

    >>> get_module_part('astroid.as_string.dump')
    'astroid.as_string'

    :type dotted_name: str
    :param dotted_name: full name of the identifier we are interested in

    :type context_file: str or None
    :param context_file:
      context file to consider, necessary if the identifier has been
      introduced using a relative import unresolvable in the actual
      context (i.e. modutils)


    :raise ImportError: if there is no such module in the directory

    :rtype: str or None
    :return:
      the module part of the name or None if we have not been able at
      all to import the given name

    XXX: deprecated, since it doesn't handle package precedence over module
    (see #10066)
    zos.pathr9   Nr   r    z.explicit relative import, but no context_file?r\   )r   rY   )rH   rK   BUILTIN_MODULESrJ   rS   AssertionErrorr   r   r_   rangerZ   maxr   )r7   rY   r:   r   Zstartiir   r   r   get_module_part  s6    


rl   Fc       	      C   s   g }xvt | D ]h\}}}||kr$qt||| |sJd|krJd|dd< qx,|D ]$}t|rPt j||}|| qPW qW |S )aN  given a package directory return a list of all available python
    module's files in the package and its subpackages

    :type src_directory: str
    :param src_directory:
      path of the directory corresponding to the package

    :type blacklist: list or tuple
    :param blacklist: iterable
      list of files or directories to ignore.

    :type list_all: bool
    :param list_all:
        get files from all paths, including ones without __init__.py

    :rtype: list
    :return:
      the list of all available python module's files in the package and
      its subpackages
    z__init__.pyr   N)r   walkr/   _is_python_filer   r   r@   )	Zsrc_directoryr,   Zlist_allfiles	directoryr-   r.   r'   srcr   r   r   get_module_files  s    
rr   c             C   sp   t jt| } t j| \}}x*tD ]"}| d| }t j|r&|S q&W |rd|sdt j|rd|S t| dS )a  given a python module's file name return the matching source file
    name (the filename will be returned identically if it's already an
    absolute path to a python source file...)

    :type filename: str
    :param filename: python module's file name


    :raise NoSourceFile: if no source file exists on the file system

    :rtype: str
    :return: the absolute path of the source file if it exists
    r9   N)r   r   r!   r*   rI   PY_SOURCE_EXTSexistsr   )r'   Zinclude_no_extbaseZorig_extextsource_pathr   r   r   get_source_file  s    
rx   c             C   s   t j| d dd tkS )zN
    rtype: bool
    return: True if the filename is a python source file
    r\   N)r   r   rI   rs   )r'   r   r   r   is_python_source  s    ry   c             C   s   |  dd } yt| g}W n tk
r0   dS X |dkrFt|  S t|}xtD ]}|t|rTdS qTW |dkrzt	}x|D ]}|t|rdS qW dS )a  try to guess if a module is a standard python module (by default,
    see `std_path` parameter's description)

    :type modname: str
    :param modname: name of the module we are interested in

    :type std_path: list(str) or tuple(str)
    :param std_path: list of path considered has standard


    :rtype: bool
    :return:
      true if the module:
      - is located on the path listed in one of the directory in `std_path`
      - is a built-in module
    r9   r   FNT)
rK   rZ   rS   r   rB   r"   EXT_LIB_DIRSrH   r3   STD_LIB_DIRS)modnameZstd_pathr'   r   r   r   r   is_standard_module	  s"    

r}   c             C   sJ   t j|st j|}|tjkr&dS ttjj	| j
dddd |gS )av  return true if the given module name is relative to the given
    file name

    :type modname: str
    :param modname: name of the module we are interested in

    :type from_file: str
    :param from_file:
      path of the module from which modname has been imported

    :rtype: bool
    :return:
      true if the module has been imported relatively to `from_file`
    Fr9   r\   )maxsplitr   )r   r   isdirr_   r   boolr5   	machinery
PathFinder	find_specrK   )r|   	from_filer   r   r   is_relative2  s    
r   c             C   s   | st d}|dk	rVyt| |g}|j}W qb tk
rR   t| |}|j}Y qbX nt| |}|jtjjkryt|j}|j	|tjj
dS  tk
r   |j	|dS X nD|jtjjkr|j	ddS |jtjjkrt|j}|j	|tjj
dS |S )zgiven a mod path (i.e. split module / package name), return the
    corresponding spec

    this function is used internally, see `file_from_modpath`'s
    documentation for more information
    N)rX   type)rX   )rh   r   r   rX   rS   r   rc   PY_COMPILEDrx   _replacerd   r   Z	C_BUILTINPKG_DIRECTORYrA   )r>   r   re   rX   Z
found_specr   r   r   r`   O  s.    


r`   c             C   s
   |  dS )zkreturn true if the given filename should be considered as a python file

    .pyc and .pyo are ignored
    )z.pyz.soz.pydz.pyw)endswith)r'   r   r   r   rn   r  s    rn   c             C   sD   t j| d}x0td D ]$}t j|d | r|d | S qW dS )z\if the given directory has a valid __init__ file, return its path,
    else return None
    __init__)ZpycZpyor9   N)r   r   r   rs   rt   )rp   Zmod_or_packrv   r   r   r   rA   z  s
    rA   c             C   s   | j tjjkS )N)r   r   rc   ZPY_NAMESPACE)specobjr   r   r   rB     s    rB   c             C   s   | j tjjkS )N)r   r   rc   r   )r   r   r   r   is_directory  s    r   )NN)N)NN)NN)N)F)F)N)NN)Er   r5   Zimportlib.machineryimportlib.utilrP   r   platformr   distutils.errorsr   distutils.sysconfigr   Zastroid.interpreter._importr   r   rH   rs   ZPY_COMPILED_EXTSr   exec_prefixr{   setr]   addr   r   real_prefixAttributeErrorbase_exec_prefixpython_implementationbase_prefix_rootr   maxsizerz   Z	IS_JYTHONdictfromkeysbuiltin_module_namesrg   	Exceptionr   r"   r%   r*   r/   r0   r3   r8   r;   strr?   rD   rN   rV   r=   rZ   rW   rl   rr   rx   ry   r}   r   r`   rn   rA   rB   r   r   r   r   r   <module>%   s   

	"



2
=
%

)
#