diff --git a/mhctools/base_predictor.py b/mhctools/base_predictor.py index cf96d60..4c581d3 100644 --- a/mhctools/base_predictor.py +++ b/mhctools/base_predictor.py @@ -11,6 +11,7 @@ # limitations under the License. import logging +import warnings from collections import defaultdict from typechecks import require_iterable_of @@ -207,6 +208,10 @@ def predict_peptides_dataframe(self, peptides): ``predictor_version``, ``kind``, ``value`` and used ``prediction_method_name`` instead of ``predictor_name`` — see #193. """ + warnings.warn( + "predict_peptides_dataframe is deprecated; use predict_dataframe()", + DeprecationWarning, + stacklevel=2) return self.predict_dataframe(peptides) def _check_peptide_lengths(self, peptide_lengths=None): diff --git a/mhctools/cli/args.py b/mhctools/cli/args.py index 0b78569..4255c92 100644 --- a/mhctools/cli/args.py +++ b/mhctools/cli/args.py @@ -96,9 +96,15 @@ def __getattr__(self, item): return getattr(self._resolve(), item) def __eq__(self, other): + if other is self: + return True if isinstance(other, _LazyPredictor): return (self._module_name, self._class_name) == ( other._module_name, other._class_name) + # Only classes can meaningfully equal a lazy-loaded class reference. + # Bail out without triggering the import for anything else. + if not isinstance(other, type): + return NotImplemented return self._resolve() is other def __hash__(self): diff --git a/mhctools/mhcflurry.py b/mhctools/mhcflurry.py index aee62c5..6583114 100644 --- a/mhctools/mhcflurry.py +++ b/mhctools/mhcflurry.py @@ -38,7 +38,7 @@ def _normalize_models_path(models_path): """ if models_path is None: return None - return os.path.realpath(os.path.abspath(os.path.expanduser(models_path))) + return os.path.realpath(os.path.expanduser(models_path)) class MHCflurry(BasePredictor): @@ -84,7 +84,7 @@ def __init__( cache_key = ("presentation", _normalize_models_path(models_path)) if cache_key not in _model_cache: if models_path: - logging.info( + logger.info( "Loading MHCflurry models from %s", models_path) _model_cache[cache_key] = \ Class1PresentationPredictor.load(models_path) @@ -260,7 +260,7 @@ def __init__( cache_key = ("affinity", _normalize_models_path(models_path)) if cache_key not in _model_cache: if models_path: - logging.info( + logger.info( "Loading MHCflurry models from %s", models_path) _model_cache[cache_key] = \ Class1AffinityPredictor.load(models_path) diff --git a/tests/test_dataframe_schema_parity.py b/tests/test_dataframe_schema_parity.py index 5319f0c..0c3157f 100644 --- a/tests/test_dataframe_schema_parity.py +++ b/tests/test_dataframe_schema_parity.py @@ -11,15 +11,27 @@ treat rows from either path uniformly. """ +import warnings + +import pytest + from mhctools import RandomBindingPredictor from mhctools.pred import COLUMNS +def _peptides_df(p, peptides): + # predict_peptides_dataframe emits DeprecationWarning; silence here so + # the fixture doesn't pollute every assertion. + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + return p.predict_peptides_dataframe(peptides) + + def test_peptides_and_proteins_dataframes_share_schema(): p = RandomBindingPredictor( alleles=["HLA-A*02:01"], default_peptide_lengths=[9], ) - df_peptides = p.predict_peptides_dataframe(["SIINFEKLA"]) + df_peptides = _peptides_df(p, ["SIINFEKLA"]) df_proteins = p.predict_proteins_dataframe({"src": "MASIINFEKLA"}) assert list(df_peptides.columns) == list(COLUMNS), ( @@ -35,7 +47,7 @@ def test_peptides_dataframe_has_predictor_identity_columns(): """Downstream (e.g. topiary CachedPredictor) needs a stable (predictor_name, predictor_version) identity on every row.""" p = RandomBindingPredictor(alleles=["HLA-A*02:01"], default_peptide_lengths=[9]) - df = p.predict_peptides_dataframe(["SIINFEKLA"]) + df = _peptides_df(p, ["SIINFEKLA"]) assert "predictor_name" in df.columns assert "predictor_version" in df.columns assert "kind" in df.columns @@ -44,3 +56,11 @@ def test_peptides_dataframe_has_predictor_identity_columns(): assert "prediction_method_name" not in df.columns # canonical name is populated (RandomBindingPredictor sets it) assert df["predictor_name"].iloc[0] != "" + + +def test_peptides_dataframe_emits_deprecation_warning(): + """Callers on the legacy path should get a runtime signal to migrate + to predict_dataframe().""" + p = RandomBindingPredictor(alleles=["HLA-A*02:01"], default_peptide_lengths=[9]) + with pytest.warns(DeprecationWarning, match="predict_peptides_dataframe"): + p.predict_peptides_dataframe(["SIINFEKLA"])