Skip to content

Commit d8cba36

Browse files
WAAutoMatonseberg
andauthored
ENH: Ensure lib._format_impl.read_array handles file reading errors. (numpy#28330)
* BUG: Ensure ``lib._format_impl.read_array`` handles file reading errors. * ENH: improve error messages in``lib._format_impl.read_array`` * TST: add tests for file read failures in ``read_array`` * ENH: improve the phrasing of the error message in ``lib._format_impl.read_array`` * TST: fix some issues in ``test_file_truncated`` * Update numpy/lib/tests/test_format.py --------- Co-authored-by: Sebastian Berg <[email protected]>
1 parent f104291 commit d8cba36

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

numpy/lib/_format_impl.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,14 @@ def read_array(fp, allow_pickle=False, pickle_kwargs=None, *,
872872
data = _read_bytes(fp, read_size, "array data")
873873
array[i:i + read_count] = numpy.frombuffer(data, dtype=dtype,
874874
count=read_count)
875+
876+
if array.size != count:
877+
raise ValueError(
878+
"Failed to read all data for array. "
879+
f"Expected {shape} = {count} elements, "
880+
f"could only read {array.size} elements. "
881+
"(file seems not fully written?)"
882+
)
875883

876884
if fortran_order:
877885
array.shape = shape[::-1]

numpy/lib/tests/test_format.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,6 @@ def roundtrip_truncated(arr):
428428
arr2 = format.read_array(f2)
429429
return arr2
430430

431-
432431
def assert_equal_(o1, o2):
433432
assert_(o1 == o2)
434433

@@ -451,6 +450,30 @@ def test_roundtrip_truncated():
451450
if arr.dtype != object:
452451
assert_raises(ValueError, roundtrip_truncated, arr)
453452

453+
def test_file_truncated(tmp_path):
454+
path = tmp_path / "a.npy"
455+
for arr in basic_arrays:
456+
if arr.dtype != object:
457+
with open(path, 'wb') as f:
458+
format.write_array(f, arr)
459+
#truncate the file by one byte
460+
with open(path, 'rb+') as f:
461+
f.seek(-1, os.SEEK_END)
462+
f.truncate()
463+
with open(path, 'rb') as f:
464+
with pytest.raises(
465+
ValueError,
466+
match = (
467+
r"EOF: reading array header, "
468+
r"expected (\d+) bytes got (\d+)"
469+
) if arr.size == 0 else (
470+
r"Failed to read all data for array\. "
471+
r"Expected \(.*?\) = (\d+) elements, "
472+
r"could only read (\d+) elements\. "
473+
r"\(file seems not fully written\?\)"
474+
)
475+
):
476+
_ = format.read_array(f)
454477

455478
def test_long_str():
456479
# check items larger than internal buffer size, gh-4027

0 commit comments

Comments
 (0)