You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Now TPayload.__hash__ is set to None was done intentionally in daa213d apparently to fix#184. There are skim details on this motivation and that particular issue, but later TException was made hashable in 40219d4, again with skim details.
Given structs and unions are viable Thrift map keys, I would consider the current behavior a bug. The most direct fix is just to restore the old TPayload.__hash__ logic. That makes TPayload hashable, but I am not sure if this is a good idea as it was purposefully made unhashable. Though that fix was from 2016, nearly 10 years ago, and so I am wondering if the fix is still needed?
The less direct way to fix this is to have the binary protocol (and also the compact protocol) read a map not into a vanilla Python dict, but into some custom type that implements __contains__ and is otherwise duck-typed like a dict, but does not hash(key) if key is a TPayload, instead doing some other thing.
This PR implements the direct fix, but again let me know that is a bad idea. If so I can do the less direct fix, or another fix you think is more appropriate. Happy to fixup this PR to implement whatever.
In that issue, we can see the real problem was that we had defined a custom __eq__ method on TPayload that compares all the values in the struct. The default __hash__ (compare by id, in other words, memory address) doesn't follow the custom __eq__ method, so we should either update the __hash__ method to follow the __eq__ method, or simply disable the __hash__ method (so the current implmentation).
So I think just adding the __hash__ method back directly may not be the right solution. I just want to know, according to Thrift's specification or the Apache implementation, what is the right behavior when TPayload is used as a key for a map? Will a struct of the same type with all the same field values overwrite the key? If this is well-defined, I think we can follow that specification for our TPayload.__hash__ implementation.
@aisk thanks for the reply. I was off work for a bit, but am now back. I will review this today.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
We've been using Thriftpy2 successfully for a little while, however have run into what we consider a bug.
When a
TPayload(which I understand to be a struct, union, or exception) is used as the key inside a Thrift map, the binary protocol will attempt to store thatTPayloadvalue as the key in adict. BecauseTPayload.__hash__is set toNone, this makesTPayloadinstances unhashable, and so they can't be used fordictkeys and instead throw this exception:Now
TPayload.__hash__is set toNonewas done intentionally in daa213d apparently to fix #184. There are skim details on this motivation and that particular issue, but laterTExceptionwas made hashable in 40219d4, again with skim details.Given structs and unions are viable Thrift
mapkeys, I would consider the current behavior a bug. The most direct fix is just to restore the oldTPayload.__hash__logic. That makesTPayloadhashable, but I am not sure if this is a good idea as it was purposefully made unhashable. Though that fix was from 2016, nearly 10 years ago, and so I am wondering if the fix is still needed?The less direct way to fix this is to have the binary protocol (and also the compact protocol) read a map not into a vanilla Python
dict, but into some custom type that implements__contains__and is otherwise duck-typed like adict, but does nothash(key)ifkeyis aTPayload, instead doing some other thing.This PR implements the direct fix, but again let me know that is a bad idea. If so I can do the less direct fix, or another fix you think is more appropriate. Happy to fixup this PR to implement whatever.