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`.
This commit is contained in:
Tamara Dahlgren 2024-01-17 13:45:57 -08:00 committed by GitHub
parent 69d762ce6a
commit 68e00e7073
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 36 additions and 7 deletions

View File

@ -17,7 +17,12 @@
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.

View File

@ -1413,13 +1413,9 @@ def download_instr(self):
(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."""

View File

@ -12,6 +12,7 @@
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)