From d25f3a45523bb11fece05f88ca373216c3fc5f78 Mon Sep 17 00:00:00 2001 From: Cuiys Date: Wed, 24 Jun 2026 11:23:52 +0800 Subject: [PATCH] fix(python): install the _zvec extension inside the zvec package (#511) --- CMakeLists.txt | 10 +++++-- python/tests/test_convert.py | 2 +- python/tests/test_doc.py | 2 +- python/tests/test_fts_query.py | 12 ++++---- python/tests/test_params.py | 2 +- python/tests/test_query_executor.py | 2 +- python/zvec/__init__.py | 4 +-- python/zvec/executor/query_executor.py | 5 ++-- .../zvec/extension/multi_vector_reranker.py | 8 +++++- python/zvec/model/collection.py | 2 +- python/zvec/model/convert.py | 2 +- python/zvec/model/param/__init__.py | 2 +- python/zvec/model/param/__init__.pyi | 28 +++++++++---------- python/zvec/model/schema/__init__.py | 2 +- python/zvec/model/schema/__init__.pyi | 12 ++++---- python/zvec/model/schema/collection_schema.py | 2 +- python/zvec/model/schema/field_schema.py | 3 +- python/zvec/typing/__init__.py | 2 +- python/zvec/zvec.py | 2 +- 19 files changed, 57 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b79b3c..d334b85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,7 +174,10 @@ if(BUILD_PYTHON_BINDINGS) # COMPONENT python: only these runtime artifacts are pulled into the wheel # (see install.components in pyproject.toml). The cc_library(PACKED) SDK # install rules use the default component and are excluded from the wheel. - install(TARGETS _zvec LIBRARY DESTINATION ${ZVEC_PY_INSTALL_DIR} + # Install the extension inside the zvec package (zvec/_zvec*.so) rather than + # at the site-packages root, so it does not pollute the top-level namespace. + # The Python code imports it as `zvec._zvec` accordingly. + install(TARGETS _zvec LIBRARY DESTINATION ${ZVEC_PY_INSTALL_DIR}/zvec COMPONENT python) # DiskAnn ships as a runtime-loaded shared module @@ -182,7 +185,8 @@ if(BUILD_PYTHON_BINDINGS) # first time a DiskAnn index is created — users never call any load # function. The Python extension resolves the module next to _zvec.so # (see the $ORIGIN rpath in src/binding/python/CMakeLists.txt); the - # module must therefore be installed alongside _zvec.so in the wheel. + # module must therefore be installed alongside _zvec.so, i.e. inside the + # zvec package directory as well. # # Gate on DISKANN_SUPPORTED, not on the target's existence: on unsupported # platforms (e.g. macOS / ARM64) the core_knn_diskann target is still @@ -191,7 +195,7 @@ if(BUILD_PYTHON_BINDINGS) # (#if DISKANN_SUPPORTED). Shipping that stub is pure dead weight, so it is # only packaged where DiskAnn is real — currently Linux x86_64 with libaio. if(DISKANN_SUPPORTED) - install(TARGETS core_knn_diskann LIBRARY DESTINATION ${ZVEC_PY_INSTALL_DIR} + install(TARGETS core_knn_diskann LIBRARY DESTINATION ${ZVEC_PY_INSTALL_DIR}/zvec COMPONENT python) endif() # Bundle cppjieba's dictionary files so the `jieba` FTS tokenizer works diff --git a/python/tests/test_convert.py b/python/tests/test_convert.py index f30eada..2fac2f5 100644 --- a/python/tests/test_convert.py +++ b/python/tests/test_convert.py @@ -3,7 +3,7 @@ from __future__ import annotations import math import pytest -from _zvec import _Doc +from zvec._zvec import _Doc from zvec.model.convert import convert_to_py_doc, convert_to_cpp_doc from zvec import Doc, CollectionSchema, DataType, FieldSchema, VectorSchema diff --git a/python/tests/test_doc.py b/python/tests/test_doc.py index d4a60ff..ecfd31e 100644 --- a/python/tests/test_doc.py +++ b/python/tests/test_doc.py @@ -17,7 +17,7 @@ import math import pytest -from _zvec import _Doc +from zvec._zvec import _Doc from zvec import FieldSchema, VectorSchema, Doc, DataType diff --git a/python/tests/test_fts_query.py b/python/tests/test_fts_query.py index 16db8b4..e87c7c1 100644 --- a/python/tests/test_fts_query.py +++ b/python/tests/test_fts_query.py @@ -79,7 +79,7 @@ class TestFtsQueryBinding: def test_import_fts_query(self): """_Fts should be importable from _zvec.param.""" - from _zvec.param import _Fts + from zvec._zvec.param import _Fts fts = _Fts() assert fts.query_string == "" @@ -87,7 +87,7 @@ class TestFtsQueryBinding: def test_fts_query_set_fields(self): """Setting fields on _Fts should work.""" - from _zvec.param import _Fts + from zvec._zvec.param import _Fts fts = _Fts() fts.query_string = "+hello -world" @@ -99,7 +99,7 @@ class TestFtsQueryBinding: def test_fts_query_pickle(self): """_Fts should support pickling.""" - from _zvec.param import _Fts + from zvec._zvec.param import _Fts fts = _Fts() fts.query_string = "+vector search" @@ -112,7 +112,7 @@ class TestFtsQueryBinding: def test_search_query_fts_field(self): """_SearchQuery should have fts field.""" - from _zvec.param import _Fts, _SearchQuery + from zvec._zvec.param import _Fts, _SearchQuery vq = _SearchQuery() # fts should be None by default (optional) @@ -127,7 +127,7 @@ class TestFtsQueryBinding: def test_search_query_pickle_with_fts(self): """_SearchQuery with fts should survive pickling.""" - from _zvec.param import _Fts, _SearchQuery + from zvec._zvec.param import _Fts, _SearchQuery vq = _SearchQuery() vq.topk = 10 @@ -145,7 +145,7 @@ class TestFtsQueryBinding: def test_search_query_pickle_without_fts(self): """_SearchQuery without fts should survive pickling.""" - from _zvec.param import _SearchQuery + from zvec._zvec.param import _SearchQuery vq = _SearchQuery() vq.topk = 5 diff --git a/python/tests/test_params.py b/python/tests/test_params.py index 2d2ba27..728b305 100644 --- a/python/tests/test_params.py +++ b/python/tests/test_params.py @@ -40,7 +40,7 @@ from zvec import ( VectorSchema, ) -from _zvec.param import _SearchQuery +from zvec._zvec.param import _SearchQuery # ---------------------------- # Invert Index Param Test Case diff --git a/python/tests/test_query_executor.py b/python/tests/test_query_executor.py index 1d20e33..390da2d 100644 --- a/python/tests/test_query_executor.py +++ b/python/tests/test_query_executor.py @@ -18,7 +18,7 @@ from unittest.mock import MagicMock, patch import numpy as np import math -from _zvec.param import _SearchQuery +from zvec._zvec.param import _SearchQuery import pytest from zvec.executor.query_executor import ( diff --git a/python/zvec/__init__.py b/python/zvec/__init__.py index 5fdf973..cdb7fc0 100644 --- a/python/zvec/__init__.py +++ b/python/zvec/__init__.py @@ -28,7 +28,7 @@ if TYPE_CHECKING: try: from importlib.resources import files as _resource_files - from _zvec import ( + from zvec._zvec import ( get_default_jieba_dict_dir, set_default_jieba_dict_dir, ) @@ -48,7 +48,7 @@ except Exception: # DiskAnn normally auto-loads on first use; these APIs let tests and # diagnostic tools preload the plugin and get a clear error if libaio is # missing or the plugin shared object cannot be located. -from _zvec import ( +from zvec._zvec import ( DISKANN_PLUGIN_DLOPEN_FAILED, DISKANN_PLUGIN_LIBAIO_MISSING, DISKANN_PLUGIN_OK, diff --git a/python/zvec/executor/query_executor.py b/python/zvec/executor/query_executor.py index 952ac16..c615929 100644 --- a/python/zvec/executor/query_executor.py +++ b/python/zvec/executor/query_executor.py @@ -16,8 +16,9 @@ from __future__ import annotations from typing import Optional, Union import numpy as np -from _zvec import _Collection, _MultiQuery -from _zvec.param import _Fts, _SearchQuery, _SubQuery + +from zvec._zvec import _Collection, _MultiQuery +from zvec._zvec.param import _Fts, _SearchQuery, _SubQuery from ..extension import CallbackReRanker, ReRanker, RrfReRanker, WeightedReRanker from ..model.convert import convert_to_py_doc diff --git a/python/zvec/extension/multi_vector_reranker.py b/python/zvec/extension/multi_vector_reranker.py index acee984..a04c9f8 100644 --- a/python/zvec/extension/multi_vector_reranker.py +++ b/python/zvec/extension/multi_vector_reranker.py @@ -16,7 +16,13 @@ from __future__ import annotations from collections.abc import Callable from typing import TYPE_CHECKING -from _zvec import _CallbackParams, _Doc, _reranker_rerank, _RrfParams, _WeightedParams +from zvec._zvec import ( + _CallbackParams, + _Doc, + _reranker_rerank, + _RrfParams, + _WeightedParams, +) from ..model.doc import Doc, DocList from .rerank_function import RerankFunction diff --git a/python/zvec/model/collection.py b/python/zvec/model/collection.py index 3d1ae38..b90caae 100644 --- a/python/zvec/model/collection.py +++ b/python/zvec/model/collection.py @@ -16,7 +16,7 @@ from __future__ import annotations import warnings from typing import Optional, Union, overload -from _zvec import _Collection +from zvec._zvec import _Collection from ..executor import QueryContext, QueryExecutor from ..extension import ReRanker diff --git a/python/zvec/model/convert.py b/python/zvec/model/convert.py index 2eac08c..421bd17 100644 --- a/python/zvec/model/convert.py +++ b/python/zvec/model/convert.py @@ -11,7 +11,7 @@ # limitations under the License. from __future__ import annotations -from _zvec import _Doc +from zvec._zvec import _Doc from .doc import Doc from .schema import CollectionSchema diff --git a/python/zvec/model/param/__init__.py b/python/zvec/model/param/__init__.py index 43fc1dd..782b037 100644 --- a/python/zvec/model/param/__init__.py +++ b/python/zvec/model/param/__init__.py @@ -13,7 +13,7 @@ # limitations under the License. from __future__ import annotations -from _zvec.param import ( +from zvec._zvec.param import ( AddColumnOption, AlterColumnOption, CollectionOption, diff --git a/python/zvec/model/param/__init__.pyi b/python/zvec/model/param/__init__.pyi index c1d2272..6418c2d 100644 --- a/python/zvec/model/param/__init__.pyi +++ b/python/zvec/model/param/__init__.pyi @@ -7,7 +7,7 @@ from __future__ import annotations import collections import typing -import _zvec.typing +import zvec._zvec.typing __all__: list[str] = [ "AddColumnOption", @@ -161,8 +161,8 @@ class FlatIndexParam(VectorIndexParam): def __getstate__(self) -> tuple: ... def __init__( self, - metric_type: _zvec.typing.MetricType = ..., - quantize_type: _zvec.typing.QuantizeType = ..., + metric_type: zvec._zvec.typing.MetricType = ..., + quantize_type: zvec._zvec.typing.QuantizeType = ..., ) -> None: """ Constructs a FlatIndexParam instance. @@ -221,10 +221,10 @@ class HnswIndexParam(VectorIndexParam): def __getstate__(self) -> tuple: ... def __init__( self, - metric_type: _zvec.typing.MetricType = ..., + metric_type: zvec._zvec.typing.MetricType = ..., m: typing.SupportsInt = 50, ef_construction: typing.SupportsInt = 500, - quantize_type: _zvec.typing.QuantizeType = ..., + quantize_type: zvec._zvec.typing.QuantizeType = ..., use_contiguous_memory: bool = False, ) -> None: ... def __repr__(self) -> str: ... @@ -365,7 +365,7 @@ class HnswRabitqIndexParam(VectorIndexParam): def __getstate__(self) -> tuple: ... def __init__( self, - metric_type: _zvec.typing.MetricType = ..., + metric_type: zvec._zvec.typing.MetricType = ..., total_bits: typing.SupportsInt = 7, num_clusters: typing.SupportsInt = 16, m: typing.SupportsInt = 50, @@ -493,11 +493,11 @@ class IVFIndexParam(VectorIndexParam): def __getstate__(self) -> tuple: ... def __init__( self, - metric_type: _zvec.typing.MetricType = ..., + metric_type: zvec._zvec.typing.MetricType = ..., n_list: typing.SupportsInt = 10, n_iters: typing.SupportsInt = 10, use_soar: bool = False, - quantize_type: _zvec.typing.QuantizeType = ..., + quantize_type: zvec._zvec.typing.QuantizeType = ..., ) -> None: """ Constructs an IVFIndexParam instance. @@ -595,14 +595,14 @@ class VamanaIndexParam(VectorIndexParam): def __getstate__(self) -> tuple: ... def __init__( self, - metric_type: _zvec.typing.MetricType = ..., + metric_type: zvec._zvec.typing.MetricType = ..., max_degree: typing.SupportsInt = 64, search_list_size: typing.SupportsInt = 100, alpha: typing.SupportsFloat = 1.2, saturate_graph: bool = False, use_contiguous_memory: bool = False, use_id_map: bool = False, - quantize_type: _zvec.typing.QuantizeType = ..., + quantize_type: zvec._zvec.typing.QuantizeType = ..., ) -> None: ... def __repr__(self) -> str: ... def __setstate__(self, arg0: tuple) -> None: ... @@ -837,7 +837,7 @@ class IndexParam: """ @property - def type(self) -> _zvec.typing.IndexType: + def type(self) -> zvec._zvec.typing.IndexType: """ IndexType: The type of the index. """ @@ -966,7 +966,7 @@ class QueryParam: IndexType: The type of index this query targets. """ @property - def type(self) -> _zvec.typing.IndexType: + def type(self) -> zvec._zvec.typing.IndexType: """ IndexType: The type of index this query targets. """ @@ -1036,13 +1036,13 @@ class VectorIndexParam(IndexParam): """ @property - def metric_type(self) -> _zvec.typing.MetricType: + def metric_type(self) -> zvec._zvec.typing.MetricType: """ MetricType: Distance metric (e.g., IP, COSINE, L2). """ @property - def quantize_type(self) -> _zvec.typing.QuantizeType: + def quantize_type(self) -> zvec._zvec.typing.QuantizeType: """ QuantizeType: Vector quantization type (e.g., FP16, INT8). """ diff --git a/python/zvec/model/schema/__init__.py b/python/zvec/model/schema/__init__.py index 5ff532f..b952454 100644 --- a/python/zvec/model/schema/__init__.py +++ b/python/zvec/model/schema/__init__.py @@ -13,7 +13,7 @@ # limitations under the License. from __future__ import annotations -from _zvec.schema import CollectionStats +from zvec._zvec.schema import CollectionStats from .collection_schema import CollectionSchema from .field_schema import FieldSchema, VectorSchema diff --git a/python/zvec/model/schema/__init__.pyi b/python/zvec/model/schema/__init__.pyi index 30ba20f..0dfa80d 100644 --- a/python/zvec/model/schema/__init__.pyi +++ b/python/zvec/model/schema/__init__.pyi @@ -7,8 +7,8 @@ from __future__ import annotations import collections.abc import typing -import _zvec.param -import _zvec.typing +import zvec._zvec.param +import zvec._zvec.typing from .collection_schema import CollectionSchema from .field_schema import FieldSchema, VectorSchema @@ -85,20 +85,20 @@ class _FieldSchema: def __init__( self, name: str, - data_type: _zvec.typing.DataType, + data_type: zvec._zvec.typing.DataType, nullable: bool = False, dimension: typing.SupportsInt = 0, - index_param: _zvec.param.IndexParam = None, + index_param: zvec._zvec.param.IndexParam = None, ) -> None: ... def __ne__(self, arg0: _FieldSchema) -> bool: ... @property - def data_type(self) -> _zvec.typing.DataType: ... + def data_type(self) -> zvec._zvec.typing.DataType: ... @property def dimension(self) -> int: ... @property def index_param(self) -> typing.Any: ... @property - def index_type(self) -> _zvec.typing.IndexType: ... + def index_type(self) -> zvec._zvec.typing.IndexType: ... @property def is_dense_vector(self) -> bool: ... @property diff --git a/python/zvec/model/schema/collection_schema.py b/python/zvec/model/schema/collection_schema.py index e07095b..3e89710 100644 --- a/python/zvec/model/schema/collection_schema.py +++ b/python/zvec/model/schema/collection_schema.py @@ -16,7 +16,7 @@ from __future__ import annotations import json from typing import Optional, Union -from _zvec.schema import _CollectionSchema, _FieldSchema +from zvec._zvec.schema import _CollectionSchema, _FieldSchema from .field_schema import FieldSchema, VectorSchema diff --git a/python/zvec/model/schema/field_schema.py b/python/zvec/model/schema/field_schema.py index ff10997..9b757d6 100644 --- a/python/zvec/model/schema/field_schema.py +++ b/python/zvec/model/schema/field_schema.py @@ -16,8 +16,7 @@ from __future__ import annotations import json from typing import Any, Optional, Union -from _zvec.schema import _FieldSchema - +from zvec._zvec.schema import _FieldSchema from zvec.model.param import ( FlatIndexParam, FtsIndexParam, diff --git a/python/zvec/typing/__init__.py b/python/zvec/typing/__init__.py index da83c44..0faa19d 100644 --- a/python/zvec/typing/__init__.py +++ b/python/zvec/typing/__init__.py @@ -13,7 +13,7 @@ # limitations under the License. from __future__ import annotations -from _zvec.typing import ( +from zvec._zvec.typing import ( DataType, IndexType, MetricType, diff --git a/python/zvec/zvec.py b/python/zvec/zvec.py index 9f3e815..7bc6bc6 100644 --- a/python/zvec/zvec.py +++ b/python/zvec/zvec.py @@ -15,7 +15,7 @@ from __future__ import annotations from typing import Optional -from _zvec import Initialize, _Collection +from zvec._zvec import Initialize, _Collection from .model import Collection from .model.param import CollectionOption