From 9265ffab4b4c3e4d9bba4e9b96f881a426f337ea Mon Sep 17 00:00:00 2001 From: Agisilaos Kounelis Date: Thu, 5 Feb 2026 17:52:17 +0200 Subject: [PATCH 1/9] Add support for pandas3 --- tiledb/dataframe_.py | 31 ++++++++++++++++++++++--------- tiledb/dense_array.py | 8 ++++++++ tiledb/multirange_indexing.py | 6 +++++- tiledb/sparse_array.py | 9 +++++++++ tiledb/tests/datatypes.py | 8 +++++++- 5 files changed, 51 insertions(+), 11 deletions(-) diff --git a/tiledb/dataframe_.py b/tiledb/dataframe_.py index 50755eccad..aad5788147 100644 --- a/tiledb/dataframe_.py +++ b/tiledb/dataframe_.py @@ -154,7 +154,7 @@ class ColumnInfo: @classmethod def from_values(cls, array_like, varlen_types=()): - from pandas import CategoricalDtype + from pandas import CategoricalDtype, StringDtype from pandas.api import types as pd_types if pd_types.is_object_dtype(array_like): @@ -171,6 +171,16 @@ def from_values(cls, array_like, varlen_types=()): raise NotImplementedError( f"{inferred_dtype} inferred dtype not supported (column {array_like.name})" ) + elif hasattr(array_like, "dtype") and isinstance(array_like.dtype, StringDtype): + # Explicit pd.StringDtype() (name="string") is always nullable; + # auto-inferred str (name="str") depends on data + explicit = array_like.dtype.name == "string" + return cls( + np.dtype(np.str_), + repr="string" if explicit else None, + var=True, + nullable=explicit or bool(array_like.isna().any()), + ) elif hasattr(array_like, "dtype") and isinstance( array_like.dtype, CategoricalDtype ): @@ -211,6 +221,14 @@ def from_dtype(cls, dtype, column_name, varlen_types=()): dtype = pd_types.pandas_dtype(dtype) # Note: be careful if you rearrange the order of the following checks + # pandas StringDtype (auto-inferred 'str' and explicit 'string') + from pandas import StringDtype + + if isinstance(dtype, StringDtype): + repr_val = "string" if dtype.name == "string" else None + nullable = dtype.name == "string" + return cls(np.dtype(np.str_), repr=repr_val, var=True, nullable=nullable) + # extension types if pd_types.is_extension_array_dtype(dtype): if libtiledb_version() < (2, 10) and pd_types.is_bool_dtype(dtype): @@ -255,12 +273,7 @@ def from_dtype(cls, dtype, column_name, varlen_types=()): # datetime types if pd_types.is_datetime64_any_dtype(dtype): - if dtype == "datetime64[ns]": - return cls(dtype) - else: - raise NotImplementedError( - f"Only 'datetime64[ns]' datetime dtype is supported (column {column_name})" - ) + return cls(dtype) # string types # don't use pd_types.is_string_dtype() because it includes object types too @@ -517,8 +530,8 @@ def _df_to_np_arrays(df, column_infos, fillna): if not column_info.var: to_numpy_kwargs.update(dtype=column_info.dtype) - if column_info.nullable: - # use default 0/empty for the dtype + if column_info.nullable and column.isna().any(): + # Only create nullmap if data actually has nulls to_numpy_kwargs.update(na_value=column_info.dtype.type()) nullmaps[name] = (~column.isna()).to_numpy(dtype=np.uint8) diff --git a/tiledb/dense_array.py b/tiledb/dense_array.py index 71e086aaa4..41ed5aed80 100644 --- a/tiledb/dense_array.py +++ b/tiledb/dense_array.py @@ -481,6 +481,14 @@ def _setitem_impl(self, selection, val, nullmaps: dict): try: if attr.isvar: + # Capture null mask before np.asarray() loses pandas NA info + if ( + attr.isnullable + and name not in nullmaps + and hasattr(attr_val, "isna") + ): + nullmaps[name] = (~attr_val.isna()).to_numpy(dtype=np.uint8) + # ensure that the value is array-convertible, for example: pandas.Series attr_val = np.asarray(attr_val) if attr.isnullable and name not in nullmaps: diff --git a/tiledb/multirange_indexing.py b/tiledb/multirange_indexing.py index 537caf22dd..bf66f7b251 100644 --- a/tiledb/multirange_indexing.py +++ b/tiledb/multirange_indexing.py @@ -890,7 +890,11 @@ def _update_df_from_meta( col_dtypes[name] = dtype if col_dtypes: - df = df.astype(col_dtypes, copy=False) + # Use str instead of ' Date: Thu, 5 Feb 2026 17:52:34 +0200 Subject: [PATCH 2/9] Add and modify tests --- tiledb/tests/test_pandas_dataframe.py | 57 ++++++++++++--------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/tiledb/tests/test_pandas_dataframe.py b/tiledb/tests/test_pandas_dataframe.py index fa4350d8d6..9812b12eb8 100644 --- a/tiledb/tests/test_pandas_dataframe.py +++ b/tiledb/tests/test_pandas_dataframe.py @@ -204,32 +204,34 @@ def test_implemented(self, type_specs, info_dtype, info_repr, info_nullable): def test_object_dtype(self): self.assertColumnInfo( - ColumnInfo.from_values(pd.Series(["hello", "world"])), np.dtype(" Date: Thu, 5 Feb 2026 18:04:28 +0200 Subject: [PATCH 3/9] Remove pandas version restriction --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b8f88f2dd3..4fabff4fd0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,7 +57,7 @@ test = [ "hypothesis", "psutil", "pyarrow", - "pandas<3", + "pandas", "dask[distributed]", ] @@ -118,6 +118,6 @@ test-requires = [ "hypothesis", "psutil", "pyarrow", - "pandas<3", + "pandas", ] test-command = "pytest {project}" From bbbc39fe3f6630df5f6448cd7b6cc7d5bd46a87c Mon Sep 17 00:00:00 2001 From: Agisilaos Kounelis Date: Thu, 5 Feb 2026 18:05:16 +0200 Subject: [PATCH 4/9] Simplify pandas dependency checks --- examples/incomplete_iteration.py | 13 +++---------- examples/parallel_csv_ingestion.py | 13 +++---------- tiledb/dataframe_.py | 23 +++-------------------- tiledb/tests/common.py | 11 +++-------- 4 files changed, 12 insertions(+), 48 deletions(-) diff --git a/examples/incomplete_iteration.py b/examples/incomplete_iteration.py index 4166cff7d9..aa458a3c84 100644 --- a/examples/incomplete_iteration.py +++ b/examples/incomplete_iteration.py @@ -40,21 +40,14 @@ def check_dataframe_deps(): - pd_error = """Pandas version >= 1.0 and < 3.0 required for dataframe functionality. - Please `pip install pandas>=1.0,<3.0` to proceed.""" + pd_error = """Pandas is required for dataframe functionality. + Please `pip install pandas` to proceed.""" try: - import pandas as pd + import pandas except ImportError: raise Exception(pd_error) - from packaging.version import Version - - if Version(pd.__version__) < Version("1.0") or Version(pd.__version__) >= Version( - "3.0.0.dev0" - ): - raise Exception(pd_error) - # Name of the array to create. array_name = "incomplete_iteration" diff --git a/examples/parallel_csv_ingestion.py b/examples/parallel_csv_ingestion.py index 2038df7093..799f210f92 100644 --- a/examples/parallel_csv_ingestion.py +++ b/examples/parallel_csv_ingestion.py @@ -49,21 +49,14 @@ def check_dataframe_deps(): - pd_error = """Pandas version >= 1.0 and < 3.0 required for dataframe functionality. - Please `pip install pandas>=1.0,<3.0` to proceed.""" + pd_error = """Pandas is required for dataframe functionality. + Please `pip install pandas` to proceed.""" try: - import pandas as pd + import pandas except ImportError: raise Exception(pd_error) - from packaging.version import Version - - if Version(pd.__version__) < Version("1.0") or Version(pd.__version__) >= Version( - "3.0.0.dev0" - ): - raise Exception(pd_error) - def generate_csvs(csv_folder, count=9, min_length=1, max_length=109): def make_dataframe(col_size): diff --git a/tiledb/dataframe_.py b/tiledb/dataframe_.py index aad5788147..10539e94ca 100644 --- a/tiledb/dataframe_.py +++ b/tiledb/dataframe_.py @@ -15,31 +15,14 @@ def check_dataframe_deps(): - pd_error = """Pandas version >= 1.0 and < 3.0 required for dataframe functionality. - Please `pip install pandas>=1.0,<3.0` to proceed.""" - pa_error = """PyArrow version >= 1.0 is suggested for dataframe functionality. - Please `pip install pyarrow>=1.0`.""" + pd_error = """Pandas is required for dataframe functionality. + Please `pip install pandas` to proceed.""" try: - import pandas as pd + import pandas except ImportError: raise Exception(pd_error) - from packaging.version import Version - - if Version(pd.__version__) < Version("1.0") or Version(pd.__version__) >= Version( - "3.0.0.dev0" - ): - raise Exception(pd_error) - - try: - import pyarrow as pa - - if Version(pa.__version__) < Version("1.0"): - warnings.warn(pa_error) - except ImportError: - warnings.warn(pa_error) - # Note: 'None' is used to indicate optionality for many of these options # For example, if the `sparse` argument is unspecified we will default diff --git a/tiledb/tests/common.py b/tiledb/tests/common.py index 087089b363..de1555411c 100644 --- a/tiledb/tests/common.py +++ b/tiledb/tests/common.py @@ -26,17 +26,12 @@ def has_pandas(): try: - import pandas as pd - except ImportError: - return False + import pandas - if Version(pd.__version__) < Version("1.0") or Version(pd.__version__) >= Version( - "3.0.0.dev0" - ): + return True + except ImportError: return False - return True - def has_pyarrow(): try: From 223aec8e9b7d9174f94c809f33ce8d7f47190f52 Mon Sep 17 00:00:00 2001 From: Agisilaos Kounelis Date: Thu, 5 Feb 2026 18:06:35 +0200 Subject: [PATCH 5/9] Update test skip reason messages --- tiledb/tests/test_enumeration.py | 4 ++-- tiledb/tests/test_examples.py | 7 +++---- tiledb/tests/test_fixes.py | 6 +++--- tiledb/tests/test_hypothesis.py | 2 +- tiledb/tests/test_libtiledb.py | 8 ++++---- tiledb/tests/test_multi_index.py | 16 ++++++++-------- tiledb/tests/test_pandas_dataframe.py | 2 +- tiledb/tests/test_query_condition.py | 4 ++-- 8 files changed, 24 insertions(+), 25 deletions(-) diff --git a/tiledb/tests/test_enumeration.py b/tiledb/tests/test_enumeration.py index 00ed043fd0..7d7c8e5382 100644 --- a/tiledb/tests/test_enumeration.py +++ b/tiledb/tests/test_enumeration.py @@ -111,7 +111,7 @@ def test_array_schema_enumeration(self): @pytest.mark.skipif( not has_pyarrow() or not has_pandas(), - reason="pyarrow>=1.0 and/or pandas>=1.0,<3.0 not installed", + reason="pyarrow>=1.0 and/or pandas not installed", ) @pytest.mark.parametrize("sparse", [True, False]) @pytest.mark.parametrize("pass_df", [True, False]) @@ -185,7 +185,7 @@ def test_enum_dtypes(self, dtype, values): assert enmr.dtype == enmr.values().dtype == dtype assert_array_equal(enmr.values(), values) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_from_pandas_dtype_mismatch(self): import pandas as pd diff --git a/tiledb/tests/test_examples.py b/tiledb/tests/test_examples.py index 1c3f18a899..10793e36d4 100644 --- a/tiledb/tests/test_examples.py +++ b/tiledb/tests/test_examples.py @@ -43,7 +43,7 @@ def test_examples(self, path): ] ] if not has_pandas() and path in requires_pd: - pytest.mark.skip("pandas>=1.0,<3.0 not installed") + pytest.mark.skip("pandas not installed") else: with tempfile.TemporaryDirectory() as tmpdir: try: @@ -73,10 +73,9 @@ def test_docs(self, capsys): if failures: stderr = capsys.readouterr().out if "No module named 'pandas'" in stderr or ( - "Pandas version >= 1.0 and < 3.0 required for dataframe functionality" - in stderr + "Pandas is required for dataframe functionality" in stderr and not has_pandas() ): - pytest.skip("pandas>=1.0,<3.0 not installed") + pytest.skip("pandas not installed") else: pytest.fail(stderr) diff --git a/tiledb/tests/test_fixes.py b/tiledb/tests/test_fixes.py index 73d5611f5b..aa82d4f2e3 100644 --- a/tiledb/tests/test_fixes.py +++ b/tiledb/tests/test_fixes.py @@ -91,7 +91,7 @@ def test_ch8292(self): buffers = list(*q._get_buffers().values()) assert buffers[0].nbytes == max_val - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_ch10282_concurrent_multi_index(self): """Test concurrent access to a single tiledb.Array using Array.multi_index and Array.df. We pass an array and slice @@ -230,7 +230,7 @@ def test_fix_stats_error_messages(self): @pytest.mark.skipif( not has_pandas() and has_pyarrow(), - reason="pandas>=1.0,<3.0 or pyarrow>=1.0 not installed", + reason="pandas or pyarrow>=1.0 not installed", ) def test_py1078_df_all_empty_strings(self): uri = self.path() @@ -246,7 +246,7 @@ def test_py1078_df_all_empty_strings(self): with tiledb.open(uri) as arr: tm.assert_frame_equal(arr.df[:], df) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") @pytest.mark.parametrize("is_sparse", [True, False]) def test_sc1430_nonexisting_timestamp(self, is_sparse): path = self.path("nonexisting_timestamp") diff --git a/tiledb/tests/test_hypothesis.py b/tiledb/tests/test_hypothesis.py index 6494f420da..c73bb876cd 100644 --- a/tiledb/tests/test_hypothesis.py +++ b/tiledb/tests/test_hypothesis.py @@ -13,7 +13,7 @@ tm = pd._testing -@pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") +@pytest.mark.skipif(not has_pandas(), reason="pandas not installed") @pytest.mark.parametrize("mode", ["np", "df"]) @hp.settings(deadline=None, verbosity=hp.Verbosity.verbose) @hp.given(st.binary()) diff --git a/tiledb/tests/test_libtiledb.py b/tiledb/tests/test_libtiledb.py index 07d852ba5b..38f04c5cf4 100644 --- a/tiledb/tests/test_libtiledb.py +++ b/tiledb/tests/test_libtiledb.py @@ -418,7 +418,7 @@ def test_array_delete(self): @pytest.mark.skipif( not has_pyarrow() or not has_pandas(), - reason="pyarrow>=1.0 and/or pandas>=1.0,<3.0 not installed", + reason="pyarrow>=1.0 and/or pandas not installed", ) @pytest.mark.parametrize("sparse", [True, False]) @pytest.mark.parametrize("pass_df", [True, False]) @@ -1784,7 +1784,7 @@ def test_query_real_multi_index(self, fx_sparse_cell_order): "coords" not in T.query(coords=False).multi_index[-10.0:5.0] ) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") @pytest.mark.parametrize("dtype", ["u1", "u2", "u4", "u8", "i1", "i2", "i4", "i8"]) def test_sparse_index_dtypes(self, dtype): path = self.path() @@ -1805,7 +1805,7 @@ def test_sparse_index_dtypes(self, dtype): assert B[data[1]]["attr"] == data[1] assert B.multi_index[data[0]]["attr"] == data[0] - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") @pytest.mark.skipif( tiledb.libtiledb.version() < (2, 10), reason="TILEDB_BOOL introduced in libtiledb 2.10", @@ -3743,7 +3743,7 @@ def test_query_return_incomplete_error(self, sparse): with self.assertRaises(tiledb.TileDBError): A.query(return_incomplete=True)[:] - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") @pytest.mark.parametrize( "use_arrow, return_arrow, indexer", [ diff --git a/tiledb/tests/test_multi_index.py b/tiledb/tests/test_multi_index.py index 6f8c7ef166..1a6f713ca8 100644 --- a/tiledb/tests/test_multi_index.py +++ b/tiledb/tests/test_multi_index.py @@ -141,7 +141,7 @@ def make_arr(ndim): class TestMultiRange(DiskTestCase): @pytest.mark.skipif( not has_pyarrow() or not has_pandas(), - reason="pyarrow>=1.0 and/or pandas>=1.0,<3.0 not installed", + reason="pyarrow>=1.0 and/or pandas not installed", ) def test_return_arrow_indexers(self): uri = self.path("multirange_behavior_sparse") @@ -183,7 +183,7 @@ def test_return_arrow_indexers(self): @pytest.mark.skipif( not has_pyarrow() or not has_pandas(), - reason="pyarrow>=1.0 and/or pandas>=1.0,<3.0 not installed", + reason="pyarrow>=1.0 and/or pandas not installed", ) @pytest.mark.parametrize("sparse", [True, False]) def test_return_large_arrow_table(self, sparse): @@ -727,7 +727,7 @@ def test_fix_473_sparse_index_bug(self): np.array([], dtype=np.uint64), ) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_fixed_multi_attr_df(self): uri = self.path("test_fixed_multi_attr_df") dom = tiledb.Domain( @@ -761,7 +761,7 @@ def test_fixed_multi_attr_df(self): result = A.query(attrs=["111"], use_arrow=False) assert_array_equal(result.df[0]["111"], data_111) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_var_multi_attr_df(self): uri = self.path("test_var_multi_attr_df") dom = tiledb.Domain( @@ -845,7 +845,7 @@ def test_multi_index_open_timestamp_with_empty_nonempty_domain(self): assert A.nonempty_domain() is None assert_array_equal(A.multi_index[:][""], A[:][""]) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_multi_index_query_args(self): uri = self.path("test_multi_index_query_args") schema = tiledb.ArraySchema( @@ -871,7 +871,7 @@ def test_multi_index_query_args(self): assert_array_equal(q.multi_index[:]["a"], q.df[:]["a"]) assert all(q[:]["a"] >= 5) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_multi_index_timing(self): path = self.path("test_multi_index_timing") attr_name = "a" @@ -886,7 +886,7 @@ def test_multi_index_timing(self): assert "py.getitem_time.pandas_index_update_time :" in internal_stats tiledb.stats_disable() - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_fixed_width_char(self): uri = self.path("test_fixed_width_char") schema = tiledb.ArraySchema( @@ -903,7 +903,7 @@ def test_fixed_width_char(self): with tiledb.open(uri, mode="r") as A: assert all(A.query(use_arrow=True).df[:][""] == data) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_empty_idx(self): uri = self.path("test_empty_idx") diff --git a/tiledb/tests/test_pandas_dataframe.py b/tiledb/tests/test_pandas_dataframe.py index 9812b12eb8..67e6dfdcb4 100644 --- a/tiledb/tests/test_pandas_dataframe.py +++ b/tiledb/tests/test_pandas_dataframe.py @@ -29,7 +29,7 @@ from .datatypes import RaggedDtype if not has_pandas(): - pytest.skip("pandas>=1.0,<3.0 not installed", allow_module_level=True) + pytest.skip("pandas not installed", allow_module_level=True) else: import pandas as pd diff --git a/tiledb/tests/test_query_condition.py b/tiledb/tests/test_query_condition.py index 7caa7966ae..550d5300af 100644 --- a/tiledb/tests/test_query_condition.py +++ b/tiledb/tests/test_query_condition.py @@ -615,7 +615,7 @@ def test_not_supported_operators(self, expression_and_message, sparse): with self.assertRaisesRegex(tiledb.TileDBError, message): A.query(cond=expression)[:] - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_dense_datetime(self): import pandas as pd @@ -808,7 +808,7 @@ def test_attribute_with_dot(self): result = A.query(cond='attr("at.tr.thr.ee") in [1, 2, 3]')[:] assert_array_equal(result["at.tr.thr.ee"], A[1:4]["at.tr.thr.ee"]) - @pytest.mark.skipif(not has_pandas(), reason="pandas>=1.0,<3.0 not installed") + @pytest.mark.skipif(not has_pandas(), reason="pandas not installed") def test_do_not_return_attrs(self): with tiledb.open(self.create_input_array_UIDSA(sparse=True)) as A: cond = None From 1348fb511ba46dc24e8cbe648d267d60bc99a32e Mon Sep 17 00:00:00 2001 From: Agisilaos Kounelis Date: Thu, 5 Feb 2026 19:03:29 +0200 Subject: [PATCH 6/9] Add step to re-run tests with pandas 2 in CI --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5802d7fda1..9884102931 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -156,6 +156,13 @@ jobs: cd $RUNNER_TEMP pytest -vv --showlocals $PROJECT_CWD + - name: "Re-run tests with pandas 2" + run: | + PROJECT_CWD=$PWD + pip install "pandas>=2,<3" + cd $RUNNER_TEMP + pytest -vv --showlocals $PROJECT_CWD + - name: "Re-run tests without pandas" run: | PROJECT_CWD=$PWD From c3bde10eb3b4e068d97e4b63dc64c1e631f8607c Mon Sep 17 00:00:00 2001 From: Agisilaos Kounelis Date: Thu, 5 Feb 2026 20:22:40 +0200 Subject: [PATCH 7/9] Easy fixes --- tiledb/dataframe_.py | 7 +++++++ tiledb/tests/test_pandas_dataframe.py | 8 +++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tiledb/dataframe_.py b/tiledb/dataframe_.py index 10539e94ca..4f9d3afd78 100644 --- a/tiledb/dataframe_.py +++ b/tiledb/dataframe_.py @@ -17,12 +17,19 @@ def check_dataframe_deps(): pd_error = """Pandas is required for dataframe functionality. Please `pip install pandas` to proceed.""" + pa_error = """PyArrow is suggested for dataframe functionality. + Please `pip install pyarrow`.""" try: import pandas except ImportError: raise Exception(pd_error) + try: + import pyarrow + except ImportError: + warnings.warn(pa_error) + # Note: 'None' is used to indicate optionality for many of these options # For example, if the `sparse` argument is unspecified we will default diff --git a/tiledb/tests/test_pandas_dataframe.py b/tiledb/tests/test_pandas_dataframe.py index 67e6dfdcb4..144abe98b3 100644 --- a/tiledb/tests/test_pandas_dataframe.py +++ b/tiledb/tests/test_pandas_dataframe.py @@ -204,12 +204,10 @@ def test_implemented(self, type_specs, info_dtype, info_repr, info_nullable): def test_object_dtype(self): self.assertColumnInfo( - ColumnInfo.from_values(pd.Series(["hello", "world"], dtype=object)), - np.dtype(" Date: Thu, 5 Feb 2026 20:29:46 +0200 Subject: [PATCH 8/9] Comment --- tiledb/multirange_indexing.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tiledb/multirange_indexing.py b/tiledb/multirange_indexing.py index bf66f7b251..2f2fe8fc49 100644 --- a/tiledb/multirange_indexing.py +++ b/tiledb/multirange_indexing.py @@ -890,11 +890,16 @@ def _update_df_from_meta( col_dtypes[name] = dtype if col_dtypes: - # Use str instead of ''). Applying astype(' Date: Fri, 6 Feb 2026 00:44:59 +0200 Subject: [PATCH 9/9] Remove `copy` arg --- tiledb/multirange_indexing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiledb/multirange_indexing.py b/tiledb/multirange_indexing.py index 2f2fe8fc49..72cfb67bc9 100644 --- a/tiledb/multirange_indexing.py +++ b/tiledb/multirange_indexing.py @@ -899,7 +899,7 @@ def _update_df_from_meta( name: dtype for name, dtype in col_dtypes.items() if dtype != "