From 0b014bd66ef1cf725174392bf5e3611d0d083241 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 12 Oct 2017 19:47:38 -0500 Subject: [PATCH 1/7] IPython console: Don't catch PermissionError when creating connection_file This is because it's not available in Python 2 --- spyder/plugins/ipythonconsole.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spyder/plugins/ipythonconsole.py b/spyder/plugins/ipythonconsole.py index c4ee674842f..5e43408033d 100644 --- a/spyder/plugins/ipythonconsole.py +++ b/spyder/plugins/ipythonconsole.py @@ -1559,7 +1559,7 @@ def _new_connection_file(self): if not osp.isdir(jupyter_runtime_dir()): try: os.makedirs(jupyter_runtime_dir()) - except PermissionError: + except (IOError, OSError): return None cf = '' while not cf: From 7a19d3f6e9274402d37848b0817466e7ec6dc36e Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 12 Oct 2017 19:49:27 -0500 Subject: [PATCH 2/7] IPython console: Make stderr_file to be None if errors appear --- spyder/widgets/ipythonconsole/client.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/spyder/widgets/ipythonconsole/client.py b/spyder/widgets/ipythonconsole/client.py index ffa9d632946..39b838206f7 100644 --- a/spyder/widgets/ipythonconsole/client.py +++ b/spyder/widgets/ipythonconsole/client.py @@ -156,15 +156,19 @@ def kernel_id(self): @property def stderr_file(self): """Filename to save kernel stderr output.""" + stderr_file = None if self.connection_file is not None: stderr_file = self.kernel_id + '.stderr' if self.stderr_dir is not None: stderr_file = osp.join(self.stderr_dir, stderr_file) else: - if not osp.isdir(TEMPDIR): - os.makedirs(TEMPDIR) - stderr_file = osp.join(TEMPDIR, stderr_file) - return stderr_file + try: + if not osp.isdir(TEMPDIR): + os.makedirs(TEMPDIR) + stderr_file = osp.join(TEMPDIR, stderr_file) + except (IOError, OSError): + stderr_file = None + return stderr_file def configure_shellwidget(self, give_focus=True): """Configure shellwidget after kernel is started""" From 20dc5e9d9d937be76b98d49ad35da03f9c081e60 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 12 Oct 2017 19:51:52 -0500 Subject: [PATCH 3/7] IPython console: Make consoles to start without a stderr file if it can't be created --- spyder/plugins/ipythonconsole.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/spyder/plugins/ipythonconsole.py b/spyder/plugins/ipythonconsole.py index 5e43408033d..b4b903e633b 100644 --- a/spyder/plugins/ipythonconsole.py +++ b/spyder/plugins/ipythonconsole.py @@ -1021,12 +1021,7 @@ def create_client_for_kernel(self): def connect_client_to_kernel(self, client): """Connect a client to its kernel""" connection_file = client.connection_file - try: - stderr_file = client.stderr_file - except PermissionError: - error_msg = self.permission_error_msg.format(TEMPDIR) - client.show_kernel_error(error_msg) - return + stderr_file = client.stderr_file km, kc = self.create_kernel_manager_and_kernel_client(connection_file, stderr_file) @@ -1430,7 +1425,10 @@ def create_kernel_manager_and_kernel_client(self, connection_file, kernel_manager._kernel_spec = kernel_spec # Save stderr in a file to read it later in case of errors - stderr = codecs.open(stderr_file, 'w', encoding='utf-8') + if stderr_file is not None: + stderr = codecs.open(stderr_file, 'w', encoding='utf-8') + else: + stderr = None kernel_manager.start_kernel(stderr=stderr) # Kernel client From 2ebc924b0b6867388bf98349c7c516c9b35f70dd Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 12 Oct 2017 19:52:22 -0500 Subject: [PATCH 4/7] Bump qtpy version in requirements.txt --- requirements/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index a94aacd1b16..0ed40dff9ab 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -9,7 +9,7 @@ pycodestyle pylint psutil qtawesome>=0.4.1 -qtpy>=1.1.0 +qtpy>=1.2.0 pickleshare pyzmq chardet>=2.0.0 From 7360cd099da2818a645d5a8e54994b3b5780a85b Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Tue, 17 Oct 2017 12:26:34 -0500 Subject: [PATCH 5/7] Testing: Verify that the IPython console can work without stderr files --- spyder/plugins/ipythonconsole.py | 9 ++++++- spyder/plugins/tests/test_ipythonconsole.py | 30 ++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/spyder/plugins/ipythonconsole.py b/spyder/plugins/ipythonconsole.py index b4b903e633b..29cb34df3f7 100644 --- a/spyder/plugins/ipythonconsole.py +++ b/spyder/plugins/ipythonconsole.py @@ -623,8 +623,11 @@ def __init__(self, parent, testing=False, test_dir=TEMPDIR): self.filenames = [] self.mainwindow_close = False self.create_new_client_if_empty = True + + # Attrs for testing self.testing = testing self.test_dir = test_dir + self.test_no_stderr = None # Initialize plugin if not self.testing: @@ -1021,7 +1024,11 @@ def create_client_for_kernel(self): def connect_client_to_kernel(self, client): """Connect a client to its kernel""" connection_file = client.connection_file - stderr_file = client.stderr_file + + if self.test_no_stderr: + stderr_file = None + else: + stderr_file = client.stderr_file km, kc = self.create_kernel_manager_and_kernel_client(connection_file, stderr_file) diff --git a/spyder/plugins/tests/test_ipythonconsole.py b/spyder/plugins/tests/test_ipythonconsole.py index 4560703c4bf..a9e3846a2d7 100644 --- a/spyder/plugins/tests/test_ipythonconsole.py +++ b/spyder/plugins/tests/test_ipythonconsole.py @@ -64,22 +64,50 @@ def get_console_background_color(style_sheet): #============================================================================== @pytest.fixture def ipyconsole(request): + """IPython console fixture.""" + try: console = IPythonConsole(None, testing=True, test_dir=request.param) except AttributeError: console = IPythonConsole(None, testing=True) + + # Intruct the console to not use a stderr file + no_stderr_file = request.node.get_marker('no_stderr_file') + if no_stderr_file: + console.test_no_stderr = True + console.create_new_client() + def close_console(): console.closing_plugin() console.close() request.addfinalizer(close_console) console.show() + return console #============================================================================== # Tests #============================================================================== +@flaky(max_runs=3) +@pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") +@pytest.mark.no_stderr_file +def test_no_stderr_file(ipyconsole, qtbot): + """Test that consoles can run without an stderr.""" + # Wait until the window is fully up + shell = ipyconsole.get_current_shellwidget() + qtbot.waitUntil(lambda: shell._prompt_html is not None, + timeout=SHELL_TIMEOUT) + + # Execute a simple assignment + with qtbot.waitSignal(shell.executed): + shell.execute('a = 1') + + # Assert we get the value correctly + assert shell.get_value('a') == 1 + + @pytest.mark.parametrize('ipyconsole', [osp.join(TEMP_DIRECTORY, u'測試', u'اختبار')], indirect=True) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") @@ -531,7 +559,7 @@ def test_restart_kernel(ipyconsole, qtbot): client = ipyconsole.get_current_client() qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) - # Do an assigment to verify that it's not there after restarting + # Do an assignment to verify that it's not there after restarting with qtbot.waitSignal(shell.executed): shell.execute('a = 10') From 7ded4eae0bd60880800960ca40bac42b84e9f7d0 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Tue, 17 Oct 2017 13:10:30 -0500 Subject: [PATCH 6/7] Testing: Simplify an IPython console test --- spyder/plugins/tests/test_ipythonconsole.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/spyder/plugins/tests/test_ipythonconsole.py b/spyder/plugins/tests/test_ipythonconsole.py index a9e3846a2d7..385bad42b1b 100644 --- a/spyder/plugins/tests/test_ipythonconsole.py +++ b/spyder/plugins/tests/test_ipythonconsole.py @@ -36,6 +36,7 @@ SHELL_TIMEOUT = 20000 PYQT_WHEEL = PYQT_VERSION > '5.6' TEMP_DIRECTORY = tempfile.gettempdir() +NON_ASCII_DIR = osp.join(TEMP_DIRECTORY, u'測試', u'اختبار') #============================================================================== @@ -66,12 +67,16 @@ def get_console_background_color(style_sheet): def ipyconsole(request): """IPython console fixture.""" - try: - console = IPythonConsole(None, testing=True, test_dir=request.param) - except AttributeError: + # Test the console with a non-ascii temp dir + non_ascii_dir = request.node.get_marker('non_ascii_dir') + + # Create the console + if non_ascii_dir: + console = IPythonConsole(None, testing=True, test_dir=NON_ASCII_DIR) + else: console = IPythonConsole(None, testing=True) - # Intruct the console to not use a stderr file + # Instruct the console to not use a stderr file no_stderr_file = request.node.get_marker('no_stderr_file') if no_stderr_file: console.test_no_stderr = True @@ -108,11 +113,11 @@ def test_no_stderr_file(ipyconsole, qtbot): assert shell.get_value('a') == 1 -@pytest.mark.parametrize('ipyconsole', [osp.join(TEMP_DIRECTORY, u'測試', - u'اختبار')], indirect=True) +@flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows") -def test_console_stderr_file(ipyconsole, qtbot): - """Test a the creation of a console with a stderr file in ascii dir.""" +@pytest.mark.non_ascii_dir +def test_non_ascii_stderr_file(ipyconsole, qtbot): + """Test the creation of a console with a stderr file in a non-ascii dir.""" # Wait until the window is fully up shell = ipyconsole.get_current_shellwidget() qtbot.waitUntil(lambda: shell._prompt_html is not None, From 30bab3e5b9b733403cc80e9447988696c88aabc8 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Tue, 17 Oct 2017 14:04:39 -0500 Subject: [PATCH 7/7] Testing: Correctly create IPython console with testing parameters --- spyder/plugins/ipythonconsole.py | 5 ++-- spyder/plugins/tests/test_ipythonconsole.py | 26 +++++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/spyder/plugins/ipythonconsole.py b/spyder/plugins/ipythonconsole.py index 29cb34df3f7..378f57dbd0c 100644 --- a/spyder/plugins/ipythonconsole.py +++ b/spyder/plugins/ipythonconsole.py @@ -602,7 +602,8 @@ class IPythonConsole(SpyderPluginWidget): "required to create IPython consoles. Please " "make it writable.") - def __init__(self, parent, testing=False, test_dir=TEMPDIR): + def __init__(self, parent, testing=False, test_dir=TEMPDIR, + test_no_stderr=False): """Ipython Console constructor.""" if PYQT5: SpyderPluginWidget.__init__(self, parent, main = parent) @@ -627,7 +628,7 @@ def __init__(self, parent, testing=False, test_dir=TEMPDIR): # Attrs for testing self.testing = testing self.test_dir = test_dir - self.test_no_stderr = None + self.test_no_stderr = test_no_stderr # Initialize plugin if not self.testing: diff --git a/spyder/plugins/tests/test_ipythonconsole.py b/spyder/plugins/tests/test_ipythonconsole.py index 385bad42b1b..3c2aaf45ca5 100644 --- a/spyder/plugins/tests/test_ipythonconsole.py +++ b/spyder/plugins/tests/test_ipythonconsole.py @@ -26,6 +26,7 @@ KernelConnectionDialog) from spyder.utils.environ import listdict2envdict from spyder.utils.ipython.style import create_style_class +from spyder.utils.programs import TEMPDIR from spyder.utils.test import close_message_box from spyder.widgets.variableexplorer.collectionseditor import CollectionsEditor @@ -69,18 +70,23 @@ def ipyconsole(request): # Test the console with a non-ascii temp dir non_ascii_dir = request.node.get_marker('non_ascii_dir') - - # Create the console if non_ascii_dir: - console = IPythonConsole(None, testing=True, test_dir=NON_ASCII_DIR) + test_dir = NON_ASCII_DIR else: - console = IPythonConsole(None, testing=True) + test_dir = TEMPDIR # Instruct the console to not use a stderr file no_stderr_file = request.node.get_marker('no_stderr_file') if no_stderr_file: - console.test_no_stderr = True + test_no_stderr = True + else: + test_no_stderr = False + # Create the console and a new client + console = IPythonConsole(parent=None, + testing=True, + test_dir=test_dir, + test_no_stderr=test_no_stderr) console.create_new_client() def close_console(): @@ -109,7 +115,7 @@ def test_no_stderr_file(ipyconsole, qtbot): with qtbot.waitSignal(shell.executed): shell.execute('a = 1') - # Assert we get the value correctly + # Assert we get the assigned value correctly assert shell.get_value('a') == 1 @@ -123,15 +129,11 @@ def test_non_ascii_stderr_file(ipyconsole, qtbot): qtbot.waitUntil(lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT) - # Create a new client with s stderr file in a non-ascii dir - ipyconsole.create_new_client() - shell = ipyconsole.get_current_shellwidget() - qtbot.waitUntil(lambda: shell._prompt_html is not None, - timeout=SHELL_TIMEOUT) + # Execute a simple assignment with qtbot.waitSignal(shell.executed): shell.execute('a = 1') - # Assert we get the a value correctly + # Assert we get the assigned value assert shell.get_value('a') == 1