Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/hiero_sdk_python/system/freeze_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,7 @@ def __eq__(self, other: object) -> bool:
if isinstance(other, int):
return self.value == other
return False

def __hash__(self) -> int:
"""Hash by value, consistent with the int-accepting __eq__."""
return hash(self.value)
4 changes: 4 additions & 0 deletions src/hiero_sdk_python/tokens/token_freeze_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ def __eq__(self, other: Any) -> bool:
if isinstance(other, int):
return self.value == other
return False

def __hash__(self) -> int:
"""Hash by value, consistent with the int-accepting __eq__."""
return hash(self.value)
4 changes: 4 additions & 0 deletions src/hiero_sdk_python/tokens/token_key_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ def __eq__(self, other: Any) -> bool:
if isinstance(other, int):
return self.value == other
return False

def __hash__(self) -> int:
"""Hash by value, consistent with the int-accepting __eq__."""
return hash(self.value)
4 changes: 4 additions & 0 deletions src/hiero_sdk_python/tokens/token_kyc_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@ def __eq__(self, other: Any) -> bool:
if isinstance(other, int):
return self.value == other
return False

def __hash__(self) -> int:
"""Hash by value, consistent with the int-accepting __eq__."""
return hash(self.value)
4 changes: 4 additions & 0 deletions src/hiero_sdk_python/tokens/token_pause_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,7 @@ def __eq__(self, other: Any) -> bool:
if isinstance(other, int):
return self.value == other
return False

def __hash__(self) -> int:
"""Hash by value, consistent with the int-accepting __eq__."""
return hash(self.value)
57 changes: 57 additions & 0 deletions tests/unit/status_enum_hashability_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""
Hashability tests for status enums that define a custom __eq__.

Defining __eq__ in a class body sets __hash__ = None unless __hash__ is
also defined — which had silently made these Enum members unhashable:
natural user code like `status in {TokenFreezeStatus.FROZEN}` raised
TypeError. These tests pin that every such enum is hashable and that its
hash is consistent with its int-accepting __eq__ (equal objects must hash
equally, so hash(MEMBER) == hash(MEMBER.value)).
"""

from __future__ import annotations

import pytest

from hiero_sdk_python.system.freeze_type import FreezeType
from hiero_sdk_python.tokens.token_freeze_status import TokenFreezeStatus
from hiero_sdk_python.tokens.token_key_validation import TokenKeyValidation
from hiero_sdk_python.tokens.token_kyc_status import TokenKycStatus
from hiero_sdk_python.tokens.token_pause_status import TokenPauseStatus


pytestmark = pytest.mark.unit

STATUS_ENUMS = [
TokenFreezeStatus,
TokenKycStatus,
TokenPauseStatus,
FreezeType,
TokenKeyValidation,
]

_IDS = [cls.__name__ for cls in STATUS_ENUMS]


@pytest.mark.parametrize("enum_cls", STATUS_ENUMS, ids=_IDS)
def test_members_are_hashable(enum_cls):
"""Every member must be hashable — usable in sets and as dict keys."""
members = list(enum_cls)

assert set(members) == set(members)
assert members[0] in set(members)

lookup = {member: member.name for member in members}
assert lookup[members[0]] == members[0].name


@pytest.mark.parametrize("enum_cls", STATUS_ENUMS, ids=_IDS)
def test_hash_is_consistent_with_int_equality(enum_cls):
"""__eq__ equates members with their int value, so their hashes must
match too — otherwise `member.value in {member}` would be False while
`member.value == member` is True."""
for member in enum_cls:
assert member == member.value
assert hash(member) == hash(member.value)
assert member.value in {member}
assert member in {member.value}
Loading