refactor: rename package codexlens -> codexlens_search for independent distribution

Rename the v2 search engine package to `codexlens-search` (import as
`codexlens_search`) so it can be installed independently and consumed
by the original codex-lens as a dependency. This avoids package path
conflicts since both previously used `src/codexlens/`.

Changes:
- Rename src/codexlens/ -> src/codexlens_search/
- Update pyproject.toml: name=codexlens-search, version=0.2.0
- Update all imports across source, tests, and scripts
- Add public API exports in __init__.py (Config, SearchPipeline,
  IndexingPipeline, SearchResult, IndexStats)

37/37 tests pass. No functional changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
catlog22
2026-03-16 23:23:22 +08:00
parent a0a50d338a
commit 6712965b7f
32 changed files with 83 additions and 63 deletions

View File

@@ -1,5 +1,5 @@
import sys
import os
# Ensure the local src directory takes precedence over any installed codexlens package
# Ensure the local src directory takes precedence over any installed codexlens_search package
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))

View File

@@ -3,9 +3,9 @@ requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "codex-lens-v2"
version = "0.1.0"
description = "Minimal code semantic search library with 2-stage pipeline"
name = "codexlens-search"
version = "0.2.0"
description = "Lightweight semantic code search engine — 2-stage vector + FTS + RRF fusion"
requires-python = ">=3.10"
dependencies = []
@@ -33,4 +33,4 @@ dev = [
]
[tool.hatch.build.targets.wheel]
packages = ["src/codexlens"]
packages = ["src/codexlens_search"]

View File

@@ -9,13 +9,13 @@ from pathlib import Path
# 确保 src 可被导入
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
from codexlens.config import Config
from codexlens.core.factory import create_ann_index, create_binary_index
from codexlens.embed.local import FastEmbedEmbedder
from codexlens.indexing import IndexingPipeline
from codexlens.rerank.local import FastEmbedReranker
from codexlens.search.fts import FTSEngine
from codexlens.search.pipeline import SearchPipeline
from codexlens_search.config import Config
from codexlens_search.core.factory import create_ann_index, create_binary_index
from codexlens_search.embed.local import FastEmbedEmbedder
from codexlens_search.indexing import IndexingPipeline
from codexlens_search.rerank.local import FastEmbedReranker
from codexlens_search.search.fts import FTSEngine
from codexlens_search.search.pipeline import SearchPipeline
# ─── 配置 ──────────────────────────────────────────────────────────────────
REPO_ROOT = Path("D:/Claude_dms3")

View File

@@ -11,13 +11,13 @@ from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
import numpy as np
from codexlens.config import Config
from codexlens.core.factory import create_ann_index, create_binary_index
from codexlens.embed.local import FastEmbedEmbedder
from codexlens.indexing import IndexingPipeline
from codexlens.rerank.base import BaseReranker
from codexlens.search.fts import FTSEngine
from codexlens.search.pipeline import SearchPipeline
from codexlens_search.config import Config
from codexlens_search.core.factory import create_ann_index, create_binary_index
from codexlens_search.embed.local import FastEmbedEmbedder
from codexlens_search.indexing import IndexingPipeline
from codexlens_search.rerank.base import BaseReranker
from codexlens_search.search.fts import FTSEngine
from codexlens_search.search.pipeline import SearchPipeline
class KeywordReranker(BaseReranker):
@@ -32,7 +32,7 @@ class KeywordReranker(BaseReranker):
return scores
PROJECT = Path(__file__).parent.parent
TARGET_DIR = PROJECT / "src" / "codexlens" # ~21 .py files, small
TARGET_DIR = PROJECT / "src" / "codexlens_search" # ~21 .py files, small
INDEX_DIR = PROJECT / ".test_index_cache"
EXTENSIONS = {".py"}

View File

@@ -0,0 +1,20 @@
"""codexlens-search: Lightweight semantic code search engine.
Public API for consumers (e.g. codex-lens):
from codexlens_search import SearchPipeline, IndexingPipeline, Config
from codexlens_search.core import create_ann_index, create_binary_index
from codexlens_search.embed.local import FastEmbedEmbedder
from codexlens_search.rerank.api import APIReranker
"""
from codexlens_search.config import Config
from codexlens_search.indexing import IndexingPipeline, IndexStats
from codexlens_search.search.pipeline import SearchPipeline, SearchResult
__all__ = [
"Config",
"IndexingPipeline",
"IndexStats",
"SearchPipeline",
"SearchResult",
]

View File

@@ -6,8 +6,8 @@ from pathlib import Path
import numpy as np
from codexlens.config import Config
from codexlens.core.base import BaseBinaryIndex
from codexlens_search.config import Config
from codexlens_search.core.base import BaseBinaryIndex
logger = logging.getLogger(__name__)

View File

@@ -3,8 +3,8 @@ from __future__ import annotations
import logging
from pathlib import Path
from codexlens.config import Config
from codexlens.core.base import BaseANNIndex, BaseBinaryIndex
from codexlens_search.config import Config
from codexlens_search.core.base import BaseANNIndex, BaseBinaryIndex
logger = logging.getLogger(__name__)
@@ -52,22 +52,22 @@ def create_ann_index(path: str | Path, dim: int, config: Config) -> BaseANNIndex
backend = config.ann_backend
if backend == "faiss":
from codexlens.core.faiss_index import FAISSANNIndex
from codexlens_search.core.faiss_index import FAISSANNIndex
return FAISSANNIndex(path, dim, config)
if backend == "hnswlib":
from codexlens.core.index import ANNIndex
from codexlens_search.core.index import ANNIndex
return ANNIndex(path, dim, config)
# auto: try faiss first, then hnswlib
if _FAISS_AVAILABLE:
from codexlens.core.faiss_index import FAISSANNIndex
from codexlens_search.core.faiss_index import FAISSANNIndex
gpu_tag = " (GPU available)" if _has_faiss_gpu() else " (CPU)"
logger.info("Auto-selected FAISS ANN backend%s", gpu_tag)
return FAISSANNIndex(path, dim, config)
if _HNSWLIB_AVAILABLE:
from codexlens.core.index import ANNIndex
from codexlens_search.core.index import ANNIndex
logger.info("Auto-selected hnswlib ANN backend")
return ANNIndex(path, dim, config)
@@ -97,20 +97,20 @@ def create_binary_index(
backend = config.binary_backend
if backend == "faiss":
from codexlens.core.faiss_index import FAISSBinaryIndex
from codexlens_search.core.faiss_index import FAISSBinaryIndex
return FAISSBinaryIndex(path, dim, config)
if backend == "hnswlib":
from codexlens.core.binary import BinaryStore
from codexlens_search.core.binary import BinaryStore
return BinaryStore(path, dim, config)
# auto: try faiss first, then numpy-based BinaryStore
if _FAISS_AVAILABLE:
from codexlens.core.faiss_index import FAISSBinaryIndex
from codexlens_search.core.faiss_index import FAISSBinaryIndex
logger.info("Auto-selected FAISS binary backend")
return FAISSBinaryIndex(path, dim, config)
# numpy BinaryStore is always available (no extra deps)
from codexlens.core.binary import BinaryStore
from codexlens_search.core.binary import BinaryStore
logger.info("Auto-selected numpy BinaryStore backend")
return BinaryStore(path, dim, config)

View File

@@ -7,8 +7,8 @@ from pathlib import Path
import numpy as np
from codexlens.config import Config
from codexlens.core.base import BaseANNIndex, BaseBinaryIndex
from codexlens_search.config import Config
from codexlens_search.core.base import BaseANNIndex, BaseBinaryIndex
logger = logging.getLogger(__name__)

View File

@@ -6,8 +6,8 @@ from pathlib import Path
import numpy as np
from codexlens.config import Config
from codexlens.core.base import BaseANNIndex
from codexlens_search.config import Config
from codexlens_search.core.base import BaseANNIndex
logger = logging.getLogger(__name__)

View File

@@ -14,11 +14,11 @@ from pathlib import Path
import numpy as np
from codexlens.config import Config
from codexlens.core.binary import BinaryStore
from codexlens.core.index import ANNIndex
from codexlens.embed.base import BaseEmbedder
from codexlens.search.fts import FTSEngine
from codexlens_search.config import Config
from codexlens_search.core.binary import BinaryStore
from codexlens_search.core.index import ANNIndex
from codexlens_search.embed.base import BaseEmbedder
from codexlens_search.search.fts import FTSEngine
logger = logging.getLogger(__name__)

View File

@@ -5,7 +5,7 @@ import time
import httpx
from codexlens.config import Config
from codexlens_search.config import Config
from .base import BaseReranker
logger = logging.getLogger(__name__)

View File

@@ -1,6 +1,6 @@
from __future__ import annotations
from codexlens.config import Config
from codexlens_search.config import Config
from .base import BaseReranker

View File

@@ -3,12 +3,12 @@ import numpy as np
import tempfile
from pathlib import Path
from codexlens.config import Config
from codexlens.core import ANNIndex, BinaryStore
from codexlens.embed.base import BaseEmbedder
from codexlens.rerank.base import BaseReranker
from codexlens.search.fts import FTSEngine
from codexlens.search.pipeline import SearchPipeline
from codexlens_search.config import Config
from codexlens_search.core import ANNIndex, BinaryStore
from codexlens_search.embed.base import BaseEmbedder
from codexlens_search.rerank.base import BaseReranker
from codexlens_search.search.fts import FTSEngine
from codexlens_search.search.pipeline import SearchPipeline
# Test documents: 20 code snippets with id, path, content
TEST_DOCS = [

View File

@@ -1,4 +1,4 @@
from codexlens.config import Config
from codexlens_search.config import Config
def test_config_instantiates_no_args():

View File

@@ -8,8 +8,8 @@ from pathlib import Path
import numpy as np
import pytest
from codexlens.config import Config
from codexlens.core import ANNIndex, BinaryStore
from codexlens_search.config import Config
from codexlens_search.core import ANNIndex, BinaryStore
DIM = 32

View File

@@ -18,9 +18,9 @@ def _make_fastembed_mock():
_make_fastembed_mock()
from codexlens.config import Config # noqa: E402
from codexlens.embed.base import BaseEmbedder # noqa: E402
from codexlens.embed.local import EMBED_PROFILES, FastEmbedEmbedder # noqa: E402
from codexlens_search.config import Config # noqa: E402
from codexlens_search.embed.base import BaseEmbedder # noqa: E402
from codexlens_search.embed.local import EMBED_PROFILES, FastEmbedEmbedder # noqa: E402
class TestEmbedSingle(unittest.TestCase):

View File

@@ -5,10 +5,10 @@ from unittest.mock import MagicMock, patch
import pytest
from codexlens.config import Config
from codexlens.rerank.base import BaseReranker
from codexlens.rerank.local import FastEmbedReranker
from codexlens.rerank.api import APIReranker
from codexlens_search.config import Config
from codexlens_search.rerank.base import BaseReranker
from codexlens_search.rerank.local import FastEmbedReranker
from codexlens_search.rerank.api import APIReranker
# ---------------------------------------------------------------------------

View File

@@ -5,16 +5,16 @@ from unittest.mock import MagicMock
import pytest
from codexlens.search.fts import FTSEngine
from codexlens.search.fusion import (
from codexlens_search.search.fts import FTSEngine
from codexlens_search.search.fusion import (
DEFAULT_WEIGHTS,
QueryIntent,
detect_query_intent,
get_adaptive_weights,
reciprocal_rank_fusion,
)
from codexlens.search.pipeline import SearchPipeline, SearchResult
from codexlens.config import Config
from codexlens_search.search.pipeline import SearchPipeline, SearchResult
from codexlens_search.config import Config
# ---------------------------------------------------------------------------