U
    k°ft                     @   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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( ddl)m*Z* ddl+m,Z, dd	l-m.Z. d
dl/m0Z0m1Z1 e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 ZCdCddZDdDdd ZEdEd!d"ZFdedfd#dZGd$d% ZHe2d&ej4ZIeHd'd( ZJG d)d* d*ZKG d+d, d,eKZLG d-d deZMe2d.jNZOd/d0 ZPd1d2 ZQdFd3d4ZRd5d6 ZSG d7d8 d8ZTG d9d: d:ejUZVejWjXfd;d<ZYd=d> ZZeRe<eYZYd?d@ Z[dAdB Z\dS )Gz$PyPI and direct package downloading.    Nwraps)CHECKOUT_DISTDistributionBINARY_DISTnormalize_pathSOURCE_DISTEnvironmentfind_distributions	safe_namesafe_versionto_filenameRequirementDEVELOP_DISTEGG_DISTparse_version)log)DistutilsError)	translate)Wheelunique_everseen   )_read_utf8_with_fallback_cfg_read_utf8_with_fallbackz^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%   7lib/python3.8/site-packages/setuptools/package_index.pyparse_requirement_argH   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.exeNiZwin32z	.win32-pyiiz.win-amd64.exeiz	win-amd64z.win-amd64-pyi)lowerendswith
startswith)namer*   basepy_verZplatr%   r%   r&   r   Q   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pathZ
parametersqueryfragmentr.   r%   r%   r&   egg_info_for_urli   s    r@   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)r@   distros_for_locationEGG_FRAGMENTmatchr   groupr   )r9   metadatar.   r?   rD   r%   r%   r&   r   t   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	rt|\}}}|dk	rt	| |||t
|S tD ]0}| |r|dt|  }t	| ||  S qg S )
z:Yield egg or source distribution objects based on basename.egg.zipNr)   z.egg-z.whlr   )locationproject_nameversionrA   r(   )r+   r   Zfrom_locationr   Zis_compatiblerJ   rK   r   r   r   r   
EXTENSIONSlen)rI   basenamerF   ZwheelZwin_baser/   platformZextr%   r%   r&   rB      s>    
	
     
rB   c                 C   s   t t| tj| |S )zEYield possible egg or source distribution objects based on a filename)rB   r   osr=   rN   )filenamerF   r%   r%   r&   distros_for_filename   s
     
 rR   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 )zGenerate 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!
    rH   c                 s   s   | ]}t d |V  qdS )z	py\d\.\d$N)rerD   ).0pr%   r%   r&   	<genexpr>   s     z(interpret_distro_name.<locals>.<genexpr>   Nr   )
py_versionrA   rO   )r8   anyrangerM   isdigitr   join)rI   rN   rF   rX   rA   rO   r:   rU   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   )ra   rb   r%   r`   r&   unique_values   s    rc   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homepager2   r   )z<th>Home Pagez<th>Download URLr1   N)RELfinditergroupssetmapstrstripr*   r8   HREFr5   r!   urljoin
htmldecoderE   findsearch)r9   pagerD   tagZrelZrelsposr%   r%   r&   find_external_links   s    
rt   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%   rw   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%   )rw   reportertemplater%   r%   r&   report  s    zContentChecker.reportN)__name__
__module____qualname____doc__ry   r{   r~   r%   r%   r%   r&   ru      s   ru   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 r]   )	hash_namehashlibnewhashexpected)rw   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 URLr1   )r5   r!   r6   ru   patternrp   	groupdict)clsr9   r?   rD   r%   r%   r&   from_url  s    zHashChecker.from_urlc                 C   s   | j | d S r]   )r   updaterv   r%   r%   r&   ry   !  s    zHashChecker.feedc                 C   s   | j  | jkS r]   )r   Z	hexdigestr   rz   r%   r%   r&   r{   $  s    zHashChecker.is_validc                 C   s   || j  }||S r]   )r   )rw   r|   r}   msgr%   r%   r&   r~   '  s    
zHashChecker.reportN)r   r   r   rS   compiler   r   classmethodr   ry   r{   r~   r%   r%   r%   r&   r     s   

r   c                       sV  e Zd ZdZdN fdd	Z fdd	ZdOddZdPddZdQddZd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/d0 Zd1Zd2d3 Zd4d5 ZdVd6d7Zd8d9 Ze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                    sh   t  j|| |dd |d   | _i | _i | _i | _td	t
t|j| _g | _tjj| _d S )Nr0   |)superr   r+   	index_urlscanned_urlsfetched_urlspackage_pagesrS   r   r\   ri   r   rD   allowsto_scanr5   requesturlopenopener)rw   r   ZhostsZ	ca_bundleZ
verify_sslr^   kw	__class__r%   r&   r   /  s    	zPackageIndex.__init__c                    s2   zt |j W n tk
r$   Y d S X t |S r]   )r   rK   	Exceptionr   add)rw   distr   r%   r&   r   A  s
    zPackageIndex.addFc                 C   s  t drtd| || jkr(|s(dS d| j|< t|sH| | dS tt|}|rr| |sfdS | 	d| |s|r|| j
krtt| j| dS | |sd| j
|< dS | d| d| j
|< d}| ||| }|dkrdS t|tjjr|jdkr| d	|j  d| j
|j< d
|jdd krB|  dS |j}| }t|tst|tjjrrd}n|jdpd}||d}|  t|D ](}	tj !|t"|	#d}
| $|
 q|%| j&rt'|dddkr| (||}dS )z<Evaluate a URL as a possible download, and maybe retrieve itZCONDA_BUILDzkSetuptools downloading is disabled in conda build. Be sure to add all dependencies in the meta.yaml  url=%sNTz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  ))rP   getenvRuntimeErrorr   
URL_SCHEMEprocess_filenamelistr   url_okdebugr   ri   r   infoopen_url
isinstancer5   error	HTTPErrorr   r   r9   headersgetr*   closereadrj   Z	get_paramdecoderl   rf   r!   rm   rn   rE   process_urlr,   r   getattrprocess_index)rw   r9   Zretrievediststmplfr.   rq   r   rD   linkr%   r%   r&   r   J  s\    






 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)rP   r=   existswarnisdirrealpathlistdirr   r\   rR   r   r   ri   r   )rw   fnnestedr=   itemr   r%   r%   r&   r     s    zPackageIndex.process_filenamec                 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   rE   r*   r   r5   r!   r6   r   r   )rw   r9   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)rP   r   r+   )rT   r=   entryr%   r%   r&   rV     s
    
z.PackageIndex.scan_egg_links.<locals>.<genexpr>)filterrP   r=   r   r   	itertoolsstarmapscan_egg_link)rw   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 )NrW   )r   rP   r=   r\   r   r   ri   rj   rk   
splitlinesrM   r
   rI   r   rA   r   )rw   r=   r   Z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)NNr0   rW   r4   r   r   T)r,   r   r   ri   r5   r!   r7   rM   r8   r   r   r   
setdefaultr*   r   )rw   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      rW   )rE   )mr%   r%   r&   <lambda>      z,PackageIndex.process_index.<locals>.<lambda>)rl   rf   r   r5   r!   rm   rn   rE   r"   rt   r@   r+   need_version_infoscan_urlPYPI_MD5sub)	rw   r9   rq   rD   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rw   r9   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   rw   r   r^   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 )Nr0   r%   )	r   r   unsafe_namer   r   keyrJ   not_found_in_indexr   )rw   requirementr9   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)rw   r   Z	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   rP   unlinkr   r   r-   r=   rN   )rw   checkerrQ   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)rw   Zurlsr9   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   ri   r   rz   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   )rw   r   methr   r%   r%   r&   r   3  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   rI   N)r   r   r   _download_urlr@   r+   	gen_setuprP   r=   r   r'   r   fetch_distribution)rw   r#   tmpdirr;   foundr.   r?   r%   r%   r&   r2   >  s    

zPackageIndex.downloadc           	         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rdpd| 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   rA   r   r   r   r   r2   rI   download_locationrP   r=   r   )Zreqenvr   ZtestZloc
develop_okrw   Zskippedsourcer   r%   r&   ro   ~  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)rI   )N)r   rh   r   r   r   r   cloner   )	rw   r   r   
force_scanr  r  Zlocal_indexr   ro   r%   r  r&   r   `  s4    




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   rI   )rw   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rtj|}tj||krtj	||}tj
|r~tj||st|| |}ttj	|dddd2}|d|d	 j|d	 jtj|d	 f  W 5 Q R X |S |rtd
||f ntdd S )Nc                 S   s   g | ]}|j r|qS r%   )rK   )rT   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   zCan'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.)rC   rD   r   rE   rM   rP   r=   rN   dirnamer\   r   samefileshutilZcopy2openwriterJ   rK   splitextr   )	rw   rQ   r?   r   rD   r   rN   Zdstr   r%   r%   r&   r     sD    

	zPackageIndex.gen_setupi    c              	   C   s  |  d| d }zt|}| |}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 }| ||||| qqq| |||
 W 5 Q R X |W S |r|  X d S )	NzDownloading %szCan't download %s: %s %sr   r1   zcontent-lengthzContent-Lengthwbr   )r   r   r   r   r   r   r5   r   r   r   r   r   dl_blocksizeZget_allmaxri   int
reporthookr  r   ry   r  r   )rw   r9   rQ   fpr   r   blocknumZbssizeZsizesr   rx   r%   r%   r&   _download_to  s:    





zPackageIndex._download_toc                 C   s   d S r]   r%   )rw   r9   rQ   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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%   )rj   )rT   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
InvalidURLr\   r^   r   r   r5   r   r   ZURLErrorreasonZBadStatusLinelineZHTTPExceptionOSError)rw   r9   Zwarningvr   r%   r%   r&   r     sB    
$zPackageIndex.open_urlc                 C   sp   t |\}}|r0d|kr4|dddd}qnd}|drJ|d d }tj||}| ||pn| ||S )Nz...\_Z__downloaded__rG   r)   )r@   replacer+   rP   r=   r\   _download_vcs_download_other)rw   r9   r   r-   r?   rQ   r%   r%   r&   r   9  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)	r5   r!   urlsplitr;   	partitionrh   boolnextiter)r9   r;   preseppostZallowedr%   r%   r&   _resolve_vcsJ  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 )Nr-  z/Invalid config, SVN download is not supported: r4   zDoing z clone from z to r  z--quietz-CZcheckoutz--cwdZupz-rz-q)r.  r/  zChecking out )r8  r   r1  _vcs_split_rev_from_urlr   
subprocessZ
check_calldict)rw   r9   Zspec_filenameZvcsrQ   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)
r5   r!   r0  r;   r   url2pathnamer6   r=   r   _attempt_download)rw   r9   rQ   r;   r%   r%   r&   r+  v  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*   _invalid_download_html)rw   r9   rQ   r   r%   r%   r&   r>    s    zPackageIndex._attempt_downloadc                 C   s   t | td| d S )NzUnexpected HTML page found at )rP   r   r   )rw   r9   r   rQ   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)
        r,  r   r1   r4   @Nr   )r;   r=   r?   )
r5   r!   r0  r;   r8   r=   r1  
rpartition_replaceZgeturl)r9   r:   Zclean_schemeZno_fragment_pathr(  r5  r6  r7  Z
clean_pathr<  Zresolvedr%   r%   r&   r9    s    
z$PackageIndex._vcs_split_rev_from_urlc                 G   s   t j|f|  d S r]   )r   r   r   r%   r%   r&   r     s    zPackageIndex.debugc                 G   s   t j|f|  d S r]   )r   r   r   r%   r%   r&   r     s    zPackageIndex.infoc                 G   s   t j|f|  d S r]   )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   r   r   r2   r   r  r   r  r  r  r   r   staticmethodr8  r*  r+  r   r>  r?  r9  r   r   r   __classcell__r%   r%   r   r&   r   ,  s^       	
9



	&    
R
.$
"

z!&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?c                 C   s   |  d}t|S )Nr   )rE   r   Zunescape)rD   Zwhatr%   r%   r&   decode_entity  s    
rE  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_subrE  )textr%   r%   r&   rn     s    	rn   c                    s    fdd}|S )Nc                    s    fdd}|S )Nc               	      s2   t  }t  z | |W S t | X d S r]   )socketZgetdefaulttimeoutZsetdefaulttimeout)r^   r_   Zold_timeout)ra   timeoutr%   r&   _socket_timeout  s
    
z@socket_timeout.<locals>._socket_timeout.<locals>._socket_timeoutr%   )ra   rJ  rI  r`   r&   rJ    s    z'socket_timeout.<locals>._socket_timeoutr%   )rI  rJ  r%   rK  r&   socket_timeout  s    rL  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   )r5   r!   r7   encodebase64Z	b64encoder   r)  )authZauth_sZ
auth_bytesZencoded_bytesZencodedr%   r%   r&   _encode_auth  s
    
rQ  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 r]   usernamepassword)rw   rT  rU  r%   r%   r&   r     s    zCredential.__init__c                 c   s   | j V  | jV  d S r]   rS  rz   r%   r%   r&   __iter__  s    zCredential.__iter__c                 C   s   dt |  S )Nz%(username)s:%(password)s)varsrz   r%   r%   r&   __str__  s    zCredential.__str__N)r   r   r   r   r   rV  rX  r%   r%   r%   r&   rR    s   rR  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
        rT  rU  
repositoryr   ~z.pypircN)
r;  fromkeysr   r   rP   r=   r\   
expanduserr   r   )rw   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 )rZ  )r   rk   )rT   sectionrz   r%   r&   r	    s   z2PyPIConfig.creds_by_repository.<locals>.<listcomp>)Zsectionsr;  ri   _get_repo_cred)rw   Zsections_with_repositoriesr%   rz   r&   creds_by_repository  s    
zPyPIConfig.creds_by_repositoryc                 C   s6   |  |d }|t|  |d |  |d fS )NrZ  rT  rU  )r   rk   rR  )rw   r_  Z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)ra  itemsr,   )rw   r9   rZ  credr%   r%   r&   find_credential  s    

zPyPIConfig.find_credential)	r   r   r   r   propertyra  r`  rd  rD  r%   r%   r   r&   rY    s
   
	rY  c                 C   s<  t j| }|\}}}}}}|dr2tjd|dkrHt|\}	}
nd}	|	st 	| }|rt
|}	|j| f}tjd	|  |	rdt|	 }	||
||||f}t j|}t j|}|d|	 nt j| }|dt ||}|	r8t j|j\}}}}}}||kr8||
kr8||||||f}t j||_|S )
z4Open a urllib2 request, handling HTTP authentication:znonnumeric port: '')r  ZhttpsN*Authenticating as %s for %s (from .pypirc)zBasic ZAuthorizationz
User-Agent)rg  )r5   r!   r6   r+   r  r   r!  
_splituserrY  rd  rj   rT  r   r   rQ  Z
urlunparser   ZRequestZ
add_header
user_agentr9   )r9   r   Zparsedr;   Znetlocr=   Zparamsr>   r   rP  Zaddressrc  r   r:   r   r   r  s2Zh2Zpath2Zparam2Zquery2Zfrag2r%   r%   r&   r  )  s8    

r  c                 C   s    |  d\}}} |r|nd| fS )zNsplituser('user[:passwd]@host[:port]')
    --> 'user[:passwd]', 'host[:port]'.r@  N)rA  )ZhostuserZdelimr%   r%   r&   rh  X  s    rh  c                 C   s   | S r]   r%   )r9   r%   r%   r&   
fix_sf_urlc  s    rl  c                 C   s  t j| \}}}}}}t j|}tj|r<t j| S |	drtj
|rg }t|D ]N}	tj||	}
|	dkrt|
} qn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 directoriesr0   z
index.htmlz<a href="{name}">{name}</a>)r-   zB<html><head><title>{url}</title></head><body>{files}</body></html>rM  )r9   files)   ZOK)r   zPath not foundz	Not foundr   z	text/html)r5   r!   r6   r   r=  rP   r=   isfiler   r+   r   r   r\   r   r   formatioStringIOr   r   )r9   r;   r<   r=   Zparamr>   r   rQ   rm  r   filepathZbodyr   Zstatusmessager   Zbody_streamr%   r%   r&   r  g  s*    


r  )N)N)N)r   )]r   sysr:  rP   rS   rq  r  rH  rO  r   r   Zconfigparserr   Zhttp.clientr  Zurllib.parser5   Zurllib.requestZurllib.error	functoolsr   r    Zpkg_resourcesr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   	distutilsr   Zdistutils.errorsr   Zfnmatchr   Zsetuptools.wheelr   Zmore_itertoolsr   Zunicode_utilsr   r   r   rC   Irl   r   rD   r   r8   rL   __all__Z_SOCKET_TIMEOUTZ_tmplrp  version_infori  r'   r   r@   r   rB   rR   r   rc   re   rt   ru   r   r   r   rF  rE  rn   rL  rQ  rR  ZRawConfigParserrY  r   r   r  rh  rl  r  r%   r%   r%   r&   <module>   s   @

 	

#
  
"
!     
(/