Add --transitive option to spack dependents
				
					
				
			This commit is contained in:
		@@ -31,7 +31,7 @@
 | 
				
			|||||||
import spack.store
 | 
					import spack.store
 | 
				
			||||||
import spack.cmd
 | 
					import spack.cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
description = "show installed packages that depend on another"
 | 
					description = "show packages that depend on another"
 | 
				
			||||||
section = "basic"
 | 
					section = "basic"
 | 
				
			||||||
level = "long"
 | 
					level = "long"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -41,9 +41,12 @@ def setup_parser(subparser):
 | 
				
			|||||||
        '-i', '--installed', action='store_true', default=False,
 | 
					        '-i', '--installed', action='store_true', default=False,
 | 
				
			||||||
        help="List installed dependents of an installed spec, "
 | 
					        help="List installed dependents of an installed spec, "
 | 
				
			||||||
        "instead of possible dependents of a package.")
 | 
					        "instead of possible dependents of a package.")
 | 
				
			||||||
 | 
					    subparser.add_argument(
 | 
				
			||||||
 | 
					        '-t', '--transitive', action='store_true', default=False,
 | 
				
			||||||
 | 
					        help="Show all transitive dependents.")
 | 
				
			||||||
    subparser.add_argument(
 | 
					    subparser.add_argument(
 | 
				
			||||||
        'spec', nargs=argparse.REMAINDER,
 | 
					        'spec', nargs=argparse.REMAINDER,
 | 
				
			||||||
        help="spec to list dependents for")
 | 
					        help="spec or package name")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def inverted_dependencies():
 | 
					def inverted_dependencies():
 | 
				
			||||||
@@ -69,12 +72,13 @@ def inverted_dependencies():
 | 
				
			|||||||
    return dag
 | 
					    return dag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_dependents(pkg_name, ideps, dependents=None):
 | 
					def get_dependents(pkg_name, ideps, transitive=False, dependents=None):
 | 
				
			||||||
    """Get all dependents for a package.
 | 
					    """Get all dependents for a package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Args:
 | 
					    Args:
 | 
				
			||||||
        pkg_name (str): name of the package whose dependents should be returned
 | 
					        pkg_name (str): name of the package whose dependents should be returned
 | 
				
			||||||
        ideps (dict): dictionary of dependents, from inverted_dependencies()
 | 
					        ideps (dict): dictionary of dependents, from inverted_dependencies()
 | 
				
			||||||
 | 
					        transitive (bool, optional): return transitive dependents when True
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    if dependents is None:
 | 
					    if dependents is None:
 | 
				
			||||||
        dependents = set()
 | 
					        dependents = set()
 | 
				
			||||||
@@ -84,8 +88,9 @@ def get_dependents(pkg_name, ideps, dependents=None):
 | 
				
			|||||||
    dependents.add(pkg_name)
 | 
					    dependents.add(pkg_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    direct = ideps[pkg_name]
 | 
					    direct = ideps[pkg_name]
 | 
				
			||||||
 | 
					    if transitive:
 | 
				
			||||||
        for dep_name in direct:
 | 
					        for dep_name in direct:
 | 
				
			||||||
        get_dependents(dep_name, ideps, dependents)
 | 
					            get_dependents(dep_name, ideps, transitive, dependents)
 | 
				
			||||||
    dependents.update(direct)
 | 
					    dependents.update(direct)
 | 
				
			||||||
    return dependents
 | 
					    return dependents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -109,7 +114,7 @@ def dependents(parser, args):
 | 
				
			|||||||
        spec = specs[0]
 | 
					        spec = specs[0]
 | 
				
			||||||
        ideps = inverted_dependencies()
 | 
					        ideps = inverted_dependencies()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dependents = get_dependents(spec.name, ideps)
 | 
					        dependents = get_dependents(spec.name, ideps, args.transitive)
 | 
				
			||||||
        dependents.remove(spec.name)
 | 
					        dependents.remove(spec.name)
 | 
				
			||||||
        if dependents:
 | 
					        if dependents:
 | 
				
			||||||
            colify(sorted(dependents))
 | 
					            colify(sorted(dependents))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -711,11 +711,16 @@ def remove(self, spec):
 | 
				
			|||||||
            return self._remove(spec)
 | 
					            return self._remove(spec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @_autospec
 | 
					    @_autospec
 | 
				
			||||||
    def installed_dependents(self, spec):
 | 
					    def installed_dependents(self, spec, transitive=True):
 | 
				
			||||||
        """List the installed specs that depend on this one."""
 | 
					        """List the installed specs that depend on this one."""
 | 
				
			||||||
        dependents = set()
 | 
					        dependents = set()
 | 
				
			||||||
        for spec in self.query(spec):
 | 
					        for spec in self.query(spec):
 | 
				
			||||||
            for dependent in spec.traverse(direction='parents', root=False):
 | 
					            if transitive:
 | 
				
			||||||
 | 
					                to_add = spec.traverse(direction='parents', root=False)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                to_add = spec.dependents()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for dependent in to_add:
 | 
				
			||||||
                dependents.add(dependent)
 | 
					                dependents.add(dependent)
 | 
				
			||||||
        return dependents
 | 
					        return dependents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user