Add subscript notation to packages (#48467)

This PR allows using the subscript notation directly on packages. The
intent is to reduce the boilerplate needed to retrieve package
properties from nodes other than root.
This commit is contained in:
Massimiliano Culpo 2025-01-10 19:00:51 +01:00 committed by GitHub
parent b670205e54
commit dd69b646ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 44 additions and 37 deletions

View File

@ -767,6 +767,9 @@ def __init__(self, spec):
self.win_rpath = fsys.WindowsSimulatedRPath(self) self.win_rpath = fsys.WindowsSimulatedRPath(self)
super().__init__() super().__init__()
def __getitem__(self, key: str) -> "PackageBase":
return self.spec[key].package
@classmethod @classmethod
def dependency_names(cls): def dependency_names(cls):
return _subkeys(cls.dependencies) return _subkeys(cls.dependencies)

View File

@ -285,3 +285,16 @@ def compilers(compiler, arch_spec):
error = capfd.readouterr()[1] error = capfd.readouterr()[1]
assert "Skipping tests for package" in error assert "Skipping tests for package" in error
assert "test requires missing compiler" in error assert "test requires missing compiler" in error
def test_package_subscript(default_mock_concretization):
"""Tests that we can use the subscript notation on packages, and that it returns a package"""
root = default_mock_concretization("mpileaks")
root_pkg = root.package
# Subscript of a virtual
assert isinstance(root_pkg["mpi"], spack.package_base.PackageBase)
# Subscript on concrete
for d in root.traverse():
assert isinstance(root_pkg[d.name], spack.package_base.PackageBase)

View File

@ -790,7 +790,7 @@ def edit(self, pkg, spec, prefix):
"# include Plumed.inc as recommended by" "# include Plumed.inc as recommended by"
"PLUMED to include libraries and flags" "PLUMED to include libraries and flags"
) )
mkf.write("include {0}\n".format(spec["plumed"].package.plumed_inc)) mkf.write("include {0}\n".format(self.pkg["plumed"].plumed_inc))
mkf.write("\n# COMPILER, LINKER, TOOLS\n\n") mkf.write("\n# COMPILER, LINKER, TOOLS\n\n")
mkf.write( mkf.write(

View File

@ -153,7 +153,7 @@ def common_args(self):
"CC={0}".format(env["CC"]), "CC={0}".format(env["CC"]),
"PREFIX={0}".format(self.spec.prefix.bin), "PREFIX={0}".format(self.spec.prefix.bin),
"MFEM_DIR={0}".format(self.spec["mfem"].prefix), "MFEM_DIR={0}".format(self.spec["mfem"].prefix),
"CONFIG_MK={0}".format(self.spec["mfem"].package.config_mk), "CONFIG_MK={0}".format(self.pkg["mfem"].config_mk),
] ]
# https://github.com/spack/spack/issues/42839 # https://github.com/spack/spack/issues/42839

View File

@ -585,7 +585,7 @@ def patch(self):
) )
if self.spec.satisfies("+plumed"): if self.spec.satisfies("+plumed"):
self.spec["plumed"].package.apply_patch(self) self["plumed"].apply_patch(self)
if self.spec.satisfies("%nvhpc"): if self.spec.satisfies("%nvhpc"):
# Disable obsolete workaround # Disable obsolete workaround

View File

@ -58,8 +58,8 @@ def build_targets(self):
spec = self.spec spec = self.spec
targets.append("MFEM_DIR=%s" % spec["mfem"].prefix) targets.append("MFEM_DIR=%s" % spec["mfem"].prefix)
targets.append("CONFIG_MK=%s" % spec["mfem"].package.config_mk) targets.append("CONFIG_MK=%s" % self["mfem"].config_mk)
targets.append("TEST_MK=%s" % spec["mfem"].package.test_mk) targets.append("TEST_MK=%s" % self["mfem"].test_mk)
if spec.satisfies("@:2.0"): if spec.satisfies("@:2.0"):
targets.append("CXX=%s" % spec["mpi"].mpicxx) targets.append("CXX=%s" % spec["mpi"].mpicxx)
if self.spec.satisfies("+ofast %gcc"): if self.spec.satisfies("+ofast %gcc"):

View File

@ -1309,7 +1309,7 @@ def libs(self):
@property @property
def config_mk(self): def config_mk(self):
"""Export the location of the config.mk file. """Export the location of the config.mk file.
This property can be accessed using spec["mfem"].package.config_mk This property can be accessed using pkg["mfem"].config_mk
""" """
dirs = [self.prefix, self.prefix.share.mfem] dirs = [self.prefix, self.prefix.share.mfem]
for d in dirs: for d in dirs:
@ -1321,7 +1321,7 @@ def config_mk(self):
@property @property
def test_mk(self): def test_mk(self):
"""Export the location of the test.mk file. """Export the location of the test.mk file.
This property can be accessed using spec["mfem"].package.test_mk. This property can be accessed using pkg["mfem"].test_mk.
In version 3.3.2 and newer, the location of test.mk is also defined In version 3.3.2 and newer, the location of test.mk is also defined
inside config.mk, variable MFEM_TEST_MK. inside config.mk, variable MFEM_TEST_MK.
""" """

View File

@ -147,11 +147,9 @@ def _copy_arch_file(self, lib):
def _append_option(self, opts, lib): def _append_option(self, opts, lib):
if lib != "python": if lib != "python":
self._copy_arch_file(lib) self._copy_arch_file(lib)
spec = self.spec lib_pkg = self[lib]
lib_prefix = ( lib_prefix = (
spec[lib].package.component_prefix lib_pkg.component_prefix if lib_pkg.name == "intel-oneapi-mkl" else lib_pkg.prefix
if spec[lib].name == "intel-oneapi-mkl"
else spec[lib].prefix
) )
opts.extend(["--with-{0}".format(lib), "--{0}-prefix".format(lib), lib_prefix]) opts.extend(["--with-{0}".format(lib), "--{0}-prefix".format(lib), lib_prefix])

View File

@ -35,7 +35,7 @@ class Nfft(AutotoolsPackage):
@property @property
def fftw_selected_precisions(self): def fftw_selected_precisions(self):
if not self._fftw_precisions: if not self._fftw_precisions:
self._fftw_precisions = self.spec["fftw"].package.selected_precisions self._fftw_precisions = self["fftw"].selected_precisions
return self._fftw_precisions return self._fftw_precisions
def configure(self, spec, prefix): def configure(self, spec, prefix):

View File

@ -84,10 +84,10 @@ def post_install(self):
pyso = "pyopenvdb.dylib" pyso = "pyopenvdb.dylib"
else: else:
pyso = "pyopenvdb.so" pyso = "pyopenvdb.so"
pyver = "python{0}".format(spec["python"].package.version.up_to(2)) pyver = f"python{self['python'].version.up_to(2)}"
src = prefix.lib.join(pyver).join(pyso) src = self.prefix.lib.join(pyver).join(pyso)
if not os.path.isfile(src): if not os.path.isfile(src):
src = prefix.lib64.join(pyver).join(pyso) src = self.prefix.lib64.join(pyver).join(pyso)
assert os.path.isfile(src) assert os.path.isfile(src)
os.rename(src, os.path.join(python_platlib, pyso)) os.rename(src, os.path.join(python_platlib, pyso))

View File

@ -21,11 +21,11 @@ def home(self):
@property @property
def headers(self): def headers(self):
return self.spec["mesa"].package.libosmesa_headers return self["mesa"].libosmesa_headers
@property @property
def libs(self): def libs(self):
return self.spec["mesa"].package.libosmesa_libs return self["mesa"].libosmesa_libs
@property @property
def gl_headers(self): def gl_headers(self):
@ -33,4 +33,4 @@ def gl_headers(self):
@property @property
def gl_libs(self): def gl_libs(self):
return self.spec["mesa"].package.libosmesa_libs return self["mesa"].libosmesa_libs

View File

@ -31,7 +31,7 @@ class Pnfft(AutotoolsPackage):
@property @property
def fftw_selected_precisions(self): def fftw_selected_precisions(self):
if not self._fftw_precisions: if not self._fftw_precisions:
self._fftw_precisions = self.spec["fftw"].package.selected_precisions self._fftw_precisions = self["fftw"].selected_precisions
return self._fftw_precisions return self._fftw_precisions
def configure(self, spec, prefix): def configure(self, spec, prefix):

View File

@ -43,7 +43,7 @@ def configure_args(self):
"--sip", "--sip",
self.spec["py-sip"].prefix.bin.sip, self.spec["py-sip"].prefix.bin.sip,
"--sip-incdir", "--sip-incdir",
join_path(self.spec["py-sip"].prefix, self.spec["python"].package.include), join_path(self.spec["py-sip"].prefix, self["python"].include),
"--bindir", "--bindir",
self.prefix.bin, self.prefix.bin,
"--destdir", "--destdir",

View File

@ -71,7 +71,7 @@ def install(self, spec, prefix):
"--sip-module={0}".format(spec.variants["module"].value), "--sip-module={0}".format(spec.variants["module"].value),
"--bindir={0}".format(prefix.bin), "--bindir={0}".format(prefix.bin),
"--destdir={0}".format(python_platlib), "--destdir={0}".format(python_platlib),
"--incdir={0}".format(join_path(prefix, spec["python"].package.include)), "--incdir={0}".format(join_path(prefix, self["python"].include)),
"--sipdir={0}".format(prefix.share.sip), "--sipdir={0}".format(prefix.share.sip),
"--stubsdir={0}".format(python_platlib), "--stubsdir={0}".format(python_platlib),
] ]

View File

@ -217,9 +217,7 @@ def fix_qsci_sip(self):
elif "^py-pyqt6" in self.spec: elif "^py-pyqt6" in self.spec:
pyqtx = "PyQt6" pyqtx = "PyQt6"
sip_inc_dir = join_path( sip_inc_dir = join_path(self["qscintilla"].module.python_platlib, pyqtx, "bindings")
self.spec["qscintilla"].package.module.python_platlib, pyqtx, "bindings"
)
with open(join_path("python", "gui", "pyproject.toml.in"), "a") as tomlfile: with open(join_path("python", "gui", "pyproject.toml.in"), "a") as tomlfile:
tomlfile.write(f'\n[tool.sip.project]\nsip-include-dirs = ["{sip_inc_dir}"]\n') tomlfile.write(f'\n[tool.sip.project]\nsip-include-dirs = ["{sip_inc_dir}"]\n')

View File

@ -101,9 +101,7 @@ def make_qsci_python(self):
with working_dir(join_path(self.stage.source_path, "Python")): with working_dir(join_path(self.stage.source_path, "Python")):
copy(ftoml, "pyproject.toml") copy(ftoml, "pyproject.toml")
sip_inc_dir = join_path( sip_inc_dir = join_path(self[py_pyqtx].module.python_platlib, pyqtx, "bindings")
self.spec[py_pyqtx].package.module.python_platlib, pyqtx, "bindings"
)
with open("pyproject.toml", "a") as tomlfile: with open("pyproject.toml", "a") as tomlfile:
# https://pyqt-builder.readthedocs.io/en/latest/pyproject_toml.html # https://pyqt-builder.readthedocs.io/en/latest/pyproject_toml.html

View File

@ -38,14 +38,11 @@ class Remhos(MakefilePackage):
@property @property
def build_targets(self): def build_targets(self):
targets = [] return [
spec = self.spec f"MFEM_DIR={self['mfem'].prefix}",
f"CONFIG_MK={self['mfem'].config_mk}",
targets.append("MFEM_DIR=%s" % spec["mfem"].prefix) f"TEST_MK={self['mfem'].test_mk}",
targets.append("CONFIG_MK=%s" % spec["mfem"].package.config_mk) ]
targets.append("TEST_MK=%s" % spec["mfem"].package.test_mk)
return targets
# See lib/spack/spack/build_systems/makefile.py # See lib/spack/spack/build_systems/makefile.py
def check(self): def check(self):

View File

@ -323,8 +323,8 @@ def install(self, spec, prefix):
env["F77"] = spec["mpi"].mpif77 env["F77"] = spec["mpi"].mpif77
env["FC"] = spec["mpi"].mpifc env["FC"] = spec["mpi"].mpifc
if spec["mpi"].name == "intel-oneapi-mpi": if spec["mpi"].name == "intel-oneapi-mpi":
options.append("-mpiinc=%s/include" % spec["mpi"].package.component_prefix) options.append("-mpiinc=%s/include" % self["mpi"].component_prefix)
options.append("-mpilib=%s/lib" % spec["mpi"].package.component_prefix) options.append("-mpilib=%s/lib" % self["mpi"].component_prefix)
else: else:
options.append("-mpiinc=%s" % spec["mpi"].prefix.include) options.append("-mpiinc=%s" % spec["mpi"].prefix.include)
options.append("-mpilib=%s" % spec["mpi"].prefix.lib) options.append("-mpilib=%s" % spec["mpi"].prefix.lib)