nodes: 0, module; 1, function_definition; 2, function_name:iter_gff3; 3, parameters; 4, block; 5, identifier:path; 6, default_parameter; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, default_parameter; 11, default_parameter; 12, expression_statement; 13, comment:# prepare fill values for attributes; 14, if_statement; 15, comment:# open input stream; 16, if_statement; 17, try_statement; 18, identifier:attributes; 19, None; 20, identifier:region; 21, None; 22, identifier:score_fill; 23, unary_operator; 24, identifier:phase_fill; 25, unary_operator; 26, identifier:attributes_fill; 27, string; 28, identifier:tabix; 29, string; 30, comment:"""Iterate over records in a GFF3 file.
  
      Parameters
      ----------
      path : string
          Path to input file.
      attributes : list of strings, optional
          List of columns to extract from the "attributes" field.
      region : string, optional
          Genome region to extract. If given, file must be position
          sorted, bgzipped and tabix indexed. Tabix must also be installed
          and on the system path.
      score_fill : int, optional
          Value to use where score field has a missing value.
      phase_fill : int, optional
          Value to use where phase field has a missing value.
      attributes_fill : object or list of objects, optional
          Value(s) to use where attribute field(s) have a missing value.
      tabix : string
          Tabix command.
  
      Returns
      -------
      Iterator
  
      """; 31, comparison_operator:attributes is not None; 32, block; 33, comparison_operator:region is not None; 34, block; 35, elif_clause; 36, else_clause; 37, block; 38, finally_clause; 39, integer:1; 40, integer:1; 41, string_content:.; 42, string_content:tabix; 43, identifier:attributes; 44, None; 45, expression_statement; 46, if_statement; 47, identifier:region; 48, None; 49, expression_statement; 50, expression_statement; 51, boolean_operator; 52, block; 53, block; 54, for_statement; 55, block; 56, assignment; 57, call; 58, block; 59, else_clause; 60, assignment; 61, assignment; 62, call; 63, call; 64, expression_statement; 65, expression_statement; 66, identifier:line; 67, identifier:buffer; 68, block; 69, expression_statement; 70, identifier:attributes; 71, call; 72, identifier:isinstance; 73, argument_list; 74, if_statement; 75, block; 76, identifier:cmd; 77, list; 78, identifier:buffer; 79, attribute; 80, attribute; 81, argument_list; 82, attribute; 83, argument_list; 84, assignment; 85, assignment; 86, if_statement; 87, if_statement; 88, expression_statement; 89, if_statement; 90, call; 91, identifier:list; 92, argument_list; 93, identifier:attributes_fill; 94, tuple; 95, comparison_operator:len(attributes) != len(attributes_fill); 96, block; 97, expression_statement; 98, identifier:tabix; 99, identifier:path; 100, identifier:region; 101, call; 102, identifier:stdout; 103, identifier:path; 104, identifier:endswith; 105, string; 106, identifier:path; 107, identifier:endswith; 108, string; 109, identifier:buffer; 110, call; 111, identifier:buffer; 112, call; 113, comparison_operator:line[0] == b'>'; 114, comment:# assume begin embedded FASTA; 115, block; 116, comparison_operator:line[0] == b'#'; 117, comment:# skip comment lines; 118, block; 119, assignment; 120, comparison_operator:len(vals) == 9; 121, comment:# unpack for processing; 122, block; 123, attribute; 124, argument_list; 125, identifier:attributes; 126, identifier:list; 127, identifier:tuple; 128, call; 129, call; 130, raise_statement; 131, assignment; 132, attribute; 133, argument_list; 134, string_content:.gz; 135, string_content:.bgz; 136, attribute; 137, argument_list; 138, identifier:open; 139, argument_list; 140, subscript; 141, string; 142, return_statement; 143, subscript; 144, string; 145, continue_statement; 146, identifier:vals; 147, call; 148, call; 149, integer:9; 150, expression_statement; 151, comment:# convert numerics; 152, expression_statement; 153, expression_statement; 154, if_statement; 155, if_statement; 156, if_statement; 157, expression_statement; 158, if_statement; 159, expression_statement; 160, identifier:buffer; 161, identifier:close; 162, identifier:len; 163, argument_list; 164, identifier:len; 165, argument_list; 166, call; 167, identifier:attributes_fill; 168, binary_operator:[attributes_fill] * len(attributes); 169, identifier:subprocess; 170, identifier:Popen; 171, identifier:cmd; 172, keyword_argument; 173, identifier:gzip; 174, identifier:open; 175, identifier:path; 176, keyword_argument; 177, identifier:path; 178, keyword_argument; 179, identifier:line; 180, integer:0; 181, string_content:>; 182, identifier:line; 183, integer:0; 184, string_content:#; 185, attribute; 186, argument_list; 187, identifier:len; 188, argument_list; 189, assignment; 190, assignment; 191, assignment; 192, comparison_operator:fscore == b'.'; 193, block; 194, else_clause; 195, comparison_operator:fphase == b'.'; 196, block; 197, else_clause; 198, not_operator; 199, block; 200, assignment; 201, comparison_operator:attributes is not None; 202, block; 203, yield; 204, identifier:attributes; 205, identifier:attributes_fill; 206, identifier:ValueError; 207, argument_list; 208, list; 209, call; 210, identifier:stdout; 211, attribute; 212, identifier:mode; 213, string; 214, identifier:mode; 215, string; 216, identifier:line; 217, identifier:split; 218, string; 219, identifier:vals; 220, pattern_list; 221, identifier:vals; 222, identifier:fstart; 223, call; 224, identifier:fend; 225, call; 226, identifier:fscore; 227, string; 228, expression_statement; 229, block; 230, identifier:fphase; 231, string; 232, expression_statement; 233, block; 234, identifier:PY2; 235, expression_statement; 236, expression_statement; 237, expression_statement; 238, expression_statement; 239, expression_statement; 240, identifier:rec; 241, tuple; 242, identifier:attributes; 243, None; 244, expression_statement; 245, expression_statement; 246, expression_statement; 247, identifier:rec; 248, string; 249, identifier:attributes_fill; 250, identifier:len; 251, argument_list; 252, identifier:subprocess; 253, identifier:PIPE; 254, string_content:rb; 255, string_content:rb; 256, string_content; 257, identifier:fseqid; 258, identifier:fsource; 259, identifier:ftype; 260, identifier:fstart; 261, identifier:fend; 262, identifier:fscore; 263, identifier:fstrand; 264, identifier:fphase; 265, identifier:fattrs; 266, identifier:int; 267, argument_list; 268, identifier:int; 269, argument_list; 270, string_content:.; 271, assignment; 272, expression_statement; 273, string_content:.; 274, assignment; 275, expression_statement; 276, assignment; 277, assignment; 278, assignment; 279, assignment; 280, assignment; 281, identifier:fseqid; 282, identifier:fsource; 283, identifier:ftype; 284, identifier:fstart; 285, identifier:fend; 286, identifier:fscore; 287, identifier:fstrand; 288, identifier:fphase; 289, assignment; 290, assignment; 291, augmented_assignment; 292, string_content:number of fills does not match attributes; 293, identifier:attributes; 294, escape_sequence:\t; 295, identifier:fstart; 296, identifier:fend; 297, identifier:fscore; 298, identifier:score_fill; 299, assignment; 300, identifier:fphase; 301, identifier:phase_fill; 302, assignment; 303, identifier:fseqid; 304, call; 305, identifier:fsource; 306, call; 307, identifier:ftype; 308, call; 309, identifier:fstrand; 310, call; 311, identifier:fattrs; 312, call; 313, identifier:dattrs; 314, call; 315, identifier:vattrs; 316, call; 317, identifier:rec; 318, identifier:vattrs; 319, identifier:fscore; 320, call; 321, identifier:fphase; 322, call; 323, identifier:str; 324, argument_list; 325, identifier:str; 326, argument_list; 327, identifier:str; 328, argument_list; 329, identifier:str; 330, argument_list; 331, identifier:str; 332, argument_list; 333, identifier:gff3_parse_attributes; 334, argument_list; 335, identifier:tuple; 336, generator_expression; 337, identifier:float; 338, argument_list; 339, identifier:int; 340, argument_list; 341, identifier:fseqid; 342, string; 343, identifier:fsource; 344, string; 345, identifier:ftype; 346, string; 347, identifier:fstrand; 348, string; 349, identifier:fattrs; 350, string; 351, identifier:fattrs; 352, call; 353, for_in_clause; 354, identifier:fscore; 355, identifier:fphase; 356, string_content:ascii; 357, string_content:ascii; 358, string_content:ascii; 359, string_content:ascii; 360, string_content:ascii; 361, attribute; 362, argument_list; 363, pattern_list; 364, call; 365, identifier:dattrs; 366, identifier:get; 367, identifier:k; 368, identifier:f; 369, identifier:k; 370, identifier:f; 371, identifier:zip; 372, argument_list; 373, identifier:attributes; 374, identifier:attributes_fill
code: def iter_gff3(path, attributes=None, region=None, score_fill=-1,
                phase_fill=-1, attributes_fill='.', tabix='tabix'):
      """Iterate over records in a GFF3 file.
  
      Parameters
      ----------
      path : string
          Path to input file.
      attributes : list of strings, optional
          List of columns to extract from the "attributes" field.
      region : string, optional
          Genome region to extract. If given, file must be position
          sorted, bgzipped and tabix indexed. Tabix must also be installed
          and on the system path.
      score_fill : int, optional
          Value to use where score field has a missing value.
      phase_fill : int, optional
          Value to use where phase field has a missing value.
      attributes_fill : object or list of objects, optional
          Value(s) to use where attribute field(s) have a missing value.
      tabix : string
          Tabix command.
  
      Returns
      -------
      Iterator
  
      """
  
      # prepare fill values for attributes
      if attributes is not None:
          attributes = list(attributes)
          if isinstance(attributes_fill, (list, tuple)):
              if len(attributes) != len(attributes_fill):
                  raise ValueError('number of fills does not match attributes')
          else:
              attributes_fill = [attributes_fill] * len(attributes)
  
      # open input stream
      if region is not None:
          cmd = [tabix, path, region]
          buffer = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout
      elif path.endswith('.gz') or path.endswith('.bgz'):
          buffer = gzip.open(path, mode='rb')
      else:
          buffer = open(path, mode='rb')
  
      try:
          for line in buffer:
              if line[0] == b'>':
                  # assume begin embedded FASTA
                  return
              if line[0] == b'#':
                  # skip comment lines
                  continue
              vals = line.split(b'\t')
              if len(vals) == 9:
                  # unpack for processing
                  fseqid, fsource, ftype, fstart, fend, fscore, fstrand, fphase, fattrs = vals
                  # convert numerics
                  fstart = int(fstart)
                  fend = int(fend)
                  if fscore == b'.':
                      fscore = score_fill
                  else:
                      fscore = float(fscore)
                  if fphase == b'.':
                      fphase = phase_fill
                  else:
                      fphase = int(fphase)
                  if not PY2:
                      fseqid = str(fseqid, 'ascii')
                      fsource = str(fsource, 'ascii')
                      ftype = str(ftype, 'ascii')
                      fstrand = str(fstrand, 'ascii')
                      fattrs = str(fattrs, 'ascii')
                  rec = (fseqid, fsource, ftype, fstart, fend, fscore, fstrand, fphase)
                  if attributes is not None:
                      dattrs = gff3_parse_attributes(fattrs)
                      vattrs = tuple(
                          dattrs.get(k, f)
                          for k, f in zip(attributes, attributes_fill)
                      )
                      rec += vattrs
                  yield rec
  
      finally:
          buffer.close()