def gemerate_database_info(inputs, targets, allow_unfound=False):
    """
    Construct db info from input nodes and target nodes.
    :param inputs: list of input nodes
    :param targets: list of target nodes
    :param allow_unfound: don't check if names are valid

    Builds a list of the db names for the nodes.
    If

    :return:
    """
    db_info = {
        "inputs": [i.db_name for i in inputs],
        "targets": [i.db_name for i in targets],
    }

    # Allows `None` to pass through.
    if allow_unfound:
        return db_info

    # If none of the names was `None`, return.
    if not any(name is None for row in db_info.values() for name in row):
        return db_info

    # Else, we need to raise an error.

    missing_inputs = [i for i, idb in zip(inputs, db_info["inputs"]) if idb is None]
    missing_targets = [i for i, idb in zip(targets, db_info["targets"]) if idb is None]

    msg = ""
    if missing_inputs:
        msg += "Missing inputs: {}\n".format(missing_inputs)
    if missing_targets:
        msg += "Missing targets: {}\n".format(missing_targets)

    raise ValueError("Required quantities for the graph inputs or targets are not mapped to a db name:\n{}".format(msg))