From eea8a227b4b11472134cf937ca464dda38a02619 Mon Sep 17 00:00:00 2001 From: Nikita Karetnikov Date: Sun, 17 Dec 2023 21:07:30 +0100 Subject: [PATCH 1/2] Use string substitution in `normalized_channel_url` Fixes #602. --- conda-store-server/conda_store_server/conda_utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/conda-store-server/conda_store_server/conda_utils.py b/conda-store-server/conda_store_server/conda_utils.py index a2a88d868..7439b4385 100644 --- a/conda-store-server/conda_store_server/conda_utils.py +++ b/conda-store-server/conda_store_server/conda_utils.py @@ -132,7 +132,13 @@ def download_repodata( "https://repo.anaconda.com/pkgs/main" ) } - normalized_channel_url = yarl.URL(channel) / "./" + # Note: this doesn't use the / operator to append the trailing / character + # because it's ignored on Windows. Instead, string substitution is used if + # the / character is not present + if channel.endswith("/"): + normalized_channel_url = yarl.URL(channel) + else: + normalized_channel_url = yarl.URL(f"{channel}/") channel_url = channel_replacements.get( str(normalized_channel_url), yarl.URL(channel) ) From b7a81f05ae6f7d1037a6f72e301ffe8b3be87f51 Mon Sep 17 00:00:00 2001 From: Nikita Karetnikov Date: Mon, 18 Dec 2023 20:37:17 +0100 Subject: [PATCH 2/2] Add a test for `channel_replacements` --- .../conda_store_server/conda_utils.py | 40 ++++++++++--------- conda-store-server/tests/test_actions.py | 11 +++++ 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/conda-store-server/conda_store_server/conda_utils.py b/conda-store-server/conda_store_server/conda_utils.py index 7439b4385..9db4f5ee7 100644 --- a/conda-store-server/conda_store_server/conda_utils.py +++ b/conda-store-server/conda_store_server/conda_utils.py @@ -109,21 +109,7 @@ def conda_lock(specification: "CondaSpecification", conda_exe: str = "mamba"): return {"conda": conda_packages, "pip": pip_packages} -def download_repodata( - channel: str, - last_update: datetime.datetime = None, - subdirs=None, -): - """Download repodata for channel only if changed since last update - - A channel consists of several architectures: linux-32, linux-64, - linux-aarch64, linux-armv6l, linux-armv7l, linux-ppc64le, noarch, - osx-64, win-32, win-64, zos-z (possibly others). - - Check ``conda.base.constants.KNOWN_SUBDIRS`` for the full list. - """ - subdirs = set(subdirs or [conda_platform(), "noarch"]) - +def get_channel_url(channel: str) -> yarl.URL: # the conda main channel does not have a channeldata.json within # the https://conda.anaconda.org//channeldata.json # so we replace the given url with it's equivalent alias @@ -132,6 +118,7 @@ def download_repodata( "https://repo.anaconda.com/pkgs/main" ) } + # Note: this doesn't use the / operator to append the trailing / character # because it's ignored on Windows. Instead, string substitution is used if # the / character is not present @@ -139,9 +126,26 @@ def download_repodata( normalized_channel_url = yarl.URL(channel) else: normalized_channel_url = yarl.URL(f"{channel}/") - channel_url = channel_replacements.get( - str(normalized_channel_url), yarl.URL(channel) - ) + + return channel_replacements.get(str(normalized_channel_url), yarl.URL(channel)) + + +def download_repodata( + channel: str, + last_update: datetime.datetime = None, + subdirs=None, +): + """Download repodata for channel only if changed since last update + + A channel consists of several architectures: linux-32, linux-64, + linux-aarch64, linux-armv6l, linux-armv7l, linux-ppc64le, noarch, + osx-64, win-32, win-64, zos-z (possibly others). + + Check ``conda.base.constants.KNOWN_SUBDIRS`` for the full list. + """ + subdirs = set(subdirs or [conda_platform(), "noarch"]) + + channel_url = get_channel_url(channel) headers = {} if last_update: diff --git a/conda-store-server/tests/test_actions.py b/conda-store-server/tests/test_actions.py index e3a455489..c9f6c04cb 100644 --- a/conda-store-server/tests/test_actions.py +++ b/conda-store-server/tests/test_actions.py @@ -5,6 +5,7 @@ import sys import pytest +import yarl from conda_store_server import ( BuildKey, action, @@ -346,3 +347,13 @@ def lockfile_url(build_key): assert lockfile_url(build_key) == build.conda_lock_key assert lockfile_url(build_key) == res.headers['location'] assert res.status_code == 307 + + +def test_get_channel_url(): + conda_main = "https://conda.anaconda.org/main" + repo_main = "https://repo.anaconda.com/pkgs/main" + example = "https://example.com" + + assert conda_utils.get_channel_url(conda_main) == yarl.URL(repo_main) + assert conda_utils.get_channel_url(f"{conda_main}/") == yarl.URL(repo_main) + assert conda_utils.get_channel_url(example) == yarl.URL(example)