Repository: spyder-ide/spyder
Pull request: PR: Handle paths for recent files on a different mount than the project root path
<!--- Make sure to read the Contributing Guidelines:                   --->
<!--- https://github.com/spyder-ide/spyder/blob/master/CONTRIBUTING.md --->
<!--- and follow PEP 8, PEP 257 and Spyder's code style:               --->
<!--- https://github.com/spyder-ide/spyder/wiki/Dev:-Coding-Style      --->

## Description of Changes


* [ ] Wrote at least one-line docstrings (for any new functions)
* [x] Added unit test(s) covering the changes (if testable)
<!--- Remember that an image/animation is worth a thousand words! --->
* [ ] Included a screenshot or animation (if affecting the UI, see [Licecap](https://www.cockos.com/licecap/))


<!--- Explain what you've done and why --->

Handle recent files saving in cases where paths doesn't have a relative path to the project root path


### Issue(s) Resolved

<!--- List the issue(s) below, in the form "Fixes #1234"; one per line --->

Fixes #10045


### Affirmation

By submitting this Pull Request or typing my (user)name below,
I affirm the [Developer Certificate of Origin](https://developercertificate.org)
with respect to all commits and content included in this PR,
and understand I am releasing the same under Spyder's MIT (Expat) license.

<!--- TYPE YOUR USER/NAME AFTER THE FOLLOWING: --->
I certify the above statement is true and correct: dalthviz

<!--- Thanks for your help making Spyder better for everyone! --->


Problem statement:
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)
```

Hints from issue 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!

Commit message: Projects: Remove file validation for test

Patch to review:
diff --git a/spyder/plugins/projects/projecttypes/__init__.py b/spyder/plugins/projects/projecttypes/__init__.py
index a2864c01054..70a8fee66ca 100644
--- a/spyder/plugins/projects/projecttypes/__init__.py
+++ b/spyder/plugins/projects/projecttypes/__init__.py
@@ -61,12 +61,15 @@ 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:
+            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,11 +78,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)
-
         return list(OrderedDict.fromkeys(recent_files))
 
 


Code review comments:
diff_hunk: @@ -75,11 +78,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)
-
path: spyder/plugins/projects/projecttypes/__init__.py
text: @user1:
Why did you remove these lines? Without these lines `get_recent_files` does nothing.

@user2:
@author ?

@author:
I made this change (removing the validation of the path being a file) to check the tests (`test_set_get_project_filenames_when_closing` and `test_set_get_project_filenames_when_switching`). Seems like the existing tests were passing because of the mutability property of a list (the `set_recent_files` method was changing directly the `opened_files` list that at the end is the object passed by parameter, so the [assert](https://github.com/spyder-ide/spyder/blob/aafb1c21f6e8c58997e43ccfc8cf8d06e2feb9c6/spyder/plugins/projects/tests/test_plugin.py#L197) was checking the return with a list changed by the `set_recent_files` method (the recent files in the tests always were an empty list, since the paths we are testing here aren't actually created).

However, probably we need here to change the tests to create the files and add again the check for the path being a file. So this is not ready yet :)


@user1:
> So this is not ready yet :)

@author, then please don't forget to add WIP to the PR title.

@author:
Yep :+1: