a
    6Rhk                     @  s  d Z ddlm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/m0Z0m1Z1 ddl2m3Z3 ddl4m5Z5 e6dZ7e6dej8Z9e6dZ:e6dej8j;Z<d= Z>g dZ?dZ@dejA dejBjC dejBjD ZEdd ZFdd ZGdd ZHdFddZIdGd d!ZJdHd"d#ZKde#dfd$d%ZLd&d' ZMe6d(ej8ZNeMd)d* ZOG d+d, d,ZPG d-d. d.ePZQG d/d0 d0e%ZRe6d1jSZTd2d3 ZUd4d5 ZVdId6d7ZWd8d9 ZXG d:d; d;eZYG d<d= d=ejZZ[ej\j]fd>d?Z^d@dA Z_eWe@e^Z^dBdC Z`dDdE ZadS )Jz$PyPI and direct package downloading.    )annotationsN)	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/z Python-urllib/.c              
   C  sF   zt | W S  ty@ } ztd| |W Y d }~n
d }~0 0 d S )Nz/Not a URL, existing file, or requirement spec: )r   parse
ValueErrorr   )spece r'   N/opt/python-3.9.24/usr/lib/python3.9/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.exeNiwin32z	.win32-pyiiz.win-amd64.exeiz	win-amd64z.win-amd64-pyi)lowerendswith
startswith)namer-   basepy_verplatr'   r'   r(   r   Q   s$    



r   c           	      C  sx   t j| }|\}}}}}}t j|dd }|dkrX|dkrXt j|dd }d|v rp|dd\}}||fS )N/zsourceforge.netdownload#r   )urllibr#   urlparseunquotesplit)	urlparts_schemeserverpath_parameters_queryfragmentr1   r'   r'   r(   egg_info_for_urli   s    rE   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)rE   distros_for_locationEGG_FRAGMENTmatchr    groupr
   )r=   metadatar1   rD   rI   r'   r'   r(   r   t   s    
r   c                 C  s   | dr|dd }| dr8d|v r8t| ||gS | drxd|v rxt|}| s^g S t| |j|jtd dgS | d	rt|\}}}|durt	| |||t
|S tD ]0}| |r|dt|  }t	| ||  S qg S )
z:Yield egg or source distribution objects based on basenamez.egg.zipNr,   .egg-z.whlr   )locationproject_nameversionrF   r*   )r.   r   from_locationr   is_compatiblerO   rP   r   r   r    r	   
EXTENSIONSlen)rN   basenamerK   wheelZwin_baser2   platformextr'   r'   r(   rG      s4    
	

rG   c                 C  s   t t| tj| |S )zEYield possible egg or source distribution objects based on a filename)rG   r   osrA   rU   )filenamerK   r'   r'   r(   distros_for_filename   s    r[   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!
    rM   c                 s  s   | ]}t d |V  qdS )z	py\d\.\d$N)rerI   ).0pr'   r'   r(   	<genexpr>       z(interpret_distro_name.<locals>.<genexpr>   Nr   )
py_versionrF   rW   )r<   anyrangerT   isdigitr   join)rN   rU   rK   rb   rF   rW   r>   r^   r'   r'   r(   r       s     

r    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  | i |S Nr   )argskwargsfuncr'   r(   wrapper   s    zunique_values.<locals>.wrapperr   )rk   rl   r'   rj   r(   unique_values   s    rm   z3<([^>]*\srel\s{0,10}=\s{0,10}['"]?([^'" >]+)[^>]*)>c              	   c  s   t |D ]d}| \}}tttj| d}d|v sDd|v 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homepager6   r   )z<th>Home Pagez<th>Download URLr5   N)RELfinditergroupssetmapstrstripr-   r<   HREFr9   r#   urljoin
htmldecoderJ   findsearch)r=   pagerI   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                   @  sH   e Zd ZedZdd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]+)Nonereturnc                 C  s   || _ t|| _|| _d S rg   )	hash_namehashlibnewhashexpected)r   r   r   r'   r'   r(   __init__  s    zHashChecker.__init__c                 C  sB   t j|d }|st S | j|}|s0t S | f i | S )z5Construct a (possibly null) ContentChecker from a URLr5   )r9   r#   r:   r   patternrz   	groupdict)clsr=   rD   rI   r'   r'   r(   from_url  s    zHashChecker.from_urlc                 C  s   | j | d S rg   )r   updater   r'   r'   r(   r   !  s    zHashChecker.feedc                 C  s   | j  | jkS rg   )r   	hexdigestr   r   r'   r'   r(   r   $  s    zHashChecker.is_validc                 C  s   || j  }||S rg   )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d^dddd	 fd
dZ fddZd_dddddZd`dddddZdadddddZddddZ	ddddZ
dd Zdd  Zddd!d"Zdbddd#d$Zddd%d&Zdc fd'd(	Zddd)d*Zddd+d,Zd-d. Zddd/d0Zd1d2 Zdddddd3d4d5d6Zdeddd7d8d9d:Zd;d< Zd=Zd>d? Zddd@dAZdfdBdCZedDdE ZedFdG Z dHdI Z!edJdK Z"dLdM Z#dNdO Z$dddPdQZ%dRdS Z&dTdU Z'edVdW Z(dddXdYZ)dddZd[Z*ddd\d]Z+  Z,S )gr   z;A distribution index that scans web pages for download URLshttps://pypi.org/simple/*NTrt   boolr   )	index_url
verify_sslr   c                   sl   t  j|i | |dd |d   | _i | _i | _i | _td	t
t|j| _g | _tjj| _d S )Nr4   |)superr   r.   r   scanned_urlsfetched_urlspackage_pagesr\   r   rf   rs   r   rI   allowsto_scanr9   requesturlopenopener)r   r   hostsZ	ca_bundler   rh   kw	__class__r'   r(   r   /  s    	zPackageIndex.__init__c                   s0   zt |j W n ty"   Y d S 0 t |S rg   )r   rP   	Exceptionr   add)r   distr   r'   r(   r   A  s
    zPackageIndex.addF)retriever   c                 C  s  || j v r|sdS d| j |< t|s2| | dS tt|}|r\| |sPdS | d| |sn|rn|| jv rtt| j	| dS | |sd| j|< dS | 
d| d| j|< d}| ||| }|du rdS t|tjjr|jdkr| 
d|j  d| j|j< d|jd	d
 vr*|  dS |j}| }t|tsxt|tjjrZd}n|jdpjd}||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 itNTzFound link: %sz
Reading %sz<Download error on %s: %%s -- Some packages may not be found!i  zAuthentication error: htmlcontent-type zlatin-1charsetignorer   code  )&r   
URL_SCHEMEprocess_filenamelistr   url_okdebugr   rs   r   infoopen_url
isinstancer9   error	HTTPErrorr   r   r=   headersgetr-   closereadrt   	get_paramdecoderv   rp   r#   rw   rx   rJ   process_urlr/   r   getattrprocess_index)r   r=   r   diststmplfr1   r{   r   rI   linkr'   r'   r(   r   J  sT    





 zPackageIndex.process_url)nestedr   c                 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)rY   rA   existswarnisdirrealpathlistdirr   rf   r[   r   r   rs   r   )r   fnr   rA   itemr   r'   r'   r(   r     s    zPackageIndex.process_filename)fatalr   c                 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   rJ   r-   r   r9   r#   r:   r   r   )r   r=   r   sis_filer   r'   r'   r(   r     s    zPackageIndex.url_okr   c                 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)rY   r   r.   )r]   rA   entryr'   r'   r(   r_     s   
z.PackageIndex.scan_egg_links.<locals>.<genexpr>)filterrY   rA   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|g|R  |_t|_| | qVd S )Nra   )r   rY   rA   rf   r   r   rs   rt   ru   
splitlinesrT   r   rN   r   rF   r   )r   rA   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 v rV|S t	|d }t
|d }d| j| i |< t|t|fS )NNNr4   ra   r8   r   r   T)r/   r   r   rs   r9   r#   r;   rT   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yB   Y q
0 q
| |\}}|s\dS t	||D ]L}t
|\}}|dr|s|r|d| d| 7 }n
| | | | qftdd |S )z#Process the contents of a PyPI pager   r   .pyz#egg=rM   c                 S  s   dj | ddd S )Nz<a href="{}#md5={}">{}</a>r      ra   )formatrJ   )mr'   r'   r(   <lambda>  r`   z,PackageIndex.process_index.<locals>.<lambda>)rv   rp   r   r9   r#   rw   rx   rJ   r$   r   rE   r.   need_version_infoscan_urlPYPI_MD5sub)	r   r=   r{   rI   r   r   new_urlr1   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vr,|r"| j|g|R   | d | | j  d S )Nz6Scanning index of all packages (this may take a while))r   r   r   r   r   r   r   rh   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 )Nr4   r'   )	r   r   unsafe_namer   r   keyrO   not_found_in_indexr   )r   requirementr=   r'   r'   r(   find_packages  s    
zPackageIndex.find_packagesc                   sN   |    | | | |j D ]"}||v 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  sR   | | jd|  | sN|  t| t|jj dtj	
| ddS )z-
        checker is a ContentChecker
        zValidating %s checksum for z validation failed for z; possible download problem?N)r   r   r   r   rY   unlinkr   r   r0   rA   rU   )r   checkerrZ   tfpr'   r'   r(   
check_hash  s    
zPackageIndex.check_hashc                 C  sN   |D ]D}| j du 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   rs   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  .  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   rN   N)r   r   r   _download_urlrE   r.   	gen_setuprY   rA   r   r)   r   fetch_distribution)r   r%   tmpdirschemefoundr1   rD   r'   r'   r(   r6   6  s    

zPackageIndex.downloadzDistribution | None)
force_scansource
develop_okr   c           	        s    d| t d}ddd fdd}|rP  | ||}|sf|durf|||}|du rjdur  ||}|du r|s| ||}|du 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 %sNzEnvironment | None)envc                   s   |d u r}|| j  D ]x}|jtkrH sH|vrd| | q|| v o^|jtkp^ }|r|j}||_t	j
|jr|  S qd S )Nz&Skipping development or system egg: %s)r  rF   r   r   r   r   r6   rN   download_locationrY   rA   r   )reqr  r   testlocr  r   Zskippedr  r  r'   r(   ry   v  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)rN   )N)r   rr   r  r  r   r   cloner  )	r   r  r  r  r  r  Zlocal_indexr   ry   r'   r   r(   r  X  s4    




zPackageIndex.fetch_distributionz
str | None)r  r  r   c                 C  s"   |  ||||}|du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  rN   )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rtj	||}tj
|rtj||st|| |}ttj	|ddddF}|d|d	 jd
|d	 jdtj|d	 d W d    n1 s0    Y  |S |rtd|d|ntdd S )Nc                 S  s   g | ]}|j r|qS r'   )rP   )r]   dr'   r'   r(   
<listcomp>  s   z*PackageIndex.gen_setup.<locals>.<listcomp>r   zsetup.pywzutf-8)encodingz(from setuptools import setup
setup(name=r   z
, version=z, py_modules=[z])
z9Can't unambiguously interpret project/version identifier zI; any dashes in the name or version should be escaped using underscores. zpCan't process plain .py files without an '#egg=name-version' suffix to enable automatic setup script generation.)rH   rI   r    rJ   rT   rY   rA   rU   dirnamerf   r   samefileshutilcopy2openwriterO   rP   splitextr   )	r   rZ   rD   r  rI   r   rU   dstr   r'   r'   r(   r    sF    

"zPackageIndex.gen_setupi    c                 C  sB  |  d| d }zt|}| |}t|tjjrTtd| d|j	 d|j
 |  }d}| j}d}d|v r|d}	ttt|	}| ||||| t|d	`}
||}|r|| |
| |d
7 }| ||||| qqq| |||
 W d    n1 s0    Y  |W |r*|  S n|r<|  0 d S )NzDownloading %szCan't download :  r   r5   zcontent-lengthzContent-Lengthwbr   )r   r   r   r   r   r9   r   r   r   r   r   dl_blocksizeget_allmaxrs   int
reporthookr+  r   r   r,  r  r   )r   r=   rZ   fpr
  r   blocknumbssizesizesr  r   r'   r'   r(   _download_to  s@    





. zPackageIndex._download_toc                 C  s   d S rg   r'   )r   r=   rZ   r8  Zblksizer:  r'   r'   r(   r6    s    zPackageIndex.reporthookc              
   C  s  | drt|S zt|| jW S  ttjjfy } zJddd |j	D }|r`| 
|| nt| d| |W Y d }~n2d }~0  tjjy } z|W  Y d }~S d }~0  tjjy } z8|r| 
||j ntd| d|j |W Y d }~nd }~0  tjjy\ } z8|r2| 
||j nt| d|j |W Y d }~n`d }~0  tjjtfy } z6|r| 
|| ntd| d| |W Y d }~n
d }~0 0 d S )Nr  r0  c                 S  s   g | ]}t |qS r'   )rt   )r]   argr'   r'   r(   r$    r`   z)PackageIndex.open_url.<locals>.<listcomp>zDownload error for r/  z7 returned a bad status line. The server might be down, )r/   
local_openopen_with_authr   r$   httpclient
InvalidURLrf   rh   r   r   r9   r   r   URLErrorreasonBadStatusLinelineHTTPExceptionOSError)r   r=   warningvr   r'   r'   r(   r   
  s:    
*,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(?:(?<=([/\\]|:))\.\.(?=[/\\]|$))|(?:^\.\.(?=[/\\]|$))_)rf   r\   r   )r0   r   r'   r'   r(   	_sanitize*  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$rL   )rE   rM  r\   r   rY   rA   rf   )r   r=   r  r0   Z	_fragmentr'   r'   r(   _resolve_download_filenameG  s    
z'PackageIndex._resolve_download_filenamec                 C  s$   |  ||}| ||p"| ||S )z2
        Determine the download filename.
        )rN  _download_vcs_download_other)r   r=   r  rZ   r'   r'   r(   r  ^  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)	r9   r#   urlsplitr  	partitionrr   r   nextiter)r=   r  presep_postallowedr'   r'   r(   _resolve_vcse  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 ur| d|  t||  |S )NrR  z/Invalid config, SVN download is not supported: r8   zDoing z clone from z to r!  z--quietz-Ccheckoutz--cwdupz-rz-q)rS  rT  zChecking out )r]  r   rV  _vcs_split_rev_from_urlr   
subprocess
check_calldict)r   r=   Zspec_filenamevcsrZ   rL  revZco_commandsr'   r'   r(   rO  x  s&    
zPackageIndex._download_vcsc                 C  sD   t j|j}|dkr,t jt j|jS | |d | 	||S )Nr   T)
r9   r#   rU  r  r   url2pathnamer:   rA   r   _attempt_download)r   r=   rZ   r  r'   r'   r(   rP    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 v r.| |||S |S d S )Nr   r   r   )r<  r   r-   _invalid_download_html)r   r=   rZ   r   r'   r'   r(   rg    s    zPackageIndex._attempt_downloadc                 C  s   t | td| d S )NzUnexpected HTML page found at )rY   r	  r   )r   r=   r   rZ   r'   r'   r(   rh    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)
        rQ  r   r5   r8   @Nr   )r  rA   rD   )
r9   r#   rU  r  r<   rA   rV  
rpartition_replacegeturl)r=   r>   Zclean_schemeZno_fragment_pathrL  rY  rZ  postZ
clean_pathre  resolvedr'   r'   r(   r`    s    
z$PackageIndex._vcs_split_rev_from_urlc                 G  s   t j|g|R   d S rg   )r   r   r   r'   r'   r(   r     s    zPackageIndex.debugc                 G  s   t j|g|R   d S rg   )r   r   r   r'   r'   r(   r     s    zPackageIndex.infoc                 G  s   t j|g|R   d S rg   )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  r6   r  r"  r  r2  r<  r6  r   staticmethodrM  r   rN  r  r]  rO  rP  r   rg  rh  r`  r   r   r   __classcell__r'   r'   r   r(   r   ,  sh       	5
	&    S )"
 



r   z!&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?c                 C  s   |  d}t|S )Nr   )rJ   r   unescape)rI   whatr'   r'   r(   decode_entity  s    
rs  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_subrs  )textr'   r'   r(   rx     s    	rx   c                   s    fdd}|S )Nc                   s    fdd}|S )Nc               	     s>   t  }t  z | i |W t | S t | 0 d S rg   )socketgetdefaulttimeoutsetdefaulttimeout)rh   ri   Zold_timeout)rk   timeoutr'   r(   _socket_timeout  s    

z@socket_timeout.<locals>._socket_timeout.<locals>._socket_timeoutr'   )rk   rz  ry  rj   r(   rz    s    z'socket_timeout.<locals>._socket_timeoutr'   )ry  rz  r'   r{  r(   socket_timeout  s    r|  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   )r9   r#   r;   encodebase64	b64encoder   replace)authZauth_sZ
auth_bytesZencoded_bytesencodedr'   r'   r(   _encode_auth  s
    
r  c                   @  s0   e Zd ZU dZded< ded< ddddZdS )	
Credentialz
    A username/password pair.

    Displayed separated by `:`.
    >>> str(Credential('username', 'password'))
    'username:password'
    rt   usernamepasswordr   c                 C  s   | j  d| j S )NrK  )r  r  r   r'   r'   r(   __str__  s    zCredential.__str__N)r   r   r   r   __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                   sL   t g dd}t | tjtjdd}tj|rHt	| | dS )z%
        Load from ~/.pypirc
        )r  r  
repositoryr   ~z.pypircN)
rc  fromkeysr   r   rY   rA   rf   
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   ru   )r]   sectionr   r'   r(   r$  )  s   z2PyPIConfig.creds_by_repository.<locals>.<listcomp>)sectionsrc  rs   _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 )Nr  r  r  )r   ru   r  )r   r  repor'   r'   r(   r  1  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_credential8  s    

zPyPIConfig.find_credential)	r   r   r   r   propertyr  r  r  rp  r'   r'   r   r(   r    s
   
	r  c                 C  sD  t j| }|\}}}}}}|dr2tjd|dv rHt|\}	}
nd\}	}
|	st 	| }|rt
|}	|j| f}tjdg|R   |	rd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 authenticationrK  znonnumeric port: '')r@  httpsr   z*Authenticating as %s for %s (from .pypirc)zBasic Authorizationz
User-Agent)r9   r#   r:   r.   r@  rA  rB  
_splituserr  r  rt   r  r   r   r  
urlunparser   Request
add_header
user_agentr=   )r=   r   parsedr  netlocrA   paramsqueryr   r  addressr  r   r>   r   r   r7  s2Zh2Zpath2Zparam2Zquery2Zfrag2r'   r'   r(   r?  C  s8    

r?  c                 C  s    |  d\}}} |r|nd| fS )zNsplituser('user[:passwd]@host[:port]')
    --> 'user[:passwd]', 'host[:port]'.ri  N)rj  )hostuserdelimr'   r'   r(   r  s  s    r  c                 C  s   | S rg   r'   )r=   r'   r'   r(   
fix_sf_url~  s    r  c                 C  s  t j| \}}}}}}t j|}tj|r<t j| S |	drtj
|rg }t|D ]T}	tj||	}
|	dkrt|
} qntj
|
r|	d7 }	|d|	 d|	 d q`d}|j| d|d}d	\}}n
d
\}}}ddi}t|}t j| ||||S )z7Read a local path, with special support for directoriesr4   z
index.htmlz	<a href="z">z</a>zB<html><head><title>{url}</title></head><body>{files}</body></html>r}  )r=   files)   OK)r   zPath not foundz	Not foundr   z	text/html)r9   r#   r:   r   rf  rY   rA   isfiler   r.   r   r   rf   r   r  r   ioStringIOr   r   )r=   r?   _serverrA   Z_paramrC   Z_fragrZ   r  r   filepathbodyr   statusmessager   Zbody_streamr'   r'   r(   r>    s*    


r>  )N)N)N)r!   )br   
__future__r   r  configparserr   r   http.clientr@  r  r   rY   r\   r)  rv  ra  sysurllib.errorr9   urllib.parseurllib.requestfnmatchr   	functoolsr   typingr   Zmore_itertoolsr   
setuptools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   rH   Irv   r   rI   r   r<   rS   __all__Z_SOCKET_TIMEOUT__version__version_infomajorminorr  r)   r   rE   r   rG   r[   r    rm   ro   r   r   r   r   r   rt  rs  rx   r|  r  r  RawConfigParserr  r   r   r?  r  r  r>  r'   r'   r'   r(   <module>   s   @
 	

#

"
!     ,
(0