Skip to content
Snippets Groups Projects
execution.py 2.87 KiB
Newer Older
#  This file is part of the mantidqt package
#
#  Copyright (C) 2017 mantidproject
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, unicode_literals)

# std imports

# local imports
from mantidqt.utils.async import AsyncTask


class PythonCodeExecution(object):
    """Provides the ability to execute arbitrary
    strings of Python code. It supports
    reporting progress updates in asynchronous execution
    """

    def execute_async(self, code_str, user_globals,
                      user_locals, success_cb=None, error_cb=None,
                      progress_cb=None):
        """
        Execute the given code string on a separate thread. This function
        returns as soon as the new thread starts

        :param code_str: A string containing code to execute
        :param user_globals: A mutable mapping type to store global variables
        :param user_locals: A mutable mapping type to store local variables
        :param success_cb: A callback of the form f() called on success
        :param error_cb: A callback of the form f(exc) called on error,
        :param progress_cb: A callback for progress updates
        providing the exception generated
        :returns: The created async task
        """
        # AsyncTask's callbacks have a slightly different form
        if success_cb:
            def on_success(_): success_cb()
        else:
            def on_success(_): pass

        if error_cb:
            def on_error(task_result): error_cb(task_result.exception)
        else:
            def on_error(_): pass

        t = AsyncTask(self.execute, args=(code_str, user_globals, user_locals),
                      success_cb=on_success, error_cb=on_error)
        t.start()
        return t

    def execute(self, code_str, user_globals,
                user_locals):
        """Execute the given code on the calling thread
        within the provided context. All exceptions are caught
        and stored with the returned result

        :param code_str: A string containing code to execute
        :param user_globals: A mutable mapping type to store global variables
        :param user_locals: A mutable mapping type to store local variables
        :raises: Any error that the code generates
        """
        exec(code_str, user_globals, user_locals)