diff --git a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
index 1c30d3d0007..dc52e00db5c 100644
--- a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
+++ b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
@@ -48,6 +48,7 @@
from spyder.plugins.help.tests.test_plugin import check_text
from spyder.plugins.help.utils.sphinxify import CSS_PATH
from spyder.plugins.ipythonconsole.plugin import IPythonConsole
+from spyder.plugins.ipythonconsole.utils import stdfile
from spyder.plugins.ipythonconsole.utils.style import create_style_class
from spyder.plugins.ipythonconsole.widgets import ClientWidget
from spyder.utils.programs import get_temp_dir
@@ -209,7 +210,7 @@ def __getattr__(self, attr):
# Create the console and a new client and set environment
os.environ['IPYCONSOLE_TESTING'] = 'True'
- os.environ['IPYCONSOLE_TEST_DIR'] = test_dir
+ stdfile.IPYCONSOLE_TEST_DIR = test_dir
os.environ['IPYCONSOLE_TEST_NO_STDERR'] = test_no_stderr
window = MainWindowMock()
console = IPythonConsole(parent=window, configuration=configuration)
@@ -274,7 +275,7 @@ def __getattr__(self, attr):
# Close
console.on_close()
os.environ.pop('IPYCONSOLE_TESTING')
- os.environ.pop('IPYCONSOLE_TEST_DIR')
+ stdfile.IPYCONSOLE_TEST_DIR = None
os.environ.pop('IPYCONSOLE_TEST_NO_STDERR')
if os.name == 'nt' or known_leak:
diff --git a/spyder/plugins/ipythonconsole/utils/stdfile.py b/spyder/plugins/ipythonconsole/utils/stdfile.py
index c0cb22fa454..fb985d2bd3a 100644
--- a/spyder/plugins/ipythonconsole/utils/stdfile.py
+++ b/spyder/plugins/ipythonconsole/utils/stdfile.py
@@ -21,26 +21,27 @@
from spyder.utils.programs import get_temp_dir
-def std_filename(connection_file, extension, std_dir=None):
+IPYCONSOLE_TEST_DIR = None
+
+
+def std_filename(connection_file, extension):
"""Filename to save kernel output."""
json_file = osp.basename(connection_file)
file = json_file.split('.json')[0] + extension
- if std_dir is not None:
- file = osp.join(std_dir, file)
- else:
- try:
- file = osp.join(get_temp_dir(), file)
- except (IOError, OSError):
- file = None
- return file
+ if IPYCONSOLE_TEST_DIR is not None:
+ return osp.join(IPYCONSOLE_TEST_DIR, file)
+ try:
+ return osp.join(get_temp_dir(), file)
+ except (IOError, OSError):
+ return None
class StdFile:
- def __init__(self, connection_file, extension=None, std_dir=None):
+ def __init__(self, connection_file, extension=None):
if extension is None:
self.filename = connection_file
else:
- self.filename = std_filename(connection_file, extension, std_dir)
+ self.filename = std_filename(connection_file, extension)
self._mtime = 0
self._cursor = 0
self._handle = None
diff --git a/spyder/plugins/ipythonconsole/widgets/client.py b/spyder/plugins/ipythonconsole/widgets/client.py
index f7b32a2cfca..12605ec62cf 100644
--- a/spyder/plugins/ipythonconsole/widgets/client.py
+++ b/spyder/plugins/ipythonconsole/widgets/client.py
@@ -186,7 +186,7 @@ def start_std_poll(self):
self.std_poll_timer.start()
self.shellwidget.executed.connect(self.poll_std_file_change)
- def connect_kernel(self, kernel, known_spyder_kernel=True):
+ def connect_kernel(self, kernel):
"""Connect kernel to client."""
self.connection_file = kernel["connection_file"]
self.stderr_obj = kernel["stderr_obj"]
@@ -197,7 +197,7 @@ def connect_kernel(self, kernel, known_spyder_kernel=True):
self.shellwidget.connect_kernel(
kernel["kernel_client"],
kernel["kernel_manager"],
- known_spyder_kernel
+ kernel["known_spyder_kernel"]
)
# ----- Private methods ---------------------------------------------------
diff --git a/spyder/plugins/ipythonconsole/widgets/main_widget.py b/spyder/plugins/ipythonconsole/widgets/main_widget.py
index c55cb38a378..a4918963805 100644
--- a/spyder/plugins/ipythonconsole/widgets/main_widget.py
+++ b/spyder/plugins/ipythonconsole/widgets/main_widget.py
@@ -306,14 +306,8 @@ def __init__(self, name=None, plugin=None, parent=None):
# Attrs for testing
self._testing = bool(os.environ.get('IPYCONSOLE_TESTING'))
- self._test_dir = os.environ.get('IPYCONSOLE_TEST_DIR')
self._test_no_stderr = os.environ.get('IPYCONSOLE_TEST_NO_STDERR')
- # Create temp dir on testing to save kernel errors
- if self._test_dir:
- if not osp.isdir(osp.join(self._test_dir)):
- os.makedirs(osp.join(self._test_dir))
-
layout = QVBoxLayout()
layout.setSpacing(0)
self.tabwidget = Tabs(self, menu=self._options_menu,
@@ -1392,20 +1386,19 @@ def create_new_client(self, give_focus=True, filename='', is_cython=False,
give_focus=give_focus,
handlers=self.registered_spyder_kernel_handlers
)
-
+ # Add client to widget
self.add_tab(
client, name=client.get_name(), filename=filename,
give_focus=give_focus)
- std_dir = self._test_dir if self._test_dir else None
+ # Create new kernel
kernel_spec = self.create_kernel_spec(
is_cython=is_cython,
is_pylab=is_pylab,
is_sympy=is_sympy
)
try:
- kernel = self.get_new_kernel(
- kernel_spec, std_dir=std_dir, cache=cache)
+ kernel = self.get_cached_kernel(kernel_spec, cache=cache)
except Exception:
# See spyder-ide/spyder#7302.
error_msg = _("The error is:
"
@@ -1413,12 +1406,11 @@ def create_new_client(self, give_focus=True, filename='', is_cython=False,
client.show_kernel_error(error_msg)
return
+ # Connect kernel to client
client.connect_kernel(kernel)
- def create_client_for_kernel(self, connection_file, hostname, sshkey,
- password):
- """Create a client connected to an existing kernel."""
- # Verifying if the connection file exists
+ def check_connection_file(self, connection_file):
+ """Verify if the connection file exists"""
try:
cf_path = osp.dirname(connection_file)
cf_filename = osp.basename(connection_file)
@@ -1435,12 +1427,22 @@ def create_client_for_kernel(self, connection_file, hostname, sshkey,
_("Unable to connect to "
"%s") % connection_file)
return
+ return connection_file
+
+
+ def create_client_for_kernel(self, connection_file, hostname, sshkey,
+ password):
+ """Create a client connected to an existing kernel."""
+
+ connection_file = self.check_connection_file(connection_file)
+ if connection_file is None:
+ return
# Getting the master id that corresponds to the client
# (i.e. the i in i/A)
master_id = None
given_name = None
- known_spyder_kernel = False
+
slave_ord = ord('A') - 1
t0 = None
kernel = dict(
@@ -1449,7 +1451,8 @@ def create_client_for_kernel(self, connection_file, hostname, sshkey,
connection_file=None,
stderr_obj=None,
stdout_obj=None,
- fault_obj=None)
+ fault_obj=None,
+ known_spyder_kernel=False)
for cl in self.clients:
if connection_file in cl.connection_file:
@@ -1459,7 +1462,8 @@ def create_client_for_kernel(self, connection_file, hostname, sshkey,
t0 = cl.t0
if master_id is None:
master_id = cl.id_['int_id']
- known_spyder_kernel = cl.shellwidget.is_spyder_kernel
+ kernel["known_spyder_kernel"] = (
+ cl.shellwidget.is_spyder_kernel)
if cl.stderr_obj:
kernel["stderr_obj"] = cl.stderr_obj.copy()
if cl.stdout_obj:
@@ -1511,7 +1515,7 @@ def create_client_for_kernel(self, connection_file, hostname, sshkey,
kernel["connection_file"] = connection_file
kernel["kernel_client"] = kernel_client
- client.connect_kernel(kernel, known_spyder_kernel)
+ client.connect_kernel(kernel)
def new_kernel_client(self, connection_file, hostname, sshkey, password):
"""Create kernel client."""
@@ -1562,21 +1566,20 @@ def create_cython_client(self):
"""Force creation of Cython client"""
self.create_new_client(is_cython=True, given_name="Cython")
- def check_cached_kernel_spec(self, kernel_spec, std_dir):
+ def check_cached_kernel_spec(self, kernel_spec):
"""Test if kernel_spec corresponds to the cached kernel_spec."""
if self._cached_kernel_properties is None:
return False
- (cached_spec, cached_env, cached_argv, cached_dir, cached_kernel
+ (cached_spec, cached_env, cached_argv, cached_kernel
) = self._cached_kernel_properties
# Call interrupt_mode so the dict will be the same
kernel_spec.interrupt_mode
cached_spec.interrupt_mode
- return (std_dir == cached_dir
- and cached_spec.__dict__ == kernel_spec.__dict__
+ return (cached_spec.__dict__ == kernel_spec.__dict__
and kernel_spec.argv == cached_argv
and kernel_spec.env == cached_env)
- def get_new_kernel(self, kernel_spec, std_dir=None, cache=True):
+ def get_cached_kernel(self, kernel_spec, cache=True):
"""Get a new kernel, and cache one for next time."""
# Check if ipykernel is present in the external interpreter.
# Else we won't be able to create a client
@@ -1614,7 +1617,7 @@ def get_new_kernel(self, kernel_spec, std_dir=None, cache=True):
)
# Cache another kernel for next time.
- new_kernel = self.create_new_kernel(kernel_spec, std_dir)
+ new_kernel = self.create_new_kernel(kernel_spec)
if not cache:
# remove/don't use cache if requested
@@ -1625,7 +1628,7 @@ def get_new_kernel(self, kernel_spec, std_dir=None, cache=True):
cached_kernel = None
if self._cached_kernel_properties is not None:
cached_kernel = self._cached_kernel_properties[-1]
- if not self.check_cached_kernel_spec(kernel_spec, std_dir):
+ if not self.check_cached_kernel_spec(kernel_spec):
# Close the kernel
self.close_cached_kernel()
cached_kernel = None
@@ -1635,11 +1638,10 @@ def get_new_kernel(self, kernel_spec, std_dir=None, cache=True):
kernel_spec,
kernel_spec.env,
kernel_spec.argv,
- std_dir,
new_kernel)
if cached_kernel is None:
- return self.create_new_kernel(kernel_spec, std_dir)
+ return self.create_new_kernel(kernel_spec)
return cached_kernel
@@ -1662,37 +1664,54 @@ def close_cached_kernel(self):
if fault_obj:
fault_obj.remove()
- def create_new_kernel(self, kernel_spec, std_dir=None):
- """Create a new kernel."""
+ def create_new_kernel(self, kernel_spec):
+ """
+ Create a new kernel.
+
+ Might raise all kinds of exceptions
+ """
connection_file = self._new_connection_file()
if connection_file is None:
raise RuntimeError(
self.PERMISSION_ERROR_MSG.format(jupyter_runtime_dir()))
stderr_obj = None
- stderr_handle = None
stdout_obj = None
- stdout_handle = None
if not self._test_no_stderr:
- stderr_obj = StdFile(connection_file, '.stderr', std_dir)
- stderr_handle = stderr_obj.handle
- stdout_obj = StdFile(connection_file, '.stdout', std_dir)
- stdout_handle = stdout_obj.handle
- fault_obj = StdFile(connection_file, '.fault', std_dir)
-
- km, kc = self.create_kernel_manager_and_kernel_client(
- connection_file,
- stderr_handle,
- stdout_handle,
- kernel_spec,
+ stderr_obj = StdFile(connection_file, '.stderr')
+ stdout_obj = StdFile(connection_file, '.stdout')
+ fault_obj = StdFile(connection_file, '.fault')
+
+ # Kernel manager
+ kernel_manager = SpyderKernelManager(
+ connection_file=connection_file,
+ config=None,
+ autorestart=True,
+ )
+
+ kernel_manager._kernel_spec = kernel_spec
+
+ kernel_manager.start_kernel(
+ stderr=stderr_obj.handle,
+ stdout=stdout_obj.handle,
+ env=kernel_spec.env
)
+
+ # Kernel client
+ kernel_client = kernel_manager.client()
+
+ # Increase time (in seconds) to detect if a kernel is alive.
+ # See spyder-ide/spyder#3444.
+ kernel_client.hb_channel.time_to_dead = 25.0
+
return dict(
connection_file=connection_file,
- kernel_manager=km,
- kernel_client=kc,
+ kernel_manager=kernel_manager,
+ kernel_client=kernel_client,
stderr_obj=stderr_obj,
stdout_obj=stdout_obj,
- fault_obj=fault_obj)
+ fault_obj=fault_obj,
+ known_spyder_kernel=True)
@Slot(str)
def create_client_from_path(self, path):
@@ -2004,35 +2023,6 @@ def create_kernel_spec(self, is_cython=False,
is_pylab=is_pylab,
is_sympy=is_sympy)
- def create_kernel_manager_and_kernel_client(self, connection_file,
- stderr_handle,
- stdout_handle,
- kernel_spec):
- """Create kernel manager and client."""
- # Kernel manager
- kernel_manager = SpyderKernelManager(
- connection_file=connection_file,
- config=None,
- autorestart=True,
- )
-
- kernel_manager._kernel_spec = kernel_spec
-
- kernel_manager.start_kernel(
- stderr=stderr_handle,
- stdout=stdout_handle,
- env=kernel_spec.env
- )
-
- # Kernel client
- kernel_client = kernel_manager.client()
-
- # Increase time (in seconds) to detect if a kernel is alive.
- # See spyder-ide/spyder#3444.
- kernel_client.hb_channel.time_to_dead = 25.0
-
- return kernel_manager, kernel_client
-
@Slot()
def restart_kernel(self, client=None, ask_before_restart=True):
"""Restart kernel of current client."""
diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py
index 3a14cfd9fe5..07b77b00607 100644
--- a/spyder/plugins/ipythonconsole/widgets/shell.py
+++ b/spyder/plugins/ipythonconsole/widgets/shell.py
@@ -250,7 +250,7 @@ def call_kernel(self, interrupt=False, blocking=False, callback=None,
)
def connect_kernel(
- self, kernel_client, kernel_manager, known_spyder_kernel=True):
+ self, kernel_client, kernel_manager, known_spyder_kernel):
"""Connect to kernel."""
kernel_client.stopped_channels.connect(
lambda: self.sig_shellwidget_deleted.emit(self))