Repository: spyder-ide/spyder

Issue:
UnicodeDecodeError when moving a file with Project Explorer
## UnicodeDecodeError when moving an opened file with _Project Explorer_

Possibly due to old version?

**What steps will reproduce the problem?**

1. Created a file `chess.py` and a folder `tmp` in the same folder
2. Open `chess.py` in Spyder editor
3. Move `chess.py` in `tmp` folder with the _Project Explorer_ bar

**What is the expected output? What do you see instead?**
Expected output: nothing, correctly moved file.

Effective output: the error trace (below).

**Please provide any additional information below**

  File "%PYTHON%\lib\site-packages\spyder\widgets\explorer.py", line 710, in move
    ) % (basename, to_text_string(error)))
  File "%PYTHON%\Python\lib\site-packages\spyder\py3compat.py", line 123, in to_text_string
    return unicode(obj)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 49: ordinal not in range(128)


## Version and main components

* Spyder Version: 3.2.3 
* Python Version: 2.7.12
* Qt Versions: 5.6.2, PyQt5 5.6 on Windows

## Dependencies
```
pyflakes >=0.5.0  :  1.3.0 (OK)
pycodestyle >=2.3 :  2.3.1 (OK)
pygments >=2.0    :  2.1.3 (OK)
pandas >=0.13.1   :  0.18.1 (OK)
numpy >=1.7       :  1.11.1 (OK)
sphinx >=0.6.6    :  1.4.6 (OK)
rope >=0.9.4      :  0.9.4 (OK)
jedi >=0.9.0      :  0.9.0 (OK)
nbconvert >=4.0   :  4.2.0 (OK)
sympy >=0.7.3     :  1.0 (OK)
cython >=0.21     :  0.24.1 (OK)
qtconsole >=4.2.0 :  4.2.1 (OK)
IPython >=4.0;<6.0:  5.1.0 (OK)
pylint >=0.25     :  1.5.4 (OK)

```



Discussion:
What's the full path to `chess.py` before moving? Does it contain any non-ASCII characters?
Note: Works the following configuration. (also with non-ASCII chars in the path to `chess.py`).

## Version and main components

* Spyder Version: 3.2.5.dev0 ed53e29
* Python Version: 2.7.14
* Qt Versions: 5.6.2, PyQt5 5.6 on Windows

## Dependencies
```
pyflakes >=0.5.0  :  1.6.0 (OK)
pycodestyle >=2.3 :  2.3.1 (OK)
pygments >=2.0    :  2.2.0 (OK)
pandas >=0.13.1   :  None (NOK)
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     :  None (NOK)
cython >=0.21     :  None (NOK)
qtconsole >=4.2.0 :  4.3.1 (OK)
IPython >=4.0;<6.0:  5.4.1 (OK)
pylint >=0.25     :  1.7.4 (OK)
Try using python3, python2 could throw weird issues when working with unicode
@rlaverde my whole project is fully written in Python 2. I can not translate every single class to Python3....
@salvioner, what's the name of the folder you tried to move `chess.py` to?
I'm moving from
`C:\Projects\PyBoardChess`
to
`C:\Projects\PyBoardChess\tmp`

@ccordoba12 sry for late answer, i haven't logged in in a while
@dalthviz, please take a look at this one. If you're unable to reproduce it, add a test for it.

Resolving patch:
diff --git a/spyder/widgets/explorer.py b/spyder/widgets/explorer.py
--- a/spyder/widgets/explorer.py
+++ b/spyder/widgets/explorer.py
@@ -694,14 +694,18 @@ def rename(self, fnames=None):
             self.rename_file(fname)
 
     @Slot()
-    def move(self, fnames=None):
+    def move(self, fnames=None, directory=None):
         """Move files/directories"""
         if fnames is None:
             fnames = self.get_selected_filenames()
         orig = fixpath(osp.dirname(fnames[0]))
         while True:
             self.parent_widget.redirect_stdio.emit(False)
-            folder = getexistingdirectory(self, _("Select directory"), orig)
+            if directory is None:
+                folder = getexistingdirectory(self, _("Select directory"),
+                                              orig)
+            else:
+                folder = directory
             self.parent_widget.redirect_stdio.emit(True)
             if folder:
                 folder = fixpath(folder)
diff --git a/spyder/widgets/projects/explorer.py b/spyder/widgets/projects/explorer.py
--- a/spyder/widgets/projects/explorer.py
+++ b/spyder/widgets/projects/explorer.py
@@ -169,6 +169,7 @@ def delete(self, fnames=None):
 
 class ProjectExplorerWidget(QWidget):
     """Project Explorer"""
+    redirect_stdio = Signal(bool)
     sig_option_changed = Signal(str, object)
     sig_open_file = Signal(str)
 
@@ -261,13 +262,17 @@ def delete_project(self):
 # Tests
 #==============================================================================
 class ProjectExplorerTest(QWidget):
-    def __init__(self):
+    def __init__(self, directory=None):
         QWidget.__init__(self)
         vlayout = QVBoxLayout()
         self.setLayout(vlayout)
 
-        self.explorer = ProjectExplorerWidget(None, show_all=True)
-        self.explorer.setup_project(osp.dirname(osp.abspath(__file__)))
+        self.explorer = ProjectExplorerWidget(self, show_all=True)
+        if directory is not None:
+            self.directory = directory
+        else:
+            self.directory = osp.dirname(osp.abspath(__file__))
+        self.explorer.setup_project(self.directory)
         vlayout.addWidget(self.explorer)
 
         hlayout1 = QHBoxLayout()


Test patch:
diff --git a/spyder/widgets/projects/tests/test_project_explorer.py b/spyder/widgets/projects/tests/test_project_explorer.py
--- a/spyder/widgets/projects/tests/test_project_explorer.py
+++ b/spyder/widgets/projects/tests/test_project_explorer.py
@@ -7,26 +7,61 @@
 """
 Tests for explorer.py
 """
+# Standard imports
+import os
+import os.path as osp
 
 # Test library imports
 import pytest
 
 # Local imports
 from spyder.widgets.projects.explorer import ProjectExplorerTest
+from spyder.py3compat import to_text_string
+
 
 @pytest.fixture
-def setup_projects_explorer(qtbot):
-    """Set up ProjectExplorerWidgetTest."""
-    project_explorer = ProjectExplorerTest()
+def project_explorer(qtbot, request, tmpdir):
+    """Setup Project Explorer widget."""
+    directory = request.node.get_marker('change_directory')
+    if directory:
+        project_dir = to_text_string(tmpdir.mkdir('project'))
+    else:
+        project_dir = None
+    project_explorer = ProjectExplorerTest(directory=project_dir)
     qtbot.addWidget(project_explorer)
     return project_explorer
 
-def test_project_explorer(qtbot):
+
+@pytest.mark.change_directory
+def test_change_directory_in_project_explorer(project_explorer, qtbot):
+    """Test changing a file from directory in the Project explorer."""
+    # Create project
+    project = project_explorer
+    project_dir = project.directory
+
+    # Create a temp project directory and file
+    project_dir_tmp = osp.join(project_dir, u'測試')
+    project_file = osp.join(project_dir, 'script.py')
+
+    # Create an empty file in the project dir
+    os.mkdir(project_dir_tmp)
+    open(project_file, 'w').close()
+
+    # Move Python file
+    project.explorer.treewidget.move(
+                            fnames=[osp.join(project_dir, 'script.py')],
+                            directory=project_dir_tmp)
+
+    # Assert content was moved
+    assert osp.isfile(osp.join(project_dir_tmp, 'script.py'))
+
+
+def test_project_explorer(project_explorer, qtbot):
     """Run project explorer."""
-    project_explorer = setup_projects_explorer(qtbot)
-    project_explorer.resize(250, 480)
-    project_explorer.show()
-    assert project_explorer
+    project = project_explorer
+    project.resize(250, 480)
+    project.show()
+    assert project
 
 
 if __name__ == "__main__":