-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
PR: Get user environment variables asynchronously #24269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
9136d62
to
fdee59f
Compare
@hlouzada, thanks for helping me get started on implementing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall everything looks good. But I noticed that there's no need for the get_user_environment_variables
function to be run in it's own thread/event loop, since the get env is a shell function that starts a subprocesses, so you can just await
for it to finish.
b30098f
to
c74b713
Compare
@dalthviz, this seems to be working for all but one test on Windows conda. I can't figure out why this is happening; perhaps you have some ideas? I suspect this is some kind of race condition between the prompt and the banner. |
@mrclary about the Windows test failing ( spyder/spyder/app/tests/test_mainwindow.py Lines 6707 to 6709 in 3606d9b
To something like # Run test file
with qtbot.waitSignal(shell.sig_prompt_ready):
qtbot.mouseClick(main_window.run_button, Qt.LeftButton) helps Checking the failing one on Linux ( spyder/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py Lines 1395 to 1398 in 3606d9b
For something like shell = ipyconsole.get_current_shellwidget()
control = shell._control
qtbot.waitUntil(lambda: shell._prompt_html is not None,
timeout=SHELL_TIMEOUT) ? |
@mrclary I had a look at this and I think that I made some headway. Apologies for the long post. I believe the relevant difference between the first console (the one created when Spyder starts up) and subsequent consoles is that in the first console, spyder/spyder/plugins/ipythonconsole/widgets/shell.py Lines 725 to 739 in fc230d3
I presume this function is called when the conf file with the colour scheme is read in and that this happens shortly after the first console is created but before user create any other consoles. As the code shows, setting the colour scheme resets the console. Resetting the console prints a new prompt. Printing a prompt requires a kernel. If the kernel is not ready, then no prompt appears. With this PR, if getting the env vars takes some time, it may happen that You may ask, why does no prompt appear if the console is reset before the kernel is ready? I think the answer lies in this function in spyder/external-deps/qtconsole/qtconsole/jupyter_widget.py Lines 365 to 389 in fc230d3
This function is called with number = None and it "makes a prompt number request". If there is no kernel (which may happen when the kernel is slow to start), then self.kernel_client = None so the self.kernel_client.execute() fails (I guess an exception is raised which is silently somewhere swallowed). Even worse, self._prompt_requested is set to True so on subsequent calls (e.g., when the kernel has finally started up) no further requests will be made. A fix here is to change
if self._prompt_requested: to if self._prompt_requested or self.kernel_client is None: This also fixes the issue in my testing. |
Thanks @dalthviz and @jitseniesen! I haven't had a chance to incorporate your suggestions yet, but I wanted you to know that they are much appreciated and I will be working on them soon. |
I've confirmed @jitseniesen recommendations worked! 🥇 |
Looks like @dalthviz suggestions did the trick for the tests! This should be ready for review now that everything is working. Thanks for everyone's help! |
Unfortunately, this PR seems to break the spyder-notebook plugin. That plugin uses the same kernel spec as Spyder. With this PR, the notebook server spits out many errors, starting with:
I have very little experience with async programming in Python and I don't understand this error. By trial and error, I found the breaking change: commit 8c74b90, specifically changing the decorator of Fortunately, this suggests an easy fix: Remove the import from @hlouzada Perhaps you know whether this makes sense or can suggest a better fix? |
@hlouzada, you made the code suggestion earlier that removed
I'm wondering if this implies that all plugins should be using their own event loop. While I have no objection to @jitseniesen's recommendation, per se, if the issue arises because of a collision in the main event loop, then the issue @jitseniesen sees could affect any plugin that directly or indirectly imports from |
c89cde3
to
547950b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mrclary, last comment for you then this should be ready.
547950b
to
1380774
Compare
Raise the timeout to 10s. Since this should be run asynchronously, we can afford to have a large timeout; however, if the process truly hangs, then a timeout error in the logs will be useful. Note: get_user_environment_variables returns a Future.
… client for the IPython console. * get_user_environment_variables is extracted from SpyderKernelSpec.env to more conveniently run it asynchronously. This is now called in IPythonConsoleWidget.create_new_client. * SpyderKernelSpec.env is separated into setter/getter, with environment variables as an argument. This effectively caches SpyderKernelSpec.env. Since this gets referenced many times, there should be no need to recompute it except on instantiation.
…nous and non-asynchronous use cases.
…rival of kernel connection
qtbot.waitUntil hangs after quitting the shells, but qtbot.waitSignal context seems to work 🤷. Mark close_main_window prevents "QThread: Destroyed while thread still running".
Mark close_main_window qtbot.wait required after qtbot.keyClick, else qtbot.waitUntil freezes 🤷.
Co-authored-by: Hendrik <[email protected]>
Check that the kernel is ready before resetting the shell or setting the color scheme in the shell widget.
Co-authored-by: Carlos Cordoba <[email protected]>
Add test for attempting to execute while shell is already executing.
1380774
to
9e22123
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me now, thanks @mrclary!
Under some circumstances, getting user environment variables may take some time. In order to not block Spyder's UI during the subprocess to get environment variables on unix systems, this is moved to a separate thread. This also allows a larger timeout to be specified.
get_user_environment_variables
is changed to a concurrent future objectget_user_environment_variables
is not called in thekernelspec
module, but now in theipythonconsole
main widget module when creating a new client, and in the Pythonpath manager utils.