diff --git a/IPython/frontend/qt/console/frontend_widget.py b/IPython/frontend/qt/console/frontend_widget.py index 1f62432..15eff37 100644 --- a/IPython/frontend/qt/console/frontend_widget.py +++ b/IPython/frontend/qt/console/frontend_widget.py @@ -138,6 +138,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): self._input_splitter = self._input_splitter_class(input_mode='cell') self._kernel_manager = None self._request_info = {} + self._request_info['execute'] = {}; self._callback_dict = {} # Configure the ConsoleWidget. @@ -199,7 +200,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): See parent class :meth:`execute` docstring for full details. """ msg_id = self.kernel_manager.shell_channel.execute(source, hidden) - self._request_info['execute'] = self._ExecutionRequest(msg_id, 'user') + self._request_info['execute'][msg_id] = self._ExecutionRequest(msg_id, 'user') self._hidden = hidden if not hidden: self.executing.emit(source) @@ -343,7 +344,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): msg_id = self.kernel_manager.shell_channel.execute('', silent=True, user_expressions={ local_uuid:expr }) self._callback_dict[local_uuid] = callback - self._request_info['execute'] = self._ExecutionRequest(msg_id, 'silent_exec_callback') + self._request_info['execute'][msg_id] = self._ExecutionRequest(msg_id, 'silent_exec_callback') def _handle_exec_callback(self, msg): """Execute `callback` corresonding to `msg` reply, after ``_silent_exec_callback`` @@ -373,12 +374,12 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): """ Handles replies for code execution. """ self.log.debug("execute: %s", msg.get('content', '')) - info = self._request_info.get('execute') + msg_id = msg['parent_header']['msg_id'] + info = self._request_info['execute'].get(msg_id) # unset reading flag, because if execute finished, raw_input can't # still be pending. self._reading = False - if info and info.id == msg['parent_header']['msg_id'] and \ - info.kind == 'user' and not self._hidden: + if info and info.kind == 'user' and not self._hidden: # Make sure that all output from the SUB channel has been processed # before writing a new prompt. self.kernel_manager.sub_channel.flush() @@ -400,9 +401,10 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): self._show_interpreter_prompt_for_reply(msg) self.executed.emit(msg) - elif info and info.id == msg['parent_header']['msg_id'] and \ - info.kind == 'silent_exec_callback' and not self._hidden: + self._request_info['execute'].pop(msg_id) + elif info and info.kind == 'silent_exec_callback' and not self._hidden: self._handle_exec_callback(msg) + self._request_info['execute'].pop(msg_id) else: super(FrontendWidget, self)._handle_execute_reply(msg) @@ -559,7 +561,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): """ if self._executing: self._executing = False - self._request_info['execute'] = None + self._request_info['execute'] = {} self._reading = False self._highlighter.highlighting_on = False diff --git a/IPython/frontend/qt/console/history_console_widget.py b/IPython/frontend/qt/console/history_console_widget.py index 944f9bd..5c7657d 100644 --- a/IPython/frontend/qt/console/history_console_widget.py +++ b/IPython/frontend/qt/console/history_console_widget.py @@ -211,14 +211,14 @@ class HistoryConsoleWidget(ConsoleWidget): 'hlen':'len(get_ipython().history_manager.input_hist_raw)', } ) - self._request_info['execute'] = self._ExecutionRequest(msg_id, 'save_magic') + self._request_info['execute'][msg_id] = self._ExecutionRequest(msg_id, 'save_magic') def _handle_execute_reply(self, msg): """ Handles replies for code execution, here only session history length """ - info = self._request_info.get('execute') - if info and info.id == msg['parent_header']['msg_id'] and \ - info.kind == 'save_magic' and not self._hidden: + msg_id = msg['parent_header']['msg_id'] + info = self._request_info.get['execute'].pop(msg_id,None) + if info and info.kind == 'save_magic' and not self._hidden: content = msg['content'] status = content['status'] if status == 'ok': diff --git a/IPython/frontend/qt/console/ipython_widget.py b/IPython/frontend/qt/console/ipython_widget.py index ae183ab..5147139 100644 --- a/IPython/frontend/qt/console/ipython_widget.py +++ b/IPython/frontend/qt/console/ipython_widget.py @@ -165,13 +165,14 @@ class IPythonWidget(FrontendWidget): def _handle_execute_reply(self, msg): """ Reimplemented to support prompt requests. """ - info = self._request_info.get('execute') - if info and info.id == msg['parent_header']['msg_id']: - if info.kind == 'prompt': - number = msg['content']['execution_count'] + 1 - self._show_interpreter_prompt(number) - else: - super(IPythonWidget, self)._handle_execute_reply(msg) + msg_id = msg['parent_header'].get('msg_id') + info = self._request_info['execute'].get(msg_id) + if info and info.kind == 'prompt': + number = msg['content']['execution_count'] + 1 + self._show_interpreter_prompt(number) + self._request_info['execute'].pop(msg_id) + else: + super(IPythonWidget, self)._handle_execute_reply(msg) def _handle_history_reply(self, msg): """ Implemented to handle history tail replies, which are only supported @@ -358,7 +359,7 @@ class IPythonWidget(FrontendWidget): if number is None: msg_id = self.kernel_manager.shell_channel.execute('', silent=True) info = self._ExecutionRequest(msg_id, 'prompt') - self._request_info['execute'] = info + self._request_info['execute'][msg_id] = info return # Show a new prompt and save information about it so that it can be diff --git a/IPython/frontend/qt/console/mainwindow.py b/IPython/frontend/qt/console/mainwindow.py index cd0a721..7cf24a7 100644 --- a/IPython/frontend/qt/console/mainwindow.py +++ b/IPython/frontend/qt/console/mainwindow.py @@ -626,17 +626,12 @@ class MainWindow(QtGui.QMainWindow): # is updated at first kernel response. Though, it is necessary when # connecting through X-forwarding, as in this case, the menu is not # auto updated, SO DO NOT DELETE. - - ######################################################################## - ## TEMPORARILY DISABLED - see #1057 for details. Uncomment this - ## section when a proper fix is found - - ## self.pop = QtGui.QAction("&Update All Magic Menu ", - ## self, triggered=self.update_all_magic_menu) - ## self.add_menu_action(self.all_magic_menu, self.pop) - - ## END TEMPORARY FIX - ######################################################################## + self.pop = QtGui.QAction("&Update All Magic Menu ", + self, triggered=self.update_all_magic_menu) + self.add_menu_action(self.all_magic_menu, self.pop) + # we need to populate the 'Magic Menu' once the kernel has answer at + # least once let's do it immedialy, but it's assured to works + self.pop.trigger() self.reset_action = QtGui.QAction("&Reset", self, @@ -674,49 +669,6 @@ class MainWindow(QtGui.QMainWindow): triggered=self.whos_magic_active_frontend) self.add_menu_action(self.magic_menu, self.whos_action) - - ######################################################################## - ## TEMPORARILY ADDED BACK - see #1057 for details. The magic menu is - ## supposed to be dynamic, but the mechanism merged in #1057 has a race - ## condition that locks up the console very often. We're putting back - ## the static list temporarily/ Remove this code when a proper fix is - ## found. - - # allmagics submenu. - - # for now this is just a copy and paste, but we should get this - # dynamically - magiclist = ["%alias", "%autocall", "%automagic", "%bookmark", "%cd", - "%clear", "%colors", "%debug", "%dhist", "%dirs", "%doctest_mode", - "%ed", "%edit", "%env", "%gui", "%guiref", "%hist", "%history", - "%install_default_config", "%install_profiles", "%less", "%load_ext", - "%loadpy", "%logoff", "%logon", "%logstart", "%logstate", "%logstop", - "%lsmagic", "%macro", "%magic", "%man", "%more", "%notebook", "%page", - "%pastebin", "%pdb", "%pdef", "%pdoc", "%pfile", "%pinfo", "%pinfo2", - "%popd", "%pprint", "%precision", "%profile", "%prun", "%psearch", - "%psource", "%pushd", "%pwd", "%pycat", "%pylab", "%quickref", - "%recall", "%rehashx", "%reload_ext", "%rep", "%rerun", "%reset", - "%reset_selective", "%run", "%save", "%sc", "%sx", "%tb", "%time", - "%timeit", "%unalias", "%unload_ext", "%who", "%who_ls", "%whos", - "%xdel", "%xmode"] - - def make_dynamic_magic(i): - def inner_dynamic_magic(): - self.active_frontend.execute(i) - inner_dynamic_magic.__name__ = "dynamics_magic_%s" % i - return inner_dynamic_magic - - for magic in magiclist: - xaction = QtGui.QAction(magic, - self, - triggered=make_dynamic_magic(magic) - ) - self.all_magic_menu.addAction(xaction) - - ## END TEMPORARY FIX - ######################################################################## - - def init_window_menu(self): self.window_menu = self.menuBar().addMenu("&Window") if sys.platform == 'darwin': diff --git a/IPython/frontend/qt/console/qtconsoleapp.py b/IPython/frontend/qt/console/qtconsoleapp.py index 727cb93..bd4cec2 100644 --- a/IPython/frontend/qt/console/qtconsoleapp.py +++ b/IPython/frontend/qt/console/qtconsoleapp.py @@ -452,16 +452,6 @@ class IPythonQtConsoleApp(BaseIPythonApplication): self.window.add_tab_with_frontend(self.widget) self.window.init_menu_bar() - # we need to populate the 'Magic Menu' once the kernel has answer at - # least once - - ######################################################################## - ## TEMPORARILY DISABLED - see #1057 for details, uncomment the next - ## line when a proper fix is found: - ## self.kernel_manager.shell_channel.first_reply.connect(self.window.pop.trigger) - ## END TEMPORARY FIX - ######################################################################## - self.window.setWindowTitle('Python' if self.pure else 'IPython') def init_colors(self):