"""
================
Warping programs
================

The ``@command`` decorator makes binding command line executables
easy to write and easy to use.

To wrap a program, write a function that takes whatever arguments
you will need to run the program like if it where on the shell.
The function should return a dictionary containing several keys:

    * mandatory: ``arguments``
    * optional: ``stdin``
    * optional: ``return_value``.

Firstly, ``arguments`` should be a list of strings which is
the actual command and arguments to be executed (e.g. ``["touch", filename]``).

Secondly, ``stdin`` should be a value to feed the subprocess once it is launched.

Thirdly, ``return_value`` should be a value to return, or a callable
object which takes ``(stdout,strerr)`` as parameters and returns the value
that will be passed back to the user when this program is run.
You can also simply specify ``"stdout"`` to have the output of the
process returned directly.

For example, to wrap ``touch``, we write a one argument function that
takes the filename of the file to touch, and apply the ``@command``
decorator to it::

    from plumbing.common import command

    @command
    def touch(filename):
        return {"arguments": ["touch", filename],
                "return_value": filename}

We can now call this function directly::

     f = touch("myfile")

The value returned by touch is ``"myfile"``, the name of
the touched file.

A more complicated example would include binding the BLASTP algorithm::

    from plumbing.common import command

    @command
    def blastp(database, sequences, **kwargs):
         \"\"\"Will launch the 'blastp' algorithm using the NCBI executable.

        :param database: The path to the database to blast against.
        :param sequences: A fasta formated string.
        :param **kwargs: Extra parameters that will be passed to the executable
                        For instance, you could specify "e=1e-20".
        :returns: A list of top hits in blast format.
        \"\"\"
        return {"arguments": ["blastall", "-p", "blastp", "-d" database] +
                             [a for k,v in kwargs.items() for a in ('-'+k,v)],
                "stdin": sequences)
                "return_value": 'stdout'}

As shown above, we can now call this function directly::

     hits = blastp("swissprot", open("proteins.fasta").read())

The value returned by blastp is a long string containing all the
results from the BLASTP algorithm.

Often you want to call a function, but not block when it returns
so you can run several in parallel. ``@command`` also creates a
method ``parallel`` which does this. The return value is a
Future object with a single method: ``wait()``. When you call
``wait()``, it blocks until the program finishes, then returns the
same value that you would get from calling the function directly.
So, to touch two files, and not block until both commands have
started, you would write::

    a = blastp.parallel("nr", open("fasta1").read(), e=1e-20)
    b = blastp.parallel("nr", open("fasta2").read(), e=1e-20)
    hitsA = a.wait()
    hitsB = b.wait()

The ``parallel`` method will runs processes without blocking.
Other methods exists for running commands in parallel.