Ejemplo n.º 1
0
 def _load(self, file_name):
     project_loader = ProjectLoader(self.project_file_ext)
     task = BlockingAsyncTaskWithCallback(
         target=project_loader.load_project,
         args=[file_name],
         blocking_cb=QApplication.processEvents)
     task.start()
Ejemplo n.º 2
0
    def test_successful_no_arg_operation_without_callback(self):
        def foo():
            return 42

        task = BlockingAsyncTaskWithCallback(foo)

        self.assertEqual(42, task.start())
Ejemplo n.º 3
0
    def test_successful_no_arg_operation_without_callback(self):
        def foo():
            return 42

        task = BlockingAsyncTaskWithCallback(foo)

        self.assertEqual(42, task.start())
Ejemplo n.º 4
0
    def async_run_code(self, code_obj, result=None, async_=False):
        """A monkey-patched replacement for the InteractiveShell.run_code method.
        It runs the in a separate thread and calls QApplication.processEvents
        periodically until the method finishes.

        :param code_obj : code object
          A compiled code object, to be executed
        :param result : ExecutionResult, optional
          An object to store exceptions that occur during execution.
        :param async_ : Bool (Experimental))
           Attempt to run top-level asynchronous code in a default loop.

        :returns: An AsyncTaskResult object
        """
        # Different target arguments depending on IPython's version
        function_parameters = getfullargspec(orig_run_code)
        if 'result' in function_parameters.args:
            if hasattr(function_parameters, 'kwonlyargs'
                       ) and 'async_' in function_parameters.kwonlyargs:
                return orig_run_code(
                    code_obj, result,
                    async_=async_)  # return coroutine to be awaited
            else:
                task = BlockingAsyncTaskWithCallback(
                    target=orig_run_code,
                    args=(code_obj, result),
                    blocking_cb=QApplication.processEvents)
        else:
            task = BlockingAsyncTaskWithCallback(
                target=orig_run_code,
                args=(code_obj, ),
                blocking_cb=QApplication.processEvents)
        return task.start()
Ejemplo n.º 5
0
    def execute_async(self,
                      code_str,
                      line_offset,
                      filename=None,
                      blocking=False):
        """
        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 line_offset: See PythonCodeExecution.execute()
        :param filename: See PythonCodeExecution.execute()
        :param blocking: If True the call will block until the task is finished
        :returns: The created async task, only returns task if the blocking is False
        """
        # Stack is chopped on error to avoid the  AsyncTask.run->self.execute calls appearing
        # as these are not useful for the user in this context
        if not blocking:
            task = AsyncTask(self.execute,
                             args=(code_str, filename, line_offset),
                             success_cb=self._on_success,
                             error_cb=self._on_error)
            task.start()
            self._task = task
            return task
        else:
            self._task = BlockingAsyncTaskWithCallback(
                self.execute,
                args=(code_str, filename, line_offset),
                success_cb=self._on_success,
                error_cb=self._on_error,
                blocking_cb=QApplication.processEvents)
            return self._task.start()
Ejemplo n.º 6
0
    def test_successful_positional_args_operation(self):
        def foo(shift):
            return 42 + shift

        shift = 2
        task = BlockingAsyncTaskWithCallback(foo, args=(shift,))

        self.assertEqual(42 + shift, task.start())
Ejemplo n.º 7
0
    def test_successful_args_and_kwargs_operation(self):
        def foo(scale, shift):
            return scale*42 + shift

        scale, shift = 2, 4

        task = BlockingAsyncTaskWithCallback(foo, args=(scale,), kwargs={'shift': shift})
        self.assertEqual(scale * 42 + shift, task.start())
Ejemplo n.º 8
0
    def test_successful_positional_args_operation(self):
        def foo(shift):
            return 42 + shift

        shift = 2
        task = BlockingAsyncTaskWithCallback(foo, args=(shift, ))

        self.assertEqual(42 + shift, task.start())
Ejemplo n.º 9
0
    def test_successful_args_and_kwargs_operation(self):
        def foo(scale, shift):
            return scale * 42 + shift

        scale, shift = 2, 4

        task = BlockingAsyncTaskWithCallback(foo,
                                             args=(scale, ),
                                             kwargs={'shift': shift})
        self.assertEqual(scale * 42 + shift, task.start())
Ejemplo n.º 10
0
 def generate_script_from_workspaces(self):
     if not self.workspacewidget.empty_of_workspaces():
         task = BlockingAsyncTaskWithCallback(target=self._generate_script_from_workspaces,
                                              blocking_cb=QApplication.processEvents)
         task.start()
     else:
         # Tell users they need a workspace to do that
         QMessageBox().warning(None, "No Workspaces!",
                               "In order to generate a recovery script there needs to be some workspaces.",
                               QMessageBox.Ok)
Ejemplo n.º 11
0
    def _do_show_detectors(self, names):
        successful_workspaces = []
        for ws in self._ads.retrieveWorkspaces(names, unrollGroups=True):
            try:
                task = BlockingAsyncTaskWithCallback(self._run_create_detector_table, [ws],
                                                     blocking_cb=QApplication.processEvents)
                task.start()
            except RuntimeError:
                continue
            else:
                successful_workspaces.append(ws.name())

        self._do_show_data(list(map(lambda x: x + "-Detectors", successful_workspaces)))
Ejemplo n.º 12
0
 def async_run_code(self, code_obj, result=None):
     """A monkey-patched replacement for the InteractiveShell.run_code method.
     It runs the in a separate thread and calls QApplication.processEvents
     periodically until the method finishes
     """
     # ipython 3.0 introduces a third argument named result
     if len(getfullargspec(orig_run_code).args) == 3:
         args = (code_obj, result)
     else:
         args = (code_obj, )
     task = BlockingAsyncTaskWithCallback(
         target=orig_run_code,
         args=args,
         blocking_cb=QApplication.processEvents)
     return task.start()
Ejemplo n.º 13
0
    def save_as(self):
        """
        The function that is called if the save as... button is clicked on the mainwindow
        :return: True; if the user cancels.
        """
        path = self._save_file_dialog()
        if path is None:
            # Cancel close dialogs
            return True

        # todo: get a list of workspaces but to be implemented on GUI implementation
        self.last_project_location = path
        task = BlockingAsyncTaskWithCallback(
            target=self._save, blocking_cb=QApplication.processEvents)
        task.start()
Ejemplo n.º 14
0
    def test_unsuccessful_args_and_kwargs_operation_raises_exception(self):
        def foo(scale, shift):
            raise RuntimeError("Bad operation")

        scale, shift = 2, 4
        task = BlockingAsyncTaskWithCallback(foo,
                                             args=(scale, ),
                                             kwargs={'shift': shift})
        self.assertRaises(RuntimeError, task.start)
Ejemplo n.º 15
0
    def save(self, conf=None):
        """
        The function that is called if the save button is clicked on the mainwindow
        :param: conf: an optional UserConfig to which the user's input will be saved (if the save dialog is shown).
        :return: True; if the user cancels
        """
        if self.last_project_location is None:
            return self.open_project_save_dialog(conf)
        else:
            # Offer an are you sure? overwriting GUI
            answer = self._offer_overwriting_gui()

            if answer == QMessageBox.Yes:
                # Actually save
                task = BlockingAsyncTaskWithCallback(target=self._save, blocking_cb=QApplication.processEvents)
                task.start()
            elif answer == QMessageBox.No:
                # Save with a new name
                return self.open_project_save_dialog(conf)
            else:
                # Cancel clicked
                return True
Ejemplo n.º 16
0
    def save(self):
        """
        The function that is called if the save button is clicked on the mainwindow
        :return: True; if the user cancels
        """
        if self.last_project_location is None:
            return self.save_as()
        else:
            # Offer an are you sure? overwriting GUI
            answer = self._offer_overwriting_gui()

            if answer == QMessageBox.Yes:
                # Actually save
                task = BlockingAsyncTaskWithCallback(
                    target=self._save, blocking_cb=QApplication.processEvents)
                task.start()
            elif answer == QMessageBox.No:
                # Save with a new name
                return self.save_as()
            else:
                # Cancel clicked
                return True
Ejemplo n.º 17
0
    def execute_async(self, code_str, filename=None, blocking=False):
        """
        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 filename: See PythonCodeExecution.execute()
        :param blocking: If True the call will block until the task is finished
        :returns: The created async task, only returns task if the blocking is False
        """
        # Stack is chopped on error to avoid the  AsyncTask.run->self.execute calls appearing
        # as these are not useful for the user in this context
        if not blocking:
            task = AsyncTask(self.execute, args=(code_str, filename),
                             success_cb=self._on_success, error_cb=self._on_error)
            task.start()
            self._task = task
            return task
        else:
            self._task = BlockingAsyncTaskWithCallback(self.execute, args=(code_str, filename),
                                                       success_cb=self._on_success, error_cb=self._on_error,
                                                       blocking_cb=QApplication.processEvents)
            return self._task.start()
Ejemplo n.º 18
0
class PythonCodeExecution(QObject):
    """Provides the ability to execute arbitrary
    strings of Python code. It supports
    reporting progress updates in asynchronous execution
    """
    sig_exec_success = Signal(object)
    sig_exec_error = Signal(object)

    def __init__(self, editor=None):
        """Initialize the object"""
        super(PythonCodeExecution, self).__init__()
        self._editor = editor
        self._globals_ns = None
        self._task = None
        self.reset_context()

    @property
    def globals_ns(self):
        return self._globals_ns

    def abort(self):
        if self._task is not None:
            self._task.abort()

    def execute_async(self,
                      code_str,
                      line_offset,
                      filename=None,
                      blocking=False):
        """
        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 line_offset: See PythonCodeExecution.execute()
        :param filename: See PythonCodeExecution.execute()
        :param blocking: If True the call will block until the task is finished
        :returns: The created async task, only returns task if the blocking is False
        """
        # Stack is chopped on error to avoid the  AsyncTask.run->self.execute calls appearing
        # as these are not useful for the user in this context
        if not blocking:
            task = AsyncTask(self.execute,
                             args=(code_str, filename, line_offset),
                             success_cb=self._on_success,
                             error_cb=self._on_error)
            task.start()
            self._task = task
            return task
        else:
            self._task = BlockingAsyncTaskWithCallback(
                self.execute,
                args=(code_str, filename, line_offset),
                success_cb=self._on_success,
                error_cb=self._on_error,
                blocking_cb=QApplication.processEvents)
            return self._task.start()

    def execute(self, code_str, filename=None, line_offset=0):
        """Execute the given code on the calling thread
        within the provided context.

        :param code_str: A string containing code to execute
        :param filename: An optional identifier specifying the file source of the code. If None then '<string>'
        is used
        :param line_offset: The number of lines offset into the script that the code_str starts at
        :raises: Any error that the code generates
        """
        if not filename:
            filename = EMPTY_FILENAME_ID

        self.globals_ns[FILE_ATTR] = filename
        flags = get_future_import_compiler_flags(code_str)
        with AddedToSysPath([os.path.dirname(filename)]):
            executor = CodeExecution(self._editor)
            hide_warnings_in_script_editor()
            executor.execute(code_str, filename, flags, self.globals_ns,
                             line_offset)

    def reset_context(self):
        # create new context for execution
        self._globals_ns = copy.copy(builtins.globals())

    # --------------------- Callbacks -------------------------------
    def _on_success(self, task_result):
        self._reset_task()
        self.sig_exec_success.emit(task_result)

    def _on_error(self, task_error):
        self._reset_task()
        self.sig_exec_error.emit(task_error)

    # --------------------- Private -------------------------------
    def _reset_task(self):
        self._task = None
Ejemplo n.º 19
0
class PythonCodeExecution(QObject):
    """Provides the ability to execute arbitrary
    strings of Python code. It supports
    reporting progress updates in asynchronous execution
    """
    sig_exec_success = Signal(object)
    sig_exec_error = Signal(object)
    sig_exec_progress = Signal(int)

    def __init__(self, startup_code=None):
        """Initialize the object"""
        super(PythonCodeExecution, self).__init__()

        self._globals_ns = None

        self._task = None

        self.reset_context()

        # the code is not executed initially so code completion won't work
        # on variables until part is executed

    @property
    def globals_ns(self):
        return self._globals_ns

    def abort(self):
        if self._task is not None:
            self._task.abort()

    def execute_async(self, code_str, filename=None, blocking=False):
        """
        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 filename: See PythonCodeExecution.execute()
        :param blocking: If True the call will block until the task is finished
        :returns: The created async task, only returns task if the blocking is False
        """
        # Stack is chopped on error to avoid the  AsyncTask.run->self.execute calls appearing
        # as these are not useful for the user in this context
        if not blocking:
            task = AsyncTask(self.execute, args=(code_str, filename),
                             success_cb=self._on_success, error_cb=self._on_error)
            task.start()
            self._task = task
            return task
        else:
            self._task = BlockingAsyncTaskWithCallback(self.execute, args=(code_str, filename),
                                                       success_cb=self._on_success, error_cb=self._on_error,
                                                       blocking_cb=QApplication.processEvents)
            return self._task.start()

    def execute(self, code_str, filename=None):
        """Execute the given code on the calling thread
        within the provided context.

        :param code_str: A string containing code to execute
        :param filename: An optional identifier specifying the file source of the code. If None then '<string>'
        is used
        :raises: Any error that the code generates
        """
        if filename:
            self.globals_ns[FILE_ATTR] = filename
        else:
            filename = EMPTY_FILENAME_ID
        compile(code_str, filename, mode=COMPILE_MODE, dont_inherit=True)

        with AddedToSysPath([os.path.dirname(filename)]):
            sig_progress = self.sig_exec_progress
            for block in code_blocks(code_str):
                sig_progress.emit(block.lineno)
                # compile so we can set the filename
                code_obj = compile(block.code_str, filename, mode=COMPILE_MODE,
                                   dont_inherit=True)
                exec (code_obj, self.globals_ns, self.globals_ns)

    def generate_calltips(self):
        """
        Return a list of calltips for the current global scope. This is currently
        very basic and only inspects the available functions and builtins at the current scope.

        :return: A list of strings giving calltips for each global callable
        """
        calltips = []
        for name, attr in iteritems(self._globals_ns):
            if inspect.isfunction(attr) or inspect.isbuiltin(attr):
                calltips.append(name + get_function_spec(attr))

        return calltips

    def reset_context(self):
        # create new context for execution
        self._globals_ns, self._namespace = {}, {}

    # --------------------- Callbacks -------------------------------
    def _on_success(self, task_result):
        self._reset_task()
        self.sig_exec_success.emit(task_result)

    def _on_error(self, task_error):
        self._reset_task()
        self.sig_exec_error.emit(task_error)

    def _on_progress_updated(self, lineno):
        self.sig_exec_progress(lineno)

    # --------------------- Private -------------------------------
    def _reset_task(self):
        self._task = None
Ejemplo n.º 20
0
 def save_as(self, path):
     self.last_project_location = path
     task = BlockingAsyncTaskWithCallback(
         target=self._save, blocking_cb=QApplication.processEvents)
     task.start()
Ejemplo n.º 21
0
    def manual_reduce_run(self):
        """

        (simply) reduce a list of runs in same experiment in a batch

        Returns
        -------

        """
        # Files names: NeXus, (output) project, mask, calibration
        run_number = self._current_runnumber()
        if isinstance(run_number, int):
            # use specify run number (integer)
            nexus_file = get_nexus_file(run_number)
        else:
            nexus_file = str(self.ui.lineEdit_runNumber.text()).strip()

            # quit if the input is not NeXus
            if not (os.path.exists(nexus_file)
                    and nexus_file.endswith('.nxs.h5')):
                return
        # END-IF

        # Output HidraProject file
        project_file = str(self.ui.lineEdit_outputDirectory.text().strip())
        # mask file
        mask_file = str(self.ui.lineEdit_maskFile.text().strip())
        if mask_file == '':
            mask_file = None
        # calibration file
        calibration_file = str(self.ui.lineEdit_calibrationFile.text().strip())
        if calibration_file == '':
            calibration_file = None
        # vanadium file
        vanadium_file = str(self.ui.lineEdit_vanRunNumber.text().strip())
        if vanadium_file == '':
            vanadium_file = None

        # Start task
        if True:
            # single thread:
            try:
                hidra_ws = self._controller.reduce_hidra_workflow(
                    nexus_file,
                    project_file,
                    self.ui.progressBar,
                    mask=mask_file,
                    calibration=calibration_file,
                    vanadium_file=vanadium_file)
            except RuntimeError as run_err:
                pop_message(self.parent,
                            'Failed to reduce {}',
                            str(run_err),
                            message_type='error')
                return

            # Update table
            # TODO - Need to fill the table!
            sub_runs = list(hidra_ws.get_sub_runs())
            # for sub_run in sub_runs:
            #     self.ui.rawDataTable.update_reduction_state(sub_run, True)

            # Set the sub runs combo box
            self._set_sub_run_numbers(sub_runs)

        else:
            task = BlockingAsyncTaskWithCallback(
                self._controller.reduce_hidra_workflow,
                args=(nexus_file, project_file, self.ui.progressBar),
                kwargs={
                    'mask': mask_file,
                    'calibration': calibration_file
                },
                blocking_cb=QApplication.processEvents)
            # TODO - catch RuntimeError! ...
            # FIXME - check output directory
            task.start()

        return
Ejemplo n.º 22
0
 def generate_script_from_workspaces(self):
     task = BlockingAsyncTaskWithCallback(
         target=self._generate_script_from_workspaces,
         blocking_cb=QApplication.processEvents)
     task.start()
Ejemplo n.º 23
0
class PythonCodeExecution(QObject):
    """Provides the ability to execute arbitrary
    strings of Python code. It supports
    reporting progress updates in asynchronous execution
    """
    sig_exec_success = Signal(object)
    sig_exec_error = Signal(object)
    sig_exec_progress = Signal(int)

    def __init__(self, startup_code=None):
        """Initialize the object"""
        super(PythonCodeExecution, self).__init__()

        self._globals_ns = None

        self._task = None

        self.reset_context()

        # the code is not executed initially so code completion won't work
        # on variables until part is executed

    @property
    def globals_ns(self):
        return self._globals_ns

    def abort(self):
        if self._task is not None:
            self._task.abort()

    def execute_async(self, code_str, filename=None, blocking=False):
        """
        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 filename: See PythonCodeExecution.execute()
        :param blocking: If True the call will block until the task is finished
        :returns: The created async task, only returns task if the blocking is False
        """
        # Stack is chopped on error to avoid the  AsyncTask.run->self.execute calls appearing
        # as these are not useful for the user in this context
        if not blocking:
            task = AsyncTask(self.execute,
                             args=(code_str, filename),
                             success_cb=self._on_success,
                             error_cb=self._on_error)
            task.start()
            self._task = task
            return task
        else:
            self._task = BlockingAsyncTaskWithCallback(
                self.execute,
                args=(code_str, filename),
                success_cb=self._on_success,
                error_cb=self._on_error,
                blocking_cb=QApplication.processEvents)
            return self._task.start()

    def execute(self, code_str, filename=None):
        """Execute the given code on the calling thread
        within the provided context.

        :param code_str: A string containing code to execute
        :param filename: An optional identifier specifying the file source of the code. If None then '<string>'
        is used
        :raises: Any error that the code generates
        """
        if filename:
            self.globals_ns[FILE_ATTR] = filename
        else:
            filename = EMPTY_FILENAME_ID
        compile(code_str, filename, mode=COMPILE_MODE, dont_inherit=True)

        with AddedToSysPath([os.path.dirname(filename)]):
            sig_progress = self.sig_exec_progress
            for block in code_blocks(code_str):
                sig_progress.emit(block.lineno)
                # compile so we can set the filename
                code_obj = compile(block.code_str,
                                   filename,
                                   mode=COMPILE_MODE,
                                   dont_inherit=True)
                exec(code_obj, self.globals_ns, self.globals_ns)

    def reset_context(self):
        # create new context for execution
        self._globals_ns, self._namespace = {}, {}

    # --------------------- Callbacks -------------------------------
    def _on_success(self, task_result):
        self._reset_task()
        self.sig_exec_success.emit(task_result)

    def _on_error(self, task_error):
        self._reset_task()
        self.sig_exec_error.emit(task_error)

    def _on_progress_updated(self, lineno):
        self.sig_exec_progress(lineno)

    # --------------------- Private -------------------------------
    def _reset_task(self):
        self._task = None