Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure hashability of classes with custom equality check #363

Closed
wants to merge 2 commits into from

Conversation

macisamuele
Copy link
Collaborator

Ensure hashability of classes with custom equality check.

The issue has been noticed because Yelp/swagger-spec-compatibility tests are broken (due to the fact that bravado_core.spec.Spec instances are not hashable).

In #360 equality methods have been added in order to increase testing coverage of deepcopy of instances.

Objects inheriting from object (aka all) have:

  • __eq__ implemented as always returning False
  • __hash__ implemented as returning a unique identifier of the specific instance (aka result of id)

Unfortunately, on Python, if you override one __eq__ method then the "default" __hash__ implementation is not is use, and so to make the object hashable again you need to implement __hash__ yourself (what this CR does). (Documentation reference)

… method

The implementation is quite simplistic as it relies uniquely on the memory address location of the object.
macisamuele added a commit to macisamuele/swagger-spec-compatibility that referenced this pull request Jan 4, 2020
@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 98.508% when pulling 4807fb5 on macisamuele:maci-ensure-hashability into 9c20a25 on Yelp:master.

@@ -465,6 +465,9 @@ def __delitem__(self, property_name):
else:
del self.__dict[property_name]

def __hash__(self):
return id(self)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this seems like a quick fix, I think it violates one of the assumptions of hashes and equality of objects.

If obj1 == obj2 then hash(obj1) == hash(obj2)

What you're doing here is the default for the __hash__ method. Python 3 intentionally removes it since you implemented __eq__. I'm honestly not sure if this is what we want to do, but I also don't have a better idea.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right ... for some reason I was remembering the property in the opposite direction.
I'll be fixing it before merging.
The fix might be based on top of equality check, not great as it will depend on the size of the Swagger Specs but I don't expect this to be a big issue.

If we do this that this is an issue we might just want to remove the "custom" equality checks as they were added mostly for testing purposes

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sjaensch I'm planning to drop this PR and to create a new PR where the custom __eq__ methods (that made bravado_core.spec.Spec not hashable) are replaced by a different method is_equal.

Technically that change will be backward incompatible, so I'd like to have your thoughts around it.

@macisamuele macisamuele closed this Feb 7, 2020
@macisamuele macisamuele deleted the maci-ensure-hashability branch February 7, 2020 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants