docs: def david_results_iterator(fn, verbose=False):
    """
    Iterate over a DAVID result set and yeild GeneOntologyTerm objects
    representing each of the terms reported. The expected format for a DAVID
    result file is tab-seperated format. The following fields should be present:
  
    ===  ===============  ==========  ====================================
    Num  Field                 Type        Example
    ===  ===============  ==========  ====================================
    0    Category         string      GOTERM_BP_FAT
    1    Term             string      GO:0046907~intracellular transport
    2    Count            int         43
    3    Percent          float       11.345646437994723
    4    PValue           float       1.3232857694449546E-9
    5    Genes            string      ARSB, KPNA6, GNAS
    6    List Total       int         310
    7    Pop Hits         int         657
    8    Pop Total        int         13528
    9    Fold Enrichment  float       2.8561103746256196
    10   Bonferroni       float       2.6293654579179204E-6
    11   Benjamini        float       2.6293654579179204E-6
    12   FDR              float       2.2734203852792234E-6
    ===  ===============  ==========  ====================================
  
    The first line is a header giving the field names -- this is ignored though,
    and we expect them in the order given above.
  
    Most of the fields are ignored at present; we take fields 0,1, and 11 (as the
    significance/p-value). When parsing the term field, we try to extract a term
    ID by splitting on tilde, but if we can't then this is set to None.
  
    :param fn: the file to parse
    :param verbose: if True, output progress to stderr.
    """
    first = True
    for line in open(fn):
      line = line.strip()
      if line == "":
        continue
      if first:
        first = False
        continue
  
      parts = line.split("\t")
      if len(parts) != NUM_FIELDS_IN_DAVID_RECORD:
        raise IOError("failed to parse " + fn + " as DAVID result file. "
                      + "Expected " + str(NUM_FIELDS_IN_DAVID_RECORD) + " "
                      + "tab-separated fields, but found "
                      + str(len(parts)) + " instead")
      n_parts = parts[1].split("~")
      name = n_parts[-1].strip()
      identifier = n_parts[0] if len(n_parts) > 1 else None
      catagory = parts[0].strip()
      try:
        p_val = float(parts[PVAL_FIELD_NUM])
      except ValueError:
        raise IOError("Failed to parse " + fn + " as DAVID result file. "
                      + "Expected field " + str(PVAL_FIELD_NUM) + " "
                      + "to contain a floating point number "
                      + "(Benjamini), found this instead: "
                      + str(parts[PVAL_FIELD_NUM]))
      yield GeneOntologyEnrichmentResult(name, p_val, identifier, catagory)