Skip to content

Commit

Permalink
IPython Console: Add a way to register/unregister handlers for the ke…
Browse files Browse the repository at this point in the history
…rnel
  • Loading branch information
dalthviz committed Sep 16, 2021
1 parent 71e73d0 commit b7906b6
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 148 deletions.
89 changes: 89 additions & 0 deletions spyder/plugins/editor/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,7 @@ def register_plugin(self):
completions = self.main.get_plugin(Plugins.Completions, error=False)
outlineexplorer = self.main.get_plugin(
Plugins.OutlineExplorer, error=False)
ipyconsole = self.main.get_plugin(Plugins.IPythonConsole)
self.main.restore_scrollbar_position.connect(
self.restore_scrollbar_position)
self.main.console.sig_edit_goto_requested.connect(self.load)
Expand All @@ -1232,6 +1233,16 @@ def register_plugin(self):
if outlineexplorer:
self.set_outlineexplorer(self.main.outlineexplorer)

if ipyconsole:
self.main.ipyconsole.register_spyder_kernel_call_handler(
'cell_count', self.handle_cell_count)
self.main.ipyconsole.register_spyder_kernel_call_handler(
'current_filename', self.handle_current_filename)
self.main.ipyconsole.register_spyder_kernel_call_handler(
'get_file_code', self.handle_get_file_code)
self.main.ipyconsole.register_spyder_kernel_call_handler(
'run_cell', self.handle_run_cell)

self.add_dockwidget()
self.update_pdb_state(False, {})

Expand Down Expand Up @@ -2691,6 +2702,84 @@ def debug_command(self, command):
self.main.ipyconsole.pdb_execute_command(command)
self.main.ipyconsole.switch_to_plugin()

# ----- Handlers for the IPython Console kernels
def _get_editorstack(self):
"""
Get the current editorstack.
Raises an exception in case no editorstack is found
"""
editorstack = self.get_current_editorstack()
if editorstack is None:
raise RuntimeError('No editorstack found.')

return editorstack

def _get_editor(self, filename):
"""Get editor for filename and set it as the current editor."""
editorstack = self._get_editorstack()
if editorstack is None:
return None

if not filename:
return None

index = editorstack.has_filename(filename)
if index is None:
return None

return editorstack.data[index].editor

def handle_run_cell(self, cell_name, filename):
"""
Get cell code from cell name and file name.
"""
editorstack = self._get_editorstack()
editor = self._get_editor(filename)

if editor is None:
raise RuntimeError(
"File {} not open in the editor".format(filename))

editorstack.last_cell_call = (filename, cell_name)

# The file is open, load code from editor
return editor.get_cell_code(cell_name)

def handle_cell_count(self, filename):
"""Get number of cells in file to loop."""
editor = self._get_editor(filename)

if editor is None:
raise RuntimeError(
"File {} not open in the editor".format(filename))

# The file is open, get cell count from editor
return editor.get_cell_count()

def handle_current_filename(self, filename):
"""Get the current filename."""
return self._get_editorstack().get_current_finfo().filename

def handle_get_file_code(self, filename, save_all=True):
"""
Return the bytes that compose the file.
Bytes are returned instead of str to support non utf-8 files.
"""
editorstack = self._get_editorstack()
if save_all and self.get_conf(
'save_all_before_run', default=True, section='editor'):
editorstack.save_all(save_new_files=False)
editor = self._get_editor(filename)

if editor is None:
# Load it from file instead
text, _enc = encoding.read(filename)
return text

return editor.toPlainText()

#------ Run Python script
@Slot()
def edit_run_configurations(self):
Expand Down
101 changes: 31 additions & 70 deletions spyder/plugins/ipythonconsole/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,88 +344,49 @@ def _remove_old_stderr_files(self):
except Exception:
pass

# ---- For getting a reference to the Editor editorstack
def _get_editorstack(self):
"""Get the Editor current editorstack."""
editor = self.get_plugin(Plugins.Editor)
if editor is None:
return None

editorstack = editor.get_current_editorstack()
if editorstack is None:
raise RuntimeError('No editorstack found.')

return editorstack

def _get_editor(self, filename):
"""Get editor for filename and set it as the current editor."""
editorstack = self._get_editorstack()
if editorstack is None:
return None

if not filename:
return None

index = editorstack.has_filename(filename)
if index is None:
return None

return editorstack.data[index].editor
# --- Public API
# -------------------------------------------------------------------------

# --- Spyder-kernels runcell related functionality that uses the Editor
# ---- Spyder Kernels handlers registry functionality ---------------------
# -------------------------------------------------------------------------
def handle_run_cell(self, cell_name, filename):
def register_spyder_kernel_call_handler(self, handler_id, handler):
"""
Get cell code from cell name and file name.
"""
editorstack = self._get_editorstack()
editor = self._get_editor(filename)

if editor is None:
raise RuntimeError(
"File {} not open in the editor".format(filename))

editorstack.last_cell_call = (filename, cell_name)

# The file is open, load code from editor
return editor.get_cell_code(cell_name)

def handle_cell_count(self, filename):
"""Get number of cells in file to loop."""
editor = self._get_editor(filename)
Register a callback for it to be available for all the available
spyder kernels
if editor is None:
raise RuntimeError(
"File {} not open in the editor".format(filename))

# The file is open, get cell count from editor
return editor.get_cell_count()
Parameters
----------
handler_id : str
Handler name to be registered and that will be used to
call the respective handler from the spyder kernel.
handler : func
Callback function that will be call when the spyder-kernel instance
request the request_i identifierd.
def handle_current_filename(self, filename):
"""Get the current filename."""
return self._get_editorstack().get_current_finfo().filename
Returns
-------
None.
def handle_get_file_code(self, filename, save_all=True):
"""
Return the bytes that compose the file.
self.get_widget().register_spyder_kernel_call_handler(
handler_id, handler)

Bytes are returned instead of str to support non utf-8 files.
def unregister_spyder_kernel_call_handler(self, handler_id):
"""
editorstack = self._get_editorstack()
if save_all and self.get_conf(
'save_all_before_run', default=True, section='editor'):
editorstack.save_all(save_new_files=False)
editor = self._get_editor(filename)
Unregister/remove a handler from the spyder kernels
if editor is None:
# Load it from file instead
text, _enc = encoding.read(filename)
return text
Parameters
----------
request_id : str
Handler name that was registered and that will be removed
from the spyder kernel available handlers.
return editor.toPlainText()
Returns
-------
None.
# --- Public API
# -------------------------------------------------------------------------
"""
self.get_widget().unregister_spyder_kernel_call_handler(handler_id)

# ---- For client widgets
def get_clients(self):
Expand Down
28 changes: 3 additions & 25 deletions spyder/plugins/ipythonconsole/widgets/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ def __init__(self, parent, id_,
ask_before_restart=True,
ask_before_closing=False,
css_path=None,
configuration=None):
configuration=None,
handlers={}):
super(ClientWidget, self).__init__(parent)
SaveHistoryMixin.__init__(self, history_filename)

Expand Down Expand Up @@ -144,6 +145,7 @@ def __init__(self, parent, id_,
additional_options=additional_options,
interpreter_versions=interpreter_versions,
external_kernel=external_kernel,
handlers=handlers,
local_kernel=True,
configuration=configuration)
self.infowidget = self.container.infowidget
Expand Down Expand Up @@ -326,30 +328,6 @@ def _connect_control_signals(self):
page_control.sig_show_find_widget_requested.connect(
self.container.find_widget.show)

# ---- Spyder-kernels runcell related functionality that uses the Editor --
def handle_get_file_code(self, filename, save_all=True):
"""
Return the bytes that compose the file.
Bytes are returned instead of str to support non utf-8 files.
"""
return self.container.handle_get_file_code(
filename, save_all=save_all)

def handle_run_cell(self, cell_name, filename):
"""
Get cell code from cell name and file name.
"""
return self.container.handle_run_cell(cell_name, filename)

def handle_cell_count(self, filename):
"""Get number of cells in file to loop."""
return self.container.handle_cell_count(filename)

def handle_current_filename(self):
"""Get the current filename."""
return self.container.handle_current_filename()

# ---- Public methods -----------------------------------------------------
@property
def kernel_id(self):
Expand Down
59 changes: 39 additions & 20 deletions spyder/plugins/ipythonconsole/widgets/main_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ def __init__(
self.run_cell_filename = None
self.interrupt_action = None
self.initial_conf_options = self.get_conf_options()
self.registered_spyder_kernel_handlers = {}

# Attrs for testing
self._testing = bool(os.environ.get('testing'))
Expand Down Expand Up @@ -349,6 +350,7 @@ def __init__(
# Find/replace widget
self.find_widget = FindReplace(self)
self.find_widget.hide()
# TODO: Check shortcut for find widget
# self.register_widget_shortcuts(self.find_widget)
layout.addWidget(self.find_widget)

Expand Down Expand Up @@ -1049,7 +1051,8 @@ def _create_client_for_kernel(self, connection_file, hostname, sshkey,
reset_warning=reset_warning,
ask_before_restart=ask_before_restart,
css_path=self.css_path,
configuration=self.CONFIGURATION)
configuration=self.CONFIGURATION,
handlers=self.registered_spyder_kernel_handlers)

# Change stderr_dir if requested
if self._test_dir:
Expand Down Expand Up @@ -1113,33 +1116,48 @@ def _create_client_for_kernel(self, connection_file, hostname, sshkey,
# Register client
self.register_client(client)

# --- Spyder-kernels runcell related functionality that uses the Editor
# ---- Public API
# -------------------------------------------------------------------------
def handle_get_file_code(self, filename, save_all=True):
"""
Return the bytes that compose the file.

Bytes are returned instead of str to support non utf-8 files.
# ---- Spyder Kernels handlers registry functionality ---------------------
# -------------------------------------------------------------------------
def register_spyder_kernel_call_handler(self, handler_id, handler):
"""
return self._plugin.handle_get_file_code(
filename, save_all=save_all)
Register a callback for it to be available for all the available
spyder kernels
Parameters
----------
handler_id : str
Handler name to be registered and that will be used to
call the respective handler from the spyder kernel.
handler : func
Callback function that will be call when the spyder-kernel instance
request the request_i identifierd.
Returns
-------
None.
def handle_run_cell(self, cell_name, filename):
"""
Get cell code from cell name and file name.
self.registered_spyder_kernel_handlers[handler_id] = handler

def unregister_spyder_kernel_call_handler(self, handler_id):
"""
return self._plugin.handle_run_cell(cell_name, filename)
Unregister/remove a handler from the spyder kernels
def handle_cell_count(self, filename):
"""Get number of cells in file to loop."""
return self._plugin.handle_cell_count(filename)
Parameters
----------
request_id : str
Handler name that was registered and that will be removed
from the spyder kernel available handlers.
def handle_current_filename(self):
"""Get the current filename."""
return self._plugin.handle_current_filename()
Returns
-------
None.
# ---- Public API
# -------------------------------------------------------------------------
"""
self.registered_spyder_kernel_handlers.pop(handler_id, None)

# ---- General
# -------------------------------------------------------------------------
Expand Down Expand Up @@ -1482,7 +1500,8 @@ def create_new_client(self, give_focus=True, filename='', is_cython=False,
ask_before_restart=ask_before_restart,
ask_before_closing=ask_before_closing,
css_path=self.css_path,
configuration=self.CONFIGURATION)
configuration=self.CONFIGURATION,
handlers=self.registered_spyder_kernel_handlers)

# Change stderr_dir if requested
if self._test_dir:
Expand Down
Loading

0 comments on commit b7906b6

Please sign in to comment.