Skip to content
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

PR: Fix listing envs in the Consoles' environment menu (IPython console) #22380

Merged
merged 7 commits into from
Aug 29, 2024
13 changes: 13 additions & 0 deletions spyder/app/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import random
import socket
import time
import warnings

# Prevent showing internal logging errors
# Fixes spyder-ide/spyder#15768
Expand Down Expand Up @@ -56,6 +57,13 @@
from spyder.utils.external import lockfile
from spyder.py3compat import is_text_string


# On macOS conda installations, sys.executable may be a symlink in the
# application bundle, and therefore should be resolved to the executable in the
# environment.
if sys.platform == "darwin" and sys.executable.endswith("MacOS/python"):
sys.executable = os.readlink(sys.executable)

# Enforce correct CONDA_EXE environment variable
# Do not rely on CONDA_PYTHON_EXE or CONDA_PREFIX in case Spyder is started
# from the commandline
Expand All @@ -80,6 +88,11 @@
if CLI_OPTIONS.conf_dir:
os.environ['SPYDER_CONFDIR'] = CLI_OPTIONS.conf_dir

# -- Ignore useless warnings
# From the cryptography module
warnings.filterwarnings("ignore", message="ARC4 has been moved")
warnings.filterwarnings("ignore", message="TripleDES has been moved")


def send_args_to_spyder(args):
"""
Expand Down
36 changes: 32 additions & 4 deletions spyder/config/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,20 @@
"""

# Standard library imports
from importlib import reload
import os
import os.path as osp
try:
from importlib import reload
except ImportError: # A builtin on Python 2
pass
from pathlib import Path
import shutil


# Third party imports
import pytest

# Local imports
import spyder.config.base
from spyder.config.utils import is_anaconda
from spyder.utils.conda import get_list_conda_envs


# ============================================================================
Expand Down Expand Up @@ -52,5 +54,31 @@ def test_get_conf_path(monkeypatch, use_dev_config_dir):
reload(spyder.config.base)


@pytest.mark.skipif(
not spyder.config.base.running_in_ci(), reason="Only works on CIs"
)
@pytest.mark.skipif(not is_anaconda(), reason='Only works with Anaconda')
def test_is_conda_based_app():
"""Test that is_conda_based_app is working as expected."""
# Get conda env to use
pyexec = get_list_conda_envs()['Conda: jedi-test-env'][0]

# Get env's root
env_root = (
Path(pyexec).parents[0] if os.name == "nt" else Path(pyexec).parents[1]
)

# Create dir and file necessary to detect the app
menu_dir = env_root / "Menu"
menu_dir.mkdir()
(menu_dir / "conda-based-app").touch()

# Check the env is detected as belonging to the app
assert spyder.config.base.is_conda_based_app(pyexec=pyexec)

# Remove added dir
shutil.rmtree(menu_dir, ignore_errors=True)


if __name__ == '__main__':
pytest.main()
8 changes: 5 additions & 3 deletions spyder/plugins/ipythonconsole/widgets/main_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# Standard library imports
from __future__ import annotations
import functools
import logging
import os
import os.path as osp
Expand Down Expand Up @@ -1217,9 +1218,10 @@ def _update_environment_menu(self):
text=text,
icon=self.create_icon('ipython_console'),
triggered=(
lambda checked, env_name=env_name,
path_to_interpreter=path_to_interpreter:
self.create_environment_client(
self.create_new_client
if path_to_interpreter == default_interpreter
else functools.partial(
self.create_environment_client,
env_name,
path_to_interpreter
)
Expand Down
1 change: 1 addition & 0 deletions spyder/plugins/maininterpreter/confpage.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def setup_page(self):
validate_callback=programs.is_python_interpreter,
)
self.cus_exec_combo.setStyleSheet("margin-left: 3px")
self.cus_exec_combo.combobox.setMinimumWidth(400)

self.def_exec_radio.radiobutton.toggled.connect(
self.cus_exec_combo.setDisabled)
Expand Down
33 changes: 31 additions & 2 deletions spyder/plugins/maininterpreter/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,27 @@ def _finish_updating_envs(self, worker, output, error):
# proper output.
# Fixes spyder-ide/spyder#20539
if output is not None:
self.envs.update(**output)
# Update envs with autodetected info
for new_name, new_info in output.items():
if new_name in self.envs:
# The env is already listed, so we don't need to do
# anything else.
continue
elif (
new_name not in self.envs
and new_info in self.envs.values()
):
# Replace name of envs that are detected as Conda/Pyenv
# envs after running _update_envs, but were listed in
# self.envs differently.
for name, info in self.envs.copy().items():
if info == new_info:
self.envs.pop(name)
self.envs[new_name] = info
break
else:
# Add new env to the current ones
self.envs[new_name] = new_info

if self._current_envs != self.envs:
for env in list(self.envs.keys()):
Expand Down Expand Up @@ -251,7 +271,16 @@ def _get_env_info(self, path):
except KeyError:
env_name = get_env_dir(original_path, only_dir=True)

if 'conda' in path:
if (
# For Anaconda/Miniconda distros
"conda" in path.lower()
# For Mambaforge
or "mamba" in path.lower()
# For Miniforge
or "miniforge" in path.lower()
# For our installers
or (is_conda_based_app() and "spyder-runtime" in path)
):
name = 'Conda: ' + env_name
elif 'pyenv' in path:
name = 'Pyenv: ' + env_name
Expand Down
8 changes: 6 additions & 2 deletions spyder/utils/conda.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,12 @@ def get_list_conda_envs():
path = osp.join(env, 'python.exe') if WINDOWS else osp.join(
env, 'bin', 'python')

# In case the environment doesn't have Python
if not osp.isfile(path):
if (
# In case the environment doesn't have Python
not osp.isfile(path)
# Don't list the installers base env
or (is_conda_based_app(pyexec=path) and name != "spyder-runtime")
):
continue

try:
Expand Down