Repository: spyder-ide/spyder

Issue:
ValueError when closing project on USB stick
## Description

### What steps will reproduce the problem?

<!--- You can use Markdown here --->

1. Open project from USB stick with Spyder 3
2. Update to Spyder 4 beta
3. Try closing project. Results in an error.

### Traceback
```python-traceback
  File "C:\Users\jmgro\Anaconda3\lib\site-packages\spyder\plugins\projects\plugin.py", line 342, in close_project
    self.main.editor.get_open_filenames())
  File "C:\Users\jmgro\Anaconda3\lib\site-packages\spyder\plugins\projects\plugin.py", line 427, in set_project_filenames
    self.current_active_project.set_recent_files(recent_files)
  File "C:\Users\jmgro\Anaconda3\lib\site-packages\spyder\plugins\projects\api.py", line 76, in set_recent_files
    for recent_file in recent_files]
  File "C:\Users\jmgro\Anaconda3\lib\site-packages\spyder\plugins\projects\api.py", line 76, in <listcomp>
    for recent_file in recent_files]
  File "C:\Users\jmgro\Anaconda3\lib\ntpath.py", line 562, in relpath
    path_drive, start_drive))
ValueError: path is on mount 'C:', start on mount 'E:'
```

## Versions

* Spyder version: 4.0.0b4 
* Python version: 3.7.3
* Qt version: 5.9.6
* PyQt5 version: 5.9.2
* Operating System: Windows 10

### Dependencies

```
pygments >=2.0    :  2.4.2 (OK)
qdarkstyle >=2.6.4:  2.7 (OK)
sphinx >=0.6.6    :  2.1.2 (OK)
pyls >=0.27.0     :  0.28.0 (OK)
nbconvert >=4.0   :  5.5.0 (OK)
pandas >=0.13.1   :  0.24.2 (OK)
numpy >=1.7       :  1.16.4 (OK)
sympy >=0.7.3     :  1.4 (OK)
cython >=0.21     :  0.29.12 (OK)
qtconsole >=4.5.2 :  4.5.3 (OK)
IPython >=4.0     :  7.6.1 (OK)
matplotlib >=2.0.0:  3.1.0 (OK)
pylint >=0.25     :  2.3.1 (OK)
```



Discussion:
@goanpeca, please take a look at this one. I think this is caused because we're now using relative paths in our projects instead of absolute ones.
>I think this is caused because we're now using relative paths in our projects instead of absolute ones.

Yes, that is correct, will try to add a test for this then
I updated to beta 4.0.0b4 from 4.0.0b2 - and now I get this issue when opening a project folder - it's stored on a network drive. Here is the output from the error dialog:

 ```
 File "c:\program files (x86)\python365_64bit\lib\site-packages\spyder\plugins\projects\plugin.py", line 97, in <lambda>
    triggered=lambda v: self.open_project())
  File "c:\program files (x86)\python365_64bit\lib\site-packages\spyder\plugins\projects\plugin.py", line 319, in open_project
    self.main.editor.get_open_filenames())
  File "c:\program files (x86)\python365_64bit\lib\site-packages\spyder\plugins\projects\plugin.py", line 427, in set_project_filenames
    self.current_active_project.set_recent_files(recent_files)
  File "c:\program files (x86)\python365_64bit\lib\site-packages\spyder\plugins\projects\api.py", line 76, in set_recent_files
    for recent_file in recent_files]
  File "c:\program files (x86)\python365_64bit\lib\site-packages\spyder\plugins\projects\api.py", line 76, in <listcomp>
    for recent_file in recent_files]
  File "c:\program files (x86)\python365_64bit\lib\ntpath.py", line 586, in relpath
    path_drive, start_drive))
ValueError: path is on mount 'C:', start on mount '\\\\networkDrive\\users'
```

That last line appears to indicate that it is an issue related to the URI file path. If I try to explicitly use the drive letter instead (in the open dialog), I still get the same error.

I'm on Windows 10.
```

pygments >=2.0    :  2.4.0 (OK)
qdarkstyle >=2.6.4:  2.7 (OK)
sphinx >=0.6.6    :  2.0.1 (OK)
pyls >=0.27.0     :  v0.28.1 (OK)
nbconvert >=4.0   :  5.5.0 (OK)
pandas >=0.13.1   :  0.24.2 (OK)
numpy >=1.7       :  1.16.3 (OK)
sympy >=0.7.3     :  None (NOK)
cython >=0.21     :  None (NOK)
qtconsole >=4.5.2 :  4.5.3 (OK)
IPython >=4.0     :  7.5.0 (OK)
matplotlib >=2.0.0:  3.1.0 (OK)
pylint >=0.25     :  2.3.1 (OK)
```

@jasonmaskell thanks for the information. Working on this!

Resolving patch:
diff --git a/spyder/plugins/projects/projecttypes/__init__.py b/spyder/plugins/projects/projecttypes/__init__.py
--- a/spyder/plugins/projects/projecttypes/__init__.py
+++ b/spyder/plugins/projects/projecttypes/__init__.py
@@ -61,12 +61,16 @@ def set_option(self, section, option, value):
 
     def set_recent_files(self, recent_files):
         """Set a list of files opened by the project."""
-        for recent_file in recent_files[:]:
-            if not os.path.isfile(recent_file):
-                recent_files.remove(recent_file)
-        recent_files = [os.path.relpath(recent_file, self.root_path)
-                        for recent_file in recent_files]
-        files = list(OrderedDict.fromkeys(recent_files))
+        processed_recent_files = []
+        for recent_file in recent_files:
+            if os.path.isfile(recent_file):
+                try:
+                    relative_recent_file = os.path.relpath(
+                        recent_file, self.root_path)
+                    processed_recent_files.append(relative_recent_file)
+                except ValueError:
+                    processed_recent_files.append(recent_file)
+        files = list(OrderedDict.fromkeys(processed_recent_files))
         self.config.set('main', 'recent_files', files)
 
     def get_recent_files(self):
@@ -75,7 +79,6 @@ def get_recent_files(self):
         recent_files = [recent_file if os.path.isabs(recent_file)
                         else os.path.join(self.root_path, recent_file)
                         for recent_file in recent_files]
-
         for recent_file in recent_files[:]:
             if not os.path.isfile(recent_file):
                 recent_files.remove(recent_file)


Test patch:
diff --git a/spyder/plugins/projects/tests/test_plugin.py b/spyder/plugins/projects/tests/test_plugin.py
--- a/spyder/plugins/projects/tests/test_plugin.py
+++ b/spyder/plugins/projects/tests/test_plugin.py
@@ -175,18 +175,52 @@ def test_open_project_uses_visible_config(projects, tmpdir, value):
     assert projects.dockwidget.isVisible() == value
 
 
-def test_set_get_project_filenames_when_closing(create_projects, tmpdir):
+def test_set_get_project_filenames_when_closing_no_files(create_projects,
+                                                         tmpdir):
     """
     Test that the currently opened files in the Editor are saved and loaded
     correctly to and from the project config when the project is closed and
     then reopened.
 
-    Regression test for spyder-ide/spyder#8375.
+    Regression test for spyder-ide/spyder#10045.
     """
     path = to_text_string(tmpdir.mkdir('project1'))
+    # Create paths but no actual files
     opened_files = [os.path.join(path, file)
                     for file in ['file1', 'file2', 'file3']]
 
+    # Create the projects plugin without creating files.
+    projects = create_projects(path, opened_files)
+    assert projects.get_project_filenames() == []
+
+    # Close and reopen the project.
+    projects.close_project()
+    projects.open_project(path=path)
+
+    # Check the original list isn't empty (was not changed)
+    assert opened_files
+
+
+def test_set_get_project_filenames_when_closing(create_projects, tmpdir):
+    """
+    Test that the currently opened files in the Editor are saved and loaded
+    correctly to and from the project config when the project is closed and
+    then reopened.
+
+    Regression test for spyder-ide/spyder#8375.
+    Updated for spyder-ide/spyder#10045.
+    """
+    # Setup tmp dir and files
+    dir_object = tmpdir.mkdir('project1')
+    path = to_text_string(dir_object)
+
+    # Needed to actually create the files
+    opened_files = []
+    for file in ['file1', 'file2', 'file3']:
+        file_object = dir_object.join(file)
+        file_object.write(file)
+        opened_files.append(to_text_string(file_object))
+
     # Create the projects plugin.
     projects = create_projects(path, opened_files)
     assert projects.get_project_filenames() == []
@@ -201,11 +235,19 @@ def test_set_get_project_filenames_when_switching(create_projects, tmpdir):
     """
     Test that files in the Editor are loaded and saved correctly when
     switching projects.
+
+    Updated for spyder-ide/spyder#10045.
     """
-    path1 = to_text_string(tmpdir.mkdir('project1'))
+    dir_object1 = tmpdir.mkdir('project1')
+    path1 = to_text_string(dir_object1)
     path2 = to_text_string(tmpdir.mkdir('project2'))
-    opened_files = [os.path.join(path1, file)
-                    for file in ['file1', 'file2', 'file3']]
+
+    # Needed to actually create the files
+    opened_files = []
+    for file in ['file1', 'file2', 'file3']:
+        file_object = dir_object1.join(file)
+        file_object.write(file)
+        opened_files.append(to_text_string(file_object))
 
     # Create the projects plugin.
     projects = create_projects(path1, opened_files)