o
    LK&h                     @  s  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m	Z	m
Z
mZ ddlmZ ddlmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZ ddlmZmZmZmZ ddl m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& ddl#m'Z' ddl(m)Z)m*Z* ddl+m,Z, ddl-m.Z. ddl/m0Z0m1Z1 ddl2m2Z3 ddl4m4Z5 ddl6m6Z7 ddl8m8Z9 ddl:m:Z; ddl<m<Z= erddl>m?Z? ddl@mAZA ede'dZBeCeDZEG dd  d eZFd!ZGd"ZHG d#d$ d$e!ZIG d%d& d&eZJG d'd( d(ZKG d)d* d*eKZLG d+d, d,ZMdmd1d2ZNdnd6d7ZOdod>d?ZPd@dA ZQdpdEdFZRdpdGdHZSdqdKdLZTdrdNdOZUdsdQdRZVdtdUdVZWdudWdXZXdvd]d^ZYdwd`daZZG dbdc dce&j[Z\ddZ]dxdidjZ^G dkdl dle%j_Z`dS )ya  
Create a wheel that, when installed, will make the source package 'editable'
(add it to the interpreter's path, including metadata) per PEP 660. Replaces
'setup.py develop'.

.. note::
   One of the mechanisms briefly mentioned in PEP 660 to implement editable installs is
   to create a separated directory inside ``build`` and use a .pth file to point to that
   directory. In the context of this file such directory is referred as
   *auxiliary build directory* or ``auxiliary_dir``.
    )annotationsN)IterableIteratorMapping)suppress)Enum)cleandoc)chainstarmap)Path)TemporaryDirectory)TracebackType)TYPE_CHECKINGProtocolTypeVarcast   )Command_normalization_path_shutilerrors
namespaces)StrPath)py310py312find_package_path)Distribution)InformationOnlySetuptoolsDeprecationWarning   )build)build_py)	dist_info)egg_info)install)install_scripts)Self	WheelFile_P)boundc                   @  s*   e Zd ZdZdZdZdZeddd	Zd
S )_EditableModea  
    Possible editable installation modes:
    `lenient` (new files automatically added to the package - DEFAULT);
    `strict` (requires a new installation when files are added/removed); or
    `compat` (attempts to emulate `python setup.py develop` - DEPRECATED).
    strictlenientcompatmode
str | Nonereturnc                 C  sN   |st jS | }|t jvrtd|d|dkr#tjdddd t | S )NzInvalid editable mode: z. Try: 'strict'.COMPATzCompat editable installsa
  
                The 'compat' editable mode is transitional and will be removed
                in future versions of `setuptools`.
                Please adapt your code accordingly to use either the 'strict' or the
                'lenient' modes.
                zuserguide/development_mode.html)see_docs)r-   LENIENTupper__members__r   OptionErrorr    emit)clsr1   _mode r=   T/var/www/html/venv/lib/python3.10/site-packages/setuptools/command/editable_wheel.pyconvert@   s   
z_EditableMode.convertN)r1   r2   r3   r-   )	__name__
__module____qualname____doc__STRICTr6   r4   classmethodr?   r=   r=   r=   r>   r-   4   s    r-   zU
New or renamed files may not be automatically picked up without a new installation.
zt
Options like `package-data`, `include/exclude-package-data` or
`packages.find.exclude/include` may have no effect.
c                   @  s   e Zd ZdZdZddddeejpdfgZdd	 Zd5ddZ	d5ddZ
dd Zdd Zd6ddZd7ddZdd  Zd8d"d#Zd9d%d&Zd5d'd(Zd:d*d+Zd,d- Zd;d/d0Zd<d3d4ZdS )=editable_wheelzBuild 'editable' wheel for development.
    This command is private and reserved for internal use of setuptools,
    users should rely on ``setuptools.build_meta`` APIs.
    zBDO NOT CALL DIRECTLY, INTERNAL ONLY: create PEP 660 editable wheel)z	dist-dir=dz-directory to put final built distributions in)zdist-info-dir=Iz(path to a pre-build .dist-info directoryzmode=N c                 C  s   d | _ d | _d | _d | _d S N)dist_dirdist_info_dirproject_dirr1   selfr=   r=   r>   initialize_optionsu   s   
z!editable_wheel.initialize_optionsr3   Nonec                 C  s@   | j }|jptj| _|jpi | _t| jptj	| jd| _d S )Ndist)
distributionsrc_rootoscurdirrM   package_dirr   rK   pathjoin)rO   rR   r=   r=   r>   finalize_options{   s    zeditable_wheel.finalize_optionsc              
   C  s   z#| j jdd |   | d | d}|| j | | W d S  tyC } z| j	j
p3| j	 }t|d| d  d }~ww )NT)exist_okbdist_wheelz3An error occurred when building editable wheel for zl.
See debugging tips in: https://setuptools.pypa.io/en/latest/userguide/development_mode.html#debugging-tips)rK   mkdir_ensure_dist_inforeinitialize_commandget_finalized_commandwrite_wheelfilerL   _create_wheel_file	ExceptionrS   nameget_namer   add_note)rO   r\   exprojectr=   r=   r>   run   s    


zeditable_wheel.runc                 C  sj   | j d u rtt| d}| j|_|  |  |j | _ d S t| j 	ds)J t
| j d s3J d S )Nr$   z
.dist-infoMETADATA)rL   r   dist_info_clsr_   rK   
output_dirensure_finalizedri   strendswithr   exists)rO   r$   r=   r=   r>   r^      s   
z editable_wheel._ensure_dist_infoc                 C  sD   | j }|jsd S t| j| jdd }t||||}|  d S )NrI   .)	rS   namespace_packagesr   rM   rW   getresolve_NamespaceInstallerinstall_namespaces)rO   installation_dir
pth_prefixrR   rT   	installerr=   r=   r>   _install_namespaces   s   z"editable_wheel._install_namespacesr2   c                 C  s2   | j r	t| j jnt }tt|d}t|d S )Nz
*.egg-info)rL   r   parentmaprn   globnext)rO   
parent_dir
candidatesr=   r=   r>   _find_egg_info_dir   s   
z!editable_wheel._find_egg_info_dirrd   rn   unpacked_wheelr   	build_libtmp_dirc                 C  sL  | j }t|}t|}tt|| dd}tt|| dd}tt|| dd}	tt|jddd}
t||
_d|
_tt|jddd}tt	|jd	dd}| |_
 |_|_| |_ |_|_|	 |_|_||_||_|d
}d|_tt|d}d|_t||_tt|d}d|_|  |_|   |  |  dS )a  Configure commands to behave in the following ways:

        - Build commands can write to ``build_lib`` if they really want to...
          (but this folder is expected to be ignored and modules are expected to live
          in the project directory...)
        - Binary extensions should be built in-place (editable_mode = True)
        - Data/header/script files are not part of the "editable" specification
          so they are written directly to the unpacked_wheel directory.
        z.datadataheadersscriptsr%   T)reinit_subcommandsr"   r&   build_scriptspythonr'   r#   FN)rS   rn   r   r   egg_info_clsr_   egg_baseignore_egg_info_in_manifest	build_clsinstall_clsbuild_platlibbuild_purelibr   install_purelibinstall_platlibinstall_libr'   r   install_headersinstall_dataget_command_obj
executableinstall_scripts_clsno_ep
build_tempbuild_py_clscompiler   existing_egg_info_dir_set_editable_moderm   )rO   rd   r   r   r   rR   wheelr   r   r   r%   r"   r&   r   r'   r#   r=   r=   r>   _configure_build   sF   




zeditable_wheel._configure_buildc                 C  sN   | j }|d}| D ]}||}t|drd|_qt|dr$d|_qdS )z8Set the ``editable_mode`` flag in the build sub-commandsr"   editable_modeTinplaceN)rS   r   get_sub_commandshasattrr   r   )rO   rR   r"   cmd_namecmdr=   r=   r>   r      s   



z!editable_wheel._set_editable_mode tuple[list[str], dict[str, str]]c                 C  sj   g }i }|  d}| D ]#}|  |}t|dr"|| p g  t|dr0|| p.i  q||fS )Nr"   get_outputsget_output_mapping)r`   r   r   extendr   updater   )rO   filesmappingr"   r   r   r=   r=   r>   _collect_build_outputs   s   



z%editable_wheel._collect_build_outputs	dist_namec                 C  sJ   |  |||| |   |  \}}| d | d | d ||fS )Nr   r   r   )r   _run_build_subcommandsr   _run_install)rO   r   r   r   r   r   r   r=   r=   r>   _run_build_commands  s   


z"editable_wheel._run_build_commandsc                 C  sP   |  d}| D ]}|  |}|dkr t|tur | | q	| | q	dS )a}  
        Issue #3501 indicates that some plugins/customizations might rely on:

        1. ``build_py`` not running
        2. ``build_py`` always copying files to ``build_lib``

        However both these assumptions may be false in editable_wheel.
        This method implements a temporary workaround to support the ecosystem
        while the implementations catch up.
        r"   r#   N)r`   r   typer   _safely_runrun_command)rO   r"   rd   r   r=   r=   r>   r     s   

z%editable_wheel._run_build_subcommandsr   c                 C  sF   z|  |W S  ty"   tddt  d| d| d Y d S w )Nz0Customization incompatible with editable installz
                z

                If you are seeing this warning it is very likely that a setuptools
                plugin or customization overrides the `a  ` command, without
                taking into consideration how editable installs run build steps
                starting from setuptools v64.0.0.

                Plugin authors and developers relying on custom build steps are
                encouraged to update their `aa  ` implementation considering the
                information about editable installs in
                https://setuptools.pypa.io/en/latest/userguide/extension.html.

                For the time being `setuptools` will silence this error and ignore
                the faulty command, but this behavior will change in future versions.
                )r   rc   r    r:   	traceback
format_exc)rO   r   r=   r=   r>   r   -  s   	
zeditable_wheel._safely_runc                 C  s  ddl m} | d}|j}d| }d}| d| d| d}t| j|}| r0|	  t
|d}	t
dd}
t
d	d}|	}|
s}|a}t|t| jj}t| j| | || | ||||\}}| |||}|( ||d
}|||| || W d    n1 sw   Y  W d    n1 sw   Y  W d    n1 sw   Y  W d    n1 sw   Y  W d    |S W d    |S 1 sw   Y  |S )Nr   r)   r$   -z
0.editablez.whl)suffixz
.build-libz.build-tempw)wheel.wheelfiler*   r`   rd   rY   get_tagr   rK   rp   unlinkr   rL   shutilcopytreerz   r   _select_strategywrite_files)rO   r\   r*   r$   r   tag	build_tagarchive_name
wheel_pathr   r   	build_tmpunpackedlibtmpunpacked_dist_infor   r   strategy	wheel_objr=   r=   r>   rb   I  sB   



 ( 


z!editable_wheel._create_wheel_filecategoryc                 C  sL   t | jd| d }|r"| r$td| d | d|  d S d S d S )Nhas_zInstalling z as non editableinstall_)getattrrS   _loggerinfor   )rO   r   has_categoryr=   r=   r>   r   e  s
   
zeditable_wheel._run_installr   EditableStrategyc                 C  s   d| d| }t | j}t| j}|tju r)tt | jd|}t| j|||S t	| j}t
|| j|}	|tju }
t| jdhkrD|	sF|
rX| jdd}t| j|t ||gS t| j|S )zDDecides which strategy to use to implement an editable installation.__editable__.r   r"   rI   rq   )r   rM   r-   r?   r1   rD   
_empty_dir	_LinkTreerS   _find_packages_simple_layoutrW   r4   setrs   
_StaticPth_TopLevelFinder)rO   rd   r   r   
build_namerM   r1   auxiliary_dirpackageshas_simple_layoutis_compat_modesrc_dirr=   r=   r>   r   k  s   



zeditable_wheel._select_strategyr3   rQ   )r3   r2   )rd   rn   r   r   r   r   r   r   )r3   r   )
r   rn   r   r   r   r   r   r   r3   r   )r   rn   )r   rn   )rd   rn   r   rn   r   r   r3   r   )r@   rA   rB   rC   descriptionr   r-   user_optionsrP   rZ   ri   r^   rz   r   r   r   r   r   r   r   rb   r   r   r=   r=   r=   r>   rF   g   s,    




?




rF   c                   @  s*   e Zd Zdd	d
ZdddZdddZdS )r   r   r*   r   	list[str]r   Mapping[str, str]r3   objectc                 C     d S rJ   r=   rO   r   r   r   r=   r=   r>   __call__  s   zEditableStrategy.__call__r(   c                 C  r   rJ   r=   rN   r=   r=   r>   	__enter__  s    zEditableStrategy.__enter__	_exc_typetype[BaseException] | None
_exc_valueBaseException | None
_tracebackTracebackType | Nonec                 C  r   rJ   r=   rO   r   r   r   r=   r=   r>   __exit__  s   zEditableStrategy.__exit__N)r   r*   r   r   r   r   r3   r   r3   r(   )r   r   r   r   r   r   r3   r   )r@   rA   rB   r   r   r   r=   r=   r=   r>   r     s    

r   c                   @  s4   e Zd Zdd	d
ZdddZdddZd ddZdS )!r   rR   r   rd   rn   path_entries
list[Path]r3   rQ   c                 C  s   || _ || _|| _d S rJ   )rR   rd   r   )rO   rR   rd   r   r=   r=   r>   __init__  s   
z_StaticPth.__init__r   r*   r   r   r   r   c                 C  s>   d dd | jD }t| d}|d| j d| d S )N
c                 s  s    | ]	}t | V  qd S rJ   )rn   rt   ).0pr=   r=   r>   	<genexpr>      z&_StaticPth.__call__.<locals>.<genexpr>r   .pth)rY   r   _encode_pthwritestrrd   )rO   r   r   r   entriescontentsr=   r=   r>   r     s   z_StaticPth.__call__r(   c                 C  s,   dt ttj| jd}t|t  | S )Nz_
        Editable install will be performed using .pth file to extend `sys.path` with:
        z	
        )listr|   rU   fspathr   r   warning_LENIENT_WARNINGrO   msgr=   r=   r>   r     s
   z_StaticPth.__enter__r   r   r   r   c                 C  r   rJ   r=   r   r=   r=   r>   r     s   z_StaticPth.__exit__N)rR   r   rd   rn   r   r   r3   rQ   r   r*   r   r   r   r   r   r   r   r   r   r   r   r3   rQ   )r@   rA   rB   r   r   r   r   r=   r=   r=   r>   r     s
    


r   c                      sd   e Zd ZdZd* fddZd+ fddZd,ddZd-d.ddZd/dd Zd0d"d#Z	d1d(d)Z
  ZS )2r   a`  
    Creates a ``.pth`` file that points to a link tree in the ``auxiliary_dir``.

    This strategy will only link files (not dirs), so it can be implemented in
    any OS, even if that means using hardlinks instead of symlinks.

    By collocating ``auxiliary_dir`` and the original source code, limitations
    with hardlinks should be avoided.
    rR   r   rd   rn   r   r   r   r3   rQ   c                   s>   t || _t | | _|dj| _t ||| jg d S )Nr#   )	r   r   rt   r   r   	copy_file_filesuperr   )rO   rR   rd   r   r   	__class__r=   r>   r     s   
z_LinkTree.__init__r   r*   r   r   r   r   c                   s    |  || t ||| d S rJ   )_create_linksr  r   r   r  r=   r>   r     s   z_LinkTree.__call__filer2   c                 C  sR   t t t| | j}t|tj	dW  d    S 1 s"w   Y  d S )N/)
r   
ValueErrorr   rt   relative_tor   rn   replacerU   sep)rO   r  rX   r=   r=   r>   _normalize_output  s
   
 z_LinkTree._normalize_outputNrelative_outputsrc_filec                 C  s6   | j | }|j s|jjdd | j|||d d S )NT)parentslink)r   r{   is_dirr]   r  )rO   r  r  r  destr=   r=   r>   _create_file  s   

z_LinkTree._create_fileoutput_mappingc           	        s    j jddd t j rdnd} fdd| D }dd |D }|D ]} |}|r8||vr8 || q%| D ]\}} j|||d	 q=d S )
NT)r  r[   symhardc                 3  s"    | ]\}}  ||fV  qd S rJ   )r  r   kvrN   r=   r>   r     s     z*_LinkTree._create_links.<locals>.<genexpr>c                 S  s   i | ]\}}|d ur||qS rJ   r=   r$  r=   r=   r>   
<dictcomp>  s    z+_LinkTree._create_links.<locals>.<dictcomp>r  )r   r]   _can_symlink_filesitemsr  r   )	rO   outputsr!  	link_type
normalisedmappingsoutputrelativesrcr=   rN   r>   r    s   
z_LinkTree._create_linksr(   c                 C     d}t |t  | S )Nz=Strict editable install will be performed using a link tree.
)r   r  _STRICT_WARNINGr  r=   r=   r>   r        z_LinkTree.__enter__r   r   r   r   c                 C  s   d| j  d}td| d S )Nz\

        Strict editable installation performed using the auxiliary directory:
            z

        Please be careful to not remove this directory, otherwise you might not be able
        to import/use your package.
        Editable installation.)r   r   r:   rO   r   r   r   r	  r=   r=   r>   r     s   z_LinkTree.__exit__)
rR   r   rd   rn   r   r   r   r   r3   rQ   r
  )r  rn   r3   r2   rJ   )r  rn   r  rn   )r!  r   r   r  )r@   rA   rB   rC   r   r   r  r   r  r   r   __classcell__r=   r=   r  r>   r     s    



r   c                   @  sH   e Zd Zd!ddZd"d
dZd#ddZd$ddZd%ddZd&ddZd S )'r   rR   r   rd   rn   r3   rQ   c                 C  s   || _ || _d S rJ   )rR   rd   )rO   rR   rd   r=   r=   r>   r     s   
z_TopLevelFinder.__init__5tuple[str, str, dict[str, str], dict[str, list[str]]]c           	        s   j jptj}ttj tj }j jpi }t||| t	tt
j jp&g  dd t D } fddj jp>g D }i  |}dj d}t|}||||fS )Nc                 s  s    | ]}|g fV  qd S rJ   r=   )r   nsr=   r=   r>   r   	  s    z0_TopLevelFinder.template_vars.<locals>.<genexpr>c                   s"   i | ]}|t | jjpd qS )rI   )r   rR   rT   r   pkgrootsrO   r=   r>   r'    s    z1_TopLevelFinder.template_vars.<locals>.<dictcomp>r   z.finder)rR   rT   rU   rV   r	   r   _find_top_level_modulesrW   _find_package_rootsdict_find_namespacesr   _find_virtual_namespacesrr   rd   r   safe_identifier)	rO   rT   	top_levelrW   namespaces_legacy_namespacesr   rd   finderr=   r;  r>   template_vars   s"   

z_TopLevelFinder.template_varsIterator[tuple[str, bytes]]c                 c  sb    |   \}}}}tt|||d}| d|fV  td| d| d}d| j d|fV  d S )Nutf-8z.pyzimport z; z
.install()r   r   )rG  bytes_finder_templater   rd   )rO   rF  rd   r   rD  contentr=   r=   r>   get_implementation  s   z"_TopLevelFinder.get_implementationr   r*   r   r   r   r   c                 C  s"   |   D ]
\}}||| qd S rJ   )rM  r  )rO   r   r   r   r  rL  r=   r=   r>   r   $  s   z_TopLevelFinder.__call__r(   c                 C  r1  )Nz=Editable install will be performed using a meta path finder.
)r   r  r  r  r=   r=   r>   r   (  r3  z_TopLevelFinder.__enter__r   r   r   r   c                 C  s   d}t d| d S )Nz

        Please be careful with folders in your working directory with the same
        name as your package as they may take precedence during imports.
        r4  )r   r:   r5  r=   r=   r>   r   -  s   z_TopLevelFinder.__exit__N)rR   r   rd   rn   r3   rQ   )r3   r7  )r3   rH  r
  r   r  )	r@   rA   rB   r   rG  rM  r   r   r   r=   r=   r=   r>   r     s    



	
r   rL  rn   r3   rJ  c                 C  s`   t  "}t j|tjd}||  |  |d | W  d   S 1 s)w   Y  dS )a  
    Prior to Python 3.13 (see https://github.com/python/cpython/issues/77102),
    .pth files are always read with 'locale' encoding, the recommendation
    from the cpython core developers is to write them as ``open(path, "w")``
    and ignore warnings (see python/cpython#77102, pypa/setuptools#3937).
    This function tries to simulate this behavior without having to create an
    actual file, in a way that supports a range of active Python versions.
    (There seems to be some variety in the way different version of Python handle
    ``encoding=None``, not all of them use ``locale.getpreferredencoding(False)``
    or ``locale.getencoding()``).
    encodingr   N)	ioBytesIOTextIOWrapperr   PTH_ENCODINGwriteflushseekread)rL  bufferwrapperr=   r=   r>   r   :  s   


$r   base_dirr   boolc                 C  s  t t|  do}t|dt|d}}|jddd tttt) t	
|| | rD|jdddkrD	 W d    W d    dS W d    n1 sNw   Y  zt	|| W n tyn } zd}t||d }~ww 	 W d    d	S 1 s{w   Y  d S )
N)dirz	file1.txtz	file2.txtfile1rI  rN  TzFile system does not seem to support either symlinks or hard links. Strict editable installs require one of them to be supported.F)r   rn   rt   r   
write_textr   AttributeErrorNotImplementedErrorOSErrorrU   symlink
is_symlink	read_textr  rc   LinksNotSupported)rZ  r   path1path2rg   r	  r=   r=   r>   r(  O  s*   
$r(  r   Iterable[str]rW   dict[str, str]rM   r   c                   sZ    fdd| D }|st  i dhfv S tjtt| tfdd| D S )a[  Return ``True`` if:
    - all packages are contained by the same parent directory, **and**
    - all packages become importable if the parent directory is added to ``sys.path``.

    >>> _simple_layout(['a'], {"": "src"}, "/tmp/myproj")
    True
    >>> _simple_layout(['a', 'a.b'], {"": "src"}, "/tmp/myproj")
    True
    >>> _simple_layout(['a', 'a.b'], {}, "/tmp/myproj")
    True
    >>> _simple_layout(['a', 'a.a1', 'a.a1.a2', 'b'], {"": "src"}, "/tmp/myproj")
    True
    >>> _simple_layout(['a', 'a.a1', 'a.a1.a2', 'b'], {"a": "a", "b": "b"}, ".")
    True
    >>> _simple_layout(['a', 'a.a1', 'a.a1.a2', 'b'], {"a": "_a", "b": "_b"}, ".")
    False
    >>> _simple_layout(['a', 'a.a1', 'a.a1.a2', 'b'], {"a": "_a"}, "/tmp/myproj")
    False
    >>> _simple_layout(['a', 'a.a1', 'a.a1.a2', 'b'], {"a.a1.a2": "_a2"}, ".")
    False
    >>> _simple_layout(['a', 'a.b'], {"": "src", "a.b": "_ab"}, "/tmp/myproj")
    False
    >>> # Special cases, no packages yet:
    >>> _simple_layout([], {"": "src"}, "/tmp/myproj")
    True
    >>> _simple_layout([], {"a": "_a", "": "src"}, "/tmp/myproj")
    False
    c                   s   i | ]	}|t | qS r=   r   r9  )rW   rM   r=   r>   r'    s    z"_simple_layout.<locals>.<dictcomp>rI   c                 3  s2    | ]\}}t t g|d R  |V  qdS rq   N)r   	same_pathr   split)r   keyvalue)r{   r=   r>   r     s
    
z!_simple_layout.<locals>.<genexpr>)r   rU   rX   
commonpathr
   _parent_pathr)  all)r   rW   rM   layoutr=   )rW   r{   rM   r>   r   c  s   r   c                 C  s0   | | r|dt|   n|}|dtj S )a7  Infer the parent path containing a package, that if added to ``sys.path`` would
    allow importing that package.
    When ``pkg`` is directly mapped into a directory with a different name, return its
    own path.
    >>> _parent_path("a", "src/a")
    'src'
    >>> _parent_path("b", "src/c")
    'src/c'
    Nr  )ro   lenrstriprU   r  )r:  pkg_pathr{   r=   r=   r>   rp    s    
rp  rR   r   Iterator[str]c                 c  s~    t | jpg E d H  | jpg }dd |D }| jr| jV  n| jp#g }|dd |D 7 }|D ]}|d\}}}|V  q/d S )Nc                 S  s   g | ]}d |v r|qS rq   r=   r   modr=   r=   r>   
<listcomp>  s    z"_find_packages.<locals>.<listcomp>c                 S  s   g | ]
}d |j v r|j qS rw  rd   r   xr=   r=   r>   rz    s    rq   )iterr   
py_modulesext_packageext_modules
rpartition)rR   r  nested_modulesr  modulepackage_r=   r=   r>   r     s   


r   c                 c  sL    | j pg }dd |D E d H  | js$| jpg }dd |D E d H  d S d S )Nc                 s  s    | ]	}d |vr|V  qdS rj  r=   rx  r=   r=   r>   r     r   z*_find_top_level_modules.<locals>.<genexpr>c                 s  s     | ]}d |j vr|j V  qdS rj  r{  r|  r=   r=   r>   r     s    )r  r  r  )rR   r  r  r=   r=   r>   r=    s   

r=  r   rT   c                   s     fddt | D }t|S )Nc                   s   i | ]}|t t| qS r=   )_absolute_rootr   r9  rW   rT   r=   r>   r'    s    z'_find_package_roots.<locals>.<dictcomp>)sorted_remove_nested)r   rW   rT   	pkg_rootsr=   r  r>   r>    s   r>  rX   c                 C  s4   t | }|j}| rt| S t| |j S )z(Works for packages and top-level modules)r   r{   rp   rn   rt   rd   )rX   path_r{   r=   r=   r>   r    s
   r  r  c                 c  sv    | D ]5}d|vr
q| d}tt|d ddD ]}d|d| }tt|| d}| r4|| vr7|V  qqdS )a8  By carefully designing ``package_dir``, it is possible to implement the logical
    structure of PEP 420 in a package without the corresponding directories.

    Moreover a parent package can be purposefully/accidentally skipped in the discovery
    phase (e.g. ``find_packages(include=["mypkg.*"])``, when ``mypkg.foo`` is included
    by ``mypkg`` itself is not).
    We consider this case to also be a virtual namespace (ignoring the original
    directory) to emulate a non-editable installation.

    This function will try to find these kinds of namespaces.
    rq   r!   r   NrI   )rl  rangers  rY   r   r   rp   )r  r:  partsipartial_namerX   r=   r=   r>   rA    s   
rA  r   Iterator[tuple[str, list[str]]]c                 c  sB    | D ]}t ||d}t| rt|d s||gfV  qd S )NrI   z__init__.py)r   r   rp   )r   r  r:  rX   r=   r=   r>   r@    s   r@  c                   sP   t |  }tt|  D ]\ t fdd|  D r%| q|S )Nc                 3  s*    | ]\}}|kot  ||V  qd S rJ   )
_is_nested)r   other
other_pathrX   r:  r=   r>   r     s
    
z!_remove_nested.<locals>.<genexpr>)r?  copyreversedr  r)  anypop)r  r.  r=   r  r>   r    s   
r  r:  ru  r{   parent_pathc                 C  sH   t |}| |dddd}| |o#|t t|g|R  kS )a  
    Return ``True`` if ``pkg`` is nested inside ``parent`` both logically and in the
    file system.
    >>> _is_nested("a.b", "path/a/b", "a", "path/a")
    True
    >>> _is_nested("a.b", "path/a/b", "a", "otherpath/a")
    False
    >>> _is_nested("a.b", "path/a/b", "c", "path/c")
    False
    >>> _is_nested("a.a", "path/a/a", "a", "path/a")
    True
    >>> _is_nested("b.a", "path/b/a", "a", "path/a")
    False
    rI   r!   rq   )r   normpathr  striprl  
startswithr   )r:  ru  r{   r  norm_pkg_pathrestr=   r=   r>   r    s
   
r  dir_c                 C  s   t j| dd t|  | S )zFCreate a directory ensured to be empty. Existing files may be removed.T)ignore_errors)r   rmtreerU   makedirs)r  r=   r=   r>   r     s   
r   c                   @  s&   e Zd Zd
ddZdd Zdd Zd	S )ru   r3   rQ   c                 C  s(   || _ || _|| _|| _g | _d| _d S )NF)rS   rT   rw   editable_namer*  dry_run)rO   rS   rw   r  rT   r=   r=   r>   r     s   
z_NamespaceInstaller.__init__c                 C  s   t j| j| j| j S )zInstallation target.)rU   rX   rY   rw   r  	nspkg_extrN   r=   r=   r>   _get_nspkg_file  s   z#_NamespaceInstaller._get_nspkg_filec                 C  s   t t| jS )z1Where the modules/packages should be loaded from.)reprrn   rT   rN   r=   r=   r>   	_get_root#  s   z_NamespaceInstaller._get_rootNr   )r@   rA   rB   r   r  r  r=   r=   r=   r>   ru     s    
ru   a  from __future__ import annotations
import sys
from importlib.machinery import ModuleSpec, PathFinder
from importlib.machinery import all_suffixes as module_suffixes
from importlib.util import spec_from_file_location
from itertools import chain
from pathlib import Path

MAPPING: dict[str, str] = {mapping!r}
NAMESPACES: dict[str, list[str]] = {namespaces!r}
PATH_PLACEHOLDER = {name!r} + ".__path_hook__"


class _EditableFinder:  # MetaPathFinder
    @classmethod
    def find_spec(cls, fullname: str, path=None, target=None) -> ModuleSpec | None:  # type: ignore
        # Top-level packages and modules (we know these exist in the FS)
        if fullname in MAPPING:
            pkg_path = MAPPING[fullname]
            return cls._find_spec(fullname, Path(pkg_path))

        # Handle immediate children modules (required for namespaces to work)
        # To avoid problems with case sensitivity in the file system we delegate
        # to the importlib.machinery implementation.
        parent, _, child = fullname.rpartition(".")
        if parent and parent in MAPPING:
            return PathFinder.find_spec(fullname, path=[MAPPING[parent]])

        # Other levels of nesting should be handled automatically by importlib
        # using the parent path.
        return None

    @classmethod
    def _find_spec(cls, fullname: str, candidate_path: Path) -> ModuleSpec | None:
        init = candidate_path / "__init__.py"
        candidates = (candidate_path.with_suffix(x) for x in module_suffixes())
        for candidate in chain([init], candidates):
            if candidate.exists():
                return spec_from_file_location(fullname, candidate)
        return None


class _EditableNamespaceFinder:  # PathEntryFinder
    @classmethod
    def _path_hook(cls, path) -> type[_EditableNamespaceFinder]:
        if path == PATH_PLACEHOLDER:
            return cls
        raise ImportError

    @classmethod
    def _paths(cls, fullname: str) -> list[str]:
        paths = NAMESPACES[fullname]
        if not paths and fullname in MAPPING:
            paths = [MAPPING[fullname]]
        # Always add placeholder, for 2 reasons:
        # 1. __path__ cannot be empty for the spec to be considered namespace.
        # 2. In the case of nested namespaces, we need to force
        #    import machinery to query _EditableNamespaceFinder again.
        return [*paths, PATH_PLACEHOLDER]

    @classmethod
    def find_spec(cls, fullname: str, target=None) -> ModuleSpec | None:  # type: ignore
        if fullname in NAMESPACES:
            spec = ModuleSpec(fullname, None, is_package=True)
            spec.submodule_search_locations = cls._paths(fullname)
            return spec
        return None

    @classmethod
    def find_module(cls, _fullname) -> None:
        return None


def install():
    if not any(finder == _EditableFinder for finder in sys.meta_path):
        sys.meta_path.append(_EditableFinder)

    if not NAMESPACES:
        return

    if not any(hook == _EditableNamespaceFinder._path_hook for hook in sys.path_hooks):
        # PathEntryFinder is needed to create NamespaceSpec without private APIS
        sys.path_hooks.append(_EditableNamespaceFinder._path_hook)
    if PATH_PLACEHOLDER not in sys.path:
        sys.path.append(PATH_PLACEHOLDER)  # Used just to trigger the path hook
rd   r   r   dict[str, list[str]]c                 C  s(   t t| dd d}tj| ||dS )z_Create a string containing the code for the``MetaPathFinder`` and
    ``PathEntryFinder``.
    c                 S  s   | d S )Nr   r=   )r   r=   r=   r>   <lambda>  s    z"_finder_template.<locals>.<lambda>)rm  rd   r   r   )r?  r  r)  _FINDER_TEMPLATEformatr  r=   r=   r>   rK    s   rK  c                   @  s   e Zd ZdZdS )re  zCFile system does not seem to support either symlinks or hard links.N)r@   rA   rB   rC   r=   r=   r=   r>   re    s    re  )rL  rn   r3   rJ  )rZ  r   r3   r[  )r   rh  rW   ri  rM   r   r3   r[  )rR   r   r3   rv  )r   rh  rW   r   rT   r   r3   ri  )rX   r   r3   rn   )r  ri  r3   rv  )r   r   r  ri  r3   r  )r  ri  r3   ri  )
r:  rn   ru  rn   r{   rn   r  rn   r3   r[  )r  r+   r3   r+   )rd   rn   r   r   r   r  r3   rn   )arC   
__future__r   rP  loggingrU   r   r   collections.abcr   r   r   
contextlibr   enumr   inspectr   	itertoolsr	   r
   pathlibr   tempfiler   typesr   typingr   r   r   r   rI   r   r   r   r   r   r   r   r0   r   r   	discoveryr   rR   r   warningsr   r    r"   r   r#   r   r$   rk   r%   r   r&   r   r'   r   typing_extensionsr(   _vendor.wheel.wheelfiler*   r+   	getLoggerr@   r   r-   r2  r  rF   r   r   r   r   r   r(  r   rp  r   r=  r>  r  rA  r@  r  r  r   	Installerru   r  rK  	FileErrorre  r=   r=   r=   r>   <module>   sx     
)  !L
?

)


	



	


Y
