U
    K÷†i„  ã                   @   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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 ddl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)m*Z* ddl+m,Z, d	d
l-m.Z.m/Z/ ddl0m1Z1 ddl2m3Z3 e
 4d¡Z5e
 4de
j6¡Z7e
 4d¡Z8e
 4de
j6¡j9Z:d ;¡ Z<ddddgZ=dZ>dZ?e?j@dj@ejAŽ edZBdd„ ZCdd„ ZDdd„ ZEdDdd„ZFdEd d!„ZGdFd"d#„ZHde!dfd$d„ZId%d&„ ZJe
 4d'e
j6¡ZKeJd(d)„ ƒZLG d*d+„ d+ƒZMG d,d-„ d-eMƒZNG d.d„ de#ƒZOe
 4d/¡jPZQd0d1„ ZRd2d3„ ZSdGd4d5„ZTd6d7„ ZUG d8d9„ d9eƒZVG d:d;„ d;ejWƒZXejYjZfd<d=„Z[d>d?„ Z\eTe>ƒe[ƒZ[d@dA„ Z]dBdC„ Z^dS )Hz$PyPI and direct package downloading.é    N)Ú	translate©Úwraps)Ú
NamedTuple©Úunique_everseen)ÚBINARY_DISTÚCHECKOUT_DISTÚDEVELOP_DISTÚEGG_DISTÚSOURCE_DISTÚDistributionÚEnvironmentÚRequirementÚfind_distributionsÚnormalize_pathÚparse_versionÚ	safe_nameÚsafe_versionÚto_filename)ÚWheelé   )Ú_cfg_read_utf8_with_fallbackÚ_read_utf8_with_fallback)Úlog)ÚDistutilsErrorz^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   sD   zt  | ¡W S  tk
r> } ztd| f ƒ|‚W 5 d }~X Y nX d S )Nz1Not a URL, existing file, or requirement spec: %r)r   ÚparseÚ
ValueErrorr   )ÚspecÚe© r&   ú</tmp/pip-unpacked-wheel-ffidw15h/setuptools/package_index.pyÚparse_requirement_argI   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öÿÿÿÚwin32z	.win32-pyiðÿÿÿiùÿÿÿéüÿÿÿz.win-amd64.exeiòÿÿÿz	win-amd64z.win-amd64-pyiìÿÿÿ)ÚlowerÚendswithÚ
startswith)Únamer,   ÚbaseÚpy_verÚplatr&   r&   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   )Úurllibr"   ÚurlparseÚunquoteÚsplit)	ÚurlÚpartsÚschemeÚserverÚpathÚ
parametersÚqueryÚfragmentr0   r&   r&   r'   Úegg_info_for_urlj   s    rD   c                 c   sP   t | ƒ\}}t| ||ƒE dH  |rLt |¡}|rLt| | d¡|tdE dH  dS )zEYield egg or source distribution objects that might be found at a URLNr   )Ú
precedence)rD   Údistros_for_locationÚEGG_FRAGMENTÚmatchr   Úgroupr	   )r<   Úmetadatar0   rC   rH   r&   r&   r'   r   u   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 basenamez.egg.zipNr+   ú.eggú-z.whlr   )ÚlocationÚproject_nameÚversionrE   r)   )r-   r   Úfrom_locationr   Úis_compatiblerN   rO   r   r   r   r   Ú
EXTENSIONSÚlen)rM   ÚbasenamerJ   ÚwheelZwin_baser1   ÚplatformÚextr&   r&   r'   rF      s>    
ûÿ	
     ÿ
rF   c                 C   s   t t| ƒtj | ¡|ƒS )zEYield possible egg or source distribution objects based on a filename)rF   r   Úosr@   rT   )ÚfilenamerJ   r&   r&   r'   Údistros_for_filename¤   s
     
 ÿrZ   c              	   c   s–   |  d¡}|s,tdd„ |dd… D ƒƒr,dS tt|ƒƒD ]}|| dd…  ¡ r8 q^q8t|ƒ}t| |d |d|… ¡d ||d… ¡|||dV  dS )zÏGenerate the interpretation 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!
    rL   c                 s   s   | ]}t  d |¡V  qdS )z	py\d\.\d$N)ÚrerH   )Ú.0Úpr&   r&   r'   Ú	<genexpr>¶   s     z(interpret_distro_name.<locals>.<genexpr>é   Nr   )Ú
py_versionrE   rV   )r;   ÚanyÚrangerS   Úisdigitr   Újoin)rM   rT   rJ   r`   rE   rV   r=   r]   r&   r&   r'   r   «   s     

ù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 ©Nr   )ÚargsÚkwargs©Úfuncr&   r'   ÚwrapperÓ   s    zunique_values.<locals>.wrapperr   )ri   rj   r&   rh   r'   Úunique_valuesÍ   s    rk   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homepager5   r   )z<th>Home Pagez<th>Download URLr4   N)ÚRELÚfinditerÚgroupsÚsetÚmapÚstrÚstripr,   r;   ÚHREFr8   r"   ÚurljoinÚ
htmldecoderI   ÚfindÚsearch)r<   ÚpagerH   ÚtagÚ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 re   )Ú	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 URLr4   )r8   r"   r9   r~   Úpatternrx   Ú	groupdict)Úclsr<   rC   rH   r&   r&   r'   Úfrom_url  s    zHashChecker.from_urlc                 C   s   | j  |¡ d S re   )r   Úupdater   r&   r&   r'   r‚   "  s    zHashChecker.feedc                 C   s   | j  ¡ | jkS re   )r   Ú	hexdigestr‘   rƒ   r&   r&   r'   r„   %  s    zHashChecker.is_validc                 C   s   || j  }||ƒS re   )r   )r€   r…   r†   Úmsgr&   r&   r'   r‡   (  s    
zHashChecker.reportN)rˆ   r‰   rŠ   r[   Úcompiler“   r’   Úclassmethodr–   r‚   r„   r‡   r&   r&   r&   r'   rŒ     s   ÿ

rŒ   c                       sš  e Zd ZdZdXeedœ‡ fdd„Z‡ fd	d
„ZdYedœdd„ZdZedœdd„Z	d[edœdd„Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd\dd „Zd!d"„ Zd]‡ fd#d$„	Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd^eeed/œd0d1„Zd_eed2œd3d4„Zd5d6„ Zd7Zd8d9„ Zd:d;„ Zd`d<d=„Zed>d?„ ƒZ e!d@dA„ ƒZ"dBdC„ Z#edDdE„ ƒZ$dFdG„ Z%dHdI„ Z&dJdK„ Z'dLdM„ Z(dNdO„ Z)edPdQ„ ƒZ*dRdS„ Z+dTdU„ Z,dVdW„ Z-‡  Z.S )ar   z;A distribution index that scans web pages for download URLsúhttps://pypi.org/simple/©Ú*NT)Ú	index_urlÚ
verify_sslc                    sh   t ƒ j||Ž |dd | d¡ …  | _i | _i | _i | _t d 	t
t|ƒ¡¡j| _g | _tjj| _d S )Nr3   ú|)Úsuperr’   r-   rŸ   Úscanned_urlsÚfetched_urlsÚpackage_pagesr[   rš   rd   rq   r   rH   ÚallowsÚto_scanr8   ÚrequestÚurlopenÚopener)r€   rŸ   ÚhostsZ	ca_bundler    rf   Úkw©Ú	__class__r&   r'   r’   0  s    	zPackageIndex.__init__c                    s2   zt |jƒ W n tk
r$   Y d S X tƒ  |¡S re   )r   rO   Ú	Exceptionr¢   Úadd)r€   Údistr­   r&   r'   r°   B  s
    zPackageIndex.addF)Úretrievec                 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 t|tjjƒrø|jdkrø|  
d|j ¡ d| j|j< d|j d	d
¡ ¡ kr(| ¡  dS |j}| ¡ }t|tƒsvt|tjjƒrXd}n|j d¡phd}| |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!i‘  zAuthentication error: %sÚhtmlúcontent-typeÚ zlatin-1ÚcharsetÚignorer   Úcodeé”  )&r£   Ú
URL_SCHEMEÚprocess_filenameÚlistr   Úurl_okÚdebugr¤   rq   r°   ÚinfoÚopen_urlÚ
isinstancer8   ÚerrorÚ	HTTPErrorr¸   r™   r<   ÚheadersÚgetr,   ÚcloseÚreadrr   Ú	get_paramÚdecodert   rn   r"   ru   rv   rI   Úprocess_urlr.   rŸ   ÚgetattrÚprocess_index)r€   r<   r²   ÚdistsÚtmplÚfr0   ry   r¶   rH   Úlinkr&   r&   r'   rÊ   K  sT    





 zPackageIndex.process_url)Únestedc                 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)rX   r@   ÚexistsÚwarnÚisdirÚrealpathÚlistdirr»   rd   rZ   r¾   r¼   rq   r°   )r€   ÚfnrÑ   r@   ÚitemrÍ   r&   r&   r'   r»   €  s    zPackageIndex.process_filename)Úfatalc                 C   sf   t |ƒ}|o| d¡ ¡ dk}|s8|  tj |¡d ¡r<dS d}|rRt|| ƒ‚n|  ||¡ dS d S )Nr   ÚfileTz¡
Note: Bypassing %s (disallowed host; see https://setuptools.pypa.io/en/latest/deprecated/easy_install.html#restricting-downloads-with-allow-hosts for details).
F)	rº   rI   r,   r¦   r8   r"   r9   r   rÓ   )r€   r<   rÙ   Ú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)rX   rÖ   r-   )r\   r@   Úentryr&   r&   r'   r^   ¢  s
    
ýz.PackageIndex.scan_egg_links.<locals>.<genexpr>)ÚfilterrX   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| 	¡ ƒƒƒ}t
|ƒdkr<d S |\}}ttj ||¡ƒD ](}tjj|f|žŽ |_t|_|  |¡ qVd S )Nr_   )r   rX   r@   rd   r¼   rÞ   rq   rr   rs   Ú
splitlinesrS   r   rM   r   rE   r°   )r€   r@   rÝ   ÚcontentÚlinesZegg_pathZ
setup_pathr±   r&   r&   r'   rá   ª  s    zPackageIndex.scan_egg_linkc                 C   s”   d}|  | j¡s|S tttjj|t| jƒd …  d¡ƒƒ}t|ƒdksRd|d krV|S t	|d ƒ}t
|d ƒ}d| j | ¡ i ¡|< t|ƒt|ƒfS )N©NNr3   r_   r7   r   r   T)r.   rŸ   r¼   rq   r8   r"   r:   rS   r;   r   r   r¥   Ú
setdefaultr,   r   )r€   rÐ   ZNO_MATCH_SENTINELr=   ÚpkgÚverr&   r&   r'   Ú_scanº  s    &zPackageIndex._scanc           	   
   C   sÂ   t  |¡D ]<}z"|  tj |t| d¡ƒ¡¡ W q
 tk
rD   Y q
X q
|  |¡\}}|s^dS t	||ƒD ]H}t
|ƒ\}}| d¡r¦|s¦|rœ|d||f 7 }n
|  |¡ |  |¡ qht dd„ |¡S )z#Process the contents of a PyPI pager   rµ   ú.pyz
#egg=%s-%sc                 S   s   d|   ddd¡ S )Nz<a href="%s#md5=%s">%s</a>r   é   r_   )rI   )Úmr&   r&   r'   Ú<lambda>ä  ó    z,PackageIndex.process_index.<locals>.<lambda>)rt   rn   rì   r8   r"   ru   rv   rI   r#   r}   rD   r-   Úneed_version_infoÚscan_urlÚPYPI_MD5Úsub)	r€   r<   ry   rH   rê   rë   Únew_urlr0   Ú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™   rf   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 )Nr3   r&   )	ró   rŸ   Úunsafe_namer¥   rÅ   ÚkeyrN   Únot_found_in_indexr¼   )r€   Úrequirementr<   r&   r&   r'   Úfind_packagesõ  s    
zPackageIndex.find_packagesc                    sN   |   ¡  |  |¡ | |j D ]"}||kr0|  S |  d||¡ qtƒ  ||¡S )Nz%s does not match %s)Úprescanrÿ   rü   r¾   r¢   Úobtain)r€   rþ   Ú	installerr±   r­   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Æ   rX   Úunlinkr   r   r/   r@   rT   )r€   ÚcheckerrY   Ú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€   Ú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¼   rq   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?))rü   r¿   rÓ   rû   rø   )r€   rþ   Úmethr™   r&   r&   r'   rý   0  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í   rM   N)rÁ   r   rº   Ú_download_urlrD   r-   Ú	gen_setuprX   r@   rÒ   r(   rË   Úfetch_distribution)r€   r$   Útmpdirr>   Úfoundr0   rC   r&   r&   r'   r5   8  s    

zPackageIndex.download)Ú
force_scanÚsourceÚ
develop_okc           	         sà   ˆ  d|¡ tƒ ‰d}d
‡ ‡‡‡‡fdd„	}|rJˆ ¡  ˆ |¡ ||ƒ}|s`|dk	r`|||ƒ}|dkr‚ˆjdk	rzˆ ¡  ||ƒ}|dkr |s ˆ |¡ ||ƒ}|dkrÂˆ dˆr¶dp¸d|¡ dS ˆ  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 ]x}|jtkrHˆ sH|ˆkrˆ d|¡ ˆ |¡ q|| ko^|jtkp^ˆ }|rˆ |jˆ¡}||_t	j
 |j¡r|  S qd S )Nz&Skipping development or system egg: %s)rü   rE   r
   rÓ   r°   r   r5   rM   Údownload_locationrX   r@   rÒ   )ÚreqÚenvr±   ÚtestÚloc©r  r€   Úskippedr  r  r&   r'   rw   x  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)rM   )N)r¿   rp   r   rÿ   r§   rÓ   Úcloner  )	r€   rþ   r  r  r  r  Zlocal_indexr±   rw   r&   r  r'   r  Z  s4    




ýzPackageIndex.fetch_distribution)r  r  c                 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  rM   )r€   rþ   r  r  r  r±   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 	||¡}tj 
|¡r~tj ||¡sŽt ||¡ |}ttj 	|d¡d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&   )rO   )r\   Údr&   r&   r'   Ú
<listcomp>¿  s   þz*PackageIndex.gen_setup.<locals>.<listcomp>r   zsetup.pyÚwzutf-8)ÚencodingzIfrom setuptools import setup
setup(name=%r, version=%r, py_modules=[%r])
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.)rG   rH   r   rI   rS   rX   r@   rT   Údirnamerd   rÒ   ÚsamefileÚshutilÚcopy2ÚopenÚwriterN   rO   Úsplitextr   )	r€   rY   rC   r  rH   rÍ   rT   ÚdstrÚ   r&   r&   r'   r  »  sD    
þÿù
ýþÿ	þÿÿ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’| 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   r4   zcontent-lengthzContent-LengthÚwbr   )r¿   rÆ   rŒ   r–   rÀ   rÁ   r8   rÂ   rÃ   r   r¸   r™   Údl_blocksizeÚget_allÚmaxrq   ÚintÚ
reporthookr%  rÇ   r‚   r&  r  )r€   r<   rY   Úfpr  rÄ   ÚblocknumÚbsÚsizeZsizesr  r   r&   r&   r'   Ú_download_toë  s:    

ÿ



zPackageIndex._download_toc                 C   s   d S re   r&   )r€   r<   rY   r0  Zblksizer2  r&   r&   r'   r.    s    zPackageIndex.reporthookc              
   C   s¦  |  d¡rt|ƒS zt|| jƒW S  ttjjfk
r† } z>d dd„ |j	D ƒ¡}|rb|  
||¡ 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jk
rP } z.|r,|  
||j¡ ntd||jf ƒ|‚W 5 d }~X Y nR tjjtfk
r  } z*|r~|  
||¡ ntd||f ƒ|‚W 5 d }~X Y nX d S )Nr  ú c                 S   s   g | ]}t |ƒ‘qS r&   )rr   )r\   Ú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#   ÚhttpÚclientÚ
InvalidURLrd   rf   rÓ   r   r8   rÂ   rÃ   ÚURLErrorÚreasonÚBadStatusLineÚlineÚHTTPExceptionÚOSError)r€   r<   ÚwarningÚvr™   r&   r&   r'   rÀ     sB    
$ÿþÿÿýzPackageIndex.open_urlc                 C   s   d  d¡}t |d| ¡S )a±  
        Replace unsafe path directives with underscores.

        >>> san = PackageIndex._sanitize
        >>> san('/home/user/.ssh/authorized_keys')
        '_home_user_.ssh_authorized_keys'
        >>> san('..\\foo\\bing')
        '__foo_bing'
        >>> san('D:bar')
        'D_bar'
        >>> san('C:\\bar')
        'C__bar'
        >>> san('foo..bar')
        'foo..bar'
        >>> san('D:../foo')
        'D___foo'
        r¡   )ú:z[/\\]z6(?:(?<=([/\\]|:))\.\.(?=[/\\]|$))|(?:^\.\.(?=[/\\]|$))Ú_)rd   r[   rõ   )r/   r“   r&   r&   r'   Ú	_sanitize5  s    
zPackageIndex._sanitizec                 C   s6   t |ƒ\}}|  |pd¡}t dd|¡}tj ||¡S )aK  
        >>> 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'
        Z__downloaded__z\.egg\.zip$rK   )rD   rE  r[   rõ   rX   r@   rd   )r•   r<   r  r/   Z	_fragmentr&   r&   r'   Ú_resolve_download_filenameR  s    
üz'PackageIndex._resolve_download_filenamec                 C   s$   |   ||¡}|  ||¡p"|  ||¡S )z2
        Determine the download filename.
        )rF  Ú_download_vcsÚ_download_other)r€   r<   r  rY   r&   r&   r'   r  i  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)	r8   r"   Úurlsplitr>   Ú	partitionrp   ÚboolÚnextÚiter)r<   r>   ÚpreÚsepÚpostÚallowedr&   r&   r'   Ú_resolve_vcsp  s    zPackageIndex._resolve_vcsc              
   C   sÈ   |   |¡}|sd S |dkr(td|› ƒ‚| 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 )NrJ  z/Invalid config, SVN download is not supported: r7   zDoing z clone from z to r  z--quietz-CÚcheckoutz--cwdZupz-rz-q)rK  rL  zChecking out )rV  r   rN  Ú_vcs_split_rev_from_urlr¿   Ú
subprocessÚ
check_callÚdict)r€   r<   Zspec_filenameÚvcsrY   rD  ÚrevZco_commandsr&   r&   r'   rG  ƒ  s&    
ÿþzPackageIndex._download_vcsc                 C   sD   t j |¡j}|dkr,t j t j |¡j¡S |  |d¡ |  	||¡S )NrÚ   T)
r8   r"   rM  r>   r¨   Úurl2pathnamer9   r@   r½   Ú_attempt_download)r€   r<   rY   r>   r&   r&   r'   rH  œ  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µ   )r3  rÅ   r,   Ú_invalid_download_html)r€   r<   rY   rÄ   r&   r&   r'   r_  §  s    zPackageIndex._attempt_downloadc                 C   s   t  |¡ td|› ƒ‚d S )NzUnexpected HTML page found at )rX   r  r   )r€   r<   rÄ   rY   r&   r&   r'   r`  ®  s    
z#PackageIndex._invalid_download_htmlc                 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)
        rI  r   r4   r7   ú@Nrµ   )r>   r@   rC   )
r8   r"   rM  r>   r;   r@   rN  Ú
rpartitionÚ_replaceÚgeturl)r<   r=   Zclean_schemeZno_fragment_pathrD  rR  rS  rT  Z
clean_pathr]  Zresolvedr&   r&   r'   rX  ²  s    ü
z$PackageIndex._vcs_split_rev_from_urlc                 G   s   t j|f|žŽ  d S re   )r   r¾   rú   r&   r&   r'   r¾   Ò  s    zPackageIndex.debugc                 G   s   t j|f|žŽ  d S re   )r   r¿   rú   r&   r&   r'   r¿   Õ  s    zPackageIndex.infoc                 G   s   t j|f|žŽ  d S re   )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‹   rr   rO  r’   r°   rÊ   r»   r½   rä   rá   rì   rÌ   rò   rø   rÿ   r  r  r
  r   rý   r5   r  r  r  r*  r3  r.  rÀ   ÚstaticmethodrE  r›   rF  r  rV  rG  rH  ró   r_  r`  rX  r¾   r¿   rÓ   Ú__classcell__r&   r&   r­   r'   r   -  s~       ûû	5

	&    ùúS   ÿ ÿ.$
"



z!&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?c                 C   s   |   d¡}t |¡S )Nr   )rI   r³   Úunescape)rH   Úwhatr&   r&   r'   Údecode_entityá  s    
ri  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_subri  )Útextr&   r&   r'   rv   æ  s    	rv   c                    s   ‡ fdd„}|S )Nc                    s   ‡ ‡fdd„}|S )Nc               	      s2   t  ¡ }t  ˆ¡ zˆ | |ŽW ¢S t  |¡ X d S re   )ÚsocketÚgetdefaulttimeoutÚsetdefaulttimeout)rf   rg   Zold_timeout)ri   Útimeoutr&   r'   Ú_socket_timeoutô  s
    
z@socket_timeout.<locals>._socket_timeout.<locals>._socket_timeoutr&   )ri   rp  ©ro  rh   r'   rp  ó  s    z'socket_timeout.<locals>._socket_timeoutr&   )ro  rp  r&   rq  r'   Úsocket_timeoutò  s    rr  c                 C   s2   t j | ¡}| ¡ }t |¡}| ¡ }| dd¡S )a9  
    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µ   )r8   r"   r:   ÚencodeÚbase64Ú	b64encoderÉ   Úreplace)ÚauthZauth_sZ
auth_bytesZencoded_bytesÚencodedr&   r&   r'   Ú_encode_auth  s
    
rz  c                   @   s0   e Zd ZU dZeed< eed< edœdd„ZdS )Ú
CredentialzŒ
    A username/password pair.

    Displayed separated by `:`.
    >>> str(Credential('username', 'password'))
    'username:password'
    ÚusernameÚpassword)Úreturnc                 C   s   | j › d| j› S )NrC  )r|  r}  rƒ   r&   r&   r'   Ú__str__"  s    zCredential.__str__N)rˆ   r‰   rŠ   r‹   rr   Ú__annotations__r  r&   r&   r&   r'   r{    s   
r{  c                       s8   e Zd Z‡ fdd„Zedd„ ƒZdd„ Zdd„ Z‡  ZS )	Ú
PyPIConfigc                    sN   t  dddgd¡}tƒ  |¡ tj tj d¡d¡}tj |¡rJt	| |ƒ dS )z%
        Load from ~/.pypirc
        r|  r}  Ú
repositoryrµ   ú~z.pypircN)
r[  Úfromkeysr¢   r’   rX   r@   rd   Ú
expanduserrÒ   r   )r€   ÚdefaultsÚ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 )r‚  )rÅ   rs   )r\   Úsectionrƒ   r&   r'   r  4  s   þz2PyPIConfig.creds_by_repository.<locals>.<listcomp>)Úsectionsr[  rq   Ú_get_repo_cred)r€   Zsections_with_repositoriesr&   rƒ   r'   Úcreds_by_repository2  s    
þzPyPIConfig.creds_by_repositoryc                 C   s6   |   |d¡ ¡ }|t|   |d¡ ¡ |   |d¡ ¡ ƒfS )Nr‚  r|  r}  )rÅ   rs   r{  )r€   rˆ  Úrepor&   r&   r'   rŠ  <  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)r‹  Úitemsr.   )r€   r<   r‚  Úcredr&   r&   r'   Úfind_credentialC  s    

zPyPIConfig.find_credential)	rˆ   r‰   rŠ   r’   Úpropertyr‹  rŠ  r  rf  r&   r&   r­   r'   r  &  s
   
	r  c                 C   s@  t j | ¡}|\}}}}}}| d¡r2tj d¡‚|dkrHt|ƒ\}	}
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¡ ||ƒ}|	r<t j |j¡\}}}}}}||kr<||
kr<||||||f}t j |¡|_|S )
z4Open a urllib2 request, handling HTTP authenticationrC  znonnumeric port: '')r8  Úhttpsrè   ú*Authenticating as %s for %s (from .pypirc)zBasic ÚAuthorizationz
User-Agent)r’  )r8   r"   r9   r-   r8  r9  r:  Ú
_splituserr  r  rr   r|  r   r¿   rz  Ú
urlunparser¨   ÚRequestÚ
add_headerÚ
user_agentr<   )r<   rª   Úparsedr>   Únetlocr@   ÚparamsrB   r÷   rx  ÚaddressrŽ  r¿   r=   rö   r¨   r/  Ús2Úh2Úpath2Zparam2Zquery2Zfrag2r&   r&   r'   r7  N  s8    

r7  c                 C   s    |   d¡\}}} |r|nd| fS )zNsplituser('user[:passwd]@host[:port]')
    --> 'user[:passwd]', 'host[:port]'.ra  N)rb  )ÚhostÚuserÚdelimr&   r&   r'   r”  }  s    r”  c                 C   s   | S re   r&   )r<   r&   r&   r'   Ú
fix_sf_urlˆ  s    r£  c                 C   s  t j | ¡\}}}}}}t j |¡}tj |¡r<t j | ¡S | 	d¡rÒtj 
|¡rÒg }t |¡D ]N}	tj ||	¡}
|	dkrˆt|
ƒ} 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 directoriesr3   z
index.htmlz<a href="{name}">{name}</a>)r/   zB<html><head><title>{url}</title></head><body>{files}</body></html>rs  )r<   Úfiles)éÈ   ÚOK)r¹   zPath not foundz	Not foundr´   z	text/html)r8   r"   r9   r¨   r^  rX   r@   Úisfiler©   r-   rÔ   rÖ   rd   r   r  ÚformatÚioÚStringIOrÂ   rÃ   )r<   r>   r?   r@   ÚparamrB   r÷   rY   r¤  rÏ   ÚfilepathÚbodyrÎ   ÚstatusÚmessagerÄ   Zbody_streamr&   r&   r'   r6  Œ  s*    


r6  )N)N)N)r    )_r‹   ru  ÚconfigparserrŽ   r³   Úhttp.clientr8  r©  rß   rX   r[   r#  rl  rY  ÚsysÚurllib.errorr8   Úurllib.parseÚurllib.requestÚfnmatchr   Ú	functoolsr   Útypingr   Zmore_itertoolsr   r!   Úpkg_resourcesr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   Zsetuptools.wheelr   Zunicode_utilsr   r   Ú	distutilsr   Údistutils.errorsr   rš   rG   ÚIrt   rô   rH   rº   r;   rR   Ú__all__Z_SOCKET_TIMEOUTZ_tmplr¨  Úversion_infor˜  r(   r   rD   r   rF   rZ   r   rk   rm   r}   r~   rŒ   r   rõ   rj  ri  rv   rr  rz  r{  ÚRawConfigParserr  r¨   r©   r7  r”  r£  r6  r&   r&   r&   r'   Ú<module>   sœ   @
ÿü
 ÿ	

#
  ÿ
"
!     6
(/