;
AHc           @   sx  d  Z  d k l Z d e i d Z e i Z d k Z d k Z d k	 l
 Z
 d k l Z l Z d f  d     YZ d	 e i f d
     YZ d e f d     YZ d e f d     YZ e d j o d k Z d d  Z d d  Z d d d  Z e   Z e i e d  e i e d h  d d <e i e d  e i d  e d i GHe d i   d Ge d i GHn d S(   s  Manage background (threaded) jobs conveniently from an interactive shell.

This module provides a BackgroundJobManager class.  This is the main class
meant for public usage, it implements an object which can create and manage
new background jobs.

It also provides the actual job classes managed by these BackgroundJobManager
objects, see their docstrings below.


This system was inspired by discussions with B. Granger and the
BackgroundCommand class described in the book Python Scripting for
Computational Science, by H. P. Langtangen:

http://folk.uio.no/hpl/scripting

(although ultimately no code from this text was used, as IPython's system is a
separate implementation).

$Id: background_jobs.py 994 2006-01-08 08:29:44Z fperez $
(   s   Releases   %s <%s>s   FernandoN(   s   AutoFormattedTB(   s   warns   errors   BackgroundJobManagerc           B   s   t  Z d  Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z	 d   Z
 d	 d
  Z d   Z d   Z d   Z d   Z RS(   sh  Class to manage a pool of backgrounded threaded jobs.

    Below, we assume that 'jobs' is a BackgroundJobManager instance.
    
    Usage summary (see the method docstrings for details):

      jobs.new(...) -> start a new job
      
      jobs() or jobs.status() -> print status summary of all jobs

      jobs[N] -> returns job number N.

      foo = jobs[N].result -> assign to variable foo the result of job N

      jobs[N].traceback() -> print the traceback of dead job N

      jobs.remove(N) -> remove (finished) job N

      jobs.flush_finished() -> remove all finished jobs
      
    As a convenience feature, BackgroundJobManager instances provide the
    utility result and traceback methods which retrieve the corresponding
    information from the jobs list:

      jobs.result(N) <--> jobs[N].result
      jobs.traceback(N) <--> jobs[N].traceback()

    While this appears minor, it allows you to use tab completion
    interactively on the job manager instance.

    In interactive mode, IPython provides the magic fuction %bg for quick
    creation of backgrounded expression-based jobs. Type bg? for details.c         C   sj   g  |  _ g  |  _ g  |  _ h  |  _ g  |  _ g  |  _ t i |  _	 t i
 |  _ t i |  _ t i |  _ d  S(   N(   s   selfs   jobs_runs	   jobs_comps	   jobs_deads   jobs_alls   _comp_reports   _dead_reports   BackgroundJobBases   stat_created_cs
   _s_createds   stat_running_cs
   _s_runnings   stat_completed_cs   _s_completeds   stat_dead_cs   _s_dead(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   __init__L   s    						c   
      O   sV  t  |  o( | i d h   } t | | |  } n t | t	  o | o+ t
 i d  }	 |	 i |	 i f \ } } nR t |  d j o | d } } n- t |  d j o | \ } } n
 t d  t | | |  } n   |  i i   } | o t |  d | _ n
 d | _ |  i i |  | |  i | i <d | i GH| i   | Sd S(   s
  Add a new background job and start it in a separate thread.

        There are two types of jobs which can be created:

        1. Jobs based on expressions which can be passed to an eval() call.
        The expression must be given as a string.  For example:

          job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])

        The given expression is passed to eval(), along with the optional
        global/local dicts provided.  If no dicts are given, they are
        extracted automatically from the caller's frame.
        
        A Python statement is NOT a valid eval() expression.  Basically, you
        can only use as an eval() argument something which can go on the right
        of an '=' sign and be assigned to a variable.

        For example,"print 'hello'" is not valid, but '2+3' is.

        2. Jobs given a function object, optionally passing additional
        positional arguments:

          job_manager.new(myfunc,x,y)

        The function is called with the given arguments.

        If you need to pass keyword arguments to your function, you must
        supply them as a dict named kw:

          job_manager.new(myfunc,x,y,kw=dict(z=1))

        The reason for this assymmetry is that the new() method needs to
        maintain access to its own keywords, and this prevents name collisions
        between arguments to new() and arguments to your own functions.

        In both cases, the result is stored in the job.result field of the
        background job object.


        Notes and caveats:

        1. All threads running share the same standard output.  Thus, if your
        background jobs generate output, it will come out on top of whatever
        you are currently writing.  For this reason, background jobs are best
        used with silent functions which simply return their output.

        2. Threads also all work within the same global namespace, and this
        system does not lock interactive variables.  So if you send job to the
        background which operates on a mutable object for a long time, and
        start modifying that same mutable object interactively (or in another
        backgrounded job), all sorts of bizarre behaviour will occur.

        3. If a background job is spending a lot of time inside a C extension
        module which does not release the Python Global Interpreter Lock
        (GIL), this will block the IPython prompt.  This is simply because the
        Python interpreter can only switch between threads at Python
        bytecodes.  While the execution is inside C code, the interpreter must
        simply wait unless the extension module releases the GIL.

        4. There is no way, due to limitations in the Python threads library,
        to kill a thread once it has started.s   kwi   i    i   s4   Expression jobs take at most 2 args (globals,locals)s'   Starting job # %s in a separate thread.N(   s   callables   func_or_exps   kwargss   gets   kws   BackgroundJobFuncs   argss   jobs
   isinstances
   basestrings   syss	   _getframes   frames	   f_globalss   f_localss   globs   locs   lens
   ValueErrors   BackgroundJobExprs   selfs   jobs_alls   keyss   jkeyss   maxs   nums   jobs_runs   appends   start(
   s   selfs   func_or_exps   argss   kwargss   locs   globs   jobs   jkeyss   kws   frame(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   new\   s0    = 		
c         C   s   |  i | Sd  S(   N(   s   selfs   jobs_alls   key(   s   selfs   key(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   __getitem__   s    c         C   s   |  i   Sd S(   s   An alias to self.status(),

        This allows you to simply call a job manager instance much like the
        Unix jobs shell command.N(   s   selfs   status(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   __call__   s     c         C   s   |  i |  i |  i f \ } } } |  i } x t t	 |   D] } | | } | i } | | j o q= q= | | j o. |  i i |  |  i i |  t | | <q= | | j o. |  i i |  |  i i |  t | | <q= q= Wt t |  i  |  _ d S(   s  Update the status of the job lists.

        This method moves finished jobs to one of two lists:
          - self.jobs_comp: jobs which completed successfully
          - self.jobs_dead: jobs which finished but died.

        It also copies those jobs to corresponding _report lists.  These lists
        are used to report jobs completed/dead since the last update, and are
        then cleared by the reporting function after each call.N(   s   selfs
   _s_runnings   _s_completeds   _s_deads   runs   comps   deads   jobs_runs   ranges   lens   nums   jobs	   stat_codes   stats	   jobs_comps   appends   _comp_reports   Falses	   jobs_deads   _dead_reports   filters   None(   s   selfs   stats   runs   comps   jobs   jobs_runs   nums   dead(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   _update_status   s$    	 !	 
	c         C   s@   | o5 d | GHx  | D] } d | i | f GHq WHt Sn d S(   sY   Report summary for a given job group.

        Return True if the group had any elements.s   %s jobs:s   %s : %sN(   s   groups   names   jobs   nums   True(   s   selfs   groups   names   job(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   _group_report   s     	 c         C   sS   t  |  } | o< h  d d <i | d  } d | | | f GHg  | (t Sn d S(   sK   Flush a given job group

        Return True if the group had any elements.i   s    s   ss   Flushing %s %s job%s.N(   s   lens   groups   njobss
   setdefaults   plurals   names   True(   s   selfs   groups   names   njobss   plural(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   _group_flush   s     c         C   sW   |  i   |  i |  i d  } |  i |  i d  } g  |  i (g  |  i (| p | Sd S(   s   Print the status of newly finished jobs.

        Return True if any new jobs are reported.

        This call resets its own state every time, so it only reports jobs
        which have finished since the last time it was called.s	   Completeds&   Dead, call job.traceback() for detailsN(   s   selfs   _update_statuss   _group_reports   _comp_reports   new_comps   _dead_reports   new_dead(   s   selfs   new_comps   new_dead(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   _status_new   s     
	

i    c         C   s[   |  i   |  i |  i d  |  i |  i d  |  i |  i d  g  |  i (g  |  i (d S(   s3   Print a status of all jobs currently being managed.s   Runnings	   Completeds   DeadN(   s   selfs   _update_statuss   _group_reports   jobs_runs	   jobs_comps	   jobs_deads   _comp_reports   _dead_report(   s   selfs   verbose(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   status  s     

c         C   s   y |  i | } Wn! t j
 o t d |  ny X| i } | |  i j o t d |  d SnI | |  i j o |  i	 i
 |  n% | |  i j o |  i i
 |  n d S(   s*   Remove a finished (completed or dead) job.s   Job #%s not founds0   Job #%s is still running, it can not be removed.N(   s   selfs   jobs_alls   nums   jobs   KeyErrors   errors	   stat_codes
   _s_runnings   _s_completeds	   jobs_comps   removes   _s_deads	   jobs_dead(   s   selfs   nums	   stat_codes   job(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   remove  s     	c         C   s   |  i   o t d  d Sn |  i } x" |  i |  i D] } | | i =q9 W|  i |  i d  } |  i |  i d  } | p | o	 d GHn d S(   s  Flush all jobs finished (completed and dead) from lists.

        Running jobs are never flushed.

        It first calls _status_new(), to update info. If any jobs have
        completed since the last _status_new() call, the flush operation
        aborts.s<   New jobs completed since last _status_new(), aborting flush.Ns	   Completeds   Deads   No jobs to flush.(   s   selfs   _status_news   errors   jobs_alls	   jobs_comps	   jobs_deads   jobs   nums   _group_flushs   fl_comps   fl_dead(   s   selfs   fl_deads   jobs_alls   jobs   fl_comp(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   flush_finished"  s     
	 c         C   s:   y |  i | i SWn! t j
 o t d |  n Xd S(   s(   result(N) -> return the result of job N.s   Job #%s not foundN(   s   selfs   jobs_alls   nums   results   KeyErrors   error(   s   selfs   num(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   result;  s
     c         C   s=   y |  i | i   Wn! t j
 o t d |  n Xd  S(   Ns   Job #%s not found(   s   selfs   jobs_alls   nums	   tracebacks   KeyErrors   error(   s   selfs   num(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys	   tracebackB  s    (   s   __name__s
   __module__s   __doc__s   __init__s   news   __getitem__s   __call__s   _update_statuss   _group_reports   _group_flushs   _status_news   statuss   removes   flush_finisheds   results	   traceback(    (    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   BackgroundJobManager*   s     		[									s   BackgroundJobBasec           B   st   t  Z d  Z d Z d Z d Z d Z d Z d Z d Z	 d Z
 d	   Z d
   Z d   Z d   Z d   Z d   Z RS(   s  Base class to build BackgroundJob classes.

    The derived classes must implement:

    - Their own __init__, since the one here raises NotImplementedError.  The
    derived constructor must call self._init() at the end, to provide common
    initialization.

    - A strform attribute used in calls to __str__.

    - A call() method, which will make the actual execution call and must
    return a value to be held in the 'result' field of the job object.s   Createdi    s   Runningi   s	   Completedi   s2   Dead (Exception), call job.traceback() for detailsic         C   s   t  d  d  S(   Ns,   This class can not be instantiated directly.(   s   NotImplementedError(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   __init__`  s    c         C   s   x2 d d g D]$ } t |  |  p t d |  q Wt |  _ t i |  _ t i	 |  _
 t |  _ d |  _ y t i i |  _ Wn( t d d d d d	 d
  i |  _ n Xt |  _ t i i |   d S(   s3   Common initialization for all BackgroundJob objectss   calls   strforms   Missing attribute <%s>s!   <BackgroundJob has not completed>s   modes   Contexts   color_schemes   NoColors	   tb_offseti   N(   s   attrs   hasattrs   selfs   AssertionErrors   Nones   nums   BackgroundJobBases   stat_createds   statuss   stat_created_cs	   stat_codes   Falses   finisheds   results   __IPYTHON__s   InteractiveTBs   texts   _make_tbs   AutoFormattedTBs   _tbs	   threadings   Threads   __init__(   s   selfs   attr(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   _initd  s"      "					c         C   s   |  i Sd  S(   N(   s   selfs   strform(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   __str__~  s    c         C   s   d |  i Sd  S(   Ns   <BackgroundJob: %s>(   s   selfs   strform(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   __repr__  s    c         C   s   |  i GHd  S(   N(   s   selfs   _tb(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys	   traceback  s    c         C   s   y+ t  i |  _ t  i |  _ |  i   |  _ Wn@ t  i |  _ t  i	 |  _ t
 |  _ d |  _ |  i   |  _ n" Xt  i |  _ t  i |  _ t |  _ d  S(   Ns6   <BackgroundJob died, call job.traceback() for details>(   s   BackgroundJobBases   stat_runnings   selfs   statuss   stat_running_cs	   stat_codes   calls   results	   stat_deads   stat_dead_cs   Nones   finisheds   _make_tbs   _tbs   stat_completeds   stat_completed_cs   True(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   run  s    		(   s   __name__s
   __module__s   __doc__s   stat_createds   stat_created_cs   stat_runnings   stat_running_cs   stat_completeds   stat_completed_cs	   stat_deads   stat_dead_cs   __init__s   _inits   __str__s   __repr__s	   tracebacks   run(    (    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   BackgroundJobBaseI  s    					s   BackgroundJobExprc           B   s&   t  Z d  Z e e d  Z d   Z RS(   sD   Evaluate an expression as a background job (uses a separate thread).c         C   ss   t  | d d  |  _ | t j o
 h  } n | t j o
 h  } n | |  _ |  _ | |  _ | |  _ |  i   d S(   s   Create a new job from a string which can be fed to eval().

        global/locals dicts can be provided, which will be passed to the eval
        call.s   <BackgroundJob compilation>s   evalN(	   s   compiles
   expressions   selfs   codes   globs   Nones   locs   strforms   _init(   s   selfs
   expressions   globs   loc(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   __init__  s     

		c         C   s   t  |  i |  i |  i  Sd  S(   N(   s   evals   selfs   codes   globs   loc(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   call  s    (   s   __name__s
   __module__s   __doc__s   Nones   __init__s   call(    (    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   BackgroundJobExpr  s    s   BackgroundJobFuncc           B   s    t  Z d  Z d   Z d   Z RS(   sA   Run a function call as a background job (uses a separate thread).c         O   s}   t  |  p
 t d  | t j o
 g  } n | t j o
 h  } n | |  _ | |  _ | |  _ t |  |  _ |  i	   d S(   s   Create a new job from a callable object.

        Any positional arguments and keyword args given to this constructor
        after the initial callable are passed directly to it.s   first argument must be callableN(
   s   callables   funcs   AssertionErrors   argss   Nones   kwargss   selfs   strs   strforms   _init(   s   selfs   funcs   argss   kwargs(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   __init__  s     

			c         C   s   |  i |  i |  i   Sd  S(   N(   s   selfs   funcs   argss   kwargs(   s   self(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   call  s    (   s   __name__s
   __module__s   __doc__s   __init__s   call(    (    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   BackgroundJobFunc  s    	s   __main__i   c         O   s0   t  d |  d | d |  } t i |   | Sd  S(   Ns   intervals   argss   kwargs(   s   dicts   intervals   as   kws   argss   times   sleep(   s   intervals   as   kws   args(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys	   sleepfunc  s
    	c         O   s   t  i |   t d  S(   N(   s   times   sleeps   intervals   die(   s   intervals   as   kw(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   diefunc  s    i   i   c         C   s-   x& t  |  D] } t i |   d GHq Wd  S(   Ns   In the background...(   s   ranges   repss   ns   times   sleeps   interval(   s   intervals   repss   n(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys	   printfunc  s     i   s   kws   repss   printfunc(1,3)s   The result of job #0 is:i    (   s   __doc__s   IPythons   Releases   authorss
   __author__s   licenses   __license__s   syss	   threadings   IPython.ultraTBs   AutoFormattedTBs   IPython.genutilss   warns   errors   BackgroundJobManagers   Threads   BackgroundJobBases   BackgroundJobExprs   BackgroundJobFuncs   __name__s   times	   sleepfuncs   diefuncs	   printfuncs   jobss   news   statuss	   tracebacks   result(   s   warns   diefuncs   BackgroundJobFuncs   __license__s   times   BackgroundJobExprs   BackgroundJobManagers
   __author__s   syss	   threadings   AutoFormattedTBs   errors   Releases	   sleepfuncs   BackgroundJobBases   jobss	   printfunc(    (    sG   /nyx/web/d/b/dbachman/work/src/ipython-0.8.4/IPython/background_jobs.pys   ?   s2   				  N		