diff --git a/apis/python/src/tiledbsoma/_dense_nd_array.py b/apis/python/src/tiledbsoma/_dense_nd_array.py index b89f25e666..9f18d7d8e9 100644 --- a/apis/python/src/tiledbsoma/_dense_nd_array.py +++ b/apis/python/src/tiledbsoma/_dense_nd_array.py @@ -22,7 +22,7 @@ from ._exception import SOMAError, map_exception_for_create from ._flags import DENSE_ARRAYS_CAN_HAVE_CURRENT_DOMAIN, NEW_SHAPE_FEATURE_FLAG_ENABLED from ._tdb_handles import DenseNDArrayWrapper -from ._types import OpenTimestamp, Slice +from ._types import OpenTimestamp, Slice, StatusAndReason from ._util import dense_indices_to_shape from .options._soma_tiledb_context import ( SOMATileDBContext, @@ -361,6 +361,22 @@ def resize(self, newshape: Sequence[Union[int, None]]) -> None: else: raise NotImplementedError("Not implemented for libtiledbsoma < 2.27.0") + def tiledbsoma_upgrade_shape( + self, newshape: Sequence[Union[int, None]], check_only: bool = False + ) -> StatusAndReason: + """Allows the array to have a resizeable shape as described in the TileDB-SOMA + 1.15 release notes. Raises an error if the new shape exceeds maxshape in + any dimension. Raises an error if the array already has a shape. + """ + if NEW_SHAPE_FEATURE_FLAG_ENABLED and DENSE_ARRAYS_CAN_HAVE_CURRENT_DOMAIN: + if check_only: + return self._handle.tiledbsoma_can_upgrade_shape(newshape) + else: + self._handle.tiledbsoma_upgrade_shape(newshape) + return (True, "") + else: + raise NotImplementedError("Not implemented for libtiledbsoma < 2.27.0") + @classmethod def _dim_capacity_and_extent( cls, diff --git a/apis/python/src/tiledbsoma/_tdb_handles.py b/apis/python/src/tiledbsoma/_tdb_handles.py index 915cfb67a2..9e160c79b0 100644 --- a/apis/python/src/tiledbsoma/_tdb_handles.py +++ b/apis/python/src/tiledbsoma/_tdb_handles.py @@ -658,6 +658,24 @@ def tiledbsoma_can_resize( else: raise NotImplementedError("Not implemented for libtiledbsoma < 2.27.0") + def tiledbsoma_upgrade_shape(self, newshape: Sequence[Union[int, None]]) -> None: + """Wrapper-class internals""" + if DENSE_ARRAYS_CAN_HAVE_CURRENT_DOMAIN: + self._handle.tiledbsoma_upgrade_shape(newshape) + else: + raise NotImplementedError("Not implemented for libtiledbsoma < 2.27.0") + + def tiledbsoma_can_upgrade_shape( + self, newshape: Sequence[Union[int, None]] + ) -> StatusAndReason: + """Wrapper-class internals""" + if DENSE_ARRAYS_CAN_HAVE_CURRENT_DOMAIN: + return cast( + StatusAndReason, self._handle.tiledbsoma_can_upgrade_shape(newshape) + ) + else: + raise NotImplementedError("Not implemented for libtiledbsoma < 2.27.0") + class SparseNDArrayWrapper(SOMAArrayWrapper[clib.SOMASparseNDArray]): """Wrapper around a Pybind11 SparseNDArrayWrapper handle.""" diff --git a/apis/python/tests/test_shape.py b/apis/python/tests/test_shape.py index 4777a4d6b0..13362da3f1 100644 --- a/apis/python/tests/test_shape.py +++ b/apis/python/tests/test_shape.py @@ -228,6 +228,18 @@ def test_dense_nd_array_basics(tmp_path): else: assert dnda.shape == (100, 200) + if ( + tiledbsoma._flags.DENSE_ARRAYS_CAN_HAVE_CURRENT_DOMAIN + and tiledbsoma._flags.NEW_SHAPE_FEATURE_FLAG_ENABLED + ): + with tiledbsoma.DenseNDArray.open(uri) as dnda: + ok, msg = dnda.tiledbsoma_upgrade_shape((600, 700), check_only=True) + assert not ok + assert ( + msg + == "tiledbsoma_can_upgrade_shape: array already has a shape: please use resize" + ) + @pytest.mark.parametrize( "soma_joinid_domain",