Skip to content

Commit

Permalink
Move all Python tests to same directory, Require KWs for `SOMADataFra…
Browse files Browse the repository at this point in the history
…me.open`
  • Loading branch information
nguyenv committed Jan 19, 2024
1 parent 19fcf84 commit 7c4b511
Show file tree
Hide file tree
Showing 12 changed files with 64 additions and 59 deletions.
7 changes: 0 additions & 7 deletions .github/workflows/python-ci-single.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,6 @@ jobs:
- name: Run libtiledbsoma unit tests
run: ctest --output-on-failure --test-dir build/libtiledbsoma -C Release --verbose

- name: Run pytests for C++
shell: bash
# Setting PYTHONPATH ensures the tests load the in-tree source code unde apis/python/src
# instead of copy we `pip install`ed to site-packages above. That's needed for the code
# coverage analysis to work.
run: PYTHONPATH=$(pwd)/apis/python/src python -m pytest --cov=apis/python/src --cov-report=xml libtiledbsoma/test -v --durations=20

- name: Run pytests for Python
shell: bash
# Setting PYTHONPATH ensures the tests load the in-tree source code unde apis/python/src
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ update:
.PHONY: test
test: data
ctest --test-dir build/libtiledbsoma -C Release --verbose --rerun-failed --output-on-failure
pytest apis/python/tests libtiledbsoma/test
pytest apis/python/tests

.PHONY: data
data:
Expand Down
28 changes: 11 additions & 17 deletions apis/python/src/tiledbsoma/_dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,12 @@ def read(
ts = (0, self._handle._handle.timestamp)

sr = clib.SOMADataFrame.open(
self._handle._handle.uri,
clib.OpenMode.read,
platform_config or {},
column_names or [],
_util.to_clib_result_order(result_order),
ts,
uri=self._handle._handle.uri,
mode=clib.OpenMode.read,
platform_config=platform_config or {},
column_names=column_names or [],
result_order=_util.to_clib_result_order(result_order),
timestamp=ts,
)

if value_filter is not None:
Expand Down Expand Up @@ -533,11 +533,6 @@ def _set_reader_coord(
# There's no way to specify "to infinity" for strings.
# We have to get the nonempty domain and use that as the end.
ned = self._handle.non_empty_domain()
if ned is None:
raise ValueError(
"Found empty nonempty domain when setting "
"string coordinates in _set_reader_coord"
)
_, stop = ned[dim_idx]
else:
stop = coord.stop
Expand Down Expand Up @@ -587,6 +582,7 @@ def _set_reader_coord_by_py_seq_or_np_array(

if _util.pa_types_is_string_or_bytes(dim.type):
sr.set_dim_points_string_or_bytes(dim.name, coord)
return True
elif pa.types.is_timestamp(dim.type):
if not isinstance(coord, (tuple, list, np.ndarray)):
raise ValueError(
Expand All @@ -597,15 +593,13 @@ def _set_reader_coord_by_py_seq_or_np_array(
for e in coord
]
sr.set_dim_points_int64(dim.name, icoord)
return True

# TODO: bool

else:
raise ValueError(
f"unhandled type {dim.dtype} for index column named {dim.name}"
)

return True
raise ValueError(
f"unhandled type {dim.dtype} for index column named {dim.name}"
)

def _set_reader_coord_by_numeric_slice(
self, sr: clib.SOMAArray, dim_idx: int, dim: pa.Field, coord: Slice[Any]
Expand Down
13 changes: 4 additions & 9 deletions apis/python/src/tiledbsoma/_tdb_handles.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
Type,
TypeVar,
Union,
cast,
)

import attrs
Expand Down Expand Up @@ -243,12 +242,9 @@ def _opener(
def schema(self) -> tiledb.ArraySchema:
return self._handle.schema

def non_empty_domain(self) -> Optional[Tuple[Tuple[object, object], ...]]:
def non_empty_domain(self) -> Tuple[Tuple[object, object], ...]:
try:
ned = self._handle.nonempty_domain()
if ned is None:
return None
return cast(Tuple[Tuple[object, object], ...], ned)
return self._handle.nonempty_domain() or ()
except tiledb.TileDBError as e:
raise SOMAError(e)

Expand Down Expand Up @@ -393,9 +389,8 @@ def _cast_domain(
def domain(self) -> Tuple[Tuple[object, object], ...]:
return self._cast_domain(self._handle.domain)

def non_empty_domain(self) -> Optional[Tuple[Tuple[object, object], ...]]:
result = self._cast_domain(self._handle.non_empty_domain)
return result or None
def non_empty_domain(self) -> Tuple[Tuple[object, object], ...]:
return self._cast_domain(self._handle.non_empty_domain) or ()

@property
def attr_names(self) -> Tuple[str, ...]:
Expand Down
5 changes: 2 additions & 3 deletions apis/python/src/tiledbsoma/_tiledb_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ def schema(self) -> pa.Schema:
return tiledb_schema_to_arrow(
self._tiledb_array_schema(), self.uri, self._ctx
)
else:
return self._tiledb_array_schema()
return self._tiledb_array_schema()

def non_empty_domain(self) -> Optional[Tuple[Tuple[Any, Any], ...]]:
def non_empty_domain(self) -> Tuple[Tuple[Any, Any], ...]:
"""
Retrieves the non-empty domain for each dimension, namely the smallest
and largest indices in each dimension for which the array/dataframe has
Expand Down
7 changes: 5 additions & 2 deletions apis/python/src/tiledbsoma/io/ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2251,7 +2251,7 @@ def _coo_to_table(

def _chunk_is_contained_in(
chunk_bounds: Sequence[Tuple[int, int]],
storage_nonempty_domain: Optional[Sequence[Tuple[Optional[int], Optional[int]]]],
storage_nonempty_domain: Sequence[Tuple[Optional[int], Optional[int]]],
) -> bool:
"""
Determines if a dim range is included within the array's non-empty domain. Ranges are inclusive
Expand All @@ -2269,7 +2269,7 @@ def _chunk_is_contained_in(
user that they declare they are retrying the exact same input file -- and we do our best to
fulfill their ask by checking the dimension being strided on.
"""
if storage_nonempty_domain is None:
if len(storage_nonempty_domain) == 0:
return False

if len(chunk_bounds) != len(storage_nonempty_domain):
Expand All @@ -2288,6 +2288,9 @@ def _chunk_is_contained_in_axis(
stride_axis: int,
) -> bool:
"""Helper function for ``_chunk_is_contained_in``."""
if len(storage_nonempty_domain) == 0:
return False

storage_lo, storage_hi = storage_nonempty_domain[stride_axis]
if storage_lo is None or storage_hi is None:
# E.g. an array has had its schema created but no data written yet
Expand Down
18 changes: 17 additions & 1 deletion apis/python/src/tiledbsoma/soma_dataframe.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,23 @@ using namespace tiledbsoma;
void load_soma_dataframe(py::module &m) {
py::class_<SOMADataFrame, SOMAObject>(m, "SOMADataFrame")

.def_static("open", py::overload_cast<std::string_view, OpenMode, std::map<std::string, std::string>, std::vector<std::string>, ResultOrder, std::optional<std::pair<uint64_t, uint64_t>>>(&SOMADataFrame::open))
.def_static(
"open",
py::overload_cast<
std::string_view,
OpenMode,
std::map<std::string, std::string>,
std::vector<std::string>,
ResultOrder,
std::optional<std::pair<uint64_t, uint64_t>>>(&SOMADataFrame::open),
"uri"_a,
"mode"_a,
py::kw_only(),
"platform_config"_a = py::dict(),
"column_names"_a = py::none(),
"result_order"_a = ResultOrder::automatic,
"timestamp"_a = py::none())

.def_static("exists", &SOMADataFrame::exists)
.def("reopen", py::overload_cast<OpenMode, std::optional<std::pair<uint64_t, uint64_t>>>(&SOMADataFrame::open))
.def("close", &SOMADataFrame::close)
Expand Down
4 changes: 4 additions & 0 deletions apis/python/tests/test_dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -1356,3 +1356,7 @@ def test_enum_extend_past_numerical_limit(tmp_path):
with pytest.raises(ValueError):
with soma.open(uri, mode="w") as A:
A.write(tbl)


def test_write_str_empty_ned(tmp_path):
tmp_path.as_posix()
34 changes: 17 additions & 17 deletions apis/python/tests/test_experiment_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -628,23 +628,23 @@ def test_experiment_query_to_anndata_obsm_varm(soma_experiment):
)
def test_experiment_query_to_anndata_obsp_varp(soma_experiment):
with soma_experiment.axis_query("RNA") as query:
query.to_anndata("raw", obsp_layers=["foo"], varp_layers=["bar"])
# assert set(ad.obsp.keys()) == {"foo"}
# obsp = ad.obsp["foo"]
# assert isinstance(obsp, np.ndarray)
# assert obsp.shape == (query.n_obs, query.n_obs)

# assert np.array_equal(
# query.obsp("foo").coos().concat().to_scipy().todense(), obsp
# )

# assert set(ad.varp.keys()) == {"bar"}
# varp = ad.varp["bar"]
# assert isinstance(varp, np.ndarray)
# assert varp.shape == (query.n_vars, query.n_vars)
# assert np.array_equal(
# query.varp("bar").coos().concat().to_scipy().todense(), varp
# )
ad = query.to_anndata("raw", obsp_layers=["foo"], varp_layers=["bar"])
assert set(ad.obsp.keys()) == {"foo"}
obsp = ad.obsp["foo"]
assert isinstance(obsp, np.ndarray)
assert obsp.shape == (query.n_obs, query.n_obs)

assert np.array_equal(
query.obsp("foo").coos().concat().to_scipy().todense(), obsp
)

assert set(ad.varp.keys()) == {"bar"}
varp = ad.varp["bar"]
assert isinstance(varp, np.ndarray)
assert varp.shape == (query.n_vars, query.n_vars)
assert np.array_equal(
query.varp("bar").coos().concat().to_scipy().todense(), varp
)


def test_axis_query():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
VERBOSE = False

TEST_DIR = os.path.dirname(__file__)
SOMA_URI = f"{TEST_DIR}/../../test/soco/pbmc3k_processed"
SOMA_URI = f"{TEST_DIR}/../../../test/soco/pbmc3k_processed"

if VERBOSE:
clib.config_logging("debug")
Expand Down Expand Up @@ -228,6 +228,7 @@ def test_eval_error_conditions(malformed_condition):
with pytest.raises(SOMAError):
# test function directly for codecov
qc.init_query_condition(schema, [])
qc.init_query_condition(schema, ["bad_query_attr"])


if __name__ == "__main__":
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
VERBOSE = False

TEST_DIR = os.path.dirname(__file__)
SOMA_URI = f"{TEST_DIR}/../../test/soco/pbmc3k_processed"
SOMA_URI = f"{TEST_DIR}/../../../test/soco/pbmc3k_processed"

if VERBOSE:
clib.config_logging("debug")
Expand Down

0 comments on commit 7c4b511

Please sign in to comment.