From ae74ecde526be4b633d0541d9accaa0afb809d8d Mon Sep 17 00:00:00 2001 From: Stephan Breimann Date: Sat, 4 Jul 2026 23:16:54 +0200 Subject: [PATCH] fix(seq_preproc): reject an over-large sliding window instead of returning [] check_match_slide_start_slide_stop_window_size had a typo (slide_stop - slide_stop, always 0) that made the guard dead, so requesting a window larger than the explicit slide span silently returned an empty list. It now raises a clear ValueError when window_size > slide_stop - slide_start + 1 (the point past which no window fits). The two hypothesis tests that encoded the old silent-empty behavior are updated to the new contract, plus a dedicated over-large-window test. Co-Authored-By: Claude Opus 4.8 --- aaanalysis/data_handling/_seq_preproc.py | 6 ++-- .../test_sp_get_sliding_aa_window.py | 30 +++++++++++++------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/aaanalysis/data_handling/_seq_preproc.py b/aaanalysis/data_handling/_seq_preproc.py index ec26038a..d2fcbcd0 100644 --- a/aaanalysis/data_handling/_seq_preproc.py +++ b/aaanalysis/data_handling/_seq_preproc.py @@ -89,9 +89,9 @@ def check_match_slide_start_slide_stop(slide_start=None, slide_stop=None) -> Non def check_match_slide_start_slide_stop_window_size(slide_start=None, slide_stop=None, window_size=None) -> None: """Check if one is given""" if slide_stop is not None: - min_window_size = slide_stop - slide_stop - if window_size < min_window_size: - raise ValueError(f"'window_size' ('{window_size}') should be smaller then the distance ({min_window_size})" + max_window_size = slide_stop - slide_start + 1 + if window_size > max_window_size: + raise ValueError(f"'window_size' ('{window_size}') should be <= the distance ({max_window_size})" f" between 'slide_start' ('{slide_start}') and 'slide_stop' ({slide_stop}).") diff --git a/tests/unit/data_handling_tests/test_sp_get_sliding_aa_window.py b/tests/unit/data_handling_tests/test_sp_get_sliding_aa_window.py index 837adc8d..cc325d63 100644 --- a/tests/unit/data_handling_tests/test_sp_get_sliding_aa_window.py +++ b/tests/unit/data_handling_tests/test_sp_get_sliding_aa_window.py @@ -48,7 +48,8 @@ def test_slide_start_invalid(self): sp.get_sliding_aa_window(seq="ACDEFGHIKLMNPQRSTVWY", slide_start=100, accept_gap=False) @settings(max_examples=10, deadline=None) - @given(slide_stop=st.integers(min_value=1, max_value=50)) + # window_size defaults to 5, so a valid span needs slide_stop >= 4 (slide_start defaults to 0) + @given(slide_stop=st.integers(min_value=4, max_value=50)) def test_slide_stop_valid(self, slide_stop): """Test a valid 'slide_stop' parameter.""" sp = aa.SequencePreprocessor() @@ -56,6 +57,15 @@ def test_slide_stop_valid(self, slide_stop): assert isinstance(windows, list) assert all(isinstance(window, str) for window in windows) + def test_window_larger_than_span_raises(self): + """An explicit slide window larger than the slide span is rejected.""" + sp = aa.SequencePreprocessor() + with pytest.raises(ValueError): + sp.get_sliding_aa_window(seq="ACDEFGHIKLMNPQRSTVWY", slide_start=0, slide_stop=2, window_size=100) + # a window that exactly fits the span (span + 1) is accepted + windows = sp.get_sliding_aa_window(seq="ACDEFGHIKLMNPQRSTVWY", slide_start=0, slide_stop=4, window_size=5) + assert isinstance(windows, list) and len(windows) >= 1 + def test_slide_stop_invalid(self): """Test an invalid 'slide_stop' parameter.""" sp = aa.SequencePreprocessor() @@ -144,14 +154,16 @@ def test_valid_combination(self, seq, slide_start, slide_stop, window_size, inde """Test valid combinations of parameters.""" sp = aa.SequencePreprocessor() if slide_start < slide_stop: - windows = sp.get_sliding_aa_window(seq=seq, - slide_start=slide_start, - slide_stop=slide_stop, - window_size=window_size, - index1=index1, - gap=gap) - assert isinstance(windows, list) - assert all(isinstance(window, str) for window in windows) + kwargs = dict(seq=seq, slide_start=slide_start, slide_stop=slide_stop, + window_size=window_size, index1=index1, gap=gap) + if window_size <= slide_stop - slide_start + 1: + windows = sp.get_sliding_aa_window(**kwargs) + assert isinstance(windows, list) + assert all(isinstance(window, str) for window in windows) + else: + # a window larger than the slide span is now rejected + with pytest.raises(ValueError): + sp.get_sliding_aa_window(**kwargs) @settings(max_examples=10, deadline=None) @given(