U
    O.eT-                  	   @   s  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mZmZmZmZmZmZmZmZmZ d dlZd dlmZ d dlZd dlmZ zd dlZW n ek
r   dZY nX dZe e!Z"ej#e$d	d
dZ%ej#d,e$ee$ dddZ&ej#d-e$ee$ dddZ'ej#e$eej(e$ee$e$f eej(e$f f ee$e$f dddZ)ed.e$e*ed dddZ+ed/e$e$e*eee ddf dddZ,e$e*ddd Z-G d!d" d"Z.G d#d$ d$Z/e$dd%d&d'ZG d(d) d)Z0G d*d+ d+ej0Z1dS )0    N)contextmanager)TracebackType)
AnyCallableListTupleUnion	GeneratorIOAnyStrDictOptional)Type)VERSIONFTreturnc                  C   s   t j} tjtjt}tj|d}tj|r||d}zZt	d}t
j||d d}t
jt	d|d}|r~dnd}t d	| d	| } W n tk
r   Y nX | S )
Nz.git)ZGIT_WORK_TREEZGIT_DIRzgit rev-parse --short HEAD)envzutf-8zgit diff HEADdirtyclean-)parsl__version__ospathdirname__file__joinexistsshlexsplit
subprocesscheck_outputstripdecoder   	Exception)versionZ	work_treeZgit_dirr   cmdheaddiffstatus r*   i/mounts/lovelace/software/anaconda3/envs/qiime2-shotgun-2023.9/lib/python3.8/site-packages/parsl/utils.pyget_version   s    

r,   runinfo)rundirr   c                 C   s^   t j| sg S tt | }g }|D ]2}t j|  d| d}t j|r&|| q&|S )zFinds the checkpoints from all runs in the rundir.

    Kwargs:
       - rundir(str) : Path to the runinfo directory

    Returns:
       - a list suitable for the checkpoint_files parameter of `Config`

    //checkpoint)r   r   isdirsortedlistdirabspathappend)r.   dirscheckpointsZrunid
checkpointr*   r*   r+   get_all_checkpoints1   s    r9   c                 C   sd   t j| sg S tt | }t|dkr.g S |d }t j|  d| d}t j|s^g S |gS )a  Finds the checkpoint from the last run, if one exists.

    Note that checkpoints are incremental, and this helper will not find
    previous checkpoints from earlier than the most recent run. If you
    want that behaviour, see `get_all_checkpoints`.

    Kwargs:
       - rundir(str) : Path to the runinfo directory

    Returns:
     - a list suitable for the checkpoint_files parameter of `Config`,
       with 0 or 1 elements

    r   r/   r0   )r   r   r1   r2   r3   lenr4   )r.   r6   Z
last_runidZlast_checkpointr*   r*   r+   get_last_checkpointN   s    r<   )fdnamestdfspecr   c                 C   sz   dd l m  m} t|ttjfr,|}d}nBt|trnt|dkrfd|  dt| }|	|t
d|\}}t||fS )Nr   za+   zstd descriptor z has incorrect tuple length zBad Tuple Length)parsl.app.errorsapperrors
isinstancestrr   PathLiketupler;   BadStdStreamFile	TypeError)r=   r>   pefnamemodemsgr*   r*   r+   get_std_fname_modeo   s    
rM   
   )NNN)r   secondsr   c                 c   s@   t dt|d D ]"}t|d  tj| r q6qd V  d S )Nr   d   g      Y@)rangeinttimesleepr   r   r   )r   rO   ir*   r*   r+   wait_for_file   s
    rV      )r   rK   rO   r   c              	   c   s<   t | | td W 5 Q R X t| |}|V  |  d S )Nzwait_for_file yielded)rV   loggerdebugopenclose)r   rK   rO   fr*   r*   r+   time_limited_open   s
    
r]   )time_stringr   c                 C   sL   |  d\}}}t|d t| }|dk rHd|  d| d}t| |S )z wtime_to_minutes

    Convert standard wallclock time string to minutes.

    Args:
        - Time_string in HH:MM:SS format

    Returns:
        (int) minutes

    :<   rW   zTime string 'z' parsed to z minutes, less than 1)r   rR   rX   warning)r^   hoursminsrO   Z
total_minsrL   r*   r*   r+   wtime_to_minutes   s    
rd   c                   @   s"   e Zd ZdZdZedddZdS )RepresentationMixina  A mixin class for adding a __repr__ method.

    The __repr__ method will return a string equivalent to the code used to instantiate
    the child class, with any defaults included explicitly. The __max_width__ class variable
    controls the maximum width of the representation string. If this width is exceeded,
    the representation string will be split up, with one argument or keyword argument per line.

    Any arguments or keyword arguments in the constructor must be defined as attributes, or
    an AttributeError will be raised.

    Examples
    --------
    >>> from parsl.utils import RepresentationMixin
    >>> class Foo(RepresentationMixin):
            def __init__(self, first, second, third='three', fourth='fourth'):
                self.first = first
                self.second = second
                self.third = third
                self.fourth = fourth
    >>> bar = Foo(1, 'two', fourth='baz')
    >>> bar
    Foo(1, 'two', third='three', fourth='baz')
    P   r   c           
         sf   j }t|dr|j}t|}t|jdkrT|jd k	rTtt	t
|jt
|j}ni }|jdd  D ],}t |sfd jj d| d}t|qft|dkrć fdd|jdt|  D }n fd	d|jdd  D } fd
d|D }tt tttf td fdd}tt tttf td fdd}	t|	|| jjkrX|	||S |||S d S )N__wrapped__rW   zclass z uses z; in the constructor, but does not define it as an attributer   c                    s   g | ]}t  |qS r*   getattr.0aselfr*   r+   
<listcomp>   s     z0RepresentationMixin.__repr__.<locals>.<listcomp>c                    s   g | ]}t  |qS r*   rh   rj   rm   r*   r+   ro      s     c                    s   i | ]}|t  |qS r*   rh   )rk   keyrm   r*   r+   
<dictcomp>   s      z0RepresentationMixin.__repr__.<locals>.<dictcomp>)argskwargsr   c                    sd   t t ddd  fdd| D }  fddt| D }d| d| }jjd	| d
 S )N)textr   c                 S   s0   |   }t|dkr| S ddd |D  S )NrW   
c                 s   s   | ]}d | V  qdS )z    Nr*   )rk   liner*   r*   r+   	<genexpr>   s     z[RepresentationMixin.__repr__.<locals>.assemble_multiline.<locals>.indent.<locals>.<genexpr>)
splitlinesr;   r   r"   )rt   linesr*   r*   r+   indent   s    zHRepresentationMixin.__repr__.<locals>.assemble_multiline.<locals>.indentc                    s    g | ]}d  t | dqS )
    ,reprrj   rz   r*   r+   ro      s     zLRepresentationMixin.__repr__.<locals>.assemble_multiline.<locals>.<listcomp>c                    s(   g | ] \}}d | d t | qS )r{   =r}   rk   kvr   r*   r+   ro      s      , (z
))rD   r2   itemsr   	__class____name__rr   rs   Zkwargslinform   r   r+   assemble_multiline   s    

z8RepresentationMixin.__repr__.<locals>.assemble_multilinec                    sB   dd t | D }ddd | D | } jjd| d S )Nc                 S   s"   g | ]\}}| d t | qS )r   r}   r   r*   r*   r+   ro      s     zGRepresentationMixin.__repr__.<locals>.assemble_line.<locals>.<listcomp>r   c                 S   s   g | ]}t |qS r*   r}   rj   r*   r*   r+   ro      s     r   ))r2   r   r   r   r   r   rm   r*   r+   assemble_line   s    z3RepresentationMixin.__repr__.<locals>.assemble_line)__init__hasattrrg   inspectgetfullargspecr;   rr   defaultsdictzipreversedr   r   AttributeErrorr   rD   r   object__max_width__)
rn   initargspecr   argtemplaterr   rs   r   r   r*   rm   r+   __repr__   s(    




$""
zRepresentationMixin.__repr__N)r   
__module____qualname____doc__r   rD   r   r*   r*   r*   r+   re      s   re   c                   @   s,   e Zd ZdZddddZedddZdS )AtomicIDCounterzAA class to allocate counter-style IDs, in a thread-safe way.
    Nr   c                 C   s   d| _ t | _d S )Nr   )count	threadingLocklockrm   r*   r*   r+   r      s    zAtomicIDCounter.__init__c              
   C   s6   | j & | j}|  jd7  _|W  5 Q R  S Q R X d S )NrW   )r   r   )rn   Znew_idr*   r*   r+   get_id  s    zAtomicIDCounter.get_id)r   r   r   r   r   rR   r   r*   r*   r*   r+   r      s   r   )titler   c                 C   s$   t rt|  ntd|   d S )Nz%setproctitle not enabled for process )_setproctitle_enabledsetproctitle_modulesetproctitlerX   warn)r   r*   r*   r+   r     s    r   c                   @   s`   e Zd ZdZdddeeeee ddddZ	e
jddd	d
ZddddZddddZdS )Timera  This class will make a callback periodically, with a period
    specified by the interval parameter.

    This is based on the following logic :

    .. code-block:: none


        BEGIN (INTERVAL, THRESHOLD, callback) :
            start = current_time()

            while (current_time()-start < INTERVAL) :
                 wait()
                 break

            callback()

       N)intervalname)callbackrr   r   r   r   c                G   s   || _ || _|| _t d | _t | _|dkrBdt	| }nd|t	| }tj
| j| jf|d| _d| j_| j  dS )zInitialize the Timer object.
        We start the timer thread here

        KWargs:
             - interval (int) : number of seconds between callback events
             - name (str) : a base name to use when naming the started thread
        rW   NzTimer-Thread-{}z{}-Timer-Thread-{})targetrr   r   T)r   cb_argsr   rS   _wake_up_timer   Event_kill_eventformatidThread_wake_up_timer_threaddaemonstart)rn   r   r   r   rr   r*   r*   r+   r   &  s    	
zTimer.__init__)
kill_eventr   c                 C   sL   | j }|tt|t  d}|r*dS || j kr>|   q td q dS )zInternal. This is the function that the thread will execute.
        waits on an event so that the thread can make a quick exit when close() is called

        Args:
            - kill_event (threading.Event) : Event to wait on
        r   NzSleeping a bit more)r   waitfloatmaxrS   make_callbackprint)rn   r   prevZtime_to_dier*   r*   r+   r   =  s    


zTimer._wake_up_timerr   c                 C   sH   t   | j | _z| j| j  W n" tk
rB   tjddd Y nX dS )z1Makes the callback and resets the timer.
        z;Callback threw an exception - logging and proceeding anywayT)exc_infoN)rS   r   r   r   r   r$   rX   errorrm   r*   r*   r+   r   U  s
    zTimer.make_callbackc                 C   s   | j   | j  dS )z)Merge the threads and terminate.
        N)r   setr   r   rm   r*   r*   r+   r[   _  s    
zTimer.close)r   r   r   r   r   r   rR   r   rD   r   r   r   r   r   r[   r*   r*   r*   r+   r     s
   "
r   c                   @   sB   e Zd ZdZd dddZeee  ee ee ddddZ	dS )	AutoCancelTimerz
    Extend threading.Timer for use as a context manager

    Example:

        with AutoCancelTimer(delay, your_callback):
            some_func()

    If `some_func()` returns before the delay is up, the timer will
    be cancelled.
    r   c                 C   s   |    | S N)r   rm   r*   r*   r+   	__enter__r  s    zAutoCancelTimer.__enter__N)exc_typeexc_valexc_tbr   c                 C   s   |    d S r   )cancel)rn   r   r   r   r*   r*   r+   __exit__v  s    zAutoCancelTimer.__exit__)
r   r   r   r   r   r   r   BaseExceptionr   r   r*   r*   r*   r+   r   f  s   
r   )r-   )r-   )rN   )rW   )2r   loggingr   r   r    r   rS   
contextlibr   typesr   typingr   r   r   r   r   r	   r
   r   r   r   	typeguardtyping_extensionsr   r   parsl.versionr   r   r   ImportErrorr   	getLoggerr   rX   typecheckedrD   r,   r9   r<   rE   rM   rR   rV   r]   rd   re   r   r   r   r*   r*   r*   r+   <module>   sP   0

 "
&TT