diff --git a/CHANGELOG.md b/CHANGELOG.md index f033cf1..2251938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Fixed memory leak with `register_vector` and `register_vector_async` for Psycopg 3 - Fixed error with `Bit` constructor and empty strings - Fixed equality for `HalfVector` with signed zeros +- Fixed error type for multi-dimensional NumPy arrays with `SparseVector` constructor ## 0.5.1 (2026-10-08) diff --git a/pgvector/sparsevec.py b/pgvector/sparsevec.py index 76e1356..7cc2a85 100644 --- a/pgvector/sparsevec.py +++ b/pgvector/sparsevec.py @@ -1,7 +1,7 @@ from __future__ import annotations from struct import pack, unpack_from from typing import TYPE_CHECKING, Final, cast, overload -from ._utils import is_sparse_array, ndarray +from ._utils import is_ndarray, is_sparse_array, ndarray if TYPE_CHECKING: import numpy as np @@ -136,6 +136,9 @@ def _from_sparse(self, arr: sparray | spmatrix, /) -> None: self._values = [float(v[1]) for v in elements] def _from_dense(self, value: list[float] | ndarray, /) -> None: + if is_ndarray(value) and value.ndim != 1: + raise ValueError('expected ndim to be 1') + self._dim = len(value) self._indices = [] self._values = [] diff --git a/tests/test_sparse_vector.py b/tests/test_sparse_vector.py index e3bb8cc..4ffeaa9 100644 --- a/tests/test_sparse_vector.py +++ b/tests/test_sparse_vector.py @@ -37,6 +37,15 @@ def test_init_ndarray(self) -> None: assert vec.to_list() == [1, 0, 2, 0, 3, 0] assert vec.indices() == [0, 2, 4] + def test_init_ndarray_ndim(self) -> None: + if np is None: + pytest.skip('NumPy required') + + for arr in (np.zeros((2, 2)), np.array([[1], [0], [2]]), np.array(5.0)): + with pytest.raises(ValueError) as error: + SparseVector(arr) + assert str(error.value) == 'expected ndim to be 1' + def test_init_dict(self) -> None: vec = SparseVector({2: 2, 4: 3, 0: 1, 3: 0}, 6) assert vec.to_list() == [1, 0, 2, 0, 3, 0]