From cffb15fa2a6ced2597661a4b0ab0e6f20c40221b Mon Sep 17 00:00:00 2001 From: Claudio Cacciari Date: Sun, 11 Oct 2026 15:02:28 +0200 Subject: [PATCH 1/2] fix(fsspec): keep last_modified and version in ls() detail entries --- obstore/python/obstore/fsspec.py | 2 ++ tests/test_fsspec.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/obstore/python/obstore/fsspec.py b/obstore/python/obstore/fsspec.py index 277fb6d1..86e37a49 100644 --- a/obstore/python/obstore/fsspec.py +++ b/obstore/python/obstore/fsspec.py @@ -571,6 +571,8 @@ async def _ls( "size": obj["size"], "type": "file", "e_tag": obj["e_tag"], + "last_modified": obj["last_modified"], + "version": obj["version"], } for obj in objects ] + [ diff --git a/tests/test_fsspec.py b/tests/test_fsspec.py index 8bf490ef..66a3861c 100644 --- a/tests/test_fsspec.py +++ b/tests/test_fsspec.py @@ -3,6 +3,7 @@ import gc import os import zipfile +from datetime import datetime from io import UnsupportedOperation from pathlib import Path from tempfile import TemporaryDirectory @@ -417,6 +418,31 @@ def test_list( assert types.get(f"{bucket}/dir") == "directory" +def test_list_detail_matches_info( + minio_bucket: tuple[S3Config, ClientConfig], +): + bucket = minio_bucket[0].get("bucket") + assert bucket is not None + + register("s3") + fs = fsspec.filesystem( + "s3", + config=minio_bucket[0], + client_options=minio_bucket[1], + ) + + fs.pipe_file(f"{bucket}/afile", b"hello world") + + out = fs.ls(f"{bucket}", detail=True, refresh=True) + entry = next(o for o in out if o["name"] == f"{bucket}/afile") + # Without the listing in the cache, info() asks the store itself (HEAD). + fs.invalidate_cache() + info = fs.info(f"{bucket}/afile") + assert isinstance(entry["last_modified"], datetime) + assert entry["last_modified"] == info["last_modified"] + assert entry["version"] == info["version"] + + @pytest.mark.asyncio async def test_list_async( minio_bucket: tuple[S3Config, ClientConfig], From f836b32785c929d4301c9ae825177578b408f336 Mon Sep 17 00:00:00 2001 From: Claudio Cacciari Date: Sun, 11 Oct 2026 15:11:44 +0200 Subject: [PATCH 2/2] test: compare last_modified to within a second --- tests/test_fsspec.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_fsspec.py b/tests/test_fsspec.py index 66a3861c..ee99c3f3 100644 --- a/tests/test_fsspec.py +++ b/tests/test_fsspec.py @@ -3,7 +3,7 @@ import gc import os import zipfile -from datetime import datetime +from datetime import datetime, timedelta from io import UnsupportedOperation from pathlib import Path from tempfile import TemporaryDirectory @@ -439,7 +439,8 @@ def test_list_detail_matches_info( fs.invalidate_cache() info = fs.info(f"{bucket}/afile") assert isinstance(entry["last_modified"], datetime) - assert entry["last_modified"] == info["last_modified"] + # A listing reports milliseconds; HEAD's Last-Modified header whole seconds. + assert abs(entry["last_modified"] - info["last_modified"]) < timedelta(seconds=1) assert entry["version"] == info["version"]