From 414941c71f26e1fd1f24a30eb72fde2e2b3135c0 2011-11-24 06:52:00 From: Matthias BUSSONNIER Date: 2011-11-24 06:52:00 Subject: [PATCH] fix @fperez suggestions --- diff --git a/IPython/frontend/qt/console/frontend_widget.py b/IPython/frontend/qt/console/frontend_widget.py index 732d343..c3c7e9e 100644 --- a/IPython/frontend/qt/console/frontend_widget.py +++ b/IPython/frontend/qt/console/frontend_widget.py @@ -138,7 +138,7 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): self._input_splitter = self._input_splitter_class(input_mode='cell') self._kernel_manager = None self._request_info = {} - self._callback_dict=dict([]) + self._callback_dict = {} # Configure the ConsoleWidget. self.tab_width = 4 @@ -313,40 +313,43 @@ class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin): cursor.movePosition(QtGui.QTextCursor.Left, n=len(text)) self._complete_with_items(cursor, rep['content']['matches']) - def _silent_exec_callback(self,expr,callback): - """ silently execute a function in the kernel and send the reply to the callback + def _silent_exec_callback(self, expr, callback): + """Silently execute `expr` in the kernel and call `callback` with reply - expr should be a valid string to be executed by the kernel. + `expr` : valid string to be executed by the kernel. + `callback` : function accepting one string as argument. - callback a function accepting one argument (str) - - the callback is called with the 'repr()' of the result as first argument. - to get the object, do 'eval()' on the passed value. + The `callback` is called with the 'repr()' of the result of `expr` as + first argument. To get the object, do 'eval()' on the passed value. """ # generate uuid, which would be used as a indication of wether or not # the unique request originate from here (can use msg id ?) local_uuid = str(uuid.uuid1()) msg_id = self.kernel_manager.shell_channel.execute('', - silent=True, - user_expressions={ local_uuid:expr, - } - ) - self._callback_dict[local_uuid]=callback + silent=True, user_expressions={ local_uuid:expr }) + self._callback_dict[local_uuid] = callback self._request_info['execute'] = self._ExecutionRequest(msg_id, 'silent_exec_callback') - def _handle_exec_callback(self,msg): - """ Called when _silent_exec_callback message comme back from the kernel. + def _handle_exec_callback(self, msg): + """Execute `callback` corresonding to `msg` reply, after ``_silent_exec_callback`` + + `msg` : raw message send by the kernel containing an `user_expressions` + and having a 'silent_exec_callback' kind. - Strip the message comming back from the kernel and send it to the - corresponding callback function. + This fonction will look for a `callback` associated with the + corresponding message id. Association has been made by + ``_silent_exec_callback``. `callback`is then called with the `repr()` + of the value of corresponding `user_expressions` as argument. + `callback` is then removed from the known list so that any message + coming again with the same id won't trigger it. """ - cnt=msg['content'] - ue=cnt['user_expressions'] + + cnt = msg['content'] + ue = cnt['user_expressions'] for i in ue.keys(): - if i in self._callback_dict.keys(): - f= self._callback_dict[i] - f(ue[i]) + if i in self._callback_dict: + self._callback_dict[i](ue[i]) self._callback_dict.pop(i) def _handle_execute_reply(self, msg): diff --git a/IPython/frontend/qt/console/mainwindow.py b/IPython/frontend/qt/console/mainwindow.py index ff8224b..aaa4c46 100644 --- a/IPython/frontend/qt/console/mainwindow.py +++ b/IPython/frontend/qt/console/mainwindow.py @@ -544,32 +544,54 @@ class MainWindow(QtGui.QMainWindow): self.kernel_menu.addSeparator() + def _make_dynamic_magic(self,magic): + """Return a function `fun` that will execute `magic` on active frontend. + + `magic` : valid python string + + return `fun`, function with no parameters + + `fun` execute `magic` an active frontend at the moment it is triggerd, + not the active frontend at the moment it has been created. + + This function is mostly used to create the "All Magics..." Menu at run time. + """ + # need to level nested function to be sure to past magic + # on active frontend **at run time**. + def inner_dynamic_magic(): + self.active_frontend.execute(magic) + inner_dynamic_magic.__name__ = "dynamics_magic_s" + return inner_dynamic_magic + + def populate_all_magic_menu(self, listofmagic=None): + """Clean "All Magics..." menu and repopulate it with `listofmagic` + + `listofmagic` : string, repr() of a list of strings. + + `listofmagic`is a repr() of list because it is fed with the result of + a 'user_expression' + """ + alm_magic_menu = self.all_magic_menu + alm_magic_menu.clear() + + # list of protected magic that don't like to be called without argument + # append '?' to the end to print the docstring when called from the menu + protected_magic = set(["more","less","load_ext","pycat","loadpy","save"]) + + for magic in eval(listofmagic): + if magic in protected_magic: + pmagic = '%s%s%s'%('%',magic,'?') + else: + pmagic = '%s%s'%('%',magic) + xaction = QtGui.QAction(pmagic, + self, + triggered=self._make_dynamic_magic(pmagic) + ) + alm_magic_menu.addAction(xaction) + def update_all_magic_menu(self): # first define a callback which will get the list of all magic and put it in the menu. - def populate_all_magic_menu(val=None): - alm_magic_menu = self.all_magic_menu - alm_magic_menu.clear() - def make_dynamic_magic(i): - def inner_dynamic_magic(): - self.active_frontend.execute(i) - inner_dynamic_magic.__name__ = "dynamics_magic_s" - return inner_dynamic_magic - - # list of protected magic that don't like to be called without argument - # append '?' to the end to print the docstring when called from the menu - protected_magic= ["more","less","load_ext","pycat","loadpy","save"] - - for magic in eval(val): - if magic in protected_magic: - pmagic = '%s%s%s'%('%',magic,'?') - else: - pmagic = '%s%s'%('%',magic) - xaction = QtGui.QAction(pmagic, - self, - triggered=make_dynamic_magic(pmagic) - ) - alm_magic_menu.addAction(xaction) - self.active_frontend._silent_exec_callback('get_ipython().lsmagic()',populate_all_magic_menu) + self.active_frontend._silent_exec_callback('get_ipython().lsmagic()',self.populate_all_magic_menu) def init_magic_menu(self): self.magic_menu = self.menuBar().addMenu("&Magic") @@ -578,8 +600,7 @@ class MainWindow(QtGui.QMainWindow): # this action should not appear as it will be cleard when menu # will be updated at first kernel response. self.pop = QtGui.QAction("&Update All Magic Menu ", - self, - triggered=self.update_all_magic_menu) + self, triggered=self.update_all_magic_menu) self.add_menu_action(self.all_magic_menu, self.pop) self.reset_action = QtGui.QAction("&Reset", diff --git a/IPython/frontend/qt/console/qtconsoleapp.py b/IPython/frontend/qt/console/qtconsoleapp.py index 95b60a8..21594e8 100644 --- a/IPython/frontend/qt/console/qtconsoleapp.py +++ b/IPython/frontend/qt/console/qtconsoleapp.py @@ -452,7 +452,7 @@ 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 + # we need to populate the 'Magic Menu' once the kernel has answer at least once self.kernel_manager.shell_channel.first_reply.connect(self.window.pop.trigger) self.window.setWindowTitle('Python' if self.pure else 'IPython')