diff --git a/bob/devtools/graph.py b/bob/devtools/graph.py
index 059d0190e49ebc2f0cd30a8e60bfb52de75efa53..cb8d4819900356385053e0eac3ad274b7621a652 100644
--- a/bob/devtools/graph.py
+++ b/bob/devtools/graph.py
@@ -16,13 +16,21 @@ from .build import (
     get_parsed_recipe,
     get_output_path,
 )
-from .log import get_logger
+from .log import get_logger, echo_info
+
 logger = get_logger(__name__)
 
 
-def compute_adjencence_matrix(gl, package, conda_config, main_channel,
-        recurse_regexp="^(bob|beat|batl|gridtk)(\.)?(?!-).*$", current={},
-        ref="master"):
+def compute_adjencence_matrix(
+    gl,
+    package,
+    conda_config,
+    main_channel,
+    recurse_regexp="^(bob|beat|batl|gridtk)(\.)?(?!-).*$",
+    current={},
+    ref="master",
+    deptypes=[],
+):
     """
     Given a target package, returns an adjacence matrix with its dependencies
     returned via the conda-build API
@@ -62,6 +70,11 @@ def compute_adjencence_matrix(gl, package, conda_config, main_channel,
     ref : str
         Name of the git reference (branch, tag or commit hash) to use
 
+    deptypes : list
+        A list of dependence types to preserve when building the graph.  If
+        empty, then preserve all.  You may set values "build", "host",
+        "run" and "test", in any combination
+
 
     Returns
     -------
@@ -75,24 +88,31 @@ def compute_adjencence_matrix(gl, package, conda_config, main_channel,
     """
 
     use_package = gl.projects.get(package)
+    deptypes = deptypes if deptypes else ["host", "build", "run", "test"]
+
+    if use_package.attributes["path_with_namespace"] in current:
+        return current
 
-    logger.info('Resolving graph for %s@%s',
-            use_package.attributes["path_with_namespace"], ref)
+    echo_info(
+        "Resolving graph for %s@%s"
+        % (use_package.attributes["path_with_namespace"], ref)
+    )
     with tempfile.TemporaryDirectory() as tmpdir:
 
-        logger.debug('Downloading archive for %s...', ref)
-        archive = use_package.repository_archive(ref=ref)  #in memory
+        logger.debug("Downloading archive for %s...", ref)
+        archive = use_package.repository_archive(ref=ref)  # in memory
         logger.debug("Archive has %d bytes", len(archive))
 
         with tarfile.open(fileobj=BytesIO(archive), mode="r:gz") as f:
             f.extractall(path=tmpdir)
 
         # use conda-build API to figure out all dependencies
-        recipe_dir = glob.glob(os.path.join(tmpdir, '*', 'conda'))[0]
-        logger.debug('Resolving conda recipe for package at %s...', recipe_dir)
+        recipe_dir = glob.glob(os.path.join(tmpdir, "*", "conda"))[0]
+        logger.debug("Resolving conda recipe for package at %s...", recipe_dir)
         if not os.path.exists(recipe_dir):
-            raise RuntimeError("The conda recipe directory %s does not " \
-                    "exist" % recipe_dir)
+            raise RuntimeError(
+                "The conda recipe directory %s does not " "exist" % recipe_dir
+            )
 
         version_candidate = os.path.join(recipe_dir, "..", "version.txt")
         if os.path.exists(version_candidate):
@@ -105,65 +125,94 @@ def compute_adjencence_matrix(gl, package, conda_config, main_channel,
         path = get_output_path(metadata, conda_config)
 
         # gets the next build number
-        build_number, _ = next_build_number(main_channel,
-                os.path.basename(path))
+        build_number, _ = next_build_number(
+            main_channel, os.path.basename(path)
+        )
 
         # at this point, all elements are parsed, I know the package version,
         # build number and all dependencies
+        # exclude stuff we are not interested in
 
         # host and build should have precise numbers to be used for building
         # this package.
-        host = rendered_recipe['requirements'].get('host', [])
-        build = rendered_recipe['requirements'].get('build', [])
+        if "host" not in deptypes:
+            host = []
+        else:
+            host = rendered_recipe["requirements"].get("host", [])
+
+        if "build" not in deptypes:
+            build = []
+        else:
+            build = rendered_recipe["requirements"].get("build", [])
 
         # run dependencies are more vague
-        run = rendered_recipe['requirements'].get('run', [])
+        if "run" not in deptypes:
+            run = []
+        else:
+            run = rendered_recipe["requirements"].get("run", [])
 
         # test dependencies even more vague
-        test = rendered_recipe.get('test', {}).get('requires', [])
+        if "test" not in deptypes:
+            test = []
+        else:
+            test = rendered_recipe.get("test", {}).get("requires", [])
 
         # for each of the above sections, recurse in figuring out dependencies,
         # if dependencies match a target set of globs
         recurse_compiled = re.compile(recurse_regexp)
+
         def _re_filter(l):
             return [k for k in l if recurse_compiled.match(k)]
-        host_recurse = set([z.split()[0] for z in _re_filter(host)])
-        build_recurse = set([z.split()[0] for z in _re_filter(build)])
-        run_recurse = set([z.split()[0] for z in _re_filter(run)])
-        test_recurse = set([z.split()[0] for z in _re_filter(test)])
 
-        # we do not separate host/build/run/test dependencies and assume they
-        # will all be of the same version in the end.  Otherwise, we would need
-        # to do this in a bit more careful way.
-        all_recurse = host_recurse | build_recurse | run_recurse | test_recurse
+        all_recurse = set()
+        all_recurse |= set([z.split()[0] for z in _re_filter(host)])
+        all_recurse |= set([z.split()[0] for z in _re_filter(build)])
+        all_recurse |= set([z.split()[0] for z in _re_filter(run)])
+        all_recurse |= set([z.split()[0] for z in _re_filter(test)])
 
         # complete the package group, which is not provided by conda-build
         def _add_default_group(p):
-            if p.startswith('bob') or p.startswith('gridtk'):
-                return '/'.join(('bob', p))
-            elif p.startswith('beat'):
-                return '/'.join(('beat', p))
-            elif p.startswith('batl'):
-                return '/'.join(('batl', p))
+            if p.startswith("bob") or p.startswith("gridtk"):
+                return "/".join(("bob", p))
+            elif p.startswith("beat"):
+                return "/".join(("beat", p))
+            elif p.startswith("batl"):
+                return "/".join(("batl", p))
             else:
-                raise RuntimeError('Do not know how to recurse to package %s' \
-                        % (p,))
+                logger.warning("Do not know how to recurse to package %s "
+                        "(to which group does it belong?) - skipping...", p)
+                return None
+
         all_recurse = set([_add_default_group(k) for k in all_recurse])
+        if None in all_recurse:
+            all_recurse.remove(None)
 
         # do not recurse for packages we already know
         all_recurse -= set(current.keys())
-        logger.debug("Recursing over the following packages: %s",
+        logger.info("Recursing over the following packages: %s",
                 ", ".join(all_recurse))
 
         for dep in all_recurse:
-            dep_adjmtx = compute_adjencence_matrix(gl, dep, conda_config,
-                    main_channel, recurse_regexp=recurse_regexp, ref=ref)
+            dep_adjmtx = compute_adjencence_matrix(
+                gl,
+                dep,
+                conda_config,
+                main_channel,
+                recurse_regexp=recurse_regexp,
+                ref=ref,
+                deptypes=deptypes,
+            )
             current.update(dep_adjmtx)
 
-        current[package] = dict(host=host, build=build, run=run, test=test,
-                version=rendered_recipe["package"]["version"],
-                name=rendered_recipe["package"]["name"],
-                build_string=os.path.basename(path).split('-')[-1].split('.')[0])
+        current[package] = dict(
+            host=host,
+            build=build,
+            run=run,
+            test=test,
+            version=rendered_recipe["package"]["version"],
+            name=rendered_recipe["package"]["name"],
+            build_string=os.path.basename(path).split("-")[-1].split(".")[0],
+        )
 
     return current
 
@@ -208,13 +257,21 @@ def generate_graph(adjacence_matrix, deptypes, whitelist):
     # generate nodes for all packages we want to track explicitly
     for package, values in adjacence_matrix.items():
         if not whitelist_compiled.match(values["name"]):
-            logger.debug("Skipping main package %s (did not match whitelist)",
-                    value["name"])
+            logger.debug(
+                "Skipping main package %s (did not match whitelist)",
+                values["name"],
+            )
             continue
-        name = values["name"] + "\n" + values["version"] + "\n" \
-                + values["build_string"]
-        nodes[values["name"]] = graph.node(values["name"], name, shape="box",
-                color="blue")
+        name = (
+            values["name"]
+            + "\n"
+            + values["version"]
+            + "\n"
+            + values["build_string"]
+        )
+        nodes[values["name"]] = graph.node(
+            values["name"], name, shape="box", color="blue"
+        )
 
     # generates nodes for all dependencies
     for package, values in adjacence_matrix.items():
@@ -231,17 +288,18 @@ def generate_graph(adjacence_matrix, deptypes, whitelist):
 
         for ref, parts in deps.items():
             if not whitelist_compiled.match(ref):
-                logger.debug("Skipping dependence %s (did not match whitelist)",
-                        ref)
+                logger.debug(
+                    "Skipping dependence %s (did not match whitelist)", ref
+                )
                 continue
 
             if not any([k == ref for k in nodes.keys()]):
                 # we do not have a node for that dependence, create it
-                name = str(ref)  #new string
+                name = str(ref)  # new string
                 if len(parts) >= 1:
-                    name += "\n" + parts[0]  #dep version
+                    name += "\n" + parts[0]  # dep version
                 if len(parts) >= 2:
-                    name += "\n" + parts[1]  #dep build
+                    name += "\n" + parts[1]  # dep build
                 nodes[ref] = graph.node(ref, name)
 
             # connects package -> dep
diff --git a/bob/devtools/scripts/graph.py b/bob/devtools/scripts/graph.py
index ffc790c471448bdc7cc418c1df9cd022fbbb4f5d..922ecaa83b8f87407f09bcdf96af0dabcc7a758a 100644
--- a/bob/devtools/scripts/graph.py
+++ b/bob/devtools/scripts/graph.py
@@ -30,7 +30,9 @@ Examples:
 
   1. Draws the graph of a package
 
-     $ bdt gitlab graph bob/bob.bio.face
+     $ bdt gitlab graph -vv bob/bob.learn.linear
+
+  2.
 
 
 """
@@ -115,11 +117,22 @@ Examples:
     default="^(bob|beat|batl|gridtk)(\.)?(?!-).*$",
     help="package regular expression to preserve in the graph, "
     "use .* for keeping all packages, including non-maintained ones.  The "
-    "current expression accepts most of our packages, excluding bob/beat-devel")
+    "current expression accepts most of our packages, excluding "
+    "bob/beat-devel.  This flag only affects the graph generation - we still "
+    "recurse over all packages to calculate dependencies.")
+@click.option(
+    "-d",
+    "--deptypes",
+    show_default=True,
+    default=[],
+    multiple=True,
+    help="types of dependencies to consider.  Pass multiple times to include "
+    "more types.  Valid types are 'host', 'build', 'run' and 'test'.  An "
+    "empty set considers all dependencies to the graph")
 @verbosity_option()
 @bdt.raise_on_error
 def graph(package, python, condarc, config, append_file, server, private,
-        stable, ci, name, format, whitelist):
+        stable, ci, name, format, whitelist, deptypes):
     """
     Computes the dependency graph of a gitlab package (via its conda recipe)
     and outputs an dot file that can be used by graphviz to draw a direct
@@ -171,7 +184,8 @@ def graph(package, python, condarc, config, append_file, server, private,
     set_environment("BOB_DOCUMENTATION_SERVER", "/not/set")
 
     adj_matrix = compute_adjencence_matrix(gl, package, conda_config,
-            channels[0])
+            channels[0], deptypes=deptypes)
 
-    graph = generate_graph(adj_matrix, deptypes=[], whitelist=whitelist)
+    graph = generate_graph(adj_matrix, deptypes=deptypes, whitelist=whitelist)
     graph.render(name, format=format, cleanup=True)
+