
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
ÝPf]R  ã               @   sÈ   d dl Z d dlZd dlZd dlZd dlZd dlZyd dlmZ W n  ek
r`   d dl	mZ Y nX ddl
mZ ddlmZmZmZmZmZmZ ddlmZmZmZ ejeƒZdZdZG d	d
„ d
eƒZdS )é    N)ÚThreadé   )ÚDistlibException)ÚHTTPBasicAuthHandlerÚRequestÚHTTPPasswordMgrÚurlparseÚbuild_openerÚstring_types)Úcached_propertyÚzip_dirÚServerProxyzhttps://pypi.python.org/pypiÚpypic               @   s¶   e Zd ZdZdZd*dd„Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zd+dd„Zd,dd„Zd-dd„Zd.dd„Zdd„ Zd/dd„Zd0d d!„Zd1d"d#„Zd$d%„ Zd&d'„ Zd2d(d)„ZdS )3ÚPackageIndexzc
    This class represents a package index compatible with PyPI, the Python
    Package Index.
    s.   ----------ThIs_Is_tHe_distlib_index_bouNdaRY_$Nc             C   sÐ   |pt | _| jƒ  t| jƒ\}}}}}}|s<|s<|s<|dkrJtd| j ƒ‚d| _d| _d| _d| _d| _	t
tjdƒ�R}xJdD ]B}	y(tj|	dg||d	�}
|
d
kr¦|	| _P W q| tk
r¼   Y q|X q|W W dQ R X dS )z”
        Initialise an instance.

        :param url: The URL of the index. If not specified, the URL for PyPI is
                    used.
        ÚhttpÚhttpszinvalid repository: %sNÚwÚgpgÚgpg2z	--version)ÚstdoutÚstderrr   )r   r   )r   r   )ÚDEFAULT_INDEXÚurlÚread_configurationr   r   Úpassword_handlerÚssl_verifierr   Úgpg_homeÚ	rpc_proxyÚopenÚosÚdevnullÚ
subprocessZ
check_callÚOSError)Úselfr   ÚschemeÚnetlocÚpathZparamsZqueryZfragZsinkÚsÚrc© r)   ú/usr/lib/python3.6/index.pyÚ__init__$   s(    

zPackageIndex.__init__c             C   s&   ddl m} ddlm} |ƒ }||ƒS )zs
        Get the distutils command for interacting with PyPI configurations.
        :return: the command.
        r   )ÚDistribution)ÚPyPIRCCommand)Zdistutils.corer,   Zdistutils.configr-   )r#   r,   r-   Údr)   r)   r*   Ú_get_pypirc_commandB   s    z PackageIndex._get_pypirc_commandc             C   sR   | j ƒ }| j|_|jƒ }|jdƒ| _|jdƒ| _|jddƒ| _|jd| jƒ| _dS )zç
        Read the PyPI access configuration as supported by distutils, getting
        PyPI to do the actual work. This populates ``username``, ``password``,
        ``realm`` and ``url`` attributes from the configuration.
        ÚusernameÚpasswordÚrealmr   Ú
repositoryN)r/   r   r3   Z_read_pypircÚgetr0   r1   r2   )r#   ÚcZcfgr)   r)   r*   r   L   s    zPackageIndex.read_configurationc             C   s$   | j ƒ  | jƒ }|j| j| jƒ dS )zÍ
        Save the PyPI access configuration. You must have set ``username`` and
        ``password`` attributes before calling this method.

        Again, distutils is used to do the actual work.
        N)Úcheck_credentialsr/   Z_store_pypircr0   r1   )r#   r5   r)   r)   r*   Úsave_configuration[   s    zPackageIndex.save_configurationc             C   s\   | j dks| jdkrtdƒ‚tƒ }t| jƒ\}}}}}}|j| j|| j | jƒ t|ƒ| _	dS )zp
        Check that ``username`` and ``password`` have been set, and raise an
        exception if not.
        Nz!username and password must be set)
r0   r1   r   r   r   r   Zadd_passwordr2   r   r   )r#   ZpmÚ_r%   r)   r)   r*   r6   g   s    zPackageIndex.check_credentialsc             C   s\   | j ƒ  |jƒ  |jƒ }d|d< | j|jƒ g ƒ}| j|ƒ}d|d< | j|jƒ g ƒ}| j|ƒS )aq  
        Register a distribution on PyPI, using the provided metadata.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the distribution to be
                         registered.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        Zverifyz:actionZsubmit)r6   ÚvalidateÚtodictÚencode_requestÚitemsÚsend_request)r#   Úmetadatar.   ÚrequestZresponser)   r)   r*   Úregisters   s    

zPackageIndex.registerc             C   sJ   x<|j ƒ }|sP |jdƒjƒ }|j|ƒ tjd||f ƒ qW |jƒ  dS )ar  
        Thread runner for reading lines of from a subprocess into a buffer.

        :param name: The logical name of the stream (used for logging only).
        :param stream: The stream to read from. This will typically a pipe
                       connected to the output stream of a subprocess.
        :param outbuf: The list to append the read lines to.
        zutf-8z%s: %sN)ÚreadlineÚdecodeÚrstripÚappendÚloggerÚdebugÚclose)r#   ÚnameÚstreamZoutbufr'   r)   r)   r*   Ú_reader‡   s    	
zPackageIndex._readerc             C   sš   | j dddg}|dkr| j}|r.|jd|gƒ |dk	rF|jdddgƒ tjƒ }tjj|tjj|ƒd	 ƒ}|jd
dd|d||gƒ t	j
ddj|ƒƒ ||fS )a‰  
        Return a suitable command for signing a file.

        :param filename: The pathname to the file to be signed.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: The signing command as a list suitable to be
                 passed to :class:`subprocess.Popen`.
        z--status-fdÚ2z--no-ttyNz	--homedirz--batchz--passphrase-fdÚ0z.ascz--detach-signz--armorz--local-userz--outputzinvoking: %sú )r   r   ÚextendÚtempfileZmkdtempr   r&   ÚjoinÚbasenamerE   rF   )r#   ÚfilenameÚsignerÚsign_passwordÚkeystoreÚcmdZtdZsfr)   r)   r*   Úget_sign_command™   s    
zPackageIndex.get_sign_commandc       	      C   s´   t jt jdœ}|dk	r t j|d< g }g }t j|f|Ž}t| jd|j|fd�}|jƒ  t| jd|j|fd�}|jƒ  |dk	r�|jj	|ƒ |jj
ƒ  |jƒ  |jƒ  |jƒ  |j||fS )aæ  
        Run a command in a child process , passing it any input data specified.

        :param cmd: The command to run.
        :param input_data: If specified, this must be a byte string containing
                           data to be sent to the child process.
        :return: A tuple consisting of the subprocess' exit code, a list of
                 lines read from the subprocess' ``stdout``, and a list of
                 lines read from the subprocess' ``stderr``.
        )r   r   NÚstdinr   )ÚtargetÚargsr   )r!   ÚPIPEÚPopenr   rJ   r   Ústartr   rX   ÚwriterG   ÚwaitrP   Ú
returncode)	r#   rV   Z
input_dataÚkwargsr   r   ÚpZt1Zt2r)   r)   r*   Úrun_command¶   s$    


zPackageIndex.run_commandc       
      C   sD   | j ||||ƒ\}}| j||jdƒƒ\}}}	|dkr@td| ƒ‚|S )aR  
        Sign a file.

        :param filename: The pathname to the file to be signed.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param keystore: The path to a directory which contains the keys
                         used in signing. If not specified, the instance's
                         ``gpg_home`` attribute is used instead.
        :return: The absolute pathname of the file where the signature is
                 stored.
        zutf-8r   z&sign command failed with error code %s)rW   rc   Úencoder   )
r#   rR   rS   rT   rU   rV   Úsig_filer(   r   r   r)   r)   r*   Ú	sign_fileÙ   s    

zPackageIndex.sign_fileÚsdistÚsourcec             C   s(  | j ƒ  tjj|ƒs td| ƒ‚|jƒ  |jƒ }d}	|rZ| jsJtj	dƒ n| j
||||ƒ}	t|dƒ�}
|
jƒ }W dQ R X tj|ƒjƒ }tj|ƒjƒ }|jdd||||dœƒ dtjj|ƒ|fg}|	�rt|	dƒ�}
|
jƒ }W dQ R X |jd	tjj|	ƒ|fƒ tjtjj|	ƒƒ | j|jƒ |ƒ}| j|ƒS )
a´  
        Upload a release file to the index.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the file to be uploaded.
        :param filename: The pathname of the file to be uploaded.
        :param signer: The identifier of the signer of the file.
        :param sign_password: The passphrase for the signer's
                              private key used for signing.
        :param filetype: The type of the file being uploaded. This is the
                        distutils command which produced that file, e.g.
                        ``sdist`` or ``bdist_wheel``.
        :param pyversion: The version of Python which the release relates
                          to. For code compatible with any Python, this would
                          be ``source``, otherwise it would be e.g. ``3.2``.
        :param keystore: The path to a directory which contains the keys
                         used in signing. If not specified, the instance's
                         ``gpg_home`` attribute is used instead.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        znot found: %sNz)no signing program available - not signedÚrbZfile_uploadÚ1)z:actionZprotocol_versionÚfiletypeÚ	pyversionÚ
md5_digestÚsha256_digestÚcontentZgpg_signature)r6   r   r&   Úexistsr   r9   r:   r   rE   Zwarningrf   r   ÚreadÚhashlibÚmd5Ú	hexdigestZsha256ÚupdaterQ   rD   ÚshutilZrmtreeÚdirnamer;   r<   r=   )r#   r>   rR   rS   rT   rk   rl   rU   r.   re   ÚfZ	file_datarm   rn   ÚfilesZsig_datar?   r)   r)   r*   Úupload_fileð   s>    

zPackageIndex.upload_filec       
      C   sœ   | j ƒ  tjj|ƒs td| ƒ‚tjj|dƒ}tjj|ƒsFtd| ƒ‚|jƒ  |j|j	 }}t
|ƒjƒ }d	d|fd|fg}d||fg}| j||ƒ}	| j|	ƒS )
a2  
        Upload documentation to the index.

        :param metadata: A :class:`Metadata` instance defining at least a name
                         and version number for the documentation to be
                         uploaded.
        :param doc_dir: The pathname of the directory which contains the
                        documentation. This should be the directory that
                        contains the ``index.html`` for the documentation.
        :return: The HTTP response received from PyPI upon submission of the
                request.
        znot a directory: %rz
index.htmlznot found: %rú:actionÚ
doc_uploadrH   Úversionro   )r{   r|   )r6   r   r&   Úisdirr   rP   rp   r9   rH   r}   r   Úgetvaluer;   r=   )
r#   r>   Zdoc_dirÚfnrH   r}   Zzip_dataÚfieldsry   r?   r)   r)   r*   Úupload_documentation)  s    z!PackageIndex.upload_documentationc             C   sT   | j dddg}|dkr| j}|r.|jd|gƒ |jd||gƒ tjddj|ƒƒ |S )	a|  
        Return a suitable command for verifying a file.

        :param signature_filename: The pathname to the file containing the
                                   signature.
        :param data_filename: The pathname to the file containing the
                              signed data.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: The verifying command as a list suitable to be
                 passed to :class:`subprocess.Popen`.
        z--status-fdrK   z--no-ttyNz	--homedirz--verifyzinvoking: %srM   )r   r   rN   rE   rF   rP   )r#   Úsignature_filenameÚdata_filenamerU   rV   r)   r)   r*   Úget_verify_commandE  s    zPackageIndex.get_verify_commandc             C   sH   | j stdƒ‚| j|||ƒ}| j|ƒ\}}}|dkr@td| ƒ‚|dkS )a6  
        Verify a signature for a file.

        :param signature_filename: The pathname to the file containing the
                                   signature.
        :param data_filename: The pathname to the file containing the
                              signed data.
        :param keystore: The path to a directory which contains the keys
                         used in verification. If not specified, the
                         instance's ``gpg_home`` attribute is used instead.
        :return: True if the signature was verified, else False.
        z0verification unavailable because gpg unavailabler   r   z(verify command failed with error code %s)r   r   )r   r   r…   rc   )r#   rƒ   r„   rU   rV   r(   r   r   r)   r)   r*   Úverify_signature]  s    zPackageIndex.verify_signaturec             C   sp  |dkrd}t jdƒ n6t|ttfƒr0|\}}nd}tt|ƒƒ }t jd| ƒ t|dƒ�²}| jt	|ƒƒ}z’|j
ƒ }	d}
d}d}d}d	|	kr–t|	d
 ƒ}|r¦|||
|ƒ xP|j|
ƒ}|s¸P |t|ƒ7 }|j|ƒ |rÜ|j|ƒ |d7 }|r¨|||
|ƒ q¨W W d|jƒ  X W dQ R X |dk�r4||k �r4td||f ƒ‚|�rl|jƒ }||k�r`td||||f ƒ‚t jd|ƒ dS )a  
        This is a convenience method for downloading a file from an URL.
        Normally, this will be a file from the index, though currently
        no check is made for this (i.e. a file can be downloaded from
        anywhere).

        The method is just like the :func:`urlretrieve` function in the
        standard library, except that it allows digest computation to be
        done during download and checking that the downloaded data
        matched any expected value.

        :param url: The URL of the file to be downloaded (assumed to be
                    available via an HTTP GET request).
        :param destfile: The pathname where the downloaded file is to be
                         saved.
        :param digest: If specified, this must be a (hasher, value)
                       tuple, where hasher is the algorithm used (e.g.
                       ``'md5'``) and ``value`` is the expected value.
        :param reporthook: The same as for :func:`urlretrieve` in the
                           standard library.
        NzNo digest specifiedrs   zDigest specified: %sÚwbi    r   r   zcontent-lengthzContent-Lengthz1retrieval incomplete: got only %d out of %d bytesz.%s digest mismatch for %s: expected %s, got %szDigest verified: %séÿÿÿÿ)rE   rF   Ú
isinstanceÚlistÚtupleÚgetattrrr   r   r=   r   ÚinfoÚintrq   Úlenr^   ru   rG   r   rt   )r#   r   ÚdestfileZdigestZ
reporthookZdigesterZhasherZdfpZsfpÚheadersZ	blocksizeÚsizerq   ZblocknumÚblockÚactualr)   r)   r*   Údownload_filev  sV    




zPackageIndex.download_filec             C   s:   g }| j r|j| j ƒ | jr(|j| jƒ t|Ž }|j|ƒS )zÝ
        Send a standard library :class:`Request` to PyPI and return its
        response.

        :param req: The request to send.
        :return: The HTTP response from PyPI (a standard library HTTPResponse).
        )r   rD   r   r	   r   )r#   ZreqZhandlersÚopenerr)   r)   r*   r=   Ã  s    zPackageIndex.send_requestc             C   sä   g }| j }xX|D ]P\}}t|ttfƒs,|g}x2|D ]*}|jd| d| jdƒd|jdƒfƒ q2W qW x6|D ].\}}	}
|jd| d||	f jdƒd|
fƒ qjW |jd| d dfƒ dj|ƒ}d| }|tt|ƒƒdœ}t	| j
||ƒS )	a&  
        Encode fields and files for posting to an HTTP server.

        :param fields: The fields to send as a list of (fieldname, value)
                       tuples.
        :param files: The files to send as a list of (fieldname, filename,
                      file_bytes) tuple.
        s   --z)Content-Disposition: form-data; name="%s"zutf-8ó    z8Content-Disposition: form-data; name="%s"; filename="%s"s   
s   multipart/form-data; boundary=)zContent-typezContent-length)Úboundaryr‰   rŠ   r‹   rN   rd   rP   Ústrr�   r   r   )r#   r�   ry   Úpartsr˜   ÚkÚvaluesÚvÚkeyrR   ÚvalueZbodyZctr‘   r)   r)   r*   r;   Ó  s2    


zPackageIndex.encode_requestc             C   s>   t |tƒrd|i}| jd kr,t| jdd�| _| jj||p:dƒS )NrH   g      @)ZtimeoutÚand)r‰   r
   r   r   r   Úsearch)r#   ZtermsÚoperatorr)   r)   r*   r¡   þ  s
    

zPackageIndex.search)N)N)N)N)NNrg   rh   N)N)N)NN)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r˜   r+   r/   r   r7   r6   r@   rJ   rW   rc   rf   rz   r‚   r…   r†   r•   r=   r;   r¡   r)   r)   r)   r*   r      s*   



#
 
8


M+r   )rr   Zloggingr   rv   r!   rO   Z	threadingr   ÚImportErrorZdummy_threadingÚ r   Úcompatr   r   r   r   r	   r
   Úutilr   r   r   Z	getLoggerr£   rE   r   ZDEFAULT_REALMÚobjectr   r)   r)   r)   r*   Ú<module>   s     
