fix: avoid manifest writes for read-only directory namespace opens (#3635)

Bumps Lance to v9.0.0-beta.19, which includes lance-format/lance#7687
for side-effect-free DirectoryNamespace read paths.

This fixes root-level read-only table opens that previously could
trigger `__manifest` creation through directory namespace construction,
including Hugging Face bucket reads with read-only tokens. A LanceDB
regression test now covers root listing operations without creating
`__manifest`.

Fixes #3633.
This commit is contained in:
Xuanwo
2026-07-10 03:39:34 +08:00
committed by GitHub
parent ff81428a9c
commit 22bf091de1
7 changed files with 211 additions and 101 deletions

View File

@@ -149,8 +149,14 @@ def connect(
For object storage, use a URI prefix:
>>> db = lancedb.connect("s3://my-bucket/lancedb",
... storage_options={"aws_access_key_id": "***"})
>>> db = lancedb.connect( # doctest: +SKIP
... "s3://my-bucket/lancedb",
... storage_options={
... "aws_access_key_id": "***",
... "aws_secret_access_key": "***",
... "aws_region": "us-east-1",
... },
... )
For tests and temporary data, use an in-memory database:

View File

@@ -7,7 +7,8 @@ Tests for S3 bucket names containing dots.
Related issue: https://github.com/lancedb/lancedb/issues/1898
These tests validate the early error checking for S3 bucket names with dots.
No actual S3 connection is made - validation happens before connection.
When validation succeeds, eager namespace initialization may still fail later
because these tests intentionally do not provide real S3 credentials.
"""
import pytest
@@ -20,6 +21,13 @@ BUCKET_WITH_DOTS_AND_AWS_REGION = ("s3://my.bucket.name", {"aws_region": "us-eas
BUCKET_WITHOUT_DOTS = "s3://my-bucket/path"
def assert_not_rejected_for_bucket_dots(connect):
try:
connect()
except ValueError as err:
assert "contains dots" not in str(err)
class TestS3BucketWithDotsSync:
"""Tests for connect()."""
@@ -27,19 +35,22 @@ class TestS3BucketWithDotsSync:
with pytest.raises(ValueError, match="contains dots"):
lancedb.connect(BUCKET_WITH_DOTS)
def test_bucket_with_dots_and_region_passes(self):
def test_bucket_with_dots_and_region_is_not_rejected(self):
uri, opts = BUCKET_WITH_DOTS_AND_REGION
db = lancedb.connect(uri, storage_options=opts)
assert db is not None
assert_not_rejected_for_bucket_dots(
lambda: lancedb.connect(uri, storage_options=opts)
)
def test_bucket_with_dots_and_aws_region_passes(self):
def test_bucket_with_dots_and_aws_region_is_not_rejected(self):
uri, opts = BUCKET_WITH_DOTS_AND_AWS_REGION
db = lancedb.connect(uri, storage_options=opts)
assert db is not None
assert_not_rejected_for_bucket_dots(
lambda: lancedb.connect(uri, storage_options=opts)
)
def test_bucket_without_dots_passes(self):
db = lancedb.connect(BUCKET_WITHOUT_DOTS)
assert db is not None
def test_bucket_without_dots_is_not_rejected(self):
assert_not_rejected_for_bucket_dots(
lambda: lancedb.connect(BUCKET_WITHOUT_DOTS)
)
class TestS3BucketWithDotsAsync:
@@ -51,18 +62,24 @@ class TestS3BucketWithDotsAsync:
await lancedb.connect_async(BUCKET_WITH_DOTS)
@pytest.mark.asyncio
async def test_bucket_with_dots_and_region_passes(self):
async def test_bucket_with_dots_and_region_is_not_rejected(self):
uri, opts = BUCKET_WITH_DOTS_AND_REGION
db = await lancedb.connect_async(uri, storage_options=opts)
assert db is not None
try:
await lancedb.connect_async(uri, storage_options=opts)
except ValueError as err:
assert "contains dots" not in str(err)
@pytest.mark.asyncio
async def test_bucket_with_dots_and_aws_region_passes(self):
async def test_bucket_with_dots_and_aws_region_is_not_rejected(self):
uri, opts = BUCKET_WITH_DOTS_AND_AWS_REGION
db = await lancedb.connect_async(uri, storage_options=opts)
assert db is not None
try:
await lancedb.connect_async(uri, storage_options=opts)
except ValueError as err:
assert "contains dots" not in str(err)
@pytest.mark.asyncio
async def test_bucket_without_dots_passes(self):
db = await lancedb.connect_async(BUCKET_WITHOUT_DOTS)
assert db is not None
async def test_bucket_without_dots_is_not_rejected(self):
try:
await lancedb.connect_async(BUCKET_WITHOUT_DOTS)
except ValueError as err:
assert "contains dots" not in str(err)