Repository: modernatx/seqlike

Issue:
fix codons_table bug
Adding entries to a codon table generated by `python_codon_tables.get_codons_table()` has the insidious effect of adding these entries to codon tables generated by subsequent calls to `get_codons_table()`.   For example:

```python
import python_codon_tables as pct

# generate a codon table; assertion passes
table1 = pct.get_codons_table("h_sapiens_9606")
assert ''.join(sorted(table1.keys())) == '*ACDEFGHIKLMNPQRSTVWY'

# let's add some new letters; assertion passes
table1["-"] = {"---": 1}
table1["X"] = {"NNN": 1}
assert ''.join(sorted(table1.keys())) == '*-ACDEFGHIKLMNPQRSTVWXY'

# now if we call get_codons_table again, these new letters are somehow included and the assertion will fail
table2 = pct.get_codons_table("h_sapiens_9606")
assert ''.join(sorted(table2.keys())) == '*ACDEFGHIKLMNPQRSTVWY'
```

Simply adding a copy operation to codon table objects fixes this bug.

Discussion:
ericmjl: Thank you, @ndousis, for the improvements here!

I am going to merge and cut a new patch release for you.

Patch:
diff --git a/seqlike/codon_tables.py b/seqlike/codon_tables.py
index 349b764..0849d4e 100644
--- a/seqlike/codon_tables.py
+++ b/seqlike/codon_tables.py
@@ -79,13 +79,13 @@ CODON_TABLE = {
 }
 
 # https://github.com/Edinburgh-Genome-Foundry/codon-usage-tables/blob/master/codon_usage_data/tables/h_sapiens_9606.csv
-human_codon_table = get_codons_table("h_sapiens_9606")
+human_codon_table = get_codons_table("h_sapiens_9606").copy()
 
 # https://github.com/Edinburgh-Genome-Foundry/codon-usage-tables/blob/master/codon_usage_data/tables/s_cerevisiae_4932.csv
-yeast_codon_table = get_codons_table("s_cerevisiae_4932")
+yeast_codon_table = get_codons_table("s_cerevisiae_4932").copy()
 
 # https://github.com/Edinburgh-Genome-Foundry/codon-usage-tables/blob/master/codon_usage_data/tables/e_coli_316407.csv
-ecoli_codon_table = get_codons_table("e_coli_316407")
+ecoli_codon_table = get_codons_table("e_coli_316407").copy()
 
 random_codon_table = {
     "*": {"TAA": 0.33, "TAG": 0.33, "TGA": 0.33},


Test patch:
diff --git a/tests/test_codon_tables.py b/tests/test_codon_tables.py
index d7c449d..2a78b85 100644
--- a/tests/test_codon_tables.py
+++ b/tests/test_codon_tables.py
@@ -1,5 +1,6 @@
 import pytest
 
+from python_codon_tables import get_codons_table
 from seqlike import aaSeqLike
 from seqlike.codon_tables import (
     codon_table_to_codon_map,
@@ -32,3 +33,11 @@ def test_codon_table_to_codon_map(letter):
     human_codon_map = codon_table_to_codon_map(sort_codon_table_by_frequency(human_codon_table))
     codon = aaSeqLike(letter).back_translate(codon_map=human_codon_map)
     assert sorted(human_codon_table[letter].items(), key=lambda x: x[1], reverse=True)[0][0] == str(codon)
+
+
+@pytest.mark.parametrize("codon_table_name", ["h_sapiens_9606", "s_cerevisiae_4932"])
+def test_codon_table(codon_table_name):
+    assert ''.join(sorted(human_codon_table.keys())) == '*-ACDEFGHIKLMNPQRSTVWXY'
+
+    codons_table = get_codons_table(codon_table_name)
+    assert ''.join(sorted(codons_table.keys())) == '*ACDEFGHIKLMNPQRSTVWY'
\ No newline at end of file