U
    8hX:                     @   s~  d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlmZ	 d dl
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 erd d	lmZ G d
d deZeeef eddddZeeeef dddZG dd deZG dd deZG dd deZd"ee ee eeeef  ddddZ d#ee ee eeeef  ddddZ!eeedddZ"G d d! d!Z#dS )$    N)contextmanager)abspath)join)STDOUT
check_callcheck_output)TYPE_CHECKINGAnyIteratorMappingOptionalSequence   )_in_proc_script_path)Protocolc                   @   s:   e Zd ZdZdee ee eeeef  ddddZdS )SubprocessRunnerz%A protocol for the subprocess runner.Ncmdcwdextra_environreturnc                 C   s   d S N )selfr   r   r   r   r   _C:\Users\jeffr\AppData\Local\Temp\pip-install-hfyjq797\pip\pip\_vendor\pyproject_hooks\_impl.py__call__   s    zSubprocessRunner.__call__)NN)	__name__
__module____qualname____doc__r   strr   r   r   r   r   r   r   r      s     r   )objpathr   c              	   K   s.   t |ddd}tj| |f| W 5 Q R X d S )Nwutf-8encoding)openjsondump)r!   r"   kwargsfr   r   r   
write_json   s    r,   )r"   r   c              
   C   s.   t | dd}t|W  5 Q R  S Q R X d S )Nr$   r%   )r'   r(   load)r"   r+   r   r   r   	read_json!   s    r.   c                       s@   e Zd ZdZdeee ee eee  dd fddZ  ZS )BackendUnavailablezEWill be raised if the backend cannot be imported in the hook process.N)	tracebackmessagebackend_namebackend_pathr   c                    s&   || _ || _|| _t |pd d S )NzError while importing backend)r2   r3   r0   super__init__)r   r0   r1   r2   r3   	__class__r   r   r5   )   s    zBackendUnavailable.__init__)NNN)	r   r   r   r   r    r   r   r5   __classcell__r   r   r6   r   r/   &   s      
r/   c                       s(   e Zd ZdZedd fddZ  ZS )HookMissingz>Will be raised on missing hooks (if a fallback can't be used).N)	hook_namer   c                    s   t  | || _d S r   )r4   r5   r:   )r   r:   r6   r   r   r5   :   s    zHookMissing.__init__)r   r   r   r   r    r5   r8   r   r   r6   r   r9   7   s   r9   c                   @   s    e Zd ZdZeddddZdS )UnsupportedOperationzDMay be raised by build_sdist if the backend indicates that it can't.N)r0   r   c                 C   s
   || _ d S r   )r0   )r   r0   r   r   r   r5   B   s    zUnsupportedOperation.__init__)r   r   r   r   r    r5   r   r   r   r   r;   ?   s   r;   r   c                 C   s*   t j }|r|| t| ||d dS )zwThe default method of calling the wrapper subprocess.

    This uses :func:`subprocess.check_call` under the hood.
    )r   envN)osenvironcopyupdater   r   r   r   r<   r   r   r   default_subprocess_runnerF   s    	

rB   c                 C   s,   t j }|r|| t| ||td dS )zqCall the subprocess while suppressing output.

    This uses :func:`subprocess.check_output` under the hood.
    )r   r<   stderrN)r=   r>   r?   r@   r   r   rA   r   r   r   quiet_subprocess_runnerV   s    	

rD   )source_tree	requestedr   c                 C   sn   t j|rtdt j| }t jt j||}t j|}t j|}t j||g|krjtd|S )zNormalise and check a backend path.

    Ensure that the requested backend path is specified as a relative path,
    and resolves to a location under the given source tree.

    Return an absolute version of the requested path.
    zpaths must be relativez paths must be inside source tree)	r=   r"   isabs
ValueErrorr   normpathr   normcasecommonprefix)rE   rF   Z
abs_sourceZabs_requestedZnorm_sourceZnorm_requestedr   r   r   norm_and_checkf   s    rL   c                   @   s  e Zd ZdZd%eeeee  ed ee ddddZede	d ddd	Z
ee d
ddZd&eeeef  ee dddZd'eeeeef  eedddZd(eeeeef  ee edddZd)eeeef  ee dddZd*eeeeef  eee dddZd+eeeeef  ee edddZd,eeeef  ee dddZd-eeeeef  edd d!Zeeeef ed"d#d$ZdS ).BuildBackendHookCallerzAA wrapper to call the build backend hooks for a source directory.Nr   )
source_dirbuild_backendr3   runnerpython_executabler   c                    sR   |dkrt }t| _| _|r2 fdd|D }| _| _|sHtj}| _dS )a  
        :param source_dir: The source directory to invoke the build backend for
        :param build_backend: The build backend spec
        :param backend_path: Additional path entries for the build backend spec
        :param runner: The :ref:`subprocess runner <Subprocess Runners>` to use
        :param python_executable:
            The Python executable used to invoke the build backend
        Nc                    s   g | ]}t  j|qS r   )rL   rN   ).0pr   r   r   
<listcomp>   s     z3BuildBackendHookCaller.__init__.<locals>.<listcomp>)	rB   r   rN   rO   r3   _subprocess_runnersys
executablerQ   )r   rN   rO   r3   rP   rQ   r   rT   r   r5      s    
zBuildBackendHookCaller.__init__)rP   r   c                 c   s$   | j }|| _ z
dV  W 5 || _ X dS )ay  A context manager for temporarily overriding the default
        :ref:`subprocess runner <Subprocess Runners>`.

        :param runner: The new subprocess runner to use within the context.

        .. code-block:: python

            hook_caller = BuildBackendHookCaller(...)
            with hook_caller.subprocess_runner(quiet_subprocess_runner):
                ...
        N)rV   )r   rP   prevr   r   r   subprocess_runner   s
    
z(BuildBackendHookCaller.subprocess_runner)r   c                 C   s   |  di S )z>Return the list of optional features supported by the backend._supported_features
_call_hookrT   r   r   r   r[      s    z*BuildBackendHookCaller._supported_features)config_settingsr   c                 C   s   |  dd|iS )am  Get additional dependencies required for building a wheel.

        :param config_settings: The configuration settings for the build backend
        :returns: A list of :pep:`dependency specifiers <508>`.

        .. admonition:: Fallback

            If the build backend does not defined a hook with this name, an
            empty list will be returned.
        get_requires_for_build_wheelr^   r\   r   r^   r   r   r   r_      s     z3BuildBackendHookCaller.get_requires_for_build_wheelT)metadata_directoryr^   _allow_fallbackr   c                 C   s   |  dt|||dS )aS  Prepare a ``*.dist-info`` folder with metadata for this project.

        :param metadata_directory: The directory to write the metadata to
        :param config_settings: The configuration settings for the build backend
        :param _allow_fallback:
            Whether to allow the fallback to building a wheel and extracting
            the metadata from it. Should be passed as a keyword argument only.

        :returns: Name of the newly created subfolder within
                  ``metadata_directory``, containing the metadata.

        .. admonition:: Fallback

            If the build backend does not define a hook with this name and
            ``_allow_fallback`` is truthy, the backend will be asked to build a
            wheel via the ``build_wheel`` hook and the dist-info extracted from
            that will be returned.
         prepare_metadata_for_build_wheelra   r^   rb   r]   r   r   ra   r^   rb   r   r   r   rc      s    z7BuildBackendHookCaller.prepare_metadata_for_build_wheel)wheel_directoryr^   ra   r   c                 C   s(   |dk	rt |}| dt |||dS )a  Build a wheel from this project.

        :param wheel_directory: The directory to write the wheel to
        :param config_settings: The configuration settings for the build backend
        :param metadata_directory: The directory to reuse existing metadata from
        :returns:
            The name of the newly created wheel within ``wheel_directory``.

        .. admonition:: Interaction with fallback

            If the ``build_wheel`` hook was called in the fallback for
            :meth:`prepare_metadata_for_build_wheel`, the build backend would
            not be invoked. Instead, the previously built wheel will be copied
            to ``wheel_directory`` and the name of that file will be returned.
        Nbuild_wheelrg   r^   ra   r   r]   r   rg   r^   ra   r   r   r   rh      s    z"BuildBackendHookCaller.build_wheelc                 C   s   |  dd|iS )aw  Get additional dependencies required for building an editable wheel.

        :param config_settings: The configuration settings for the build backend
        :returns: A list of :pep:`dependency specifiers <508>`.

        .. admonition:: Fallback

            If the build backend does not defined a hook with this name, an
            empty list will be returned.
        get_requires_for_build_editabler^   r\   r`   r   r   r   rl   	  s     z6BuildBackendHookCaller.get_requires_for_build_editablec                 C   s   |  dt|||dS )aU  Prepare a ``*.dist-info`` folder with metadata for this project.

        :param metadata_directory: The directory to write the metadata to
        :param config_settings: The configuration settings for the build backend
        :param _allow_fallback:
            Whether to allow the fallback to building a wheel and extracting
            the metadata from it. Should be passed as a keyword argument only.
        :returns: Name of the newly created subfolder within
                  ``metadata_directory``, containing the metadata.

        .. admonition:: Fallback

            If the build backend does not define a hook with this name and
            ``_allow_fallback`` is truthy, the backend will be asked to build a
            wheel via the ``build_editable`` hook and the dist-info
            extracted from that will be returned.
        #prepare_metadata_for_build_editablerd   re   rf   r   r   r   rm     s    z:BuildBackendHookCaller.prepare_metadata_for_build_editablec                 C   s(   |dk	rt |}| dt |||dS )a  Build an editable wheel from this project.

        :param wheel_directory: The directory to write the wheel to
        :param config_settings: The configuration settings for the build backend
        :param metadata_directory: The directory to reuse existing metadata from
        :returns:
            The name of the newly created wheel within ``wheel_directory``.

        .. admonition:: Interaction with fallback

            If the ``build_editable`` hook was called in the fallback for
            :meth:`prepare_metadata_for_build_editable`, the build backend
            would not be invoked. Instead, the previously built wheel will be
            copied to ``wheel_directory`` and the name of that file will be
            returned.
        Nbuild_editableri   rj   rk   r   r   r   rn   ;  s    z%BuildBackendHookCaller.build_editablec                 C   s   |  dd|iS )zGet additional dependencies required for building an sdist.

        :returns: A list of :pep:`dependency specifiers <508>`.
        get_requires_for_build_sdistr^   r\   r`   r   r   r   ro   \  s     z3BuildBackendHookCaller.get_requires_for_build_sdist)sdist_directoryr^   r   c                 C   s   |  dt||dS )zBuild an sdist from this project.

        :returns:
            The name of the newly created sdist within ``wheel_directory``.
        build_sdist)rp   r^   re   )r   rp   r^   r   r   r   rq   h  s    
z"BuildBackendHookCaller.build_sdist)r:   r*   r   c           
   
   C   s  d| j i}| jr&tj| j}||d< t }d|i}t|t|ddd t	 .}| j
}| j|tt|||g| j|d W 5 Q R X tt|d}	|	d	rt|	d
d|	drt|	d
d|	dd| j | jd|	drt|	dp||	d W  5 Q R  S Q R X d S )NZ_PYPROJECT_HOOKS_BUILD_BACKENDZ_PYPROJECT_HOOKS_BACKEND_PATHr*   z
input.json   )indent)r   r   zoutput.jsonunsupportedr0    
no_backendZbackend_error)r1   r2   r3   Zhook_missingZmissing_hook_name
return_val)rO   r3   r=   pathsepr   tempfileTemporaryDirectoryr,   pjoinr   rQ   rV   r   r    rN   r.   getr;   r/   r9   )
r   r:   r*   r   r3   tdZ
hook_inputscriptpythondatar   r   r   r]   z  s6    






z!BuildBackendHookCaller._call_hook)NNN)N)NT)NN)N)NT)NN)N)N)r   r   r   r   r    r   r   r5   r   r
   rZ   r[   r   r	   r_   boolrc   rh   rl   rm   rn   ro   rq   r]   r   r   r   r   rM   ~   s      
   $  "   #  #  rM   )NN)NN)$r(   r=   rW   ry   
contextlibr   os.pathr   r   r{   
subprocessr   r   r   typingr   r	   r
   r   r   r   Z_in_processr   r   r   r    r,   r.   	Exceptionr/   r9   r;   rB   rD   rL   rM   r   r   r   r   <module>   sF    	    