Source code for qs_codec.models.weak_wrapper
"""A wrapper that allows weak references to be used as dictionary keys."""
import typing as t
from dataclasses import dataclass
[docs]
@dataclass(frozen=True)
class WeakWrapper:
"""A wrapper that allows weak references to be used as dictionary keys."""
value: t.Any
def __hash__(self) -> int:
"""Return the hash of the value."""
return hash(self._hash_recursive(self.value, seen=set(), stack=set()))
def _hash_recursive(
self, value: t.Any, seen: set, stack: set, depth: int = 0, max_depth: int = 1000
) -> t.Union[t.Tuple, t.Any]:
"""Recursively hash a value."""
if id(value) in stack:
raise ValueError("Circular reference detected")
seen.add(id(value))
stack.add(id(value))
if depth > max_depth:
raise ValueError("Maximum recursion depth exceeded")
if isinstance(value, t.Mapping):
result = tuple((k, self._hash_recursive(v, seen, stack, depth + 1)) for k, v in sorted(value.items()))
elif isinstance(value, (t.List, t.Set)):
result = tuple(self._hash_recursive(v, seen, stack, depth + 1) for v in value)
else:
result = value
stack.remove(id(value))
return result