nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: cogent3/cogent3
Pull request #1164 (2022-10-06 07:57:56)

MAINT: fixed consistency of state order in Alphabet.get_word_alphabet
[CHANGED] previous implementation produced a strange state order that meant
    a k-mer inferred from extrapolation of bases indices into a 1D
    index did not match those produced by this method. Code is simplified,
    uses the itertools.product and addresses the issue.


Patch:
diff --git a/src/cogent3/core/alphabet.py b/src/cogent3/core/alphabet.py
index 340962b48..2fca6ec70 100644
--- a/src/cogent3/core/alphabet.py
+++ b/src/cogent3/core/alphabet.py
@@ -547,14 +547,9 @@ class Alphabet(Enumeration):
         Note that the result is not a JointEnumeration object, and cannot
         unpack its indices. However, the items in the result _are_ all strings.
         """
-        crossproduct = [""]
-        for a in range(word_length):
-            n = []
-            for c in crossproduct:
-                for m in self:
-                    n.append(m + c)
-            crossproduct = n
-        return Alphabet(crossproduct, moltype=self.moltype)
+        states = (list(self),) * word_length
+        cross_product = ["".join(combo) for combo in product(*states)]
+        return Alphabet(cross_product, moltype=self.moltype)
 
     def from_seq_to_array(self, sequence):
         """Returns an array of indices corresponding to items in sequence.


Test patch:
diff --git a/tests/test_core/test_alphabet.py b/tests/test_core/test_alphabet.py
index 396ca9b9b..26d90772b 100644
--- a/tests/test_core/test_alphabet.py
+++ b/tests/test_core/test_alphabet.py
@@ -7,6 +7,7 @@ import pickle
 
 from unittest import TestCase, main
 
+from numpy import unravel_index
 from numpy.testing import assert_equal
 
 from cogent3.core.alphabet import (
@@ -240,6 +241,14 @@ class CharAlphabetTests(TestCase):
         self.assertIsInstance(got, type(r))
         self.assertEqual(got.get_word_alphabet(2), wa)
 
+    def test_word_alphabet_order(self):
+        bases = "TCAG"
+        r = CharAlphabet(bases)
+        indices = [unravel_index(i, shape=(4, 4, 4)) for i in range(64)]
+        expect = tuple("".join([bases[b] for b in coord]) for coord in indices)
+        got = tuple(r.get_word_alphabet(3))
+        assert got == expect
+
     def test_from_string(self):
         """CharAlphabet from_string should return correct array"""
         r = CharAlphabet("UCAG")
Repository: cogent3/cogent3
Pull request #1178 (2022-10-25 07:14:48)

API: apply_to changed get_source argument name to id_from_source


Patch:
diff --git a/src/cogent3/app/composable.py b/src/cogent3/app/composable.py
index c87ea9590..d2c1e2148 100644
--- a/src/cogent3/app/composable.py
+++ b/src/cogent3/app/composable.py
@@ -1311,7 +1311,7 @@ def is_composable(obj):
 def _apply_to(
     self,
     dstore,
-    get_data_source: callable = get_data_source,
+    id_from_source: callable = get_data_source,
     parallel=False,
     par_kw=None,
     logger=None,
@@ -1325,6 +1325,9 @@ def _apply_to(
     dstore
         a path, list of paths, or DataStore to which the process will be
         applied.
+    id_from_source : callable
+        makes the unique identifier from elements of dstore that will be
+        used for writing results
     parallel : bool
         run in parallel, according to arguments in par_kwargs. If True,
         the last step of the composable function serves as the master
@@ -1361,7 +1364,7 @@ def _apply_to(
     # todo this should fail if somebody provides data that cannot produce a unique_id
     inputs = {}
     for m in dstore:
-        input_id = Path(m if isinstance(m, DataStoreMember) else get_data_source(m))
+        input_id = Path(m if isinstance(m, DataStoreMember) else id_from_source(m))
         suffixes = input_id.suffixes
         input_id = input_id.name.replace("".join(suffixes), "")
         if input_id in inputs:
@@ -1380,7 +1383,7 @@ def _apply_to(
     inputs = _proxy_input(dstore)
     for result in self.as_completed(inputs, parallel=parallel, par_kw=par_kw):
         member = self.main(
-            data=result.obj, identifier=get_data_source(result.source)
+            data=result.obj, identifier=id_from_source(result.source)
         )  # writers must return DataMember
         md5 = member.md5
         logger.log_message(str(member), label="output")


Test patch:
diff --git a/tests/test_app/test_composable.py b/tests/test_app/test_composable.py
index d05d682d9..ace7c01c3 100644
--- a/tests/test_app/test_composable.py
+++ b/tests/test_app/test_composable.py
@@ -231,7 +231,7 @@ def test_apply_to_strings(tmp_dir, klass):
     )
     process = reader + min_length + writer
     # create paths as strings
-    _ = process.apply_to(dstore, get_data_source=get_data_source)
+    _ = process.apply_to(dstore, id_from_source=get_data_source)
     assert len(process.data_store.logs) == 1