directives: types, avoid redundant parsing (#45208)
This commit is contained in:
		@@ -90,7 +90,7 @@ class OpenMpi(Package):
 | 
				
			|||||||
_patch_order_index = 0
 | 
					_patch_order_index = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SpecType = Union["spack.spec.Spec", str]
 | 
					SpecType = str
 | 
				
			||||||
DepType = Union[Tuple[str, ...], str]
 | 
					DepType = Union[Tuple[str, ...], str]
 | 
				
			||||||
WhenType = Optional[Union["spack.spec.Spec", str, bool]]
 | 
					WhenType = Optional[Union["spack.spec.Spec", str, bool]]
 | 
				
			||||||
Patcher = Callable[[Union["spack.package_base.PackageBase", Dependency]], None]
 | 
					Patcher = Callable[[Union["spack.package_base.PackageBase", Dependency]], None]
 | 
				
			||||||
@@ -475,7 +475,7 @@ def _execute_version(pkg, ver, **kwargs):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def _depends_on(
 | 
					def _depends_on(
 | 
				
			||||||
    pkg: "spack.package_base.PackageBase",
 | 
					    pkg: "spack.package_base.PackageBase",
 | 
				
			||||||
    spec: SpecType,
 | 
					    spec: "spack.spec.Spec",
 | 
				
			||||||
    *,
 | 
					    *,
 | 
				
			||||||
    when: WhenType = None,
 | 
					    when: WhenType = None,
 | 
				
			||||||
    type: DepType = dt.DEFAULT_TYPES,
 | 
					    type: DepType = dt.DEFAULT_TYPES,
 | 
				
			||||||
@@ -485,11 +485,10 @@ def _depends_on(
 | 
				
			|||||||
    if not when_spec:
 | 
					    if not when_spec:
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dep_spec = spack.spec.Spec(spec)
 | 
					    if not spec.name:
 | 
				
			||||||
    if not dep_spec.name:
 | 
					        raise DependencyError(f"Invalid dependency specification in package '{pkg.name}':", spec)
 | 
				
			||||||
        raise DependencyError("Invalid dependency specification in package '%s':" % pkg.name, spec)
 | 
					    if pkg.name == spec.name:
 | 
				
			||||||
    if pkg.name == dep_spec.name:
 | 
					        raise CircularReferenceError(f"Package '{pkg.name}' cannot depend on itself.")
 | 
				
			||||||
        raise CircularReferenceError("Package '%s' cannot depend on itself." % pkg.name)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    depflag = dt.canonicalize(type)
 | 
					    depflag = dt.canonicalize(type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -505,7 +504,7 @@ def _depends_on(
 | 
				
			|||||||
    # ensure `Spec.virtual` is a valid thing to call in a directive.
 | 
					    # ensure `Spec.virtual` is a valid thing to call in a directive.
 | 
				
			||||||
    # For now, we comment out the following check to allow for virtual packages
 | 
					    # For now, we comment out the following check to allow for virtual packages
 | 
				
			||||||
    # with package files.
 | 
					    # with package files.
 | 
				
			||||||
    # if patches and dep_spec.virtual:
 | 
					    # if patches and spec.virtual:
 | 
				
			||||||
    #     raise DependencyPatchError("Cannot patch a virtual dependency.")
 | 
					    #     raise DependencyPatchError("Cannot patch a virtual dependency.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # ensure patches is a list
 | 
					    # ensure patches is a list
 | 
				
			||||||
@@ -520,13 +519,13 @@ def _depends_on(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # this is where we actually add the dependency to this package
 | 
					    # this is where we actually add the dependency to this package
 | 
				
			||||||
    deps_by_name = pkg.dependencies.setdefault(when_spec, {})
 | 
					    deps_by_name = pkg.dependencies.setdefault(when_spec, {})
 | 
				
			||||||
    dependency = deps_by_name.get(dep_spec.name)
 | 
					    dependency = deps_by_name.get(spec.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if not dependency:
 | 
					    if not dependency:
 | 
				
			||||||
        dependency = Dependency(pkg, dep_spec, depflag=depflag)
 | 
					        dependency = Dependency(pkg, spec, depflag=depflag)
 | 
				
			||||||
        deps_by_name[dep_spec.name] = dependency
 | 
					        deps_by_name[spec.name] = dependency
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        dependency.spec.constrain(dep_spec, deps=False)
 | 
					        dependency.spec.constrain(spec, deps=False)
 | 
				
			||||||
        dependency.depflag |= depflag
 | 
					        dependency.depflag |= depflag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # apply patches to the dependency
 | 
					    # apply patches to the dependency
 | 
				
			||||||
@@ -591,12 +590,13 @@ def depends_on(
 | 
				
			|||||||
    @see The section "Dependency specs" in the Spack Packaging Guide.
 | 
					    @see The section "Dependency specs" in the Spack Packaging Guide.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    if spack.spec.Spec(spec).name in SUPPORTED_LANGUAGES:
 | 
					    dep_spec = spack.spec.Spec(spec)
 | 
				
			||||||
 | 
					    if dep_spec.name in SUPPORTED_LANGUAGES:
 | 
				
			||||||
        assert type == "build", "languages must be of 'build' type"
 | 
					        assert type == "build", "languages must be of 'build' type"
 | 
				
			||||||
        return _language(lang_spec_str=spec, when=when)
 | 
					        return _language(lang_spec_str=spec, when=when)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _execute_depends_on(pkg: "spack.package_base.PackageBase"):
 | 
					    def _execute_depends_on(pkg: "spack.package_base.PackageBase"):
 | 
				
			||||||
        _depends_on(pkg, spec, when=when, type=type, patches=patches)
 | 
					        _depends_on(pkg, dep_spec, when=when, type=type, patches=patches)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return _execute_depends_on
 | 
					    return _execute_depends_on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -666,25 +666,24 @@ def extends(spec, when=None, type=("build", "run"), patches=None):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    keyword arguments can be passed to extends() so that extension
 | 
					    keyword arguments can be passed to extends() so that extension
 | 
				
			||||||
    packages can pass parameters to the extendee's extension
 | 
					    packages can pass parameters to the extendee's extension
 | 
				
			||||||
    mechanism.
 | 
					    mechanism."""
 | 
				
			||||||
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _execute_extends(pkg):
 | 
					    def _execute_extends(pkg):
 | 
				
			||||||
        when_spec = _make_when_spec(when)
 | 
					        when_spec = _make_when_spec(when)
 | 
				
			||||||
        if not when_spec:
 | 
					        if not when_spec:
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        _depends_on(pkg, spec, when=when, type=type, patches=patches)
 | 
					        dep_spec = spack.spec.Spec(spec)
 | 
				
			||||||
        spec_obj = spack.spec.Spec(spec)
 | 
					
 | 
				
			||||||
 | 
					        _depends_on(pkg, dep_spec, when=when, type=type, patches=patches)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # When extending python, also add a dependency on python-venv. This is done so that
 | 
					        # When extending python, also add a dependency on python-venv. This is done so that
 | 
				
			||||||
        # Spack environment views are Python virtual environments.
 | 
					        # Spack environment views are Python virtual environments.
 | 
				
			||||||
        if spec_obj.name == "python" and not pkg.name == "python-venv":
 | 
					        if dep_spec.name == "python" and not pkg.name == "python-venv":
 | 
				
			||||||
            _depends_on(pkg, "python-venv", when=when, type=("build", "run"))
 | 
					            _depends_on(pkg, spack.spec.Spec("python-venv"), when=when, type=("build", "run"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # TODO: the values of the extendees dictionary are not used. Remove in next refactor.
 | 
					        # TODO: the values of the extendees dictionary are not used. Remove in next refactor.
 | 
				
			||||||
        pkg.extendees[spec_obj.name] = (spec_obj, None)
 | 
					        pkg.extendees[dep_spec.name] = (dep_spec, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return _execute_extends
 | 
					    return _execute_extends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import spack.compilers
 | 
					import spack.compilers
 | 
				
			||||||
import spack.config
 | 
					import spack.config
 | 
				
			||||||
 | 
					import spack.dependency
 | 
				
			||||||
import spack.deptypes as dt
 | 
					import spack.deptypes as dt
 | 
				
			||||||
import spack.directives
 | 
					import spack.directives
 | 
				
			||||||
import spack.directory_layout
 | 
					import spack.directory_layout
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@ def test_extends_spec(config, mock_packages):
 | 
				
			|||||||
def test_error_on_anonymous_dependency(config, mock_packages):
 | 
					def test_error_on_anonymous_dependency(config, mock_packages):
 | 
				
			||||||
    pkg = spack.repo.PATH.get_pkg_class("pkg-a")
 | 
					    pkg = spack.repo.PATH.get_pkg_class("pkg-a")
 | 
				
			||||||
    with pytest.raises(spack.directives.DependencyError):
 | 
					    with pytest.raises(spack.directives.DependencyError):
 | 
				
			||||||
        spack.directives._depends_on(pkg, "@4.5")
 | 
					        spack.directives._depends_on(pkg, spack.spec.Spec("@4.5"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.regression("34879")
 | 
					@pytest.mark.regression("34879")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user