Format: application/x-python-code
⬇ Download File (15.6 KB)
   1  o
   2  
   3  ��hJE�@s�dZddlZddlZddlmZddlmZddlmZm	Z	Gdd�de
   4  �ZGdd	�d	ej�Z
   5  Gd
   6  d�de
   7  �ZGdd
   8  �d
   9  e
  10  �ZdS)a
  11  Manage background (threaded) jobs conveniently from an interactive shell.
  12  
  13  This module provides a BackgroundJobManager class.  This is the main class
  14  meant for public usage, it implements an object which can create and manage
  15  new background jobs.
  16  
  17  It also provides the actual job classes managed by these BackgroundJobManager
  18  objects, see their docstrings below.
  19  
  20  
  21  This system was inspired by discussions with B. Granger and the
  22  BackgroundCommand class described in the book Python Scripting for
  23  Computational Science, by H. P. Langtangen:
  24  
  25  http://folk.uio.no/hpl/scripting
  26  
  27  (although ultimately no code from this text was used, as IPython's system is a
  28  separate implementation).
  29  
  30  An example notebook is provided in our documentation illustrating interactive
  31  use of the system.
  32  �N)�get_ipython)�AutoFormattedTB)�error�debugc@s�eZdZdZdd�Zedd��Zedd��Zedd	��Zd
  33  d�Z	dd
  34  �Z
  35  dd�Zdd�Zdd�Z
  36  dd�Zdd�Zd&dd�Zdd�Zdd�Zdd �Zd!d"�Zd'd$d%�Zd#S)(�BackgroundJobManagera�Class to manage a pool of backgrounded threaded jobs.
  37  
  38      Below, we assume that 'jobs' is a BackgroundJobManager instance.
  39      
  40      Usage summary (see the method docstrings for details):
  41  
  42        jobs.new(...) -> start a new job
  43        
  44        jobs() or jobs.status() -> print status summary of all jobs
  45  
  46        jobs[N] -> returns job number N.
  47  
  48        foo = jobs[N].result -> assign to variable foo the result of job N
  49  
  50        jobs[N].traceback() -> print the traceback of dead job N
  51  
  52        jobs.remove(N) -> remove (finished) job N
  53  
  54        jobs.flush() -> remove all finished jobs
  55        
  56      As a convenience feature, BackgroundJobManager instances provide the
  57      utility result and traceback methods which retrieve the corresponding
  58      information from the jobs list:
  59  
  60        jobs.result(N) <--> jobs[N].result
  61        jobs.traceback(N) <--> jobs[N].traceback()
  62  
  63      While this appears minor, it allows you to use tab completion
  64      interactively on the job manager instance.
  65      cCsNg|_g|_g|_i|_g|_g|_tj|_tj	|_
  66  tj|_tj
  67  |_d|_dS)Nr)�_running�
  68  _completed�_dead�all�_comp_report�_dead_report�BackgroundJobBase�stat_created_cZ
  69  _s_created�stat_running_c�
  70  _s_running�stat_completed_c�_s_completed�stat_dead_c�_s_dead�_current_job_id��self�r�Pc:\Users\shubh\Videos\agent\nova\Lib\site-packages\IPython/lib/backgroundjobs.py�__init__Is
  71  zBackgroundJobManager.__init__cC�|��|jS�N)�_update_statusrrrrr�running[�zBackgroundJobManager.runningcCrr)rr	rrrr�dead`rzBackgroundJobManager.deadcCrr)rrrrrr�	completederzBackgroundJobManager.completedc	Os�t|�r|�di�}t|g|�Ri|��}n;t|t�rM|s*t�d�}|j|j}}nt	|�dkr7|d}}nt	|�dkrB|\}}nt
  72  d��t|||�}ntd��|�dd�rZd	|_
  73  |j|_|jd7_|j�|�||j|j<td
  74  |j�|��|S)a@Add a new background job and start it in a separate thread.
  75  
  76          There are two types of jobs which can be created:
  77  
  78          1. Jobs based on expressions which can be passed to an eval() call.
  79          The expression must be given as a string.  For example:
  80  
  81            job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
  82  
  83          The given expression is passed to eval(), along with the optional
  84          global/local dicts provided.  If no dicts are given, they are
  85          extracted automatically from the caller's frame.
  86  
  87          A Python statement is NOT a valid eval() expression.  Basically, you
  88          can only use as an eval() argument something which can go on the right
  89          of an '=' sign and be assigned to a variable.
  90  
  91          For example,"print 'hello'" is not valid, but '2+3' is.
  92  
  93          2. Jobs given a function object, optionally passing additional
  94          positional arguments:
  95  
  96            job_manager.new(myfunc, x, y)
  97  
  98          The function is called with the given arguments.
  99  
 100          If you need to pass keyword arguments to your function, you must
 101          supply them as a dict named kw:
 102  
 103            job_manager.new(myfunc, x, y, kw=dict(z=1))
 104  
 105          The reason for this asymmetry is that the new() method needs to
 106          maintain access to its own keywords, and this prevents name collisions
 107          between arguments to new() and arguments to your own functions.
 108  
 109          In both cases, the result is stored in the job.result field of the
 110          background job object.
 111  
 112          You can set `daemon` attribute of the thread by giving the keyword
 113          argument `daemon`.
 114  
 115          Notes and caveats:
 116  
 117          1. All threads running share the same standard output.  Thus, if your
 118          background jobs generate output, it will come out on top of whatever
 119          you are currently writing.  For this reason, background jobs are best
 120          used with silent functions which simply return their output.
 121  
 122          2. Threads also all work within the same global namespace, and this
 123          system does not lock interactive variables.  So if you send job to the
 124          background which operates on a mutable object for a long time, and
 125          start modifying that same mutable object interactively (or in another
 126          backgrounded job), all sorts of bizarre behaviour will occur.
 127  
 128          3. If a background job is spending a lot of time inside a C extension
 129          module which does not release the Python Global Interpreter Lock
 130          (GIL), this will block the IPython prompt.  This is simply because the
 131          Python interpreter can only switch between threads at Python
 132          bytecodes.  While the execution is inside C code, the interpreter must
 133          simply wait unless the extension module releases the GIL.
 134  
 135          4. There is no way, due to limitations in the Python threads library,
 136          to kill a thread once it has started.�kw�r�z4Expression jobs take at most 2 args (globals,locals)zinvalid args for new job�daemonFTz'Starting job # %s in a separate thread.)�callable�get�BackgroundJobFunc�
 137  isinstance�str�sys�	_getframe�	f_globals�f_locals�len�
 138  ValueError�BackgroundJobExpr�	TypeErrorr%r�numr�appendr
 139  r�start)	rZfunc_or_exp�args�kwargsr"�job�frame�glob�locrrr�newjs2A
 140  
 141  
 142  �zBackgroundJobManager.newcCst|t�r|n|j}|j|Sr)r)�intr3r
 143  )rZjob_keyr3rrr�__getitem__�s
 144  z BackgroundJobManager.__getitem__cCs|��S)z�An alias to self.status(),
 145  
 146          This allows you to simply call a job manager instance much like the
 147          Unix `jobs` shell command.)�statusrrrr�__call__�szBackgroundJobManager.__call__c
 148  Cs�|j|j|j}}}|j|j|j}}}t|�D]3\}}|j}	|	|kr&q|	|kr:|�|�|j	�|�d||<q|	|krM|�|�|j
 149  �|�d||<qtd|�|dd�<dS)a�Update the status of the job lists.
 150  
 151          This method moves finished jobs to one of two lists:
 152            - self.completed: jobs which completed successfully
 153            - self.dead: jobs which finished but died.
 154  
 155          It also copies those jobs to corresponding _report lists.  These lists
 156          are used to report jobs completed/dead since the last update, and are
 157          then cleared by the reporting function after each call.FN)rrrrrr	�	enumerate�	stat_coder4rr�filter)
 158  rZsrunZscompZsdeadrr!r r3r8�statrrrr�s 
 159  
 160  
 161  �z#BackgroundJobManager._update_statuscCs:|rtd|�|D]}td|j|f�q
 162  t�dSdS)zYReport summary for a given job group.
 163  
 164          Return True if the group had any elements.z%s jobs:z%s : %sTN)�printr3)r�group�namer8rrr�
 165  _group_report�s�z"BackgroundJobManager._group_reportcCsBt|�}|rddi�|d�}td|||f�g|dd�<dSdS)zKFlush a given job group
 166  
 167          Return True if the group had any elements.r#��szFlushing %s %s job%s.NT)r/�
 168  setdefaultrE)rrFrGZnjobs�pluralrrr�_group_flushs�z!BackgroundJobManager._group_flushcCsH|��|�|jd�}|�|jd�}g|jdd�<g|jdd�<|p#|S)z�Print the status of newly finished jobs.
 169  
 170          Return True if any new jobs are reported.
 171  
 172          This call resets its own state every time, so it only reports jobs
 173          which have finished since the last time it was called.�	Completedz'Dead, call jobs.traceback() for detailsN)rrHrr)rZnew_compZnew_deadrrr�_status_news�z BackgroundJobManager._status_newrcCsR|��|�|jd�|�|jd�|�|jd�g|jdd�<g|jdd�<dS)z3Print a status of all jobs currently being managed.�RunningrN�DeadN)rrHrr!r rr)r�verboserrrr?szBackgroundJobManager.statuscCs�z|j|}Wntytd|�YdSw|j}||jkr(td|�dS||jkr5|j�|�dS||jkrB|j	�|�dSdS)z*Remove a finished (completed or dead) job.�Job #%s not foundz0Job #%s is still running, it can not be removed.N)
 174  r
 175  �KeyErrorrrBrrr!�removerr )rr3r8rBrrrrU's�
 176  
 177  
 178  �zBackgroundJobManager.removecCsX|j}|j|jD]}||j=q	|�|jd�}|�|jd�}|s(|s*td�dSdSdS)aFlush all finished jobs (completed and dead) from lists.
 179  
 180          Running jobs are never flushed.
 181  
 182          It first calls _status_new(), to update info. If any jobs have
 183          completed since the last _status_new() call, the flush operation
 184          aborts.rNrQzNo jobs to flush.N)r
 185  r!r r3rMrE)rZalljobsr8Zfl_compZfl_deadrrr�flush8s
 186  
 187  �zBackgroundJobManager.flushcCs0z|j|jWStytd|�YdSw)z(result(N) -> return the result of job N.rSN)r
 188  �resultrTr)rr3rrrrWLs
 189  �zBackgroundJobManager.resultcCsJt|t�r|n|j}z
 190  |j|��WdSty$td|�YdSw)NrS)r)r=r3r
 191  �	tracebackrTr)rr8r3rrr�
 192  _tracebackSs�zBackgroundJobManager._tracebackNcCsJ|dur|��|jD]}td|�|�|�t�qdS|�|�dS)NzTraceback for: %r)rr rErY)rr8ZdeadjobrrrrXZs
 193  
 194  �zBackgroundJobManager.traceback)rr)�__name__�
 195  __module__�__qualname__�__doc__r�propertyrr r!r<r>r@rrHrMrOr?rUrVrWrYrXrrrrr)s,
 196  
 197  
 198  ]!
 199  rc@s`eZdZdZdZdZdZdZdZdZ	dZ
 200  d	Zd
 201  d�Zdd
 202  �Z
 203  dd�Zdd�Zdd�Zdd�ZdS)r
 204  a�Base class to build BackgroundJob classes.
 205  
 206      The derived classes must implement:
 207  
 208      - Their own __init__, since the one here raises NotImplementedError.  The
 209        derived constructor must call self._init() at the end, to provide common
 210        initialization.
 211  
 212      - A strform attribute used in calls to __str__.
 213  
 214      - A call() method, which will make the actual execution call and must
 215        return a value to be held in the 'result' field of the job object.
 216      �CreatedrrPr#rNr$z3Dead (Exception), call jobs.traceback() for details�����cCstd��)ztMust be implemented in subclasses.
 217  
 218          Subclasses must call :meth:`_init` for standard initialisation.
 219          z,This class can not be instantiated directly.)�NotImplementedErrorrrrrr}szBackgroundJobBase.__init__cs�dD]
 220  }t||�sJd|��qd|_tj|_tj|_d|_d|_zt	�j
 221  j�Wntdddd	�j�Y�fd
 222  d�|_
 223  d|_tj�|�dS)z3Common initialization for all BackgroundJob objects)�call�strformzMissing attribute <%s>NFz!<BackgroundJob has not completed>�ContextZNoColorr#)�modeZcolor_scheme�	tb_offsetcs�ddd�Srrr�Zmake_tbrr�<lambda>�sz)BackgroundJobBase._init.<locals>.<lambda>)�hasattrr3r
 224  �stat_createdr?rrB�finishedrWrZ
 225  InteractiveTB�textr�_make_tb�_tb�	threading�Threadr)r�attrrrgr�_init�s&��zBackgroundJobBase._initcCs|jSr)rcrrrr�__str__�szBackgroundJobBase.__str__cCsd|j|jfS)Nz<BackgroundJob #%d: %s>)r3rcrrrr�__repr__�szBackgroundJobBase.__repr__cCst|j�dSr)rErnrrrrrX�szBackgroundJobBase.tracebackcCslztj|_tj|_|��|_Wntj|_tj|_d|_	d|_|�
 226  �|_YdStj|_tj
 227  |_d|_	dS)Nz7<BackgroundJob died, call jobs.traceback() for details>T)r
 228  �stat_runningr?rrBrbrW�	stat_deadrrkrmrn�stat_completedrrrrr�run�s
 229  zBackgroundJobBase.runN)rZr[r\r]rjrrurrwrrvrrrrrsrtrXrxrrrrr
 230  esr
 231  c@s"eZdZdZddd�Zdd�ZdS)r1zDEvaluate an expression as a background job (uses a separate thread).NcCsRt|dd�|_|dur
 232  in|}|durin|}||_|_||_||_|��dS)z�Create a new job from a string which can be fed to eval().
 233  
 234          global/locals dicts can be provided, which will be passed to the eval
 235          call.z<BackgroundJob compilation>�evalN)�compile�code�
 236  expressionrcr:r;rr)rr|r:r;rrrr�szBackgroundJobExpr.__init__cCst|j|j|j�Sr)ryr{r:r;rrrrrb�szBackgroundJobExpr.call)NN�rZr[r\r]rrbrrrrr1�s
 237  r1c@s eZdZdZdd�Zdd�ZdS)r(zARun a function call as a background job (uses a separate thread).cOs8t|�std��||_||_||_t|�|_|��dS)z�Create a new job from a callable object.
 238  
 239          Any positional arguments and keyword args given to this constructor
 240          after the initial callable are passed directly to it.z4first argument to BackgroundJobFunc must be callableN)r&r2�funcr6r7r*rcrr)rr~r6r7rrrr�s�
 241  zBackgroundJobFunc.__init__cCs|j|ji|j��Sr)r~r6r7rrrrrb�szBackgroundJobFunc.callNr}rrrrr(�sr()r]r+roZIPythonrZIPython.core.ultratbr�loggingrr�objectrrpr
 242  r1r(rrrr�<module>s>X