From 016f896a2663a92488729ff754966fb5ca539351 Mon Sep 17 00:00:00 2001 From: XanthosXanthopoulos Date: Tue, 13 Feb 2024 12:36:57 +0200 Subject: [PATCH 1/3] Add type checks to obsm, obsp, varm and varp early in ingestion --- apis/python/src/tiledbsoma/io/ingest.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/apis/python/src/tiledbsoma/io/ingest.py b/apis/python/src/tiledbsoma/io/ingest.py index e5f4ed6fa9..415b5db98a 100644 --- a/apis/python/src/tiledbsoma/io/ingest.py +++ b/apis/python/src/tiledbsoma/io/ingest.py @@ -420,6 +420,30 @@ def from_anndata( raise TypeError( "Second argument is not an AnnData object -- did you want from_h5ad?" ) + + for key in anndata.obsm.keys(): + if not isinstance(anndata.obsm[key], Matrix.__args__): + raise TypeError( + f"Obsm value at {key} in not of type {list(cl.__name__ for cl in Matrix.__args__)}" + ) + + for key in anndata.obsp.keys(): + if not isinstance(anndata.obsp[key], Matrix.__args__): + raise TypeError( + f"Obsp value at {key} in not of type {list(cl.__name__ for cl in Matrix.__args__)}" + ) + + for key in anndata.varm.keys(): + if not isinstance(anndata.varm[key], Matrix.__args__): + raise TypeError( + f"Varm value at {key} in not of type {list(cl.__name__ for cl in Matrix.__args__)}" + ) + + for key in anndata.varp.keys(): + if not isinstance(anndata.varp[key], Matrix.__args__): + raise TypeError( + f"Varp value at {key} in not of type {list(cl.__name__ for cl in Matrix.__args__)}" + ) # For single ingest (no append): # From 1bf36de4604d2318fdb1e740e9f4d5fe373d53d5 Mon Sep 17 00:00:00 2001 From: XanthosXanthopoulos Date: Tue, 13 Feb 2024 13:43:42 +0200 Subject: [PATCH 2/3] mypy error fix --- apis/python/src/tiledbsoma/io/ingest.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/apis/python/src/tiledbsoma/io/ingest.py b/apis/python/src/tiledbsoma/io/ingest.py index 415b5db98a..b6723fec35 100644 --- a/apis/python/src/tiledbsoma/io/ingest.py +++ b/apis/python/src/tiledbsoma/io/ingest.py @@ -39,6 +39,7 @@ from anndata._core import file_backing from anndata._core.sparse_dataset import SparseDataset from somacore.options import PlatformConfig +from typing_extensions import get_args from .. import ( Collection, @@ -420,29 +421,29 @@ def from_anndata( raise TypeError( "Second argument is not an AnnData object -- did you want from_h5ad?" ) - + for key in anndata.obsm.keys(): - if not isinstance(anndata.obsm[key], Matrix.__args__): + if not isinstance(anndata.obsm[key], get_args(Matrix)): raise TypeError( - f"Obsm value at {key} in not of type {list(cl.__name__ for cl in Matrix.__args__)}" + f"Obsm value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" ) - + for key in anndata.obsp.keys(): - if not isinstance(anndata.obsp[key], Matrix.__args__): + if not isinstance(anndata.obsp[key], get_args(Matrix)): raise TypeError( - f"Obsp value at {key} in not of type {list(cl.__name__ for cl in Matrix.__args__)}" + f"Obsp value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" ) - + for key in anndata.varm.keys(): - if not isinstance(anndata.varm[key], Matrix.__args__): + if not isinstance(anndata.varm[key], get_args(Matrix)): raise TypeError( - f"Varm value at {key} in not of type {list(cl.__name__ for cl in Matrix.__args__)}" + f"Varm value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" ) - + for key in anndata.varp.keys(): - if not isinstance(anndata.varp[key], Matrix.__args__): + if not isinstance(anndata.varp[key], get_args(Matrix)): raise TypeError( - f"Varp value at {key} in not of type {list(cl.__name__ for cl in Matrix.__args__)}" + f"Varp value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" ) # For single ingest (no append): From ac10e71fe4ee24c95f9e99540f3e7c9199202a69 Mon Sep 17 00:00:00 2001 From: XanthosXanthopoulos Date: Wed, 14 Feb 2024 01:21:05 +0200 Subject: [PATCH 3/3] Add unit test for type checks --- apis/python/src/tiledbsoma/io/ingest.py | 8 ++++---- apis/python/tests/test_basic_anndata_io.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apis/python/src/tiledbsoma/io/ingest.py b/apis/python/src/tiledbsoma/io/ingest.py index b6723fec35..7550d1d549 100644 --- a/apis/python/src/tiledbsoma/io/ingest.py +++ b/apis/python/src/tiledbsoma/io/ingest.py @@ -425,25 +425,25 @@ def from_anndata( for key in anndata.obsm.keys(): if not isinstance(anndata.obsm[key], get_args(Matrix)): raise TypeError( - f"Obsm value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" + f"obsm value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" ) for key in anndata.obsp.keys(): if not isinstance(anndata.obsp[key], get_args(Matrix)): raise TypeError( - f"Obsp value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" + f"obsp value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" ) for key in anndata.varm.keys(): if not isinstance(anndata.varm[key], get_args(Matrix)): raise TypeError( - f"Varm value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" + f"varm value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" ) for key in anndata.varp.keys(): if not isinstance(anndata.varp[key], get_args(Matrix)): raise TypeError( - f"Varp value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" + f"varp value at {key} in not of type {list(cl.__name__ for cl in get_args(Matrix))}" ) # For single ingest (no append): diff --git a/apis/python/tests/test_basic_anndata_io.py b/apis/python/tests/test_basic_anndata_io.py index 46ba266a78..4611194c89 100644 --- a/apis/python/tests/test_basic_anndata_io.py +++ b/apis/python/tests/test_basic_anndata_io.py @@ -1134,3 +1134,13 @@ def test_index_names_io(tmp_path, obs_index_name, var_index_name): assert bdata.var.index.name is None else: assert adata.var.index.name == bdata.var.index.name + +def test_obsm_data_type(adata): + tempdir = tempfile.TemporaryDirectory() + soma_path = tempdir.name + bdata = anndata.AnnData(X=adata.X, obs=adata.obs, var=adata.var, obsm={"testing": adata.obs}) + + with pytest.raises(TypeError): + tiledbsoma.io.from_anndata(soma_path, bdata, measurement_name="RNA") + + assert not any(Path(soma_path).iterdir())