o d_Q@sddlZddlZddlZddlZddlZddlZzddlmZWney/ddl mZYnwddl m Z ddl m Z mZmZmZmZmZddlmZmZeeZdZdZGd 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*ddZ  d+ddZddZ d*ddZ d*d d!Zd,d"d#Zd$d%Zd&d'Zd*d(d)ZdS)- PackageIndexzc This class represents a package index compatible with PyPI, the Python Package Index. s.----------ThIs_Is_tHe_distlib_index_bouNdaRY_$Nc Cs|pt|_|t|j\}}}}}}|s|s|s|dvr%td|jd|_d|_d|_d|_t t j d5}dD]!} zt j | dg||d} | dkrQ| |_WnWq:ty[Yq:wWddSWddS1sowYdS) z Initialise an instance. :param url: The URL of the index. If not specified, the URL for PyPI is used. )httphttpszinvalid repository: %sNw)gpggpg2z --versionstdoutstderrr) DEFAULT_INDEXurlread_configurationrrpassword_handler ssl_verifierrgpg_homeopenosdevnull subprocess check_callOSError) selfrschemenetlocpathparamsqueryfragsinksrcr-//usr/lib/python3/dist-packages/distlib/index.py__init__$s4    "zPackageIndex.__init__cCsddlm}|S)zs Get the distutils command for interacting with PyPI configurations. :return: the command. r)_get_pypirc_command)utilr0)r#cmdr-r-r.r0As z PackageIndex._get_pypirc_commandcCsNddlm}||}|d|_|d|_|dd|_|d|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)r1r3getr4r5r6r)r#r3cfgr-r-r.rIs   zPackageIndex.read_configurationcCs |ddlm}||dS)z Save the PyPI access configuration. You must have set ``username`` and ``password`` attributes before calling this method. r) _store_pypircN)check_credentialsr1r:)r#r:r-r-r.save_configurationVs  zPackageIndex.save_configurationcCs\|jdus |jdurtdt}t|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) r4r5rrrr add_passwordr6rr)r#pm_r%r-r-r.r;_s zPackageIndex.check_credentialscCs\|||}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:actionsubmit)r;validatetodictencode_requestitems send_request)r#metadatadrequestresponser-r-r.registerks   zPackageIndex.registercCsH |}|sn|d}||td||fq|dS)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. Tutf-8z%s: %sN)readlinedecoderstripappendloggerdebugclose)r#namestreamoutbufr+r-r-r._readers   zPackageIndex._readerc Cs|jdddg}|dur|j}|r|d|g|dur"|gdt}tj|tj|d}|dd d |d ||gt d d |||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`. --status-fd2--no-ttyN --homedir)z--batchz--passphrase-fd0z.ascz --detach-signz--armorz --local-userz--output invoking: %s ) rrextendtempfilemkdtemprr&joinbasenamerRrS)r#filenamesigner sign_passwordkeystorer2tdsfr-r-r.get_sign_commands zPackageIndex.get_sign_commandc Cstjtjd}|durtj|d<g}g}tj|fi|}t|jd|j|fd}|t|jd|j|fd}||durJ|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``. rNstdinr)targetargsr)r PIPEPopenrrXrstartrrlwriterTwaitrc returncode) r#r2 input_datakwargsrrpt1t2r-r-r. run_commands&     zPackageIndex.run_commandc CsD|||||\}}|||d\}}} |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. rMrz&sign command failed with error code %s)rkrzencoder) r#rerfrgrhr2sig_filer,rrr-r-r. sign_files  zPackageIndex.sign_filesdistsourcec CsN|tj|std|||}d} |r-|js%t dn| ||||} t |d } | } Wdn1sAwYt | } t | } |dd||| | ddtj|| fg}| rt | d } | }Wdn1swY|d tj| |fttj| |||}||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 signedrb file_upload1)rAprotocol_versionfiletype pyversion md5_digest sha256_digestcontent gpg_signature)r;rr&existsrrCrDrrRwarningr}rreadhashlibmd5 hexdigestsha256updaterdrQshutilrmtreedirnamerErFrG)r#rHrerfrgrrrhrIr|f file_datarrfilessig_datarJr-r-r. upload_filesH         zPackageIndex.upload_filec Cs|tj|std|tj|d}tj|s#td|||j|j }}t | }dd|fd|fg}d||fg}| ||} | | 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)rA doc_uploadrUversionr)r;rr&isdirrrcrrCrUrr getvaluerErG) r#rHdoc_dirfnrUrzip_datafieldsrrJr-r-r.upload_documentation!s         z!PackageIndex.upload_documentationcCsT|jdddg}|dur|j}|r|d|g|d||gtdd||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`. rYrZr[Nr\z--verifyr^r_)rrr`rRrSrc)r#signature_filename data_filenamerhr2r-r-r.get_verify_command=szPackageIndex.get_verify_commandcCsH|jstd||||}||\}}}|dvr 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 unavailable)rrz(verify command failed with error code %sr)rrrrz)r#rrrhr2r,rrr-r-r.verify_signatureUszPackageIndex.verify_signaturec Cs|dur d}tdnt|ttfr|\}}nd}tt|}td|t|da}|t |}zL| } d} d} d} d} d | vrKt | d } |rS|| | |  | | }|s\n| t |7} |||rn||| d 7} |rz|| | | qTW|n|wWdn1swY| dkr| | krtd | | f|r|}||krtd||||ftd|dSdS)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 specifiedrzDigest specified: %swbi rzcontent-lengthzContent-LengthTrz1retrieval incomplete: got only %d out of %d bytesz.%s digest mismatch for %s: expected %s, got %szDigest verified: %s)rRrS isinstancelisttuplegetattrrrrGrinfointrlenrrrrTrr)r#rdestfiledigest reporthookdigesterhasherdfpsfpheaders blocksizesizerblocknumblockactualr-r-r. download_filensf            zPackageIndex.download_filecCs:g}|jr ||j|jr||jt|}||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). )rrQrr r)r#reqhandlersopenerr-r-r.rGs   zPackageIndex.send_requestc Csg}|j}|D]&\}}t|ttfs|g}|D]}|d|d|dd|dfqq|D]\}} } |d|d|| fdd| fq0|d|ddfd|} 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"rMz8Content-Disposition: form-data; name="%s"; filename="%s"s smultipart/form-data; boundary=)z Content-typezContent-length) boundaryrrrr`r{rcstrrrr)r#rrpartsrkvaluesvkeyrevaluebodyctrr-r-r.rEsB    zPackageIndex.encode_requestcCsJt|tr d|i}t|jdd}z|||pdW|dS|dw)NrUg@)timeoutandrT)rr r rsearch)r#termsoperator rpc_proxyr-r-r.rs zPackageIndex.search)N)NNr~rN)NN)__name__ __module__ __qualname____doc__rr/r0rr<r;rLrXrkrzr}rrrrrrGrErr-r-r-r.rs4      # 9  M+r)rloggingrrr ra threadingr ImportErrordummy_threadingrcompatrrrrr r r1r r getLoggerrrRr DEFAULT_REALMobjectrr-r-r-r.s$