From edaeef136b0be7a95095bd6e016be990c11c2417 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Mon, 10 Apr 2023 11:35:52 -0700 Subject: [PATCH 01/17] Use pcre2grep, which is already installed by git --- .github/workflows/installers-conda.yml | 11 +---------- installers-conda/notarize.sh | 6 +++--- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/.github/workflows/installers-conda.yml b/.github/workflows/installers-conda.yml index 73cf48230d1..bf1504894b4 100644 --- a/.github/workflows/installers-conda.yml +++ b/.github/workflows/installers-conda.yml @@ -162,15 +162,6 @@ jobs: with: fetch-depth: 0 - - name: Install pcregrep - if: runner.os == 'macOS' - run: | - if [[ -z "$(which pcregrep)" ]]; then - brew install pcre - else - echo "$(which pcregrep) already installed." - fi - - name: Setup Build Environment uses: mamba-org/provision-with-micromamba@main with: @@ -225,7 +216,7 @@ jobs: if: runner.os == 'macOS' && (env.IS_RELEASE == 'true' || env.IS_PRE == 'true') run: | ./certkeychain.sh "${MACOS_CERTIFICATE_PWD}" "${MACOS_CERTIFICATE}" "${MACOS_INSTALLER_CERTIFICATE}" - CNAME=$(security find-identity -p codesigning -v | pcregrep -o1 "\(([0-9A-Z]+)\)") + CNAME=$(security find-identity -p codesigning -v | pcre2grep -o1 "\(([0-9A-Z]+)\)") echo "CNAME=$CNAME" >> $GITHUB_ENV _codesign=$(which codesign) diff --git a/installers-conda/notarize.sh b/installers-conda/notarize.sh index 77855a431dc..c37b2dac6e8 100755 --- a/installers-conda/notarize.sh +++ b/installers-conda/notarize.sh @@ -44,7 +44,7 @@ shift $(($OPTIND - 1)) PKG=$(cd $(dirname $1) && pwd -P)/$(basename $1) # Resolve full path # --- Get certificate id -CNAME=$(security find-identity -p codesigning -v | pcregrep -o1 "\(([0-9A-Z]+)\)") +CNAME=$(security find-identity -p codesigning -v | pcre2grep -o1 "\(([0-9A-Z]+)\)") [[ -z $CNAME ]] && log "Could not locate certificate ID" && exit 1 log "Certificate ID: $CNAME" @@ -54,8 +54,8 @@ notarize_args+=("--team-id" "$CNAME" "${pwd_args[@]}") log "Notarizing..." xcrun notarytool submit $PKG --wait ${notarize_args[@]} | tee temp.txt -submitid=$(pcregrep -o1 "^\s*id: ([0-9a-z-]+)" temp.txt | head -1) -status=$(pcregrep -o1 "^\s*status: (\w+$)" temp.txt) +submitid=$(pcre2grep -o1 "^\s*id: ([0-9a-z-]+)" temp.txt | head -1) +status=$(pcre2grep -o1 "^\s*status: (\w+$)" temp.txt) rm temp.txt xcrun notarytool log $submitid ${notarize_args[@]} From 8cd728a023db55c8ce237af97ab37d1da1f08210 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Mon, 10 Apr 2023 14:46:36 -0700 Subject: [PATCH 02/17] Rename post-install script for linux. Clarify uninstall instruction --- installers-conda/build_installers.py | 2 +- .../resources/{post-install.sh => post-install-linux.sh} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename installers-conda/resources/{post-install.sh => post-install-linux.sh} (96%) diff --git a/installers-conda/build_installers.py b/installers-conda/build_installers.py index 9883a9fb7a4..daf13d775cc 100644 --- a/installers-conda/build_installers.py +++ b/installers-conda/build_installers.py @@ -258,7 +258,7 @@ def _definitions(): ), "license_file": str(SPYREPO / "LICENSE.txt"), "installer_type": "sh", - "post_install": str(RESOURCES / "post-install.sh"), + "post_install": str(RESOURCES / "post-install-linux.sh"), } ) diff --git a/installers-conda/resources/post-install.sh b/installers-conda/resources/post-install-linux.sh similarity index 96% rename from installers-conda/resources/post-install.sh rename to installers-conda/resources/post-install-linux.sh index 0c39c6aa32b..e4424234641 100755 --- a/installers-conda/resources/post-install.sh +++ b/installers-conda/resources/post-install-linux.sh @@ -69,7 +69,7 @@ by: $ spyder -To uninstall Spyder, you need to run from the following from the command line: +To uninstall Spyder, run the following from the command line: $ uninstall-spyder From 5672c268f91bf63f7207afddca89c555d0592fc6 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:19:35 -0700 Subject: [PATCH 03/17] Fall back to SPY_COMMIT and SPY_BRANCH for git revision. This has the effect of reporting these values when running from conda-based installers, otherwise no effect. --- spyder/__init__.py | 10 +++------- spyder/utils/vcs.py | 6 +++--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/spyder/__init__.py b/spyder/__init__.py index 241ab379fca..020e5e7e38a 100644 --- a/spyder/__init__.py +++ b/spyder/__init__.py @@ -66,13 +66,9 @@ def get_versions(reporev=True): revision = branch = None if reporev: - if running_in_mac_app(): - revision = os.environ.get('SPY_COMMIT', None) - branch = os.environ.get('SPY_BRANCH', None) - else: - from spyder.utils import vcs - revision, branch = vcs.get_git_revision( - os.path.dirname(__current_directory__)) + from spyder.utils import vcs + revision, branch = vcs.get_git_revision( + os.path.dirname(__current_directory__)) if is_pynsist() or running_in_mac_app(): installer = 'standalone' diff --git a/spyder/utils/vcs.py b/spyder/utils/vcs.py index a04a6170026..d5751c2c08b 100644 --- a/spyder/utils/vcs.py +++ b/spyder/utils/vcs.py @@ -117,8 +117,8 @@ def get_git_revision(repopath): """ Return Git revision for the repository located at repopath - Result is a tuple (latest commit hash, branch), with None values on - error + Result is a tuple (latest commit hash, branch), falling back to + SPY_COMMIT and SPY_BRANCH environment variables, if present, else None. """ try: git = programs.find_git() @@ -143,7 +143,7 @@ def get_git_revision(repopath): return commit, branch except (subprocess.CalledProcessError, AssertionError, AttributeError, OSError): - return None, None + return os.environ.get('SPY_COMMIT'), os.environ.get('SPY_BRANCH') def get_git_refs(repopath): From 3bb088bfc25361a946e8fed4102da962af196afe Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:28:56 -0700 Subject: [PATCH 04/17] running_in_mac_app is no longer applicable here since the mac app is now conda-based --- spyder/app/start.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/spyder/app/start.py b/spyder/app/start.py index 1b4a96945dd..fb015174701 100644 --- a/spyder/app/start.py +++ b/spyder/app/start.py @@ -50,8 +50,8 @@ # Local imports from spyder.app.cli_options import get_options -from spyder.config.base import (get_conf_path, running_in_mac_app, - reset_config_files, running_under_pytest) +from spyder.config.base import (get_conf_path, reset_config_files, + running_under_pytest) from spyder.utils.external import lockfile from spyder.py3compat import is_text_string @@ -200,8 +200,7 @@ def main(): return if (CONF.get('main', 'single_instance') and not options.new_instance - and not options.reset_config_files - and not running_in_mac_app()): + and not options.reset_config_files): # Minimal delay (0.1-0.2 secs) to avoid that several # instances started at the same time step in their # own foots while trying to create the lock file From ddb8cfcf981d73cc04766d1a5005bc0b2d1e5e87 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Thu, 13 Apr 2023 19:56:21 -0700 Subject: [PATCH 05/17] Rename running_in_mac_app -> is_conda_based_app. is_conda_based_app checks if Spyder is from a conda-based installer. Conda-based installer is determined by existence of spyder-menu.json file in environment instead of SPYDER_APP environment variable. --- installers-conda/resources/spyder-menu.json | 1 - spyder/__init__.py | 4 +-- spyder/app/mainwindow.py | 4 +-- spyder/app/utils.py | 4 +-- spyder/config/base.py | 29 +++++++++---------- spyder/dependencies.py | 4 +-- spyder/plugins/application/confpage.py | 9 +++--- spyder/plugins/application/container.py | 6 ++-- spyder/plugins/application/widgets/status.py | 6 ++-- .../ipythonconsole/utils/kernelspec.py | 16 ++++------ .../plugins/ipythonconsole/widgets/shell.py | 10 +++---- .../plugins/maininterpreter/widgets/status.py | 4 +-- spyder/plugins/projects/plugin.py | 6 ++-- .../widgets/collectionsdelegate.py | 6 ++-- spyder/utils/qthelpers.py | 6 ++-- spyder/widgets/reporterror.py | 4 +-- 16 files changed, 57 insertions(+), 62 deletions(-) diff --git a/installers-conda/resources/spyder-menu.json b/installers-conda/resources/spyder-menu.json index 2af0280d8af..72d7bf45372 100644 --- a/installers-conda/resources/spyder-menu.json +++ b/installers-conda/resources/spyder-menu.json @@ -38,7 +38,6 @@ "CFBundleIdentifier": "org.spyder-ide.Spyder", "CFBundleVersion": "__PKG_VERSION__", "LSEnvironment": { - "SPYDER_APP": "True", "SPY_BRANCH": "__SPY_BRANCH__", "SPY_COMMIT": "__SPY_COMMIT__" } diff --git a/spyder/__init__.py b/spyder/__init__.py index 020e5e7e38a..a7fa9dd7cc0 100644 --- a/spyder/__init__.py +++ b/spyder/__init__.py @@ -62,7 +62,7 @@ def get_versions(reporev=True): import qtpy.QtCore from spyder.utils.conda import is_conda_env - from spyder.config.base import is_pynsist, running_in_mac_app + from spyder.config.base import is_pynsist, is_conda_based_app revision = branch = None if reporev: @@ -70,7 +70,7 @@ def get_versions(reporev=True): revision, branch = vcs.get_git_revision( os.path.dirname(__current_directory__)) - if is_pynsist() or running_in_mac_app(): + if is_pynsist() or is_conda_based_app(): installer = 'standalone' elif is_conda_env(pyexec=sys.executable): installer = 'conda' diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py index 6cc39c0335e..93fe76e76bb 100644 --- a/spyder/app/mainwindow.py +++ b/spyder/app/mainwindow.py @@ -73,7 +73,7 @@ from spyder.api.plugin_registration.registry import PLUGIN_REGISTRY from spyder.api.config.mixins import SpyderConfigurationAccessor from spyder.config.base import (_, DEV, get_conf_path, get_debug_level, - get_home_dir, is_pynsist, running_in_mac_app, + get_home_dir, is_pynsist, is_conda_based_app, running_under_pytest, STDERR) from spyder.config.gui import is_dark_font_color from spyder.config.main import OPEN_FILES_PORT @@ -945,7 +945,7 @@ def set_window_title(self): title = u"Spyder %s (Python %s.%s)" % (__version__, sys.version_info[0], sys.version_info[1]) - elif running_in_mac_app() or is_pynsist(): + elif is_conda_based_app() or is_pynsist(): title = "Spyder" else: title = u"Spyder (Python %s.%s)" % (sys.version_info[0], diff --git a/spyder/app/utils.py b/spyder/app/utils.py index 700ec6d131d..fc16a2855ff 100644 --- a/spyder/app/utils.py +++ b/spyder/app/utils.py @@ -23,7 +23,7 @@ # Local imports from spyder.config.base import ( - DEV, get_conf_path, get_debug_level, running_in_mac_app, + DEV, get_conf_path, get_debug_level, is_conda_based_app, running_under_pytest) from spyder.config.manager import CONF from spyder.utils.external.dafsa.dafsa import DAFSA @@ -312,7 +312,7 @@ def create_window(WindowClass, app, splash, options, args): # Open external files with our Mac app # ??? Do we need this? - if running_in_mac_app(): + if sys.platform == 'darwin' and is_conda_based_app(): app.sig_open_external_file.connect(main.open_external_file) app._has_started = True if hasattr(app, '_pending_file_open'): diff --git a/spyder/config/base.py b/spyder/config/base.py index ae633953b79..d323bf21918 100644 --- a/spyder/config/base.py +++ b/spyder/config/base.py @@ -541,32 +541,31 @@ def translate_gettext(x): #============================================================================== -# Mac application utilities +# Conda-based installer application utilities #============================================================================== -def running_in_mac_app(pyexec=sys.executable): +def is_conda_based_app(pyexec=sys.executable): """ - Check if Spyder is running as a macOS bundle app by looking for the - `SPYDER_APP` environment variable. + Check if Spyder is running from the conda-based installer by looking for + the `spyder-menu.json` file. - If a python executable is provided, checks if it is the same as the macOS - bundle app environment executable. + If a Python executable is provided, checks if it is the same as a + conda-based installer environment executable. """ - # Spyder is macOS app - mac_app = os.environ.get('SPYDER_APP') is not None - - if sys.platform == 'darwin' and mac_app and pyexec == sys.executable: - # executable is macOS app - return True + real_pyexec = osp.realpath(pyexec) # pyexec may be symlink + if os.name == 'nt': + env_path = osp.dirname(real_pyexec) else: - return False - + env_path = osp.dirname(osp.dirname(real_pyexec)) + menu_path = osp.join(env_path, 'Menu', 'spyder-menu.json') + + return osp.exists(menu_path) # ============================================================================= # Micromamba # ============================================================================= def get_spyder_umamba_path(): """Return the path to the Micromamba executable bundled with Spyder.""" - if running_in_mac_app(): + if is_conda_based_app(): # TODO: Change to CONDA_EXE when # conda-forge/conda-standalone-feedstock#45 is resolved path = os.environ.get('CONDA_PYTHON_EXE') diff --git a/spyder/dependencies.py b/spyder/dependencies.py index f3079f5b40f..d0f88a7a09d 100644 --- a/spyder/dependencies.py +++ b/spyder/dependencies.py @@ -12,7 +12,7 @@ import sys # Local imports -from spyder.config.base import _, is_pynsist, running_in_ci, running_in_mac_app +from spyder.config.base import _, is_pynsist, running_in_ci, is_conda_based_app from spyder.utils import programs HERE = osp.dirname(osp.abspath(__file__)) @@ -95,7 +95,7 @@ 'package_name': "applaunchservices", 'features': _("Notify macOS that Spyder can open Python files"), 'required_version': APPLAUNCHSERVICES_REQVER, - 'display': sys.platform == "darwin" and not running_in_mac_app()}, + 'display': sys.platform == "darwin" and not is_conda_based_app()}, {'modname': "atomicwrites", 'package_name': "atomicwrites", 'features': _("Atomic file writes in the Editor"), diff --git a/spyder/plugins/application/confpage.py b/spyder/plugins/application/confpage.py index a287e32766b..f34c8ae5b46 100644 --- a/spyder/plugins/application/confpage.py +++ b/spyder/plugins/application/confpage.py @@ -22,7 +22,7 @@ QVBoxLayout, QWidget) from spyder.config.base import (_, DISABLED_LANGUAGES, LANGUAGE_CODES, - running_in_mac_app, save_lang_conf) + is_conda_based_app, save_lang_conf) from spyder.api.preferences import PluginConfigPage from spyder.py3compat import to_text_string @@ -69,7 +69,8 @@ def setup_page(self): 'check_updates_on_startup') # Decide if it's possible to activate or not single instance mode - if running_in_mac_app(): + # ??? Should this apply to all conda-based installers? + if is_conda_based_app(): self.set_option("single_instance", True) single_instance_box.setEnabled(False) @@ -135,7 +136,7 @@ def setup_page(self): interface_layout.addLayout(margins_cursor_layout) interface_group.setLayout(interface_layout) - if sys.platform == "darwin" and not running_in_mac_app(): + if sys.platform == "darwin" and not is_conda_based_app(): # To open files from Finder directly in Spyder. from spyder.utils.qthelpers import (register_app_launchservices, restore_launchservices) @@ -224,7 +225,7 @@ def set_open_file(state): screen_resolution_layout.addLayout(screen_resolution_inner_layout) screen_resolution_group.setLayout(screen_resolution_layout) - if sys.platform == "darwin" and not running_in_mac_app(): + if sys.platform == "darwin" and not is_conda_based_app(): interface_tab = self.create_tab(screen_resolution_group, interface_group, macOS_group) else: diff --git a/spyder/plugins/application/container.py b/spyder/plugins/application/container.py index e848652d621..0a5c53116df 100644 --- a/spyder/plugins/application/container.py +++ b/spyder/plugins/application/container.py @@ -29,7 +29,7 @@ from spyder.utils.installers import InstallerMissingDependencies from spyder.config.utils import is_anaconda from spyder.config.base import (get_conf_path, get_debug_level, is_pynsist, - running_in_mac_app) + is_conda_based_app) from spyder.plugins.application.widgets.status import ApplicationUpdateStatus from spyder.plugins.console.api import ConsoleActions from spyder.utils.environ import UserEnvDialog @@ -105,7 +105,7 @@ def setup(self): # Attributes self.dialog_manager = DialogManager() self.application_update_status = None - if is_pynsist() or running_in_mac_app(): + if is_pynsist() or is_conda_based_app(): self.application_update_status = ApplicationUpdateStatus( parent=self) (self.application_update_status.sig_check_for_updates_requested @@ -318,7 +318,7 @@ def _check_updates_ready(self): "conda update anaconda
" "conda install spyder={}

" ).format(latest_release) - elif is_pynsist() or running_in_mac_app(): + elif is_pynsist() or is_conda_based_app(): box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) content = _( diff --git a/spyder/plugins/application/widgets/status.py b/spyder/plugins/application/widgets/status.py index 5c298dcdc87..357c28e06c3 100644 --- a/spyder/plugins/application/widgets/status.py +++ b/spyder/plugins/application/widgets/status.py @@ -19,7 +19,7 @@ # Local imports from spyder.api.translations import _ from spyder.api.widgets.status import StatusBarWidget -from spyder.config.base import is_pynsist, running_in_mac_app +from spyder.config.base import is_pynsist, is_conda_based_app from spyder.plugins.application.widgets.install import ( UpdateInstallerDialog, NO_STATUS, DOWNLOADING_INSTALLER, INSTALLING, PENDING, CHECKING) @@ -150,10 +150,10 @@ def show_installation_dialog_or_menu(self): value = self.value.split(":")[-1].strip() if ((not self.tooltip == self.BASE_TOOLTIP and not value == PENDING) - and (is_pynsist() or running_in_mac_app())): + and (is_pynsist() or is_conda_based_app())): self.installer.show() elif (value == PENDING and - (is_pynsist() or running_in_mac_app())): + (is_pynsist() or is_conda_based_app())): self.installer.continue_installation() elif value == NO_STATUS: self.menu.clear() diff --git a/spyder/plugins/ipythonconsole/utils/kernelspec.py b/spyder/plugins/ipythonconsole/utils/kernelspec.py index 014f0bba631..e1e616f5d0a 100644 --- a/spyder/plugins/ipythonconsole/utils/kernelspec.py +++ b/spyder/plugins/ipythonconsole/utils/kernelspec.py @@ -20,7 +20,7 @@ # Local imports from spyder.api.config.mixins import SpyderConfigurationAccessor from spyder.api.translations import _ -from spyder.config.base import (get_safe_mode, is_pynsist, running_in_mac_app, +from spyder.config.base import (get_safe_mode, is_pynsist, is_conda_based_app, running_under_pytest) from spyder.plugins.ipythonconsole import ( SPYDER_KERNELS_CONDA, SPYDER_KERNELS_PIP, SPYDER_KERNELS_VERSION, @@ -234,15 +234,11 @@ def env(self): # App considerations # ??? Do we need this? - if (running_in_mac_app() or is_pynsist()): - if default_interpreter: - # See spyder-ide/spyder#16927 - # See spyder-ide/spyder#16828 - # See spyder-ide/spyder#17552 - env_vars['PYDEVD_DISABLE_FILE_VALIDATION'] = 1 - else: - # ??? Do we need this? - env_vars.pop('PYTHONHOME', None) + if (is_conda_based_app() or is_pynsist()) and default_interpreter: + # See spyder-ide/spyder#16927 + # See spyder-ide/spyder#16828 + # See spyder-ide/spyder#17552 + env_vars['PYDEVD_DISABLE_FILE_VALIDATION'] = 1 # Remove this variable because it prevents starting kernels for # external interpreters when present. diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py index 3c3f0bc3c5f..04436348aac 100644 --- a/spyder/plugins/ipythonconsole/widgets/shell.py +++ b/spyder/plugins/ipythonconsole/widgets/shell.py @@ -23,7 +23,7 @@ # Local imports from spyder.config.base import ( - _, is_pynsist, running_in_mac_app, running_under_pytest) + _, is_pynsist, is_conda_based_app, running_under_pytest) from spyder.config.gui import get_color_scheme, is_dark_interface from spyder.py3compat import to_text_string from spyder.utils.palette import QStylePalette, SpyderPalette @@ -129,7 +129,7 @@ class ShellWidget(NamepaceBrowserWidget, HelpWidget, DebuggingWidget, sig_kernel_state_arrived = Signal(dict) """ A new kernel state, which needs to be processed. - + Parameters ---------- state: dict @@ -178,7 +178,7 @@ def __init__(self, ipyclient, additional_options, interpreter_versions, # Show a message in our installers to explain users how to use # modules that don't come with them. - self.show_modules_message = is_pynsist() or running_in_mac_app() + self.show_modules_message = is_pynsist() or is_conda_based_app() # ---- Public API --------------------------------------------------------- @property @@ -191,7 +191,7 @@ def is_spyder_kernel(self): def spyder_kernel_ready(self): """ Check if Spyder kernel is ready. - + Notes ----- This is used for our tests. @@ -352,7 +352,7 @@ def setup_spyder_kernel(self): if not self._init_kernel_setup: # Only do this setup once self._init_kernel_setup = True - + # For errors self.kernel_handler.kernel_comm.sig_exception_occurred.connect( self.sig_exception_occurred) diff --git a/spyder/plugins/maininterpreter/widgets/status.py b/spyder/plugins/maininterpreter/widgets/status.py index 90139e81ad3..8439b9d85f5 100644 --- a/spyder/plugins/maininterpreter/widgets/status.py +++ b/spyder/plugins/maininterpreter/widgets/status.py @@ -17,7 +17,7 @@ # Local imports from spyder.api.widgets.status import BaseTimerStatus -from spyder.config.base import is_pynsist, running_in_mac_app +from spyder.config.base import is_pynsist, is_conda_based_app from spyder.utils.envs import get_list_envs from spyder.utils.programs import get_interpreter_info from spyder.utils.workers import WorkerManager @@ -114,7 +114,7 @@ def _get_env_info(self, path): except KeyError: if ( self.default_interpreter == path - and (running_in_mac_app() or is_pynsist()) + and (is_conda_based_app() or is_pynsist()) ): name = 'internal' elif 'conda' in path: diff --git a/spyder/plugins/projects/plugin.py b/spyder/plugins/projects/plugin.py index ca8ed9029b3..5e86fd453c7 100644 --- a/spyder/plugins/projects/plugin.py +++ b/spyder/plugins/projects/plugin.py @@ -23,7 +23,7 @@ on_plugin_available, on_plugin_teardown) from spyder.api.plugins import Plugins, SpyderDockablePlugin from spyder.api.translations import _ -from spyder.config.base import running_in_mac_app +from spyder.config.base import is_conda_based_app from spyder.plugins.completion.api import WorkspaceUpdateKind from spyder.plugins.mainmenu.api import ApplicationMenus, ProjectsMenuSections from spyder.plugins.projects.api import EmptyProject @@ -269,8 +269,8 @@ def on_mainwindow_visible(self): initial_cwd = self._main.get_initial_working_directory() if cli_options.project is not None: - # This doesn't work for our Mac app - if not running_in_mac_app(): + # This doesn't work for our conda-based installer apps + if not is_conda_based_app(): logger.debug('Opening project from the command line') project = osp.normpath( osp.join(initial_cwd, cli_options.project) diff --git a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py index 9cdfab880a0..ac820e266bb 100644 --- a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py +++ b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py @@ -24,7 +24,7 @@ is_known_type) # Local imports -from spyder.config.base import _, is_pynsist, running_in_mac_app +from spyder.config.base import _, is_pynsist, is_conda_based_app from spyder.config.fonts import DEFAULT_SMALL_DELTA from spyder.config.gui import get_font from spyder.py3compat import is_binary_string, is_text_string, to_text_string @@ -119,7 +119,7 @@ def createEditor(self, parent, option, index, object_explorer=False): message = _("Spyder is unable to show the {val_type} or object" " you're trying to view because {module}" " is not installed. ") - if running_in_mac_app(): + if is_conda_based_app(): message += _("Please consider using the full version of " "the Spyder MacOS application.
") else: @@ -130,7 +130,7 @@ def createEditor(self, parent, option, index, object_explorer=False): message.format(val_type=val_type, module=module)) return else: - if running_in_mac_app() or is_pynsist(): + if is_conda_based_app() or is_pynsist(): message = _("Spyder is unable to show the variable you're" " trying to view because the module " "{module} is not supported in the " diff --git a/spyder/utils/qthelpers.py b/spyder/utils/qthelpers.py index 1ddeae1159c..0dcee3ea354 100644 --- a/spyder/utils/qthelpers.py +++ b/spyder/utils/qthelpers.py @@ -30,7 +30,7 @@ QToolButton, QVBoxLayout, QWidget) # Local imports -from spyder.config.base import running_in_mac_app +from spyder.config.base import is_conda_based_app from spyder.config.manager import CONF from spyder.py3compat import is_text_string, to_text_string from spyder.utils.icon_manager import ima @@ -41,7 +41,7 @@ from spyder.widgets.waitingspinner import QWaitingSpinner # Third party imports -if sys.platform == "darwin" and not running_in_mac_app(): +if sys.platform == "darwin" and not is_conda_based_app(): import applaunchservices as als @@ -115,7 +115,7 @@ def qapplication(translate=True, test_time=3): app.setApplicationName('Spyder') if (sys.platform == "darwin" - and not running_in_mac_app() + and not is_conda_based_app() and CONF.get('main', 'mac_open_file', False)): # Register app if setting is set register_app_launchservices() diff --git a/spyder/widgets/reporterror.py b/spyder/widgets/reporterror.py index 56870a4f7d1..48db1ea0387 100644 --- a/spyder/widgets/reporterror.py +++ b/spyder/widgets/reporterror.py @@ -23,7 +23,7 @@ from spyder import (__project_url__, __trouble_url__, dependencies, get_versions_text) from spyder.api.config.mixins import SpyderConfigurationAccessor -from spyder.config.base import _, is_pynsist, running_in_mac_app +from spyder.config.base import _, is_pynsist, is_conda_based_app from spyder.config.gui import get_font from spyder.plugins.console.widgets.console import ConsoleBaseWidget from spyder.utils.conda import is_conda_env, get_conda_env_path, find_conda @@ -255,7 +255,7 @@ def __init__(self, parent=None, is_report=False): # Only provide checkbox if not an installer default interpreter if ( - not (is_pynsist() or running_in_mac_app()) + not (is_pynsist() or is_conda_based_app()) or not self.get_conf('default', section='main_interpreter') ): layout.addWidget(self.include_env) From c727e4d2755796bb7be1553143dabc19f2323533 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Thu, 13 Apr 2023 20:20:00 -0700 Subject: [PATCH 06/17] Remove is_pynsist, obsolete --- spyder/__init__.py | 4 ++-- spyder/app/mainwindow.py | 4 ++-- spyder/config/base.py | 13 ------------- spyder/dependencies.py | 6 +++--- spyder/plugins/application/container.py | 6 +++--- spyder/plugins/application/widgets/install.py | 4 ++-- spyder/plugins/application/widgets/status.py | 12 ++++++------ .../completion/providers/languageserver/client.py | 5 +++-- spyder/plugins/ipythonconsole/utils/kernelspec.py | 4 ++-- spyder/plugins/ipythonconsole/widgets/shell.py | 5 ++--- spyder/plugins/maininterpreter/widgets/status.py | 10 ++++------ spyder/plugins/onlinehelp/widgets.py | 5 +++-- spyder/plugins/pylint/main_widget.py | 5 ++--- .../variableexplorer/widgets/collectionsdelegate.py | 4 ++-- spyder/widgets/reporterror.py | 4 ++-- 15 files changed, 38 insertions(+), 53 deletions(-) diff --git a/spyder/__init__.py b/spyder/__init__.py index a7fa9dd7cc0..f8797105569 100644 --- a/spyder/__init__.py +++ b/spyder/__init__.py @@ -62,7 +62,7 @@ def get_versions(reporev=True): import qtpy.QtCore from spyder.utils.conda import is_conda_env - from spyder.config.base import is_pynsist, is_conda_based_app + from spyder.config.base import is_conda_based_app revision = branch = None if reporev: @@ -70,7 +70,7 @@ def get_versions(reporev=True): revision, branch = vcs.get_git_revision( os.path.dirname(__current_directory__)) - if is_pynsist() or is_conda_based_app(): + if is_conda_based_app(): installer = 'standalone' elif is_conda_env(pyexec=sys.executable): installer = 'conda' diff --git a/spyder/app/mainwindow.py b/spyder/app/mainwindow.py index 93fe76e76bb..9b24f8b8927 100644 --- a/spyder/app/mainwindow.py +++ b/spyder/app/mainwindow.py @@ -73,7 +73,7 @@ from spyder.api.plugin_registration.registry import PLUGIN_REGISTRY from spyder.api.config.mixins import SpyderConfigurationAccessor from spyder.config.base import (_, DEV, get_conf_path, get_debug_level, - get_home_dir, is_pynsist, is_conda_based_app, + get_home_dir, is_conda_based_app, running_under_pytest, STDERR) from spyder.config.gui import is_dark_font_color from spyder.config.main import OPEN_FILES_PORT @@ -945,7 +945,7 @@ def set_window_title(self): title = u"Spyder %s (Python %s.%s)" % (__version__, sys.version_info[0], sys.version_info[1]) - elif is_conda_based_app() or is_pynsist(): + elif is_conda_based_app(): title = "Spyder" else: title = u"Spyder (Python %s.%s)" % (sys.version_info[0], diff --git a/spyder/config/base.py b/spyder/config/base.py index d323bf21918..da6b16a0daf 100644 --- a/spyder/config/base.py +++ b/spyder/config/base.py @@ -341,16 +341,6 @@ def is_py2exe_or_cx_Freeze(): return osp.isfile(osp.join(get_module_path('spyder'), osp.pardir)) -def is_pynsist(): - """Return True if this is a pynsist installation of Spyder.""" - base_path = osp.abspath(osp.dirname(__file__)) - pkgs_path = osp.abspath( - osp.join(base_path, '..', '..', '..', 'pkgs')) - if os.environ.get('PYTHONPATH') is not None: - return pkgs_path in os.environ.get('PYTHONPATH') - return False - - #============================================================================== # Translations #============================================================================== @@ -569,9 +559,6 @@ def get_spyder_umamba_path(): # TODO: Change to CONDA_EXE when # conda-forge/conda-standalone-feedstock#45 is resolved path = os.environ.get('CONDA_PYTHON_EXE') - elif is_pynsist(): - path = osp.abspath(osp.join(osp.dirname(osp.dirname(__file__)), - 'bin', 'micromamba.exe')) else: path = None diff --git a/spyder/dependencies.py b/spyder/dependencies.py index d0f88a7a09d..33098c025b0 100644 --- a/spyder/dependencies.py +++ b/spyder/dependencies.py @@ -12,7 +12,7 @@ import sys # Local imports -from spyder.config.base import _, is_pynsist, running_in_ci, is_conda_based_app +from spyder.config.base import _, running_in_ci, is_conda_based_app from spyder.utils import programs HERE = osp.dirname(osp.abspath(__file__)) @@ -37,7 +37,7 @@ DIFF_MATCH_PATCH_REQVER = '>=20181111' # None for pynsist install for now # (check way to add dist.info/egg.info from packages without wheels available) -INTERVALTREE_REQVER = None if is_pynsist() else '>=3.0.2' +INTERVALTREE_REQVER = None if os.name == 'nt' and is_conda_based_app() else '>=3.0.2' IPYTHON_REQVER = ">=7.31.1,<9.0.0,!=8.8.0,!=8.9.0,!=8.10.0" JEDI_REQVER = '>=0.17.2,<0.19.0' JELLYFISH_REQVER = '>=0.7' @@ -71,7 +71,7 @@ THREE_MERGE_REQVER = '>=0.1.1' # None for pynsist install for now # (check way to add dist.info/egg.info from packages without wheels available) -WATCHDOG_REQVER = None if is_pynsist() else '>=0.10.3' +WATCHDOG_REQVER = None if os.name == 'nt' and is_conda_based_app() else '>=0.10.3' # Optional dependencies diff --git a/spyder/plugins/application/container.py b/spyder/plugins/application/container.py index 0a5c53116df..fc917828b0f 100644 --- a/spyder/plugins/application/container.py +++ b/spyder/plugins/application/container.py @@ -28,7 +28,7 @@ from spyder.api.widgets.main_container import PluginMainContainer from spyder.utils.installers import InstallerMissingDependencies from spyder.config.utils import is_anaconda -from spyder.config.base import (get_conf_path, get_debug_level, is_pynsist, +from spyder.config.base import (get_conf_path, get_debug_level, is_conda_based_app) from spyder.plugins.application.widgets.status import ApplicationUpdateStatus from spyder.plugins.console.api import ConsoleActions @@ -105,7 +105,7 @@ def setup(self): # Attributes self.dialog_manager = DialogManager() self.application_update_status = None - if is_pynsist() or is_conda_based_app(): + if is_conda_based_app(): self.application_update_status = ApplicationUpdateStatus( parent=self) (self.application_update_status.sig_check_for_updates_requested @@ -318,7 +318,7 @@ def _check_updates_ready(self): "conda update anaconda
" "conda install spyder={}

" ).format(latest_release) - elif is_pynsist() or is_conda_based_app(): + elif is_conda_based_app(): box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) content = _( diff --git a/spyder/plugins/application/widgets/install.py b/spyder/plugins/application/widgets/install.py index ffc6d40ddeb..4d05efe25e4 100644 --- a/spyder/plugins/application/widgets/install.py +++ b/spyder/plugins/application/widgets/install.py @@ -20,7 +20,7 @@ # Local imports from spyder import __version__ from spyder.api.translations import _ -from spyder.config.base import is_pynsist +from spyder.config.base import is_conda_based_app from spyder.utils.icon_manager import ima from spyder.workers.updates import WorkerDownloadInstaller @@ -257,7 +257,7 @@ def confirm_installation(self, installer_path): ) msg_box.setWindowTitle(_("Spyder update")) msg_box.setAttribute(Qt.WA_ShowWithoutActivating) - if is_pynsist(): + if os.name == 'nt' and is_conda_based_app(): # Only add yes button for Windows installer # since it has the logic to restart Spyder yes_button = msg_box.addButton(QMessageBox.Yes) diff --git a/spyder/plugins/application/widgets/status.py b/spyder/plugins/application/widgets/status.py index 357c28e06c3..2bacc493102 100644 --- a/spyder/plugins/application/widgets/status.py +++ b/spyder/plugins/application/widgets/status.py @@ -19,7 +19,7 @@ # Local imports from spyder.api.translations import _ from spyder.api.widgets.status import StatusBarWidget -from spyder.config.base import is_pynsist, is_conda_based_app +from spyder.config.base import is_conda_based_app from spyder.plugins.application.widgets.install import ( UpdateInstallerDialog, NO_STATUS, DOWNLOADING_INSTALLER, INSTALLING, PENDING, CHECKING) @@ -148,12 +148,12 @@ def set_no_status(self): def show_installation_dialog_or_menu(self): """Show installation dialog or menu.""" value = self.value.split(":")[-1].strip() - if ((not self.tooltip == self.BASE_TOOLTIP - and not value == PENDING) - and (is_pynsist() or is_conda_based_app())): + if ( + self.tooltip != self.BASE_TOOLTIP and value != PENDING + and is_conda_based_app() + ): self.installer.show() - elif (value == PENDING and - (is_pynsist() or is_conda_based_app())): + elif value == PENDING and is_conda_based_app(): self.installer.continue_installation() elif value == NO_STATUS: self.menu.clear() diff --git a/spyder/plugins/completion/providers/languageserver/client.py b/spyder/plugins/completion/providers/languageserver/client.py index d00efa31f9d..fa5cd0c64af 100644 --- a/spyder/plugins/completion/providers/languageserver/client.py +++ b/spyder/plugins/completion/providers/languageserver/client.py @@ -28,7 +28,8 @@ # Local imports from spyder.api.config.mixins import SpyderConfigurationAccessor from spyder.config.base import ( - DEV, get_conf_path, get_debug_level, is_pynsist, running_under_pytest) + DEV, get_conf_path, get_debug_level, is_conda_based_app, + running_under_pytest) from spyder.config.utils import is_anaconda from spyder.plugins.completion.api import ( CLIENT_CAPABILITES, SERVER_CAPABILITES, @@ -280,7 +281,7 @@ def start_server(self): # that directory. # Fixes spyder-ide/spyder#17661 if ( - not (is_anaconda() or is_pynsist()) + not (is_anaconda() or is_conda_based_app()) and "APPDATA" in os.environ ): env.insert("APPDATA", os.environ["APPDATA"]) diff --git a/spyder/plugins/ipythonconsole/utils/kernelspec.py b/spyder/plugins/ipythonconsole/utils/kernelspec.py index e1e616f5d0a..44ee91aa50e 100644 --- a/spyder/plugins/ipythonconsole/utils/kernelspec.py +++ b/spyder/plugins/ipythonconsole/utils/kernelspec.py @@ -20,7 +20,7 @@ # Local imports from spyder.api.config.mixins import SpyderConfigurationAccessor from spyder.api.translations import _ -from spyder.config.base import (get_safe_mode, is_pynsist, is_conda_based_app, +from spyder.config.base import (get_safe_mode, is_conda_based_app, running_under_pytest) from spyder.plugins.ipythonconsole import ( SPYDER_KERNELS_CONDA, SPYDER_KERNELS_PIP, SPYDER_KERNELS_VERSION, @@ -234,7 +234,7 @@ def env(self): # App considerations # ??? Do we need this? - if (is_conda_based_app() or is_pynsist()) and default_interpreter: + if is_conda_based_app() and default_interpreter: # See spyder-ide/spyder#16927 # See spyder-ide/spyder#16828 # See spyder-ide/spyder#17552 diff --git a/spyder/plugins/ipythonconsole/widgets/shell.py b/spyder/plugins/ipythonconsole/widgets/shell.py index 04436348aac..0648933344c 100644 --- a/spyder/plugins/ipythonconsole/widgets/shell.py +++ b/spyder/plugins/ipythonconsole/widgets/shell.py @@ -22,8 +22,7 @@ from traitlets import observe # Local imports -from spyder.config.base import ( - _, is_pynsist, is_conda_based_app, running_under_pytest) +from spyder.config.base import _, is_conda_based_app, running_under_pytest from spyder.config.gui import get_color_scheme, is_dark_interface from spyder.py3compat import to_text_string from spyder.utils.palette import QStylePalette, SpyderPalette @@ -178,7 +177,7 @@ def __init__(self, ipyclient, additional_options, interpreter_versions, # Show a message in our installers to explain users how to use # modules that don't come with them. - self.show_modules_message = is_pynsist() or is_conda_based_app() + self.show_modules_message = is_conda_based_app() # ---- Public API --------------------------------------------------------- @property diff --git a/spyder/plugins/maininterpreter/widgets/status.py b/spyder/plugins/maininterpreter/widgets/status.py index 8439b9d85f5..8c2cc92faa8 100644 --- a/spyder/plugins/maininterpreter/widgets/status.py +++ b/spyder/plugins/maininterpreter/widgets/status.py @@ -17,7 +17,7 @@ # Local imports from spyder.api.widgets.status import BaseTimerStatus -from spyder.config.base import is_pynsist, is_conda_based_app +from spyder.config.base import is_conda_based_app from spyder.utils.envs import get_list_envs from spyder.utils.programs import get_interpreter_info from spyder.utils.workers import WorkerManager @@ -44,7 +44,8 @@ def __init__(self, parent, icon=None, interpreter=None): self.value = '' self.default_interpreter = sys.executable - if is_pynsist(): + # ??? Do we need this? + if os.name == 'nt' and is_conda_based_app(): # Be sure to use 'python' executable instead of 'pythonw' since # no output is generated with 'pythonw'. self.default_interpreter = self.default_interpreter.replace( @@ -112,10 +113,7 @@ def _get_env_info(self, path): try: name = self.path_to_env[path] except KeyError: - if ( - self.default_interpreter == path - and (is_conda_based_app() or is_pynsist()) - ): + if self.default_interpreter == path and is_conda_based_app(): name = 'internal' elif 'conda' in path: name = 'conda' diff --git a/spyder/plugins/onlinehelp/widgets.py b/spyder/plugins/onlinehelp/widgets.py index 2936a752615..e99a2e945d8 100644 --- a/spyder/plugins/onlinehelp/widgets.py +++ b/spyder/plugins/onlinehelp/widgets.py @@ -23,7 +23,7 @@ # Local imports from spyder.api.translations import _ from spyder.api.widgets.main_widget import PluginMainWidget -from spyder.config.base import is_pynsist +from spyder.config.base import is_conda_based_app from spyder.plugins.onlinehelp.pydoc_patch import _start_server, _url_handler from spyder.widgets.browser import FrameWebView, WebViewActions from spyder.widgets.comboboxes import UrlComboBox @@ -71,7 +71,8 @@ def spyder_safeimport(path, forceload=0, cache={}): # Needed to prevent showing a warning message regarding debugging # See spyder-ide/spyder#20390 -if is_pynsist(): +# ??? Do we need this? +if is_conda_based_app(): os.environ["PYDEVD_DISABLE_FILE_VALIDATION"] = "1" diff --git a/spyder/plugins/pylint/main_widget.py b/spyder/plugins/pylint/main_widget.py index 60658d99473..45329d9ca5c 100644 --- a/spyder/plugins/pylint/main_widget.py +++ b/spyder/plugins/pylint/main_widget.py @@ -31,7 +31,7 @@ from spyder.api.config.decorators import on_conf_change from spyder.api.translations import _ from spyder.api.widgets.main_widget import PluginMainWidget -from spyder.config.base import get_conf_path, is_pynsist +from spyder.config.base import get_conf_path, is_conda_based_app from spyder.config.utils import is_anaconda from spyder.plugins.pylint.utils import get_pylintrc_path from spyder.plugins.variableexplorer.widgets.texteditor import TextEditor @@ -60,7 +60,6 @@ MAIN_PREVRATE_COLOR = QStylePalette.COLOR_TEXT_1 - class PylintWidgetActions: ChangeHistory = "change_history_depth_action" RunCodeAnalysis = "run_analysis_action" @@ -372,7 +371,7 @@ def _start(self): processEnvironment.insert("USERPROFILE", user_profile) # Needed for Windows installations using standalone Python and pip. # See spyder-ide/spyder#19385 - if not is_pynsist() and not is_anaconda(): + if not is_conda_based_app() and not is_anaconda(): processEnvironment.insert("APPDATA", os.environ.get("APPDATA")) process.setProcessEnvironment(processEnvironment) diff --git a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py index ac820e266bb..da7c79de88c 100644 --- a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py +++ b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py @@ -24,7 +24,7 @@ is_known_type) # Local imports -from spyder.config.base import _, is_pynsist, is_conda_based_app +from spyder.config.base import _, is_conda_based_app from spyder.config.fonts import DEFAULT_SMALL_DELTA from spyder.config.gui import get_font from spyder.py3compat import is_binary_string, is_text_string, to_text_string @@ -130,7 +130,7 @@ def createEditor(self, parent, option, index, object_explorer=False): message.format(val_type=val_type, module=module)) return else: - if is_conda_based_app() or is_pynsist(): + if is_conda_based_app(): message = _("Spyder is unable to show the variable you're" " trying to view because the module " "{module} is not supported in the " diff --git a/spyder/widgets/reporterror.py b/spyder/widgets/reporterror.py index 48db1ea0387..e5187b725bc 100644 --- a/spyder/widgets/reporterror.py +++ b/spyder/widgets/reporterror.py @@ -23,7 +23,7 @@ from spyder import (__project_url__, __trouble_url__, dependencies, get_versions_text) from spyder.api.config.mixins import SpyderConfigurationAccessor -from spyder.config.base import _, is_pynsist, is_conda_based_app +from spyder.config.base import _, is_conda_based_app from spyder.config.gui import get_font from spyder.plugins.console.widgets.console import ConsoleBaseWidget from spyder.utils.conda import is_conda_env, get_conda_env_path, find_conda @@ -255,7 +255,7 @@ def __init__(self, parent=None, is_report=False): # Only provide checkbox if not an installer default interpreter if ( - not (is_pynsist() or is_conda_based_app()) + not is_conda_based_app() or not self.get_conf('default', section='main_interpreter') ): layout.addWidget(self.include_env) From a83bebbe3c4fef1e08fe90126a6654f353ec5f80 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Thu, 13 Apr 2023 20:36:30 -0700 Subject: [PATCH 07/17] Remove reference to micromamba since standalone conda executable is now bundled with conda-based installers --- spyder/config/base.py | 9 ++++----- spyder/utils/conda.py | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/spyder/config/base.py b/spyder/config/base.py index da6b16a0daf..48eb75e6046 100644 --- a/spyder/config/base.py +++ b/spyder/config/base.py @@ -550,11 +550,10 @@ def is_conda_based_app(pyexec=sys.executable): return osp.exists(menu_path) -# ============================================================================= -# Micromamba -# ============================================================================= -def get_spyder_umamba_path(): - """Return the path to the Micromamba executable bundled with Spyder.""" +def get_spyder_conda_path(): + """ + Return the path to the conda executable from the conda-based installer. + """ if is_conda_based_app(): # TODO: Change to CONDA_EXE when # conda-forge/conda-standalone-feedstock#45 is resolved diff --git a/spyder/utils/conda.py b/spyder/utils/conda.py index f5a4d33272d..04218f23955 100644 --- a/spyder/utils/conda.py +++ b/spyder/utils/conda.py @@ -13,7 +13,7 @@ import sys from spyder.utils.programs import find_program, run_program, run_shell_command -from spyder.config.base import get_spyder_umamba_path +from spyder.config.base import get_spyder_conda_path WINDOWS = os.name == 'nt' CONDA_ENV_LIST_CACHE = {} @@ -70,8 +70,8 @@ def get_conda_activation_script(quote=False): If `quote` is True, then quotes are added if spaces are found in the path. """ - # Use micromamba bundled with Spyder installers or find conda exe - standalone_exe = get_spyder_umamba_path() + # Use conda bundled with Spyder conda-based installers or find conda exe + standalone_exe = get_spyder_conda_path() exe = standalone_exe or find_conda() if osp.basename(exe) in ('micromamba.exe', 'conda.exe') and standalone_exe: From 80902a15504e8c3c370f788f77f508f10b52667a Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Mon, 24 Apr 2023 13:00:18 -0700 Subject: [PATCH 08/17] Move get_spyder_conda_path to find_conda, which should first look for Spyder's mamba executable (from conda-based installers). When testing for standalone conda executable, use endswith in order to capture '_conda.exe' as well as 'conda.exe' Non-standalone conda executables are in the same directory as activate; no need to back out two directory levels and go back in. Enforce correct CONDA_EXE environment variable for conda-based installers. --- spyder/app/start.py | 12 +++++++++++- spyder/config/base.py | 14 -------------- spyder/utils/conda.py | 32 +++++++++++++++++--------------- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/spyder/app/start.py b/spyder/app/start.py index fb015174701..8f8ecccab10 100644 --- a/spyder/app/start.py +++ b/spyder/app/start.py @@ -51,10 +51,20 @@ # Local imports from spyder.app.cli_options import get_options from spyder.config.base import (get_conf_path, reset_config_files, - running_under_pytest) + running_under_pytest, is_conda_based_app) +from spyder.utils.conda import get_conda_root_prefix from spyder.utils.external import lockfile from spyder.py3compat import is_text_string +# Enforce correct CONDA_EXE environment variable +# Do not rely on CONDA_PYTHON_EXE or CONDA_PREFIX in case Spyder is started +# from the commandline +if is_conda_based_app(): + conda_root = get_conda_root_prefix() + if os.name == 'nt': + os.environ['CONDA_EXE'] = conda_root + r'\Scripts\conda.exe' + else: + os.environ['CONDA_EXE'] = conda_root + '/bin/conda' # Get argv if running_under_pytest(): diff --git a/spyder/config/base.py b/spyder/config/base.py index 48eb75e6046..64b5b94cd1a 100644 --- a/spyder/config/base.py +++ b/spyder/config/base.py @@ -550,20 +550,6 @@ def is_conda_based_app(pyexec=sys.executable): return osp.exists(menu_path) -def get_spyder_conda_path(): - """ - Return the path to the conda executable from the conda-based installer. - """ - if is_conda_based_app(): - # TODO: Change to CONDA_EXE when - # conda-forge/conda-standalone-feedstock#45 is resolved - path = os.environ.get('CONDA_PYTHON_EXE') - else: - path = None - - return path - - #============================================================================== # Reset config files #============================================================================== diff --git a/spyder/utils/conda.py b/spyder/utils/conda.py index 04218f23955..63207340985 100644 --- a/spyder/utils/conda.py +++ b/spyder/utils/conda.py @@ -13,7 +13,7 @@ import sys from spyder.utils.programs import find_program, run_program, run_shell_command -from spyder.config.base import get_spyder_conda_path +from spyder.config.base import is_conda_based_app WINDOWS = os.name == 'nt' CONDA_ENV_LIST_CACHE = {} @@ -70,21 +70,14 @@ def get_conda_activation_script(quote=False): If `quote` is True, then quotes are added if spaces are found in the path. """ - # Use conda bundled with Spyder conda-based installers or find conda exe - standalone_exe = get_spyder_conda_path() - exe = standalone_exe or find_conda() + exe = find_conda() - if osp.basename(exe) in ('micromamba.exe', 'conda.exe') and standalone_exe: + if exe.endswith(('micromamba.exe', 'conda.exe', 'micromamba')): # For standalone conda, use the executable script_path = exe else: - # Conda activation script is relative to executable - conda_exe_root = osp.dirname(osp.dirname(exe)) - if WINDOWS: - activate = 'Scripts/activate' - else: - activate = 'bin/activate' - script_path = osp.join(conda_exe_root, activate) + # If not a standalone executable, activate is in same directory + script_path = osp.dirname(exe) + '/activate' script_path = script_path.replace('\\', '/') @@ -114,12 +107,21 @@ def get_conda_env_path(pyexec, quote=False): def find_conda(): """Find conda executable.""" - # First try the environment variables - conda = os.environ.get('CONDA_EXE') or os.environ.get('MAMBA_EXE') + conda = None + + # First try Spyder's conda executable + if is_conda_based_app(): + conda = osp.join(osp.dirname(os.environ['CONDA_EXE']), 'mamba') + + # Next try the environment variables + if conda is None: + conda = os.environ.get('CONDA_EXE') or os.environ.get('MAMBA_EXE') + + # Next try searching for the executable if conda is None: - # Try searching for the executable conda_exec = 'conda.bat' if WINDOWS else 'conda' conda = find_program(conda_exec) + return conda From eddeb6e5d5512a732ddd2cbe60f13ddddcc735fb Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Mon, 24 Apr 2023 17:45:05 -0700 Subject: [PATCH 09/17] Remove conda-based Spyder runtime environments, and base environments thereof, from custom interpreter list. Note that sys.executable may be a symlink for conda-based runtime environments. Windows requires USERPROFILE environment variable to find all conda environments. --- spyder/config/base.py | 18 +++++++++++++----- .../plugins/ipythonconsole/utils/kernelspec.py | 7 +++++-- spyder/plugins/maininterpreter/confpage.py | 17 +++++++++-------- spyder/utils/programs.py | 2 +- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/spyder/config/base.py b/spyder/config/base.py index 64b5b94cd1a..095e8a9b3bf 100644 --- a/spyder/config/base.py +++ b/spyder/config/base.py @@ -12,6 +12,7 @@ sip API incompatibility issue in spyder's non-gui modules) """ +from glob import glob import locale import os import os.path as osp @@ -538,17 +539,24 @@ def is_conda_based_app(pyexec=sys.executable): Check if Spyder is running from the conda-based installer by looking for the `spyder-menu.json` file. - If a Python executable is provided, checks if it is the same as a - conda-based installer environment executable. + If a Python executable is provided, checks if it is in a conda-based + installer environment or the root environment thereof. """ real_pyexec = osp.realpath(pyexec) # pyexec may be symlink if os.name == 'nt': env_path = osp.dirname(real_pyexec) else: env_path = osp.dirname(osp.dirname(real_pyexec)) - menu_path = osp.join(env_path, 'Menu', 'spyder-menu.json') - - return osp.exists(menu_path) + + menu_rel_path = '/Menu/spyder-menu.json' + if ( + osp.exists(env_path + menu_rel_path) + or glob(env_path + '/envs/*' + menu_rel_path) + ): + return True + else: + return False + #============================================================================== # Reset config files diff --git a/spyder/plugins/ipythonconsole/utils/kernelspec.py b/spyder/plugins/ipythonconsole/utils/kernelspec.py index 44ee91aa50e..b1d8517f707 100644 --- a/spyder/plugins/ipythonconsole/utils/kernelspec.py +++ b/spyder/plugins/ipythonconsole/utils/kernelspec.py @@ -55,8 +55,11 @@ def is_different_interpreter(pyexec): """Check that pyexec is a different interpreter from sys.executable.""" - executable_validation = osp.basename(pyexec).startswith('python') - directory_validation = osp.dirname(pyexec) != osp.dirname(sys.executable) + # Paths may be symlinks + real_pyexe = osp.realpath(pyexec) + real_sys_exe = osp.realpath(sys.executable) + executable_validation = osp.basename(real_pyexe).startswith('python') + directory_validation = osp.dirname(real_pyexe) != osp.dirname(real_sys_exe) return directory_validation and executable_validation diff --git a/spyder/plugins/maininterpreter/confpage.py b/spyder/plugins/maininterpreter/confpage.py index c760336998c..368a4bc58ae 100644 --- a/spyder/plugins/maininterpreter/confpage.py +++ b/spyder/plugins/maininterpreter/confpage.py @@ -18,6 +18,7 @@ # Local imports from spyder.api.translations import _ from spyder.api.preferences import PluginConfigPage +from spyder.config.base import is_conda_based_app from spyder.py3compat import to_text_string from spyder.utils import programs from spyder.utils.conda import get_list_conda_envs_cache @@ -80,7 +81,7 @@ def setup_page(self): ) if os.name == 'nt': - filters = _("Executables")+" (*.exe)" + filters = _("Executables") + " (*.exe)" else: filters = None @@ -174,12 +175,12 @@ def warn_python_compatibility(self, pyexec): QMessageBox.warning( self, _('Warning'), - _("You selected a Python %d interpreter for the console " - "but Spyder is running on Python %d!.

" + _("You selected a Python %d interpreter for the " + "console but Spyder is running on Python %d!.

" "Although this is possible, we recommend you to install and " - "run Spyder directly with your selected interpreter, to avoid " - "seeing false warnings and errors due to the incompatible " - "syntax between these two Python versions." + "run Spyder directly with your selected interpreter, to " + "avoid seeing false warnings and errors due to the " + "incompatible syntax between these two Python versions." ) % (console_version, spyder_version), QMessageBox.Ok, ) @@ -206,7 +207,7 @@ def set_umr_namelist(self): if programs.is_module_installed(module_name): fixed_namelist.append(module_name) - invalid = ", ".join(set(namelist)-set(fixed_namelist)- + invalid = ", ".join(set(namelist) - set(fixed_namelist) - set(non_ascii_namelist)) if invalid: QMessageBox.warning( @@ -233,7 +234,7 @@ def validate_custom_interpreters_list(self): custom_list = self.get_option('custom_interpreters_list') valid_custom_list = [] for value in custom_list: - if osp.isfile(value): + if osp.isfile(value) and not is_conda_based_app(value): valid_custom_list.append(value) self.set_option('custom_interpreters_list', valid_custom_list) diff --git a/spyder/utils/programs.py b/spyder/utils/programs.py index 75c0d7cd4e7..8bbcaa87517 100644 --- a/spyder/utils/programs.py +++ b/spyder/utils/programs.py @@ -177,7 +177,7 @@ def alter_subprocess_kwargs_by_platform(**kwargs): # ensure Windows subprocess environment has SYSTEMROOT if kwargs.get('env') is not None: # Is SYSTEMROOT, SYSTEMDRIVE in env? case insensitive - for env_var in ['SYSTEMROOT', 'SYSTEMDRIVE']: + for env_var in ['SYSTEMROOT', 'SYSTEMDRIVE', 'USERPROFILE']: if env_var not in map(str.upper, kwargs['env'].keys()): # Add from os.environ for k, v in os.environ.items(): From 57432a0042eac293e30a4c16b6bfe8e17c4a6a2a Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Sat, 15 Apr 2023 09:34:32 -0700 Subject: [PATCH 10/17] Simplify spyder-kernels startup by using conda's run command. Obviates conda-activate.[sh|bat] and get_conda_activation_script. --- .../ipythonconsole/scripts/conda-activate.bat | 26 ----------- .../ipythonconsole/scripts/conda-activate.sh | 18 -------- .../ipythonconsole/utils/kernelspec.py | 46 ++++++++----------- spyder/utils/conda.py | 23 ---------- spyder/utils/tests/test_conda.py | 9 +--- 5 files changed, 22 insertions(+), 100 deletions(-) delete mode 100755 spyder/plugins/ipythonconsole/scripts/conda-activate.bat delete mode 100755 spyder/plugins/ipythonconsole/scripts/conda-activate.sh diff --git a/spyder/plugins/ipythonconsole/scripts/conda-activate.bat b/spyder/plugins/ipythonconsole/scripts/conda-activate.bat deleted file mode 100755 index 87ff84188a3..00000000000 --- a/spyder/plugins/ipythonconsole/scripts/conda-activate.bat +++ /dev/null @@ -1,26 +0,0 @@ -:: This scripts helps activate a conda environment before running a spyder-kernel -@echo off - -:: Create variables for arguments -set CONDA_ACTIVATE_SCRIPT=%1 -set CONDA_ENV_PATH=%2 -set CONDA_ENV_PYTHON=%3 -set SPYDER_KERNEL_SPEC=%4 - -:: Enforce encoding -chcp 65001>nul - -:: Activate kernel environment -echo %CONDA_ACTIVATE_SCRIPT%| findstr /e "micromamba.exe">Nul && goto micromamba || goto conda - -:micromamba Activate using micromamba -for /f %%i in ('%CONDA_ACTIVATE_SCRIPT% shell activate %CONDA_ENV_PATH%') do set SCRIPT=%%i -call %SCRIPT% -goto start - -:conda Activate using conda -call %CONDA_ACTIVATE_SCRIPT% %CONDA_ENV_PATH% -goto start - -:start Start kernel -%CONDA_ENV_PYTHON% -m spyder_kernels.console -f %SPYDER_KERNEL_SPEC% diff --git a/spyder/plugins/ipythonconsole/scripts/conda-activate.sh b/spyder/plugins/ipythonconsole/scripts/conda-activate.sh deleted file mode 100755 index 56cc34ee8f1..00000000000 --- a/spyder/plugins/ipythonconsole/scripts/conda-activate.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -# This script helps activate a conda environment before running a spyder-kernel - -# Create variables for arguments -CONDA_ACTIVATE_SCRIPT=$1 -CONDA_ENV_PATH=$2 -CONDA_ENV_PYTHON=$3 -SPYDER_KERNEL_SPEC=$4 - -# Activate kernel environment -if [[ "$CONDA_ACTIVATE_SCRIPT" = *"conda.exe" ]]; then - eval "$($CONDA_ACTIVATE_SCRIPT shell.bash activate $CONDA_ENV_PATH)" -else - source $CONDA_ACTIVATE_SCRIPT $CONDA_ENV_PATH -fi - -# Start kernel -$CONDA_ENV_PYTHON -m spyder_kernels.console -f $SPYDER_KERNEL_SPEC diff --git a/spyder/plugins/ipythonconsole/utils/kernelspec.py b/spyder/plugins/ipythonconsole/utils/kernelspec.py index b1d8517f707..e35eed1cdc1 100644 --- a/spyder/plugins/ipythonconsole/utils/kernelspec.py +++ b/spyder/plugins/ipythonconsole/utils/kernelspec.py @@ -25,8 +25,8 @@ from spyder.plugins.ipythonconsole import ( SPYDER_KERNELS_CONDA, SPYDER_KERNELS_PIP, SPYDER_KERNELS_VERSION, SpyderKernelError) -from spyder.utils.conda import (add_quotes, get_conda_activation_script, - get_conda_env_path, is_conda_env) +from spyder.utils.conda import (add_quotes, get_conda_env_path, is_conda_env, + find_conda) from spyder.utils.environ import clean_env from spyder.utils.misc import get_python_executable from spyder.utils.programs import is_python_interpreter, is_module_installed @@ -127,11 +127,11 @@ def argv(self): if not has_spyder_kernels(pyexec): raise SpyderKernelError( ERROR_SPYDER_KERNEL_INSTALLED.format( - pyexec, - SPYDER_KERNELS_VERSION, - SPYDER_KERNELS_CONDA, - SPYDER_KERNELS_PIP - ) + pyexec, + SPYDER_KERNELS_VERSION, + SPYDER_KERNELS_CONDA, + SPYDER_KERNELS_PIP + ) ) return if not is_python_interpreter(pyexec): @@ -144,27 +144,21 @@ def argv(self): is_different = is_different_interpreter(pyexec) # Command used to start kernels + kernel_cmd = [ + pyexec, + '-m', 'spyder_kernels.console', + '-f', '{connection_file}' + ] + if is_different and is_conda_env(pyexec=pyexec): - # If this is a conda environment we need to call an intermediate - # activation script to correctly activate the spyder-kernel - - # If changes are needed on this section make sure you also update - # the activation scripts at spyder/plugins/ipythonconsole/scripts/ - kernel_cmd = [ - get_activation_script(), # This is bundled with Spyder - get_conda_activation_script(), - get_conda_env_path(pyexec), # Might be external - pyexec, - '{connection_file}', - ] - else: - kernel_cmd = [ - pyexec, - '-m', - 'spyder_kernels.console', - '-f', - '{connection_file}' + # If executable is a conda environment and different from Spyder's + # runtime environment, we need to activate the environment to run + # spyder-kernels + kernel_cmd[:0] = [ + find_conda(), 'run', + '-p', get_conda_env_path(pyexec), ] + logger.info('Kernel command: {}'.format(kernel_cmd)) return kernel_cmd diff --git a/spyder/utils/conda.py b/spyder/utils/conda.py index 63207340985..2efed939754 100644 --- a/spyder/utils/conda.py +++ b/spyder/utils/conda.py @@ -64,29 +64,6 @@ def get_conda_root_prefix(pyexec=None, quote=False): return root_prefix -def get_conda_activation_script(quote=False): - """ - Return full path to conda activation script. - - If `quote` is True, then quotes are added if spaces are found in the path. - """ - exe = find_conda() - - if exe.endswith(('micromamba.exe', 'conda.exe', 'micromamba')): - # For standalone conda, use the executable - script_path = exe - else: - # If not a standalone executable, activate is in same directory - script_path = osp.dirname(exe) + '/activate' - - script_path = script_path.replace('\\', '/') - - if quote: - script_path = add_quotes(script_path) - - return script_path - - def get_conda_env_path(pyexec, quote=False): """ Return the full path to the conda environment from give python executable. diff --git a/spyder/utils/tests/test_conda.py b/spyder/utils/tests/test_conda.py index 504225ed935..19b60d3450b 100644 --- a/spyder/utils/tests/test_conda.py +++ b/spyder/utils/tests/test_conda.py @@ -18,8 +18,8 @@ from spyder.config.base import running_in_ci from spyder.config.utils import is_anaconda from spyder.utils.conda import ( - add_quotes, find_conda, get_conda_activation_script, get_conda_env_path, - get_conda_root_prefix, get_list_conda_envs, get_list_conda_envs_cache) + add_quotes, find_conda, get_conda_env_path, get_conda_root_prefix, + get_list_conda_envs, get_list_conda_envs_cache) if not is_anaconda(): @@ -39,11 +39,6 @@ def test_add_quotes(): assert output == '/some-path/with-no-spaces' -def test_get_conda_activation_script(): - output = get_conda_activation_script() - assert os.path.exists(output) - - def test_get_conda_env_path(): output = get_conda_env_path(TEST_PYEXEC) if os.name == 'nt': From 7710c1aa105e7cbad3cf17404cfa3a644f7f88e1 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Mon, 17 Apr 2023 15:05:27 -0700 Subject: [PATCH 11/17] Windows CI now sees test environment --- spyder/utils/tests/test_conda.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/spyder/utils/tests/test_conda.py b/spyder/utils/tests/test_conda.py index 19b60d3450b..47cea1be096 100644 --- a/spyder/utils/tests/test_conda.py +++ b/spyder/utils/tests/test_conda.py @@ -65,11 +65,7 @@ def test_find_conda(): @pytest.mark.skipif(not running_in_ci(), reason="Only meant for CIs") def test_get_list_conda_envs(): output = get_list_conda_envs() - expected_envs = ['base', 'jedi-test-env', 'spytest-ž'] - - # Conda can't detect the test env on Windows, don't know why. - if os.name != 'nt': - expected_envs.append('test') + expected_envs = ['base', 'test', 'jedi-test-env', 'spytest-ž'] expected_envs = ['conda: ' + env for env in expected_envs] assert set(expected_envs) == set(output.keys()) From 86511fce4944f3f123d1b3eb420a36f7ab22875c Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Tue, 18 Apr 2023 21:47:19 -0700 Subject: [PATCH 12/17] Apply suggestions from code review Co-authored-by: Carlos Cordoba --- spyder/__init__.py | 3 ++- spyder/dependencies.py | 8 ++------ spyder/plugins/application/widgets/status.py | 3 ++- spyder/plugins/maininterpreter/widgets/status.py | 1 - 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/spyder/__init__.py b/spyder/__init__.py index f8797105569..708a699ce5b 100644 --- a/spyder/__init__.py +++ b/spyder/__init__.py @@ -68,7 +68,8 @@ def get_versions(reporev=True): if reporev: from spyder.utils import vcs revision, branch = vcs.get_git_revision( - os.path.dirname(__current_directory__)) + os.path.dirname(__current_directory__) + ) if is_conda_based_app(): installer = 'standalone' diff --git a/spyder/dependencies.py b/spyder/dependencies.py index 33098c025b0..6e68edf9a48 100644 --- a/spyder/dependencies.py +++ b/spyder/dependencies.py @@ -35,9 +35,7 @@ CLOUDPICKLE_REQVER = '>=0.5.0' COOKIECUTTER_REQVER = '>=1.6.0' DIFF_MATCH_PATCH_REQVER = '>=20181111' -# None for pynsist install for now -# (check way to add dist.info/egg.info from packages without wheels available) -INTERVALTREE_REQVER = None if os.name == 'nt' and is_conda_based_app() else '>=3.0.2' +INTERVALTREE_REQVER = '>=3.0.2' IPYTHON_REQVER = ">=7.31.1,<9.0.0,!=8.8.0,!=8.9.0,!=8.10.0" JEDI_REQVER = '>=0.17.2,<0.19.0' JELLYFISH_REQVER = '>=0.7' @@ -69,9 +67,7 @@ SPYDER_KERNELS_REQVER = '>=2.4.3,<2.5.0' TEXTDISTANCE_REQVER = '>=4.2.0' THREE_MERGE_REQVER = '>=0.1.1' -# None for pynsist install for now -# (check way to add dist.info/egg.info from packages without wheels available) -WATCHDOG_REQVER = None if os.name == 'nt' and is_conda_based_app() else '>=0.10.3' +WATCHDOG_REQVER = '>=0.10.3' # Optional dependencies diff --git a/spyder/plugins/application/widgets/status.py b/spyder/plugins/application/widgets/status.py index 2bacc493102..ea23a6aa1e9 100644 --- a/spyder/plugins/application/widgets/status.py +++ b/spyder/plugins/application/widgets/status.py @@ -149,7 +149,8 @@ def show_installation_dialog_or_menu(self): """Show installation dialog or menu.""" value = self.value.split(":")[-1].strip() if ( - self.tooltip != self.BASE_TOOLTIP and value != PENDING + self.tooltip != self.BASE_TOOLTIP + and value != PENDING and is_conda_based_app() ): self.installer.show() diff --git a/spyder/plugins/maininterpreter/widgets/status.py b/spyder/plugins/maininterpreter/widgets/status.py index 8c2cc92faa8..9c83fe72405 100644 --- a/spyder/plugins/maininterpreter/widgets/status.py +++ b/spyder/plugins/maininterpreter/widgets/status.py @@ -44,7 +44,6 @@ def __init__(self, parent, icon=None, interpreter=None): self.value = '' self.default_interpreter = sys.executable - # ??? Do we need this? if os.name == 'nt' and is_conda_based_app(): # Be sure to use 'python' executable instead of 'pythonw' since # no output is generated with 'pythonw'. From 89965ac6260809a7bc42897a633848870d88db40 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Fri, 21 Apr 2023 09:20:03 -0700 Subject: [PATCH 13/17] Apply suggestions from code review --- spyder/plugins/application/confpage.py | 4 ++-- .../variableexplorer/widgets/collectionsdelegate.py | 10 ++-------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/spyder/plugins/application/confpage.py b/spyder/plugins/application/confpage.py index f34c8ae5b46..38df265a0b4 100644 --- a/spyder/plugins/application/confpage.py +++ b/spyder/plugins/application/confpage.py @@ -69,8 +69,8 @@ def setup_page(self): 'check_updates_on_startup') # Decide if it's possible to activate or not single instance mode - # ??? Should this apply to all conda-based installers? - if is_conda_based_app(): + # ??? Should we allow multiple instances for macOS? + if sys.platform == 'darwin' and is_conda_based_app(): self.set_option("single_instance", True) single_instance_box.setEnabled(False) diff --git a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py index da7c79de88c..771461c556a 100644 --- a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py +++ b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py @@ -119,12 +119,6 @@ def createEditor(self, parent, option, index, object_explorer=False): message = _("Spyder is unable to show the {val_type} or object" " you're trying to view because {module}" " is not installed. ") - if is_conda_based_app(): - message += _("Please consider using the full version of " - "the Spyder MacOS application.
") - else: - message += _("Please install this package in your Spyder " - "environment.
") QMessageBox.critical( self.parent(), _("Error"), message.format(val_type=val_type, module=module)) @@ -133,8 +127,8 @@ def createEditor(self, parent, option, index, object_explorer=False): if is_conda_based_app(): message = _("Spyder is unable to show the variable you're" " trying to view because the module " - "{module} is not supported in the " - "Spyder Lite application.
") + "{module} is not supported " + "by Spyder.
") else: message = _("Spyder is unable to show the variable you're" " trying to view because the module " From 19249414e993fac010d5c28698cb4fcaffd413e5 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Mon, 24 Apr 2023 07:24:46 -0700 Subject: [PATCH 14/17] Apply suggestions from code review. Flow control in projects plugin does not need to distinguish conda-based Spyder from other installations. CLI works for macOS, Linux, and Windows. Corrected syntax to the Windows command allows for commandline arguments passed to the batch file. --- installers-conda/resources/spyder-menu.json | 5 +++-- spyder/app/cli_options.py | 2 +- spyder/plugins/projects/plugin.py | 18 ++++++++---------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/installers-conda/resources/spyder-menu.json b/installers-conda/resources/spyder-menu.json index 72d7bf45372..ec884e8de87 100644 --- a/installers-conda/resources/spyder-menu.json +++ b/installers-conda/resources/spyder-menu.json @@ -7,13 +7,13 @@ "name": "Spyder", "description": "Scientific PYthon Development EnviRonment", "icon": "{{ MENU_DIR }}/spyder.{{ ICON_EXT }}", - "command": ["spyder", "$@"], "activate": true, "terminal": false, "platforms": { "win": { "desktop": true, - "precommand": "set SPY_BRANCH=__SPY_BRANCH__\nset SPY_COMMIT=__SPY_COMMIT__" + "precommand": "set SPY_BRANCH=__SPY_BRANCH__\nset SPY_COMMIT=__SPY_COMMIT__", + "command": ["spyder", "%*"] }, "linux": { "Categories": [ @@ -21,6 +21,7 @@ "Science" ], "precommand": "export SPY_BRANCH=__SPY_BRANCH__ && export SPY_COMMIT=__SPY_COMMIT__", + "command": ["spyder", "$@"], "StartupWMClass": "Spyder" }, "osx": { diff --git a/spyder/app/cli_options.py b/spyder/app/cli_options.py index 3ae36f094b4..9dee61ab853 100644 --- a/spyder/app/cli_options.py +++ b/spyder/app/cli_options.py @@ -86,7 +86,7 @@ def get_options(argv=None): default=None, type=str, dest="project", - help="Path that contains an Spyder project" + help="Path that contains a Spyder project" ) parser.add_argument( '--opengl', diff --git a/spyder/plugins/projects/plugin.py b/spyder/plugins/projects/plugin.py index 5e86fd453c7..b7d7bd075c4 100644 --- a/spyder/plugins/projects/plugin.py +++ b/spyder/plugins/projects/plugin.py @@ -269,16 +269,14 @@ def on_mainwindow_visible(self): initial_cwd = self._main.get_initial_working_directory() if cli_options.project is not None: - # This doesn't work for our conda-based installer apps - if not is_conda_based_app(): - logger.debug('Opening project from the command line') - project = osp.normpath( - osp.join(initial_cwd, cli_options.project) - ) - self.open_project( - project, - workdir=cli_options.working_directory - ) + logger.debug('Opening project from the command line') + project = osp.normpath( + osp.join(initial_cwd, cli_options.project) + ) + self.open_project( + project, + workdir=cli_options.working_directory + ) else: logger.debug('Reopening project from last session') self.get_widget().reopen_last_project() From 7639ea73fb477b0d46497d6c9d2434f9a0b6d8ff Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Mon, 24 Apr 2023 08:40:40 -0700 Subject: [PATCH 15/17] Apply suggestions from code review. Regression of #20390 does not occur. --- spyder/plugins/onlinehelp/widgets.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/spyder/plugins/onlinehelp/widgets.py b/spyder/plugins/onlinehelp/widgets.py index e99a2e945d8..7f81974dcd1 100644 --- a/spyder/plugins/onlinehelp/widgets.py +++ b/spyder/plugins/onlinehelp/widgets.py @@ -9,7 +9,6 @@ """ # Standard library imports -import os import os.path as osp import pydoc import sys @@ -23,7 +22,6 @@ # Local imports from spyder.api.translations import _ from spyder.api.widgets.main_widget import PluginMainWidget -from spyder.config.base import is_conda_based_app from spyder.plugins.onlinehelp.pydoc_patch import _start_server, _url_handler from spyder.widgets.browser import FrameWebView, WebViewActions from spyder.widgets.comboboxes import UrlComboBox @@ -69,12 +67,6 @@ def spyder_safeimport(path, forceload=0, cache={}): except Exception: pass -# Needed to prevent showing a warning message regarding debugging -# See spyder-ide/spyder#20390 -# ??? Do we need this? -if is_conda_based_app(): - os.environ["PYDEVD_DISABLE_FILE_VALIDATION"] = "1" - class PydocServer(QThread): """ From a13aeb21c18e3fb41ae3f48059fdb7fd1f33349a Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Tue, 25 Apr 2023 22:38:41 -0700 Subject: [PATCH 16/17] Apply review suggestions. --- spyder/plugins/variableexplorer/widgets/collectionsdelegate.py | 2 +- spyder/utils/conda.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py index 771461c556a..1cdd56f56dd 100644 --- a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py +++ b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py @@ -128,7 +128,7 @@ def createEditor(self, parent, option, index, object_explorer=False): message = _("Spyder is unable to show the variable you're" " trying to view because the module " "{module} is not supported " - "by Spyder.
") + "by Spyder's standalone application.
") else: message = _("Spyder is unable to show the variable you're" " trying to view because the module " diff --git a/spyder/utils/conda.py b/spyder/utils/conda.py index 2efed939754..eb38639b913 100644 --- a/spyder/utils/conda.py +++ b/spyder/utils/conda.py @@ -88,7 +88,8 @@ def find_conda(): # First try Spyder's conda executable if is_conda_based_app(): - conda = osp.join(osp.dirname(os.environ['CONDA_EXE']), 'mamba') + root = osp.dirname(os.environ['CONDA_EXE']) + conda = osp.join(root, 'mamba.exe' if WINDOWS else 'mamba') # Next try the environment variables if conda is None: From c524c92287a14ea3d211e46037a74937e9a0fd57 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Wed, 26 Apr 2023 19:20:39 -0700 Subject: [PATCH 17/17] Apply review suggestions. --- .../variableexplorer/widgets/collectionsdelegate.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py index 1cdd56f56dd..76837508a17 100644 --- a/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py +++ b/spyder/plugins/variableexplorer/widgets/collectionsdelegate.py @@ -115,10 +115,11 @@ def createEditor(self, parent, option, index, object_explorer=False): if module == 'numpy': val_type = 'array' else: - val_type = 'dataframe, series' - message = _("Spyder is unable to show the {val_type} or object" - " you're trying to view because {module}" - " is not installed. ") + val_type = 'dataframe or series' + message = _("Spyder is unable to show the {val_type} object " + "you're trying to view because {module} " + "is missing. Please install that package in your " + "Spyder environment to fix this problem.") QMessageBox.critical( self.parent(), _("Error"), message.format(val_type=val_type, module=module))