Is your feature request related to a problem? Please describe.
I often find debugging errors and edge cases to be quite challenging as the issues that cause the exception are often hidden beneath a layer of other general exceptions, which obfuscate the actual source of the error. As and example: when debugging the edge case raised in: #2855 The actual exception I got was: "unable to read budget information from first entry in list file". This is useful for providing a high level explanation of the issue, but makes debugging quite difficult. Additionally many of the exceptions raised like this are the base class Exception, which means that any try/except clause will include all Exceptions that could be raised throughout the case. As an example a try/except clause for the budget file issue would capture both FileNotFoundExceptions as well as the general parsing exception. I could always test whether the file exists first, but here I would have to test all possible exceptions rather than just being able to handle a specific exception appropriately.
Describe the solution you'd like
I would suggest two simple solutions:
- Create one or more deticated "FlopyParsingException" or simlilar, so that people could catch just that exception.
- Add from context to the raised exception so that those of us who end up debugging can get some additional clarity on the error.
Implementing this in the ListBudget._set_entries method would transform
def _set_entries(self):
if len(self.idx_map) < 1:
return None, None
if len(self.entries) > 0:
raise Exception(f"entries already set:{self.entries}")
if not self.idx_map:
raise Exception("must call build_index before call set_entries")
try:
incdict, cumdict = self._get_sp(
self.idx_map[0][0], self.idx_map[0][1], self.idx_map[0][2]
)
except Exception
raise Exception(
"unable to read budget information from first entry in list file"
)
to
def _set_entries(self):
if len(self.idx_map) < 1:
return None, None
if len(self.entries) > 0:
raise Exception(f"entries already set:{self.entries}")
if not self.idx_map:
raise Exception("must call build_index before call set_entries")
try:
incdict, cumdict = self._get_sp(
self.idx_map[0][0], self.idx_map[0][1], self.idx_map[0][2]
)
except Exception as e:
raise FlopyParsingException(
"unable to read budget information from first entry in list file"
) from e
Where FlopyParsingException is defined as:
class FlopyParsingException(Exception):
"""An exception to catch errors when parsing modflow text files"""
pass
This would transfrom the traceback from:
File ".../python3.14/site-packages/flopy/utils/mflistfile.py", line 679, in _set_entries
raise Exception(
"unable to read budget information from first entry in list file"
)
Exception: unable to read budget information from first entry in list file
to
Traceback (most recent call last):
File ".../python3.14/site-packages/flopy/utils/mflistfile.py", line 675, in _set_entries
incdict, cumdict = self._get_sp(
^^^^^^^^^^^^^^^^
ValueError: not enough values to unpack (expected 2, got 0)
The above exception was the direct cause of the following exception:
File ".../python3.14/site-packages/flopy/utils/mflistfile.py", line 679, in _set_entries
raise FlopyParsingException(
"unable to read budget information from first entry in list file"
)
FlopyParsingException: unable to read budget information from first entry in list file
I would be happy to help implement this with a pull request, but I would want some consensus that this is the way to go.
Describe alternatives you've considered
None
Is your feature request related to a problem? Please describe.
I often find debugging errors and edge cases to be quite challenging as the issues that cause the exception are often hidden beneath a layer of other general exceptions, which obfuscate the actual source of the error. As and example: when debugging the edge case raised in: #2855 The actual exception I got was: "unable to read budget information from first entry in list file". This is useful for providing a high level explanation of the issue, but makes debugging quite difficult. Additionally many of the exceptions raised like this are the base class Exception, which means that any try/except clause will include all Exceptions that could be raised throughout the case. As an example a try/except clause for the budget file issue would capture both FileNotFoundExceptions as well as the general parsing exception. I could always test whether the file exists first, but here I would have to test all possible exceptions rather than just being able to handle a specific exception appropriately.
Describe the solution you'd like
I would suggest two simple solutions:
Implementing this in the ListBudget._set_entries method would transform
to
Where FlopyParsingException is defined as:
This would transfrom the traceback from:
to
I would be happy to help implement this with a pull request, but I would want some consensus that this is the way to go.
Describe alternatives you've considered
None