U
    ee.                     @   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 dd	 Zd
d ZG dd deZG dd deZG dd deZG dd deZdddZdddZdd ZG dd dZdS )    N)contextmanager)abspath)join)STDOUT
check_callcheck_output   )_in_proc_script_pathc              	   K   s.   t |ddd}tj| |f| W 5 Q R X d S )Nwutf-8encoding)openjsondump)objpathkwargsf r   9/tmp/pip-unpacked-wheel-_41y_qkn/pyproject_hooks/_impl.py
write_json   s    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d ZdS )BackendUnavailablezEWill be raised if the backend cannot be imported in the hook process.c                 C   s
   || _ d S N	tracebackselfr   r   r   r   __init__   s    zBackendUnavailable.__init__N__name__
__module____qualname____doc__r    r   r   r   r   r      s   r   c                       s    e Zd ZdZ fddZ  ZS )BackendInvalidz)Will be raised if the backend is invalid.c                    s   t  | || _|| _d S r   )superr    backend_namebackend_path)r   r(   r)   message	__class__r   r   r       s    zBackendInvalid.__init__r"   r#   r$   r%   r    __classcell__r   r   r+   r   r&      s   r&   c                       s    e Zd ZdZ fddZ  ZS )HookMissingz>Will be raised on missing hooks (if a fallback can't be used).c                    s   t  | || _d S r   )r'   r    	hook_name)r   r0   r+   r   r   r    '   s    zHookMissing.__init__r-   r   r   r+   r   r/   %   s   r/   c                   @   s   e Zd ZdZdd ZdS )UnsupportedOperationzDMay be raised by build_sdist if the backend indicates that it can't.c                 C   s
   || _ d S r   r   r   r   r   r   r    .   s    zUnsupportedOperation.__init__Nr!   r   r   r   r   r1   ,   s   r1   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.
    )cwdenvN)osenvironcopyupdater   cmdr2   extra_environr3   r   r   r   default_subprocess_runner2   s    

r;   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.
    )r2   r3   stderrN)r4   r5   r6   r7   r   r   r8   r   r   r   quiet_subprocess_runner>   s    

r=   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)	r4   r   isabs
ValueErrorr   normpathr   normcasecommonprefix)source_tree	requested
abs_sourceabs_requestednorm_sourcenorm_requestedr   r   r   norm_and_checkJ   s    rI   c                   @   s   e Zd ZdZdddZedd Zd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#ddZd$ddZdd ZdS )%BuildBackendHookCallerzFA wrapper to call the build backend hooks for a source directory.
    Nc                    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   )rI   
source_dir).0pr   r   r   
<listcomp>|   s    z3BuildBackendHookCaller.__init__.<locals>.<listcomp>)	r;   r   rK   build_backendr)   _subprocess_runnersys
executablepython_executable)r   rK   rP   r)   runnerrT   r   rN   r   r    f   s    

zBuildBackendHookCaller.__init__c                 c   s$   | j }|| _ z
dV  W 5 || _ X dS )a,  A context manager for temporarily overriding the default
        :ref:`subprocess runner <Subprocess Runners>`.

        .. code-block:: python

            hook_caller = BuildBackendHookCaller(...)
            with hook_caller.subprocess_runner(quiet_subprocess_runner):
                ...
        N)rQ   )r   rU   prevr   r   r   subprocess_runner   s
    
z(BuildBackendHookCaller.subprocess_runnerc                 C   s   |  di S )z>Return the list of optional features supported by the backend._supported_features
_call_hookrN   r   r   r   rX      s    z*BuildBackendHookCaller._supported_featuresc                 C   s   |  dd|iS )a6  Get additional dependencies required for building a wheel.

        :returns: A list of :pep:`dependency specifiers <508>`.
        :rtype: list[str]

        .. admonition:: Fallback

            If the build backend does not defined a hook with this name, an
            empty list will be returned.
        get_requires_for_build_wheelconfig_settingsrY   r   r\   r   r   r   r[      s     z3BuildBackendHookCaller.get_requires_for_build_wheelTc                 C   s   |  dt|||dS )a  Prepare a ``*.dist-info`` folder with metadata for this project.

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

        .. 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metadata_directoryr\   _allow_fallbackrZ   r   r   r`   r\   ra   r   r   r   r^      s
    z7BuildBackendHookCaller.prepare_metadata_for_build_wheelc                 C   s(   |dk	rt |}| dt |||dS )a  Build a wheel from this project.

        :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wheel_directoryr\   r`   r   rZ   r   rf   r\   r`   r   r   r   rd      s    z"BuildBackendHookCaller.build_wheelc                 C   s   |  dd|iS )a@  Get additional dependencies required for building an editable wheel.

        :returns: A list of :pep:`dependency specifiers <508>`.
        :rtype: list[str]

        .. 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\   rY   r]   r   r   r   ri      s     z6BuildBackendHookCaller.get_requires_for_build_editablec                 C   s   |  dt|||dS )a  Prepare a ``*.dist-info`` folder with metadata for this project.

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

        .. 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_editabler_   rb   rc   r   r   r   rj      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.

        :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_editablere   rg   rh   r   r   r   rk      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>`.
        :rtype: list[str]
        get_requires_for_build_sdistr\   rY   r]   r   r   r   rl     s     z3BuildBackendHookCaller.get_requires_for_build_sdistc                 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)sdist_directoryr\   rb   )r   rn   r\   r   r   r   rm     s    z"BuildBackendHookCaller.build_sdistc           
   
   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rt| j | j|	ddd|	drt|	dp||	d W  5 Q R  S Q R X d S )NPEP517_BUILD_BACKENDPEP517_BACKEND_PATHr   z
input.json   )indent)r2   r:   zoutput.jsonunsupportedr    
no_backendbackend_invalidbackend_error)r(   r)   r*   hook_missingZmissing_hook_name
return_val)rP   r)   r4   pathsepr   tempfileTemporaryDirectoryr   pjoinr	   rT   rQ   r   strrK   r   getr1   r   r&   r/   )
r   r0   r   r:   r)   td
hook_inputscriptpythondatar   r   r   rZ   )  s8    





z!BuildBackendHookCaller._call_hook)NNN)N)NT)NN)N)NT)NN)N)N)r"   r#   r$   r%   r    r   rW   rX   r[   r^   rd   ri   rj   rk   rl   rm   rZ   r   r   r   r   rJ   b   s2      


  
  

  
  



rJ   )NN)NN)r   r4   rR   r{   
contextlibr   os.pathr   r   r}   
subprocessr   r   r   Z_in_processr	   r   r   	Exceptionr   r&   r/   r1   r;   r=   rI   rJ   r   r   r   r   <module>   s$   

