U
    La(                     @   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	zddl
mZ W n  ek
r|   ddlmZ Y nX ddlZddlmZ eeZdd Zdd	 Zed
d ed
d edd edejejB ZddddddjZdd Zdd ZedejZedejZ edejZ!edejZ"dd Z#dd Z$d d! Z%d"d# Z&d$d% Z'G d&d' d'e(Z)d(d) Z*d*d+ Z+d>d-d.Z,d/d0 Z-d1d2 Z.d3d4 Z/d5d6 Z0d7d8 Z1z dd9l2m3Z3 d:d; Z4d<d= Z5W n ek
r   e*Z4e1Z5Y nX dS )?z6minimal PyPI like server for use with pip/easy_install    N)quote   )Configurationc            
   	      s  t f | }td| |jdkr.tjd|_t|jtt	frD|jn|jg dd  D   D ]J}zt
| W q^ tk
r   t d }d}t|||f  Y q^X q^ fdd	} d
 |_|jsg |_t|js|jr|jdkrd
dlm} ||j}n
d |_}tt||_zP|jsBd|_ttdd|_n(tj|jddd}|  |_W 5 Q R X W n( t!k
r   tj"d|jdd Y nX |j#dkrd|_#|j$rz
t%j&}	W n& t'k
r   ddddddg}	Y nX |j$|	krtd|j$|	f  td| ||fS )z6
    :return: a 2-tuple (Configure, package-list)
    z+++Pypiserver invoked with: %sNz
~/packagesc                 S   s   g | ]}t j|qS  )ospathabspath.0rr   r   3/tmp/pip-unpacked-wheel-8ds7z0ev/pypiserver/core.py
<listcomp>%   s     zconfigure.<locals>.<listcomp>r   z(Error: while trying to list root(%s): %sc                      s   t jdd  D  S )Nc                 S   s   g | ]}t |qS r   )listdirr	   r   r   r   r   .   s     z/configure.<locals>.<lambda>.<locals>.<listcomp>)	itertoolschainr   rootsr   r   <lambda>.       zconfigure.<locals>.<lambda>r   .)HtpasswdFilezwelcome.htmlzutf-8r   )encodingz Could not load welcome-file(%s)!)exc_infozhttps://pypi.org/simplemd5sha1sha224sha256sha384sha512z Hash-algorithm %s not one of: %sz+++Pypiserver started with: %s)(r   loginforootr   r   
expanduser
isinstancelisttupler   OSErrorsysr   exitauthenticatedcallableZautherZpassword_fileZpasslib.apacher   	functoolspartialauth_by_htpasswd_fileZwelcome_filepkg_resourcesresource_string__name__decodeZwelcome_msgioopenread	ExceptionwarningZfallback_url	hash_algohashlibalgorithms_availableAttributeError)
kwdscr   errmsgpackagesr   htPsswdFilefdZhalgosr   r   r   	configure   sf    



   
rB   c                 C   s    | dk	r|    | ||S dS )zThe default ``config.auther``.N)Zload_if_changedZcheck_password)r@   usernamepasswordr   r   r   r-   [   s    r-   zapplication/octet-streamz.egg.whlz
text/plain.ascz(\d+ | [a-z]+ | \.| -)r<   zfinal-@)prepreview-rcdevc                 c   sV   t | D ]@}t||}|dkr"q
|d d dkr@|dV  q
d| V  q
dV  d S )N) r   r   
0123456789   *z*final)component_resplitreplacezfill)spartr   r   r   _parse_version_partsm   s    
rW   c                 C   sL   g }t |  D ]2}|dr8|r8|d dkr8|  q|| qt|S )NrP   00000000)rW   lower
startswithpopappendr%   )rU   partsrV   r   r   r   parse_versionz   s    

r_   zj(\.zip|\.tar\.gz|\.tgz|\.tar\.bz2|-py[23]\.\d-.*|\.win-amd64-py[23]\.\d\..*|\.win32-py[23]\.\d\..*|\.egg)$z^(?P<namever>(?P<name>.+?)-(?P<ver>\d.*?))
    ((-(?P<build>\d.*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?)
    \.whl|\.dist-info)$z-\d+[a-z_.!+]zB[\.\-](?=cp\d|py\d|macosx|linux|sunos|solaris|irix|aix|cygwin|win)c                 C   sP   t | }|sdS |d}|d}|d}|rD||d | fS ||fS d S )N)NNnameverbuildrJ   )wheel_file_rematchgroup)basenamemr`   ra   rb   r   r   r    _guess_pkgname_and_version_wheel   s    



rh   c                 C   s   t j| } | dr | d} | dr2t| S t| s@d S td| } d| kr`| d }}nn| 	ddkr| 
dd\}}nNd| kr| dd\}}n4t
| d }| t|d d  }t
|}|d }||fS )NrF   rE   rM   rJ   r   r   r   )r   r   rf   endswithrstriprh   _archive_suffix_rxsearchsubcountrR   rsplit_pkgname_relen_pkgname_parts_re)r   pkgnameversionZver_specr^   r   r   r   guess_pkgname_and_version   s&    




ru   c                 C   s   t dd|  S )zPerform PEP 503 normalization[-_.]+rJ   )rerm   rZ   r`   r   r   r   normalize_pkgname   s    ry   c                 C   s   t tdd|  S )zDPerform PEP 503 normalization and ensure the value is safe for URLs.rv   rJ   )r   rw   rm   rZ   rx   r   r   r   normalize_pkgname_for_url   s    rz   c                 C   s    |  dd}|dpd|k S )N\/r   z/.)rS   r[   )Z	path_partpr   r   r   is_allowed_path   s    r~   c                
   @   s>   e Zd Zddddddddd	d
g
ZdddZdd Zdd ZdS )PkgFilefnr!   _fname_and_hashrelfn
relfn_unixpkgname_normrs   rt   parsed_versionreplacesNc                 C   sV   || _ t|| _|| _t|| _|| _|| _|| _|d kr>d n
|	dd| _
|| _d S )Nr{   r|   )rs   ry   r   rt   r_   r   r   r!   r   rS   r   r   )selfrs   rt   r   r!   r   r   r   r   r   __init__   s    

zPkgFile.__init__c                    s*   d j jd fddt jD f S )Nz%s(%s)z, c                    s    g | ]}d |t  |df qS )z%s=%rr:   )getattr)r
   kr   r   r   r      s   z$PkgFile.__repr__.<locals>.<listcomp>)	__class__r0   joinsorted	__slots__r   r   r   r   __repr__   s    zPkgFile.__repr__c                 C   s8   t | ds2|r*d| j|t| j|f | _n| j| _| jS )Nr   z%s#%s=%s)hasattrr   digest_filer   r   )r   r7   r   r   r   fname_and_hash   s    
  

zPkgFile.fname_and_hash)NNNN)r0   
__module____qualname__r   r   r   r   r   r   r   r   r      s    
r   c           	   
   c   s   t j| } t | D ]\}}}dd |D |d d < |D ]h}t j| ||}t|r:t j|sdq:t|}|srq:|\}}|r:t|||| |t	| d d  dV  q:qd S )Nc                 S   s   g | ]}t |r|qS r   )r~   )r
   xr   r   r   r      s      z_listdir.<locals>.<listcomp>r   )rs   rt   r   r!   r   )
r   r   r   walkr   r~   isfileru   r   rq   )	r!   dirpathdirnames	filenamesr   r   resrs   rt   r   r   r   _listdir   s$     r   c              	   C   sb   g }z4t | "}dd dd | D D }W 5 Q R X W n$ tk
r\   td|    Y nX |S )z
    Read the contents of `filename`, stripping empty lines and '#'-comments.
    Return a list of strings, containing the lines of the file.
    c                 S   s   g | ]}|r| d s|qS )#)r[   )r
   liner   r   r   r     s    
zread_lines.<locals>.<listcomp>c                 s   s   | ]}|  V  qd S N)strip)r
   lnr   r   r   	<genexpr>  s     zread_lines.<locals>.<genexpr>zUFailed to read package blacklist file "%s". Aborting server startup, please fix this.)r3   	readlinesr5   r   error)filenamelinesfr   r   r   
read_lines  s    
r   rM   c                 c   s,   t |}| D ]}|r |j|kr q|V  qd S r   )ry   r   )pkgsprefixr   r   r   r   find_packages  s
    r   c                 C   s&   t  }| D ]}|jr
||j q
|S r   )setrs   addr   )r   Znormalized_pkgnamesr   r   r   r   get_prefixes"  s
    r   c                 C   s&   d|kst tj| |}tj|S )Nr|   )AssertionErrorr   r   r   exists)r!   r   dest_fnr   r   r   r   *  s    r   c                 C   s*   d|kst tj| |}||dd d S )Nr|   T)	overwrite)r   r   r   r   )r!   r   Zsave_methodr   r   r   r   store0  s    r   c                 C   sF   | j }|dr|dd }|ddd }t|}|d|7 }|S )z Get the path for a bad root url.r|   NrX   r   r   z/simple/{}/)Zcustom_fullpathri   ro   r   format)requestr   r}   r   r   r   get_bad_url_redirect_path6  s    
r   c              	      sR   d t t| }t| d*t fdddD ]}|| q0W 5 Q R X | S )z
    Reads and digests a file according to specified hashing-algorith.

    :param str sha256: any algo contained in :mod:`hashlib`
    :return: <hash_algo>=<hex_digest>

    From http://stackoverflow.com/a/21565932/548792
    i   rbc                      s
     S r   )r4   r   	blocksizer   r   r   r   M  r   z_digest_file.<locals>.<lambda>r   )r   r8   r3   iterupdate	hexdigest)fpathr7   Zdigesterblockr   r   r   _digest_fileA  s    	r   )cache_managerc                 C   s   t | tS r   )r   r   r   )r!   r   r   r   r   U  s    r   c                 C   s   t | |tS r   )r   r   r   )r   r7   r   r   r   r   Y  s    r   )rM   )6__doc__r+   r8   r2   r   logging	mimetypesr   rw   r'   urllib.parser   ImportErrorurllibr.   rM   r   	getLoggerr0   r   rB   r-   add_typecompileIVERBOSErQ   getrS   rW   r_   rk   rc   rp   rr   rh   ru   ry   rz   r~   objectr   r   r   r   r   r   r   r   r   cacher   r   r   r   r   r   r   <module>   sv   
@&
