o
    ä§ÊhJR  ã                   @   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zd dlmZ W n ey/   d dl	mZ Y nw 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 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.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	d*d d!„Zd,d"d#„Zd$d%„ Zd&d'„ Zd*d(d)„ZdS )-Ú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 | _|  ¡  t| jƒ\}}}}}}|s|s|s|dvr%td| j ƒ‚d| _d| _d| _d| _t	t
jdƒ�5}dD ]!}	ztj|	dg||d�}
|
dkrQ|	| _W  nW q: ty[   Y q:w W d  ƒ dS W d  ƒ dS 1 sow   Y  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   )ÚDEFAULT_INDEXÚurlÚread_configurationr   r   Úpassword_handlerÚssl_verifierr   Úgpg_homeÚopenÚosÚdevnullÚ
subprocessÚ
check_callÚOSError)Úselfr   ÚschemeÚnetlocÚpathÚparamsÚqueryÚfragÚsinkÚsÚrc© r.   ú?/var/www/html/env/lib/python3.10/site-packages/distlib/index.pyÚ__init__$   s4   
ÿþÿùý	"÷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)Údistutils.corer1   Údistutils.configr2   )r$   r1   r2   Údr.   r.   r/   Ú_get_pypirc_commandA   s   z PackageIndex._get_pypirc_commandc                 C   sR   |   ¡ }| j|_| ¡ }| d¡| _| d¡| _| dd¡| _| 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)r6   r   r:   Ú_read_pypircÚgetr7   r8   r9   )r$   ÚcÚcfgr.   r.   r/   r   K   s   zPackageIndex.read_configurationc                 C   s$   |   ¡  |  ¡ }| | 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_credentialsr6   Ú_store_pypircr7   r8   )r$   r=   r.   r.   r/   Úsave_configurationZ   s   zPackageIndex.save_configurationc                 C   s\   | j du s
| jdu rtdƒ‚tƒ }t| 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)
r7   r8   r   r   r   r   Úadd_passwordr9   r   r   )r$   ÚpmÚ_r&   r.   r.   r/   r?   f   s   zPackageIndex.check_credentialsc                 C   s\   |   ¡  | ¡  | ¡ }d|d< |  | ¡ g ¡}|  |¡}d|d< |  | ¡ g ¡}|  |¡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.
        Úverifyú:actionÚsubmit)r?   ÚvalidateÚtodictÚencode_requestÚitemsÚsend_request)r$   Úmetadatar5   ÚrequestÚresponser.   r.   r/   Úregisterr   s   


zPackageIndex.registerc                 C   sH   	 |  ¡ }|sn| d¡ ¡ }| |¡ t d||f ¡ q| ¡  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.
        Túutf-8z%s: %sN)ÚreadlineÚdecodeÚrstripÚappendÚloggerÚdebugÚclose)r$   ÚnameÚstreamÚoutbufr,   r.   r.   r/   Ú_reader†   s   	
úzPackageIndex._readerc              	   C   s˜   | j dddg}|du r| j}|r| d|g¡ |dur"| g d¢¡ t ¡ }tj |tj |¡d ¡}| dd	d
|d||g¡ t	 
dd |¡¡ ||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`.
        ú--status-fdÚ2ú--no-ttyNú	--homedir)z--batchz--passphrase-fdÚ0z.ascz--detach-signz--armorz--local-userz--outputúinvoking: %sú )r   r   ÚextendÚtempfileÚmkdtempr   r'   ÚjoinÚbasenamerV   rW   )r$   ÚfilenameÚsignerÚsign_passwordÚkeystoreÚcmdÚtdÚsfr.   r.   r/   Úget_sign_command˜   s   
ÿzPackageIndex.get_sign_commandc           	      C   s¸   t jt jdœ}|durt j|d< g }g }t j|fi |¤Ž}t| jd|j|fd�}| ¡  t| jd|j|fd�}| ¡  |durJ|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   NÚstdinr   )ÚtargetÚargsr   )r!   ÚPIPEÚPopenr   r\   r   Ústartr   rq   ÚwriterX   Úwaitrg   Ú
returncode)	r$   rm   Ú
input_dataÚkwargsr   r   ÚpÚt1Út2r.   r.   r/   Úrun_commandµ   s&   þ

zPackageIndex.run_commandc           
      C   sD   |   ||||¡\}}|  || 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.
        rQ   r   z&sign command failed with error code %s)rp   r   Úencoder   )
r$   ri   rj   rk   rl   rm   Úsig_filer-   r   r   r.   r.   r/   Ú	sign_fileØ   s   
ÿ
ÿÿzPackageIndex.sign_fileÚsdistÚsourcec              	   C   sN  |   ¡  tj |¡std| ƒ‚| ¡  | ¡ }d}	|r-| js%t 	d¡ n|  
||||¡}	t|dƒ�}
|
 ¡ }W d  ƒ n1 sAw   Y  t |¡ ¡ }t |¡ ¡ }| dd||||dœ¡ dtj |¡|fg}|	ršt|	dƒ�}
|
 ¡ }W d  ƒ n1 s€w   Y  | d	tj |	¡|f¡ t t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ÚrbÚfile_uploadÚ1)rF   Úprotocol_versionÚfiletypeÚ	pyversionÚ
md5_digestÚsha256_digestÚcontentÚgpg_signature)r?   r   r'   Úexistsr   rH   rI   r   rV   Úwarningr‚   r   ÚreadÚhashlibÚmd5Ú	hexdigestÚsha256Úupdaterh   rU   ÚshutilÚrmtreeÚdirnamerJ   rK   rL   )r$   rM   ri   rj   rk   r‰   rŠ   rl   r5   r�   ÚfÚ	file_datar‹   rŒ   ÚfilesÚsig_datarN   r.   r.   r/   Úupload_fileï   sH   
ÿ
ÿú
ÿÿ
zPackageIndex.upload_filec           
      C   sœ   |   ¡  tj |¡std| ƒ‚tj |d¡}tj |¡s#td| ƒ‚| ¡  |j|j	}}t
|ƒ ¡ }dd|fd|fg}d||fg}|  ||¡}	|  |	¡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)rF   Ú
doc_uploadrY   Úversionr�   )r?   r   r'   Úisdirr   rg   r�   rH   rY   r    r   ÚgetvaluerJ   rL   )
r$   rM   Údoc_dirÚfnrY   r    Úzip_dataÚfieldsrœ   rN   r.   r.   r/   Úupload_documentation(  s   ÿ
z!PackageIndex.upload_documentationc                 C   sT   | j dddg}|du r| j}|r| d|g¡ | d||g¡ t dd |¡¡ |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`.
        r]   r^   r_   Nr`   z--verifyrb   rc   )r   r   rd   rV   rW   rg   )r$   Úsignature_filenameÚdata_filenamerl   rm   r.   r.   r/   Úget_verify_commandD  s   zPackageIndex.get_verify_commandc                 C   sH   | j stdƒ‚|  |||¡}|  |¡\}}}|dv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 unavailable)r   r   z(verify command failed with error code %sr   )r   r   rª   r   )r$   r¨   r©   rl   rm   r-   r   r   r.   r.   r/   Úverify_signature\  s   ÿÿzPackageIndex.verify_signaturec              	   C   s†  |du rd}t  d¡ nt|ttfƒr|\}}nd}tt|ƒƒ }t  d| ¡ t|dƒ�a}|  t	|ƒ¡}zL| 
¡ }	d}
d}d}d}d	|	v rKt|	d
 ƒ}|rS|||
|ƒ 	 | |
¡}|s\n|t|ƒ7 }| |¡ |rn| |¡ |d7 }|rz|||
|ƒ qTW | ¡  n| ¡  w W d  ƒ n1 s�w   Y  |dkr¥||k r¥td||f ƒ‚|rÁ| ¡ }||kr¹td||||f ƒ‚t  d|¡ dS 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 specifiedr“   zDigest specified: %sÚwbi    éÿÿÿÿr   zcontent-lengthzContent-LengthTr   z1retrieval incomplete: got only %d out of %d bytesz.%s digest mismatch for %s: expected %s, got %szDigest verified: %s)rV   rW   Ú
isinstanceÚlistÚtupleÚgetattrr’   r   rL   r   ÚinfoÚintr‘   Úlenrw   r–   rX   r   r”   )r$   r   ÚdestfileÚdigestÚ
reporthookÚdigesterÚhasherÚdfpÚsfpÚheadersÚ	blocksizeÚsizer‘   ÚblocknumÚblockÚactualr.   r.   r/   Údownload_fileu  sf   



ö	æÿÿÿÿúzPackageIndex.download_filec                 C   s:   g }| j r| | j ¡ | jr| | j¡ t|Ž }| |¡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   rU   r   r	   r   )r$   ÚreqÚhandlersÚopenerr.   r.   r/   rL   Â  s   
zPackageIndex.send_requestc              
   C   sØ   g }| j }|D ]&\}}t|ttfƒs|g}|D ]}| d| d|  d¡d| d¡f¡ qq|D ]\}}	}
| d| d||	f  d¡d|
f¡ q0| d| d df¡ d |¡}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"rQ   ó    z8Content-Disposition: form-data; name="%s"; filename="%s"s   
s   multipart/form-data; boundary=)zContent-typezContent-length)Úboundaryr®   r¯   r°   rd   r€   rg   Ústrr´   r   r   )r$   r¦   rœ   ÚpartsrÇ   ÚkÚvaluesÚvÚkeyri   ÚvalueÚbodyÚctr¼   r.   r.   r/   rJ   Ò  sB   ÿûÿÿû

þzPackageIndex.encode_requestc                 C   sJ   t |tƒr	d|i}t| jdd�}z| ||pd¡W |dƒƒ  S |dƒƒ  w )NrY   g      @)ÚtimeoutÚandrX   )r®   r
   r   r   Úsearch)r$   ÚtermsÚoperatorÚ	rpc_proxyr.   r.   r/   rÓ   ý  s   
zPackageIndex.search)N)NNrƒ   r„   N)NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rÇ   r0   r6   r   rA   r?   rP   r\   rp   r   r‚   rž   r§   rª   r«   rÂ   rL   rJ   rÓ   r.   r.   r.   r/   r      s4    


ÿ

#
ÿ9
ÿ
ÿ
M+r   )r’   Úloggingr   r—   r!   re   Ú	threadingr   ÚImportErrorÚdummy_threadingÚ r   Úcompatr   r   r   r   r	   r
   Úutilr   r   r   Ú	getLoggerr×   rV   r   ÚDEFAULT_REALMÚobjectr   r.   r.   r.   r/   Ú<module>   s$   ÿ 
