U
    tD7hš¥  ã                   @   sª  d Z ddlZddlZddlZddlZddlZddlZ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mZmZmZ ddlZddlmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z" ddlm#Z# ddl$m%Z% dd	l&m'Z' dd
l(m)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/ e0Z1e 2d¡Z3e 2dej4¡Z5e 2d¡Z6e 2dej4¡j7Z8d 9¡ Z:ddddgZ;dZ<dZ=e=j>dj>ej?Ž edZ@dd„ ZAdd„ ZBdd„ ZCdGd d„ZDdHd!d"„ZEdId#d$„ZFdedfd%d„ZGdJd&d'„ZHd(d)„ ZIe 2d*ej4¡ZJeId+d,„ ƒZKG d-d.„ d.ƒZLG d/d0„ d0eLƒZMG d1d„ deƒZNe 2d2¡jOZPd3d4„ ZQd5d6„ ZRdKd7d8„ZSd9d:„ ZTG d;d<„ d<ƒZUG d=d>„ d>ejVƒZWejXjYfd?d@„ZZdAdB„ Z[eSe<ƒeZƒZZdCdD„ Z\dEdF„ Z]dS )Lz#PyPI and direct package downloadingé    N©Úwraps)Úsix)ÚurllibÚhttp_clientÚconfigparserÚmap)ÚCHECKOUT_DISTÚDistributionÚBINARY_DISTÚnormalize_pathÚSOURCE_DISTÚEnvironmentÚfind_distributionsÚ	safe_nameÚsafe_versionÚto_filenameÚRequirementÚDEVELOP_DISTÚEGG_DIST)Ússl_support)Úlog)ÚDistutilsError)Ú	translate)Úget_all_headers)Úunescape)ÚWheelz^egg=([-A-Za-z0-9_.+!]+)$zhref\s*=\s*['"]?([^'"> ]+)zƒ<a href="([^"#]+)">([^<]+)</a>\n\s+\(<a (?:title="MD5 hash"\n\s+)href="[^?]+\?:action=show_md5&amp;digest=([0-9a-f]{32})">md5</a>\)z([-+.a-z0-9]{2,}):z.tar.gz .tar.bz2 .tar .zip .tgzÚPackageIndexÚdistros_for_urlÚparse_bdist_wininstÚinterpret_distro_nameé   z<setuptools/{setuptools.__version__} Python-urllib/{py_major}z{}.{})Zpy_majorÚ
setuptoolsc                 C   s4   zt  | ¡W S  tk
r.   td| f ƒ‚Y nX d S )Nz1Not a URL, existing file, or requirement spec: %r)r   ÚparseÚ
ValueErrorr   )Úspec© r&   ú:/usr/lib/python3/dist-packages/setuptools/package_index.pyÚparse_requirement_arg6   s    ÿr(   c                 C   s°   |   ¡ }d\}}}| d¡r¦| d¡r8| dd… }d}nn| dd¡rb| d	d
… }| dd… }d}nD| d¡r~| dd… }d}n(| dd¡r¦| d	d
… }| dd… }d}|||fS )z=Return (base,pyversion) or (None,None) for possible .exe name)NNNú.exez
.win32.exeNiöÿÿÿZwin32z	.win32-pyiðÿÿÿiùÿÿÿéüÿÿÿz.win-amd64.exeiòÿÿÿz	win-amd64z.win-amd64-pyiìÿÿÿ)ÚlowerÚendswithÚ
startswith)Únamer+   ÚbaseÚpy_verZplatr&   r&   r'   r   ?   s$    



c           	      C   sx   t j | ¡}|\}}}}}}t j | d¡d ¡}|dkrX|dkrXt j | d¡d ¡}d|krp| dd¡\}}||fS )Nú/éÿÿÿÿzsourceforge.netÚdownloadéþÿÿÿú#é   )r   r#   ÚurlparseÚunquoteÚsplit)	ÚurlÚpartsÚschemeÚserverÚpathZ
parametersÚqueryÚfragmentr/   r&   r&   r'   Úegg_info_for_urlW   s    rA   c                 c   s\   t | ƒ\}}t| ||ƒD ]
}|V  q|rXt |¡}|rXt| | d¡|tdD ]
}|V  qLdS )zEYield egg or source distribution objects that might be found at a URLr6   )Ú
precedenceN)rA   Údistros_for_locationÚEGG_FRAGMENTÚmatchr    Úgroupr	   )r:   Úmetadatar/   r@   ÚdistrE   r&   r&   r'   r   b   s    
   ÿ
c                 C   sä   |  d¡r|dd… }|  d¡r8d|kr8t | ||¡gS |  d¡rxd|krxt|ƒ}| ¡ s^g S t| |j|jtd dgS |  d	¡rªt|ƒ\}}}|dk	rªt	| |||t
|ƒS tD ]0}|  |¡r®|dt|ƒ … }t	| ||ƒ  S q®g S )
z:Yield egg or source distribution objects based on basenameú.egg.zipNr*   z.eggú-z.whlr6   )ÚlocationÚproject_nameÚversionrB   r)   )r,   r
   Zfrom_locationr   Zis_compatiblerL   rM   r   r   r    r   Ú
EXTENSIONSÚlen)rK   ÚbasenamerG   ZwheelZwin_baser0   ÚplatformZextr&   r&   r'   rC   p   s<    
û
     ÿ
rC   c                 C   s   t t| ƒtj | ¡|ƒS )zEYield possible egg or source distribution objects based on a filename)rC   r   Úosr>   rP   )ÚfilenamerG   r&   r&   r'   Údistros_for_filename‘   s
     
 ÿrT   c              
   c   s|   |  d¡}|s,tdd„ |dd… D ƒƒr,dS tdt|ƒd ƒD ]8}t| |d |d|… ¡d ||d… ¡|||dV  q>dS )zØGenerate alternative interpretations of a source distro name

    Note: if `location` is a filesystem filename, you should call
    ``pkg_resources.normalize_path()`` on it before passing it to this
    routine!
    rJ   c                 s   s   | ]}t  d |¡V  qdS )z	py\d\.\d$N)ÚrerE   )Ú.0Úpr&   r&   r'   Ú	<genexpr>¯   s     z(interpret_distro_name.<locals>.<genexpr>é   Nr6   )Ú
py_versionrB   rQ   )r9   ÚanyÚrangerO   r
   Újoin)rK   rP   rG   rZ   rB   rQ   r;   rW   r&   r&   r'   r    ˜   s    
    ýc                 c   sf   t ƒ }|j}|dkr:tj |j| ¡D ]}||ƒ |V  q$n(| D ]"}||ƒ}||kr>||ƒ |V  q>dS )zHList unique elements, preserving order. Remember all elements ever seen.N)ÚsetÚaddr   ZmovesÚfilterfalseÚ__contains__)ÚiterableÚkeyÚseenZseen_addÚelementÚkr&   r&   r'   Úunique_everseen¼   s    
rg   c                    s   t ˆ ƒ‡ fdd„ƒ}|S )zs
    Wrap a function returning an iterable such that the resulting iterable
    only ever yields unique items.
    c                     s   t ˆ | |ŽƒS ©N)rg   )ÚargsÚkwargs©Úfuncr&   r'   ÚwrapperÔ   s    zunique_values.<locals>.wrapperr   )rl   rm   r&   rk   r'   Úunique_valuesÎ   s    rn   z3<([^>]*\srel\s{0,10}=\s{0,10}['"]?([^'" >]+)[^>]*)>c              	   c   sº   t  |¡D ]d}| ¡ \}}tttj| ¡  d¡ƒƒ}d|ksDd|kr
t	 |¡D ]}t
j | t| d¡ƒ¡V  qNq
dD ]@}| |¡}|dkrtt	 ||¡}|rtt
j | t| d¡ƒ¡V  qtdS )zEFind rel="homepage" and rel="download" links in `page`, yielding URLsú,Zhomepager3   r6   )z<th>Home Pagez<th>Download URLr2   N)ÚRELÚfinditerÚgroupsr^   r   ÚstrÚstripr+   r9   ÚHREFr   r#   ÚurljoinÚ
htmldecoderF   ÚfindÚsearch)r:   ÚpagerE   ÚtagZrelZrelsÚposr&   r&   r'   Úfind_external_linksß   s    
r}   c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚContentCheckerzP
    A null content checker that defines the interface for checking content
    c                 C   s   dS )z3
        Feed a block of data to the hash.
        Nr&   ©ÚselfÚblockr&   r&   r'   Úfeed÷   s    zContentChecker.feedc                 C   s   dS )zC
        Check the hash. Return False if validation fails.
        Tr&   ©r€   r&   r&   r'   Úis_validý   s    zContentChecker.is_validc                 C   s   dS )zu
        Call reporter with information about the checker (hash name)
        substituted into the template.
        Nr&   )r€   ÚreporterÚtemplater&   r&   r'   Úreport  s    zContentChecker.reportN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r‚   r„   r‡   r&   r&   r&   r'   r~   ò   s   r~   c                   @   sB   e Zd Ze d¡Zdd„ Zedd„ ƒZdd„ Z	dd	„ Z
d
d„ ZdS )ÚHashCheckerzK(?P<hash_name>sha1|sha224|sha384|sha256|sha512|md5)=(?P<expected>[a-f0-9]+)c                 C   s   || _ t |¡| _|| _d S rh   )Ú	hash_nameÚhashlibÚnewÚhashÚexpected)r€   r   r‘   r&   r&   r'   Ú__init__  s    zHashChecker.__init__c                 C   s>   t j |¡d }|stƒ S | j |¡}|s0tƒ S | f | ¡ ŽS )z5Construct a (possibly null) ContentChecker from a URLr2   )r   r#   r7   r~   Úpatternry   Ú	groupdict)Úclsr:   r@   rE   r&   r&   r'   Úfrom_url  s    zHashChecker.from_urlc                 C   s   | j  |¡ d S rh   )r   Úupdater   r&   r&   r'   r‚   !  s    zHashChecker.feedc                 C   s   | j  ¡ | jkS rh   )r   Z	hexdigestr‘   rƒ   r&   r&   r'   r„   $  s    zHashChecker.is_validc                 C   s   || j  }||ƒS rh   )r   )r€   r…   r†   Úmsgr&   r&   r'   r‡   '  s    
zHashChecker.reportN)rˆ   r‰   rŠ   rU   Úcompiler“   r’   Úclassmethodr–   r‚   r„   r‡   r&   r&   r&   r'   rŒ     s   ÿ

rŒ   c                       sR  e Zd ZdZdNdd„ZdOd	d
„ZdPdd„ZdQdd„Zdd„ Zdd„ Z	dd„ Z
dd„ ZdRdd„Zdd„ ZdS‡ fdd„	Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ ZdTd'd(„ZdUd)d*„Zd+d,„ Zd-Zd.d/„ Zd0d1„ ZdVd2d3„Zed4d5„ ƒZd6d7„ Zed8d9„ ƒZd:d;„ Zd<d=„ Z d>d?„ Z!d@dA„ Z"dBdC„ Z#dDdE„ Z$edFdG„ ƒZ%dHdI„ Z&dJdK„ Z'dLdM„ Z(‡  Z)S )Wr   z;A distribution index that scans web pages for download URLsúhttps://pypi.org/simple/©Ú*NTc                 O   s”   t j| f|ž|Ž |dd | d¡ …  | _i | _i | _i | _t d 	t
t|ƒ¡¡j| _g | _|ortjor|prt ¡ }|r†t |¡| _n
tjj| _d S )Nr1   ú|)r   r’   r,   Ú	index_urlÚscanned_urlsÚfetched_urlsÚpackage_pagesrU   r™   r]   r   r   rE   ÚallowsÚto_scanr   Zis_availableZfind_ca_bundleZ
opener_forÚopenerr   ÚrequestÚurlopen)r€   rŸ   ZhostsZ	ca_bundleZ
verify_sslri   ÚkwZuse_sslr&   r&   r'   r’   /  s    ÿ
ýzPackageIndex.__init__Fc                 C   sº  || j kr|sdS d| j |< t|ƒs2|  |¡ dS tt|ƒƒ}|r\|  |¡sPdS |  d|¡ |sn|rn|| jkr‚tt| j	|ƒƒ dS |  |¡sšd| j|< dS |  
d|¡ d| j|< d}|  ||| ¡}|dkrÐdS d| j|j< d|j dd¡ ¡ kr | ¡  dS |j}| ¡ }t|tƒsNt|tjjƒr0d	}n|j d
¡p@d	}| |d¡}| ¡  t |¡D ](}	tj |t|	 d¡ƒ¡}
|  |
¡ q`|  | j!¡r¶t"|ddƒdkr¶|  #||¡}dS )z<Evaluate a URL as a possible download, and maybe retrieve itNTzFound link: %sz
Reading %sz<Download error on %s: %%s -- Some packages may not be found!Úhtmlúcontent-typeÚ zlatin-1ÚcharsetÚignorer6   Úcodeé”  )$r    Ú
URL_SCHEMEÚprocess_filenameÚlistr   Úurl_okÚdebugr¡   r   r_   ÚinfoÚopen_urlr:   ÚheadersÚgetr+   ÚcloseÚreadÚ
isinstancers   r   ÚerrorÚ	HTTPErrorZ	get_paramÚdecoderu   rq   r#   rv   rw   rF   Úprocess_urlr-   rŸ   ÚgetattrÚprocess_index)r€   r:   ZretrieveÚdistsÚtmplÚfr/   rz   r¬   rE   Úlinkr&   r&   r'   r¿   D  sP    





 zPackageIndex.process_urlc                 C   sŠ   t j |¡s|  d|¡ d S t j |¡r^|s^t j |¡}t  |¡D ]}|  t j ||¡d¡ qBt	|ƒ}|r†|  
d|¡ tt| j|ƒƒ d S )NzNot found: %sTz	Found: %s)rR   r>   ÚexistsÚwarnÚisdirÚrealpathÚlistdirr±   r]   rT   r´   r²   r   r_   )r€   ÚfnÚnestedr>   ÚitemrÂ   r&   r&   r'   r±   w  s    zPackageIndex.process_filenamec                 C   sb   t |ƒ}|o| d¡ ¡ dk}|s8|  tj |¡d ¡r<dS d}|rRt|| ƒ‚n|  ||¡ d S )Nr6   ÚfileTzN
Note: Bypassing %s (disallowed host; see http://bit.ly/2hrImnY for details).
)	r°   rF   r+   r£   r   r#   r7   r   rÇ   )r€   r:   ZfatalÚsÚis_filer˜   r&   r&   r'   r³   ‡  s    ÿzPackageIndex.url_okc                 C   s2   t tjj|ƒ}dd„ |D ƒ}tt | j|¡ƒ d S )Nc                 s   s0   | ](}t  |¡D ]}| d ¡r||fV  qqdS )z	.egg-linkN)rR   rÊ   r,   )rV   r>   Úentryr&   r&   r'   rX   –  s
    
ýz.PackageIndex.scan_egg_links.<locals>.<genexpr>)ÚfilterrR   r>   rÈ   r²   Ú	itertoolsÚstarmapÚscan_egg_link)r€   Úsearch_pathÚdirsZ	egg_linksr&   r&   r'   Úscan_egg_links”  s
    þzPackageIndex.scan_egg_linksc              	   C   sŒ   t tj ||¡ƒ}ttd ttj|ƒƒƒ}W 5 Q R X t	|ƒdkrDd S |\}}t
tj ||¡ƒD ](}tjj|f|žŽ |_t|_|  |¡ q^d S )NrY   )ÚopenrR   r>   r]   r²   rÒ   r   rs   rt   rO   r   rK   r   rB   r_   )r€   r>   rÑ   Z	raw_linesÚlinesZegg_pathZ
setup_pathrH   r&   r&   r'   rÕ   ž  s     zPackageIndex.scan_egg_linkc           
   	      sÎ   ‡ fdd„}t  |¡D ]:}z |tj |t| d¡ƒ¡ƒ W q tk
rN   Y qX q||ƒ\}}|rÆt||ƒD ]H}t	|ƒ\}}	| 
d¡rª|	sª|r |d||f 7 }n
ˆ  |¡ ˆ  |¡ qlt dd„ |¡S dS d	S )
z#Process the contents of a PyPI pagec                    sŒ   |   ˆ j¡rˆtttjj| tˆ jƒd …  d¡ƒƒ}t|ƒdkrˆd|d krˆt	|d ƒ}t
|d ƒ}dˆ j | ¡ i ¡| < t|ƒt|ƒfS dS )Nr1   rY   r5   r6   r   T)NN)r-   rŸ   r²   r   r   r#   r8   rO   r9   r   r   r¢   Ú
setdefaultr+   r   )rÅ   r;   ÚpkgÚverrƒ   r&   r'   Úscan±  s     ÿz(PackageIndex.process_index.<locals>.scanr6   ú.pyz
#egg=%s-%sc                 S   s   d|   ddd¡ S )Nz<a href="%s#md5=%s">%s</a>r6   é   rY   )rF   )Úmr&   r&   r'   Ú<lambda>Ô  ó    z,PackageIndex.process_index.<locals>.<lambda>r«   N)ru   rq   r   r#   rv   rw   rF   r$   r}   rA   r,   Úneed_version_infoÚscan_urlÚPYPI_MD5Úsub)
r€   r:   rz   rÞ   rE   rÜ   rÝ   Únew_urlr/   Úfragr&   rƒ   r'   rÁ   ®  s(     
 ÿzPackageIndex.process_indexc                 C   s   |   d|¡ d S )NzPPage at %s links to .py file(s) without version info; an index scan is required.)Úscan_all©r€   r:   r&   r&   r'   rä   Ù  s    þzPackageIndex.need_version_infoc                 G   s:   | j | jkr*|r | j|f|žŽ  |  d¡ |  | j ¡ d S )Nz6Scanning index of all packages (this may take a while))rŸ   r¡   rÇ   rµ   rå   ©r€   r˜   ri   r&   r&   r'   rê   ß  s    ÿzPackageIndex.scan_allc                 C   sz   |   | j|j d ¡ | j |j¡s:|   | j|j d ¡ | j |j¡sR|  |¡ t| j |jd¡ƒD ]}|   |¡ qfd S )Nr1   r&   )	rå   rŸ   Úunsafe_namer¢   r¸   rc   rL   Únot_found_in_indexr²   )r€   Úrequirementr:   r&   r&   r'   Úfind_packagesè  s    
zPackageIndex.find_packagesc                    sR   |   ¡  |  |¡ | |j D ]"}||kr0|  S |  d||¡ qtt| ƒ ||¡S )Nz%s does not match %s)Úprescanrð   rc   r´   Úsuperr   Úobtain)r€   rï   Z	installerrH   ©Ú	__class__r&   r'   ró   ÷  s    
zPackageIndex.obtainc                 C   sL   |  | jd| ¡ | ¡ sH| ¡  t |¡ td|jjtj	 
|¡f ƒ‚dS )z-
        checker is a ContentChecker
        zValidating %%s checksum for %sz7%s validation failed for %s; possible download problem?N)r‡   r´   r„   r¹   rR   Úunlinkr   r   r.   r>   rP   )r€   ÚcheckerrS   Útfpr&   r&   r'   Ú
check_hash   s    þ
þÿzPackageIndex.check_hashc                 C   sN   |D ]D}| j dks0t|ƒr0| d¡s0tt|ƒƒr<|  |¡ q| j  |¡ qdS )z;Add `urls` to the list that will be prescanned for searchesNúfile:)r¤   r°   r-   r²   r   rå   Úappend)r€   Zurlsr:   r&   r&   r'   Úadd_find_links  s    ÿþý
üzPackageIndex.add_find_linksc                 C   s"   | j rtt| j| j ƒƒ d| _ dS )z7Scan urls scheduled for prescanning (e.g. --find-links)N)r¤   r²   r   rå   rƒ   r&   r&   r'   rñ     s    zPackageIndex.prescanc                 C   s<   | |j  r| jd }}n| jd }}|||jƒ |  ¡  d S )Nz#Couldn't retrieve index page for %rz3Couldn't find index page for %r (maybe misspelled?))rc   rµ   rÇ   rí   rê   )r€   rï   Úmethr˜   r&   r&   r'   rî   %  s    
þzPackageIndex.not_found_in_indexc                 C   sv   t |tƒsbt|ƒ}|rJ|  ||¡}t|ƒ\}}| d¡rF|  |||¡}|S tj 	|¡rZ|S t
|ƒ}t|  ||¡ddƒS )a  Locate and/or download `spec` to `tmpdir`, returning a local path

        `spec` may be a ``Requirement`` object, or a string containing a URL,
        an existing local filename, or a project/version requirement spec
        (i.e. the string form of a ``Requirement`` object).  If it is the URL
        of a .py file with an unambiguous ``#egg=name-version`` tag (i.e., one
        that escapes ``-`` as ``_`` throughout), a trivial ``setup.py`` is
        automatically created alongside the downloaded file.

        If `spec` is a ``Requirement`` object or a string containing a
        project/version requirement spec, this method returns the location of
        a matching distribution (possibly after downloading it to `tmpdir`).
        If `spec` is a locally existing file or directory name, it is simply
        returned unchanged.  If `spec` is a URL, it is downloaded to a subpath
        of `tmpdir`, and the local filename is returned.  Various errors may be
        raised if a problem occurs during downloading.
        rß   rK   N)r»   r   r°   Ú_download_urlrA   r,   Ú	gen_setuprR   r>   rÆ   r(   rÀ   Úfetch_distribution)r€   r%   Útmpdirr<   Úfoundr/   r@   r&   r&   r'   r3   /  s    

zPackageIndex.downloadc           	         sÜ   ˆ  d|¡ i ‰d}d
‡ ‡‡‡‡fdd„	}|rHˆ ¡  ˆ |¡ ||ƒ}|s^|dk	r^|||ƒ}|dkr€ˆjdk	rxˆ ¡  ||ƒ}|dkrž|sžˆ |¡ ||ƒ}|dkr¾ˆ dˆr´dp¶d|¡ nˆ  d|¡ |j|jd	S dS )a|  Obtain a distribution suitable for fulfilling `requirement`

        `requirement` must be a ``pkg_resources.Requirement`` instance.
        If necessary, or if the `force_scan` flag is set, the requirement is
        searched for in the (online) package index as well as the locally
        installed packages.  If a distribution matching `requirement` is found,
        the returned distribution's ``location`` is the value you would have
        gotten from calling the ``download()`` method with the matching
        distribution's URL or filename.  If no matching distribution is found,
        ``None`` is returned.

        If the `source` flag is set, only source distributions and source
        checkout links will be considered.  Unless the `develop_ok` flag is
        set, development and system eggs (i.e., those using the ``.egg-info``
        format) will be ignored.
        zSearching for %sNc                    s’   |d krˆ}|| j  D ]v}|jtkrFˆ sF|ˆkrˆ d|¡ dˆ|< q|| ko\|jtkp\ˆ }|rˆ |jˆ¡}||_tj	 
|j¡r|  S qd S )Nz&Skipping development or system egg: %sr6   )rc   rB   r   rÇ   r   r3   rK   Údownload_locationrR   r>   rÆ   )ZreqÚenvrH   ZtestZloc©Ú
develop_okr€   ZskippedÚsourcer  r&   r'   rx   i  s&     ÿþz-PackageIndex.fetch_distribution.<locals>.findz:No local packages or working download links found for %s%sza source distribution of r«   zBest match: %s)rK   )N)rµ   rñ   rð   r¤   rÇ   Úcloner  )	r€   rï   r  Ú
force_scanr  r  Zlocal_indexrH   rx   r&   r  r'   r   Q  s2    




ýzPackageIndex.fetch_distributionc                 C   s"   |   ||||¡}|dk	r|jS dS )a3  Obtain a file suitable for fulfilling `requirement`

        DEPRECATED; use the ``fetch_distribution()`` method now instead.  For
        backward compatibility, this routine is identical but returns the
        ``location`` of the downloaded distribution instead of a distribution
        object.
        N)r   rK   )r€   rï   r  r	  r  rH   r&   r&   r'   Úfetch  s    zPackageIndex.fetchc           
   	   C   sü   t  |¡}|r*dd„ t|| d¡d ƒD ƒp,g }t|ƒdkrÚtj |¡}tj |¡|krŠtj 	||¡}ddl
m} |||ƒsŠt ||¡ |}ttj 	|d¡dƒ2}	|	 d|d j|d jtj |¡d f ¡ W 5 Q R X |S |rðtd	||f ƒ‚ntd
ƒ‚d S )Nc                 S   s   g | ]}|j r|‘qS r&   )rM   )rV   Údr&   r&   r'   Ú
<listcomp>¬  s   ÿz*PackageIndex.gen_setup.<locals>.<listcomp>r6   r   )Úsamefilezsetup.pyÚwzIfrom setuptools import setup
setup(name=%r, version=%r, py_modules=[%r])
z†Can't unambiguously interpret project/version identifier %r; any dashes in the name or version should be escaped using underscores. %rzpCan't process plain .py files without an '#egg=name-version' suffix to enable automatic setup script generation.)rD   rE   r    rF   rO   rR   r>   rP   Údirnamer]   Zsetuptools.command.easy_installr  ÚshutilZcopy2rÙ   ÚwriterL   rM   Úsplitextr   )
r€   rS   r@   r  rE   rÂ   rP   Zdstr  rÎ   r&   r&   r'   rÿ   ª  sB    

þý
 þþÿþÿÿzPackageIndex.gen_setupi    c              	   C   s  |   d|¡ d }zît |¡}|  |¡}t|tjjƒrJt	d||j
|jf ƒ‚|  ¡ }d}| j}d}d|kr’t|dƒ}	ttt|	ƒƒ}|  |||||¡ t|dƒV}
| |¡}|rà| |¡ |
 |¡ |d7 }|  |||||¡ qžqàqž|  |||
¡ W 5 Q R X |W ¢S |r| ¡  X d S )	NzDownloading %szCan't download %s: %s %sr   r2   zcontent-lengthzContent-LengthÚwbr6   )rµ   r¹   rŒ   r–   r¶   r»   r   r¼   r½   r   r®   r˜   Údl_blocksizer   Úmaxr   ÚintÚ
reporthookrÙ   rº   r‚   r  rù   )r€   r:   rS   Úfpr÷   r·   ÚblocknumZbsÚsizeZsizesrø   r   r&   r&   r'   Ú_download_toÕ  s:    

ÿ



zPackageIndex._download_toc                 C   s   d S rh   r&   )r€   r:   rS   r  Zblksizer  r&   r&   r'   r  ù  s    zPackageIndex.reporthookc              
   C   sš  |  d¡rt|ƒS zt|| jƒW S  ttjfk
r‚ } z<d dd„ |jD ƒ¡}|r`|  	||¡ nt
d||f ƒ‚W 5 d }~X Y n tjjk
r® } z| W Y ¢S d }~X Y nè tjjk
 rú } z*|rØ|  	||j¡ nt
d||jf ƒ‚W 5 d }~X Y nœ tjk
rF } z,|r$|  	||j¡ nt
d||jf ƒ‚W 5 d }~X Y nP tjtjfk
r” } z(|rt|  	||¡ nt
d||f ƒ‚W 5 d }~X Y nX d S )Nrú   ú c                 S   s   g | ]}t |ƒ‘qS r&   )rs   )rV   Úargr&   r&   r'   r    s     z)PackageIndex.open_url.<locals>.<listcomp>z%s %szDownload error for %s: %sz;%s returned a bad status line. The server might be down, %s)r-   Ú
local_openÚopen_with_authr¥   r$   r   Ú
InvalidURLr]   ri   rÇ   r   r   r¼   r½   ZURLErrorÚreasonZBadStatusLineÚlineZHTTPExceptionÚsocket)r€   r:   ZwarningÚvr˜   r&   r&   r'   r¶   ü  s>    
"ÿþÿÿzPackageIndex.open_urlc                 C   sx   t | ƒ\}}|r0d|kr4| dd¡ dd¡}qnd}| d¡rJ|dd… }tj ||¡}| t|ƒ¡sttd	|› ƒ‚|S )
aB  
        >>> import pathlib
        >>> du = PackageIndex._resolve_download_filename
        >>> root = getfixture('tmp_path')
        >>> url = 'https://files.pythonhosted.org/packages/a9/5a/0db.../setuptools-78.1.0.tar.gz'
        >>> str(pathlib.Path(du(url, root)).relative_to(root))
        'setuptools-78.1.0.tar.gz'

        Ensures the target is always in tmpdir.

        >>> url = 'https://anyhost/%2fhome%2fuser%2f.ssh%2fauthorized_keys'
        >>> du(url, root)
        Traceback (most recent call last):
        ...
        ValueError: Invalid filename...
        z..Ú.ú\Ú_Z__downloaded__rI   Nr*   zInvalid filename )	rA   Úreplacer,   rR   r>   r]   r-   rs   r$   )r:   r  r.   r@   rS   r&   r&   r'   Ú_resolve_download_filename  s    
z'PackageIndex._resolve_download_filenamec                 C   s$   |   ||¡}|  ||¡p"|  ||¡S )z2
        Determine the download filename.
        )r)  Ú_download_vcsÚ_download_other)r€   r:   r  rS   r&   r&   r'   rþ   C  s    zPackageIndex._download_urlc                 C   sL   t j | ¡j}| d¡\}}}tddgdgt|ƒ  ƒ}tt|h|@ ƒdƒS )a  
        >>> rvcs = PackageIndex._resolve_vcs
        >>> rvcs('git+http://foo/bar')
        'git'
        >>> rvcs('hg+https://foo/bar')
        'hg'
        >>> rvcs('git:myhost')
        'git'
        >>> rvcs('hg:myhost')
        >>> rvcs('http://foo/bar')
        ú+ÚsvnÚgitÚhgN)	r   r#   Úurlsplitr<   Ú	partitionr^   ÚboolÚnextÚiter)r:   r<   ÚpreÚsepÚpostZallowedr&   r&   r'   Ú_resolve_vcsJ  s    zPackageIndex._resolve_vcsc              
   C   sÆ   |   |¡}|sd S |dkr&|  ||¡S | d¡\}}}|  |¡\}}|  d|› d|› d|› ¡ t |dd||g¡ t|d|d	d|g|d
|ddd|dgd}|d k	rÂ|  d|› ¡ t || ¡ |S )Nr-  r5   zDoing z clone from z to r  z--quietz-CÚcheckoutz--cwdZupz-rú-q)r.  r/  zChecking out )r8  Ú_download_svnr1  Ú_vcs_split_rev_from_urlrµ   Ú
subprocessÚ
check_callÚdict)r€   r:   Zspec_filenameZvcsrS   r'  ÚrevZco_commandsr&   r&   r'   r*  ]  s"    
þzPackageIndex._download_vcsc                 C   sD   t j |¡j}|dkr,t j t j |¡j¡S |  |d¡ |  	||¡S )NrÎ   T)
r   r#   r0  r<   r¦   Úurl2pathnamer7   r>   r³   Ú_attempt_download)r€   r:   rS   r<   r&   r&   r'   r+  t  s
    zPackageIndex._download_otherc                 C   s   |   |d¡ d S )NT)r¿   rë   r&   r&   r'   rå   |  s    zPackageIndex.scan_urlc                 C   s6   |   ||¡}d| dd¡ ¡ kr.|  |||¡S |S d S )Nr©   rª   r«   )r  r¸   r+   Ú_download_html)r€   r:   rS   r·   r&   r&   r'   rB    s    zPackageIndex._attempt_downloadc                 C   sn   t |ƒ}|D ]>}| ¡ rt d|¡rF| ¡  t |¡ |  ||¡  S  qLq| ¡  t |¡ td| ƒ‚d S )Nz <title>([^- ]+ - )?Revision \d+:zUnexpected HTML page found at )	rÙ   rt   rU   ry   r¹   rR   rö   r;  r   )r€   r:   r·   rS   rÎ   r"  r&   r&   r'   rC  †  s    

zPackageIndex._download_htmlc                 C   s   t  dt¡ | dd¡d }g }| ¡  d¡rîd|krîtj |¡\}}}}}}	|sî| d¡rîd|d	d … krî|d	d …  dd¡\}}t	|ƒ\}
}|
rîd
|
krÀ|
 d
d¡\}}| 
d|d|g¡ n| 
d|
g¡ |}||||||	f}tj |¡}|  d||¡ dddg| ||g }t |¡ |S )Nz"SVN download support is deprecatedr5   r6   r   zsvn:ú@z//r1   rY   ú:z
--usernamez
--passwordz'Doing subversion checkout from %s to %sr-  r9  r:  )ÚwarningsrÇ   ÚUserWarningr9   r+   r-   r   r#   r7   Ú
_splituserÚextendÚ
urlunparserµ   r=  r>  )r€   r:   rS   Zcredsr<   Únetlocr>   rW   ÚqrÄ   ÚauthÚhostÚuserZpwr;   Úcmdr&   r&   r'   r;  •  s(    
zPackageIndex._download_svnc                 C   st   t j | ¡}|j dd¡d }|j d¡\}}}| d¡\}}}|rL||fn|df\}}	|j||dd 	¡ }
|
|	fS )	aò  
        Given a possible VCS URL, return a clean URL and resolved revision if any.

        >>> vsrfu = PackageIndex._vcs_split_rev_from_url
        >>> vsrfu('git+https://github.com/pypa/setuptools@v69.0.0#egg-info=setuptools')
        ('https://github.com/pypa/setuptools', 'v69.0.0')
        >>> vsrfu('git+https://github.com/pypa/setuptools#egg-info=setuptools')
        ('https://github.com/pypa/setuptools', None)
        >>> vsrfu('http://foo/bar')
        ('http://foo/bar', None)
        r,  r6   r2   r5   rD  Nr«   )r<   r>   r@   )
r   r#   r0  r<   r9   r>   r1  Ú
rpartitionÚ_replaceZgeturl)r:   r;   Zclean_schemeZno_fragment_pathr'  r5  r6  r7  Z
clean_pathr@  Zresolvedr&   r&   r'   r<  ­  s    ü
z$PackageIndex._vcs_split_rev_from_urlc                 G   s   t j|f|žŽ  d S rh   )r   r´   rì   r&   r&   r'   r´   Í  s    zPackageIndex.debugc                 G   s   t j|f|žŽ  d S rh   )r   rµ   rì   r&   r&   r'   rµ   Ð  s    zPackageIndex.infoc                 G   s   t j|f|žŽ  d S rh   )r   rÇ   rì   r&   r&   r'   rÇ   Ó  s    zPackageIndex.warn)r›   rœ   NT)F)F)F)N)N)FFFN)FF)N)*rˆ   r‰   rŠ   r‹   r’   r¿   r±   r³   rØ   rÕ   rÁ   rä   rê   rð   ró   rù   rü   rñ   rî   r3   r   r
  rÿ   r  r  r  r¶   Ústaticmethodr)  rþ   r8  r*  r+  rå   rB  rC  r;  r<  r´   rµ   rÇ   Ú__classcell__r&   r&   rô   r'   r   ,  s`         þ

3


+
		
#      þ
L
)$
#
#

z!&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?c                 C   s   |   d¡}t|ƒS )Nr   )rF   r   )rE   Zwhatr&   r&   r'   Údecode_entityÜ  s    
rU  c                 C   s
   t t| ƒS )a  
    Decode HTML entities in the given text.

    >>> htmldecode(
    ...     'https://../package_name-0.1.2.tar.gz'
    ...     '?tokena=A&amp;tokenb=B">package_name-0.1.2.tar.gz')
    'https://../package_name-0.1.2.tar.gz?tokena=A&tokenb=B">package_name-0.1.2.tar.gz'
    )Ú
entity_subrU  )Útextr&   r&   r'   rw   á  s    	rw   c                    s   ‡ fdd„}|S )Nc                    s   ‡ ‡fdd„}|S )Nc               	      s2   t  ¡ }t  ˆ¡ zˆ | |ŽW ¢S t  |¡ X d S rh   )r#  ZgetdefaulttimeoutZsetdefaulttimeout)ri   rj   Zold_timeout)rl   Útimeoutr&   r'   Ú_socket_timeoutï  s
    
z@socket_timeout.<locals>._socket_timeout.<locals>._socket_timeoutr&   )rl   rY  ©rX  rk   r'   rY  î  s    z'socket_timeout.<locals>._socket_timeoutr&   )rX  rY  r&   rZ  r'   Úsocket_timeoutí  s    r[  c                 C   s2   t j | ¡}| ¡ }t |¡}| ¡ }| dd¡S )aq  
    A function compatible with Python 2.3-3.3 that will encode
    auth from a URL suitable for an HTTP header.
    >>> str(_encode_auth('username%3Apassword'))
    'dXNlcm5hbWU6cGFzc3dvcmQ='

    Long auth strings should not cause a newline to be inserted.
    >>> long_auth = 'username:' + 'password'*10
    >>> chr(10) in str(_encode_auth(long_auth))
    False
    Ú
r«   )r   r#   r8   ÚencodeÚbase64Z	b64encoder¾   r(  )rM  Zauth_sZ
auth_bytesZencoded_bytesZencodedr&   r&   r'   Ú_encode_authü  s
    
r_  c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	Ú
Credentialz:
    A username/password pair. Use like a namedtuple.
    c                 C   s   || _ || _d S rh   ©ÚusernameÚpassword)r€   rb  rc  r&   r&   r'   r’     s    zCredential.__init__c                 c   s   | j V  | jV  d S rh   ra  rƒ   r&   r&   r'   Ú__iter__  s    zCredential.__iter__c                 C   s   dt | ƒ S )Nz%(username)s:%(password)s)Úvarsrƒ   r&   r&   r'   Ú__str__  s    zCredential.__str__N)rˆ   r‰   rŠ   r‹   r’   rd  rf  r&   r&   r&   r'   r`    s   r`  c                   @   s0   e Zd Zdd„ Zedd„ ƒZdd„ Zdd„ Zd	S )
Ú
PyPIConfigc                 C   sP   t  dddgd¡}tj | |¡ tj tj d¡d¡}tj 	|¡rL|  
|¡ dS )z%
        Load from ~/.pypirc
        rb  rc  Ú
repositoryr«   ú~z.pypircN)r?  Úfromkeysr   ÚRawConfigParserr’   rR   r>   r]   Ú
expanduserrÆ   rº   )r€   ÚdefaultsZrcr&   r&   r'   r’   $  s
    zPyPIConfig.__init__c                    s&   ‡ fdd„ˆ   ¡ D ƒ}ttˆ j|ƒƒS )Nc                    s    g | ]}ˆ   |d ¡ ¡ r|‘qS )rh  )r¸   rt   )rV   Úsectionrƒ   r&   r'   r  1  s   ÿz2PyPIConfig.creds_by_repository.<locals>.<listcomp>)Zsectionsr?  r   Ú_get_repo_cred)r€   Zsections_with_repositoriesr&   rƒ   r'   Úcreds_by_repository/  s    
ÿzPyPIConfig.creds_by_repositoryc                 C   s6   |   |d¡ ¡ }|t|   |d¡ ¡ |   |d¡ ¡ ƒfS )Nrh  rb  rc  )r¸   rt   r`  )r€   rn  Zrepor&   r&   r'   ro  8  s
    þzPyPIConfig._get_repo_credc                 C   s*   | j  ¡ D ]\}}| |¡r
|  S q
dS )zŒ
        If the URL indicated appears to be a repository defined in this
        config, return the credential for that repository.
        N)rp  Úitemsr-   )r€   r:   rh  Úcredr&   r&   r'   Úfind_credential?  s    
zPyPIConfig.find_credentialN)rˆ   r‰   rŠ   r’   Úpropertyrp  ro  rs  r&   r&   r&   r'   rg  #  s
   
rg  c                 C   s:  t j | ¡}|\}}}}}}| d¡r0t d¡‚|dkrFt|ƒ\}	}
nd}	|	s~tƒ  | ¡}|r~t	|ƒ}	|j
| f}tjd	|žŽ  |	rÄdt|	ƒ }	||
||||f}t j |¡}t j |¡}| d|	¡ nt j | ¡}| dt¡ ||ƒ}|	r6t j |j¡\}}}}}}||kr6||
kr6||||||f}t j |¡|_|S )
z4Open a urllib2 request, handling HTTP authenticationrE  znonnumeric port: '')ZhttpZhttpsNú*Authenticating as %s for %s (from .pypirc)zBasic ZAuthorizationz
User-Agent)ru  )r   r#   r7   r,   r   r   rH  rg  rs  rs   rb  r   rµ   r_  rJ  r¦   ZRequestZ
add_headerÚ
user_agentr:   )r:   r¥   Zparsedr<   rK  r>   Zparamsr?   ré   rM  Zaddressrr  rµ   r;   rè   r¦   r  Ús2Zh2Zpath2Zparam2Zquery2Zfrag2r&   r&   r'   r  I  s8    


r  c                 C   s    |   d¡\}}} |r|nd| fS )zNsplituser('user[:passwd]@host[:port]')
    --> 'user[:passwd]', 'host[:port]'.rD  N)rQ  )rN  rO  Zdelimr&   r&   r'   rH  x  s    rH  c                 C   s   | S rh   r&   )r:   r&   r&   r'   Ú
fix_sf_urlƒ  s    rx  c              
   C   s  t j | ¡\}}}}}}t j |¡}tj |¡r<t j | ¡S | 	d¡rètj 
|¡règ }t |¡D ]d}	tj ||	¡}
|	dkržt|
dƒ}| ¡ }W 5 Q R X  qÞntj 
|
¡r²|	d7 }	| dj|	d¡ q`d}|j| d |¡d}d	\}}n
d
\}}}ddi}t |¡}t j | ||||¡S )z7Read a local path, with special support for directoriesr1   z
index.htmlÚrz<a href="{name}">{name}</a>)r.   zB<html><head><title>{url}</title></head><body>{files}</body></html>r\  )r:   Úfiles)éÈ   ZOK)r¯   zPath not foundz	Not foundrª   z	text/html)r   r#   r7   r¦   rA  rR   r>   Úisfiler§   r,   rÈ   rÊ   r]   rÙ   rº   rû   Úformatr   ÚStringIOr¼   r½   )r:   r<   r=   r>   Zparamr?   ré   rS   rz  rÄ   Úfilepathr  ZbodyrÃ   ZstatusÚmessager·   Zbody_streamr&   r&   r'   r  ‡  s.    ÿ


r  )N)N)N)N)r!   )^r‹   Úsysr=  rR   rU   r  r#  r^  rŽ   rÓ   rF  Ú	functoolsr   Zsetuptools.externr   Zsetuptools.extern.six.movesr   r   r   r   r"   Zpkg_resourcesr	   r
   r   r   r   r   r   r   r   r   r   r   r   r   Z	distutilsr   Zdistutils.errorsr   Zfnmatchr   Zsetuptools.py27compatr   Zsetuptools.py33compatr   Zsetuptools.wheelr   ÚtypeZ__metaclass__r™   rD   ÚIru   ræ   rE   r°   r9   rN   Ú__all__Z_SOCKET_TIMEOUTZ_tmplr}  Úversion_inforv  r(   r   rA   r   rC   rT   r    rg   rn   rp   r}   r~   rŒ   r   rç   rV  rU  rw   r[  r_  r`  rk  rg  r¦   r§   r  rH  rx  r  r&   r&   r&   r'   Ú<module>   s˜   <
ÿ  þ
 ÿ	

!
 þ
$

!     2
&/