From c2a661869fcf2b9d263ac6859e4975f992802f31 Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Thu, 22 Oct 2026 01:21:59 +0800 Subject: [PATCH 1/2] fix(utils): preserve explicit zero slice stops --- ggml/utils.py | 5 ++- tests/test_slice_tensor_empty.py | 60 ++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/test_slice_tensor_empty.py diff --git a/ggml/utils.py b/ggml/utils.py index 79695e5d..310236d2 100644 --- a/ggml/utils.py +++ b/ggml/utils.py @@ -319,7 +319,10 @@ def slice_tensor( # calculate slice start = tuple(idx.start or 0 for idx in indices) - end = tuple(idx.stop or get_shape(tensor)[i] for i, idx in enumerate(indices)) + end = tuple( + idx.stop if idx.stop is not None else get_shape(tensor)[i] + for i, idx in enumerate(indices) + ) step = tuple(idx.step or 1 for idx in indices) # get the shape of the slice diff --git a/tests/test_slice_tensor_empty.py b/tests/test_slice_tensor_empty.py new file mode 100644 index 00000000..34f7f68b --- /dev/null +++ b/tests/test_slice_tensor_empty.py @@ -0,0 +1,60 @@ +import importlib.util +import sys +import types +from pathlib import Path +from types import SimpleNamespace + + +def test_slice_tensor_preserves_explicit_zero_stop(monkeypatch): + # Exercise the Python wrapper without loading a native ggml shared library. + fake_ggml = types.ModuleType("ggml.ggml") + type_names = ( + "F32", + "F16", + "Q4_0", + "Q4_1", + "Q5_0", + "Q5_1", + "Q8_0", + "Q8_1", + "Q2_K", + "Q3_K", + "Q4_K", + "Q5_K", + "Q6_K", + "Q8_K", + "I8", + "I16", + "I32", + "I64", + "F64", + "BF16", + ) + for value, name in enumerate(type_names): + setattr(fake_ggml, f"GGML_TYPE_{name}", value) + + fake_package = types.ModuleType("ggml") + fake_package.__path__ = [] + fake_package.ggml = fake_ggml + monkeypatch.setitem(sys.modules, "ggml", fake_package) + monkeypatch.setitem(sys.modules, "ggml.ggml", fake_ggml) + + utils_path = Path(__file__).resolve().parents[1] / "ggml" / "utils.py" + spec = importlib.util.spec_from_file_location("ggml_utils_slice_test", utils_path) + utils = importlib.util.module_from_spec(spec) + spec.loader.exec_module(utils) + + tensor = SimpleNamespace( + contents=SimpleNamespace(ne=[4, 1, 1, 1], nb=[4, 16, 16, 16]) + ) + fake_ggml.ggml_n_dims = lambda _: 1 + views = [] + + def view_1d(_, __, ne0, offset): + views.append((ne0, offset)) + return object() + + fake_ggml.ggml_view_1d = view_1d + utils.slice_tensor(None, tensor, [slice(0, 0)]) + + assert views == [(0, 0)] From 9dbaa1366a6354e8860bfa3d0842735dfc331ee9 Mon Sep 17 00:00:00 2001 From: dajiaohuang Date: Thu, 22 Oct 2026 01:23:49 +0800 Subject: [PATCH 2/2] docs: add slice fix to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e9e4215..392c4f50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - feat: add buffer protocol support to utils by @aisk in #175 +- fix(utils): preserve explicit zero slice stops by @dajiaohuang in #201 ## [0.0.45]