Skip to content

Commit 3112762

Browse files
committed
fix(sparsevec): reject non-1D NumPy arrays with ValueError
SparseVector._from_dense only checked ndim for scipy inputs. 2D arrays raised a raw TypeError from float(), and (n, 1) column arrays were silently accepted as n-dimensional vectors, unlike Vector, HalfVector and Bit which raise 'expected ndim to be 1'.
1 parent d2ace87 commit 3112762

3 files changed

Lines changed: 14 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- Fixed memory leak with `register_vector` and `register_vector_async` for Psycopg 3
44
- Fixed error with `Bit` constructor and empty strings
55
- Fixed equality for `HalfVector` with signed zeros
6+
- Fixed error type for multi-dimensional NumPy arrays with `SparseVector` constructor
67

78
## 0.5.1 (2026-10-08)
89

‎pgvector/sparsevec.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22
from struct import pack, unpack_from
33
from typing import TYPE_CHECKING, Final, cast, overload
4-
from ._utils import is_sparse_array, ndarray
4+
from ._utils import is_ndarray, is_sparse_array, ndarray
55

66
if TYPE_CHECKING:
77
import numpy as np
@@ -136,6 +136,9 @@ def _from_sparse(self, arr: sparray | spmatrix, /) -> None:
136136
self._values = [float(v[1]) for v in elements]
137137

138138
def _from_dense(self, value: list[float] | ndarray, /) -> None:
139+
if is_ndarray(value) and value.ndim != 1:
140+
raise ValueError('expected ndim to be 1')
141+
139142
self._dim = len(value)
140143
self._indices = []
141144
self._values = []

‎tests/test_sparse_vector.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ def test_init_ndarray(self) -> None:
3737
assert vec.to_list() == [1, 0, 2, 0, 3, 0]
3838
assert vec.indices() == [0, 2, 4]
3939

40+
def test_init_ndarray_ndim(self) -> None:
41+
if np is None:
42+
pytest.skip('NumPy required')
43+
44+
for arr in (np.zeros((2, 2)), np.array([[1], [0], [2]]), np.array(5.0)):
45+
with pytest.raises(ValueError) as error:
46+
SparseVector(arr)
47+
assert str(error.value) == 'expected ndim to be 1'
48+
4049
def test_init_dict(self) -> None:
4150
vec = SparseVector({2: 2, 4: 3, 0: 1, 3: 0}, 6)
4251
assert vec.to_list() == [1, 0, 2, 0, 3, 0]

0 commit comments

Comments
 (0)