Repository: spyder-ide/spyder
Pull request: PR: Fix 'run file' project explorer action and add test for it
<!--- 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 --->

Add missing parameter `console_namespace` to run a file from the Project Explorer. Add a test for the action.


### Issue(s) Resolved

<!--- List the issue(s) below, in the form "Fixes #1234"; one per line --->

Fixes #10590 


### 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:
Crash when trying to run a Python file in a project
## Description

### What steps will reproduce the problem?

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

- right click on a python file in the left pane
- choose "run" from the context menu

> issue reporter pops up

### Traceback
```python-traceback
  File "/home/sum/.pyenv/versions/3.8-dev/lib/python3.8/site-packages/spyder/plugins/projects/plugin.py", line 148, in <lambda>
    ipyconsole.run_script(fname, osp.dirname(fname), '', False, False,
TypeError: run_script() missing 1 required positional argument: 'console_namespace'
```

## Versions

* Spyder version: 4.0.0rc1 
* Python version: 3.8.0+
* Qt version: 5.12.4
* PyQt5 version: 5.12.3
* Operating System: Linux 4.19.80-1-MANJARO

### Dependencies

```
cloudpickle >=0.5.0          :  1.2.2 (OK)
pygments >=2.0               :  2.4.2 (OK)
qtconsole >=4.5.5            :  4.5.5 (OK)
nbconvert >=4.0              :  5.6.1 (OK)
sphinx >=0.6.6               :  2.2.1 (OK)
pylint >=0.25                :  2.4.3 (OK)
psutil >=0.3                 :  5.6.3 (OK)
qtawesome >=0.5.7            :  0.6.0 (OK)
qtpy >=1.5.0                 :  1.9.0 (OK)
pickleshare >=0.4            :  0.7.5 (OK)
zmq >=17                     :  18.1.0 (OK)
chardet >=2.0.0              :  3.0.4 (OK)
numpydoc >=0.6.0             :  0.9.1 (OK)
spyder_kernels >=1.7.0;<2.0.0:  1.7.0 (OK)
qdarkstyle >=2.7             :  2.7 (OK)
atomicwrites >=1.2.0         :  1.3.0 (OK)
diff_match_patch >=20181111  :  20181111 (OK)
watchdog                     :  None (OK)
keyring                      :  None (OK)
pexpect >=4.4.0              :  4.7.0 (OK)
pympler                      :  None (OK)
sympy >=0.7.3                :  None (NOK)
cython >=0.21                :  None (NOK)
IPython >=4.0                :  7.9.0 (OK)
matplotlib >=2.0.0           :  None (NOK)
pandas >=0.13.1              :  None (NOK)
numpy >=1.7                  :  None (NOK)
scipy >=0.17.0               :  None (NOK)
pyls >=0.29.3;<0.30.0        :  0.29.3 (OK)
xdg >=0.26                   :  0.26 (OK)
```

Hints from issue discussion:
@dalthviz, please take a look at this one and add a test for it.

Commit message: Projects: Fix run file action and add test for it

Patch to review:
diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py
index 631ac9b53ce..f67730aad0c 100644
--- a/spyder/app/tests/test_mainwindow.py
+++ b/spyder/app/tests/test_mainwindow.py
@@ -931,6 +931,62 @@ def test_open_notebooks_from_project_explorer(main_window, qtbot, tmpdir):
     projects.close_project()
 
 
+@pytest.mark.slow
+@flaky(max_runs=3)
+def test_runfile_from_project_explorer(main_window, qtbot, tmpdir):
+    """Test that file are run from the Project explorer."""
+    projects = main_window.projects
+    editorstack = main_window.editor.get_current_editorstack()
+
+    # Create a temp project directory
+    project_dir = to_text_string(tmpdir.mkdir('test'))
+
+    # Create an empty file in the project dir
+    test_file = osp.join(LOCATION, 'script.py')
+    shutil.copy(test_file, osp.join(project_dir, 'script.py'))
+
+    # Create project
+    with qtbot.waitSignal(projects.sig_project_loaded):
+        projects._create_project(project_dir)
+
+    # Select notebook in the project explorer
+    idx = projects.explorer.treewidget.get_index('script.py')
+    projects.explorer.treewidget.setCurrentIndex(idx)
+
+    # Prese Enter there
+    qtbot.keyClick(projects.explorer.treewidget, Qt.Key_Enter)
+
+    # Assert that the file was open
+    assert 'script.py' in editorstack.get_current_filename()
+
+    # Wait until the window is fully up
+    shell = main_window.ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
+
+    # Run Python file
+    projects.explorer.treewidget.run([osp.join(project_dir, 'script.py')])
+
+    # Wait until the new console is fully up
+    shell = main_window.ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
+
+    # Wait until all objects have appeared in the variable explorer
+    nsb = main_window.variableexplorer.get_focus_widget()
+    qtbot.waitUntil(lambda: nsb.editor.source_model.rowCount() == 4,
+                    timeout=EVAL_TIMEOUT)
+
+    # Check variables value
+    assert shell.get_value('a') == 10
+    assert shell.get_value('s') == "Z:\\escape\\test\\string\n"
+    assert shell.get_value('li') == [1, 2, 3]
+    assert_array_equal(shell.get_value('arr'), np.array([1, 2, 3]))
+
+    # Close project
+    projects.close_project()
+
+
 @pytest.mark.slow
 @flaky(max_runs=3)
 @pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows")
diff --git a/spyder/plugins/projects/plugin.py b/spyder/plugins/projects/plugin.py
index a1a956380e0..f01f6d6170a 100644
--- a/spyder/plugins/projects/plugin.py
+++ b/spyder/plugins/projects/plugin.py
@@ -146,7 +146,7 @@ def register_plugin(self):
         treewidget.sig_run.connect(
             lambda fname:
             ipyconsole.run_script(fname, osp.dirname(fname), '', False, False,
-                                  False, True))
+                                  False, True, False))
 
         # New project connections. Order matters!
         self.sig_project_loaded.connect(


Code review comments:
diff_hunk: @@ -931,6 +931,62 @@ def test_open_notebooks_from_project_explorer(main_window, qtbot, tmpdir):
     projects.close_project()
 
 
+@pytest.mark.slow
+@flaky(max_runs=3)
+def test_runfile_from_project_explorer(main_window, qtbot, tmpdir):
+    """Test that file are run from the Project explorer."""
+    projects = main_window.projects
+    editorstack = main_window.editor.get_current_editorstack()
+
+    # Create a temp project directory
+    project_dir = to_text_string(tmpdir.mkdir('test'))
+
+    # Create an empty file in the project dir
+    test_file = osp.join(LOCATION, 'script.py')
+    shutil.copy(test_file, osp.join(project_dir, 'script.py'))
+
+    # Create project
+    with qtbot.waitSignal(projects.sig_project_loaded):
+        projects._create_project(project_dir)
+
+    # Select notebook in the project explorer
+    idx = projects.explorer.treewidget.get_index('script.py')
+    projects.explorer.treewidget.setCurrentIndex(idx)
+
+    # Prese Enter there
path: spyder/app/tests/test_mainwindow.py
text: @user1:
Prese -> Press

diff_hunk: @@ -931,6 +931,62 @@ def test_open_notebooks_from_project_explorer(main_window, qtbot, tmpdir):
     projects.close_project()
 
 
+@pytest.mark.slow
+@flaky(max_runs=3)
+def test_runfile_from_project_explorer(main_window, qtbot, tmpdir):
+    """Test that file are run from the Project explorer."""
+    projects = main_window.projects
+    editorstack = main_window.editor.get_current_editorstack()
+
+    # Create a temp project directory
+    project_dir = to_text_string(tmpdir.mkdir('test'))
+
+    # Create an empty file in the project dir
+    test_file = osp.join(LOCATION, 'script.py')
+    shutil.copy(test_file, osp.join(project_dir, 'script.py'))
+
+    # Create project
+    with qtbot.waitSignal(projects.sig_project_loaded):
+        projects._create_project(project_dir)
+
+    # Select notebook in the project explorer
+    idx = projects.explorer.treewidget.get_index('script.py')
+    projects.explorer.treewidget.setCurrentIndex(idx)
+
+    # Prese Enter there
+    qtbot.keyClick(projects.explorer.treewidget, Qt.Key_Enter)
+
+    # Assert that the file was open
+    assert 'script.py' in editorstack.get_current_filename()
+
+    # Wait until the window is fully up
+    shell = main_window.ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
path: spyder/app/tests/test_mainwindow.py
text: @user1:
I don't think waiting here is necessary because files from the Project explorer are run in a dedicated console.

diff_hunk: @@ -931,6 +931,62 @@ def test_open_notebooks_from_project_explorer(main_window, qtbot, tmpdir):
     projects.close_project()
 
 
+@pytest.mark.slow
+@flaky(max_runs=3)
+def test_runfile_from_project_explorer(main_window, qtbot, tmpdir):
+    """Test that file are run from the Project explorer."""
+    projects = main_window.projects
+    editorstack = main_window.editor.get_current_editorstack()
+
+    # Create a temp project directory
+    project_dir = to_text_string(tmpdir.mkdir('test'))
+
+    # Create an empty file in the project dir
+    test_file = osp.join(LOCATION, 'script.py')
+    shutil.copy(test_file, osp.join(project_dir, 'script.py'))
+
+    # Create project
+    with qtbot.waitSignal(projects.sig_project_loaded):
+        projects._create_project(project_dir)
+
+    # Select notebook in the project explorer
path: spyder/app/tests/test_mainwindow.py
text: @user1:
notebook -> file