Repository: cogent3/cogent3
Pull request #981 (2021-11-04 05:13:49)

BUG: RichGenbankParser moltype argument now overrides file spec
[CHANGED] if provided, this defines the moltype of the returned sequence,
    otherwise the moltype is determined from the genbank file meta-data


Patch:
diff --git a/src/cogent3/parse/genbank.py b/src/cogent3/parse/genbank.py
index bf0b2932b..2e23510c0 100644
--- a/src/cogent3/parse/genbank.py
+++ b/src/cogent3/parse/genbank.py
@@ -445,12 +445,12 @@ class LocationList(list):
         """Extracts pieces of self from sequence."""
         result = []
         for i in self:
-            first, last = i.first(), i.last() + 1  # inclusive, not exclusive
+            first, last = i.first() - 1, i.last()  # inclusive, not exclusive
             # translate to 0-based indices and check if it wraps around
             if first < last:
-                curr = sequence[first - 1 : last - 1]
+                curr = sequence[first:last]
             else:
-                curr = sequence[first - 1 :] + sequence[: last - 1]
+                curr = sequence[first:] + sequence[:last]
             # reverse-complement if necessary
             if i.Strand == -1:
                 curr = curr.translate(trans_table)[::-1]
@@ -638,7 +638,7 @@ def RichGenbankParser(
 
     """
     info_excludes = info_excludes or []
-    moltype = get_moltype(moltype or "text")
+    moltype = get_moltype(moltype) if moltype else None
     for rec in MinimalGenbankParser(handle):
         info = Info()
         # populate the info object, excluding the sequence
@@ -647,11 +647,17 @@ def RichGenbankParser(
                 continue
             info[label] = value
 
-        if rec["mol_type"].lower() in ("dna", "rna", "protein"):
-            moltype = get_moltype(rec["mol_type"].lower())
+        if moltype is None:
+            rec_moltype = rec["mol_type"].lower()
+            rec_moltype = (
+                rec_moltype if rec_moltype in ("dna", "rna", "protein") else "text"
+            )
+            rec_moltype = get_moltype(rec_moltype)
+        else:
+            rec_moltype = moltype
 
         try:
-            seq = moltype.make_seq(
+            seq = rec_moltype.make_seq(
                 rec["sequence"].upper(), info=info, name=rec["locus"]
             )
         except KeyError:


Test patch:
diff --git a/tests/test_parse/test_genbank.py b/tests/test_parse/test_genbank.py
index 6cfeecbc4..ba8b75f33 100644
--- a/tests/test_parse/test_genbank.py
+++ b/tests/test_parse/test_genbank.py
@@ -477,16 +477,26 @@ ORIGIN
             parser = RichGenbankParser(infile)
             got_1 = [s for _, s in parser][0]
 
-        with open("data/annotated_seq.gb") as infile:
-            parser = RichGenbankParser(infile, moltype="dna")
-            got_2 = [s for _, s in parser][0]
-
-        self.assertEqual(len(got_1.annotations), len(got_2.annotations))
-        self.assertEqual(got_2.moltype.label, "dna")
         # name formed from /product value
-        got = {f.name for f in got_2.get_annotations_matching("mRNA")}
+        got = {f.name for f in got_1.get_annotations_matching("mRNA")}
         self.assertEqual(got, {"conserved hypothetical protein", "chaperone, putative"})
 
+        # the file defines itself as DNA
+        self.assertEqual(got_1.moltype.label, "dna")
+
+        # but that is overridden by user setting moltype explicitly
+        for moltype in ("dna", "rna", "text"):
+            with open("data/annotated_seq.gb") as infile:
+                parser = RichGenbankParser(infile, moltype=moltype)
+                got_2 = [s for _, s in parser][0]
+
+            self.assertEqual(len(got_1.annotations), len(got_2.annotations))
+            self.assertEqual(got_2.moltype.label, moltype)
+            got = {f.name for f in got_1.get_annotations_matching("mRNA")}
+            self.assertEqual(
+                got, {"conserved hypothetical protein", "chaperone, putative"}
+            )
+
 
 class LocationTests(TestCase):
     """Tests of the Location class."""