From 1467142a0727de59eb6b50aa474e752b758edd17 Mon Sep 17 00:00:00 2001 From: Alexis Simon Date: Fri, 16 Jan 2026 09:37:40 +0100 Subject: [PATCH] python/tskit/util.py: Add a file name to FileFormatError Closes #2467 Uses the .add_note method of exception, introduced in Python 3.11. Also hardcodes the file name in the raised from exceptions for HDF5 or zip. Until 3.10 is EOF, needs the sys module. --- python/tests/test_file_format.py | 35 ++++++++++++++++++++++++-------- python/tskit/util.py | 9 ++++---- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/python/tests/test_file_format.py b/python/tests/test_file_format.py index ec8a7af89d..d1246e8011 100644 --- a/python/tests/test_file_format.py +++ b/python/tests/test_file_format.py @@ -25,6 +25,7 @@ """ import os +import re import tempfile import unittest import uuid as _uuid @@ -262,12 +263,12 @@ def test_format_too_old_raised_for_hdf5(self): with pytest.raises( exceptions.FileFormatError, - match="appears to be in HDF5 format", + match=f"{re.escape(filename)}.*appears to be in HDF5 format", ): tskit.load(path) with pytest.raises( exceptions.FileFormatError, - match="appears to be in HDF5 format", + match=f"{re.escape(filename)}.*appears to be in HDF5 format", ): tskit.TableCollection.load(path) @@ -285,9 +286,15 @@ class TestErrors(TestFileFormat): def test_tszip_file(self): ts = msprime.simulate(5) tszip.compress(ts, self.temp_file) - with pytest.raises(tskit.FileFormatError, match="appears to be in zip format"): + with pytest.raises( + tskit.FileFormatError, + match=f"{re.escape(self.temp_file)}.*appears to be in zip format", + ): tskit.load(self.temp_file) - with pytest.raises(tskit.FileFormatError, match="appears to be in zip format"): + with pytest.raises( + tskit.FileFormatError, + match=f"{re.escape(self.temp_file)}.*appears to be in zip format", + ): tskit.TableCollection.load(self.temp_file) @@ -892,7 +899,10 @@ def test_format_name_error(self): data = dict(store) data["format/name"] = np.array(bytearray(bad_name.encode()), dtype=np.int8) kastore.dump(data, self.temp_file) - with pytest.raises(exceptions.FileFormatError): + with pytest.raises( + exceptions.FileFormatError, + match=f"While trying to load {re.escape(self.temp_file)}", + ): tskit.load(self.temp_file) def test_load_bad_formats(self): @@ -903,12 +913,18 @@ def test_load_bad_formats(self): # Now some ascii text with open(self.temp_file, "wb") as f: f.write(b"Some ASCII text") - with pytest.raises(exceptions.FileFormatError): + with pytest.raises( + exceptions.FileFormatError, + match=f"While trying to load {re.escape(self.temp_file)}", + ): tskit.load(self.temp_file) # Now write 8k of random bytes with open(self.temp_file, "wb") as f: f.write(os.urandom(8192)) - with pytest.raises(exceptions.FileFormatError): + with pytest.raises( + exceptions.FileFormatError, + match=f"While trying to load {re.escape(self.temp_file)}", + ): tskit.load(self.temp_file) def test_load_bad_formats_fileobj(self): @@ -920,7 +936,10 @@ def load(): load() with open(self.temp_file, "wb") as f: f.write(b"Some ASCII text") - with pytest.raises(exceptions.FileFormatError): + with pytest.raises( + exceptions.FileFormatError, + match=f"While trying to load {re.escape(self.temp_file)}", + ): load() diff --git a/python/tskit/util.py b/python/tskit/util.py index 730d2db8fb..4167bdc44f 100644 --- a/python/tskit/util.py +++ b/python/tskit/util.py @@ -878,6 +878,7 @@ def raise_known_file_format_errors(open_file, existing_exception): Sniffs the file for pk-zip or hdf header bytes, then raises an exception if these are detected, if not raises the existing exception. """ + existing_exception.add_note(f"While trying to load {open_file.name}") # Check for HDF5 header bytes try: open_file.seek(0) @@ -887,16 +888,16 @@ def raise_known_file_format_errors(open_file, existing_exception): raise existing_exception if header == b"\x89HDF": raise tskit.FileFormatError( - "The specified file appears to be in HDF5 format. This file " + f"The file {open_file.name} appears to be in HDF5 format. This file " "may have been generated by msprime < 0.6.0 (June 2018) which " "can no longer be read directly. Please convert to the new " "kastore format using the ``tskit upgrade`` command from tskit version<0.6.2" ) from existing_exception if header[:2] == b"\x50\x4b": raise tskit.FileFormatError( - "The specified file appears to be in zip format, so may be a compressed " - "tree sequence. Try using the tszip module to decompress this file before " - "loading. `pip install tszip; tsunzip ` or use " + f"The file {open_file.name} appears to be in zip format, so may be a " + "compressed tree sequence. Try using the tszip module to decompress this " + "file before loading. `pip install tszip; tsunzip ` or use " "`tszip.decompress` in Python code." ) from existing_exception raise existing_exception