Repository: spyder-ide/spyder

Issue:
Setting a path containing a single quote
## Description
(I'm new to both Python and Spyder, so I apologise if my terminology isn't correct)
Spyder 3.2.6 is unable to pass paths for working directories that contain a single quote to the IPython interpreter. I use my uni OneDrive account which has a single quote in the path that I cannot change.

**What steps will reproduce the problem?**

1. Click on the folder icon at the top right of the title bar (Windows 10).

2. Select a path with a folder containing a single quote, e.g. 
C:\Users\xxxx\OneDrive - Queen's University Belfast\test

3. IPython console throws an error. If I copy and paste the command shown in the error message then either (i) escape the single quote or (ii) change the path string to being enclosed in double quotes, it seems to work--e.g.:
get_ipython().kernel.set_cwd(u'C:\\Users\\xxxx\\OneDrive - Queen\'s University Belfast\\test')
(N.b. there is a backslash before the single quote in "Queen's" in the line above--it seems to get stripped by the webpage "Queen\\'s")
OR
get_ipython().kernel.set_cwd(u"C:\\Users\\xxxx\\OneDrive - Queen's University Belfast\\test")

**What is the expected output? What do you see instead?**
  File "<ipython-input-4-523d9ca4caac>", line 1
    get_ipython().kernel.set_cwd(u'C:\\Users\\xxxx\\OneDrive - Queen's University Belfast\\test')
                                                                     ^
SyntaxError: invalid syntax

**Please provide any additional information below**



## Version and main components

* Spyder Version: 3.2.6 
* Python Version: 3.6.4
* Qt Versions: 5.6.2, PyQt5 5.6 on Windows

## Dependencies
```
pyflakes >=0.6.0 :  1.6.0 (OK)
pycodestyle >=2.3:  2.3.1 (OK)
pygments >=2.0   :  2.2.0 (OK)
pandas >=0.13.1  :  0.20.3 (OK)
numpy >=1.7      :  1.13.3 (OK)
sphinx >=0.6.6   :  1.6.3 (OK)
rope >=0.9.4     :  0.10.5 (OK)
jedi >=0.9.0     :  0.10.2 (OK)
nbconvert >=4.0  :  5.3.1 (OK)
sympy >=0.7.3    :  1.1.1 (OK)
cython >=0.21    :  0.26.1 (OK)
qtconsole >=4.2.0:  4.3.1 (OK)
IPython >=4.0    :  6.1.0 (OK)
pylint >=0.25    :  1.7.4 (OK)

```



Discussion:
Thanks for reporting. We'll fix this problem in a future release and sorry for the inconvenience in the meantime.

Resolving patch:
diff --git a/spyder/widgets/ipythonconsole/shell.py b/spyder/widgets/ipythonconsole/shell.py
--- a/spyder/widgets/ipythonconsole/shell.py
+++ b/spyder/widgets/ipythonconsole/shell.py
@@ -108,7 +108,7 @@ def set_cwd(self, dirname):
             dirname = dirname.replace(u"\\", u"\\\\")
 
         if not self.external_kernel:
-            code = u"get_ipython().kernel.set_cwd(u'{}')".format(dirname)
+            code = u"get_ipython().kernel.set_cwd(u'''{}''')".format(dirname)
             if self._reading:
                 self.kernel_client.input(u'!' + code)
             else:


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
@@ -318,6 +318,65 @@ def test_console_coloring(ipyconsole, qtbot):
     assert console_font_color.strip() == editor_font_color.strip()
 
 
+@pytest.mark.slow
+@flaky(max_runs=3)
+def test_set_cwd(ipyconsole, qtbot, tmpdir):
+    """Test kernel when changing cwd."""
+    # Wait until the window is fully up
+    shell = ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
+
+    # Issue 6451.
+    savetemp = shell._cwd
+    tempdir = to_text_string(tmpdir.mkdir("queen's"))
+    shell.set_cwd(tempdir)
+
+    # Get current directory.
+    with qtbot.waitSignal(shell.executed):
+        shell.execute("import os; cwd = os.getcwd()")
+
+    # Assert we get the assigned value correctly
+    assert shell.get_value('cwd') == tempdir
+
+    # Restore original.
+    shell.set_cwd(savetemp)
+
+
+@pytest.mark.slow
+@flaky(max_runs=3)
+def test_get_cwd(ipyconsole, qtbot, tmpdir):
+    """Test current working directory."""
+    # Wait until the window is fully up
+    shell = ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
+
+    # Issue 6451.
+    savetemp = shell._cwd
+    tempdir = to_text_string(tmpdir.mkdir("queen's"))
+    assert shell._cwd != tempdir
+
+    # Need to escape \ on Windows.
+    if os.name == 'nt':
+        tempdir = tempdir.replace(u"\\", u"\\\\")
+
+    # Change directory in the console.
+    with qtbot.waitSignal(shell.executed):
+        shell.execute(u"import os; os.chdir(u'''{}''')".format(tempdir))
+
+    # Ask for directory.
+    with qtbot.waitSignal(shell.sig_change_cwd):
+        shell.get_cwd()
+
+    if os.name == 'nt':
+        tempdir = tempdir.replace(u"\\\\", u"\\")
+
+    assert shell._cwd == tempdir
+
+    shell.set_cwd(savetemp)
+
+
 @pytest.mark.slow
 @flaky(max_runs=3)
 def test_get_env(ipyconsole, qtbot):