New submission from Yonatan Dankner <yonatan.dank...@gmail.com>:
TL;DR: A possible method to avoid infinite recursion when comparing dataclasses with circular references, using a decorator. >>> @dataclass ... class A: ... x: int = 1 ... self_reference: Any = field(init=False) ... ... def __post_init__(self): ... self.self_reference = self ... >>> A(x=1) == A(x=1) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 3, in __eq__ File "<string>", line 3, in __eq__ File "<string>", line 3, in __eq__ [Previous line repeated 330 more times] RecursionError: maximum recursion depth exceeded in comparison It should in my opinion return True. To avoid a recursion error, I would like to suggest a solution using a wrapper, similar to the one implemented for repr (see dataclasses._recursive_repr): If within the process of comparing two objects, we have encountered an attempt to compare these objects (meaning we have reached a loop), we should return true, since no inequalities will be discovered if we continue recursing. I suggest an addition to dataclasses.py which would look something like this (drew inspiration from _recursive_repr): def _recursive_eq(user_function): # Decorator to make a eq function return True when a loop was detected. eq_running = set() @functools.wraps(user_function) def wrapper(self, other): key = id(self), id(other), _thread.get_ident() if key in eq_running: return True eq_running.add(key) try: result = user_function(self, other) finally: eq_running.discard(key) return result return wrapper # And then replacing the _cmp_fn with the following. def _cmp_fn(name, op, self_tuple, other_tuple): return _recursive_eq(_create_fn(name, ('self', 'other'), [ 'if other.__class__ is self.__class__:', f' return {self_tuple}{op}{other_tuple}', 'return NotImplemented'])) I would like to hear your thoughts! ---------- components: Library (Lib) messages: 415641 nosy: dankner priority: normal severity: normal status: open title: Solution for recursion error when comparing dataclass objects type: behavior versions: Python 3.11 _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue47073> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com