Files
qdrant-client/tests/test_serverless.py
qdrant-cloud-bot 75bdd8edcc feat(serverless): sync collections API pagination and text options
Align with the latest public-api collections.proto: paginated
ListCollections (limit/offset_token/next_offset_token) plus keyword
prefix and text analysis fields (stopwords, stemmer, ascii_folding).
2026-09-15 07:35:03 +02:00

100 lines
3.6 KiB
Python

import inspect
from qdrant_client.serverless.models import (
CollectionConfig,
DenseVectorConfig,
Distance,
IntegerIndex,
KeywordIndex,
KeywordPrefixParams,
PrecisionTier,
SnowballParams,
SparseVectorConfig,
StemmingAlgorithm,
StopwordsSet,
TextIndex,
TokenizerType,
)
from qdrant_client.serverless import AsyncQdrantServerless, QdrantServerless
from qdrant_client.serverless.conversions import (
collection_config_from_grpc,
collection_config_to_grpc,
)
def test_collection_config_grpc_roundtrip() -> None:
config = CollectionConfig(
dense_vectors={
"": DenseVectorConfig(size=1536, distance=Distance.COSINE),
"colbert": DenseVectorConfig(
size=128,
distance=Distance.DOT,
multivector=True,
precision_tier=PrecisionTier.LOW,
),
},
sparse_vectors={"bm25": SparseVectorConfig(use_idf=True)},
payload_indexes={
"user_id": KeywordIndex(prefix=KeywordPrefixParams()),
"age": IntegerIndex(lookup=True, range=False),
"description": TextIndex(
tokenizer=TokenizerType.WORD,
lowercase=False,
ascii_folding=True,
stopwords=StopwordsSet(languages=["english"]),
stemmer=StemmingAlgorithm(snowball=SnowballParams(language="english")),
),
},
)
assert collection_config_from_grpc(collection_config_to_grpc(config)) == config
def test_optional_fields_stay_unset() -> None:
config = CollectionConfig(
dense_vectors={"": DenseVectorConfig(size=4, distance=Distance.EUCLID)},
payload_indexes={
"age": IntegerIndex(),
"user_id": KeywordIndex(),
"text": TextIndex(),
},
)
grpc_config = collection_config_to_grpc(config)
assert not grpc_config.dense_vectors[""].HasField("precision_tier")
assert not grpc_config.payload_indexes["age"].integer.HasField("lookup")
assert not grpc_config.payload_indexes["user_id"].keyword.HasField("prefix")
assert not grpc_config.payload_indexes["text"].text.HasField("tokenizer")
assert not grpc_config.payload_indexes["text"].text.HasField("ascii_folding")
assert not grpc_config.payload_indexes["text"].text.HasField("stopwords")
assert not grpc_config.payload_indexes["text"].text.HasField("stemmer")
assert collection_config_from_grpc(grpc_config) == config
def test_client_construction_is_offline() -> None:
client = QdrantServerless(url="https://serverless.example.qdrant.io", api_key="secret")
assert ("api-key", "secret") in client._remote._grpc_headers
assert client._remote._grpc_port == 443
assert client._remote._https
client.close()
def test_async_client_mirrors_sync_client() -> None:
sync_methods = {
name
for name, _ in inspect.getmembers(QdrantServerless, predicate=inspect.isfunction)
if not name.startswith("__")
}
async_methods = {
name
for name, _ in inspect.getmembers(AsyncQdrantServerless, predicate=inspect.isfunction)
if not name.startswith("__")
}
assert sync_methods == async_methods
for name in async_methods:
if name.startswith("_"):
continue
assert inspect.iscoroutinefunction(getattr(AsyncQdrantServerless, name)), name
client = AsyncQdrantServerless(url="https://serverless.example.qdrant.io", api_key="secret")
assert ("api-key", "secret") in client._remote._grpc_headers
assert client._remote._grpc_port == 443