packages.yaml: set url/git (#33275)
A user may want to set some attributes on a package without actually modifying the package (e.g. if they want to git pull updates to the package without conflicts). This PR adds a per-package configuration section called "set", which is a dictionary of attribute names to desired values. For example:
packages:
openblas:
package_attributes:
submodules: true
git: "https://github.com/myfork/openblas"
in this case, the package will always retrieve git submodules, and will use an alternate location for the git repo.
While git, url, and submodules are the attributes for which we envision the most usage, this allows any attribute to be overridden, and the acceptable values are any value parseable from yaml.
This commit is contained in:
@@ -1362,6 +1362,41 @@ def get_pkg_class(self, pkg_name):
|
||||
if not inspect.isclass(cls):
|
||||
tty.die("%s.%s is not a class" % (pkg_name, class_name))
|
||||
|
||||
new_cfg_settings = (
|
||||
spack.config.get("packages").get(pkg_name, {}).get("package_attributes", {})
|
||||
)
|
||||
|
||||
overridden_attrs = getattr(cls, "overridden_attrs", {})
|
||||
attrs_exclusively_from_config = getattr(cls, "attrs_exclusively_from_config", [])
|
||||
# Clear any prior changes to class attributes in case the config has
|
||||
# since changed
|
||||
for key, val in overridden_attrs.items():
|
||||
setattr(cls, key, val)
|
||||
for key in attrs_exclusively_from_config:
|
||||
delattr(cls, key)
|
||||
|
||||
# Keep track of every class attribute that is overridden by the config:
|
||||
# if the config changes between calls to this method, we make sure to
|
||||
# restore the original config values (in case the new config no longer
|
||||
# sets attributes that it used to)
|
||||
new_overridden_attrs = {}
|
||||
new_attrs_exclusively_from_config = set()
|
||||
for key, val in new_cfg_settings.items():
|
||||
if hasattr(cls, key):
|
||||
new_overridden_attrs[key] = getattr(cls, key)
|
||||
else:
|
||||
new_attrs_exclusively_from_config.add(key)
|
||||
|
||||
setattr(cls, key, val)
|
||||
if new_overridden_attrs:
|
||||
setattr(cls, "overridden_attrs", dict(new_overridden_attrs))
|
||||
elif hasattr(cls, "overridden_attrs"):
|
||||
delattr(cls, "overridden_attrs")
|
||||
if new_attrs_exclusively_from_config:
|
||||
setattr(cls, "attrs_exclusively_from_config", new_attrs_exclusively_from_config)
|
||||
elif hasattr(cls, "attrs_exclusively_from_config"):
|
||||
delattr(cls, "attrs_exclusively_from_config")
|
||||
|
||||
return cls
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -82,6 +82,15 @@
|
||||
},
|
||||
},
|
||||
},
|
||||
# If 'get_full_repo' is promoted to a Package-level
|
||||
# attribute, it could be useful to set it here
|
||||
"package_attributes": {
|
||||
"type": "object",
|
||||
"additionalProperties": False,
|
||||
"patternProperties": {
|
||||
r"\w+": {},
|
||||
},
|
||||
},
|
||||
"providers": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
|
||||
@@ -179,6 +179,53 @@ def test_preferred_providers(self):
|
||||
spec = concretize("mpileaks")
|
||||
assert "zmpi" in spec
|
||||
|
||||
def test_config_set_pkg_property_url(self, mutable_mock_repo):
|
||||
"""Test setting an existing attribute in the package class"""
|
||||
update_packages(
|
||||
"mpileaks",
|
||||
"package_attributes",
|
||||
{"url": "http://www.somewhereelse.com/mpileaks-1.0.tar.gz"},
|
||||
)
|
||||
spec = concretize("mpileaks")
|
||||
assert spec.package.fetcher[0].url == "http://www.somewhereelse.com/mpileaks-2.3.tar.gz"
|
||||
|
||||
update_packages("mpileaks", "package_attributes", {})
|
||||
spec = concretize("mpileaks")
|
||||
assert spec.package.fetcher[0].url == "http://www.llnl.gov/mpileaks-2.3.tar.gz"
|
||||
|
||||
def test_config_set_pkg_property_new(self, mutable_mock_repo):
|
||||
"""Test that you can set arbitrary attributes on the Package class"""
|
||||
conf = syaml.load_config(
|
||||
"""\
|
||||
mpileaks:
|
||||
package_attributes:
|
||||
v1: 1
|
||||
v2: true
|
||||
v3: yesterday
|
||||
v4: "true"
|
||||
v5:
|
||||
x: 1
|
||||
y: 2
|
||||
v6:
|
||||
- 1
|
||||
- 2
|
||||
"""
|
||||
)
|
||||
spack.config.set("packages", conf, scope="concretize")
|
||||
|
||||
spec = concretize("mpileaks")
|
||||
assert spec.package.v1 == 1
|
||||
assert spec.package.v2 is True
|
||||
assert spec.package.v3 == "yesterday"
|
||||
assert spec.package.v4 == "true"
|
||||
assert dict(spec.package.v5) == {"x": 1, "y": 2}
|
||||
assert list(spec.package.v6) == [1, 2]
|
||||
|
||||
update_packages("mpileaks", "package_attributes", {})
|
||||
spec = concretize("mpileaks")
|
||||
with pytest.raises(AttributeError):
|
||||
spec.package.v1
|
||||
|
||||
def test_preferred(self):
|
||||
""" "Test packages with some version marked as preferred=True"""
|
||||
spec = Spec("python")
|
||||
|
||||
Reference in New Issue
Block a user