Repository: cogent3/cogent3
Pull request #1405 (2023-05-01 22:58:53)

API: changed signature to GffAnnotationDb and GenbankAnnotationDb
[CHANGED] both signatures now require keyword arguments

[CHANGED] all arguments are now optional, so we can create an empty
	instance


Patch:
diff --git a/src/cogent3/__init__.py b/src/cogent3/__init__.py
index 3de4e33b5..56e2acd9c 100644
--- a/src/cogent3/__init__.py
+++ b/src/cogent3/__init__.py
@@ -19,7 +19,6 @@ from cogent3.core.alignment import (
 )
 from cogent3.core.annotation_db import load_annotations
 from cogent3.core.genetic_code import available_codes, get_code
-
 # note that moltype has to be imported last, because it sets the moltype in
 # the objects created by the other modules.
 from cogent3.core.moltype import (
diff --git a/src/cogent3/core/alignment.py b/src/cogent3/core/alignment.py
index 230412f96..a689df9fc 100644
--- a/src/cogent3/core/alignment.py
+++ b/src/cogent3/core/alignment.py
@@ -65,7 +65,6 @@ from cogent3.core.genetic_code import get_code
 from cogent3.core.info import Info as InfoClass
 from cogent3.core.profile import PSSM, MotifCountsArray
 from cogent3.core.sequence import ArraySequence, Sequence, frac_same
-
 # which is a circular import otherwise.
 from cogent3.format.alignment import save_to_filename
 from cogent3.format.fasta import alignment_to_fasta
@@ -2116,9 +2115,7 @@ class SequenceCollection(_SequenceCollectionBase):
                 # no matching ID's, nothing to do
                 return
 
-            self.annotation_db = type(seq_db)(
-                data=[]
-            )  # make an empty db of the same type
+            self.annotation_db = type(seq_db)()  # make an empty db of the same type
 
         if not isinstance(seq_db, type(self.annotation_db)):
             raise TypeError(f"type {type(seq_db)} != {type(self.annotation_db)}")
@@ -2214,7 +2211,7 @@ class SequenceCollection(_SequenceCollectionBase):
         """
         if not self.annotation_db:
             # todo gah can we define the default in some better way?
-            self.annotation_db = DEFAULT_ANNOTATION_DB(data=[])
+            self.annotation_db = DEFAULT_ANNOTATION_DB()
 
         if seqid and seqid not in self.names:
             raise ValueError(f"unknown {seqid=}")
@@ -5162,7 +5159,7 @@ class Alignment(_Annotatable, AlignmentI, SequenceCollection):
 
         if not self.annotation_db:
             # probably need to define the default in some better way
-            self.annotation_db = DEFAULT_ANNOTATION_DB(data=[])
+            self.annotation_db = DEFAULT_ANNOTATION_DB()
 
         feature = {k: v for k, v in locals().items() if k != "self"}
 
diff --git a/src/cogent3/core/annotation_db.py b/src/cogent3/core/annotation_db.py
index fcf0194f0..087035101 100644
--- a/src/cogent3/core/annotation_db.py
+++ b/src/cogent3/core/annotation_db.py
@@ -628,7 +628,7 @@ class SqliteAnnotationDbMixin:
     @classmethod
     def from_dict(cls, data: dict):
         # make an empty db
-        db = cls(data=[])
+        db = cls()
         db._update_db_from_rich_dict(data)
         return db
 
@@ -670,7 +670,8 @@ class GffAnnotationDb(SqliteAnnotationDbMixin):
         "parent_id": "TEXT",
     }
 
-    def __init__(self, data, db=None, source=":memory:"):
+    def __init__(self, *, data=None, db=None, source=":memory:"):
+        data = data or []
         # note that data is destroyed
         self._num_fakeids = 0
         self.source = source
@@ -837,7 +838,15 @@ class GenbankAnnotationDb(SqliteAnnotationDbMixin):
         "attributes": "json",
     }
 
-    def __init__(self, data: typing.List[dict], seqid: str, source=":memory:", db=None):
+    def __init__(
+        self,
+        *,
+        data: typing.Optional[typing.List[dict]] = None,
+        seqid: OptionalStr = None,
+        source=":memory:",
+        db=None,
+    ):
+        data = data or []
         # note that data is destroyed
         self._db = db
         self._num_fakeids = 0
@@ -981,7 +990,7 @@ def _db_from_genbank(path, db):
     with open_(path) as infile:
         data = list(MinimalGenbankParser(infile))
 
-    return GenbankAnnotationDb(data[0]["features"], data[0]["locus"], db=db)
+    return GenbankAnnotationDb(data=data[0]["features"], seqid=data[0]["locus"], db=db)
 
 
 def _leave_attributes(*attrs):
diff --git a/src/cogent3/core/sequence.py b/src/cogent3/core/sequence.py
index 858b7b9c1..541449e17 100644
--- a/src/cogent3/core/sequence.py
+++ b/src/cogent3/core/sequence.py
@@ -1115,7 +1115,7 @@ class Sequence(_Annotatable, SequenceI):
         on_alignment: bool = False,
     ) -> Annotation:
         if self.annotation_db is None:
-            self.annotation_db = GffAnnotationDb([])
+            self.annotation_db = GffAnnotationDb()
 
         feature_data = FeatureDataType(
             seqid=self.name, **{n: v for n, v in locals().items() if n != "self"}
@@ -1176,9 +1176,7 @@ class Sequence(_Annotatable, SequenceI):
 
         if not self.annotation_db:
             # todo gah add ability to query multiple values in Annotation db
-            self.annotation_db = type(seq_db)(
-                data=[]
-            )  # make an empty db of the same type
+            self.annotation_db = type(seq_db)()  # make an empty db of the same type
         elif not isinstance(seq_db, type(self.annotation_db)):
             raise TypeError(f"type {type(seq_db)} != {type(self.annotation_db)}")
 


Test patch:
diff --git a/tests/test_core/test_annotation_db.py b/tests/test_core/test_annotation_db.py
index 7e646eae9..be52b9ac2 100644
--- a/tests/test_core/test_annotation_db.py
+++ b/tests/test_core/test_annotation_db.py
@@ -56,7 +56,7 @@ def seq() -> Sequence:
 @pytest.fixture()
 def anno_db() -> GffAnnotationDb:
     # an empty db that we can add to
-    return GffAnnotationDb([])
+    return GffAnnotationDb()
 
 
 @pytest.fixture()
@@ -146,7 +146,7 @@ def test_to_rich_dict(gff_db):
 
 
 def test_empty_data():
-    _ = GffAnnotationDb([])
+    _ = GffAnnotationDb()
 
 
 # testing GenBank files
@@ -244,7 +244,7 @@ def test_gav():
     minus_seq = "".join(raw_seq[s:e] for s, e in minus_spans)
     minus_seq = "".join([{"T": "A", "A": "T"}[b] for b in minus_seq[::-1]])
     seq = make_seq(raw_seq, name="s1", moltype="dna")
-    db = GffAnnotationDb(data=[])
+    db = GffAnnotationDb()
     db.add_feature(
         seqid="s1",
         biotype="cds",
@@ -300,7 +300,7 @@ def test_gav2():
 
 
 def test_add_feature_with_parent():
-    db = GffAnnotationDb(data=[])
+    db = GffAnnotationDb()
     db.add_feature(
         seqid="s1",
         biotype="cds",
diff --git a/tests/test_core/test_features.py b/tests/test_core/test_features.py
index 96f78571b..826fc739e 100755
--- a/tests/test_core/test_features.py
+++ b/tests/test_core/test_features.py
@@ -5,7 +5,6 @@ import pytest
 from cogent3 import ASCII, DNA, make_aligned_seqs
 from cogent3.core.annotation import Feature, Variable
 from cogent3.core.annotation_db import GenbankAnnotationDb, GffAnnotationDb
-
 # Complete version of manipulating sequence annotations
 from cogent3.util.deserialise import deserialise_object
 
@@ -628,7 +627,7 @@ def test_copy_annotations():
     aln = make_aligned_seqs(
         data=[["x", "-AAAAAAAAA"], ["y", "TTTT--CCCT"]], array_align=False
     )
-    db = GffAnnotationDb(data=[])
+    db = GffAnnotationDb()
     db.add_feature(seqid="y", biotype="exon", name="A", spans=[(5, 8)])
     aln.copy_annotations(db)
     feat = list(aln.get_features(seqid="y", biotype="exon"))[0]