3 igQ @sddlZddlZddlZddlZddlZddlZyddlmZWn ek r`ddl mZYnXddl m Z ddl m Z mZmZmZmZmZddlmZmZejeZdZdZGd d d eZdS) N)Thread)DistlibException)HTTPBasicAuthHandlerRequestHTTPPasswordMgrurlparse build_opener string_types)zip_dir ServerProxyzhttps://pypi.org/pypipypic@seZdZdZdZd*ddZddZdd Zd d Zd d Z ddZ ddZ d+ddZ d,ddZ d-ddZd.ddZddZd/ddZd0d d!Zd1d"d#Zd$d%Zd&d'Zd2d(d)ZdS)3 PackageIndexzc This class represents a package index compatible with PyPI, the Python Package Index. s.----------ThIs_Is_tHe_distlib_index_bouNdaRY_$Nc Cs|pt|_|jt|j\}}}}}}|s<|s<|s<|d krJtd|jd|_d|_d|_d|_t t j dR}xJd D]B} y(t j | dg||d } | d kr| |_PWqvtk rYqvXqvWWdQRXdS) z Initialise an instance. :param url: The URL of the index. If not specified, the URL for PyPI is used. httphttpszinvalid repository: %sNwgpggpg2z --version)stdoutstderrr)rr)rr) DEFAULT_INDEXurlread_configurationrrpassword_handler ssl_verifierrgpg_homeopenosdevnull subprocess check_callOSError) selfrschemenetlocpathparamsqueryfragZsinksrcr+8/tmp/pip-build-88gy_88q/pip/pip/_vendor/distlib/index.py__init__$s&   zPackageIndex.__init__cCsddlm}|S)zs Get the distutils command for interacting with PyPI configurations. :return: the command. r)_get_pypirc_command)utilr.)r"cmdr+r+r,r.As z PackageIndex._get_pypirc_commandcCsNddlm}||}|jd|_|jd|_|jdd|_|jd|j|_dS) z Read the PyPI access configuration as supported by distutils. This populates ``username``, ``password``, ``realm`` and ``url`` attributes from the configuration. r) _load_pypircusernamepasswordrealmr repositoryN)r/r1getr2r3r4r)r"r1cfgr+r+r,rIs    zPackageIndex.read_configurationcCs |jddlm}||dS)z Save the PyPI access configuration. You must have set ``username`` and ``password`` attributes before calling this method. r) _store_pypircN)check_credentialsr/r8)r"r8r+r+r,save_configurationVs zPackageIndex.save_configurationcCs\|jdks|jdkrtdt}t|j\}}}}}}|j|j||j|jt||_ dS)zp Check that ``username`` and ``password`` have been set, and raise an exception if not. Nz!username and password must be set) r2r3rrrr add_passwordr4rr)r"Zpm_r$r+r+r,r9_s zPackageIndex.check_credentialscCs\|j|j|j}d|d<|j|jg}|j|}d|d<|j|jg}|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. verifyz:actionZsubmit)r9validatetodictencode_requestitems send_request)r"metadatadrequestresponser+r+r,registerks  zPackageIndex.registercCsJx<|j}|sP|jdj}|j|tjd||fqW|jdS)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. zutf-8z%s: %sN)readlinedecoderstripappendloggerdebugclose)r"namestreamZoutbufr)r+r+r,_readers  zPackageIndex._readercCs|jdddg}|dkr|j}|r.|jd|g|dk rF|jdddgtj}tjj|tjj|d }|jd d d |d ||gt j ddj|||fS)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-fd2z--no-ttyNz --homedirz--batchz--passphrase-fd0z.ascz --detach-signz--armorz --local-userz--outputz invoking: %s ) rrextendtempfilemkdtemprr%joinbasenamerLrM)r"filenamesigner sign_passwordkeystorer0tdZsfr+r+r,get_sign_commands zPackageIndex.get_sign_commandc Cstjtjd}|dk r tj|d<g}g}tj|f|}t|jd|j|fd}|jt|jd|j|fd}|j|dk r|jj ||jj |j |j |j |j ||fS)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``. )rrNstdinr)targetargsr)rPIPEPopenrrQrstartrr`writerNwaitrX returncode) r"r0Z input_datakwargsrrpt1t2r+r+r, run_commands$     zPackageIndex.run_commandc CsD|j||||\}}|j||jd\}}} |dkr@td||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. zutf-8rz&sign command failed with error code %s)r_rmencoder) r"rZr[r\r]r0sig_filer*rrr+r+r, sign_files  zPackageIndex.sign_filesdistsourcecCs(|jtjj|s td||j|j}d} |rZ|jsJtj dn|j ||||} t |d} | j } WdQRXt j| j} t j| j} |jdd||| | ddtjj|| fg}| rt | d} | j }WdQRX|jd tjj| |ftjtjj| |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 signedrbZ file_upload1)z:actionZprotocol_versionfiletype pyversion md5_digest sha256_digestcontentZ gpg_signature)r9rr%existsrr>r?rrLwarningrprreadhashlibmd5 hexdigestsha256updaterYrKshutilrmtreedirnamer@rArB)r"rCrZr[r\rurvr]rDrofZ file_datarwrxfilesZsig_datarEr+r+r, upload_files>       zPackageIndex.upload_filec Cs|jtjj|s td|tjj|d}tjj|sFtd||j|j|j }}t |j }d d|fd|fg}d||fg}|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. znot a directory: %rz index.htmlz not found: %r:action doc_uploadrOversionry)rr)r9rr%isdirrrXrzr>rOrr getvaluer@rB) r"rCZdoc_dirfnrOrzip_datafieldsrrEr+r+r,upload_documentation!s        z!PackageIndex.upload_documentationcCsT|jdddg}|dkr|j}|r.|jd|g|jd||gtjddj||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-fdrRz--no-ttyNz --homedirz--verifyz invoking: %srT)rrrUrLrMrX)r"signature_filename data_filenamer]r0r+r+r,get_verify_command=szPackageIndex.get_verify_commandcCsH|jstd|j|||}|j|\}}}|dkr@td||dkS)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 unavailablerrz(verify command failed with error code %s)rr)rrrrm)r"rrr]r0r*rrr+r+r,verify_signatureUszPackageIndex.verify_signaturecCsp|dkrd}tjdn6t|ttfr0|\}}nd}tt|}tjd|t|d}|jt |}z|j } d} d} d} d} d | krt | d } |r|| | | xP|j | }|sP| t |7} |j||r|j|| d7} |r|| | | qWWd|jXWdQRX| dkr4| | kr4td | | f|rl|j}||kr`td ||||ftjd |dS)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. NzNo digest specifiedr~zDigest specified: %swbi rrzcontent-lengthzContent-Lengthz1retrieval incomplete: got only %d out of %d bytesz.%s digest mismatch for %s: expected %s, got %szDigest verified: %s)rLrM isinstancelisttuplegetattrr}rrBrinfointr|lenrfrrNrr)r"rdestfiledigest reporthookZdigesterZhasherZdfpZsfpheaders blocksizesizer|blocknumblockactualr+r+r, download_filensV             zPackageIndex.download_filecCs:g}|jr|j|j|jr(|j|jt|}|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). )rrKrr r)r"reqhandlersopenerr+r+r,rBs  zPackageIndex.send_requestcCsg}|j}xX|D]P\}}t|ttfs,|g}x2|D]*}|jd|d|jdd|jdfq2WqWx6|D].\}} } |jd|d|| fjdd| fqjW|jd|ddfdj|} d|} | tt| 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"zutf-8z8Content-Disposition: form-data; name="%s"; filename="%s"s smultipart/form-data; boundary=)z Content-typezContent-length) boundaryrrrrUrnrXstrrrr)r"rrpartsrkvaluesvkeyrZvaluebodyctrr+r+r,r@s2     zPackageIndex.encode_requestc CsBt|trd|i}t|jdd}z|j||p.dS|dXdS)NrOg@)timeoutandrN)rr r rsearch)r"ZtermsoperatorZ rpc_proxyr+r+r,rs  zPackageIndex.search)N)N)N)N)NNrqrrN)N)N)NN)N)__name__ __module__ __qualname____doc__rr-r.rr:r9rGrQr_rmrprrrrrrBr@rr+r+r+r,rs*      #  8   M+r)r}loggingrrrrV threadingr ImportErrordummy_threadingrcompatrrrrr r r/r r getLoggerrrLr DEFAULT_REALMobjectrr+r+r+r,s