Skip to content

Commit c4f076c

Browse files
BenYang12Wauplin
andauthored
(LFS)Fix SliceFileObj.__iter__ yielding only the first 4MB chunk (#4844)
Co-authored-by: Lucain <lucain@huggingface.co>
1 parent 22fe960 commit c4f076c

2 files changed

Lines changed: 14 additions & 1 deletion

File tree

src/huggingface_hub/utils/_lfs.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,5 @@ def seek(self, offset: int, whence: int = os.SEEK_SET) -> int:
106106
return self.fileobj.seek(offset, whence) - self.seek_from
107107

108108
def __iter__(self):
109-
yield self.read(n=4 * 1024 * 1024)
109+
while data := self.read(n=4 * 1024 * 1024):
110+
yield data

tests/test_lfs.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,18 @@ def test_slice_fileobj_BytesIO(self):
116116
assert fileobj_slice.tell() == 0
117117
assert fileobj_slice.fileobj.tell() == 100
118118

119+
def test_slice_fileobj_iter_reads_full_slice(self):
120+
# Regression test: iterating a slice must yield the whole slice in 4 MB
121+
# chunks. Previously __iter__ had a single `yield`, so it returned only the
122+
# first 4 MB chunk and silently dropped everything after it.
123+
chunk_size = 4 * 1024 * 1024
124+
content = b"x" * (chunk_size + 500) # spans more than one chunk
125+
fileobj = BytesIO(content)
126+
with SliceFileObj(fileobj, seek_from=0, read_limit=len(content)) as fileobj_slice:
127+
chunks = list(fileobj_slice)
128+
assert len(chunks) > 1
129+
assert b"".join(chunks) == content
130+
119131
def test_slice_fileobj_file(self):
120132
self.content = b"RANDOM self.content uauabciabeubahveb" * 1024
121133

0 commit comments

Comments
 (0)