Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Make consoles to start without an stderr file #5457

Merged
merged 7 commits into from Oct 17, 2017
2 changes: 1 addition & 1 deletion requirements/requirements.txt
Expand Up @@ -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
Expand Down
22 changes: 14 additions & 8 deletions spyder/plugins/ipythonconsole.py
Expand Up @@ -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)
Expand All @@ -623,8 +624,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 = test_no_stderr

# Initialize plugin
if not self.testing:
Expand Down Expand Up @@ -1021,12 +1025,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
try:

if self.test_no_stderr:
stderr_file = None
else:
stderr_file = client.stderr_file
except PermissionError:
error_msg = self.permission_error_msg.format(TEMPDIR)
client.show_kernel_error(error_msg)
return

km, kc = self.create_kernel_manager_and_kernel_client(connection_file,
stderr_file)
Expand Down Expand Up @@ -1430,7 +1433,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
Expand Down Expand Up @@ -1559,7 +1565,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:
Expand Down
59 changes: 47 additions & 12 deletions spyder/plugins/tests/test_ipythonconsole.py
Expand Up @@ -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

Expand All @@ -36,6 +37,7 @@
SHELL_TIMEOUT = 20000
PYQT_WHEEL = PYQT_VERSION > '5.6'
TEMP_DIRECTORY = tempfile.gettempdir()
NON_ASCII_DIR = osp.join(TEMP_DIRECTORY, u'測試', u'اختبار')


#==============================================================================
Expand Down Expand Up @@ -64,41 +66,74 @@ def get_console_background_color(style_sheet):
#==============================================================================
@pytest.fixture
def ipyconsole(request):
try:
console = IPythonConsole(None, testing=True, test_dir=request.param)
except AttributeError:
console = IPythonConsole(None, testing=True)
"""IPython console fixture."""

# Test the console with a non-ascii temp dir
non_ascii_dir = request.node.get_marker('non_ascii_dir')
if non_ascii_dir:
test_dir = NON_ASCII_DIR
else:
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:
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():
console.closing_plugin()
console.close()
request.addfinalizer(close_console)
console.show()

return console


#==============================================================================
# Tests
#==============================================================================
@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.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)

# Create a new client with s stderr file in a non-ascii dir
ipyconsole.create_new_client()
# Execute a simple assignment
with qtbot.waitSignal(shell.executed):
shell.execute('a = 1')

# Assert we get the assigned value correctly
assert shell.get_value('a') == 1


@flaky(max_runs=3)
@pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows")
@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,
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


Expand Down Expand Up @@ -531,7 +566,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')

Expand Down
12 changes: 8 additions & 4 deletions spyder/widgets/ipythonconsole/client.py
Expand Up @@ -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"""
Expand Down