mirror of
https://github.com/lancedb/lancedb.git
synced 2026-10-13 23:32:27 +00:00
fix(python): preserve code tokenizer filter defaults (#4370)
Python's FTS bindings always forwarded `stem=True` and `remove_stop_words=True`, overriding Lance's code tokenizer defaults. As a result, code indexes stemmed identifiers and discarded stop words, and `lancedb.tokenize` reproduced the same behavior. Use `None` for omitted filter options and only apply explicit booleans in the Rust bindings. This preserves tokenizer defaults across local and remote index creation, the deprecated `create_fts_index` helpers, and standalone tokenization. Update the signatures and documentation to describe the inherited defaults. Regression tests cover stored local settings, token output, stop-word searches, remote request payloads, explicit overrides, and the existing simple tokenizer behavior. The regression suite produced 16 failures before the fix and passes all 28 cases after it. Validation: - Rebuilt the Python extension using the uv-managed development environment. - Full Python FTS and index test files plus relevant remote index tests: 105 passed. - `cargo clippy --quiet --features remote --tests --examples -p lancedb-python` - `cargo fmt --all`, Ruff format/lint with CI's pinned version 0.9.9, and Pyright (zero errors). Fixes #4365 <!-- lance-gatekeeper-fix:v1 agent=9c1db2d3fc25c49c5b340f8debf43a0f generation=1 --> Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
This commit is contained in:
@@ -895,6 +895,78 @@ def test_tokenize_uses_simple_index_tokenizer(mem_db: DBConnection):
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("legacy", [False, True])
|
||||
@pytest.mark.parametrize(
|
||||
("base_tokenizer", "options", "expected_filters", "expected_tokens"),
|
||||
[
|
||||
(
|
||||
"code",
|
||||
{},
|
||||
(False, False),
|
||||
[("running", 0), ("in", 1), ("cafe", 2)],
|
||||
),
|
||||
(
|
||||
"code",
|
||||
{"stem": None, "remove_stop_words": None},
|
||||
(False, False),
|
||||
[("running", 0), ("in", 1), ("cafe", 2)],
|
||||
),
|
||||
(
|
||||
"code",
|
||||
{"stem": True},
|
||||
(True, False),
|
||||
[("run", 0), ("in", 1), ("cafe", 2)],
|
||||
),
|
||||
(
|
||||
"code",
|
||||
{"remove_stop_words": True},
|
||||
(False, True),
|
||||
[("running", 0), ("cafe", 2)],
|
||||
),
|
||||
(
|
||||
"code",
|
||||
{"stem": True, "remove_stop_words": True},
|
||||
(True, True),
|
||||
[("run", 0), ("cafe", 2)],
|
||||
),
|
||||
(
|
||||
"simple",
|
||||
{},
|
||||
(True, True),
|
||||
[("run", 0), ("cafe", 2)],
|
||||
),
|
||||
(
|
||||
"simple",
|
||||
{"stem": False, "remove_stop_words": False},
|
||||
(False, False),
|
||||
[("running", 0), ("in", 1), ("cafe", 2)],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_fts_tokenizer_filter_defaults(
|
||||
mem_db, legacy, base_tokenizer, options, expected_filters, expected_tokens
|
||||
):
|
||||
text = "Running in café"
|
||||
table = mem_db.create_table("test_filter_defaults", data=[{"text": text}])
|
||||
if legacy:
|
||||
with pytest.warns(DeprecationWarning, match="create_fts_index"):
|
||||
table.create_fts_index("text", base_tokenizer=base_tokenizer, **options)
|
||||
else:
|
||||
table.create_index("text", config=FTS(base_tokenizer=base_tokenizer, **options))
|
||||
|
||||
details = table.list_indices()[0].index_details
|
||||
assert (details["stem"], details["remove_stop_words"]) == expected_filters
|
||||
assert [
|
||||
(token.text, token.position) for token in table.tokenize(text, column="text")
|
||||
] == expected_tokens
|
||||
assert [
|
||||
(token.text, token.position)
|
||||
for token in ldb.tokenize(text, base_tokenizer=base_tokenizer, **options)
|
||||
] == expected_tokens
|
||||
if base_tokenizer == "code" and not expected_filters[1]:
|
||||
assert table.search("in", query_type="fts").to_list()[0]["text"] == text
|
||||
|
||||
|
||||
def test_tokenize_uses_icu_index_tokenizer_by_name(mem_db: DBConnection):
|
||||
data = pa.table({"text": ["Hello, こんにちは世界!"]})
|
||||
table = mem_db.create_table("test_tokenize_icu", data=data)
|
||||
|
||||
Reference in New Issue
Block a user