From b720fda1211da731091a96b416b50a40f5fcc1c3 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Fri, 12 Aug 2022 10:49:28 -0500 Subject: [PATCH 1/9] Files: Rename signal for clarity and add icon to context menu action --- spyder/plugins/explorer/plugin.py | 8 ++++---- spyder/plugins/explorer/widgets/explorer.py | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/spyder/plugins/explorer/plugin.py b/spyder/plugins/explorer/plugin.py index 38429d3b932..500c251ca7e 100644 --- a/spyder/plugins/explorer/plugin.py +++ b/spyder/plugins/explorer/plugin.py @@ -122,7 +122,7 @@ class Explorer(SpyderDockablePlugin): New path for renamed folder. """ - sig_interpreter_opened = Signal(str) + sig_open_interpreter_requested = Signal(str) """ This signal is emitted to request opening an interpreter with the given path as working directory. @@ -177,7 +177,7 @@ def on_initialize(self): widget.sig_file_created.connect(self.sig_file_created) widget.sig_open_file_requested.connect(self.sig_open_file_requested) widget.sig_open_interpreter_requested.connect( - self.sig_interpreter_opened) + self.sig_open_interpreter_requested) widget.sig_module_created.connect(self.sig_module_created) widget.sig_removed.connect(self.sig_file_removed) widget.sig_renamed.connect(self.sig_file_renamed) @@ -207,7 +207,7 @@ def on_preferences_available(self): @on_plugin_available(plugin=Plugins.IPythonConsole) def on_ipython_console_available(self): ipyconsole = self.get_plugin(Plugins.IPythonConsole) - self.sig_interpreter_opened.connect( + self.sig_open_interpreter_requested.connect( ipyconsole.create_client_from_path) self.sig_run_requested.connect( lambda fname: @@ -240,7 +240,7 @@ def on_preferences_teardown(self): @on_plugin_teardown(plugin=Plugins.IPythonConsole) def on_ipython_console_teardown(self): ipyconsole = self.get_plugin(Plugins.IPythonConsole) - self.sig_interpreter_opened.disconnect( + self.sig_open_interpreter_requested.disconnect( ipyconsole.create_client_from_path) self.sig_run_requested.disconnect() diff --git a/spyder/plugins/explorer/widgets/explorer.py b/spyder/plugins/explorer/widgets/explorer.py index cde17b99ee5..3a7aa06f2da 100644 --- a/spyder/plugins/explorer/widgets/explorer.py +++ b/spyder/plugins/explorer/widgets/explorer.py @@ -471,6 +471,7 @@ def setup(self): self.open_interpreter_action = self.create_action( DirViewActions.OpenInterpreter, text=_("Open IPython console here"), + icon=self.create_icon('ipython_console'), triggered=lambda: self.open_interpreter(), ) From 56fe9136dfeebc9d98b68afa37c8cc68331b70fe Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Fri, 12 Aug 2022 10:55:57 -0500 Subject: [PATCH 2/9] IPython console: Make create_client_from_path correctly set the cwd --- .../plugins/ipythonconsole/widgets/client.py | 18 +++++++++++------- .../ipythonconsole/widgets/main_widget.py | 10 ++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/spyder/plugins/ipythonconsole/widgets/client.py b/spyder/plugins/ipythonconsole/widgets/client.py index 03628e29bd7..2c0afea6273 100644 --- a/spyder/plugins/ipythonconsole/widgets/client.py +++ b/spyder/plugins/ipythonconsole/widgets/client.py @@ -107,7 +107,8 @@ def __init__(self, parent, id_, handlers={}, stderr_obj=None, stdout_obj=None, - fault_obj=None): + fault_obj=None, + initial_cwd=None): super(ClientWidget, self).__init__(parent) SaveHistoryMixin.__init__(self, history_filename) @@ -123,6 +124,7 @@ def __init__(self, parent, id_, self.reset_warning = reset_warning self.ask_before_restart = ask_before_restart self.ask_before_closing = ask_before_closing + self.initial_cwd = initial_cwd # --- Other attrs self.context_menu_actions = context_menu_actions @@ -220,8 +222,8 @@ def _when_prompt_is_ready(self): # To show if special console is valid self._check_special_console_error() - # Set the initial current working directory - self._set_initial_cwd() + # Set the initial current working directory in the kernel + self._set_initial_cwd_in_kernel() self.shellwidget.sig_prompt_ready.disconnect( self._when_prompt_is_ready) @@ -351,9 +353,9 @@ def _connect_control_signals(self): page_control.sig_show_find_widget_requested.connect( self.container.find_widget.show) - def _set_initial_cwd(self): - """Set initial cwd according to preferences.""" - logger.debug("Setting initial working directory") + def _set_initial_cwd_in_kernel(self): + """Set the initial cwd in the kernel.""" + logger.debug("Setting initial working directory in the kernel") cwd_path = get_home_dir() project_path = self.container.get_active_project_path() @@ -377,7 +379,9 @@ def _set_initial_cwd(self): ) else: # For new clients - if self.get_conf( + if self.initial_cwd is not None: + cwd_path = self.initial_cwd + elif self.get_conf( 'console/use_project_or_home_directory', section='workingdir' ): diff --git a/spyder/plugins/ipythonconsole/widgets/main_widget.py b/spyder/plugins/ipythonconsole/widgets/main_widget.py index e7c424947b3..08355a61f59 100644 --- a/spyder/plugins/ipythonconsole/widgets/main_widget.py +++ b/spyder/plugins/ipythonconsole/widgets/main_widget.py @@ -1412,7 +1412,7 @@ def get_current_shellwidget(self): @Slot(bool, str, bool) def create_new_client(self, give_focus=True, filename='', is_cython=False, is_pylab=False, is_sympy=False, given_name=None, - cache=True): + cache=True, initial_cwd=None): """Create a new client""" self.master_clients += 1 client_id = dict(int_id=str(self.master_clients), @@ -1449,7 +1449,8 @@ def create_new_client(self, give_focus=True, filename='', is_cython=False, handlers=self.registered_spyder_kernel_handlers, stderr_obj=stderr_obj, stdout_obj=stdout_obj, - fault_obj=fault_obj) + fault_obj=fault_obj, + initial_cwd=initial_cwd) self.add_tab( client, name=client.get_name(), filename=filename, @@ -1791,13 +1792,10 @@ def connect_client_to_kernel(self, client, km, kc): # type is Qt.DirectConnection. self._shellwidget_started(client) - @Slot(str) def create_client_from_path(self, path): """Create a client with its cwd pointing to path.""" - self.create_new_client() - sw = self.get_current_shellwidget() - sw.set_cwd(path) + self.create_new_client(initial_cwd=path) def create_client_for_file(self, filename, is_cython=False): """Create a client to execute code related to a file.""" From 665b7adb212dd84a57de571535b3165b34ec208f Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 13 Aug 2022 12:54:47 -0500 Subject: [PATCH 3/9] IPython console: Rename _set_working_directory to save_working_directory Also restore previous set_working_directory method in its main widget. That method really sets the cwd when called and it's declared as part of the console's API. --- spyder/plugins/ipythonconsole/plugin.py | 23 ++++++++++++------- .../tests/test_ipythonconsole.py | 2 +- .../ipythonconsole/widgets/main_widget.py | 16 +++++++++---- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/spyder/plugins/ipythonconsole/plugin.py b/spyder/plugins/ipythonconsole/plugin.py index c20bd16cb1d..5f09848bbf5 100644 --- a/spyder/plugins/ipythonconsole/plugin.py +++ b/spyder/plugins/ipythonconsole/plugin.py @@ -332,7 +332,7 @@ def on_projects_available(self): def on_working_directory_available(self): working_directory = self.get_plugin(Plugins.WorkingDirectory) working_directory.sig_current_directory_changed.connect( - self._set_working_directory) + self.save_working_directory) @on_plugin_teardown(plugin=Plugins.Preferences) def on_preferences_teardown(self): @@ -379,7 +379,7 @@ def on_projects_teardown(self): def on_working_directory_teardown(self): working_directory = self.get_plugin(Plugins.WorkingDirectory) working_directory.sig_current_directory_changed.disconnect( - self._set_working_directory) + self.save_working_directory) def update_font(self): """Update font from Preferences""" @@ -431,11 +431,6 @@ def _remove_old_std_files(self): except Exception: pass - @Slot(str) - def _set_working_directory(self, new_dir): - """Set current working directory on the main widget.""" - self.get_widget().set_working_directory(new_dir) - # ---- Public API # ------------------------------------------------------------------------- @@ -812,7 +807,7 @@ def set_current_client_working_directory(self, directory): def set_working_directory(self, dirname): """ - Set current working directory for the `workingdirectory` and `explorer` + Set current working directory in the Working Directory and Files plugins. Parameters @@ -826,6 +821,18 @@ def set_working_directory(self, dirname): """ self.get_widget().set_working_directory(dirname) + @Slot(str) + def save_working_directory(self, dirname): + """ + Save current working directory on the main widget to start new clients. + + Parameters + ---------- + new_dir: str + Path to the new current working directory. + """ + self.get_widget().save_working_directory(dirname) + def update_working_directory(self): """Update working directory to console current working directory.""" self.get_widget().update_working_directory() diff --git a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py index c353c7bd867..c48857f390c 100644 --- a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py +++ b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py @@ -2282,7 +2282,7 @@ def get_cwd_of_new_client(): # Simulate a specific directory cwd_dir = str(tmpdir.mkdir('ipyconsole_cwd_test')) - ipyconsole.get_widget().set_working_directory(cwd_dir) + ipyconsole.get_widget().save_working_directory(cwd_dir) # Get cwd of new client and assert is the expected one assert get_cwd_of_new_client() == cwd_dir diff --git a/spyder/plugins/ipythonconsole/widgets/main_widget.py b/spyder/plugins/ipythonconsole/widgets/main_widget.py index 08355a61f59..416810e7e92 100644 --- a/spyder/plugins/ipythonconsole/widgets/main_widget.py +++ b/spyder/plugins/ipythonconsole/widgets/main_widget.py @@ -2370,15 +2370,23 @@ def run_script(self, filename, wdir, args, debug, post_mortem, ) # ---- For working directory and path management - def set_working_directory(self, new_dir): + def set_working_directory(self, dirname): """ - Set current working directory when changed by the Working Directory + Set current working directory in the Working Directory and Files + plugins. + """ + if osp.isdir(dirname): + self.sig_current_directory_changed.emit(dirname) + + def save_working_directory(self, dirname): + """ + Save current working directory when changed by the Working Directory plugin. """ - self._current_working_directory = new_dir + self._current_working_directory = dirname def get_working_directory(self): - """Get current working directory.""" + """Get saved value of current working directory.""" return self._current_working_directory def set_current_client_working_directory(self, directory): From c38ecdba4b1a1443b300878581222230816e241d Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 13 Aug 2022 12:59:35 -0500 Subject: [PATCH 4/9] IPython console: Update cwd in other panes after initially setting it in the kernel --- spyder/plugins/ipythonconsole/widgets/client.py | 7 ++++++- spyder/plugins/ipythonconsole/widgets/shell.py | 4 +++- spyder/plugins/workingdirectory/plugin.py | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/spyder/plugins/ipythonconsole/widgets/client.py b/spyder/plugins/ipythonconsole/widgets/client.py index 2c0afea6273..b48ab7d8623 100644 --- a/spyder/plugins/ipythonconsole/widgets/client.py +++ b/spyder/plugins/ipythonconsole/widgets/client.py @@ -358,6 +358,7 @@ def _set_initial_cwd_in_kernel(self): logger.debug("Setting initial working directory in the kernel") cwd_path = get_home_dir() project_path = self.container.get_active_project_path() + update_in_spyder = True # This is for the first client if self.id_['int_id'] == '1': @@ -368,6 +369,7 @@ def _set_initial_cwd_in_kernel(self): cwd_path = get_home_dir() if project_path is not None: cwd_path = project_path + update_in_spyder = False elif self.get_conf( 'startup/use_fixed_directory', section='workingdir' @@ -390,6 +392,7 @@ def _set_initial_cwd_in_kernel(self): cwd_path = project_path elif self.get_conf('console/use_cwd', section='workingdir'): cwd_path = self.container.get_working_directory() + update_in_spyder = False elif self.get_conf( 'console/use_fixed_directory', section='workingdir' @@ -401,7 +404,9 @@ def _set_initial_cwd_in_kernel(self): ) if osp.isdir(cwd_path): - self.shellwidget.set_cwd(cwd_path) + self.shellwidget.set_cwd( + cwd_path, update_in_spyder=update_in_spyder + ) # ----- Public API -------------------------------------------------------- @property diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py index 469f827b168..71638f3e904 100644 --- a/spyder/plugins/ipythonconsole/widgets/shell.py +++ b/spyder/plugins/ipythonconsole/widgets/shell.py @@ -296,7 +296,7 @@ def check_spyder_kernel(self): else: self.silent_exec_method(code) - def set_cwd(self, dirname): + def set_cwd(self, dirname, update_in_spyder=False): """Set shell current working directory.""" if os.name == 'nt': # Use normpath instead of replacing '\' with '\\' @@ -306,6 +306,8 @@ def set_cwd(self, dirname): if self.ipyclient.hostname is None: self.call_kernel(interrupt=self.is_debugging()).set_cwd(dirname) self._cwd = dirname + if update_in_spyder: + self.sig_working_directory_changed.emit(self._cwd) def update_cwd(self): """Update current working directory in the kernel.""" diff --git a/spyder/plugins/workingdirectory/plugin.py b/spyder/plugins/workingdirectory/plugin.py index 0b8bc4f9448..3b1c6683200 100644 --- a/spyder/plugins/workingdirectory/plugin.py +++ b/spyder/plugins/workingdirectory/plugin.py @@ -188,6 +188,8 @@ def chdir(self, directory, sender_plugin=None): if sender_plugin is not None: container = self.get_container() container.chdir(directory, emit=False) + if ipyconsole: + ipyconsole.save_working_directory(directory) self.save_history() From 42e12cfa397af123c65e1f6186797673de6c09dc Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 13 Aug 2022 13:34:53 -0500 Subject: [PATCH 5/9] IPython console: Rename some methods for clarity and improve docstrings --- .../plugins/ipythonconsole/widgets/main_widget.py | 4 ++-- spyder/plugins/ipythonconsole/widgets/shell.py | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/spyder/plugins/ipythonconsole/widgets/main_widget.py b/spyder/plugins/ipythonconsole/widgets/main_widget.py index 416810e7e92..6fafcb1be7c 100644 --- a/spyder/plugins/ipythonconsole/widgets/main_widget.py +++ b/spyder/plugins/ipythonconsole/widgets/main_widget.py @@ -1859,7 +1859,7 @@ def register_client(self, client, give_focus=True): # Connect to working directory shellwidget.sig_working_directory_changed.connect( - self.working_directory_changed) + self.on_working_directory_changed) # Connect client execution state to be reflected in the interface client.sig_execution_state_changed.connect(self.update_actions) @@ -2395,7 +2395,7 @@ def set_current_client_working_directory(self, directory): if shellwidget is not None: shellwidget.set_cwd(directory) - def working_directory_changed(self, dirname): + def on_working_directory_changed(self, dirname): """ Notify that the working directory was changed in the current console to other plugins. diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py index 71638f3e904..ae1ee4a032b 100644 --- a/spyder/plugins/ipythonconsole/widgets/shell.py +++ b/spyder/plugins/ipythonconsole/widgets/shell.py @@ -310,13 +310,19 @@ def set_cwd(self, dirname, update_in_spyder=False): self.sig_working_directory_changed.emit(self._cwd) def update_cwd(self): - """Update current working directory in the kernel.""" + """ + Update working directory in Spyder after getting its value from the + kernel. + """ if self.kernel_client is None: return - self.call_kernel(callback=self.remote_set_cwd).get_cwd() + self.call_kernel(callback=self.on_getting_cwd).get_cwd() - def remote_set_cwd(self, cwd): - """Get current working directory from kernel.""" + def on_getting_cwd(self, cwd): + """ + If necessary, notify that the working directory was changed to other + plugins. + """ if cwd != self._cwd: self._cwd = cwd self.sig_working_directory_changed.emit(self._cwd) From 891a8031ffee8937ff8000ffc08855f6f52fcd79 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 13 Aug 2022 14:07:32 -0500 Subject: [PATCH 6/9] IPython console: Update cwd in other plugins after switching consoles --- .../plugins/ipythonconsole/widgets/main_widget.py | 10 +++++++++- spyder/plugins/ipythonconsole/widgets/shell.py | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/spyder/plugins/ipythonconsole/widgets/main_widget.py b/spyder/plugins/ipythonconsole/widgets/main_widget.py index 6fafcb1be7c..2a91fa2f64a 100644 --- a/spyder/plugins/ipythonconsole/widgets/main_widget.py +++ b/spyder/plugins/ipythonconsole/widgets/main_widget.py @@ -1164,6 +1164,14 @@ def refresh_container(self, give_focus=False): sw.is_waiting_pdb_input(), sw.get_pdb_last_step()) self.sig_shellwidget_changed.emit(sw) + # This is necessary to sync the current client cwd with the working + # directory displayed by other plugins in Spyder (e.g. Files). + # NOTE: Instead of emitting sig_current_directory_changed directly, + # we call on_working_directory_changed to validate that the cwd + # exists (this couldn't be the case for remote kernels). + if sw.get_cwd() != self.get_working_directory(): + self.on_working_directory_changed(sw.get_cwd()) + self.update_tabs_text() self.update_actions() @@ -2400,7 +2408,7 @@ def on_working_directory_changed(self, dirname): Notify that the working directory was changed in the current console to other plugins. """ - if osp.isdir(dirname): + if dirname and osp.isdir(dirname): self.sig_current_directory_changed.emit(dirname) def update_working_directory(self): diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py index ae1ee4a032b..c14a22c5117 100644 --- a/spyder/plugins/ipythonconsole/widgets/shell.py +++ b/spyder/plugins/ipythonconsole/widgets/shell.py @@ -309,6 +309,19 @@ def set_cwd(self, dirname, update_in_spyder=False): if update_in_spyder: self.sig_working_directory_changed.emit(self._cwd) + def get_cwd(self): + """ + Get current working directory. + + Notes + ----- + * This doesn't ask the kernel for its working directory. Instead, it + returns the last value of it saved here. + * We do it for performance reasons because we call this method when + switching consoles to update the Working Directory toolbar. + """ + return self._cwd + def update_cwd(self): """ Update working directory in Spyder after getting its value from the From a79910e9d0c3b6b4a2f3ecf7cfcb4cc222fcd2f5 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sat, 13 Aug 2022 21:51:50 -0500 Subject: [PATCH 7/9] Testing: Check that console cwd is in sync with other plugins --- spyder/app/tests/test_mainwindow.py | 89 +++++++++++++++++++++++++++++ spyder/plugins/explorer/plugin.py | 4 ++ 2 files changed, 93 insertions(+) diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py index 06cbea0a616..4e70ce83981 100644 --- a/spyder/app/tests/test_mainwindow.py +++ b/spyder/app/tests/test_mainwindow.py @@ -5376,5 +5376,94 @@ def test_out_runfile_runcell(main_window, qtbot): assert not "]: " + str(num) in control.toPlainText() +@pytest.mark.slow +def test_cwd_is_synced_when_switching_consoles(main_window, qtbot, tmpdir): + """ + Test that the current working directory is synced between the IPython + console and other plugins when switching consoles. + """ + ipyconsole = main_window.ipyconsole + workdir = main_window.workingdirectory + files = main_window.get_plugin(Plugins.Explorer) + + # Wait for the window to be fully up + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + + # Create two new clients and change their cwd's + for i in range(2): + sync_dir = tmpdir.mkdir(f'test_sync_{i}') + ipyconsole.create_new_client() + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + with qtbot.waitSignal(shell.executed): + shell.execute(f'cd {str(sync_dir)}') + + # Switch between clients and check that the cwd is in sync with other + # plugins + for i in range(3): + ipyconsole.get_widget().tabwidget.setCurrentIndex(i) + shell_cwd = ipyconsole.get_current_shellwidget().get_cwd() + assert shell_cwd == workdir.get_workdir() == files.get_current_folder() + + +@pytest.mark.slow +def test_console_initial_cwd_is_synced(main_window, qtbot, tmpdir): + """ + Test that the initial current working directory for new consoles is synced + with other plugins. + """ + ipyconsole = main_window.ipyconsole + workdir = main_window.workingdirectory + files = main_window.get_plugin(Plugins.Explorer) + + # Wait for the window to be fully up + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + + # Open console from Files in tmpdir + files.get_widget().treewidget.open_interpreter([str(tmpdir)]) + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + assert shell.get_cwd() == str(tmpdir) == workdir.get_workdir() == \ + files.get_current_folder() + + # Check that a new client has the same initial cwd as the current one + ipyconsole.create_new_client() + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + qtbot.wait(500) + assert shell.get_cwd() == str(tmpdir) == workdir.get_workdir() == \ + files.get_current_folder() + + # Check that new clients with a fixed directory + ipyconsole.set_conf('console/use_cwd', False, section='workingdir') + ipyconsole.set_conf( + 'console/use_fixed_directory', + True, + section='workingdir' + ) + + fixed_dir = str(tmpdir.mkdir('fixed_dir')) + ipyconsole.set_conf( + 'console/fixed_directory', + fixed_dir, + section='workingdir' + ) + + ipyconsole.create_new_client() + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + qtbot.wait(500) + assert shell.get_cwd() == fixed_dir == workdir.get_workdir() == \ + files.get_current_folder() + + if __name__ == "__main__": pytest.main() diff --git a/spyder/plugins/explorer/plugin.py b/spyder/plugins/explorer/plugin.py index 500c251ca7e..0070d4b78b0 100644 --- a/spyder/plugins/explorer/plugin.py +++ b/spyder/plugins/explorer/plugin.py @@ -260,6 +260,10 @@ def chdir(self, directory, emit=True): """ self.get_widget().chdir(directory, emit=emit) + def get_current_folder(self): + """Get folder displayed at the moment.""" + return self.get_widget().get_current_folder() + def refresh(self, new_path=None, force_current=True): """ Refresh history. From 5de8c9138a901099025e7c3e70fc3f09311af4d5 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Tue, 16 Aug 2022 19:40:32 -0500 Subject: [PATCH 8/9] IPython console: Update cwd for first consoles - Those are created not only when Spyder is started but also when opening/closing projects. - Expand tests to check that cwd is synced when opening/closing projects. --- spyder/app/tests/test_mainwindow.py | 25 ++++++++++++++++++- .../plugins/ipythonconsole/widgets/client.py | 1 - 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py index 20719f48b1b..fa5d6856915 100644 --- a/spyder/app/tests/test_mainwindow.py +++ b/spyder/app/tests/test_mainwindow.py @@ -5482,7 +5482,7 @@ def test_console_initial_cwd_is_synced(main_window, qtbot, tmpdir): assert shell.get_cwd() == str(tmpdir) == workdir.get_workdir() == \ files.get_current_folder() - # Check that new clients with a fixed directory + # Check new clients with a fixed directory ipyconsole.set_conf('console/use_cwd', False, section='workingdir') ipyconsole.set_conf( 'console/use_fixed_directory', @@ -5505,6 +5505,29 @@ def test_console_initial_cwd_is_synced(main_window, qtbot, tmpdir): assert shell.get_cwd() == fixed_dir == workdir.get_workdir() == \ files.get_current_folder() + # Check when opening projects + project_path = str(tmpdir.mkdir('test_project')) + main_window.projects.open_project(path=project_path) + qtbot.wait(500) + + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + qtbot.wait(500) + assert shell.get_cwd() == project_path == workdir.get_workdir() == \ + files.get_current_folder() + + # Check when closing projects + main_window.projects.close_project() + qtbot.wait(500) + + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + qtbot.wait(500) + assert shell.get_cwd() == get_home_dir() == workdir.get_workdir() == \ + files.get_current_folder() + if __name__ == "__main__": pytest.main() diff --git a/spyder/plugins/ipythonconsole/widgets/client.py b/spyder/plugins/ipythonconsole/widgets/client.py index b48ab7d8623..f927b2110ae 100644 --- a/spyder/plugins/ipythonconsole/widgets/client.py +++ b/spyder/plugins/ipythonconsole/widgets/client.py @@ -369,7 +369,6 @@ def _set_initial_cwd_in_kernel(self): cwd_path = get_home_dir() if project_path is not None: cwd_path = project_path - update_in_spyder = False elif self.get_conf( 'startup/use_fixed_directory', section='workingdir' From a92ba14b1b1fa2c065e05d665cb32b2ba5800a9a Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 17 Aug 2022 22:14:18 -0500 Subject: [PATCH 9/9] IPython console: Rename a kwarg in set_cwd for clarity Also expand the docstring of that method. --- spyder/plugins/ipythonconsole/widgets/client.py | 8 +++----- spyder/plugins/ipythonconsole/widgets/shell.py | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/spyder/plugins/ipythonconsole/widgets/client.py b/spyder/plugins/ipythonconsole/widgets/client.py index f927b2110ae..bfdae2d4f11 100644 --- a/spyder/plugins/ipythonconsole/widgets/client.py +++ b/spyder/plugins/ipythonconsole/widgets/client.py @@ -358,7 +358,7 @@ def _set_initial_cwd_in_kernel(self): logger.debug("Setting initial working directory in the kernel") cwd_path = get_home_dir() project_path = self.container.get_active_project_path() - update_in_spyder = True + emit_cwd_change = True # This is for the first client if self.id_['int_id'] == '1': @@ -391,7 +391,7 @@ def _set_initial_cwd_in_kernel(self): cwd_path = project_path elif self.get_conf('console/use_cwd', section='workingdir'): cwd_path = self.container.get_working_directory() - update_in_spyder = False + emit_cwd_change = False elif self.get_conf( 'console/use_fixed_directory', section='workingdir' @@ -403,9 +403,7 @@ def _set_initial_cwd_in_kernel(self): ) if osp.isdir(cwd_path): - self.shellwidget.set_cwd( - cwd_path, update_in_spyder=update_in_spyder - ) + self.shellwidget.set_cwd(cwd_path, emit_cwd_change=emit_cwd_change) # ----- Public API -------------------------------------------------------- @property diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py index c14a22c5117..3a22e3dace6 100644 --- a/spyder/plugins/ipythonconsole/widgets/shell.py +++ b/spyder/plugins/ipythonconsole/widgets/shell.py @@ -296,8 +296,18 @@ def check_spyder_kernel(self): else: self.silent_exec_method(code) - def set_cwd(self, dirname, update_in_spyder=False): - """Set shell current working directory.""" + def set_cwd(self, dirname, emit_cwd_change=False): + """ + Set shell current working directory. + + Parameters + ---------- + dirname: str + Path to the new current working directory. + emit_cwd_change: bool + Whether to emit a Qt signal that informs other panes in Spyder that + the current working directory has changed. + """ if os.name == 'nt': # Use normpath instead of replacing '\' with '\\' # See spyder-ide/spyder#10785 @@ -306,7 +316,7 @@ def set_cwd(self, dirname, update_in_spyder=False): if self.ipyclient.hostname is None: self.call_kernel(interrupt=self.is_debugging()).set_cwd(dirname) self._cwd = dirname - if update_in_spyder: + if emit_cwd_change: self.sig_working_directory_changed.emit(self._cwd) def get_cwd(self):