docs: def write_taxtable(self, out_fp, **kwargs):
          """
          Write a taxtable for this node and all descendants,
          including the lineage leading to this node.
          """
          ranks_represented = frozenset(i.rank for i in self) | \
              frozenset(i.rank for i in self.lineage())
          ranks = [i for i in self.ranks if i in ranks_represented]
          assert len(ranks_represented) == len(ranks)
  
          def node_record(node):
              parent_id = node.parent.tax_id if node.parent else node.tax_id
              d = {'tax_id': node.tax_id,
                   'tax_name': node.name,
                   'parent_id': parent_id,
                   'rank': node.rank}
              L = {i.rank: i.tax_id for i in node.lineage()}
              d.update(L)
              return d
  
          header = ['tax_id', 'parent_id', 'rank', 'tax_name'] + ranks
          w = csv.DictWriter(out_fp, header, quoting=csv.QUOTE_NONNUMERIC,
                             lineterminator='\n')
          w.writeheader()
          # All nodes leading to this one
          for i in self.lineage()[:-1]:
              w.writerow(node_record(i))
          w.writerows(node_record(i) for i in self)