Files
lancedb/python/python/tests/test_blob_query_without_pylance.py
T
importcppandimportcpp 8172298044 test(python): expand minimal dependency coverage
Expand the Linux Python test run without pandas and pylance from two files to
the suite while retaining the regular dependency run for optional-package
modules.

Move optional imports into tests that need them and use Arrow assertions where
pandas is not required, preserving the existing behavioral assertions.

Validation:
- Physical no-pandas/no-pylance broad run: 2884 passed, 316 skipped, 8 existing
  marker cases deselected.
- Regular affected suite: 1687 passed, 39 skipped.
- Current-head hosted integration: all 15 checks and 4 workflows passed.

Co-authored-by: importcpp <57519936+importcpp@users.noreply.github.com>
2026-11-03 18:31:46 +08:00

97 lines
3.8 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright The LanceDB Authors
import subprocess
import sys
import textwrap
import pytest
@pytest.mark.parametrize("api", ["sync", "async"])
@pytest.mark.parametrize("result", ["pandas", "batches", "lazy_error"])
def test_blob_query_without_pylance(tmp_path, api, result):
if result == "pandas":
pytest.importorskip("pandas")
script = """\
import importlib.abc
import sys
class MissingLance(importlib.abc.MetaPathFinder):
def find_spec(self, fullname, path, target=None):
if fullname == "lance" or fullname.startswith("lance."):
raise ModuleNotFoundError(fullname, name="lance")
sys.meta_path.insert(0, MissingLance())
""" + textwrap.dedent(
"""\
import asyncio
import lancedb
import pyarrow as pa
schema = pa.schema([pa.field("id", pa.int64()), lancedb.blob("video")])
rows = [{"id": 1, "video": b"one"}, {"id": 2, "video": None},
{"id": 3, "video": b"three"}]
def check(data):
assert data == [{"filename": 2, "payload": None},
{"filename": 3, "payload": b"three"}], data
async def main():
if sys.argv[2] == "async":
db = await lancedb.connect_async(sys.argv[1])
table = await db.create_table("videos", schema=schema)
await table.add(rows)
query = table.query()
else:
db = lancedb.connect(sys.argv[1])
table = db.create_table("videos", schema=schema)
table.add(rows)
query = table.search()
query = query.select({"filename": "id", "payload": "video"}).offset(1)
if sys.argv[3] == "pandas":
frame = query.to_pandas(blob_mode="bytes", split_blocks=True)
if sys.argv[2] == "async":
frame = await frame
check(frame.to_dict("records"))
frame = table.to_pandas(blob_mode="bytes")
if sys.argv[2] == "async":
frame = await frame
assert frame.to_dict("records") == rows
elif sys.argv[3] == "batches":
if sys.argv[2] == "async":
reader = await query.to_batches(
max_batch_length=1, blob_mode="bytes")
batches = [batch async for batch in reader]
else:
reader = query.to_batches(batch_size=1, blob_mode="bytes")
batches = list(reader)
assert reader.schema.field("payload").type == pa.large_binary()
assert all(batch.num_rows <= 1 for batch in batches)
assert all(batch.schema == reader.schema for batch in batches)
check([row for batch in batches for row in batch.to_pylist()])
else:
try:
frame = query.to_pandas()
if sys.argv[2] == "async":
await frame
except RuntimeError as error:
message = str(error)
assert "pip install pylance" in message, message
assert ".." not in message, message
assert "Use a plain scan query" not in message, message
assert "but The" not in message, message
else:
raise AssertionError("lazy handles should require pylance")
assert "lance" not in sys.modules
asyncio.run(main())
"""
)
completed = subprocess.run(
[sys.executable, "-c", script, str(tmp_path), api, result],
capture_output=True,
text=True,
)
assert completed.returncode == 0, completed.stderr