Skip to content

Making TomlDecodeError more useful #35

@ksamuel

Description

@ksamuel

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions