a
    E
ad4                     @   s  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Zd dl	m
Z
 ddlmZ eddZeddZG d	d
 d
eZG dd dZG dd deZG dd deZG dd deZG dd deZeeeefZdd Ze
 dd Zd!ddZdd Zdd Zd"dd ZdS )#    N)	lru_cache   )util
ModuleTypezyC_BUILTIN C_EXTENSION PKG_DIRECTORY PY_CODERESOURCE PY_COMPILED PY_FROZEN PY_RESOURCE PY_SOURCE PY_ZIPMODULE PY_NAMESPACE_ModuleSpecz4name type location origin submodule_search_locationsc                   @   s   e Zd ZdZdddZdS )
ModuleSpeczDefines a class similar to PEP 420's ModuleSpec

    A module spec defines a name of a module, its type, location
    and where submodules can be found, if the module is a package.
    Nc                 C   s   t j| |||||dS )N)nametypelocationoriginsubmodule_search_locations)r   __new__)clsr   module_typer
   r   r    r   ?lib/python3.9/site-packages/astroid/interpreter/_import/spec.pyr   1   s    zModuleSpec.__new__)NNN)__name__
__module____qualname____doc__r   r   r   r   r   r   *   s
   
   r   c                   @   s0   e Zd ZdZd	ddZejdd Zdd ZdS )
Finderz@A finder is a class which knows how to find a particular module.Nc                 C   s   |pt j| _d S N)syspath_pathselfr   r   r   r   __init__F   s    zFinder.__init__c                 C   s   dS )a  Find the given module

        Each finder is responsible for each protocol of finding, as long as
        they all return a ModuleSpec.

        :param str modname: The module which needs to be searched.
        :param list module_parts: It should be a list of strings,
                                  where each part contributes to the module's
                                  namespace.
        :param list processed: What parts from the module parts were processed
                               so far.
        :param list submodule_path: A list of paths where the module
                                    can be looked into.
        :returns: A ModuleSpec, describing how and where the module was found,
                  None, otherwise.
        Nr   r   modnamemodule_parts	processedsubmodule_pathr   r   r   find_moduleI   s    zFinder.find_modulec                 C   s   dS )z7Get a list of extra paths where this finder can search.Nr   r   specr!   r   r   r   contribute_to_path\   s    zFinder.contribute_to_path)N)	r   r   r   r   r   abcabstractmethodr#   r&   r   r   r   r   r   C   s
   

r   c                   @   sV   e Zd ZdZdd ejjD dd ejjD  dd ejjD  Z	dd Z
dd	 Zd
S )ImportlibFinderz'A finder based on the importlib module.c                 C   s   g | ]}|t jfqS r   )r   C_EXTENSION.0sr   r   r   
<listcomp>d       zImportlibFinder.<listcomp>c                 C   s   g | ]}|t jfqS r   )r   	PY_SOURCEr+   r   r   r   r.   e   r/   c                 C   s   g | ]}|t jfqS r   )r   PY_COMPILEDr+   r   r   r   r.   f   r/   c                 C   sT  t |tstdt| |d ur.t|}nnzTtj|}|r|jtj	j
u r`t|d tjdW S |jtj	ju rt|d tjdW S W n ty   Y n0 tj}|D ]}tj||}dtj	jd fD ]>}d| }	tj||	}
tj|
rt||tjd    S qtjD ]D\}}|| }tj||}
tj|
rt||
|d    S qqd S )Nz'modname' must be a str, not )r   r
   r   z.pyr   r   )
isinstancestr	TypeErrorr	   list	importlibr   	find_specloader	machineryBuiltinImporterr   r   Z	C_BUILTINFrozenImporterZ	PY_FROZEN
ValueErrorr   r   osjoinBYTECODE_SUFFIXESisfilePKG_DIRECTORYr)   	_SUFFIXES)r   r   r    r!   r"   r%   entryZpackage_directorysuffixZpackage_file_nameZ	file_pathtype_	file_namer   r   r   r#   i   sR    

zImportlibFinder.find_modulec                    s\   |j d u rd S t|j r. fddtjD }n*|jdkrP|j tjv rPttj}n|j g}|S )Nc                    s<   g | ]4}t jt jj|g R  rt jj|g R  qS r   )r=   r   isdirr>   )r,   pr!   r   r   r.      s   z6ImportlibFinder.contribute_to_path.<locals>.<listcomp>	distutils)r
   _is_setuptools_namespacer   r   r   rJ   __path__r5   )r   r%   r!   r   r   rI   r   r&      s    


z"ImportlibFinder.contribute_to_pathN)r   r   r   r   r6   r9   EXTENSION_SUFFIXESSOURCE_SUFFIXESr?   rB   r#   r&   r   r   r   r   r)   `   s   -r)   c                   @   s    e Zd ZdZdd Zdd ZdS )ExplicitNamespacePackageFinderzNA finder for the explicit namespace packages, generated through pkg_resources.c                 C   sL   |rd ||g }t|rH|tjv rHtj| j}t|ddtj|dS d S )N. 	namespacer   r
   r   r   r   )	r>   r   is_namespacer   modulesrL   r   r   PY_NAMESPACEr   r   r   r   r#      s    z*ExplicitNamespacePackageFinder.find_modulec                 C   s   |j S r   r   r$   r   r   r   r&      s    z1ExplicitNamespacePackageFinder.contribute_to_pathNr   r   r   r   r#   r&   r   r   r   r   rO      s   rO   c                       s(   e Zd ZdZ fddZdd Z  ZS )	ZipFinderz8Finder that knows how to find a module inside zip files.c                    s   t  | t|| _d S r   )superr   _precache_zipimporters_zipimportersr   	__class__r   r   r      s    zZipFinder.__init__c                 C   s>   zt || j\}}}W n ty*   Y d S 0 t||d||dS )NZeggrS   )_search_zipr\   ImportErrorr   )r   r   r    r!   r"   Z	file_typefilenamer   r   r   r   r#      s    zZipFinder.find_module)r   r   r   r   r   r#   __classcell__r   r   r]   r   rY      s   rY   c                   @   s    e Zd ZdZdd Zdd ZdS )PathSpecFinderz/Finder based on importlib.machinery.PathFinder.c           	      C   s`   t jjj||d}|r\|jdv }|s*|jnd }|r8tjnd }t|j||j|t	|j
pTg d}|S )N)r   )rR   NrS   )r6   r9   
PathFinderr7   r   r   rV   r   r   r5   r   )	r   r   r    r!   r"   r%   Zis_namespace_pkgr
   r   r   r   r   r#      s    
zPathSpecFinder.find_modulec                 C   s   |j tjkr|jS d S r   )r	   r   rV   r   r$   r   r   r   r&      s    z!PathSpecFinder.contribute_to_pathNrX   r   r   r   r   rc      s   rc   c                 C   s   zBt tj| dd}|d}W d    n1 s60    Y  W n tyV   Y d S 0 d|v ofd|v }d|v ovd|v }|p~|S d S )Nz__init__.pyrbi   s   pkgutils   extend_paths   pkg_resourcess   declare_namespace(__name__))openr=   r   r>   readOSError)r
   streamdataextend_pathZdeclare_namespacer   r   r   rK      s    ,rK   c                 C   s   t | }|| |S r   )setdifference_update)leftrightresultr   r   r   _cached_set_diff
  s    
rq   c              	   C   sn   t j}t| pt j}t|}t||}|D ]0}zt|||< W q* tjyX   Y q*Y q*0 q*dd | D S )a  
    For each path that has not been already cached
    in the sys.path_importer_cache, create a new zipimporter
    instance and add it into the cache.
    Return a dict associating all paths, stored in the cache, to corresponding
    zipimporter instances.

    :param path: paths that has to be added into the cache
    :return: association between paths stored in the cache and zipimporter instances
    c                 S   s"   i | ]\}}t |tjr||qS r   )r2   	zipimportzipimporter)r,   keyvaluer   r   r   
<dictcomp>,  s   z*_precache_zipimporters.<locals>.<dictcomp>)	r   path_importer_cachetupler   rq   rr   rs   ZipImportErroritems)r   picZ	req_pathsZcached_pathsZ	new_pathsZ
entry_pathr   r   r   r[     s    
r[   c                 C   s   t | D ]\}}|d ur|| d }|r|tjj| sbtdd| dd  || f tj	tj
|tjj tjj|  |f  S qtdd|  d S )Nr   zNo module named %s in %s/%srP   r   No module named %s)r5   rz   r#   r=   r   sepr>   r`   r   ZPY_ZIPMODULEabspath)modpathr{   filepathimporterfoundr   r   r   r_   3  s     
r_   c                    sV    fddt D }|D ](}|||||}|d u r4q||f  S tdd| d S )Nc                    s   g | ]}| qS r   r   )r,   findersearch_pathr   r   r.   G  r/   z(_find_spec_with_path.<locals>.<listcomp>r|   rP   )_SPEC_FINDERSr#   r`   r>   )r   r   r    r!   r"   Zfindersr   r%   r   r   r   _find_spec_with_pathF  s    r   c           	      C   s   |pt j}| dd } d}| dd }g }| r| d}t|||||pH|\}}|| | rj|||}|jtjkr*|j	|d}q*|S )a  Find a spec for the given module.

    :type modpath: list or tuple
    :param modpath:
      split module's name (i.e name of a module or package split
      on '.'), with leading empty strings for explicit relative import

    :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)

    :rtype: ModuleSpec
    :return: A module spec, which describes how the module was
             found and where.
    Nr   rW   )
r   r   popr   appendr&   r	   r   rA   _replace)	r   r   r   r"   r    r!   r   r   r%   r   r   r   r7   Q  s     


r7   )N)N)r'   collectionsrJ   enumimportlib.machineryr6   r=   r   rr   	functoolsr   rQ   r   Enumr   
namedtupler   r   r   r)   rO   rY   rc   r   rK   rq   r[   r_   r   r7   r   r   r   r   <module>   sD   N

"