U
    ad<                     @   s  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
mZ d dlmZmZ d dlZd dlmZ d dlmZmZ d d	lmZ d d
lmZ d dlmZ eejedkrd dlmZ zzd dlmZ W n  e k
r   d dl!mZ Y nX d dl"m#Z# zd dl$m%Z% W n, e k
r>   d dl&m'Z' dddZ%Y nX W n^ e k
r   z(d dlm%Z% d dl(mZ d dl)m#Z# W n e k
r   edY nX Y nX zd dl*Z*dZ+W n e k
r   dZ+Y nX G dd deZ,dS )    N)LooseVersion)urlparse)	HTTPError)Requesturlopen)ServerProxyFault)sleep)BaseCommandCommandError)color_style)signalcommand)InstallRequirementz19.0)install_req_from_line)
PipSession)parse_requirements)get_installed_distributions)castTFc           	         sX   ddl m}m} ddlm  |dkr,| }n||}|j| |||d} fdd|D S )zReturn a list of installed Distribution objects.
            Left for compatibility until direct pkg_resources uses are refactored out.
            r   )get_default_environmentget_environment)DistributionN)
local_onlyinclude_editableseditables_only	user_onlyc                    s   g | ]}t  |jqS  )r   Z_dist).0distZ_Distr   T/tmp/pip-unpacked-wheel-portabvm/django_extensions/management/commands/pipchecker.py
<listcomp>7   s     z/get_installed_distributions.<locals>.<listcomp>)Zpip._internal.metadatar   r   Z$pip._internal.metadata.pkg_resourcesr   Ziter_installed_distributions)	r   r   r   r   pathsr   r   envdistsr   r   r   r       s    
r   z#Pip version 6 or higher is requiredc                       s^   e Zd ZdZ fddZedd ZdddZd	d
 Zdd Z	dd Z
dd Zdd Z  ZS )Commandz4Scan pip requirement files for out-of-date packages.c              	      sR   t  | |jdddddd |jddd	d
g dddf |jdddddd d S )Nz-tz--github-api-tokenstoregithub_api_tokenz"A github api authentication token.)actiondesthelpz-rz--requirementappendrequirementsZFILENAMEzeCheck all the packages listed in the given requirements file. This option can be used multiple times.)r'   r(   defaultmetavarr)   z-nz--newer
store_true
show_newerz9Also show when newer version then available is installed.)superadd_argumentsadd_argument)selfparser	__class__r   r   r1   K   s0              zCommand.add_argumentsc              	   O   s  t  | _|| _|d r |d }nftjdr4dg}nRtjdrVdd tdD }n0tjdrjdg}ntjdr~dg}ntdi | _t	 }|D ]v}t
||dD ]d}t|tst|j}|jr|jn|jj}ttjtd	kr||jd
| j|< q||jd
| j|< qqW 5 Q R X |d r0|d | _n$tjdrNtjd| _nd | _|   trl|   n| j| jd |   d S )Nr+   zrequirements.txtc                 S   s:   g | ]2}t jt jd |r| drd|qS )r+   z.txtzrequirements/{0})ospathisfilejoinlowerendswithformat)r   fr   r   r   r    f   s    z"Command.handle.<locals>.<listcomp>zrequirements-dev.txtzrequirements-prod.txtzRequirements file(s) not found)sessionz6.0.8)pip_requrlr&   ZGITHUB_API_TOKENzYCannot check github urls. The requests library is not installed. ( pip install requests )) r   styleoptionsr7   r8   existslistdirr   reqsr   r   
isinstancer   r   requirementnamelinkfilenamer   pip__version__rA   r&   environget
check_pypiHAS_REQUESTScheck_githubstdoutwriteERRORcheck_other)r3   argsrC   Z	req_filesr?   rK   reqrI   r   r   r   handle\   sN    




zCommand.handleNc                 C   s   t ||d}tt| S )z#Shorcut for return contents as jsonheaders)r   jsonloadsr   read)r3   rA   r[   rX   r   r   r   _urlopen_as_json   s    zCommand._urlopen_as_jsonc                 C   s   t dt| S )Nz([ab]|rc|dev)\d+$)researchstr)r3   versionr   r   r   
_is_stable   s    zCommand._is_stablec                    s@     |r, fdd|D }|r,t|d S |r<t|d S d S )Nc                    s   g | ]}  t|r|qS r   rd   r   )r   vr3   r   r   r       s      z.Command._available_version.<locals>.<listcomp>r   re   )r3   dist_version	availableZstabler   rg   r   _available_version   s
    
zCommand._available_versionc                 C   s  t  D ]&}|j}|| j kr|| j| d< qtd}t| j D ]x\}}|d r\qDnDd|kr|d }t|j}d}d}|rz<|	|d j
dp|	|d j
ddd}d	}td
 W q tk
r } z&| j|j | jd td W 5 d}~X Y qX q| ||}	|	s,| jd}
nV| jd rV||	krV| jd|	}
n,|	|krt| jd|	}
nd}
| j|= qD| jdj|d}nd}
|}| jdj||
d | j|= qDdS )z>If the requirement is frozen to pypi, check for a new version.r   zhttps://pypi.python.org/pypirA   TNr@   -_F   zRetrying in 60 seconds!<   zFrelease is not on pypi (check capitalization and/or --extra-index-url)r/   z{0} available (newer installed)z{0} available
up to date"{dist.project_name} {dist.version}r   znot installed{pkg_info:40} {msg}pkg_infomsg)r   project_namerF   keysr   listitemsr   rc   Zpackage_releasesrI   replacer	   r   rS   rT   faultStringrj   rB   WARNrC   INFOr=   BOLD)r3   r   rI   pypirX   rh   retryri   errZavailable_versionru   rt   r   r   r   rP      sJ    


,
zCommand.check_pypic                 C   s  t | j D ]z\}}|d }|s&qt|}|drBd|krBq|drNqddi}| jrld| j|d< zt|j	
d	d
d dd
d}t|dkr|\}}nPd|kr|dd \}}|d|d dddd 7 }n| jd|f  W qW nL ttfk
rJ } z(| j| jd||f  W Y qW 5 d}~X Y nX ztjd|d }	W n@ tk
r } z | jdt|  W Y  dS d}~X Y nX d|	kr|	d dkr| j| jd  dS d|	kr
|	d dr
| j| jd  dS d}
d|kr@|
d\}}|drX|d
d }
nd|krX|
d\}}
|
dkrn| jd }|
r,d!||}tj||d }d"|||
}tj||d }d|kr|d d#kr| jd$|
dd% |}nD|d& d'd( |D kr| jd)}n| jd*|d& dd% }d+|krHd,j|d+ d-}n$|
dkrX|}nd.||
dd% }| jd/j||d0 | j|= qdS )1a  
        If the requirement is frozen to a github url, check for new commits.

        API Tokens
        ----------
        For more than 50 github api calls per hour, pipchecker requires
        authentication with the github api by settings the environemnt
        variable ``GITHUB_API_TOKEN`` or setting the command flag
        --github-api-token='mytoken'``.

        To create a github api token for use at the command line::
             curl -u 'rizumu' -d '{"scopes":["repo"], "note":"pipchecker"}' https://api.github.com/authorizations

        For more info on github api tokens:
            https://help.github.com/articles/creating-an-oauth-token-for-command-line-use
            http://developer.github.com/v3/oauth/#oauth-authorizations-api

        Requirement Format
        ------------------
        Pipchecker gets the sha of frozen repo and checks if it is
        found at the head of any branches. If it is not found then
        the requirement is considered to be out of date.

        Therefore, freezing at the commit hash will provide the expected
        results, but if freezing at a branch or tag name, pipchecker will
        not be able to determine with certainty if the repo is out of date.

        Freeze at the commit hash (sha)::
            git+git://github.com/django/django.git@393c268e725f5b229ecb554f3fac02cfc250d2df#egg=Django
            https://github.com/django/django/archive/393c268e725f5b229ecb554f3fac02cfc250d2df.tar.gz#egg=Django
            https://github.com/django/django/archive/393c268e725f5b229ecb554f3fac02cfc250d2df.zip#egg=Django

        Freeze with a branch name::
            git+git://github.com/django/django.git@master#egg=Django
            https://github.com/django/django/archive/master.tar.gz#egg=Django
            https://github.com/django/django/archive/master.zip#egg=Django

        Freeze with a tag::
            git+git://github.com/django/django.git@1.5b2#egg=Django
            https://github.com/django/django/archive/1.5b2.tar.gz#egg=Django
            https://github.com/django/django/archive/1.5b2.zip#egg=Django

        Do not freeze::
            git+git://github.com/django/django.git#egg=Django

        rA   gitzgithub.com/).tar.gzz.tar.bz2.zipzcontent-typezapplication/jsonz	token {0}Authorization#rm   r   /   archiveN@r    r   z
Failed to parse %r
z
Failed to parse %r: %s
zhttps://api.github.com/django/rZ   z
%s
messagezBad credentialsz(
Github API: Bad credentials. Aborting!
zAPI Rate Limit Exceededz,
Github API: Rate Limit Exceeded. Aborting!
z.gitzrepo is not frozenz-https://api.github.com/repos/{0}/{1}/branchesz0https://api.github.com/repos/{0}/{1}/commits/{2}z	Not Foundz*{0} not found in {1}. Repo may be private.
   shac                 S   s   g | ]}|d  d qS )commitr   r   )r   branchr   r   r   r    E  s     z(Command.check_github.<locals>.<listcomp>ro   z!{0} is not the head of any branchr   rp   rq   z{0} {1}rr   rs   )rx   rF   ry   rb   
startswithr<   r&   r=   r   r8   splitstriprstriplenrz   rB   rU   
ValueError
IndexErrorrS   rT   requestsrO   r\   r   r~   r}   )r3   rI   rX   Zreq_urlr[   
path_partsuserrepoeZ	test_authZfrozen_commit_sha	repo_nameZfrozen_commit_fullru   Z
branch_urlZbranch_dataZfrozen_commit_urlZfrozen_commit_datart   r   r   r   rR      s    /
 (
"


  

zCommand.check_githubc                 C   s   | j r| j| jd | j  D ]\\}}d|krFdj|d d}nd|kr`dj|d d}nd}| j| jd	j|d
 q$dS )z
        If the requirement is frozen somewhere other than pypi or github, skip.

        If you have a private pypi or use --extra-index-url, consider contributing
        support here.
        z7
Only pypi and github based requirements are supported:r   rp   rq   rA   z{url})rA   zunknown packagez1{pkg_info:40} is not a pypi or github requirement)rt   N)rF   rS   rT   rB   rU   ry   r=   r~   )r3   rI   rX   rt   r   r   r   rV   S  s    zCommand.check_other)N)__name__
__module____qualname__r)   r1   r   rY   r_   rd   rj   rP   rR   rV   __classcell__r   r   r5   r   r$   H   s   
6
- r$   )TTFFN)-r\   r7   r`   Zdistutils.versionr   urllib.parser   urllib.errorr   urllib.requestr   r   xmlrpc.clientr   r   rL   timer	   Zdjango.core.management.baser
   r   Z"django_extensions.management.colorr   Z"django_extensions.management.utilsr   Zpip._internal.reqr   rM   pip._internal.req.constructorsr   pip._internal.network.sessionr   ImportErrorZpip._internal.downloadZpip._internal.req.req_filer   pip._internal.utils.miscr   typingr   Zpip.downloadZpip.reqr   rQ   r$   r   r   r   r   <module>   sX        
