o
    2g#                     @   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mZ ddlm	Z	 ddl
mZ dZdd Zd	d
 Zdd ZG dd dZG dd dZdd ZdddZedejZddddddjZdd Zdd ZdS ) zIModule that checks if there is an updated version of a package available.    N)datetime)wraps)
gettempdirz0.18.0c                    sx    fdd fddi  dzt jt d  W n ty+   dY nw t fdd	}|S )
z2Return decorated function that caches the results.c                     s`     z"t d} t | tj W d   W dS 1 sw   Y  W dS  ty/   Y dS w )a.  Save the in-memory cache data to the permacache.

        There is a race condition here between two processes updating at the
        same time. It's perfectly acceptable to lose and/or corrupt the
        permacache information as each process's in-memory cache will remain
        in-tact.

        wbN)openpickledumpHIGHEST_PROTOCOLIOError)fp)cachefilenameupdate_from_permacache F/home/garg/my-data/venv/lib/python3.10/site-packages/update_checker.pysave_to_permacache   s   	&z)cache_results.<locals>.save_to_permacachec                     s   zt d} t| }W d   n1 sw   Y  W n
 ty&   Y dS w | D ]\}}| vs=|d  | d krA| |< q+dS )z2Attempt to update newer items from the permacache.rbNr   )r   r   load	Exceptionitems)r   
permacachekeyvalue)r   r   r   r   r   "   s   z-cache_results.<locals>.update_from_permacache  zupdate_checker_cache.pklNc                    sh   t   }||f}| js| v r | \}}|| k r|S | ||fi |}||f |< r2  |S )z#Return cached results if available.)time_bypass_cache)objpackage_namepackage_version
extra_datanowr   
cache_timeretval)r   cache_expire_timer   functionr   r   r   wrapped5   s   zcache_results.<locals>.wrapped)ospathjoinr   NotImplementedErrorr   )r$   r%   r   )r   r#   r   r$   r   r   r   cache_results   s   
r*   c           	      C   s   zt jd|  ddd}W n t jjy   ddi Y S w |jdkr&ddiS | }t|d  }|jt	d	d
 |d }|D ]}|sGt
|rK|} nq?d}|d | D ]}|d r`|d } nqTd	||ddS )z8Return information about the current version of package.zhttps://pypi.org/pypi/z/json   )timeoutsuccessF   releasesT)r   reverser   Nupload_time)r1   version)r-   data)requestsget
exceptionsRequestExceptionstatus_codejsonlistkeyssortparse_versionstandard_release)	packageinclude_prereleasesresponser3   versionsr2   tmp_versionr1   	file_infor   r   r   
query_pypiG   s.   
rE   c                 C   s   |  dd S )N. )replaceisdigit)r2   r   r   r   r>   b   s   r>   c                   @   s    e Zd ZdZdd Zdd ZdS )UpdateResultz:Contains the information for a package that has an update.c                 C   s2   || _ || _|| _|rt|d| _dS d| _dS )z$Initialize an UpdateResult instance.z%Y-%m-%dT%H:%M:%SN)available_versionr   running_versionr   strptimerelease_date)selfr?   running	availablerN   r   r   r   __init__l   s   
zUpdateResult.__init__c                 C   sJ   d| j  d| j d| j d}| jr|dt| j d7 }|S |d7 }|S )z'Return a printable UpdateResult string.zVersion z of z is outdated. Version  zwas released rF   zis available.)rL   r   rK   rN   pretty_date)rO   r"   r   r   r   __str__v   s   zUpdateResult.__str__N)__name__
__module____qualname____doc__rR   rU   r   r   r   r   rJ   h   s    
rJ   c                   @   s*   e Zd ZdZddddZedd ZdS )	UpdateCheckerz%A class to check for package updates.Fbypass_cachec                C   s
   || _ d S )N)r   )rO   r\   r   r   r   rR      s   
zUpdateChecker.__init__c                 C   sX   t |t| d}|drt|t|d d krdS t|||d d |d d dS )z9Return a UpdateResult object if there is a newer version.)r@   r-   r3   r2   Nr1   )rP   rQ   rN   )rE   r>   r5   r=   rJ   )rO   r   r   r3   r   r   r   check   s   



zUpdateChecker.checkN)rV   rW   rX   rY   rR   r*   r]   r   r   r   r   rZ      s
    rZ   c                 C   s   t  |  }|jdks|jdk r| dS |jdkrdS |jdkr'|j dS |jdkr.dS |jdk r9|j d	S |jd
k r@dS |jdk rQtt|jd  dS |jdk rXdS tt|jd  dS )z5Attempt to return a human-readable time delta string.   r   z%A %B %d, %Yr+   z	1 day agoz	 days agozjust now<   z seconds agox   z1 minute agor   z minutes agoi   z
1 hour agoz
 hours ago)r   utcnowdaysstrftimesecondsintround)the_datetimediffr   r   r   rT      s$   







rT   Fc                 C   s0   t |d}|| |}|rt|tjd dS dS )zDConvenience method that outputs to stderr if an update is available.r[   )fileN)rZ   r]   printsysstderr)r   r   r\   checkerresultr   r   r   update_check   s
   
ro   z(\d+ | [a-z]+ | \.| -)czfinal-@)prepreview-rcdevc                 c   s\    t | D ]"}t||}|r|dkrq|d d dv r#|dV  qd| V  qdV  d S )NrF   r+   
0123456789   **final)component_resplitrH   zfill)spartr   r   r   _parse_version_parts   s   

r   c                 C   s   g }t |  D ]8}|dr;|dk r'|r'|d dkr'|  |r'|d dks|r;|d dkr;|  |r;|d dks/|| qt|S )a  Convert a version string to a chronologically-sortable key.

    This is a rough cross between distutils' StrictVersion and LooseVersion;
    if you give it versions that would work with StrictVersion, then it behaves
    the same; otherwise it acts like a slightly-smarter LooseVersion. It is
    *possible* to create pathological version coding schemes that will fool
    this parser, but they should be very rare in practice.

    The returned value will be a tuple of strings.  Numeric portions of the
    version are padded to 8 digits so they will compare numerically, but
    without relying on how numbers compare relative to strings.  Dots are
    dropped, but dashes are retained.  Trailing zeros between alpha segments
    or dashes are suppressed, so that e.g. "2.4.0" is considered the same as
    "2.4". Alphanumeric parts are lower-cased.

    The algorithm assumes that strings like "-" and any alpha string that
    alphabetically follows "final"  represents a "patch level".  So, "2.4-1"
    is assumed to be a branch or patch of "2.4", and therefore "2.4.1" is
    considered newer than "2.4-1", which in turn is newer than "2.4".

    Strings like "a", "b", "c", "alpha", "beta", "candidate" and so on (that
    come before "final" alphabetically) are assumed to be pre-release versions,
    so that the version "2.4" is considered newer than "2.4a1".

    Finally, to handle miscellaneous cases, the strings "pre", "preview", and
    "rc" are treated as if they were "c", i.e. as though they were release
    candidates, and therefore are not as new as a version string that does not
    contain them, and "dev" is replaced with an '@' so that it sorts lower than
    than any other pre-release tag.

    ry   rz   z*final-00000000)r   lower
startswithpopappendtuple)r~   partsr   r   r   r   r=      s    
r=   )F)rY   r&   r   rer4   rk   r   r   	functoolsr   tempfiler   __version__r*   rE   r>   rJ   rZ   rT   ro   compileVERBOSEr{   r5   rH   r   r=   r   r   r   r   <module>   s,    8
