
    e@\              	          U d Z ddlm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
Z
ddlZddlZddlZddlmZmZmZ ddlmZmZ ddlmZ ddlmZ ddlmZmZmZ dd	lmZmZ erdd
l
m Z  ndd
l!m Z   ejD                  e#      Z$e
jJ                  jM                  d      rdZ'dZ(ndZ'dZ( ejR                  d       ejR                  d      hZ*e	jV                  dk(  rke*jY                  e	jZ                  j]                  e
j^                  d             	 e*jY                  e	jZ                  j]                  e
j`                  d             ere
jf                  dk  re*jY                   e4 e ejR                  d            jj                  dz               e*jY                   e4 e ejR                  d            jj                  dz               e*jY                   e4 e ejR                  d            jj                  dz               e*jY                   e4 e ejR                  d            jj                  dz               e	jV                  dk(  rS	 e
j`                  Z/de6d<   d?dZ7e*jY                   e7d             e
jp                  dkD  re*jY                   e7d              ejR                  d       ejR                  d      hZ9e:jw                  e
jx                  d       Z= G d! d"e>      Z?d?d#Z@efd@d$ZA	 	 	 	 	 	 	 	 dAd%ZBed?d&       ZCd?d'ZDdBd(ZEdCd)ZFdDd*ZGdEd+ZHdFd,ZI	 	 dG	 	 	 	 	 	 	 dHd-ZJdIdJd.ZK	 	 dG	 	 	 	 	 	 	 dKd/ZL	 	 dG	 	 	 	 	 	 	 dLd0ZMdIdMd1ZN	 dN	 	 	 	 	 	 	 dOd2ZOdNdPd3ZPdQd4ZQdRd5ZRdSd6ZSdIdTd7ZTdUd8ZU	 	 dG	 	 	 	 	 	 	 dVd9ZVdWd:ZWdXd;ZXdYd<ZYdYd=ZZ	 	 	 	 	 	 dZd>Z[y# e1$ rF 	 e*jY                  e	jZ                  j]                  e
jd                  d             n# e1$ r Y nw xY wY w xY w# e1$ r e
j^                  Z/Y w xY w)[aV  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
    )annotationsN)CallableIterableSequence)redirect_stderrredirect_stdout)	lru_cache)Path)	IS_JYTHONIS_PYPY
PY310_PLUS)specutil)stdlib_module_nameswin)pypywpyi)dllpyd)r   r   )sostdlib
platstdlibntdlls)      lib_pypyzlib-python/3posixstrprefixc                x    dt         j                  d d z  }t        j                  j	                  t
        | |      S )Nzpython%d.%d   )sysversion_infoospathjoinr!   )r'   base_pythons     2/usr/lib/python3/dist-packages/astroid/modutils.py_posix_pathr+   c   s0    #c&6&6r&::ww||FD+66    libl        lib64purelibplatlibTc                      e Zd ZdZy)NoSourceFilezbException raised when we are not able to get a python
    source file for a precompiled file.
    N)__name__
__module____qualname____doc__ r,   r*   r2   r2   v   s    r,   r2   c                z    t         j                  j                  t         j                  j                  |             S )zResolve symlinks in path and convert to absolute path.

    Note that environment variables and ~ in the path need to be expanded in
    advance.

    This can be cached by using _cache_normalize_path.
    )r&   r'   normcaserealpathr'   s    r*   _normalize_pathr<   |   s(     77BGG,,T233r,   c                F    |s| S | j                  d      \  }}}|r|dz   S | S )Nz	$py.class.py)	partition)filename	is_jythonheadhas_pyclass_s        r*   _path_from_filenamerE      s3    #--k:D+qe|Or,   c                j    | D ].  }||v r|j                  |       ||v s|j                  |       0 y)zaRemove files/directories in the black list.

    dirnames/filenames are usually from os.walk
    N)remove)	blacklistdirnames	filenamesnorecurss       r*   _handle_blacklistrL      s=      'xOOH%"X&	'r,   c                    t        |       S N)r<   r;   s    r*   _cache_normalize_path_rO      s    4  r,   c                2    | st        |       S t        |       S )zNormalize path with caching.)r<   rO   r;   s    r*   _cache_normalize_pathrQ      s    
 t$$!$''r,   c                   	 t         j                  |    S # t        $ r Y nw xY wt        t	        j
                               5 }t        t	        j
                               5 }t        j                  |       }ddd       n# 1 sw Y   nxY wddd       n# 1 sw Y   nxY wj                         }|rt        j                  d| |       j                         }|rt        j                  d| |       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
    Nz&Captured stderr while importing %s:
%sz&Captured stdout while importing %s:
%s)r$   modulesKeyErrorr   ioStringIOr   	importlibimport_modulegetvalueloggererrorinfo)dotted_namestderrstdoutmodulestderr_valuestdout_values         r*   load_module_from_namerc      s    {{;'' 
 
	' 66?
4 6	((56 6 6 6 6 6
 ??$L5{L	
 ??$L5{L	
 Ms0    	!!BA>5	B>B	BBc                6    t        dj                  |             S )zLoad a python module from its split name.

    :param parts:
      python name of a module or package split on '.'

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

    :return: the loaded module
    .)rc   r(   )partss    r*   load_module_from_modpathrg      s     !%11r,   c                .    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_filerg   )filepathmodpaths     r*   load_module_from_filerl      s      )G#G,,r,   c                    g }|D ]g  }|j                  |       t        j                  j                  | |      } t	        |       r@t        j                  dj                  |            }|rg y y)z3Check there are some __init__.py all along the way.re   FT)appendr&   r'   r(   	_has_initr   is_namespace)r'   mod_pathrk   partold_namespaces        r*   check_modpath_has_initrt      sa    G tww||D$' --chhw.?@M  r,   c                P   d}t         j                  j                  |      }t         j                  j                  |       }t         j                  j                  |      j	                  |      r|}t         j                  j                  |       }t         j                  j                  |      j	                  |      r|}|r`t         j                  j                  |      d   }|t        |      d }|j                  t         j                        D cg c]  }|s|	 c}S yc c}w )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   )
r&   r'   r9   abspath
startswithr:   splitextlensplitsep)r@   path_to_checkimportable_pathabs_filenamereal_filename	base_pathrelative_base_pathpkgs           r*   _get_relative_base_pathr      s      OGG$$]3M77??8,L	ww%00?&GG$$X.M	ww&11-@'GG$$_5a8	&s='9';<177?G3GG Hs   D#D#c                   t         j                  j                  t        |             } t        j                  j                         }|r||z  }t        j                  |t        t        |            D ](  }|st        | |      }|s|J  |||d d       s&|c S  t        dj                  | dj                  t        j                                    )Nz"Unable to find module for {} in {}z, 
)r&   r'   
expanduserrE   r$   copy	itertoolschainmaprQ   r   ImportErrorformatr(   )r@   r'   is_package_cbpaths_to_checkpathnamerk   s         r*   modpath_from_file_with_callbackr     s    
 ww!!"5h"?@HXX]]_N$OO1>B 
 )(H=(((73B<0N
 ,33Hfkk#((>ST r,   c                $    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
    )r   rt   )r@   r'   s     r*   ri   ri   7  s    $ +8T;QRRr,   c                0    t        | ||      j                  S rN   )file_info_from_modpathlocation)rk   r'   context_files      r*   file_from_modpathr   L  s    
 "'4>GGGr,   c                t   | t         j                  j                  |      }n|}| d   dk(  r	 t        dg| dd z   ||      S | ddgk(  rHt        j                  dt         j                  j                  t
        j                  j                  	      S t        | ||      S # t        $ r t        | ||      cY S w xY w)
ax  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.

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

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

    :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

    :return:
      the path to the module's file or None if it's an integrated
      builtin module such as 'sys'
    Nr   xml_xmlplus   r&   r'   os.path)namer   type)
r&   r'   dirname_spec_from_modpathr   r   
ModuleSpec__file__
ModuleType	PY_SOURCE)rk   r'   r   contexts       r*   r   r   T  s    >  ggool;qzU	>%zlWQR[&@$PP 
T6N	"WW%%**
 	

 gtW55  	>%gtW==	>s   B B76B7c           	     h   | j                  d      ry| j                  d      }|)|d   t        v rt        |      dkD  rt	        |       |d   S d}d}|d   dk(  r|J d       g }d}|t        |      k  rL||   dk(  rD|dz  }|J d       t
        j                  j                  |      }|t        |      k  r	||   dk(  rDt        |t        |            D ]  }	 t        |||dz    ||	        | S # t        $ r5 |t        dt        |      dz
        k  r dj                  |d|       cY c S w xY w)
a  Given a dotted name return the module part of the name :

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

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

    :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

    :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)
    r   re   Nr   r#    z.explicit relative import, but no context_file?r   )r'   r   )rw   rz   BUILTIN_MODULESry   r   r&   r'   r   ranger   maxr(   )r]   r   rf   r'   startiis         r*   get_module_partr     sq   . i(c"E 8&5zA~!+..8O!DFQx2~$	<;	<$
3u:
%-2"5!$	<;	<$ww|4 3u:
%-2"5 63u:& '	'fq1u%D|' 	  	'3q#e*q.))88E"1I&&	's   C339D10D1c                (   g }t        j                  |       D ]w  \  }}}||v rt        |||       |sddhj                  |      rd|dd 4|D ]?  }t	        |      st         j
                  j                  ||      }|j                  |       A y |S )a  Given a package directory return a list of all available python
    module's files in the package and its subpackages.

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

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

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

    :return:
      the list of all available python module's files in the package and
      its subpackages
    z__init__.pyz__init__.pyir7   N)r&   walkrL   
isdisjoint_is_python_filer'   r(   rn   )	src_directoryrH   list_allfiles	directoryrI   rJ   r@   srcs	            r*   get_module_filesr     s    & E*,''-*@ "&	8Y	!)Xy9]N;FFyQHQK! 	"Hx(ggll9h7S!	"" Lr,   c                   t         j                  j                  t        |             } t         j                  j	                  |       \  }}|dk(  r)t         j                  j                  | |       r| | S t        D ],  }| d| }t         j                  j                  |      s*|c S  |r#|s!t         j                  j                  |      r|S t        |       )ao  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).

    :param filename: python module's file name

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

    :return: the absolute path of the source file if it exists
    .pyire   )r&   r'   rv   rE   rx   existsPY_SOURCE_EXTSr2   )r@   include_no_extbaseorig_extextsource_paths         r*   get_source_filer     s     ww28<=HWW%%h/ND(6bggnnvhZ-@Az"" auo77>>+& h277>>$+?
x
  r,   c                ^    | syt         j                  j                  |       d   dd t        v S )z5Return: True if the filename is a python source file.Fr   N)r&   r'   rx   r   r@   s    r*   is_python_sourcer     s.    77H%a(,>>r,   c                6    | j                  d      d   t        v S )z6Return: True if the modname is in the standard libraryre   r   )rz   r   )modnames    r*   is_stdlib_moduler     s    ==a $777r,   c                    | j                  d      d   } 	 t        | g      yt              t	        |t
              rj                  t        |            S t        fd|D              S # t        $ r Y yw xY w)a
  Try to determine if a module is imported from one of the specified paths

    :param modname: name of the module

    :param path: paths to consider

    :return:
      true if the module:
      - is located on the path listed in one of the directory in `paths`
    re   r   Fc              3  R   K   | ]  }j                  t        |               y wrN   rw   rQ   ).0entryr@   s     r*   	<genexpr>z!module_in_path.<locals>.<genexpr>&  s"     SUx""#8#?@S   $')	rz   r   r   r<   
isinstancer    rw   rQ   any)r   r'   r@   s     @r*   module_in_pathr     s     mmC #G$gY/
 x(H$""#8#>??SdSSS  s   A/ /	A;:A;c                h   t        j                  dt        d       | j                  d      d   } 	 t	        | g      t        j                  |        S t              t        D ]  }j                  t        |            s y |t        }t        fd|D              S # t
        $ r Y yw xY w)a|  Try to guess if a module is a standard python module (by default,
    see `std_path` parameter's description).

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

    :param std_path: list of path considered has standard

    :return:
      true if the module:
      - is located on the path listed in one of the directory in `std_path`
      - is a built-in module
    zWis_standard_module() is deprecated. Use, is_stdlib_module() or module_in_path() insteadr#   )
stacklevelre   r   Fc              3  R   K   | ]  }j                  t        |               y wrN   r   )r   r'   r@   s     r*   r   z%is_standard_module.<locals>.<genexpr>O  s"     UDx""#8#>?Ur   )warningswarnDeprecationWarningrz   r   r   r   rp   r<   EXT_LIB_DIRSrw   rQ   STD_LIB_DIRSr   )r   std_pathr'   r@   s      @r*   is_standard_moduler   )  s     MMa mmC #G$gY/ $$W---x(H 4T:; UHUUU!   s   B% %	B10B1c                4   t         j                  j                  |      st         j                  j                  |      }|t        j                  v ryt        t        j                  j                  j                  | j                  dd      d   |g            S )a6  Return true if the given module name is relative to the given
    file name.

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

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

    :return:
      true if the module has been imported relatively to `from_file`
    Fre   r   )maxsplitr   )r&   r'   isdirr   r$   boolrW   	machinery
PathFinder	find_specrz   )r   	from_files     r*   is_relativer   R  su     77==#GGOOI.	CHH&&00MM#M*1-	{	
 r,   c                z   | sJ d}|%	 t        j                  | |g      }|j                  }nt        j                  | |      }|j                  t         j
                  j                  k(  rO	 |j                  J t        |j                        }|j                  |t         j
                  j                        S |j                  t         j
                  j                  k(  r|j                  d      S |j                  t         j
                  j                  k(  rN|j                  J t        |j                        }|j                  |t         j
                  j                        S |S # t        $ r& t        j                  | |      }|j                  }Y Tw xY w# t        $ r |j                  |      cY S w xY w)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)r   r   )r   )r   r   r   r   r   r   PY_COMPILEDr   _replacer   r2   	C_BUILTINPKG_DIRECTORYro   )rk   r'   r   r   
found_specs        r*   r   r   l  s    N7H	+';J!**H
 ^^GT2
$//555	:&&222&z':':;H&&!(A(A '  
 
DOO55	5""D"11	DOO99	9""...Z001""H4??;T;T"UU+  	+6J!**H	+  	:&&&99	:s$   #E* ,AF *+FFF:9F:c                $    | j                  d      S )zlReturn true if the given filename should be considered as a python file.

    .pyc and .pyo are ignored
    )r>   r   z.soz.pydz.pyw)endswithr   s    r*   r   r     s    
 CDDr,   c                    t         j                  j                  | d      }g t        ddD ]1  }t         j                  j	                  |dz   |z         s)|dz   |z   c S  y)z]If the given directory has a valid __init__ file, return its path,
    else return None.
    __init__pycpyore   N)r&   r'   r(   r   r   )r   mod_or_packr   s      r*   ro   ro     se     '',,y*5K.... +77>>++c12$s**+ r,   c                P    | j                   t        j                  j                  k(  S rN   )r   r   r   PY_NAMESPACEspecobjs    r*   rp   rp     s    <<4??7777r,   c                P    | j                   t        j                  j                  k(  S rN   )r   r   r   r   r   s    r*   is_directoryr     s    <<4??8888r,   c           	     ~    | j                  d      t        fdt        dt              dz         D              S )z
    Returns True if one part of the module name is in the package whitelist.

    >>> is_module_name_part_of_extension_package_whitelist('numpy.core.umath', {'numpy'})
    True
    re   c              3  J   K   | ]  }d j                  d|       v   yw)re   N)r(   )r   xpackage_whitelistrf   s     r*   r   zEis_module_name_part_of_extension_package_whitelist.<locals>.<genexpr>  s+      56r00s    #r   )rz   r   r   ry   )module_namer   rf   s    `@r*   2is_module_name_part_of_extension_package_whitelistr     s?     c"E :?3u:PQ>:R  r,   )r'   r    returnr    )r@   r    rA   r   r   r    )rH   Sequence[str]rI   	list[str]rJ   r   r   None)r]   r    r   types.ModuleType)rf   r   r   r  )rj   r    r   r  )r'   r    rq   r   r   r   )r@   r    r|   r    r   zlist[str] | None)NN)r@   r    r'   Sequence[str] | Noner   z'Callable[[str, list[str]], bool] | Noner   r   rN   )r@   r    r'   r  r   r   )rk   r   r'   r  r   
str | Noner   r  )rk   r   r'   r  r   r  r   spec.ModuleSpec)r]   r    r   r  r   r    )F)r   r    rH   r   r   r   r   r   )r@   r    r   r   r   r    )r@   r  r   r   )r   r    r   r   )r   r    r'   zstr | Iterable[str]r   r   )r   r    r   zIterable[str] | Noner   r   )r   r    r   r    r   r   )rk   r   r'   r  r   r  r   r  )r@   r    r   r   )r   r    r   r  )r   r  r   r   )r   r    r   zset[str]r   r   )\r6   
__future__r   rW   importlib.machineryimportlib.utilrU   r   loggingr&   r$   	sysconfigtypesr   collections.abcr   r   r   
contextlibr   r   	functoolsr	   pathlibr
   astroid.constr   r   r   astroid.interpreter._importr   r   r   astroid._backport_stdlib_names	getLoggerr3   rZ   platformrw   r   PY_COMPILED_EXTSget_pathr   r   addr'   r(   r!   real_prefixAttributeErrorbase_exec_prefixr%   r    parent__annotations__r+   maxsizer   dictfromkeysbuiltin_module_namesr   	Exceptionr2   r<   rE   rL   rO   rQ   rc   rg   rl   rt   r   r   ri   r   r   r   r   r   r   r   r   r   r   r   r   ro   rp   r   r   r7   r,   r*   <module>r!     s  

 #    	   	 
    8 8 7   8 8 2'B			8	$ <<5!)N%"N
 #	""8,.@i.@.@.NO77d?RWW\\#**f56
 	coov>? s&( S0i00:;BBZOPQS0i00:;BB^STU S0i00>?FFSTUD###L1299NJK 77g
oo%7 ['(
{{U 	W-."	""9-/Ay/A/A)/LM-- 8 8$?9 4 :C ''(1'>G'	' ! !("J
2-
H "&=A
 ; 	4S. "&#HH
H H 	H "&#0606
06 06 	06f:| DI  #0 <@  F!0?8
T<&VR8 "&&&
& & 	&RE89)1	]  	RWW\\#*>*>GH 		<  sH   5N* O8 *O505O&%O5&O.+O5-O..O54O58PP