diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..b25b309 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,9 @@ +# Release Build Instructions + +To build and publish the PyPI package: + +1. `python -m pip install --upgrade build` +1. `python -m pip install --upgrade twine` +1. `rm -rf dist/` +2. `python -m build` +3. `python -m twine upload dist/*` \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 65504bd..4c8ca7b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "turbopuffer" -version = "0.1.1" +version = "0.1.2" description = "Python Client for accessing the turbopuffer API" authors = ["turbopuffer Inc. "] maintainers = ["Jacob Wirth"] diff --git a/tests/test_vectors.py b/tests/test_vectors.py index 0dd6a88..6cee72c 100644 --- a/tests/test_vectors.py +++ b/tests/test_vectors.py @@ -64,7 +64,7 @@ def test_delete_vectors(): ns.upsert([tpuf.VectorRow(id=2)]) assert False, "Upserting to delete should not be allowed" except ValueError as err: - assert err.args == ('VectorRow.vector cannot be None, use Namespace.delete([ids...]) instead.',) + assert err.args == ('upsert() call would result in a vector deletion, use Namespace.delete([ids...]) instead.',) try: ns.upsert([tpuf.VectorRow(id=2, dist=5)]) @@ -77,7 +77,7 @@ def test_delete_vectors(): ns.upsert([{'id': 6}]) assert False, "Upserting to delete should not be allowed" except ValueError as err: - assert err.args == ('VectorRow.vector cannot be None, use Namespace.delete([ids...]) instead.',) + assert err.args == ('upsert() call would result in a vector deletion, use Namespace.delete([ids...]) instead.',) # Test delete single row ns.delete(2) @@ -155,11 +155,15 @@ def check_result(row, expected): assert row.id == expected.id assert row.attributes == expected.attributes if isinstance(expected.vector, list): + assert isinstance(row.vector, list) assert abs(row.vector[0] - expected.vector[0]) < 0.000001 assert abs(row.vector[1] - expected.vector[1]) < 0.000001 else: assert row.vector == expected.vector - assert abs(row.dist - expected.dist) < 0.000001 + if isinstance(expected.dist, float): + assert abs(row.dist - expected.dist) < 0.000001 + else: + assert row.dist == expected.dist expected = [ tpuf.VectorRow(id=7, vector=[0.7, 0.7], attributes={'hello': 'world'}, dist=0.01), @@ -209,6 +213,22 @@ def check_result(row, expected): check_result(row, expected[i]) i += 1 + # Test query with no vectors + expected = [ + tpuf.VectorRow(id=10), + tpuf.VectorRow(id=11), + tpuf.VectorRow(id=12), + ] + vector_set = ns.query( + top_k=3, + include_vectors=False, + filters={ + 'id': [['In', [10, 11, 12]]] + }, + ) + for i in range(len(vector_set)): # Use VectorResult in index mode + check_result(vector_set[i], expected[i]) + def test_list_vectors(): ns = tpuf.Namespace('client_test') diff --git a/turbopuffer/namespace.py b/turbopuffer/namespace.py index 01ab82d..8a3f079 100644 --- a/turbopuffer/namespace.py +++ b/turbopuffer/namespace.py @@ -14,6 +14,13 @@ class Namespace: backend: Backend def __init__(self, name: str, api_key: Optional[str] = None): + """ + Creates a new turbopuffer.Namespace object for querying the turbopuffer API. + + This function does not make any API calls on its own. + + Specifying an api_key here will override the global configuration for API calls to this namespace. + """ self.name = name self.backend = Backend(api_key) diff --git a/turbopuffer/vectors.py b/turbopuffer/vectors.py index 2fcd911..f58fdf9 100644 --- a/turbopuffer/vectors.py +++ b/turbopuffer/vectors.py @@ -37,9 +37,7 @@ class _(JSONSerializable.Meta): def __post_init__(self): if not isinstance(self.id, int): raise ValueError('VectorRow.id must be an int, got:', type(self.id)) - if self.vector is None and self.dist is None: - raise ValueError('VectorRow.vector cannot be None, use Namespace.delete([ids...]) instead.') - if not isinstance(self.vector, list) and self.dist is None: + if self.vector is not None and not isinstance(self.vector, list): raise ValueError('VectorRow.vector must be a list, got:', type(self.vector)) if self.attributes is not None and not isinstance(self.attributes, dict): raise ValueError('VectorRow.attributes must be a dict, got:', type(self.attributes)) diff --git a/turbopuffer/version.py b/turbopuffer/version.py index 8d76f25..856ce1d 100644 --- a/turbopuffer/version.py +++ b/turbopuffer/version.py @@ -1 +1 @@ -VERSION = '0.1.1' +VERSION = '0.1.2'