Repository: TileDB-Inc/TileDB-Py
Pull request #2050 (2024-08-23 08:52:41)

Remove deprecations
This PR removes some easy-to-delete deprecations. They come from either the TileDB-Py version or the Python version.


Patch:
diff --git a/pyproject.toml b/pyproject.toml
index 254f9b00..ae25be63 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -62,6 +62,7 @@ test = [
     "psutil",
     "pyarrow",
     "pandas",
+    "dask[distributed]",
 ]
 
 [project.urls]
diff --git a/tiledb/__init__.py b/tiledb/__init__.py
index 8b430cc4..8ba220bc 100644
--- a/tiledb/__init__.py
+++ b/tiledb/__init__.py
@@ -65,7 +65,6 @@ from .filter import (
 from .fragment import (
     FragmentInfo,
     FragmentInfoList,
-    FragmentsInfo,
     copy_fragments_to_existing_array,
     create_array_from_fragments,
 )
diff --git a/tiledb/dataframe_.py b/tiledb/dataframe_.py
index 9543d91a..489bb10f 100644
--- a/tiledb/dataframe_.py
+++ b/tiledb/dataframe_.py
@@ -420,7 +420,9 @@ def _sparse_from_dtypes(dtypes, sparse=None):
     return sparse if sparse is not None else False
 
 
-def create_dims(df, index_dims, tile=None, full_domain=False, filters=None):
+def create_dims(
+    df, index_dims, column_infos, tile=None, full_domain=False, filters=None
+):
     check_dataframe_deps()
     import pandas as pd
 
@@ -445,7 +447,10 @@ def create_dims(df, index_dims, tile=None, full_domain=False, filters=None):
         else:
             raise ValueError(f"Unknown column or index named {name!r}")
 
-        dtype = ColumnInfo.from_values(values).dtype
+        if name in column_infos:
+            dtype = column_infos[name].dtype
+        else:
+            dtype = ColumnInfo.from_values(values).dtype
         internal_dtype = dtype
 
         if name == "__tiledb_rows" and isinstance(index, pd.RangeIndex):
@@ -659,6 +664,7 @@ def _create_array(uri, df, sparse, full_domain, index_dims, column_infos, tiledb
     dims, dim_metadata = create_dims(
         df,
         index_dims,
+        column_infos,
         full_domain=full_domain,
         tile=tiledb_args.get("tile"),
         filters=tiledb_args.get("dim_filters", True),
diff --git a/tiledb/filestore.py b/tiledb/filestore.py
index ced85614..ffe0de76 100644
--- a/tiledb/filestore.py
+++ b/tiledb/filestore.py
@@ -142,29 +142,6 @@ class Filestore:
 
         lt.Filestore._uri_export(ctx, filestore_array_uri, file_uri)
 
-    def uri_import(self, file_uri: str, mime_type: str = "AUTODETECT") -> None:
-        warnings.warn(
-            "Filestore.uri_import is deprecated; please use Filestore.copy_from",
-            DeprecationWarning,
-        )
-
-        if not isinstance(file_uri, str):
-            raise TypeError(
-                f"Unexpected file_uri type '{type(file_uri)}': expected str"
-            )
-
-        if not isinstance(mime_type, str):
-            raise TypeError(
-                f"Unexpected mime_type type '{type(mime_type)}': expected str"
-            )
-
-        lt.Filestore._uri_import(
-            self._ctx,
-            self._filestore_uri,
-            file_uri,
-            lt.Filestore._mime_type_from_str(mime_type),
-        )
-
     def __len__(self) -> int:
         """
         :rtype: int
diff --git a/tiledb/fragment.py b/tiledb/fragment.py
index db9ae0cd..04be4021 100644
--- a/tiledb/fragment.py
+++ b/tiledb/fragment.py
@@ -131,38 +131,6 @@ class FragmentInfoList:
         if libtiledb_version() >= (2, 5, 0):
             self.array_schema_name = fi.get_array_schema_name()
 
-    @property
-    def non_empty_domain(self):
-        raise tiledb.TileDBError(
-            "FragmentInfoList.non_empty_domain is deprecated; "
-            "you must use FragmentInfoList.nonempty_domain",
-            "This message will be removed in 0.21.0.",
-        )
-
-    @property
-    def to_vacuum_num(self):
-        raise tiledb.TileDBError(
-            "FragmentInfoList.to_vacuum_num is deprecated; "
-            "you must use len(FragmentInfoList.to_vacuum)",
-            "This message will be removed in 0.21.0.",
-        )
-
-    @property
-    def to_vacuum_uri(self):
-        raise tiledb.TileDBError(
-            "FragmentInfoList.to_vacuum_uri is deprecated; "
-            "you must use FragmentInfoList.to_vacuum",
-            "This message will be removed in 0.21.0.",
-        )
-
-    @property
-    def dense(self):
-        raise tiledb.TileDBError(
-            "FragmentInfoList.dense is deprecated; "
-            "you must use FragmentInfoList.sparse",
-            "This message will be removed in 0.21.0.",
-        )
-
     def __getattr__(self, name):
         if name == "mbrs":
             raise AttributeError(
@@ -297,50 +265,6 @@ class FragmentInfo:
             )
         return self.__getattribute__(name)
 
-    @property
-    def non_empty_domain(self):
-        raise tiledb.TileDBError(
-            "FragmentInfo.non_empty_domain is deprecated; "
-            "you must use FragmentInfo.nonempty_domain. ",
-            "This message will be removed in 0.21.0.",
-        )
-
-    @property
-    def to_vacuum_num(self):
-        raise tiledb.TileDBError(
-            "FragmentInfo.to_vacuum_num is deprecated; "
-            "you must use len(FragmentInfoList.to_vacuum).",
-            "This message will be removed in 0.21.0.",
-        )
-
-    @property
-    def to_vacuum_uri(self):
-        raise tiledb.TileDBError(
-            "FragmentInfo.to_vacuum_uri is deprecated; "
-            "you must use FragmentInfoList.to_vacuum.",
-            "This message will be removed in 0.21.0.",
-        )
-
-    @property
-    def dense(self):
-        raise tiledb.TileDBError(
-            "FragmentInfo.dense is deprecated; you must use FragmentInfo.sparse",
-            "This message will be removed in 0.21.0.",
-        )
-
-
-def FragmentsInfo(array_uri, ctx=None):
-    """
-    Deprecated in 0.8.8.
-
-    Renamed to FragmentInfoList to make name more distinguishable from FragmentInfo.
-    """
-
-    raise tiledb.TileDBError(
-        "FragmentsInfo is deprecated; you must use FragmentInfoList. "
-        "This message will be removed in 0.21.0.",
-    )
-
 
 def create_array_from_fragments(
     src_uri,
diff --git a/tiledb/libtiledb.pyx b/tiledb/libtiledb.pyx
index 0a20b112..f23670ff 100644
--- a/tiledb/libtiledb.pyx
+++ b/tiledb/libtiledb.pyx
@@ -1188,17 +1188,6 @@ cdef class Array(object):
         """The view attribute of this array."""
         return self.view_attr
 
-    @property
-    def timestamp(self):
-        """Deprecated in 0.9.2.
-
-        Use `timestamp_range`
-        """
-        raise TileDBError(
-            "timestamp is deprecated; you must use timestamp_range. "
-            "This message will be removed in 0.21.0.",
-        )
-
     @property
     def timestamp_range(self):
         """Returns the timestamp range the array is opened at
@@ -1223,16 +1212,6 @@ cdef class Array(object):
 
         return (int(timestamp_start), int(timestamp_end))
 
-    @property
-    def coords_dtype(self):
-        """
-        Deprecated in 0.8.10
-        """
-        raise TileDBError(
-            "`coords_dtype` is deprecated because combined coords have been "
-            "removed from libtiledb. This message will be removed in 0.21.0.",
-        )
-
     @property
     def uri(self):
         """Returns the URI of the array"""
@@ -1913,14 +1892,6 @@ cdef class Aggregation(object):
 
             if isinstance(cond, str):
                 q.set_cond(QueryCondition(cond))
-            elif isinstance(cond, QueryCondition):
-                raise TileDBError(
-                    "Passing `tiledb.QueryCondition` to `cond` is no longer "
-                    "supported as of 0.19.0. Instead of "
-                    "`cond=tiledb.QueryCondition('expression')` "
-                    "you must use `cond='expression'`. This message will be "
-                    "removed in 0.21.0.",
-                )
             else:
                 raise TypeError("`cond` expects type str.")        
 
@@ -2103,13 +2074,6 @@ cdef class Query(object):
         """List of attributes to include in Query."""
         return self.attrs
 
-    @property
-    def attr_cond(self):
-        raise TileDBError(
-            "`attr_cond` is no longer supported. You must use `cond`. "
-            "This message will be removed in 0.21.0."
-        )
-
     @property
     def cond(self):
         """QueryCondition used to filter attributes or dimensions in Query."""
@@ -2288,9 +2252,8 @@ cdef class DenseArrayImpl(Array):
         else:
             return "DenseArray(uri={0!r}, mode=closed)".format(self.uri)
 
-    def query(self, attrs=None, attr_cond=None, cond=None, dims=None,
-              coords=False, order='C', use_arrow=None, return_arrow=False,
-              return_incomplete=False):
+    def query(self, attrs=None, cond=None, dims=None, coords=False, order='C',
+              use_arrow=None, return_arrow=False, return_incomplete=False):
         """Construct a proxy Query object for easy subarray queries of cells
         for an item or region of the array across one or more attributes.
 
@@ -2341,24 +2304,12 @@ cdef class DenseArrayImpl(Array):
         if not self.isopen or self.mode != 'r':
             raise TileDBError("DenseArray must be opened in read mode")
 
-        if attr_cond is not None:
-            if cond is not None:
-                raise TileDBError("Both `attr_cond` and `cond` were passed. "
-                    "Only use `cond`."
-                )
-
-            raise TileDBError(
-                "`attr_cond` is no longer supported. You must use `cond`. "
-                "This message will be removed in 0.21.0."
-            )
-
         return Query(self, attrs=attrs, cond=cond, dims=dims,
                       coords=coords, order=order,
                       use_arrow=use_arrow, return_arrow=return_arrow,
                       return_incomplete=return_incomplete)
 
-    def subarray(self, selection, attrs=None, cond=None, attr_cond=None,
-                 coords=False, order=None):
+    def subarray(self, selection, attrs=None, cond=None, coords=False, order=None):
         """Retrieve data cells for an item or region of the array.
 
         Optionally subselect over attributes, return dense result coordinate values,
@@ -2398,12 +2349,6 @@ cdef class DenseArrayImpl(Array):
         if not self.isopen or self.mode != 'r':
             raise TileDBError("DenseArray must be opened in read mode")
 
-        if attr_cond is not None:
-            if cond is not None:
-                raise TileDBError("Both `attr_cond` and `cond` were passed. "
-                    "Only use `cond`."
-                )
-
         cdef tiledb_layout_t layout = TILEDB_UNORDERED
         if order is None or order == 'C':
             layout = TILEDB_ROW_MAJOR
@@ -2475,14 +2420,6 @@ cdef class DenseArrayImpl(Array):
 
             if isinstance(cond, str):
                 q.set_cond(QueryCondition(cond))
-            elif isinstance(cond, QueryCondition):
-                raise TileDBError(
-                    "Passing `tiledb.QueryCondition` to `cond` is no longer "
-                    "supported as of 0.19.0. Instead of "
-                    "`cond=tiledb.QueryCondition('expression')` "
-                    "you must use `cond='expression'`. This message will be "
-                    "removed in 0.21.0.",
-                )
             else:
                 raise TypeError("`cond` expects type str.")
 
@@ -3362,9 +3299,8 @@ cdef class SparseArrayImpl(Array):
 
         return result
 
-    def query(self, attrs=None, cond=None, attr_cond=None, dims=None,
-              index_col=True, coords=None, order='U', use_arrow=None,
-              return_arrow=None, return_incomplete=False):
+    def query(self, attrs=None, cond=None, dims=None, index_col=True, coords=None,
+              order='U', use_arrow=None, return_arrow=None, return_incomplete=False):
         """
         Construct a proxy Query object for easy subarray queries of cells
         for an item or region of the array across one or more attributes.
@@ -3415,17 +3351,6 @@ cdef class SparseArrayImpl(Array):
         if not self.isopen or self.mode not in  ('r', 'd'):
             raise TileDBError("SparseArray must be opened in read or delete mode")
 
-        if attr_cond is not None:
-            if cond is not None:
-                raise TileDBError("Both `attr_cond` and `cond` were passed. "
-                    "Only use `cond`."
-                )
-
-            raise TileDBError(
-                "`attr_cond` is no longer supported. You must use `cond`. "
-                "This message will be removed in 0.21.0."
-            )
-
         # backwards compatibility
         _coords = coords
         if dims is False:
@@ -3480,8 +3405,7 @@ cdef class SparseArrayImpl(Array):
         return result_dict
 
 
-    def subarray(self, selection, coords=True, attrs=None, cond=None,
-                 attr_cond=None, order=None):
+    def subarray(self, selection, coords=True, attrs=None, cond=None, order=None):
         """
         Retrieve dimension and data cells for an item or region of the array.
 
@@ -3529,17 +3453,6 @@ cdef class SparseArrayImpl(Array):
         if not self.isopen or self.mode not in ('r', 'd'):
             raise TileDBError("SparseArray is not opened in read or delete mode")
 
-        if attr_cond is not None:
-            if cond is not None:
-                raise TileDBError("Both `attr_cond` and `cond` were passed. "
-                    "`attr_cond` is no longer supported. You must use `cond`. "
-                )
-
-            raise TileDBError(
-                "`attr_cond` is no longer supported. You must use `cond`. "
-                "This message will be removed in 0.21.0.",
-            )
-
         cdef tiledb_layout_t layout = TILEDB_UNORDERED
         if order is None or order == 'U':
             layout = TILEDB_UNORDERED
@@ -3607,14 +3520,6 @@ cdef class SparseArrayImpl(Array):
 
             if isinstance(cond, str):
                 q.set_cond(QueryCondition(cond))
-            elif isinstance(cond, QueryCondition):
-                raise TileDBError(
-                    "Passing `tiledb.QueryCondition` to `cond` is no longer "
-                    "supported as of 0.19.0. Instead of "
-                    "`cond=tiledb.QueryCondition('expression')` "
-                    "you must use `cond='expression'`. This message will be "
-                    "removed in 0.21.0.",
-                )
             else:
                 raise TypeError("`cond` expects type str.")
 
diff --git a/tiledb/multirange_indexing.py b/tiledb/multirange_indexing.py
index dbbe3278..27e5725f 100644
--- a/tiledb/multirange_indexing.py
+++ b/tiledb/multirange_indexing.py
@@ -649,13 +649,6 @@ def _get_pyquery(
     if query and query.cond is not None:
         if isinstance(query.cond, str):
             pyquery.set_cond(QueryCondition(query.cond))
-        elif isinstance(query.cond, QueryCondition):
-            raise TileDBError(
-                "Passing `tiledb.QueryCondition` to `cond` is no longer supported "
-                "as of 0.19.0. Instead of `cond=tiledb.QueryCondition('expression')` "
-                "you must use `cond='expression'`. This message will be "
-                "removed in 0.21.0.",
-            )
         else:
             raise TypeError("`cond` expects type str.")
 
diff --git a/tiledb/query_condition.py b/tiledb/query_condition.py
index 39e722f2..baf4c9f0 100644
--- a/tiledb/query_condition.py
+++ b/tiledb/query_condition.py
@@ -321,11 +321,6 @@ class QueryConditionTree(ast.NodeVisitor):
             variable = variable_node.id
         elif isinstance(variable_node, ast.Constant):
             variable = variable_node.value
-        elif isinstance(variable_node, ast.Constant) or isinstance(
-            variable_node, ast.Constant
-        ):
-            # deprecated in 3.8
-            variable = variable_node.s
         else:
             raise TileDBError(
                 f"Incorrect type for variable name: {ast.dump(variable_node)}"
@@ -492,19 +487,3 @@ class QueryConditionTree(ast.NodeVisitor):
                 )
 
             return node.operand
-
-    def visit_Num(self, node: ast.Constant) -> ast.Constant:
-        # deprecated in 3.8
-        return node
-
-    def visit_Str(self, node: ast.Constant) -> ast.Constant:
-        # deprecated in 3.8
-        return node
-
-    def visit_Bytes(self, node: ast.Constant) -> ast.Constant:
-        # deprecated in 3.8
-        return node
-
-    def visit_NameConstant(self, node: ast.Constant) -> ast.Constant:
-        # deprecated in 3.8
-        return node
diff --git a/tiledb/vfs.py b/tiledb/vfs.py
index d95c4d52..0cdc745d 100644
--- a/tiledb/vfs.py
+++ b/tiledb/vfs.py
@@ -111,15 +111,7 @@ class VFS(lt.VFS):
         :rtype: :py:func:`bytes`
         :return: read bytes
         :raises: :py:exc:`tiledb.TileDBError`
-
         """
-        if isinstance(file, FileIO):
-            raise lt.TileDBError(
-                "`tiledb.VFS().open` now returns a FileIO object. Use "
-                "`FileIO.seek` and `FileIO.read`. This message will be removed "
-                "in 0.21.0."
-            )
-
         if nbytes == 0:
             return b""
 


Test patch:
diff --git a/tiledb/tests/test_dask.py b/tiledb/tests/test_dask.py
index 6ca8da76..4d275190 100644
--- a/tiledb/tests/test_dask.py
+++ b/tiledb/tests/test_dask.py
@@ -10,10 +10,10 @@ import tiledb
 from .common import DiskTestCase
 
 # Skip this test if dask is unavailable
-da = pytest.importorskip("dask.array")
+da_array = pytest.importorskip("dask.array")
+da_distributed = pytest.importorskip("dask.distributed")
 
 
-@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
 class TestDaskSupport(DiskTestCase):
     def test_dask_from_numpy_1d(self):
         uri = self.path("np_1attr")
@@ -22,10 +22,10 @@ class TestDaskSupport(DiskTestCase):
         T.close()
 
         with tiledb.open(uri) as T:
-            D = da.from_tiledb(T)
+            D = da_array.from_tiledb(T)
             np.testing.assert_array_equal(D, A)
 
-        D2 = da.from_tiledb(uri)
+        D2 = da_array.from_tiledb(uri)
         np.testing.assert_array_equal(D2, A)
         self.assertAlmostEqual(
             np.mean(A), D2.mean().compute(scheduler="single-threaded")
@@ -43,18 +43,6 @@ class TestDaskSupport(DiskTestCase):
         tiledb.DenseArray.create(uri, schema)
 
     @pytest.mark.filterwarnings("ignore:There is no current event loop")
-    @pytest.mark.filterwarnings(
-        # In Python 3.7 on POSIX systems, Hurricane outputs a warning message
-        # that "make_current is deprecated." This should be fixed by Dask in
-        # future releases.
-        "ignore:make_current is deprecated"
-    )
-    @pytest.mark.skipif(
-        condition=(
-            sys.version_info >= (3, 11) and (datetime.now() < datetime(2023, 1, 6))
-        ),
-        reason="https://github.com/dask/distributed/issues/6785",
-    )
     def test_dask_multiattr_2d(self):
         uri = self.path("multiattr")
 
@@ -66,32 +54,30 @@ class TestDaskSupport(DiskTestCase):
             T[:] = {"attr1": ar1, "attr2": ar2}
         with tiledb.DenseArray(uri, mode="r", attr="attr2") as T:
             # basic round-trip from dask.array
-            D = da.from_tiledb(T, attribute="attr2")
+            D = da_array.from_tiledb(T, attribute="attr2")
             np.testing.assert_array_equal(ar2, np.array(D))
 
         # smoke-test computation
         # note: re-init from_tiledb each time, or else dask just uses the cached materialization
-        D = da.from_tiledb(uri, attribute="attr2")
+        D = da_array.from_tiledb(uri, attribute="attr2")
         self.assertAlmostEqual(np.mean(ar2), D.mean().compute(scheduler="threads"))
-        D = da.from_tiledb(uri, attribute="attr2")
+        D = da_array.from_tiledb(uri, attribute="attr2")
         self.assertAlmostEqual(
             np.mean(ar2), D.mean().compute(scheduler="single-threaded")
         )
-        D = da.from_tiledb(uri, attribute="attr2")
+        D = da_array.from_tiledb(uri, attribute="attr2")
         self.assertAlmostEqual(np.mean(ar2), D.mean().compute(scheduler="processes"))
 
         # test dask.distributed
-        from dask.distributed import Client
-
-        D = da.from_tiledb(uri, attribute="attr2")
-        with Client():
+        D = da_array.from_tiledb(uri, attribute="attr2")
+        with da_distributed.Client():
             np.testing.assert_approx_equal(D.mean().compute(), np.mean(ar2))
 
     def test_dask_write(self):
         uri = self.path("dask_w")
-        D = da.random.random(10, 10)
+        D = da_array.random.random(10, 10)
         D.to_tiledb(uri)
-        DT = da.from_tiledb(uri)
+        DT = da_array.from_tiledb(uri)
         np.testing.assert_array_equal(D, DT)
 
     def test_dask_overlap_blocks(self):
@@ -101,10 +87,10 @@ class TestDaskSupport(DiskTestCase):
         T.close()
 
         with tiledb.open(uri) as T:
-            D = da.from_tiledb(T)
+            D = da_array.from_tiledb(T)
             np.testing.assert_array_equal(D, A)
 
-        D2 = da.from_tiledb(uri)
+        D2 = da_array.from_tiledb(uri)
         np.testing.assert_array_equal(D2, A)
 
         D3 = D2.map_overlap(
@@ -133,7 +119,7 @@ class TestDaskSupport(DiskTestCase):
         with tiledb.open(uri, "w", attr="TDB_VALUES") as T:
             T[:] = A
 
-        D2 = da.from_tiledb(uri, attribute="TDB_VALUES")
+        D2 = da_array.from_tiledb(uri, attribute="TDB_VALUES")
 
         D3 = D2.map_overlap(
             lambda x: x + 1, depth={0: 0, 1: 1, 2: 1}, dtype=D2.dtype, boundary="none"
@@ -160,7 +146,7 @@ class TestDaskSupport(DiskTestCase):
         with tiledb.open(uri, "w", attr="TDB_VALUES") as D1:
             D1[:] = A
 
-        D2 = da.from_tiledb(uri, attribute="TDB_VALUES")
+        D2 = da_array.from_tiledb(uri, attribute="TDB_VALUES")
 
         D3 = D2.map_blocks(lambda x: x + 1, dtype=D2.dtype).compute(
             scheduler="processes"
@@ -168,11 +154,6 @@ class TestDaskSupport(DiskTestCase):
         np.testing.assert_array_equal(D2 + 1, D3)
 
 
-@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
-@pytest.mark.skipif(
-    sys.version_info[:2] == (3, 8),
-    reason="Fails on Python 3.8 due to dask worker restarts",
-)
 def test_sc33742_dask_array_object_dtype_conversion():
     # This test verifies that an array can be converted to buffer after serialization
     # through several dask.distributed compute steps. The original source of the issue
@@ -182,7 +163,6 @@ def test_sc33742_dask_array_object_dtype_conversion():
 
     import dask
     import numpy as np
-    from dask.distributed import Client, LocalCluster
 
     @dask.delayed
     def get_data():
@@ -213,7 +193,9 @@ def test_sc33742_dask_array_object_dtype_conversion():
     with warnings.catch_warnings():
         warnings.simplefilter("ignore")
         global client
-        client = Client(LocalCluster(scheduler_port=9786, dashboard_address=9787))
+        client = da_distributed.Client(
+            da_distributed.LocalCluster(scheduler_port=9786, dashboard_address=9787)
+        )
 
         w = []
 
diff --git a/tiledb/tests/test_filestore.py b/tiledb/tests/test_filestore.py
index bde45452..9d352ff2 100644
--- a/tiledb/tests/test_filestore.py
+++ b/tiledb/tests/test_filestore.py
@@ -74,22 +74,6 @@ class FilestoreTest(DiskTestCase):
             assert data == fs.read(0, len(data))
             assert len(fs) == len(data)
 
-    def test_deprecated_uri(self, text_fname):
-        path = self.path("test_uri")
-        schema = tiledb.ArraySchema.from_file(text_fname)
-        tiledb.Array.create(path, schema)
-
-        fs = tiledb.Filestore(path)
-        with pytest.warns(
-            DeprecationWarning, match="Filestore.uri_import is deprecated"
-        ):
-            fs.uri_import(text_fname)
-
-        with open(text_fname, "rb") as text:
-            data = text.read()
-            assert data == fs.read(0, len(data))
-            assert len(fs) == len(data)
-
     def test_multiple_writes(self):
         path = self.path("test_buffer")
         schema = tiledb.ArraySchema.from_file()
diff --git a/tiledb/tests/test_pandas_dataframe.py b/tiledb/tests/test_pandas_dataframe.py
index 51c02d74..9811144c 100644
--- a/tiledb/tests/test_pandas_dataframe.py
+++ b/tiledb/tests/test_pandas_dataframe.py
@@ -127,7 +127,7 @@ def make_dataframe_categorical():
     return df
 
 
-class TestColumnInfo:
+class TestColumnInfo(DiskTestCase):
     def assertColumnInfo(self, info, info_dtype, info_repr=None, info_nullable=False):
         assert isinstance(info.dtype, np.dtype)
         assert info.dtype == info_dtype
@@ -250,6 +250,96 @@ class TestColumnInfo:
                     # check that the column name is included in the error message
                     assert "supported (column foo)" in str(exc.value)
 
+    def test_apply_dtype_index_ingest(self):
+        uri = self.path("index_dtype_default_dtype")
+        tiledb.from_pandas(
+            uri,
+            pd.DataFrame({"a": np.arange(0, 20), "b": np.arange(20, 40)}),
+            sparse=True,
+            index_dims=["a"],
+        )
+        with tiledb.open(uri) as A:
+            if sys.platform == "win32" and sys.version_info[:2] == (3, 8):
+                assert A.schema.domain.dim(0).dtype == np.int32
+            else:
+                assert A.schema.domain.dim(0).dtype == np.int64
+
+        uri = self.path("index_dtype_casted_dtype")
+        tiledb.from_pandas(
+            uri,
+            pd.DataFrame({"a": np.arange(0, 20), "b": np.arange(20, 40)}),
+            sparse=True,
+            index_dims=["a"],
+            column_types={"a": np.uint8},
+        )
+        with tiledb.open(uri) as A:
+            assert A.schema.domain.dim(0).dtype == np.uint8
+
+        # multiple index dims
+        uri = self.path("index_dtype_default_dtype_multi")
+        tiledb.from_pandas(
+            uri,
+            pd.DataFrame(
+                {
+                    "a": np.random.random_sample(20),
+                    "b": [str(uuid.uuid4()) for _ in range(20)],
+                }
+            ),
+            sparse=True,
+            index_dims=["a", "b"],
+        )
+        with tiledb.open(uri) as A:
+            assert A.schema.domain.dim(0).dtype == np.float64
+            assert A.schema.domain.dim(1).dtype == np.bytes_
+
+        uri = self.path("index_dtype_casted_dtype_multi")
+        tiledb.from_pandas(
+            uri,
+            pd.DataFrame(
+                {
+                    "a": np.random.random_sample(20),
+                    "b": [str(uuid.uuid4()) for _ in range(20)],
+                }
+            ),
+            sparse=True,
+            index_dims=["a", "b"],
+            column_types={"a": np.float32, "b": np.bytes_},
+        )
+        with tiledb.open(uri) as A:
+            assert A.schema.domain.dim(0).dtype == np.float32
+            assert A.schema.domain.dim(1).dtype == np.bytes_
+
+    def test_apply_dtype_index_schema_only(self):
+        uri = self.path("index_dtype_casted_dtype")
+        tiledb.from_pandas(
+            uri,
+            pd.DataFrame({"a": np.arange(0, 20), "b": np.arange(20, 40)}),
+            sparse=True,
+            index_dims=["a"],
+            column_types={"a": np.uint8},
+            mode="schema_only",
+        )
+        with tiledb.open(uri) as A:
+            assert A.schema.domain.dim(0).dtype == np.uint8
+
+        uri = self.path("index_dtype_casted_dtype_multi")
+        tiledb.from_pandas(
+            uri,
+            pd.DataFrame(
+                {
+                    "a": np.random.random_sample(20),
+                    "b": [str(uuid.uuid4()) for _ in range(20)],
+                }
+            ),
+            sparse=True,
+            index_dims=["a", "b"],
+            column_types={"a": np.float32, "b": np.bytes_},
+            mode="schema_only",
+        )
+        with tiledb.open(uri) as A:
+            assert A.schema.domain.dim(0).dtype == np.float32
+            assert A.schema.domain.dim(1).dtype == np.bytes_
+
 
 class TestDimType:
     @pytest.mark.parametrize(
@@ -392,10 +482,6 @@ class TestPandasDataFrameRoundtrip(DiskTestCase):
         with tiledb.open(uri) as B:
             tm.assert_frame_equal(df, B.df[:])
 
-    @pytest.mark.skipif(
-        sys.version_info < (3, 8),
-        reason="requires Python 3.8 or higher. date_format argument is not supported in 3.7 and below",
-    )
     def test_dataframe_csv_rt1(self):
         def rand_dtype(dtype, size):
             nbytes = size * np.dtype(dtype).itemsize
@@ -703,10 +789,6 @@ class TestPandasDataFrameRoundtrip(DiskTestCase):
         tmp_array2 = os.path.join(tmp_dir, "array2")
         tiledb.from_csv(tmp_array2, tmp_csv, sparse=False)
 
-    @pytest.mark.skipif(
-        sys.version_info < (3, 8),
-        reason="requires Python 3.8 or higher. date_format argument is not supported in 3.7 and below",
-    )
     def test_csv_col_to_sparse_dims(self):
         df = make_dataframe_basic3(20)
 
@@ -780,10 +862,6 @@ class TestPandasDataFrameRoundtrip(DiskTestCase):
             cmp_df = df.set_index("int_vals").sort_values(by="time")
             tm.assert_frame_equal(res_df, cmp_df)
 
-    @pytest.mark.skipif(
-        sys.version_info < (3, 8),
-        reason="requires Python 3.8 or higher. date_format argument is not supported in 3.7 and below",
-    )
     def test_dataframe_csv_schema_only(self):
         col_size = 10
         df = make_dataframe_basic3(col_size)
@@ -893,10 +971,6 @@ class TestPandasDataFrameRoundtrip(DiskTestCase):
             df_bk.sort_index(level="time", inplace=True)
             tm.assert_frame_equal(df_bk, df_combined)
 
-    @pytest.mark.skipif(
-        sys.version_info < (3, 8),
-        reason="requires Python 3.8 or higher. date_format argument is not supported in 3.7 and below",
-    )
     def test_dataframe_csv_chunked(self):
         col_size = 200
         df = make_dataframe_basic3(col_size)
@@ -979,10 +1053,6 @@ class TestPandasDataFrameRoundtrip(DiskTestCase):
             df_idx_res = A.query(coords=False).df[int(ned[0]) : int(ned[1])]
             tm.assert_frame_equal(df_idx_res, df.reset_index(drop=True))
 
-    @pytest.mark.skipif(
-        sys.version_info < (3, 8),
-        reason="requires Python 3.8 or higher. date_format argument is not supported in 3.7 and below",
-    )
     def test_csv_fillna(self):
         if pytest.tiledb_vfs == "s3":
             pytest.skip(
diff --git a/tiledb/tests/test_query_condition.py b/tiledb/tests/test_query_condition.py
index 07549482..a3c3f157 100644
--- a/tiledb/tests/test_query_condition.py
+++ b/tiledb/tests/test_query_condition.py
@@ -119,12 +119,7 @@ class QueryConditionTest(DiskTestCase):
 
     def test_unsigned_sparse(self):
         with tiledb.open(self.create_input_array_UIDSA(sparse=True)) as A:
-            with pytest.raises(tiledb.TileDBError) as exc_info:
-                A.query(cond=tiledb.QueryCondition("U < 5"), attrs=["U"])[:]
-            assert (
-                "Passing `tiledb.QueryCondition` to `cond` is no longer supported"
-                in str(exc_info.value)
-            )
+            A.query(cond="U < 5", attrs=["U"])[:]
 
             result = A.query(cond="U < 5", attrs=["U"])[:]
             assert all(result["U"] < 5)
@@ -133,12 +128,7 @@ class QueryConditionTest(DiskTestCase):
         with tiledb.open(self.create_input_array_UIDSA(sparse=False)) as A:
             mask = A.attr("U").fill
 
-            with pytest.raises(tiledb.TileDBError) as exc_info:
-                A.query(cond=tiledb.QueryCondition("U < 5"), attrs=["U"])[:]
-            assert (
-                "Passing `tiledb.QueryCondition` to `cond` is no longer supported"
-                in str(exc_info.value)
-            )
+            A.query(cond="U < 5", attrs=["U"])[:]
 
             result = A.query(cond="U < 5", attrs=["U"])[:]
             assert all(self.filter_dense(result["U"], mask) < 5)
@@ -699,25 +689,9 @@ class QueryConditionTest(DiskTestCase):
         with tiledb.open(self.create_input_array_UIDSA(sparse=True)) as A:
             qc = "U < 3"
 
-            with pytest.raises(tiledb.TileDBError) as exc_info:
-                A.query(cond=qc, attr_cond=qc)
-            assert "Both `attr_cond` and `cond` were passed." in str(exc_info.value)
-
-            with pytest.raises(tiledb.TileDBError) as exc_info:
-                A.query(attr_cond=qc)
-            assert "`attr_cond` is no longer supported" in str(exc_info.value)
-
-            with pytest.raises(tiledb.TileDBError) as exc_info:
-                A.query(cond=qc).attr_cond
-            assert "`attr_cond` is no longer supported" in str(exc_info.value)
-
-            with pytest.raises(tiledb.TileDBError) as exc_info:
-                A.subarray(1, cond=qc, attr_cond=qc)
-            assert "Both `attr_cond` and `cond` were passed." in str(exc_info.value)
-
-            with pytest.raises(tiledb.TileDBError) as exc_info:
-                A.subarray(1, attr_cond=qc)
-            assert "`attr_cond` is no longer supported" in str(exc_info.value)
+            A.query(cond=qc)
+            A.query(cond=qc).cond
+            A.subarray(1, cond=qc)
 
     def test_on_dense_dimensions(self):
         with tiledb.open(self.create_input_array_UIDSA(sparse=False)) as A: