'Determine if this spec satisfies all constraints of another.
There are two senses for satisfies:
* `loose` (default): the absence of a constraint in self
implies that it *could* be satisfied by other, so we only
check that there are no conflicts with other for
constraints that this spec actually has.
* `strict`: strict means that we *must* meet all the
constraints specified on other.'

def satisfies(self, other, deps=True, strict=False, strict_deps=False):

    other = self._autospec(other)
    if other.concrete:
        return (self.concrete and (self.dag_hash() == other.dag_hash()))
    if ((not self.virtual) and other.virtual):
        try:
            pkg = spack.repo.get(self.fullname)
        except spack.repository.UnknownEntityError:
            return False
        if pkg.provides(other.name):
            for (provided, when_specs) in pkg.provided.items():
                if any((self.satisfies(when_spec, deps=False, strict=strict) for when_spec in when_specs)):
                    if provided.satisfies(other):
                        return True
        return False
    if ((self.name != other.name) and self.name and other.name):
        return False
    if ((other.namespace is not None) and (self.namespace is not None) and (self.namespace != other.namespace)):
        return False
    if (self.versions and other.versions):
        if (not self.versions.satisfies(other.versions, strict=strict)):
            return False
    elif (strict and (self.versions or other.versions)):
        return False
    if (self.compiler and other.compiler):
        if (not self.compiler.satisfies(other.compiler, strict=strict)):
            return False
    elif (strict and (other.compiler and (not self.compiler))):
        return False
    var_strict = strict
    if ((not self.name) or (not other.name)):
        var_strict = True
    if (not self.variants.satisfies(other.variants, strict=var_strict)):
        return False
    if (self.architecture and other.architecture):
        if (not self.architecture.satisfies(other.architecture, strict)):
            return False
    elif (strict and (other.architecture and (not self.architecture))):
        return False
    if (not self.compiler_flags.satisfies(other.compiler_flags, strict=strict)):
        return False
    if deps:
        deps_strict = strict
        if (self._concrete and (not other.name)):
            deps_strict = True
        return self.satisfies_dependencies(other, strict=deps_strict)
    else:
        return True
