Skip to content

Commit a5aca50

Browse files
committed
Remove unused fetch_strategy code and add tests
1 parent 5b352fb commit a5aca50

File tree

2 files changed

+32
-167
lines changed

2 files changed

+32
-167
lines changed

lib/ramble/ramble/fetch_strategy.py

Lines changed: 1 addition & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,12 @@
4747
import ramble.util.web as web_util
4848
from ramble.util.logger import logger
4949

50-
import spack.error
5150
import spack.util.crypto as crypto
5251
import spack.util.pattern as pattern
5352
import spack.util.url as url_util
53+
import spack.version
5454
from spack.util.compression import decompressor_for, extension
5555
from spack.util.executable import CommandNotFoundError, which
56-
from spack.util.string import comma_and, quote
5756
from spack.version import Version, ver
5857

5958
#: List of all fetch strategies, created by FetchStrategy metaclass.
@@ -1512,138 +1511,6 @@ def from_kwargs(**kwargs):
15121511
raise InvalidArgsError(**kwargs)
15131512

15141513

1515-
def check_pkg_attributes(pkg):
1516-
"""Find ambiguous top-level fetch attributes in a package.
1517-
1518-
Currently this only ensures that two or more VCS fetch strategies are
1519-
not specified at once.
1520-
"""
1521-
# a single package cannot have URL attributes for multiple VCS fetch
1522-
# strategies *unless* they are the same attribute.
1523-
conflicts = {s.url_attr for s in all_strategies if hasattr(pkg, s.url_attr)}
1524-
1525-
# URL isn't a VCS fetch method. We can use it with a VCS method.
1526-
conflicts -= {"url"}
1527-
1528-
if len(conflicts) > 1:
1529-
raise FetcherConflict(
1530-
"Package %s cannot specify %s together. Pick at most one."
1531-
% (pkg.name, comma_and(quote(conflicts)))
1532-
)
1533-
1534-
1535-
def _check_version_attributes(fetcher, pkg, version):
1536-
"""Ensure that the fetcher for a version is not ambiguous.
1537-
1538-
This assumes that we have already determined the fetcher for the
1539-
specific version using ``for_package_version()``
1540-
"""
1541-
all_optionals = {a for s in all_strategies for a in s.optional_attrs}
1542-
1543-
args = pkg.versions[version]
1544-
extra = set(args) - set(fetcher.optional_attrs) - {fetcher.url_attr, "no_cache"}
1545-
extra.intersection_update(all_optionals)
1546-
1547-
if extra:
1548-
legal_attrs = [fetcher.url_attr] + list(fetcher.optional_attrs)
1549-
raise FetcherConflict(
1550-
"%s version '%s' has extra arguments: %s"
1551-
% (pkg.name, version, comma_and(quote(extra))),
1552-
"Valid arguments for a %s fetcher are: \n %s"
1553-
% (fetcher.url_attr, comma_and(quote(legal_attrs))),
1554-
)
1555-
1556-
1557-
def _extrapolate(pkg, version):
1558-
"""Create a fetcher from an extrapolated URL for this version."""
1559-
try:
1560-
return URLFetchStrategy(pkg.url_for_version(version), fetch_options=pkg.fetch_options)
1561-
except spack.package.NoURLError:
1562-
msg = "Can't extrapolate a URL for version %s " "because package %s defines no URLs"
1563-
raise ExtrapolationError(msg % (version, pkg.name))
1564-
1565-
1566-
def _from_merged_attrs(fetcher, pkg, version):
1567-
"""Create a fetcher from merged package and version attributes."""
1568-
if fetcher.url_attr == "url":
1569-
url = pkg.url_for_version(version)
1570-
# TODO: refactor this logic into its own method or function
1571-
# TODO: to avoid duplication
1572-
mirrors = [spack.url.substitute_version(u, version) for u in getattr(pkg, "urls", [])[1:]]
1573-
attrs = {fetcher.url_attr: url, "mirrors": mirrors}
1574-
else:
1575-
url = getattr(pkg, fetcher.url_attr)
1576-
attrs = {fetcher.url_attr: url}
1577-
1578-
attrs["fetch_options"] = pkg.fetch_options
1579-
attrs.update(pkg.versions[version])
1580-
1581-
if fetcher.url_attr == "git" and hasattr(pkg, "submodules"):
1582-
attrs.setdefault("submodules", pkg.submodules)
1583-
1584-
return fetcher(**attrs)
1585-
1586-
1587-
def for_package_version(pkg, version):
1588-
"""Determine a fetch strategy based on the arguments supplied to
1589-
version() in the package description."""
1590-
1591-
# No-code packages have a custom fetch strategy to work around issues
1592-
# with resource staging.
1593-
if not pkg.has_code:
1594-
return BundleFetchStrategy()
1595-
1596-
check_pkg_attributes(pkg)
1597-
1598-
if not isinstance(version, spack.version.Version):
1599-
version = spack.version.Version(version)
1600-
1601-
# if it's a commit, we must use a GitFetchStrategy
1602-
if version.is_commit and hasattr(pkg, "git"):
1603-
# Populate the version with comparisons to other commits
1604-
version.generate_commit_lookup(pkg.name)
1605-
kwargs = {"git": pkg.git, "commit": str(version)}
1606-
kwargs["submodules"] = getattr(pkg, "submodules", False)
1607-
fetcher = GitFetchStrategy(**kwargs)
1608-
return fetcher
1609-
1610-
# If it's not a known version, try to extrapolate one by URL
1611-
if version not in pkg.versions:
1612-
return _extrapolate(pkg, version)
1613-
1614-
# Set package args first so version args can override them
1615-
args = {"fetch_options": pkg.fetch_options}
1616-
# Grab a dict of args out of the package version dict
1617-
args.update(pkg.versions[version])
1618-
1619-
# If the version specifies a `url_attr` directly, use that.
1620-
for fetcher in all_strategies:
1621-
if fetcher.url_attr in args:
1622-
_check_version_attributes(fetcher, pkg, version)
1623-
if fetcher.url_attr == "git" and hasattr(pkg, "submodules"):
1624-
args.setdefault("submodules", pkg.submodules)
1625-
return fetcher(**args)
1626-
1627-
# if a version's optional attributes imply a particular fetch
1628-
# strategy, and we have the `url_attr`, then use that strategy.
1629-
for fetcher in all_strategies:
1630-
if hasattr(pkg, fetcher.url_attr) or fetcher.url_attr == "url":
1631-
optionals = fetcher.optional_attrs
1632-
if optionals and any(a in args for a in optionals):
1633-
_check_version_attributes(fetcher, pkg, version)
1634-
return _from_merged_attrs(fetcher, pkg, version)
1635-
1636-
# if the optional attributes tell us nothing, then use any `url_attr`
1637-
# on the package. This prefers URL vs. VCS, b/c URLFetchStrategy is
1638-
# defined first in this file.
1639-
for fetcher in all_strategies:
1640-
if hasattr(pkg, fetcher.url_attr):
1641-
_check_version_attributes(fetcher, pkg, version)
1642-
return _from_merged_attrs(fetcher, pkg, version)
1643-
1644-
raise InvalidArgsError(pkg, version, **args)
1645-
1646-
16471514
def from_url_scheme(url, *args, **kwargs):
16481515
"""Finds a suitable FetchStrategy by matching its url_attr with the scheme
16491516
in the given url."""
@@ -1670,39 +1537,6 @@ def from_url_scheme(url, *args, **kwargs):
16701537
raise ValueError(f'No FetchStrategy found for url with scheme: "{parsed_url.scheme}"')
16711538

16721539

1673-
def from_list_url(pkg):
1674-
"""If a package provides a URL which lists URLs for resources by
1675-
version, this can can create a fetcher for a URL discovered for
1676-
the specified package's version."""
1677-
1678-
if pkg.list_url:
1679-
try:
1680-
versions = pkg.fetch_remote_versions()
1681-
try:
1682-
# get a URL, and a checksum if we have it
1683-
url_from_list = versions[pkg.version]
1684-
checksum = None
1685-
1686-
# try to find a known checksum for version, from the package
1687-
version = pkg.version
1688-
if version in pkg.versions:
1689-
args = pkg.versions[version]
1690-
checksum = next(
1691-
(v for k, v in args.items() if k in crypto.hashes), args.get("checksum")
1692-
)
1693-
1694-
# construct a fetcher
1695-
return URLFetchStrategy(url_from_list, checksum, fetch_options=pkg.fetch_options)
1696-
except KeyError as e:
1697-
logger.debug(e)
1698-
logger.msg(f"Cannot find version {pkg.version} in url_list")
1699-
1700-
except BaseException as e:
1701-
# TODO: Don't catch BaseException here! Be more specific.
1702-
logger.debug(e)
1703-
logger.msg("Could not determine url from list_url.")
1704-
1705-
17061540
class FsCache:
17071541

17081542
def __init__(self, root):
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright 2022-2025 The Ramble Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
# option. This file may not be copied, modified, or distributed
7+
# except according to those terms.
8+
"""Perform tests of the fetch_strategy functions"""
9+
10+
import pytest
11+
12+
from ramble import fetch_strategy
13+
14+
15+
@pytest.mark.parametrize(
16+
"url,expected_fetcher_type",
17+
[
18+
("file://my-path", fetch_strategy.URLFetchStrategy),
19+
("https://my-url", fetch_strategy.URLFetchStrategy),
20+
("gs://my-bucket", fetch_strategy.GCSFetchStrategy),
21+
("s3://my-bucket", fetch_strategy.S3FetchStrategy),
22+
],
23+
)
24+
def test_from_url_scheme(url, expected_fetcher_type):
25+
fetcher = fetch_strategy.from_url_scheme(url)
26+
assert isinstance(fetcher, expected_fetcher_type)
27+
28+
29+
def test_bad_from_url_scheme():
30+
with pytest.raises(ValueError, match="No FetchStrategy found"):
31+
fetch_strategy.from_url_scheme("unknown://my-url")

0 commit comments

Comments
 (0)