Skip to content

Make ValidationError Hashable #477

Closed

Description

@adksujan

cannot log ValidationError as an exception. Making the exceptions hashable would be great to use in standard logging libraries. Any plans to make ValidationError exception hashable before the v3.0 release??

Activity

  1. Julian commented on Oct 17, 2018

    @Julian
    Member

    Hey yeah this is one of the remaining things I'm thinking about before the release.

    The issue with making them hashable is that doing so requires an API change, because they've got mutable attributes on them at the minute, so those would need to become immutable ones.

  2. changed the title [-]can't logging.exception(ValidationError), raises Exception TypeError: unhashable type: 'ValidationError'[/-] [+]Make ValidationError Hashable[/+] on Nov 2, 2018
  3. stuarteberg commented on Nov 30, 2018

    @stuarteberg
    Contributor

    Of course, ValidationError and SchemaError would be trivially hashable if they didn't define __eq__. Is it necessary for those classes to be comparable? I tried grepping the jsonschema code base for == and !=, and as far as I can tell, exceptions are never explicitly compared. (But I could definitely be missing implicit comparisons, such as if exc in mylist:, etc.)

    If comparability is not necessary, I vote for simply removing _Error.__eq__() and _Error.__ne__().

    For now, here's my workaround:

    from jsonschema.exceptions import _Error
    _Error.__eq__ = object.__eq__
    _Error.__ne__ = object.__ne__
    _Error.__hash__ = object.__hash__

    Making the exceptions hashable would be great to use in standard logging libraries.

    Here's another use-case: pytest can't handle unhashable exceptions, so any users whose tests might raise a ValidationError will currently see an INTERNALERROR traceback from pytest, crashing the whole test suite.

    For example:

    # test.py
    from jsonschema import validate
    def test():
        validate([], {"type": "object"})
    $ pytest test.py
    
    ...
    
    INTERNALERROR>   File "/prefix/lib/python3.6/site-packages/_pytest/_code/code.py", line 398, in exconly
    INTERNALERROR>     lines = format_exception_only(self.type, self.value)
    INTERNALERROR>   File "/prefix/lib/python3.6/traceback.py", line 136, in format_exception_only
    INTERNALERROR>     return list(TracebackException(etype, value, None).format_exception_only())
    INTERNALERROR>   File "/prefix/lib/python3.6/traceback.py", line 462, in __init__
    INTERNALERROR>     _seen.add(exc_value)
    INTERNALERROR> TypeError: unhashable type: 'ValidationError'
    
  4. Julian commented on Dec 4, 2018

    @Julian
    Member

    It's used in tests, yes, via assertEqual.

    Here's another use-case: pytest can't handle unhashable exceptions, so any users whose tests might raise a ValidationError will currently see an INTERNALERROR traceback from pytest, crashing the whole test suite.

    Sounds like a py.test bug worth filing regardless, though presumably it's just the same underlying one (that py~34-36 broke this, and then fixed it again in 3.7). pytest seems like the sort of thing though that should be trying to fix it even on those though.

  5. added 3 commits that reference this issue on Dec 6, 2018
    c0c9de2
    2c83d78
    f9995aa
  6. stuarteberg commented on Dec 6, 2018

    @stuarteberg
    Contributor

    It's used in tests, yes, via assertEqual.

    Ah, thanks for pointing that out. Still, it's not used in many places, so I've proposed #502 to eliminate the need for comparable exceptions.

    Sounds like a py.test bug worth filing regardless

    OK, I've submitted pytest-dev/pytest#4514, to see if they're interested in supporting unhashable exceptions.

  7. added a commit that references this issue on Dec 6, 2018
    a7ca0c5
  8. stuarteberg commented on Dec 6, 2018

    @stuarteberg
    Contributor

    presumably it's just the same underlying one (that py~34-36 broke this, and then fixed it again in 3.7)

    FWIW, you're right: This is not an issue when using Python 3.7. I'm using Python 3.6, where it is an issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    EnhancementSome new desired functionality

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions