Repository: spyder-ide/spyder

Issue:
Project switching with recent projects menu fails to open correct project
## Description

### What steps will reproduce the problem?

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

Using the Recent Projects menu always reopens the last project opened.  This occurs even after a restart of Spyder.  It seems to occur regardless of the project selected from the menu, so doesn't seem immediately to be a corruption of the file where the recent projects list is stored.  

It is easily reproducible for me using the current state of the master branch, and has been for about a month.  I am not sure which PR introduced the problem for me at this time.



## Versions

* Spyder version: 4.0.0.dev0 
* Python version: 3.7.0
* Qt version: 5.9.6
* PyQt5 version: 5.9.2
* Operating System: Windows 10

### Dependencies

```
pygments >=2.0    :  2.2.0 (OK)
qdarkstyle >=2.6.4:  2.6.4 (OK)
sphinx >=0.6.6    :  2.0.0 (OK)
pyls >=0.19.0     :  0+unknown (OK)
nbconvert >=4.0   :  5.4.0 (OK)
pandas >=0.13.1   :  0.23.4 (OK)
numpy >=1.7       :  1.15.2 (OK)
sympy >=0.7.3     :  1.3 (OK)
cython >=0.21     :  0.28.5 (OK)
qtconsole >=4.2.0 :  4.4.2 (OK)
IPython >=4.0     :  7.0.1 (OK)
matplotlib >=2.0.0:  3.0.1 (OK)
pylint >=0.25     :  2.1.1 (OK)
```



Discussion:
Thanks for the report. I was just about to do it, what a coincidence!

I will fix this in a PR today and add a regression test for this.

Resolving patch:
diff --git a/spyder/plugins/projects/plugin.py b/spyder/plugins/projects/plugin.py
--- a/spyder/plugins/projects/plugin.py
+++ b/spyder/plugins/projects/plugin.py
@@ -186,7 +186,7 @@ def switch_to_plugin(self):
                 self.toggle_view_action.setChecked(True)
             self.visibility_changed(True)
 
-    #------ Public API ---------------------------------------------------------
+    # ------ Public API -------------------------------------------------------
     def setup_menu_actions(self):
         """Setup and update the menu actions."""
         self.recent_project_menu.clear()
@@ -195,15 +195,13 @@ def setup_menu_actions(self):
             for project in self.recent_projects:
                 if self.is_valid_project(project):
                     name = project.replace(get_home_dir(), '~')
-
-                    def slot():
-                        self.switch_to_plugin()
-                        self.open_project(path=project)
-
-                    action = create_action(self,
+                    action = create_action(
+                        self,
                         name,
-                        icon = ima.icon('project'),
-                        triggered=slot)
+                        icon=ima.icon('project'),
+                        triggered=(
+                            lambda _, p=project: self.open_project(path=p))
+                        )
                     self.recent_projects_actions.append(action)
                 else:
                     self.recent_projects.remove(project)


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
@@ -200,5 +200,36 @@ def test_set_get_project_filenames_when_switching(create_projects, tmpdir):
     assert projects.get_project_filenames() == opened_files
 
 
+def test_recent_projects_menu_action(projects, tmpdir):
+    """
+    Test that the actions of the submenu 'Recent Projects' in the 'Projects'
+    main menu are working as expected.
+
+    Regression test for Issue #8450.
+    """
+    recent_projects_len = len(projects.recent_projects)
+
+    # Create the directories.
+    path0 = to_text_string(tmpdir.mkdir('project0'))
+    path1 = to_text_string(tmpdir.mkdir('project1'))
+    path2 = to_text_string(tmpdir.mkdir('project2'))
+
+    # Open projects in path0, path1, and path2.
+    projects.open_project(path=path0)
+    projects.open_project(path=path1)
+    projects.open_project(path=path2)
+    assert (len(projects.recent_projects_actions) ==
+            recent_projects_len + 3 + 2)
+    assert projects.get_active_project().root_path == path2
+
+    # Trigger project1 in the list of Recent Projects actions.
+    projects.recent_projects_actions[1].trigger()
+    assert projects.get_active_project().root_path == path1
+
+    # Trigger project0 in the list of Recent Projects actions.
+    projects.recent_projects_actions[2].trigger()
+    assert projects.get_active_project().root_path == path0
+
+
 if __name__ == "__main__":
     pytest.main()