
    7gY                    N   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mZ ddlmZmZ erdd	l
mZ ndd	lmZ  ej>                  e       Z!e
jD                  jG                  d
      rdZ$dZ%dZ&ndZ$dZ%dZ& ejN                  d       ejN                  d      hZ(e	jR                  dk(  rke(jU                  e	jV                  jY                  e
jZ                  d             	 e(jU                  e	jV                  jY                  e
j\                  d             e	jR                  dk(  rS	 e
j\                  Z-de1d<   d?dZ2e(jU                   e2d             e
jf                  dkD  re(jU                   e2d              ejN                  d       ejN                  d      hZ4e5jm                  e
jn                  d      Z8 G d d e9      Z:d?d!Z;efd@d"Z<	 	 	 	 	 	 	 	 dAd#Z=ed?d$       Z>d?d%Z?dBd&Z@dCd'ZAdDd(ZBdEd)ZCdFd*ZD	 	 dG	 	 	 	 	 	 	 dHd+ZEdIdJd,ZF	 	 dG	 	 	 	 	 	 	 dKd-ZG	 	 dG	 	 	 	 	 	 	 dLd.ZHdIdMd/ZI	 dN	 	 	 	 	 	 	 dOd0ZJ	 dP	 	 	 	 	 	 	 dQd1ZKdRd2ZLdSd3ZMdTd4ZNdIdUd5ZOdVd6ZP	 	 dG	 	 	 	 	 	 	 dWd7ZQdXd8ZR ed9:      dYd;       ZSdZd<ZTdZd=ZU	 	 	 	 	 	 d[d>ZVy# e/$ rF 	 e(jU                  e	jV                  jY                  e
j`                  d             n# e/$ r Y nw xY wY w xY w# e/$ r e
jZ                  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)	IS_JYTHON
PY310_PLUS)specutil)stdlib_module_nameswin)pypywpyi)r   r   r   )dllpyd)r   r   )r   r   )sostdlib
platstdlibntdlls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     0lib/python3.12/site-packages/astroid/modutils.py_posix_pathr&   V   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%   r-   r-   i   s    r'   r-   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_pathr7   o   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_filenamer@   z   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_blacklistrG      s8     xOOH%"X&	 r'   c                    t        |       S N)r7   r6   s    r%   _cache_normalize_path_rJ      s    4  r'   c                2    | st        |       S t        |       S )zNormalize path with caching.)r7   rJ   r6   s    r%   _cache_normalize_pathrL      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_namer^      s    {{;''  	&&&&((5 	'&& 	'&&
 ??$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
    .)r^   r#   )partss    r%   load_module_from_modpathrb      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_filerb   )filepathmodpaths     r%   load_module_from_filerg      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.r`   FT)appendr!   r"   r#   	_has_initr   is_namespace)r"   mod_pathrf   partold_namespaces        r%   check_modpath_has_initro      s\    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"   r4   abspath
startswithr5   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"   
expanduserr@   r   copy	itertoolschainmaprL   r~   ImportErrorformatr#   )r;   r"   is_package_cbpaths_to_checkpathnamerf   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   ro   )r;   r"   s     r%   rd   rd   +  s    $ +8T;QRRr'   c                0    t        | ||      j                  S rI   )file_info_from_modpathlocation)rf   r"   context_files      r%   file_from_modpathr   @  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)rf   r"   r   contexts       r%   r   r   H  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   r`   Nr   r    z.explicit relative import, but no context_file?r   )r"   r   )rr   ru   BUILTIN_MODULESrt   r   r!   r"   r   ranger   maxr#   )rX   r   ra   r"   startiis         r%   get_module_partr   {  sl   . 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__.pyir2   N)r!   walkrG   
isdisjoint_is_python_filer"   r#   ri   )	src_directoryrC   list_allfiles	directoryrD   rE   r;   srcs	            r%   get_module_filesr     s    & E*,''-*@&	8Y	!)Xy9]N;FFyQHQK!Hx(ggll9h7S! " +A Lr'   c                   t         j                  j                  t        |             } t         j                  j	                  |       \  }}|dk(  r)t         j                  j                  | |       r| | S |rt        n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
    .pyir`   )	r!   r"   rq   r@   rs   existsPY_SOURCE_EXTS_STUBS_FIRSTPY_SOURCE_EXTSr-   )r;   include_no_extprefer_stubsbaseorig_extextsource_paths          r%   get_source_filer     s     ww28<=HWW%%h/ND(6bggnnvhZ-@Az""-9)~Mauo77>>+& N 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"   rs   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 libraryr`   r   )ru   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`
    r`   r   Fc              3  R   K   | ]  }j                  t        |               y wrI   rr   rL   ).0entryr;   s     r%   	<genexpr>z!module_in_path.<locals>.<genexpr>  s#     SdUx""#8#?@d   $')	ru   r   r   r7   
isinstancer   rr   rL   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   )
stacklevelr`   r   Fc              3  R   K   | ]  }j                  t        |               y wrI   r   )r   r"   r;   s     r%   r   z%is_standard_module.<locals>.<genexpr>E  s#     UHDx""#8#>?Hr   )warningswarnDeprecationWarningru   r   r   r   rk   r7   EXT_LIB_DIRSrr   rL   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`
    Fr`   r   )maxsplitr   )r!   r"   isdirr   r   boolrR   	machinery
PathFinder	find_specru   )r   	from_files     r%   is_relativer   H  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   r-   	C_BUILTINPKG_DIRECTORYrj   )rf   r"   r   r   
found_specs        r%   r   r   b  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
    )r9   r   z.soz.pydz.pyw)endswithr   s    r%   r   r     s    
 CDDr'   i   )maxsizec                    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pyor`   N)r!   r"   r#   r   r   )r   mod_or_packr   s      r%   rj   rj     s`    
 '',,y*5K....77>>++c12$s** / r'   c                P    | j                   t        j                  j                  k(  S rI   )r   r   r   PY_NAMESPACEspecobjs    r%   rk   rk     s    <<4??7777r'   c                P    | j                   t        j                  j                  k(  S rI   )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
    r`   c              3  J   K   | ]  }d j                  d|       v   yw)r`   N)r#   )r   xpackage_whitelistra   s     r%   r   zEis_module_name_part_of_extension_package_whitelist.<locals>.<genexpr>  s+      :RQr00:Rs    #r   )ru   r   r   rt   )module_namer   ra   s    `@r%   2is_module_name_part_of_extension_package_whitelistr     s?     c"E :?3u:PQ>:R  r'   )r"   r   returnr   )r;   r   r<   r   r   r   )rC   Sequence[str]rD   	list[str]rE   r   r   None)rX   r   r   types.ModuleType)ra   r   r   r   )re   r   r   r   )r"   r   rl   r   r   r   )r;   r   rw   r   r   zlist[str] | None)NN)r;   r   r"   Sequence[str] | Noner   z'Callable[[str, list[str]], bool] | Noner   r   rI   )r;   r   r"   r   r   r   )rf   r   r"   r   r   
str | Noner   r  )rf   r   r"   r   r   r  r   spec.ModuleSpec)rX   r   r   r  r   r   )F)r   r   rC   r   r   r   r   r   )FF)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   )rf   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   )Wr1   
__future__r   rR   importlib.machineryimportlib.utilrP   r   loggingr!   r   	sysconfigtypesr   collections.abcr   r   r   
contextlibr   r   	functoolsr	   astroid.constr
   r   astroid.interpreter._importr   r   r   astroid._backport_stdlib_names	getLoggerr.   rU   platformrr   r   r   PY_COMPILED_EXTSget_pathr   r   addr"   r#   r   real_prefixAttributeErrorbase_exec_prefix__annotations__r&   r   r   dictfromkeysbuiltin_module_namesr   	Exceptionr-   r7   r@   rG   rJ   rL   r^   rb   rg   ro   r~   r   rd   r   r   r   r   r   r   r   r   r   r   r   r   rj   rk   r   r   r2   r'   r%   <module>r     s  

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