Repository: cogent3/cogent3
Pull request #1582 (2023-09-21 05:23:26)

ENH: fasta parser handles internal white-space in sequence blocks


Patch:
diff --git a/changelog.d/20230921_151053_Gavin.Huttley.md b/changelog.d/20230921_151053_Gavin.Huttley.md
new file mode 100644
index 000000000..4fa939a6f
--- /dev/null
+++ b/changelog.d/20230921_151053_Gavin.Huttley.md
@@ -0,0 +1,41 @@
+<!--
+A new scriv changelog fragment.
+
+Uncomment the section that is right (remove the HTML comment wrapper).
+-->
+
+<!--
+### Contributors
+
+- A bullet item for the Contributors category.
+
+-->
+### ENH
+
+- MinimalFastaParser now removes internal spaces
+  in sequence blocks
+
+<!--
+### BUG
+
+- A bullet item for the BUG category.
+
+-->
+<!--
+### DOC
+
+- A bullet item for the DOC category.
+
+-->
+<!--
+### Deprecations
+
+- A bullet item for the Deprecations category.
+
+-->
+<!--
+### Discontinued
+
+- A bullet item for the Discontinued category.
+
+-->
diff --git a/src/cogent3/parse/fasta.py b/src/cogent3/parse/fasta.py
index ae910dbf1..255228804 100644
--- a/src/cogent3/parse/fasta.py
+++ b/src/cogent3/parse/fasta.py
@@ -14,9 +14,9 @@ from cogent3.core.moltype import ASCII, BYTES
 from cogent3.parse.record import RecordError
 from cogent3.parse.record_finder import LabeledRecordFinder
 from cogent3.util.io import open_
-from cogent3.util.warning import deprecated_args
 
 
+_white_space = re.compile(r"\s+")
 strip = str.strip
 
 Sequence = BYTES.make_seq
@@ -75,7 +75,7 @@ def _faster_parser(
 
         if line[0] in label_char:
             if seq:
-                yield label_to_name(label or ""), "".join(seq)
+                yield label_to_name(label or ""), _white_space.sub("", "".join(seq))
 
             label = line[1:].strip()
             seq = []
@@ -83,7 +83,7 @@ def _faster_parser(
             seq.append(line.strip())
 
     if seq:
-        yield label_to_name(label or ""), "".join(seq)
+        yield label_to_name(label or ""), _white_space.sub("", "".join(seq))
 
 
 def _strict_parser(
@@ -100,7 +100,7 @@ def _strict_parser(
             if label is not None:
                 if not seq:
                     raise RecordError(f"{label} has no data")
-                yield label_to_name(label), "".join(seq)
+                yield label_to_name(label), _white_space.sub("", "".join(seq))
             elif seq:
                 raise RecordError("missing a label")
 
@@ -114,7 +114,7 @@ def _strict_parser(
     if label is None:
         raise RecordError("missing a label")
 
-    yield label_to_name(label), "".join(seq)
+    yield label_to_name(label), _white_space.sub("", "".join(seq))
 
 
 def MinimalFastaParser(


Test patch:
diff --git a/tests/test_parse/test_fasta.py b/tests/test_parse/test_fasta.py
index faf5580e6..a83af8e70 100644
--- a/tests/test_parse/test_fasta.py
+++ b/tests/test_parse/test_fasta.py
@@ -424,3 +424,11 @@ def test_seq_startswith_gt_bracket_fail():
     oneseq_w_gt = ">abc\n>CAG\n".split("\n")
     with pytest.raises(RecordError):
         list(MinimalFastaParser(oneseq_w_gt))
+
+
+@pytest.mark.parametrize("sep", (" ", "\t"))
+@pytest.mark.parametrize("strict", (False, True))
+def test_fasta_with_spaces(strict, sep):
+    data = [">A", sep.join(("gaaaa", "tgatt")), ">B", sep.join(("tttga", "gcagg"))]
+    got = dict(MinimalFastaParser(data, strict=strict))
+    assert got == {"A": "gaaaatgatt", "B": "tttgagcagg"}