Answers.Body: <p>I guess you want to take the features for a gene?</p>
  
  <p>As @haci and @terdon pointed out, it's a problem with the selected. Below I included an example, with mouse_extra_comma.gff3 obtained from example file provided by the package gffutils.</p>
  
  <pre><code>#gff.py
  #!/usr/bin/python3
  
  ###
  def addNote(x):
      x.attributes['Note'] = ["Gene description"]
      return(x)
  
  ###
  
  import click
  import gffutils
  import gffutils.gffwriter as gffwriter
  
  fn = gffutils.example_filename('mouse_extra_comma.gff3')
  db = gffutils.create_db(fn, dbfn='test.db', force=True, keep_order=True,
      merge_strategy='merge', sort_attribute_values=True)
  
  db = gffutils.FeatureDB('./test.db', keep_order=True)
  
  ## here's to test so you can see how it works
  gene = next(db.features_of_type('gene', order_by='start')) 
  items =[addNote(i) for i in db.children(gene, featuretype=['exon','CDS'],order_by='start')]
  
  items[0:5]
  #[&lt;Feature mRNA (chr17:6797760-6818159[+]) at 0x103659c50&gt;,
  # &lt;Feature exon (chr17:6797760-6797769[+]) at 0x1037cee10&gt;,
  # &lt;Feature five_prime_UTR (chr17:6797760-6797769[+]) at 0x103660898&gt;,
  # &lt;Feature exon (chr17:6806513-6806553[+]) at 0x103659f98&gt;,
  # &lt;Feature five_prime_UTR (chr17:6806513-6806526[+]) at 0x1036595f8&gt;]
  #####
  ## here's following your... code...
  for gene in db.features_of_type('gene', order_by='start'):
      print(gene)
      for i in db.children(gene,order_by='start'):
          print(addNote(i))
  
  
  
  </code></pre>
  
  <p>Once you define the feature you want, should be ok</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T00:02:00.410Z
Answers.Text: Thank you but I do not know how to do it?
Answers.UserDisplayName: user977828
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T07:58:28.807Z
Answers.Text: Could you elaborate on which step are you stuck? Would be glad to guide you along
Answers.UserDisplayName: StupidWolf
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T14:12:33.063Z
Answers.Text: Where could I add something like `mrna.attributes['Note'] = "Gene description"?
Answers.UserDisplayName: user977828
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T19:18:08.283Z
Answers.Text: You would write a function. I have edited my code above, although i am still a bit confused about what you need. If I get you correct, you would like to:
  1. For every gene, print the gene first
  2. Then print all features (mRNA, exon, CDS) associated with the gene, and attached a gene description note
  3. Write to this a file
  
  Is this correct? If so, could you please formulate the question in this way.
Answers.UserDisplayName: StupidWolf
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T23:05:04.673Z
Answers.Text: Thank you for the code. I need only to append to the original GFF3 file in the mRNA attribute Note=Gene description. For example  from `NbV1Ch08 AUGUSTUS mRNA 22418839 22429909 0.17 + . ID=g1168.t1;Parent=g1168;` to  `NbV1Ch08 AUGUSTUS mRNA 22418839 22429909 0.17 + . ID=g1168.t1;Parent=g1168;Note=Gene description;`. Next I would like to save the changes.
Answers.UserDisplayName: user977828
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-28T13:43:54.803Z
Answers.LastActivityDate: 2019-08-29T19:16:30.500Z
Answers.LastEditDate: 2019-08-29T19:16:30.500Z
Answers.UserDisplayName: StupidWolf
Answers.Body: <p>If you're willing to give another GFF3 processing library a shot, I'd recommend checking out the <a href="https://tag.readthedocs.io/en/latest/" rel="nofollow noreferrer"><code>tag</code> library</a>. The following code should add the note attribute to mRNA records as you're attempting to do in you're original code, but will also print out all other records.</p>
  
  <pre class="lang-py prettyprint-override"><code>import sys
  import tag
  
  def add_description(instream):
      for record in instream:
          if not isinstance(record, tag.Feature):
              yield record
              continue
          for mrna in tag.select.features(record, type='mRNA', traverse=True):
              mrna.add_attribute('Note', 'Gene description')
          yield feature
  
  reader = tag.GFF3Reader(instream=sys.stdin)
  desc_stream = add_description(reader)
  writer = tag.GFF3Writer(desc_stream)
  writer.retainids = True
  writer.write()
  </code></pre>
  
  <p>I didn't use click or argparse to put any CLI on the script, so unless you want to add those just use STDIN and STDOUT for I/O.</p>
  
  <p><code>$ python3 myscript.py &lt; mydata.gff3 &gt; mydatawithdescription.gff3</code></p>
  
  <hr>
  
  <p>P.S. The <code>add_description</code> can be simplified if you don't care about retaining comments, <code>##sequence-region</code> pragmas, and so on.</p>
  
  <pre class="lang-py prettyprint-override"><code>def add_description(instream):
      for feature in tag.select.features(instream):
          for mrna in tag.select.features(record, type='mRNA', traverse=True):
              mrna.add_attribute('Note', 'Gene description')
          yield feature
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T00:01:23.557Z
Answers.Text: Thank you for your solution. Unfortunately, I ran into `TypeError: 'Directive' object is not iterable` as shown in my updated question. What did I miss?
Answers.UserDisplayName: user977828
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T18:29:27.993Z
Answers.Text: @user977828 I wrote the initial code with the (bad) assumption that the input data didn't include any comments, pragmas, directives, etc. I've updated my answer to show how to handle input that includes these types of records, or below that is a simpler solution that ignores them.
Answers.UserDisplayName: Daniel Standage
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T23:14:36.803Z
Answers.Text: Thank you it works.
Answers.UserDisplayName: user977828
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-30T12:44:37.780Z
Answers.Text: How is it possible to avoid to change mRNA's ID?
Answers.UserDisplayName: user977828
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-30T13:59:05.727Z
Answers.Text: At the moment, there is no way to change tag's default behavior: it rewrites all ID attributes, since according to the spec these attributes are only guaranteed to be consistent and unique within a single file, not across files.
Answers.UserDisplayName: Daniel Standage
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-04-25T21:09:14.650Z
Answers.Text: Revisiting this a few months later: as of January, `tag.GFF3Writer` objects now have a `.retainids` attribute to keep the original ID values. Example updated reflect.
Answers.UserDisplayName: Daniel Standage
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-28T13:16:57.707Z
Answers.LastActivityDate: 2020-04-25T21:09:52.367Z
Answers.LastEditDate: 2020-04-25T21:09:52.367Z
Answers.UserDisplayName: Daniel Standage
Answers.Body: <p>You might want to check this line out:</p>
  
  <p><code>for gene in db.features_of_type('gene', order_by='start'):</code></p>
  
  <p>You are specifically filtering for <code>gene</code>s hence other types of annotations are filtered out.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T00:03:14.957Z
Answers.Text: Thank you but I do not know how to do it?
Answers.UserDisplayName: user977828
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T00:15:39.227Z
Answers.Text: Please see this about the features_of_type method: https://pythonhosted.org/gffutils/autodocs/gffutils.FeatureDB.features_of_type.html . It basically tells to provide a string or tuple of feature(s) that you would like to retrieve, in your case all the features in the original file. The easiest would be take the unique values in the "feature" column of your input and feed it into the "features_of_type" method.
Answers.UserDisplayName: haci
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-29T14:15:12.430Z
Answers.Text: Where could I add something like `mrna.attributes['Note'] = "Gene description"?
Answers.UserDisplayName: user977828
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-08-28T12:59:36.997Z
Answers.LastActivityDate: 2019-08-28T13:14:59.073Z
Answers.LastEditDate: 2019-08-28T13:14:59.073Z
Answers.UserDisplayName: haci
Body: <p>I modified the GFF3 file with the below code:</p>
  <pre><code>#!/usr/bin/python3
  import click
  import gffutils
  import gffutils.gffwriter as gffwriter
  
  @click.command()
  @click.option('--gff3', help=&quot;Provide GFF3 file&quot;, required=True)
  @click.option('--keep', help=&quot;Keep GFF3 file&quot;, required=True)
  @click.option('--reject', help=&quot;Reject GFF3 file&quot;, required=True)
  def run(gff3, keep, reject):
      #db = gffutils.create_db(gff3, dbfn='data/test.db', force=True, keep_order=True, merge_strategy='merge',
      #                        sort_attribute_values=True)
  
      out_keep = gffwriter.GFFWriter(keep)
      db = gffutils.FeatureDB('data/test.db', keep_order=True)
      for gene in db.features_of_type('gene', order_by='start'):
          print(gene)
          for i in db.children(gene, featuretype='mRNA', order_by='start'):
              print(i)
              i.attributes['Note'] = [&quot;Gene description&quot;]
              print(i)
              out_keep.write_rec(gene)
  </code></pre>
  <p>Unfortunately, the above code saved only this:</p>
  
  <pre class="lang-none prettyprint-override"><code>#GFF3 file (created by gffutils (v0.9) on 2019-08-28 22:14:13)
  NbV1Ch08        AUGUSTUS        gene    7015    29794   0.01    -       .       ID=g1;
  NbV1Ch08        AUGUSTUS        gene    60876   63944   0.03    +       .       ID=g2;
  NbV1Ch08        AUGUSTUS        gene    64722   65524   0.32    -       .       ID=g3;
  NbV1Ch08        AUGUSTUS        gene    66706   67484   0.12    -       .       ID=g4;
  NbV1Ch08        AUGUSTUS        gene    115451  122754  0.16    -       .       ID=g5;
  NbV1Ch08        AUGUSTUS        gene    147786  155025  0.24    +       .       ID=g6;
  NbV1Ch08        AUGUSTUS        gene    155152  161104  0.28    -       .       ID=g7;
  NbV1Ch08        AUGUSTUS        gene    237126  238098  0.05    +       .       ID=g8;
  NbV1Ch08        AUGUSTUS        gene    265796  297830  0.82    +       .       ID=g9;
  NbV1Ch08        AUGUSTUS        gene    265796  297830  0.82    +       .       ID=g9;
  </code></pre>
  <p>Rather than:</p>
  <pre class="lang-none prettyprint-override"><code>NbV1Ch08        AUGUSTUS        gene    7015    29794   0.01    -       .       ID=g1;
  NbV1Ch08        AUGUSTUS        mRNA    7015    29794   0.01    -       .       ID=g1.t1;Parent=g1;Note=Gene description;
  NbV1Ch08        AUGUSTUS        transcription_end_site  7015    7015    .       -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        three_prime_utr 7015    8531    0.2     -       .       ID=g1.t1.3UTR1;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    7015    8747    .       -       .       ID=g1.t1.exon1;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        stop_codon      8532    8534    .       -       0       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     8532    8747    0.31    -       0       ID=g1.t1.CDS1;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        intron  8748    9191    0.49    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     9192    9342    0.66    -       1       ID=g1.t1.CDS2;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    9192    9342    .       -       .       ID=g1.t1.exon2;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  9343    9915    0.58    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     9916    10006   0.71    -       2       ID=g1.t1.CDS3;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    9916    10006   .       -       .       ID=g1.t1.exon3;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  10007   10101   0.74    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     10102   10201   0.78    -       0       ID=g1.t1.CDS4;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    10102   10201   .       -       .       ID=g1.t1.exon4;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  10202   10712   0.8     -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     10713   11107   0.11    -       2       ID=g1.t1.CDS5;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    10713   11107   .       -       .       ID=g1.t1.exon5;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  11108   11569   0.07    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     11570   12151   0.09    -       2       ID=g1.t1.CDS6;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    11570   12151   .       -       .       ID=g1.t1.exon6;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  12152   12588   0.34    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     12589   12717   0.39    -       2       ID=g1.t1.CDS7;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    12589   12717   .       -       .       ID=g1.t1.exon7;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  12718   12789   0.42    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     12790   13075   0.39    -       0       ID=g1.t1.CDS8;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    12790   13075   .       -       .       ID=g1.t1.exon8;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  13076   14832   0.51    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     14833   15009   0.39    -       0       ID=g1.t1.CDS9;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    14833   15009   .       -       .       ID=g1.t1.exon9;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  15010   15278   0.59    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     15279   15415   0.56    -       2       ID=g1.t1.CDS10;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    15279   15415   .       -       .       ID=g1.t1.exon10;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  15416   15487   0.58    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     15488   15612   0.96    -       1       ID=g1.t1.CDS11;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    15488   15612   .       -       .       ID=g1.t1.exon11;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  15613   15706   0.96    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     15707   15957   0.98    -       0       ID=g1.t1.CDS12;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    15707   15958   .       -       .       ID=g1.t1.exon12;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        start_codon     15955   15957   .       -       0       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        five_prime_utr  15958   15958   0.99    -       .       ID=g1.t1.5UTR1;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        five_prime_utr  27458   28250   0.37    -       .       ID=g1.t1.5UTR2;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    27458   28250   .       -       .       ID=g1.t1.exon13;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        five_prime_utr  29272   29794   0.08    -       .       ID=g1.t1.5UTR3;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    29272   29794   .       -       .       ID=g1.t1.exon14;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        transcription_start_site        29794   29794   .       -       .       Parent=g1.t1;
  </code></pre>
  <p>What did I miss?</p>
  <p><strong>Update</strong> This is based on @daniel-standage's code.</p>
  
  <pre class="lang-none prettyprint-override"><code>import click
  import tag
  def add_description(instream):
      for feature in instream:
          for mrna in tag.select.features(feature, type='mRNA', traverse=True):
              mrna.add_attribute('Note', 'Gene description')
  
          yield feature
  
  
  @click.command()
  @click.option('--gff3', help=&quot;Provide GFF3 file&quot;, required=True)
  @click.option('--keep', help=&quot;Keep GFF3 file&quot;, required=True)
  @click.option('--reject', help=&quot;Reject GFF3 file&quot;, required=True)
  def run(gff3, keep, reject):
      reader = tag.GFF3Reader(infilename=gff3)
      desc_stream = add_description(reader)
      writer = tag.GFF3Writer(desc_stream)
      writer.write()
  
  
  if __name__ == '__main__':
      run()
  </code></pre>
  <p>which caused this error:</p>
  <pre class="lang-none prettyprint-override"><code>mod_braker_gff3.py --gff3 data/NbV1Ch08-augustus.hints_utr.gff3 --keep data/keep.gff3 --reject data/reject.gff3
  Traceback (most recent call last):
    File &quot;/Users/lorencm/projects/bioinf-scripts/mod_braker_gff3.py&quot;, line 26, in &lt;module&gt;
      run()
    File &quot;/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/click/core.py&quot;, line 764, in __call__
      return self.main(*args, **kwargs)
    File &quot;/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/click/core.py&quot;, line 717, in main
      rv = self.invoke(ctx)
    File &quot;/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/click/core.py&quot;, line 956, in invoke
      return ctx.invoke(self.callback, **ctx.params)
    File &quot;/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/click/core.py&quot;, line 555, in invoke
      return callback(*args, **kwargs)
    File &quot;/Users/lorencm/projects/bioinf-scripts/mod_braker_gff3.py&quot;, line 22, in run
      writer.write()
    File &quot;/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/tag/writer.py&quot;, line 57, in write
      for entry in self._instream:
    File &quot;/Users/lorencm/projects/bioinf-scripts/mod_braker_gff3.py&quot;, line 8, in add_description
      for mrna in tag.select.features(feature, type='mRNA', traverse=True):
    File &quot;/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/tag/select.py&quot;, line 24, in features
      for feature in entry_type_filter(entrystream, tag.Feature):
    File &quot;/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/tag/select.py&quot;, line 99, in entry_type_filter
      for entry in entrystream:
  TypeError: 'Directive' object is not iterable
  
  Process finished with exit code 1
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-08-28T13:01:38.177Z
Comments.Text: As haci, said you're filtering for genes. When you have this sort of issue, the first step should always be to print everything. For example, if you tried `print db.children(gene, featuretype='mRNA', order_by='start')`, you'd presumably see that it is empty.
Comments.UserDisplayName: terdon
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-08-29T04:33:53.790Z
Comments.Text: If you [cross post](https://www.biostars.org/p/edit/395802/) your question please leave a note, so that other can see what is already answered!
Comments.UserDisplayName: finswimmer
Tags: <python><sequence-annotation><gff3><gffutils>
Title: Modifying a GFF3 file and writing to a new file
ThreadText: # Modifying a GFF3 file and writing to a new file
  
  (Asked by: username_0 on 2019-08-28)
  
  I modified the GFF3 file with the below code:
  
  ```
  #!/usr/bin/python3
  import click
  import gffutils
  import gffutils.gffwriter as gffwriter
  
  @click.command()
  @click.option('--gff3', help="Provide GFF3 file", required=True)
  @click.option('--keep', help="Keep GFF3 file", required=True)
  @click.option('--reject', help="Reject GFF3 file", required=True)
  def run(gff3, keep, reject):
      #db = gffutils.create_db(gff3, dbfn='data/test.db', force=True, keep_order=True, merge_strategy='merge',
      #                        sort_attribute_values=True)
  
      out_keep = gffwriter.GFFWriter(keep)
      db = gffutils.FeatureDB('data/test.db', keep_order=True)
      for gene in db.features_of_type('gene', order_by='start'):
          print(gene)
          for i in db.children(gene, featuretype='mRNA', order_by='start'):
              print(i)
              i.attributes['Note'] = ["Gene description"]
              print(i)
              out_keep.write_rec(gene)
  
  ```
  
  Unfortunately, the above code saved only this:
  
  ```none
  #GFF3 file (created by gffutils (v0.9) on 2019-08-28 22:14:13)
  NbV1Ch08        AUGUSTUS        gene    7015    29794   0.01    -       .       ID=g1;
  NbV1Ch08        AUGUSTUS        gene    60876   63944   0.03    +       .       ID=g2;
  NbV1Ch08        AUGUSTUS        gene    64722   65524   0.32    -       .       ID=g3;
  NbV1Ch08        AUGUSTUS        gene    66706   67484   0.12    -       .       ID=g4;
  NbV1Ch08        AUGUSTUS        gene    115451  122754  0.16    -       .       ID=g5;
  NbV1Ch08        AUGUSTUS        gene    147786  155025  0.24    +       .       ID=g6;
  NbV1Ch08        AUGUSTUS        gene    155152  161104  0.28    -       .       ID=g7;
  NbV1Ch08        AUGUSTUS        gene    237126  238098  0.05    +       .       ID=g8;
  NbV1Ch08        AUGUSTUS        gene    265796  297830  0.82    +       .       ID=g9;
  NbV1Ch08        AUGUSTUS        gene    265796  297830  0.82    +       .       ID=g9;
  
  ```
  
  Rather than:
  
  ```none
  NbV1Ch08        AUGUSTUS        gene    7015    29794   0.01    -       .       ID=g1;
  NbV1Ch08        AUGUSTUS        mRNA    7015    29794   0.01    -       .       ID=g1.t1;Parent=g1;Note=Gene description;
  NbV1Ch08        AUGUSTUS        transcription_end_site  7015    7015    .       -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        three_prime_utr 7015    8531    0.2     -       .       ID=g1.t1.3UTR1;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    7015    8747    .       -       .       ID=g1.t1.exon1;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        stop_codon      8532    8534    .       -       0       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     8532    8747    0.31    -       0       ID=g1.t1.CDS1;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        intron  8748    9191    0.49    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     9192    9342    0.66    -       1       ID=g1.t1.CDS2;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    9192    9342    .       -       .       ID=g1.t1.exon2;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  9343    9915    0.58    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     9916    10006   0.71    -       2       ID=g1.t1.CDS3;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    9916    10006   .       -       .       ID=g1.t1.exon3;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  10007   10101   0.74    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     10102   10201   0.78    -       0       ID=g1.t1.CDS4;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    10102   10201   .       -       .       ID=g1.t1.exon4;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  10202   10712   0.8     -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     10713   11107   0.11    -       2       ID=g1.t1.CDS5;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    10713   11107   .       -       .       ID=g1.t1.exon5;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  11108   11569   0.07    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     11570   12151   0.09    -       2       ID=g1.t1.CDS6;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    11570   12151   .       -       .       ID=g1.t1.exon6;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  12152   12588   0.34    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     12589   12717   0.39    -       2       ID=g1.t1.CDS7;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    12589   12717   .       -       .       ID=g1.t1.exon7;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  12718   12789   0.42    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     12790   13075   0.39    -       0       ID=g1.t1.CDS8;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    12790   13075   .       -       .       ID=g1.t1.exon8;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  13076   14832   0.51    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     14833   15009   0.39    -       0       ID=g1.t1.CDS9;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    14833   15009   .       -       .       ID=g1.t1.exon9;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  15010   15278   0.59    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     15279   15415   0.56    -       2       ID=g1.t1.CDS10;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    15279   15415   .       -       .       ID=g1.t1.exon10;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  15416   15487   0.58    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     15488   15612   0.96    -       1       ID=g1.t1.CDS11;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    15488   15612   .       -       .       ID=g1.t1.exon11;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        intron  15613   15706   0.96    -       .       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        CDS     15707   15957   0.98    -       0       ID=g1.t1.CDS12;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    15707   15958   .       -       .       ID=g1.t1.exon12;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        start_codon     15955   15957   .       -       0       Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        five_prime_utr  15958   15958   0.99    -       .       ID=g1.t1.5UTR1;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        five_prime_utr  27458   28250   0.37    -       .       ID=g1.t1.5UTR2;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    27458   28250   .       -       .       ID=g1.t1.exon13;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        five_prime_utr  29272   29794   0.08    -       .       ID=g1.t1.5UTR3;Parent=g1.t1
  NbV1Ch08        AUGUSTUS        exon    29272   29794   .       -       .       ID=g1.t1.exon14;Parent=g1.t1;
  NbV1Ch08        AUGUSTUS        transcription_start_site        29794   29794   .       -       .       Parent=g1.t1;
  
  ```
  
  What did I miss?
  
  **Update** This is based on @username_4-username_4's code.
  
  ```none
  import click
  import tag
  def add_description(instream):
      for feature in instream:
          for mrna in tag.select.features(feature, type='mRNA', traverse=True):
              mrna.add_attribute('Note', 'Gene description')
  
          yield feature
  
  @click.command()
  @click.option('--gff3', help="Provide GFF3 file", required=True)
  @click.option('--keep', help="Keep GFF3 file", required=True)
  @click.option('--reject', help="Reject GFF3 file", required=True)
  def run(gff3, keep, reject):
      reader = tag.GFF3Reader(infilename=gff3)
      desc_stream = add_description(reader)
      writer = tag.GFF3Writer(desc_stream)
      writer.write()
  
  if __name__ == '__main__':
      run()
  
  ```
  
  which caused this error:
  
  ```none
  mod_braker_gff3.py --gff3 data/NbV1Ch08-augustus.hints_utr.gff3 --keep data/keep.gff3 --reject data/reject.gff3
  Traceback (most recent call last):
    File "/Users/lorencm/projects/bioinf-scripts/mod_braker_gff3.py", line 26, in <module>
      run()
    File "/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/click/core.py", line 764, in __call__
      return self.main(*args, **kwargs)
    File "/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/click/core.py", line 717, in main
      rv = self.invoke(ctx)
    File "/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/click/core.py", line 956, in invoke
      return ctx.invoke(self.callback, **ctx.params)
    File "/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/click/core.py", line 555, in invoke
      return callback(*args, **kwargs)
    File "/Users/lorencm/projects/bioinf-scripts/mod_braker_gff3.py", line 22, in run
      writer.write()
    File "/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/tag/writer.py", line 57, in write
      for entry in self._instream:
    File "/Users/lorencm/projects/bioinf-scripts/mod_braker_gff3.py", line 8, in add_description
      for mrna in tag.select.features(feature, type='mRNA', traverse=True):
    File "/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/tag/select.py", line 24, in features
      for feature in entry_type_filter(entrystream, tag.Feature):
    File "/anaconda/envs/bioinf-scripts/lib/python3.7/site-packages/tag/select.py", line 99, in entry_type_filter
      for entry in entrystream:
  TypeError: 'Directive' object is not iterable
  
  Process finished with exit code 1
  
  ```
  
  **Tags:** python, sequence-annotation, gff3, gffutils
  
  > **Comments:**
  > **username_1**: As username_5, said you're filtering for genes. When you have this sort of issue, the first step should always be to print everything. For example, if you tried `print db.children(gene, featuretype='mRNA', order_by='start')`, you'd presumably see that it is empty.  
  > **username_2**: If you [cross post](https://www.biostars.org/p/edit/395802/) your question please leave a note, so that other can see what is already answered!  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_3 on 2019-08-28. Score: 2
  
  I guess you want to take the features for a gene?
  
  As @username_5 and @username_1 pointed out, it's a problem with the selected. Below I included an example, with mouse\_extra\_comma.gff3 obtained from example file provided by the package gffutils.
  
  ```
  #gff.py
  #!/usr/bin/python3
  
  ###
  def addNote(x):
      x.attributes['Note'] = ["Gene description"]
      return(x)
  
  ###
  
  import click
  import gffutils
  import gffutils.gffwriter as gffwriter
  
  fn = gffutils.example_filename('mouse_extra_comma.gff3')
  db = gffutils.create_db(fn, dbfn='test.db', force=True, keep_order=True,
      merge_strategy='merge', sort_attribute_values=True)
  
  db = gffutils.FeatureDB('./test.db', keep_order=True)
  
  ## here's to test so you can see how it works
  gene = next(db.features_of_type('gene', order_by='start')) 
  items =[addNote(i) for i in db.children(gene, featuretype=['exon','CDS'],order_by='start')]
  
  items[0:5]
  #[<Feature mRNA (chr17:6797760-6818159[+]) at 0x103659c50>,
  # <Feature exon (chr17:6797760-6797769[+]) at 0x1037cee10>,
  # <Feature five_prime_UTR (chr17:6797760-6797769[+]) at 0x103660898>,
  # <Feature exon (chr17:6806513-6806553[+]) at 0x103659f98>,
  # <Feature five_prime_UTR (chr17:6806513-6806526[+]) at 0x1036595f8>]
  #####
  ## here's following your... code...
  for gene in db.features_of_type('gene', order_by='start'):
      print(gene)
      for i in db.children(gene,order_by='start'):
          print(addNote(i))
  
  ```
  
  Once you define the feature you want, should be ok
  
  > **Comments:**
  > **username_0**: Thank you but I do not know how to do it?  
  > **username_3**: Could you elaborate on which step are you stuck? Would be glad to guide you along  
  > **username_0**: Where could I add something like `mrna.attributes['Note'] = "Gene description"?  
  > **username_3**: You would write a function. I have edited my code above, although i am still a bit confused about what you need. If I get you correct, you would like to: 1. For every gene, print the gene first 2. Then print all features (mRNA, exon, CDS) associated with the gene, and attached a gene description note 3. Write to this a file  Is this correct? If so, could you please formulate the question in this way.  
  > **username_0**: Thank you for the code. I need only to append to the original GFF3 file in the mRNA attribute Note=Gene description. For example  from `NbV1Ch08 AUGUSTUS mRNA 22418839 22429909 0.17 + . ID=g1168.t1;Parent=g1168;` to  `NbV1Ch08 AUGUSTUS mRNA 22418839 22429909 0.17 + . ID=g1168.t1;Parent=g1168;Note=Gene description;`. Next I would like to save the changes.  
  
  ---
  
  ### Answer by username_4 on 2019-08-28. Score: 1
  
  If you're willing to give another GFF3 processing library a shot, I'd recommend checking out the [`tag` library](https://tag.readthedocs.io/en/latest/). The following code should add the note attribute to mRNA records as you're attempting to do in you're original code, but will also print out all other records.
  
  ```py
  import sys
  import tag
  
  def add_description(instream):
      for record in instream:
          if not isinstance(record, tag.Feature):
              yield record
              continue
          for mrna in tag.select.features(record, type='mRNA', traverse=True):
              mrna.add_attribute('Note', 'Gene description')
          yield feature
  
  reader = tag.GFF3Reader(instream=sys.stdin)
  desc_stream = add_description(reader)
  writer = tag.GFF3Writer(desc_stream)
  writer.retainids = True
  writer.write()
  
  ```
  
  I didn't use click or argparse to put any CLI on the script, so unless you want to add those just use STDIN and STDOUT for I/O.
  
  `$ python3 myscript.py < mydata.gff3 > mydatawithdescription.gff3`
  
  ---
  
  P.S. The `add_description` can be simplified if you don't care about retaining comments, `##sequence-region` pragmas, and so on.
  
  ```py
  def add_description(instream):
      for feature in tag.select.features(instream):
          for mrna in tag.select.features(record, type='mRNA', traverse=True):
              mrna.add_attribute('Note', 'Gene description')
          yield feature
  
  ```
  
  > **Comments:**
  > **username_0**: Thank you for your solution. Unfortunately, I ran into `TypeError: 'Directive' object is not iterable` as shown in my updated question. What did I miss?  
  > **username_4**: @username_0 I wrote the initial code with the (bad) assumption that the input data didn't include any comments, pragmas, directives, etc. I've updated my answer to show how to handle input that includes these types of records, or below that is a simpler solution that ignores them.  
  > **username_0**: Thank you it works.  
  > **username_0**: How is it possible to avoid to change mRNA's ID?  
  > **username_4**: At the moment, there is no way to change tag's default behavior: it rewrites all ID attributes, since according to the spec these attributes are only guaranteed to be consistent and unique within a single file, not across files.  
  > **username_4**: Revisiting this a few months later: as of January, `tag.GFF3Writer` objects now have a `.retainids` attribute to keep the original ID values. Example updated reflect.  
  
  ---
  
  ### Answer by username_5 on 2019-08-28. Score: 1
  
  You might want to check this line out:
  
  `for gene in db.features_of_type('gene', order_by='start'):`
  
  You are specifically filtering for `gene`s hence other types of annotations are filtered out.
  
  > **Comments:**
  > **username_0**: Thank you but I do not know how to do it?  
  > **username_5**: Please see this about the features_of_type method: https://pythonhosted.org/gffutils/autodocs/gffutils.FeatureDB.features_of_type.html . It basically tells to provide a string or tuple of feature(s) that you would like to retrieve, in your case all the features in the original file. The easiest would be take the unique values in the "feature" column of your input and feed it into the "features_of_type" method.  
  > **username_0**: Where could I add something like `mrna.attributes['Note'] = "Gene description"?  
  
  ---
  
  