Making TomlDecodeError more useful
Opened this issue · 1 comments
I have some code parsing TOML doing:
except toml.TomlDecodeError as e:
msg = "'{}' is not a valid TOML file (Error given is: {})\n"
error = e.args[0]
if error == 'Invalid date or number':
msg += (
"One frequent cause of this is forgetting to put quotes "
"around secret keys. Check the file."
)
match = re.search(r"What\? (\w+) ", error)
duplicate = match and next(iter(match.groups()), None)
if duplicate:
msg += (
"One frequent cause of this is using the same account name "
"twice. Check that you didn't use '{}' several times."
).format(duplicate)
ctx.fail(msg.format(secrets_file, e))
All that is because I get bare TomlDecodeError
exceptions.
When raising an exception, we could attach some data so that catching code can make more accurate decision.
E.G:
TomlDecodeError with Invalid date or number
and What? Foo already exists
should have a field
attribute so that we can inspect what data causes the problem.
Also, it's good to have TomlDecodeError
subclasses for each particular problem so that we can have a more granular control over what we catch.
E.G:
class InvalidDateOrNumberTomlError(TomlDecodeError, ValueError):
pass
class DuplicateKeyTomlError(TomlDecodeError, KeyError):
pass
In the end, my ugly hack code could be replaced by:
except InvalidDateOrNumberTomlError as e:
ctx.fail((
'Duplicate key: "{}" '
'One frequent cause of this is using the same account name twice.'
)).format(e.field))
except DuplicateKeyTomlError as e:
ctx.fail((
'Invalid date or number on field "{}" '
'One frequent cause of this is forgetting to put quotes '
'around secret keys. Check the file.'
)).format(e.field))
Which is shorter, clearer, less error prone, and less likely to break in the future.
It's fair to expect that programmers will want to give feedback to their user if parsing a config file fail, so let's make that easy.
Thank you for the issue!
I agree with you, however time constraints don't allow me to work on this. Pull requests are welcome!