Repository: spyder-ide/spyder

Issue:
Startup run code of IPython is not working when using projects
## Description

### What steps will reproduce the problem?

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

Hello.

This promblem is similar to #16748.
This issue is also occurring in 5.x branch.

Thank you.



## Versions

* Spyder version: 5.4.0.dev0 30e09f8ee
* Python version: 3.9.12
* Qt version: 5.12.9
* PyQt5 version: 5.12.3
* Operating System: Linux 5.4.0-110-generic

### Dependencies

```
# Mandatory:
atomicwrites >=1.2.0                  :  1.4.0 (OK)
chardet >=2.0.0                       :  4.0.0 (OK)
cloudpickle >=0.5.0                   :  2.0.0 (OK)
cookiecutter >=1.6.0                  :  1.7.3 (OK)
diff_match_patch >=20181111           :  20200713 (OK)
intervaltree >=3.0.2                  :  3.1.0 (OK)
IPython >=7.31.1;<8.0.0               :  7.33.0 (OK)
jedi >=0.17.2;<0.19.0                 :  0.18.1 (OK)
jellyfish >=0.7                       :  0.8.2 (OK)
jsonschema >=3.2.0                    :  4.4.0 (OK)
keyring >=17.0.0                      :  23.4.0 (OK)
nbconvert >=4.0                       :  6.4.4 (OK)
numpydoc >=0.6.0                      :  1.2 (OK)
parso >=0.7.0;<0.9.0                  :  0.8.3 (OK)
pexpect >=4.4.0                       :  4.8.0 (OK)
pickleshare >=0.4                     :  0.7.5 (OK)
psutil >=5.3                          :  5.8.0 (OK)
pygments >=2.0                        :  2.11.2 (OK)
pylint >=2.5.0                        :  2.9.6 (OK)
pyls_spyder >=0.4.0                   :  0.4.0 (OK)
pylsp >=1.4.1;<1.5.0                  :  1.4.1 (OK)
pylsp_black >=1.2.0                   :  1.2.1 (OK)
qdarkstyle >=3.0.2;<3.1.0             :  3.0.3 (OK)
qstylizer >=0.1.10                    :  0.1.10 (OK)
qtawesome >=1.0.2                     :  1.0.3 (OK)
qtconsole >=5.3.0;<5.4.0              :  5.4.0.dev0 (OK)
qtpy >=2.1.0                          :  2.1.0 (OK)
rtree >=0.9.7                         :  0.9.7 (OK)
setuptools >=49.6.0                   :  59.5.0 (OK)
sphinx >=0.6.6                        :  4.4.0 (OK)
spyder_kernels >=2.3.0;<2.4.0         :  2.4.0.dev0 (OK)
textdistance >=4.2.0                  :  4.2.1 (OK)
three_merge >=0.1.1                   :  0.1.1 (OK)
watchdog >=0.10.3                     :  2.1.6 (OK)
xdg >=0.26                            :  0.27 (OK)
zmq >=17                              :  22.3.0 (OK)

# Optional:
cython >=0.21                         :  0.29.28 (OK)
matplotlib >=3.0.0                    :  3.5.1 (OK)
numpy >=1.7                           :  1.21.5 (OK)
pandas >=1.1.1                        :  1.4.2 (OK)
scipy >=0.17.0                        :  1.7.3 (OK)
sympy >=0.7.3                         :  1.10.1 (OK)

# Spyder plugins:
spyder_okvim.spyder.plugin 0.0.1.dev0 :  0.0.1-dev0 (OK)
```



Discussion:
Hi @ok97465 thank you for opening a new issue! We will check this in a future release :+1:

Also I noted that seems like you are using a version of the `spyder-vim` plugin? Could you be interested on submitting a PR to the `spyder-vim` repo so the changes you did to make it compatible with Spyder 5 are there if that is the case? Let us know!
Just in case, checked locally from source setting the preference with and without an active project but I wasn't able to reproduce this.

I did the test setting as the preference something simple like `import os` and `import os.path as osp` though. Any other info to replicate this in our side is greatly appreciated @ok97465 
> Also I noted that seems like you are using a version of the spyder-vim plugin? Could you be interested on submitting a PR to the spyder-vim repo so the changes you did to make it compatible with Spyder 5 are there if that is the case? Let us know!

I have created a personal repository([okvim](https://github.com/ok97465/spyder_okvim)) for using vim key on Spyder. Seems like too many changes would be needed to apply this to spyder-vim. I'm sorry.

> I did the test setting as the preference something simple like import os and import os.path as osp though. Any other info to replicate this in our side is greatly appreciated @ok97465

If the startup command is unrelated to the project folder like "import os", it works well.
[#16748](https://github.com/spyder-ide/spyder/issues/16748) But If the startup command loads file in the project folder, it does not work properly only when spyder is started. 
>I have created a personal repository([okvim](https://github.com/ok97465/spyder_okvim)) for using vim key on Spyder. Seems like too many changes would be needed to apply this to spyder-vim. I'm sorry.

Oh I see, I was thinking that you could do a PR replaicing what is currently in the repo with your version (just changing the entrypoint and other related names to use `spyder-vim/SpyderVim/spyder_vim`) and maybe help us maintaing the plugin from that repo but if that not feasible, could be okay if we mention your repo in the issues from the `spyder-vim` repo so users that could be interested in using the plugin with Spyder 5 could check your repo out?

>If the startup command is unrelated to the project folder like "import os", it works well.
https://github.com/spyder-ide/spyder/issues/16748 But If the startup command loads file in the project folder, it does not work properly only when spyder is started.

Does your custom script to run at start has relative imports? Maybe the console is not getting set the project path before running the start script and then is being unable to run it? Will try to check a little bit more to replicate it :+1:

Thanks for the new info @ok97465 !
> Oh I see, I was thinking that you could do a PR replaicing what is currently in the repo with your version (just changing the entrypoint and other related names to use spyder-vim/SpyderVim/spyder_vim) and maybe help us maintaing the plugin from that repo but if that not feasible, could be okay if we mention your repo in the issues from the spyder-vim repo so users that could be interested in using the plugin with Spyder 5 could check your repo out?

My vim has a completely different structure from the spyder vim, so I have to create and upload all the new files. If I do that, my vim has an intermittent error and the bug is often reported on Spyder-ide, which will annoy you. I think it would be better to make the spyder-vim compatible with the spyder 5, and I will try it within next month.

> Does your custom script to run at start has relative imports? Maybe the console is not getting set the project path before running the start script and then is being unable to run it? Will try to check a little bit more to replicate it 

The initial files(import_in_console.py) within the project are as follows:
```python
from numpy import pi
```

Preference > IPython Console > Startup > Run code is below:
```python
from import_in_console import *
```

![Peek 2022-05-22 07-13](https://user-images.githubusercontent.com/22970578/169670657-04805a1c-ebfd-4576-bc37-857b2528404f.gif)
Thanks for the step by step description @ok97465 ! I was able to reproduce this :+1: Seems like the console when opening a project is not getting the correct working directory set (I'm getting for the first console open with the project my home directory instead):

![imagen](https://user-images.githubusercontent.com/16781833/169879222-2775dfb7-dc4d-48a8-b35d-68de49a6a094.png)

Checking the working directory options I'm seeing this:

![imagen](https://user-images.githubusercontent.com/16781833/169879454-ffd722ba-0e84-4937-ae86-ef767d0ad0ea.png)

 

Resolving patch:
diff --git a/spyder/plugins/ipythonconsole/widgets/main_widget.py b/spyder/plugins/ipythonconsole/widgets/main_widget.py
--- a/spyder/plugins/ipythonconsole/widgets/main_widget.py
+++ b/spyder/plugins/ipythonconsole/widgets/main_widget.py
@@ -1542,14 +1542,15 @@ def get_current_shellwidget(self):
     @Slot(bool, bool)
     @Slot(bool, str, bool)
     def create_new_client(self, give_focus=True, filename='', is_cython=False,
-                          is_pylab=False, is_sympy=False, given_name=None):
+                          is_pylab=False, is_sympy=False, given_name=None,
+                          cache=True):
         """Create a new client"""
         self.master_clients += 1
         client_id = dict(int_id=str(self.master_clients),
                          str_id='A')
         std_dir = self._test_dir if self._test_dir else None
         cf, km, kc, stderr_obj, stdout_obj = self.get_new_kernel(
-            is_cython, is_pylab, is_sympy, std_dir=std_dir)
+            is_cython, is_pylab, is_sympy, std_dir=std_dir, cache=cache)
 
         if cf is not None:
             fault_obj = StdFile(cf, '.fault', std_dir)
@@ -1656,7 +1657,7 @@ def create_client_for_kernel(self):
                                            password)
 
     def get_new_kernel(self, is_cython=False, is_pylab=False,
-                       is_sympy=False, std_dir=None):
+                       is_sympy=False, std_dir=None, cache=True):
         """Get a new kernel, and cache one for next time."""
         # Cache another kernel for next time.
         kernel_spec = self.create_kernel_spec(
@@ -1666,8 +1667,9 @@ def get_new_kernel(self, is_cython=False, is_pylab=False,
         )
 
         new_kernel = self.create_new_kernel(kernel_spec, std_dir)
-        if new_kernel[2] is None:
-            # error
+
+        if new_kernel[2] is None or not cache:
+            # error or remove/don't use cache if requested
             self.close_cached_kernel()
             return new_kernel
 
@@ -1991,7 +1993,7 @@ def restart(self):
         for i in range(len(self.clients)):
             client = self.clients[-1]
             self.close_client(client=client, ask_recursive=False)
-        self.create_new_client(give_focus=False)
+        self.create_new_client(give_focus=False, cache=False)
         self.create_new_client_if_empty = True
 
     def current_client_inspect_object(self):


Test patch:
diff --git a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
--- a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
+++ b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
@@ -2313,5 +2313,52 @@ def get_cwd_of_new_client():
     assert get_cwd_of_new_client() == fixed_dir
 
 
+def test_startup_run_lines_project_directory(ipyconsole, qtbot, tmpdir):
+    """
+    Test 'startup/run_lines' config works with code from an active project.
+    """
+    project = tmpdir.mkdir('ipyconsole_project_test')
+    project_dir = str(project)
+    project_script = project.join('project_script.py')
+    project_script.write('from numpy import pi')
+
+    # Config spyder_pythonpath with the project path
+    ipyconsole.set_conf(
+        'spyder_pythonpath',
+        [project_dir],
+        section='main')
+
+    # Config console with project path
+    ipyconsole.set_conf(
+        'startup/run_lines',
+        'from project_script import *',
+        section='ipython_console')
+    ipyconsole.set_conf(
+        'console/use_project_or_home_directory',
+        True,
+        section='workingdir',
+    )
+    ipyconsole.get_widget().update_active_project_path(project_dir)
+
+    # Restart console
+    ipyconsole.restart()
+
+    # Check that the script was imnported
+    shell = ipyconsole.get_current_shellwidget()
+    qtbot.waitUntil(lambda: shell._prompt_html is not None,
+                    timeout=SHELL_TIMEOUT)
+    assert shell.get_value('pi')
+
+    # Reset config for the 'spyder_pythonpath' and 'startup/run_lines'
+    ipyconsole.set_conf(
+        'spyder_pythonpath',
+        [],
+        section='main')
+    ipyconsole.set_conf(
+        'startup/run_lines',
+        '',
+        section='ipython_console')
+
+
 if __name__ == "__main__":
     pytest.main()