Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .coverage
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ venv/
*.pyc
__pycache__
.pytest_cache/
.coverage
*.lock
examples/rag/README.md
77 changes: 77 additions & 0 deletions tests/test_bit.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,80 @@ def test_repr(self):
def test_equality(self):
assert Bit([True, False, True]) == Bit([True, False, True])
assert Bit([True, False, True]) != Bit([True, False, False])

def test_equality_with_different_type(self):
assert Bit([True, False, True]) != [True, False, True]
assert Bit([True, False, True]) != "not a bit"
assert Bit([True, False, True]) != None

def test_length(self):
assert len(Bit([True, False, True]).to_list()) == 3
assert len(Bit('10101010').to_list()) == 8

def test_to_text(self):
assert Bit([True, False, True]).to_text() == '101'
assert Bit('10101010').to_text() == '10101010'

def test_from_text(self):
bit = Bit.from_text('101')
assert bit.to_list() == [True, False, True]

def test_to_binary(self):
bit = Bit([True, False, True])
binary = bit.to_binary()
assert isinstance(binary, bytes)
assert len(binary) > 0

def test_from_binary(self):
bit = Bit([True, False, True, False, True, False, True, False])
binary = bit.to_binary()
restored = Bit.from_binary(binary)
assert restored == bit

def test_from_binary_error(self):
with pytest.raises(ValueError, match='expected bytes'):
Bit.from_binary('not bytes')

def test_to_db(self):
bit = Bit([True, False, True])
assert Bit._to_db(bit) == '101'

def test_to_db_error(self):
with pytest.raises(ValueError, match='expected bit'):
Bit._to_db([True, False, True])

def test_to_db_binary(self):
bit = Bit([True, False, True])
result = Bit._to_db_binary(bit)
assert isinstance(result, bytes)

def test_to_db_binary_error(self):
with pytest.raises(ValueError, match='expected bit'):
Bit._to_db_binary([True, False, True])

def test_empty_bit(self):
bit = Bit([])
assert bit.to_list() == []
assert bit.to_text() == ''

def test_single_bit(self):
bit = Bit([True])
assert bit.to_list() == [True]
assert bit.to_text() == '1'

def test_bytes_constructor(self):
bit = Bit(b'\x01')
assert len(bit.to_list()) == 8
assert bit.to_text() == '00000001'

def test_roundtrip_text(self):
original = Bit('10110011')
text = original.to_text()
restored = Bit.from_text(text)
assert restored == original

def test_roundtrip_binary(self):
original = Bit([True, False, True, True, False, False, True, True])
binary = original.to_binary()
restored = Bit.from_binary(binary)
assert restored == original
77 changes: 77 additions & 0 deletions tests/test_half_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ def test_equality(self):
assert HalfVector([1, 2, 3]) == HalfVector([1, 2, 3])
assert HalfVector([1, 2, 3]) != HalfVector([1, 2, 4])

def test_equality_with_different_type(self):
assert HalfVector([1, 2, 3]) != [1, 2, 3]
assert HalfVector([1, 2, 3]) != "not a vector"
assert HalfVector([1, 2, 3]) != None

def test_dimensions(self):
assert HalfVector([1, 2, 3]).dimensions() == 3

Expand All @@ -57,3 +62,75 @@ def test_from_binary(self):
assert vec.to_list() == [1.5, 2, 3]
assert np.array_equal(vec.to_numpy(), [1.5, 2, 3])
assert vec.to_binary() == data

def test_to_text(self):
vec = HalfVector([1, 2, 3])
assert vec.to_text() == '[1.0,2.0,3.0]'

def test_to_db_none(self):
assert HalfVector._to_db(None) is None

def test_to_db_vector(self):
vec = HalfVector([1, 2, 3])
assert HalfVector._to_db(vec) == '[1.0,2.0,3.0]'

def test_to_db_list(self):
assert HalfVector._to_db([1, 2, 3]) == '[1.0,2.0,3.0]'

def test_to_db_with_dim(self):
assert HalfVector._to_db([1, 2, 3], 3) == '[1.0,2.0,3.0]'

def test_to_db_wrong_dim(self):
with pytest.raises(ValueError, match='expected 3 dimensions, not 2'):
HalfVector._to_db([1, 2], 3)

def test_to_db_binary_none(self):
assert HalfVector._to_db_binary(None) is None

def test_to_db_binary_vector(self):
vec = HalfVector([1, 2, 3])
result = HalfVector._to_db_binary(vec)
assert result == pack('>HH3e', 3, 0, 1, 2, 3)

def test_to_db_binary_list(self):
result = HalfVector._to_db_binary([1, 2, 3])
assert result == pack('>HH3e', 3, 0, 1, 2, 3)

def test_from_db_none(self):
assert HalfVector._from_db(None) is None

def test_from_db_halfvector(self):
vec = HalfVector([1, 2, 3])
assert HalfVector._from_db(vec) is vec

def test_from_db_text(self):
result = HalfVector._from_db('[1.5,2,3]')
assert isinstance(result, HalfVector)
assert result.to_list() == [1.5, 2, 3]

def test_from_db_binary_none(self):
assert HalfVector._from_db_binary(None) is None

def test_from_db_binary_halfvector(self):
vec = HalfVector([1, 2, 3])
assert HalfVector._from_db_binary(vec) is vec

def test_from_db_binary_bytes(self):
data = pack('>HH3e', 3, 0, 1.5, 2, 3)
result = HalfVector._from_db_binary(data)
assert isinstance(result, HalfVector)
assert result.to_list() == [1.5, 2, 3]

def test_empty_vector(self):
vec = HalfVector([])
assert vec.dimensions() == 0
assert vec.to_list() == []

def test_single_element(self):
vec = HalfVector([42])
assert vec.dimensions() == 1
assert vec.to_list() == [42]

def test_negative_values(self):
vec = HalfVector([-1, -2, -3])
assert vec.to_list() == [-1, -2, -3]
101 changes: 101 additions & 0 deletions tests/test_sparse_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ def test_csr_matrix(self):
assert vec.to_list() == [1, 0, 2, 0, 3, 0]
assert vec.indices() == [0, 2, 4]

def test_sparse_array_wrong_ndim(self):
# 2D array with wrong ndim (not 1D as required)
arr = coo_array(np.array([[1, 0, 2], [0, 3, 0]]))
with pytest.raises(ValueError, match='expected ndim to be 1'):
SparseVector(arr)

def test_repr(self):
assert repr(SparseVector([1, 0, 2, 0, 3, 0])) == 'SparseVector({0: 1.0, 2: 2.0, 4: 3.0}, 6)'
assert str(SparseVector([1, 0, 2, 0, 3, 0])) == 'SparseVector({0: 1.0, 2: 2.0, 4: 3.0}, 6)'
Expand All @@ -77,6 +83,11 @@ def test_equality(self):
assert SparseVector([1, 0, 2, 0, 3, 0]) == SparseVector({2: 2, 4: 3, 0: 1, 3: 0}, 6)
assert SparseVector({}, 1) != SparseVector({}, 2)

def test_equality_with_different_type(self):
assert SparseVector([1, 0, 2, 0, 3, 0]) != [1, 0, 2, 0, 3, 0]
assert SparseVector([1, 0, 2, 0, 3, 0]) != "not a sparse vector"
assert SparseVector([1, 0, 2, 0, 3, 0]) != None

def test_dimensions(self):
assert SparseVector([1, 0, 2, 0, 3, 0]).dimensions() == 6

Expand Down Expand Up @@ -110,3 +121,93 @@ def test_from_binary(self):
assert vec.to_list() == [1.5, 0, 2, 0, 3, 0]
assert np.array_equal(vec.to_numpy(), [1.5, 0, 2, 0, 3, 0])
assert vec.to_binary() == data

def test_to_text(self):
vec = SparseVector([1, 0, 2, 0, 3, 0])
assert vec.to_text() == '{1:1.0,3:2.0,5:3.0}/6'

def test_to_db_none(self):
assert SparseVector._to_db(None) is None

def test_to_db_vector(self):
vec = SparseVector([1, 0, 2, 0, 3, 0])
assert SparseVector._to_db(vec) == '{1:1.0,3:2.0,5:3.0}/6'

def test_to_db_list(self):
result = SparseVector._to_db([1, 0, 2, 0, 3, 0])
assert result == '{1:1.0,3:2.0,5:3.0}/6'

def test_to_db_with_dim(self):
result = SparseVector._to_db([1, 0, 2, 0, 3, 0], 6)
assert result == '{1:1.0,3:2.0,5:3.0}/6'

def test_to_db_wrong_dim(self):
with pytest.raises(ValueError, match='expected 6 dimensions, not 5'):
SparseVector._to_db([1, 0, 2, 0, 3], 6)

def test_to_db_binary_none(self):
assert SparseVector._to_db_binary(None) is None

def test_to_db_binary_vector(self):
vec = SparseVector([1, 0, 2, 0, 3, 0])
result = SparseVector._to_db_binary(vec)
assert isinstance(result, bytes)

def test_to_db_binary_list(self):
result = SparseVector._to_db_binary([1, 0, 2, 0, 3, 0])
assert isinstance(result, bytes)

def test_from_db_none(self):
assert SparseVector._from_db(None) is None

def test_from_db_sparsevector(self):
vec = SparseVector([1, 0, 2, 0, 3, 0])
assert SparseVector._from_db(vec) is vec

def test_from_db_text(self):
result = SparseVector._from_db('{1:1.5,3:2,5:3}/6')
assert isinstance(result, SparseVector)
assert result.to_list() == [1.5, 0, 2, 0, 3, 0]

def test_from_db_binary_none(self):
assert SparseVector._from_db_binary(None) is None

def test_from_db_binary_sparsevector(self):
vec = SparseVector([1, 0, 2, 0, 3, 0])
assert SparseVector._from_db_binary(vec) is vec

def test_from_db_binary_bytes(self):
data = pack('>iii3i3f', 6, 3, 0, 0, 2, 4, 1.5, 2, 3)
result = SparseVector._from_db_binary(data)
assert isinstance(result, SparseVector)
assert result.to_list() == [1.5, 0, 2, 0, 3, 0]

def test_empty_sparse_vector(self):
vec = SparseVector({}, 5)
assert vec.dimensions() == 5
assert vec.indices() == []
assert vec.values() == []
assert vec.to_list() == [0, 0, 0, 0, 0]

def test_single_nonzero(self):
vec = SparseVector({3: 42}, 10)
assert vec.dimensions() == 10
assert vec.indices() == [3]
assert vec.values() == [42]

def test_negative_values_sparse(self):
vec = SparseVector([-1, 0, -2, 0, -3])
assert vec.values() == [-1, -2, -3]
assert vec.to_list() == [-1, 0, -2, 0, -3]

def test_roundtrip_text_sparse(self):
original = SparseVector([1.5, 0, 2.5, 0, 3.5, 0])
text = original.to_text()
restored = SparseVector.from_text(text)
assert restored == original

def test_roundtrip_binary_sparse(self):
original = SparseVector([1.5, 0, 2.5, 0, 3.5, 0])
binary = original.to_binary()
restored = SparseVector.from_binary(binary)
assert restored == original
85 changes: 85 additions & 0 deletions tests/test_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ def test_equality(self):
assert Vector([1, 2, 3]) == Vector([1, 2, 3])
assert Vector([1, 2, 3]) != Vector([1, 2, 4])

def test_equality_with_different_type(self):
assert Vector([1, 2, 3]) != [1, 2, 3]
assert Vector([1, 2, 3]) != "not a vector"
assert Vector([1, 2, 3]) != None

def test_dimensions(self):
assert Vector([1, 2, 3]).dimensions() == 3

Expand All @@ -57,3 +62,83 @@ def test_from_binary(self):
assert vec.to_list() == [1.5, 2, 3]
assert np.array_equal(vec.to_numpy(), [1.5, 2, 3])
assert vec.to_binary() == data

def test_to_text(self):
vec = Vector([1, 2, 3])
assert vec.to_text() == '[1.0,2.0,3.0]'

def test_to_db_none(self):
assert Vector._to_db(None) is None

def test_to_db_vector(self):
vec = Vector([1, 2, 3])
assert Vector._to_db(vec) == '[1.0,2.0,3.0]'

def test_to_db_list(self):
assert Vector._to_db([1, 2, 3]) == '[1.0,2.0,3.0]'

def test_to_db_with_dim(self):
assert Vector._to_db([1, 2, 3], 3) == '[1.0,2.0,3.0]'

def test_to_db_wrong_dim(self):
with pytest.raises(ValueError, match='expected 3 dimensions, not 2'):
Vector._to_db([1, 2], 3)

def test_to_db_binary_none(self):
assert Vector._to_db_binary(None) is None

def test_to_db_binary_vector(self):
vec = Vector([1, 2, 3])
result = Vector._to_db_binary(vec)
assert result == pack('>HH3f', 3, 0, 1, 2, 3)

def test_to_db_binary_list(self):
result = Vector._to_db_binary([1, 2, 3])
assert result == pack('>HH3f', 3, 0, 1, 2, 3)

def test_from_db_none(self):
assert Vector._from_db(None) is None

def test_from_db_ndarray(self):
arr = np.array([1, 2, 3], dtype=np.float32)
assert Vector._from_db(arr) is arr

def test_from_db_text(self):
result = Vector._from_db('[1.5,2,3]')
expected = np.array([1.5, 2, 3], dtype=np.float32)
assert np.array_equal(result, expected)

def test_from_db_binary_none(self):
assert Vector._from_db_binary(None) is None

def test_from_db_binary_ndarray(self):
arr = np.array([1, 2, 3], dtype=np.float32)
assert Vector._from_db_binary(arr) is arr

def test_from_db_binary_bytes(self):
data = pack('>HH3f', 3, 0, 1.5, 2, 3)
result = Vector._from_db_binary(data)
expected = np.array([1.5, 2, 3], dtype=np.float32)
assert np.array_equal(result, expected)

def test_empty_vector(self):
vec = Vector([])
assert vec.dimensions() == 0
assert vec.to_list() == []

def test_single_element(self):
vec = Vector([42])
assert vec.dimensions() == 1
assert vec.to_list() == [42]

def test_negative_values(self):
vec = Vector([-1, -2, -3])
assert vec.to_list() == [-1, -2, -3]

def test_float_precision(self):
vec = Vector([1.123456789, 2.987654321])
# Float32 precision test
result = vec.to_list()
assert len(result) == 2
assert abs(result[0] - 1.123456789) < 1e-6
assert abs(result[1] - 2.987654321) < 1e-6