def read_nodes(rows, source_id=1):
    """
    Return an iterator of rows ready to insert into table "nodes".

    * rows - iterator of lists (eg, output from read_archive or read_dmp)
    """

    ncbi_keys = ['tax_id', 'parent_id', 'rank', 'embl_code', 'division_id']
    extra_keys = ['source_id', 'is_valid']
    is_valid = True

    ncbi_cols = len(ncbi_keys)

    rank = ncbi_keys.index('rank')
    parent_id = ncbi_keys.index('parent_id')

    # assumes the first row is the root
    row = next(rows)
    row[rank] = 'root'
    # parent must be None for termination of recursive CTE for
    # calculating lineages
    row[parent_id] = None
    rows = itertools.chain([row], rows)

    yield ncbi_keys + extra_keys

    for row in rows:
        # replace whitespace in "rank" with underscore
        row[rank] = '_'.join(row[rank].split())
        # provide default values for source_id and is_valid
        yield row[:ncbi_cols] + [source_id, is_valid]
Return an iterator of rows ready to insert into table "nodes".

    * rows - iterator of lists (eg, output from read_archive or read_dmp)