From b98ef4b72d6e0a184e8eea967885cb94f8dd8067 Mon Sep 17 00:00:00 2001 From: Romain Cledat Date: Fri, 8 Dec 2023 01:21:25 -0800 Subject: [PATCH 1/4] Fix an issue when specifying full wheel URLs for a pypi package. The pypi solver expects hashes to be provided as part of the URL but, in most cases, if a user provides a URL for a package, they will not provide one with a hash. This PR ignores the missing hash instead of crashing. A test was added that fails prior to this change and succeeds after. --- conda_lock/pypi_solver.py | 7 +++++-- tests/test-pip-full-url/environment.yml | 8 ++++++++ tests/test_conda_lock.py | 22 ++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/test-pip-full-url/environment.yml diff --git a/conda_lock/pypi_solver.py b/conda_lock/pypi_solver.py index f00828a15..78eca840d 100644 --- a/conda_lock/pypi_solver.py +++ b/conda_lock/pypi_solver.py @@ -214,8 +214,11 @@ def get_requirements( if op.package.source_type == "url": url, fragment = urldefrag(op.package.source_url) - hash_type, hash = fragment.split("=") - hash = HashModel(**{hash_type: hash}) + hash_splits = fragment.split("=") + if len(hash_splits) == 2: + hash = HashModel(**{hash_splits[0]: hash_splits[1]}) + else: + hash = HashModel() source = DependencySource(type="url", url=op.package.source_url) elif op.package.source_type == "git": url = f"{op.package.source_type}+{op.package.source_url}@{op.package.source_resolved_reference}" diff --git a/tests/test-pip-full-url/environment.yml b/tests/test-pip-full-url/environment.yml new file mode 100644 index 000000000..328831ad1 --- /dev/null +++ b/tests/test-pip-full-url/environment.yml @@ -0,0 +1,8 @@ +# environment.yml +channels: + - conda-forge + +dependencies: + - pip + - pip: + - requests @ https://github.com/psf/requests/releases/download/v2.31.0/requests-2.31.0-py3-none-any.whl diff --git a/tests/test_conda_lock.py b/tests/test_conda_lock.py index 0d5d00f39..124d9ac88 100644 --- a/tests/test_conda_lock.py +++ b/tests/test_conda_lock.py @@ -2460,3 +2460,25 @@ def test_parse_environment_file_with_pip_and_platform_selector(): VersionedDependency(name="psutil", manager="pip", version="*"), VersionedDependency(name="pip", manager="conda", version="*"), ] + + +def test_pip_full_whl_url( + tmp_path: Path, conda_exe: str, monkeypatch: "pytest.MonkeyPatch" +): + """Ensure that we can specify full wheel URL in the environment file.""" + + env_file = clone_test_dir("test-pip-full-url", tmp_path).joinpath("environment.yml") + monkeypatch.chdir(env_file.parent) + run_lock( + [env_file], + conda_exe=str(conda_exe), + platforms=["linux-64"], + ) + + lockfile = parse_conda_lock_file(env_file.parent / DEFAULT_LOCKFILE_NAME) + + (requests_dep,) = [p for p in lockfile.package if p.name == "requests"] + assert ( + requests_dep.url + == "https://github.com/psf/requests/releases/download/v2.31.0/requests-2.31.0-py3-none-any.whl" + ) From 12e1e79b8463d733315b3392b4d338935af89158 Mon Sep 17 00:00:00 2001 From: Romain Date: Fri, 8 Dec 2023 14:51:11 -0800 Subject: [PATCH 2/4] Update conda_lock/pypi_solver.py Co-authored-by: Ben Mares --- conda_lock/pypi_solver.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/conda_lock/pypi_solver.py b/conda_lock/pypi_solver.py index 78eca840d..335758ae5 100644 --- a/conda_lock/pypi_solver.py +++ b/conda_lock/pypi_solver.py @@ -215,10 +215,12 @@ def get_requirements( if op.package.source_type == "url": url, fragment = urldefrag(op.package.source_url) hash_splits = fragment.split("=") - if len(hash_splits) == 2: + if fragment == "": + hash = HashModel() + elif len(hash_splits) == 2: hash = HashModel(**{hash_splits[0]: hash_splits[1]}) else: - hash = HashModel() + raise ValueError(f"Don't know what to do with {fragment}") source = DependencySource(type="url", url=op.package.source_url) elif op.package.source_type == "git": url = f"{op.package.source_type}+{op.package.source_url}@{op.package.source_resolved_reference}" From 50939243a6ee580409891c0e69d17e3dc0a64e11 Mon Sep 17 00:00:00 2001 From: Romain Date: Fri, 8 Dec 2023 14:51:33 -0800 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Ben Mares --- tests/test-pip-full-url/environment.yml | 1 + tests/test_conda_lock.py | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/tests/test-pip-full-url/environment.yml b/tests/test-pip-full-url/environment.yml index 328831ad1..017b6ba30 100644 --- a/tests/test-pip-full-url/environment.yml +++ b/tests/test-pip-full-url/environment.yml @@ -6,3 +6,4 @@ dependencies: - pip - pip: - requests @ https://github.com/psf/requests/releases/download/v2.31.0/requests-2.31.0-py3-none-any.whl + - typing-extensions @ https://files.pythonhosted.org/packages/24/21/7d397a4b7934ff4028987914ac1044d3b7d52712f30e2ac7a2ae5bc86dd0/typing_extensions-4.8.0-py3-none-any.whl#sha256=8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 diff --git a/tests/test_conda_lock.py b/tests/test_conda_lock.py index 124d9ac88..bebb18a73 100644 --- a/tests/test_conda_lock.py +++ b/tests/test_conda_lock.py @@ -2478,7 +2478,14 @@ def test_pip_full_whl_url( lockfile = parse_conda_lock_file(env_file.parent / DEFAULT_LOCKFILE_NAME) (requests_dep,) = [p for p in lockfile.package if p.name == "requests"] + (typing_extensions_dep,) = [p for p in lockfile.package if p.name == "typing-extensions"] assert ( requests_dep.url == "https://github.com/psf/requests/releases/download/v2.31.0/requests-2.31.0-py3-none-any.whl" ) + assert requests_dep.hash.sha256 is None + assert ( + typing_extensions_dep.url + == "https://files.pythonhosted.org/packages/24/21/7d397a4b7934ff4028987914ac1044d3b7d52712f30e2ac7a2ae5bc86dd0/typing_extensions-4.8.0-py3-none-any.whl" + ) + assert typing_extensions_dep.hash.sha256 == "8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0" From 6e49ef5197a96924f03c98db094f289956cf8b72 Mon Sep 17 00:00:00 2001 From: Romain Cledat Date: Fri, 8 Dec 2023 14:55:01 -0800 Subject: [PATCH 4/4] Black --- tests/test_conda_lock.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/test_conda_lock.py b/tests/test_conda_lock.py index bebb18a73..cb53f9252 100644 --- a/tests/test_conda_lock.py +++ b/tests/test_conda_lock.py @@ -2478,7 +2478,9 @@ def test_pip_full_whl_url( lockfile = parse_conda_lock_file(env_file.parent / DEFAULT_LOCKFILE_NAME) (requests_dep,) = [p for p in lockfile.package if p.name == "requests"] - (typing_extensions_dep,) = [p for p in lockfile.package if p.name == "typing-extensions"] + (typing_extensions_dep,) = [ + p for p in lockfile.package if p.name == "typing-extensions" + ] assert ( requests_dep.url == "https://github.com/psf/requests/releases/download/v2.31.0/requests-2.31.0-py3-none-any.whl" @@ -2488,4 +2490,7 @@ def test_pip_full_whl_url( typing_extensions_dep.url == "https://files.pythonhosted.org/packages/24/21/7d397a4b7934ff4028987914ac1044d3b7d52712f30e2ac7a2ae5bc86dd0/typing_extensions-4.8.0-py3-none-any.whl" ) - assert typing_extensions_dep.hash.sha256 == "8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0" + assert ( + typing_extensions_dep.hash.sha256 + == "8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0" + )