From 2ac93b8d41d6e794652752b62878e55c39e88ce6 Mon Sep 17 00:00:00 2001 From: ktz03 <2484593937@qq.com> Date: Mon, 19 Oct 2026 15:01:41 +0800 Subject: [PATCH] FIX Preserve the shape of empty object arrays --- docs/changes.rst | 2 ++ skops/io/_numpy.py | 3 +++ skops/io/tests/test_persist.py | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/docs/changes.rst b/docs/changes.rst index 4db24835..2a2b9afb 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -11,6 +11,8 @@ skops Changelog v0.17 ----- +- Fix loading empty NumPy object arrays: the recorded shape is preserved even + when a zero-length axis hides later dimensions from the nested list. - Loading a skops file now checks that each part of the file holds the kind of content its loader expects, for instance that the keyword arguments of a ``functools.partial`` are stored as a dict. A file that does not is refused diff --git a/skops/io/_numpy.py b/skops/io/_numpy.py index 1b9d6681..db38503b 100644 --- a/skops/io/_numpy.py +++ b/skops/io/_numpy.py @@ -110,6 +110,9 @@ def _construct(self): shape = self.shape.construct() tmp = [o.construct() for o in self.items] + if 0 in shape: + return np.empty(shape, dtype="O") + # TODO: this is a hack to get the correct shape of the array. We # should find _a better way_ to do this. if len(shape) == 1: diff --git a/skops/io/tests/test_persist.py b/skops/io/tests/test_persist.py index 6df4be7d..edb5e4ad 100644 --- a/skops/io/tests/test_persist.py +++ b/skops/io/tests/test_persist.py @@ -789,6 +789,25 @@ def test_numpy_object_dtype_2d_array(transpose): assert_params_equal(est.__dict__, loaded.__dict__) +@pytest.mark.parametrize( + "shape", [(0,), (0, 3), (2, 0), (2, 0, 3), (2, 3, 0), (0, 2, 3), (2, 3)] +) +@pytest.mark.parametrize("use_file", [False, True]) +def test_numpy_object_dtype_empty_array(shape, use_file, tmp_path): + arr = np.full(shape, "value", dtype=object) + + if use_file: + path = tmp_path / "array.skops" + dump(arr, path) + loaded = load(path) + else: + loaded = loads(dumps(arr)) + + assert loaded.shape == shape + assert loaded.dtype == arr.dtype + np.testing.assert_array_equal(loaded, arr) + + def test_metainfo(): class MyEstimator(BaseEstimator): """Estimator with attributes of different supported types"""