From 412f3c3f4913bc4669f2afae4c7bca6b3fbc9721 Mon Sep 17 00:00:00 2001 From: mschwoerer <82171591+mschwoer@users.noreply.github.com> Date: Tue, 1 Sep 2026 09:07:02 +0200 Subject: [PATCH 1/2] fix xxhash 4 string hashing, skip numpy-2-incompatible pytables tests --- # Conversation that produced these changes --- ## User prompt "find out the various reasons why https://github.com/MannLabs/alphabase/actions/runs/33447321676/ jobs failed" "fix 1., deactivate the failing test in 2. with a succint comment on the root cause" ## Clarifying round 1 Q: How should the pytables tests in tests/integration/test_pg_readers.py be deactivated? The failure only occurs when pytables is importable but ABI-broken (tables 3.9.2 + numpy 2.0.2 on py3.9); the stable jobs pass. - Skip only when import fails (Recommended) - Unconditional skip <-- chosen Co-Authored-By: Claude Opus 5 (1M context) --- alphabase/peptide/precursor.py | 17 +++++++++++------ tests/integration/test_pg_readers.py | 6 ++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/alphabase/peptide/precursor.py b/alphabase/peptide/precursor.py index 82dad36b..ce3684cf 100644 --- a/alphabase/peptide/precursor.py +++ b/alphabase/peptide/precursor.py @@ -15,6 +15,11 @@ from alphabase.peptide.mass_calc import calc_peptide_masses_for_same_len_seqs +def _xxh64_str_intdigest(text: str, *, seed: int) -> int: + """xxhash>=4 no longer encodes strings implicitly; utf-8 keeps hash values identical to xxhash<4.""" + return xxh64_intdigest(text.encode(), seed=seed) + + def refine_precursor_df( df: pd.DataFrame, drop_frag_idx=False, @@ -178,9 +183,9 @@ def get_mod_seq_hash( """ return np.array( [ - xxh64_intdigest(sequence, seed=seed), - xxh64_intdigest(mods, seed=seed), - xxh64_intdigest(mod_sites, seed=seed), + _xxh64_str_intdigest(sequence, seed=seed), + _xxh64_str_intdigest(mods, seed=seed), + _xxh64_str_intdigest(mod_sites, seed=seed), ], dtype=np.uint64, ).sum() # use np.sum to prevent overflow @@ -233,15 +238,15 @@ def get_mod_seq_charge_hash( def hash_mod_seq_df(precursor_df: pd.DataFrame, *, seed=0): """Internal function""" hash_vals = precursor_df.sequence.apply( - lambda x: xxh64_intdigest(x, seed=seed) + lambda x: _xxh64_str_intdigest(x, seed=seed) ).to_numpy(copy=True, dtype=np.uint64) hash_vals += ( - precursor_df.mods.apply(lambda x: xxh64_intdigest(x, seed=seed)) + precursor_df.mods.apply(lambda x: _xxh64_str_intdigest(x, seed=seed)) .astype(np.uint64) .values ) hash_vals += ( - precursor_df.mod_sites.apply(lambda x: xxh64_intdigest(x, seed=seed)) + precursor_df.mod_sites.apply(lambda x: _xxh64_str_intdigest(x, seed=seed)) .astype(np.uint64) .values ) diff --git a/tests/integration/test_pg_readers.py b/tests/integration/test_pg_readers.py index fdb8d989..16aa718b 100644 --- a/tests/integration/test_pg_readers.py +++ b/tests/integration/test_pg_readers.py @@ -53,6 +53,9 @@ def test_import_csv_file_equivalent( pd.testing.assert_frame_equal(result_df, reference) + @pytest.mark.skip( + reason="tables 3.9.2 (last release supporting py3.9) is built against numpy<2 and raises a dtype-size ValueError on import with numpy>=2" + ) @pytest.mark.optional_pytables_dependency def test_import_hdf_file_equivalent( self, example_alphapept_hdf: tuple[str, pd.DataFrame] @@ -108,6 +111,9 @@ def test_import_csv_file( PGCols.DECOY_INDICATOR, ] + @pytest.mark.skip( + reason="tables 3.9.2 (last release supporting py3.9) is built against numpy<2 and raises a dtype-size ValueError on import with numpy>=2" + ) @pytest.mark.optional_pytables_dependency @pytest.mark.parametrize( ("measurement_regex", "expected_shape", "expected_colums"), From 00d0a3e4ebaeabf567dcfc7ba92facf09fde8e3e Mon Sep 17 00:00:00 2001 From: mschwoerer <82171591+mschwoer@users.noreply.github.com> Date: Tue, 1 Sep 2026 12:01:46 +0200 Subject: [PATCH 2/2] skip pytables tests only on the numpy/tables ABI mismatch --- # Conversation that produced these changes --- ## User prompt "skip the test only for python 3.9" "the word" Co-Authored-By: Claude Opus 5 (1M context) --- tests/integration/conftest.py | 16 ++++++++++++++++ tests/integration/test_pg_readers.py | 8 ++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 4d5180fb..f61f73a2 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -2,22 +2,38 @@ import importlib.util import os +from importlib.metadata import version from pathlib import Path +import numpy as np import pandas as pd import pytest +from packaging.version import Version from alphabase.tools.data_downloader import DataShareDownloader TABLES_PACKAGE_UNAVAILABLE = importlib.util.find_spec("tables") is None NUMBA_UNAVAILABLE = importlib.util.find_spec("numba") is None +FIRST_NUMPY2_COMPATIBLE_TABLES_VERSION = Version("3.10") +FIRST_ABI_BREAKING_NUMPY_VERSION = Version("2.0") + +PYTABLES_NUMPY_ABI_BROKEN = not TABLES_PACKAGE_UNAVAILABLE and ( + Version(version("tables")) < FIRST_NUMPY2_COMPATIBLE_TABLES_VERSION + and Version(np.__version__) >= FIRST_ABI_BREAKING_NUMPY_VERSION +) + pytest.mark.optional_pytables_dependency = pytest.mark.skipif( TABLES_PACKAGE_UNAVAILABLE, reason="pytables package not installed. Install with `pip install alphabase[hdf]`", ) +pytest.mark.broken_pytables_numpy_abi = pytest.mark.skipif( + PYTABLES_NUMPY_ABI_BROKEN, + reason="tables<3.10 is built against numpy<2 and raises a dtype-size ValueError on import with numpy>=2", +) + pytest.mark.requires_numba = pytest.mark.skipif( NUMBA_UNAVAILABLE, reason="numba package not installed", diff --git a/tests/integration/test_pg_readers.py b/tests/integration/test_pg_readers.py index 16aa718b..ea6451e5 100644 --- a/tests/integration/test_pg_readers.py +++ b/tests/integration/test_pg_readers.py @@ -53,9 +53,7 @@ def test_import_csv_file_equivalent( pd.testing.assert_frame_equal(result_df, reference) - @pytest.mark.skip( - reason="tables 3.9.2 (last release supporting py3.9) is built against numpy<2 and raises a dtype-size ValueError on import with numpy>=2" - ) + @pytest.mark.broken_pytables_numpy_abi @pytest.mark.optional_pytables_dependency def test_import_hdf_file_equivalent( self, example_alphapept_hdf: tuple[str, pd.DataFrame] @@ -111,9 +109,7 @@ def test_import_csv_file( PGCols.DECOY_INDICATOR, ] - @pytest.mark.skip( - reason="tables 3.9.2 (last release supporting py3.9) is built against numpy<2 and raises a dtype-size ValueError on import with numpy>=2" - ) + @pytest.mark.broken_pytables_numpy_abi @pytest.mark.optional_pytables_dependency @pytest.mark.parametrize( ("measurement_regex", "expected_shape", "expected_colums"),