Exemplo n.º 1
0
def run(function_name=None, function_input=None):
    """Triggers the execution environment entry point processor.

    Use this function in the program entry point code:

    .. code-block:: python

       import dxpy

       @dxpy.entry_point('main')
       def hello(i):
           pass

       dxpy.run()

    This method may be used to invoke the program either in a production
    environment (inside the execution environment) or for local
    debugging (in the debug harness), as follows:

    If the environment variable *DX_JOB_ID* is set, the processor
    retrieves the job with that ID from the API server. The job's
    *function* field indicates the function name to be invoked. That
    function name is looked up in the table of all methods decorated
    with *@dxpy.entry_point('name')* in the module from which
    :func:`run()` was called, and the matching method is invoked (with
    the job's input supplied as parameters). This is the mode of
    operation used in the DNAnexus execution environment.

    .. warning::

       The parameters *function_name* and *function_input* are
       disregarded in this mode of operation.

    If the environment variable *DX_JOB_ID* is not set, the function
    name may be given in *function_name*; if not set, it is set by the
    environment variable *DX_TEST_FUNCTION*. The function input may be
    given in *function_input*; if not set, it is set by the local file
    *job_input.json* which is expected to be present.

    The absence of *DX_JOB_ID* signals to :func:`run()` that execution
    is happening in the debug harness. In this mode of operation, all
    calls to :func:`dxpy.bindings.dxjob.new_dxjob()` (and higher level
    handler methods which use it) are intercepted, and :func:`run()` is
    invoked instead with appropriate inputs.

    """

    global RUN_COUNT
    RUN_COUNT += 1

    dx_working_dir = os.getcwd()

    if dxpy.JOB_ID is not None:
        logging.basicConfig()

        try:
            logging.getLogger().addHandler(dxpy.DXLogHandler())
        except dxpy.exceptions.DXError:
            print(
                "TODO: FIXME: the EE client should die if logging is not available"
            )

        job = dxpy.describe(dxpy.JOB_ID)
    else:
        if function_name is None:
            function_name = os.environ.get('DX_TEST_FUNCTION', 'main')
        if function_input is None:
            with open("job_input.json", "r") as fh:
                function_input = json.load(fh)

        job = {'function': function_name, 'input': function_input}

    with open("job_error_reserved_space", "w") as fh:
        fh.write(
            "This file contains reserved space for writing job errors in case the filesystem becomes full.\n"
            + " " * 1024 * 64)

    print("Invoking", job.get('function'), "with", job.get('input'))

    try:
        result = ENTRY_POINT_TABLE[job['function']](**job['input'])
    except dxpy.AppError as e:
        save_error(e, dx_working_dir, error_type="AppError")
        raise
    except Exception as e:
        save_error(e, dx_working_dir)
        raise

    if result is not None:
        # TODO: protect against client removing its original working directory
        os.chdir(dx_working_dir)
        with open("job_output.json", "wb") as fh:
            json.dump(result, fh, indent=2, cls=DXJSONEncoder)
            fh.write(b"\n")

    return result
Exemplo n.º 2
0
#
# See https://wiki.dnanexus.com/Developer-Portal for documentation and
# tutorials on how to modify this file.
#
# DNAnexus Python Bindings (dxpy) documentation:
#   http://autodoc.dnanexus.com/bindings/python/current/

import subprocess
import shlex
from multiprocessing import cpu_count
import dxpy
import common
import logging

logger = logging.getLogger(__name__)
logger.addHandler(dxpy.DXLogHandler())
logger.propagate = False
logger.setLevel(logging.INFO)

SPP_VERSION_MAP = {
    "1.10.1": "/phantompeakqualtools/spp_1.10.1.tar.gz",
    "1.14": "/phantompeakqualtools/spp-1.14.tar.gz"
}


def xcor_parse(fname):
    with open(fname, 'r') as xcor_file:
        if not xcor_file:
            return None

        lines = xcor_file.read().splitlines()
Exemplo n.º 3
0
def run(function_name=None, function_input=None):
    '''
    Triggers the execution environment entry point processor.

    Use this function in the program entry point code:

    import dxpy

    @dxpy.entry_point('main')
    def hello(i):
        pass

    dxpy.run()

    If the environment variable *DX_JOB_ID* is set, the processor retrieves the job with that ID from the API server.
    The job's *job.function* field is used to invoke the entry point function in the module from which run() has been
    called. The function name is looked up in the table of all functions decorated with *@dxpy.entry_point('name')*.
    This is the mode of operation used in the DNAnexus execution environment.
    WARNING: The parameters *function_name* and *function_input* are disregarded in this mode of operation.

    If the environment variable *DX_JOB_ID* is not set, the function
    name may be given in *function_name*; if not set, it is set by the
    environment variable *DX_TEST_FUNCTION*. The function input may be
    given in *function_input*; if not set, it is set by the local file
    *job_input.json* which is expected to be present.

    The absence of *DX_JOB_ID* signals to run() that execution is happening in the debug harness. In this mode of
    operation, all calls to *dxpy.bindings.DXJob.new* (and higher level handler methods which use it) are intercepted, and run()
    is invoked instead with appropriate inputs. The initial invocation of *dxpy.run()* (with no arguments) need not be
    changed; instead, use a local file *job_input.json*.

    With this, no program code requires changing between the two modes.
    '''

    global RUN_COUNT
    RUN_COUNT += 1

    dx_working_dir = os.getcwd()

    if dxpy.JOB_ID is not None:
        logging.basicConfig()

        try:
            logging.getLogger().addHandler(dxpy.DXLogHandler())
        except dxpy.exceptions.DXError:
            print "TODO: FIXME: the EE client should die if logging is not available"

        job = dxpy.describe(dxpy.JOB_ID)
    else:
        if function_name is None:
            function_name = os.environ.get('DX_TEST_FUNCTION', 'main')
        if function_input is None:
            with open("job_input.json", "r") as fh:
                function_input = json.load(fh)

        job = {'function': function_name, 'input': function_input}

    with open("job_error_reserved_space", "w") as fh:
        fh.write(
            "This file contains reserved space for writing job errors in case the filesystem becomes full.\n"
            + " " * 1024 * 64)

    print "Invoking", job.get('function'), "with", job.get('input')

    try:
        result = ENTRY_POINT_TABLE[job['function']](**job['input'])
    except dxpy.AppError as e:
        if dxpy.JOB_ID is not None:
            os.chdir(dx_working_dir)
            with open("job_error.json", "w") as fh:
                fh.write(
                    json.dumps({
                        "error": {
                            "type": "AppError",
                            "message": _format_exception_message(e)
                        }
                    }) + "\n")
        raise
    except Exception as e:
        if dxpy.JOB_ID is not None:
            os.chdir(dx_working_dir)
            try:
                os.unlink("job_error_reserved_space")
            except:
                pass
            with open("job_error.json", "w") as fh:
                fh.write(
                    json.dumps({
                        "error": {
                            "type": "AppInternalError",
                            "message": _format_exception_message(e)
                        }
                    }) + "\n")
        raise

    result = convert_handlers_to_dxlinks(result)

    if result is not None:
        # TODO: protect against client removing its original working directory
        os.chdir(dx_working_dir)
        with open("job_output.json", "w") as fh:
            fh.write(json.dumps(result) + "\n")

    return result