From c2340047e541c0ba445df03f00028dd9a66efcd9 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:31:49 -0700 Subject: [PATCH 1/3] * Do not build Spyder on release event * Do not patch conda-lock file * Only use Github url to check for updates --- .github/workflows/installers-conda.yml | 1 + installers-conda/build_installers.py | 22 +------------ spyder/plugins/updatemanager/workers.py | 43 ++++--------------------- 3 files changed, 8 insertions(+), 58 deletions(-) diff --git a/.github/workflows/installers-conda.yml b/.github/workflows/installers-conda.yml index 78fbc1c3b24..b5f44ea93cc 100644 --- a/.github/workflows/installers-conda.yml +++ b/.github/workflows/installers-conda.yml @@ -220,6 +220,7 @@ jobs: env | sort - name: Build ${{ matrix.target-platform }} spyder Conda Package + if: env.IS_RELEASE == 'false' run: | # Copy built packages to new build location because spyder cannot be # built in workspace diff --git a/installers-conda/build_installers.py b/installers-conda/build_installers.py index cd2835b433b..4dbeee6a2ba 100644 --- a/installers-conda/build_installers.py +++ b/installers-conda/build_installers.py @@ -207,24 +207,7 @@ def _create_conda_lock(): if logger.getEffectiveLevel() <= 20: print(TMP_LOCK_FILE.read_text(), flush=True) - -def _patch_conda_lock(): - # Replace local channel url with conda-forge and remove checksum - dev_channel = "" - if SPYVER.is_prerelease: - dev_channel = "/label/spyder_dev" - - tmp_text = TMP_LOCK_FILE.read_text() - text = re.sub( - f"^{_get_conda_bld_path_url()}(.*)#.*$", - fr"https://conda.anaconda.org/conda-forge{dev_channel}\1", - tmp_text, flags=re.MULTILINE - ) - LOCK_FILE.write_text(text) - - logger.info(f"Contents of {LOCK_FILE}:") - if logger.getEffectiveLevel() <= 20: - print(LOCK_FILE.read_text(), flush=True) + LOCK_FILE.write_text(TMP_LOCK_FILE.read_text()) def _generate_background_images(installer_type): @@ -504,8 +487,6 @@ def main(): elapse = timedelta(seconds=int(time() - t0)) logger.info(f"Build time: {elapse}") - _patch_conda_lock() - if __name__ == "__main__": if args.arch: @@ -525,7 +506,6 @@ def main(): sys.exit() if args.conda_lock: _create_conda_lock() - _patch_conda_lock() sys.exit() main() diff --git a/spyder/plugins/updatemanager/workers.py b/spyder/plugins/updatemanager/workers.py index e347089c4a5..7c950d4742d 100644 --- a/spyder/plugins/updatemanager/workers.py +++ b/spyder/plugins/updatemanager/workers.py @@ -21,10 +21,7 @@ # Local imports from spyder import __version__ -from spyder.config.base import (_, is_stable_version, is_conda_based_app, - running_in_ci) -from spyder.config.utils import is_anaconda -from spyder.utils.conda import get_spyder_conda_channel +from spyder.config.base import _, is_stable_version, running_in_ci from spyder.utils.programs import check_version # Logger setup @@ -147,31 +144,11 @@ def start(self): self.latest_release = None self.update_available = False error_msg = None - pypi_url = "https://pypi.org/pypi/spyder/json" - github_url = 'https://api.github.com/repos/spyder-ide/spyder/releases' - - if is_conda_based_app(): - url = github_url - elif is_anaconda(): - self.channel, channel_url = get_spyder_conda_channel() - - if self.channel is None or channel_url is None: - logger.debug( - f"channel = {self.channel}; channel_url = {channel_url}. " - ) - - # Spyder installed in development mode, use GitHub - url = github_url - elif self.channel == "pypi": - url = pypi_url - else: - url = channel_url + '/channeldata.json' - else: - url = pypi_url + url = 'https://api.github.com/repos/spyder-ide/spyder/releases' headers = {} token = os.getenv('GITHUB_TOKEN') - if running_in_ci() and url == github_url and token: + if running_in_ci() and token: headers.update(Authorization=f"Bearer {token}") logger.info(f"Checking for updates from {url}") @@ -182,17 +159,9 @@ def start(self): data = page.json() if self.releases is None: - if url == github_url: - self.releases = [ - item['tag_name'].replace('v', '') for item in data - ] - elif url == pypi_url: - self.releases = [data['info']['version']] - else: - # Conda type url - spyder_data = data['packages'].get('spyder') - if spyder_data: - self.releases = [spyder_data["version"]] + self.releases = [ + item['tag_name'].replace('v', '') for item in data + ] self.releases.sort(key=parse) self._check_update_available() From 460de25ecddb1ceb0a218d65903fec8634ac2d8b Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Fri, 12 Jul 2024 10:51:00 -0700 Subject: [PATCH 2/3] Update tests. * No longer necessary to patch is_anaconda, is_conda_based_app, and get_spyder_conda_channel * Individual tests for PyPi, conda, and app environments are no longer necessary. --- .../tests/test_update_manager.py | 61 +------------------ 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/spyder/plugins/updatemanager/tests/test_update_manager.py b/spyder/plugins/updatemanager/tests/test_update_manager.py index f7cba68fe2c..8035cc21476 100644 --- a/spyder/plugins/updatemanager/tests/test_update_manager.py +++ b/spyder/plugins/updatemanager/tests/test_update_manager.py @@ -31,7 +31,7 @@ def worker(): # ---- Test WorkerUpdate @pytest.mark.parametrize("version", ["1.0.0", "1000.0.0"]) -def test_updates_appenv(qtbot, mocker, version, caplog): +def test_updates(qtbot, mocker, version, caplog): """ Test whether or not we offer updates for our installers according to the current Spyder version. @@ -44,12 +44,6 @@ def test_updates_appenv(qtbot, mocker, version, caplog): UpdateManagerWidget, "start_update", new=lambda x: None ) mocker.patch.object(workers, "__version__", new=version) - mocker.patch.object(workers, "is_anaconda", return_value=True) - mocker.patch.object(workers, "is_conda_based_app", return_value=True) - mocker.patch.object( - workers, "get_spyder_conda_channel", - return_value=("conda-forge", "https://conda.anaconda.org/conda-forge") - ) with caplog.at_level(logging.DEBUG, logger='spyder.plugins.updatemanager'): # Capture >=DEBUG logging messages for spyder.plugins.updatemanager @@ -77,59 +71,6 @@ def test_updates_appenv(qtbot, mocker, version, caplog): assert len(um.update_worker.releases) > 1 -@pytest.mark.parametrize("version", ["1.0.0", "1000.0.0"]) -@pytest.mark.parametrize( - "channel", [ - ("pkgs/main", "https://repo.anaconda.com/pkgs/main"), - ("conda-forge", "https://conda.anaconda.org/conda-forge"), - ("pypi", "https://conda.anaconda.org/pypi") - ] -) -def test_updates_condaenv(qtbot, worker, mocker, version, channel): - """ - Test whether or not we offer updates for conda installed Spyder according - to the current version. - """ - mocker.patch.object(workers, "__version__", new=version) - mocker.patch.object(workers, "is_anaconda", return_value=True) - mocker.patch.object(workers, "is_conda_based_app", return_value=False) - mocker.patch.object( - workers, "get_spyder_conda_channel", return_value=channel - ) - - with qtbot.waitSignal(worker.sig_ready, timeout=5000): - worker.start() - - update_available = worker.update_available - if version.split('.')[0] == '1': - assert update_available - else: - assert not update_available - assert len(worker.releases) == 1 - - -@pytest.mark.parametrize("version", ["1.0.0", "1000.0.0"]) -def test_updates_pipenv(qtbot, worker, mocker, version): - """Test updates for pip installed Spyder.""" - mocker.patch.object(workers, "__version__", new=version) - mocker.patch.object(workers, "is_anaconda", return_value=False) - mocker.patch.object(workers, "is_conda_based_app", return_value=False) - mocker.patch.object( - workers, "get_spyder_conda_channel", - return_value=("pypi", "https://conda.anaconda.org/pypi") - ) - - with qtbot.waitSignal(worker.sig_ready, timeout=5000): - worker.start() - - update_available = worker.update_available - if version.split('.')[0] == '1': - assert update_available - else: - assert not update_available - assert len(worker.releases) == 1 - - @pytest.mark.parametrize("release", ["4.0.1", "4.0.1a1"]) @pytest.mark.parametrize("version", ["4.0.0a1", "4.0.0"]) @pytest.mark.parametrize("stable_only", [True, False]) From e28daaa2d16e212ac6ddc3e3470b9f0ef16b0757 Mon Sep 17 00:00:00 2001 From: Ryan Clary <9618975+mrclary@users.noreply.github.com> Date: Mon, 15 Jul 2024 21:27:01 -0700 Subject: [PATCH 3/3] Restore using defaults channel for checking for updates when Spyder is installed using defaults channel. Because the defaults channel is usually very far behind the Github releases, this prevents users from being spammed for updates that are not available on the defaults channel. --- .../tests/test_update_manager.py | 17 +++++++++++++---- spyder/plugins/updatemanager/workers.py | 19 +++++++++++++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/spyder/plugins/updatemanager/tests/test_update_manager.py b/spyder/plugins/updatemanager/tests/test_update_manager.py index 8035cc21476..a59e61de4e1 100644 --- a/spyder/plugins/updatemanager/tests/test_update_manager.py +++ b/spyder/plugins/updatemanager/tests/test_update_manager.py @@ -31,10 +31,16 @@ def worker(): # ---- Test WorkerUpdate @pytest.mark.parametrize("version", ["1.0.0", "1000.0.0"]) -def test_updates(qtbot, mocker, version, caplog): +@pytest.mark.parametrize( + "channel", [ + ("pkgs/main", "https://repo.anaconda.com/pkgs/main"), + ("conda-forge", "https://conda.anaconda.org/conda-forge"), + ] +) +def test_updates(qtbot, mocker, caplog, version, channel): """ - Test whether or not we offer updates for our installers according to the - current Spyder version. + Test whether or not we offer updates according to the current Spyder + version and package installation channel. Uses UpdateManagerWidget in order to also test QThread. """ @@ -44,6 +50,9 @@ def test_updates(qtbot, mocker, version, caplog): UpdateManagerWidget, "start_update", new=lambda x: None ) mocker.patch.object(workers, "__version__", new=version) + mocker.patch.object( + workers, "get_spyder_conda_channel", return_value=channel + ) with caplog.at_level(logging.DEBUG, logger='spyder.plugins.updatemanager'): # Capture >=DEBUG logging messages for spyder.plugins.updatemanager @@ -68,7 +77,7 @@ def test_updates(qtbot, mocker, version, caplog): assert update_available else: assert not update_available - assert len(um.update_worker.releases) > 1 + assert len(um.update_worker.releases) >= 1 @pytest.mark.parametrize("release", ["4.0.1", "4.0.1a1"]) diff --git a/spyder/plugins/updatemanager/workers.py b/spyder/plugins/updatemanager/workers.py index 7c950d4742d..b52bee7668f 100644 --- a/spyder/plugins/updatemanager/workers.py +++ b/spyder/plugins/updatemanager/workers.py @@ -22,6 +22,8 @@ # Local imports from spyder import __version__ from spyder.config.base import _, is_stable_version, running_in_ci +from spyder.config.utils import is_anaconda +from spyder.utils.conda import get_spyder_conda_channel from spyder.utils.programs import check_version # Logger setup @@ -117,7 +119,6 @@ def __init__(self, stable_only): self.releases = None self.update_available = False self.error = None - self.channel = None def _check_update_available(self): """Checks if there is an update available from releases.""" @@ -146,6 +147,14 @@ def start(self): error_msg = None url = 'https://api.github.com/repos/spyder-ide/spyder/releases' + # If Spyder is installed from defaults channel (pkgs/main), then use + # that channel to get updates. The defaults channel can be far behind + # our latest release + if is_anaconda(): + channel, channel_url = get_spyder_conda_channel() + if channel == "pkgs/main": + url = channel_url + '/channeldata.json' + headers = {} token = os.getenv('GITHUB_TOKEN') if running_in_ci() and token: @@ -158,10 +167,16 @@ def start(self): page.raise_for_status() data = page.json() - if self.releases is None: + if url.endswith('releases'): + # Github url self.releases = [ item['tag_name'].replace('v', '') for item in data ] + else: + # Conda url + spyder_data = data['packages'].get('spyder') + if spyder_data: + self.releases = [spyder_data["version"]] self.releases.sort(key=parse) self._check_update_available()