Skip to content

Commit 77a2b3a

Browse files
authored
fix: Prevent early EOF error in reader.read (#593)
* fix: Python reader should return truncated result when requesting beyond EOF * test: Add comparison to stdlib BytesIO
1 parent 7d91acf commit 77a2b3a

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

obstore/src/buffered.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,10 @@ async fn read(reader: Arc<Mutex<BufReader>>, size: Option<usize>) -> PyResult<Py
192192
let mut reader = reader.lock().await;
193193
if let Some(size) = size {
194194
let mut buf = vec![0; size as _];
195-
reader.read_exact(&mut buf).await?;
195+
let n = reader.read(&mut buf).await?;
196+
if n < buf.len() {
197+
buf.truncate(n);
198+
}
196199
Ok(Bytes::from(buf).into())
197200
} else {
198201
let mut buf = Vec::new();

tests/test_buffered.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from io import BytesIO
2+
13
import pytest
24

35
import obstore as obs
@@ -77,3 +79,36 @@ async def test_writable_file_async():
7779
resp = await obs.get_async(store, path)
7880
retour = await resp.bytes_async()
7981
assert retour == line * 50
82+
83+
84+
def test_read_past_eof_sync():
85+
store = MemoryStore()
86+
87+
data = b"Hello, World!"
88+
path = "greeting.txt"
89+
obs.put(store, path, data)
90+
91+
file = obs.open_reader(store, path)
92+
buffer = file.read(20)
93+
assert memoryview(data) == memoryview(buffer)
94+
95+
buf = BytesIO(data)
96+
expected = buf.read(20)
97+
assert memoryview(expected) == memoryview(buffer)
98+
99+
100+
@pytest.mark.asyncio
101+
async def test_read_past_eof_async():
102+
store = MemoryStore()
103+
104+
data = b"Hello, World!"
105+
path = "greeting.txt"
106+
await obs.put_async(store, path, data)
107+
108+
file = await obs.open_reader_async(store, path)
109+
buffer = await file.read(20)
110+
assert memoryview(data) == memoryview(buffer)
111+
112+
buf = BytesIO(data)
113+
expected = buf.read(20)
114+
assert memoryview(expected) == memoryview(buffer)

0 commit comments

Comments
 (0)