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()
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)
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)))
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()
def test_successful_no_arg_operation_without_callback(self): def foo(): return 42 task = BlockingAsyncTaskWithCallback(foo) self.assertEqual(42, task.start())
def test_successful_no_arg_operation_without_callback(self): def foo(): return 42 task = BlockingAsyncTaskWithCallback(foo) self.assertEqual(42, task.start())
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()
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())
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())
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())
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())
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
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
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()
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
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
def save_as(self, path): self.last_project_location = path task = BlockingAsyncTaskWithCallback( target=self._save, blocking_cb=QApplication.processEvents) task.start()
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
def generate_script_from_workspaces(self): task = BlockingAsyncTaskWithCallback( target=self._generate_script_from_workspaces, blocking_cb=QApplication.processEvents) task.start()
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