From 68e00e7073ecc0e56f1eee8af4ebe87f5f15eb60 Mon Sep 17 00:00:00 2001 From: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com> Date: Wed, 17 Jan 2024 13:45:57 -0800 Subject: Packages requiring manual downloads: improve error message (#42017) Spack packages may not have a public download option, and can implement `download_instr` to inform users how to obtain the artifacts needed to build. `spack checksum` however did not account for this and would print out a confusing error message when invoked on such packages ("Could not find any remote versions"). This PR updates the error message to output the manual download instructions if `spack checksum` is invoked on a package with `manual_download = True`. --- lib/spack/spack/cmd/checksum.py | 11 ++++++++++- lib/spack/spack/package_base.py | 12 ++++++------ lib/spack/spack/test/cmd/checksum.py | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/lib/spack/spack/cmd/checksum.py b/lib/spack/spack/cmd/checksum.py index 8e40d5e0b5..4eae8da7d4 100644 --- a/lib/spack/spack/cmd/checksum.py +++ b/lib/spack/spack/cmd/checksum.py @@ -17,7 +17,12 @@ import spack.stage import spack.util.crypto import spack.util.web as web_util from spack.cmd.common import arguments -from spack.package_base import PackageBase, deprecated_version, preferred_version +from spack.package_base import ( + ManualDownloadRequiredError, + PackageBase, + deprecated_version, + preferred_version, +) from spack.util.editor import editor from spack.util.format import get_version_lines from spack.version import Version @@ -86,6 +91,10 @@ def checksum(parser, args): # Get the package we're going to generate checksums for pkg = spack.repo.PATH.get_pkg_class(spec.name)(spec) + # Skip manually downloaded packages + if pkg.manual_download: + raise ManualDownloadRequiredError(pkg.download_instr) + versions = [Version(v) for v in args.versions] # Define placeholder for remote versions. diff --git a/lib/spack/spack/package_base.py b/lib/spack/spack/package_base.py index a2176565fe..d23a620984 100644 --- a/lib/spack/spack/package_base.py +++ b/lib/spack/spack/package_base.py @@ -1413,13 +1413,9 @@ class PackageBase(WindowsRPath, PackageViewMixin, metaclass=PackageMeta): (str): default manual download instructions """ required = ( - "Manual download is required for {0}. ".format(self.spec.name) - if self.manual_download - else "" - ) - return "{0}Refer to {1} for download instructions.".format( - required, self.spec.package.homepage + f"Manual download is required for {self.spec.name}. " if self.manual_download else "" ) + return f"{required}Refer to {self.homepage} for download instructions." def do_fetch(self, mirror_only=False): """ @@ -2578,3 +2574,7 @@ class DependencyConflictError(spack.error.SpackError): def __init__(self, conflict): super().__init__("%s conflicts with another file in the flattened directory." % (conflict)) + + +class ManualDownloadRequiredError(InvalidPackageOpError): + """Raised when attempting an invalid operation on a package that requires a manual download.""" diff --git a/lib/spack/spack/test/cmd/checksum.py b/lib/spack/spack/test/cmd/checksum.py index abec858471..4a447ed524 100644 --- a/lib/spack/spack/test/cmd/checksum.py +++ b/lib/spack/spack/test/cmd/checksum.py @@ -12,6 +12,7 @@ import spack.parser import spack.repo import spack.spec from spack.main import SpackCommand +from spack.package_base import ManualDownloadRequiredError from spack.stage import interactive_version_filter from spack.version import Version @@ -272,3 +273,22 @@ def test_checksum_verification_fails(install_mockery, capsys): assert out.count("Correct") == 0 assert "No previous checksum" in out assert "Invalid checksum" in out + + +def test_checksum_manual_download_fails(mock_packages, monkeypatch): + """Confirm that checksumming a manually downloadable package fails.""" + name = "zlib" + pkg_cls = spack.repo.PATH.get_pkg_class(name) + versions = [str(v) for v in pkg_cls.versions] + monkeypatch.setattr(spack.package_base.PackageBase, "manual_download", True) + + # First check that the exception is raised with the default download + # instructions. + with pytest.raises(ManualDownloadRequiredError, match=f"required for {name}"): + spack_checksum(name, *versions) + + # Now check that the exception is raised with custom download instructions. + error = "Cannot calculate the checksum for a manually downloaded package." + monkeypatch.setattr(spack.package_base.PackageBase, "download_instr", error) + with pytest.raises(ManualDownloadRequiredError, match=error): + spack_checksum(name, *versions) -- cgit v1.2.3-70-g09d2