'Merge the constraints of other with self.
Returns True if the spec changed as a result, False if not.'

def constrain(self, other, deps=True):

    if self.concrete:
        if self.satisfies(other):
            return False
        else:
            raise UnsatisfiableSpecError(self, other, 'constrain    a    concrete    spec')
    other = self._autospec(other)
    if (not ((self.name == other.name) or (not self.name) or (not other.name))):
        raise UnsatisfiableSpecNameError(self.name, other.name)
    if ((other.namespace is not None) and (self.namespace is not None) and (other.namespace != self.namespace)):
        raise UnsatisfiableSpecNameError(self.fullname, other.fullname)
    if (not self.versions.overlaps(other.versions)):
        raise UnsatisfiableVersionSpecError(self.versions, other.versions)
    for v in [x for x in other.variants if (x in self.variants)]:
        if (not self.variants[v].compatible(other.variants[v])):
            raise UnsatisfiableVariantSpecError(self.variants[v], other.variants[v])
    (sarch, oarch) = (self.architecture, other.architecture)
    if ((sarch is not None) and (oarch is not None)):
        if ((sarch.platform is not None) and (oarch.platform is not None)):
            if (sarch.platform != oarch.platform):
                raise UnsatisfiableArchitectureSpecError(sarch, oarch)
        if ((sarch.platform_os is not None) and (oarch.platform_os is not None)):
            if (sarch.platform_os != oarch.platform_os):
                raise UnsatisfiableArchitectureSpecError(sarch, oarch)
        if ((sarch.target is not None) and (oarch.target is not None)):
            if (sarch.target != oarch.target):
                raise UnsatisfiableArchitectureSpecError(sarch, oarch)
    changed = False
    if ((self.compiler is not None) and (other.compiler is not None)):
        changed |= self.compiler.constrain(other.compiler)
    elif (self.compiler is None):
        changed |= (self.compiler != other.compiler)
        self.compiler = other.compiler
    changed |= self.versions.intersect(other.versions)
    changed |= self.variants.constrain(other.variants)
    changed |= self.compiler_flags.constrain(other.compiler_flags)
    old = str(self.architecture)
    (sarch, oarch) = (self.architecture, other.architecture)
    if ((sarch is None) or (other.architecture is None)):
        self.architecture = (sarch or oarch)
    else:
        if ((sarch.platform is None) or (oarch.platform is None)):
            self.architecture.platform = (sarch.platform or oarch.platform)
        if ((sarch.platform_os is None) or (oarch.platform_os is None)):
            sarch.platform_os = (sarch.platform_os or oarch.platform_os)
        if ((sarch.target is None) or (oarch.target is None)):
            sarch.target = (sarch.target or oarch.target)
    changed |= (str(self.architecture) != old)
    if deps:
        changed |= self._constrain_dependencies(other)
    return changed
