Repository: spyder-ide/spyder

Issue:
Kernels fail to start because they can't create stderr files in non-ascii accounts on Windows
## Description

**What steps will reproduce the problem?**

1. 
2. 
3. 

**What is the expected output? What do you see instead?**


**Please provide any additional information below**

  File "C:\Anaconda2\lib\site-packages\spyder\plugins\__init__.py", line 511, in <lambda>
    toggled=lambda checked: self.toggle_view(checked),
  File "C:\Anaconda2\lib\site-packages\spyder\plugins\ipythonconsole.py", line 695, in toggle_view
    self.create_new_client(give_focus=False)
  File "C:\Anaconda2\lib\site-packages\spyder\plugins\ipythonconsole.py", line 974, in create_new_client
    self.connect_client_to_kernel(client)
  File "C:\Anaconda2\lib\site-packages\spyder\plugins\ipythonconsole.py", line 995, in connect_client_to_kernel
    stderr_file)
  File "C:\Anaconda2\lib\site-packages\spyder\plugins\ipythonconsole.py", line 1384, in create_kernel_manager_and_kernel_client
    kernel_manager.start_kernel(stderr=stderr)
  File "C:\Anaconda2\lib\site-packages\jupyter_client\manager.py", line 243, in start_kernel
    **kw)
  File "C:\Anaconda2\lib\site-packages\jupyter_client\manager.py", line 189, in _launch_kernel
    return launch_kernel(kernel_cmd, **kw)
  File "C:\Anaconda2\lib\site-packages\jupyter_client\launcher.py", line 123, in launch_kernel
    proc = Popen(cmd, **kwargs)
  File "C:\Anaconda2\lib\subprocess.py", line 390, in __init__
    errread, errwrite)
  File "C:\Anaconda2\lib\sub


Discussion:
It seems there's content missing in your error report. Please post the entire error.
This is probably a duplicate of issue #4816. So I'm closing this issue for now.
On a second thought, this maybe is caused because you have a user name with non-ascii characters.

We'll take a look at it in a future release.
@dalthviz, please work on this one.
I think the idea is (as a test) make the directory where stderr files are created a non-ascii one and see if IPython consoles can start or not using Python 2 (I think they will fail).

Then you need to fix this error.
@ccordoba12  after testing no error appear for the console. It starts normally. 

A screenshot of the path for some of the stderr files of the consoles I created while testing:

![imagen](https://user-images.githubusercontent.com/16781833/29491065-bb6c51c6-8515-11e7-8744-9d76eeec1fb2.png)

Ok, then please add a test for this please. For the test, please use a non-ascii dir with Chinese and Arabic characters.

Resolving patch:
diff --git a/spyder/plugins/ipythonconsole.py b/spyder/plugins/ipythonconsole.py
--- a/spyder/plugins/ipythonconsole.py
+++ b/spyder/plugins/ipythonconsole.py
@@ -53,6 +53,7 @@
 from spyder.utils.qthelpers import create_action, MENU_SEPARATOR
 from spyder.utils import icon_manager as ima
 from spyder.utils import encoding, programs, sourcecode
+from spyder.utils.programs import TEMPDIR
 from spyder.utils.misc import get_error_match, remove_backslashes
 from spyder.widgets.findreplace import FindReplace
 from spyder.widgets.ipythonconsole import ClientWidget
@@ -590,7 +591,7 @@ class IPythonConsole(SpyderPluginWidget):
     focus_changed = Signal()
     edit_goto = Signal((str, int, str), (str, int, str, bool))
 
-    def __init__(self, parent, testing=False):
+    def __init__(self, parent, testing=False, test_dir=TEMPDIR):
         """Ipython Console constructor."""
         if PYQT5:
             SpyderPluginWidget.__init__(self, parent, main = parent)
@@ -612,6 +613,7 @@ def __init__(self, parent, testing=False):
         self.mainwindow_close = False
         self.create_new_client_if_empty = True
         self.testing = testing
+        self.test_dir = test_dir
 
         # Initialize plugin
         if not self.testing:
@@ -619,8 +621,9 @@ def __init__(self, parent, testing=False):
 
         # Create temp dir on testing to save kernel errors
         if self.testing:
-            if not osp.isdir(programs.TEMPDIR):
-                os.mkdir(programs.TEMPDIR)
+            if not osp.isdir(osp.join(test_dir)):
+                os.makedirs(osp.join(test_dir))
+
 
         layout = QVBoxLayout()
         self.tabwidget = Tabs(self, self.menu_actions, rename_tabs=True,
@@ -945,6 +948,8 @@ def create_new_client(self, give_focus=True, filename=''):
                               interpreter_versions=self.interpreter_versions(),
                               connection_file=cf,
                               menu_actions=self.menu_actions)
+        if self.testing:
+            client.stderr_dir = self.test_dir
         self.add_tab(client, name=client.get_name(), filename=filename)
 
         if cf is None:
diff --git a/spyder/widgets/ipythonconsole/client.py b/spyder/widgets/ipythonconsole/client.py
--- a/spyder/widgets/ipythonconsole/client.py
+++ b/spyder/widgets/ipythonconsole/client.py
@@ -113,6 +113,7 @@ def __init__(self, plugin, id_,
         self.stop_icon = ima.icon('stop')
         self.history = []
         self.allow_rename = True
+        self.stderr_dir = None
 
         # --- Widgets
         self.shellwidget = ShellWidget(config=config_options,
@@ -163,7 +164,10 @@ def stderr_file(self):
         """Filename to save kernel stderr output."""
         if self.connection_file is not None:
             stderr_file = self.kernel_id + '.stderr'
-            stderr_file = osp.join(TEMPDIR, stderr_file)
+            if self.stderr_dir is not None:
+                stderr_file = osp.join(self.stderr_dir, stderr_file)
+            else:
+                stderr_file = osp.join(TEMPDIR, stderr_file)
             return stderr_file
 
     def configure_shellwidget(self, give_focus=True):


Test patch:
diff --git a/spyder/plugins/tests/test_ipythonconsole.py b/spyder/plugins/tests/test_ipythonconsole.py
--- a/spyder/plugins/tests/test_ipythonconsole.py
+++ b/spyder/plugins/tests/test_ipythonconsole.py
@@ -64,7 +64,10 @@ def get_console_background_color(style_sheet):
 #==============================================================================
 @pytest.fixture
 def ipyconsole(request):
-    console = IPythonConsole(None, testing=True)
+    try:
+        console = IPythonConsole(None, testing=True, test_dir=request.param)
+    except AttributeError:
+        console = IPythonConsole(None, testing=True)
     console.create_new_client()
     def close_console():
         console.closing_plugin()
@@ -77,6 +80,27 @@ def close_console():
 #==============================================================================
 # Tests
 #==============================================================================
+@pytest.mark.parametrize('ipyconsole', [osp.join(TEMP_DIRECTORY, u'測試',
+                                                 u'اختبار')], indirect=True)
+def test_console_stderr_file(ipyconsole, qtbot):
+    """Test a the creation of a console with a stderr file in 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)
+
+    # 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)
+    with qtbot.waitSignal(shell.executed):
+        shell.execute('a = 1')
+
+    # Assert we get the a value correctly
+    assert shell.get_value('a') == 1
+
+
 @flaky(max_runs=3)
 def test_console_import_namespace(ipyconsole, qtbot):
     """Test an import of the form 'from foo import *'."""