Created
April 13, 2023 17:28
-
-
Save sdshlanta/ccafe487a32561d2c33b175b9a085de4 to your computer and use it in GitHub Desktop.
This is a utility class for safely checking dataclass structures when they may contain circular references. Such as in the case of parent child relationships where parents have references to their children and the children have references to all of their parents.
This file contains 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
from dataclasses import ( | |
dataclass, | |
fields, | |
) | |
@dataclass(eq=False) | |
class RecursiveCompareMixin: | |
"""A utility class to provide recursion safe dataclass comparison. | |
""" | |
def __eq__(self, __o: object) -> bool: | |
# Check if we are are already checking, if we are, return True. | |
# Returning True here is fine because the only case where we recurse | |
# into the same object when checking equality is when examining an | |
# objects parent list. As we are already checking the object's | |
# equality, the actual comparison value will be established higher up | |
# the stack. | |
if getattr(self, '__already_checking__', False): | |
return True | |
# Set the recursion guard to prevent infinite recursion. | |
object.__setattr__(self, '__already_checking__', True) | |
# Get our fields and the other object's | |
s_fields = fields(self) | |
o_fields = fields(__o) | |
# If the fields are different we are not the same. | |
if s_fields != o_fields: | |
return False | |
# Compare the fields of each object. If there is a difference, return | |
# False. | |
for s_field, o_field in zip(s_fields, o_fields): | |
if getattr(self, s_field.name) != getattr(__o, o_field.name): | |
return False | |
# After finishing the comparison set the recursion guard to False to | |
# allow for the object to be checked again. | |
object.__setattr__(self, '__already_checking__', False) | |
return True |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment