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
Self-review before pushing caught two subtle regressions in the prior two
commits:
1. ``_reconstruct`` used plain ``setattr`` to restore ``init=False`` fields
after construction, which raises ``FrozenInstanceError`` on
``@dataclass(frozen=True)``. Switch to ``object.__setattr__`` — the same
bypass frozen dataclasses themselves use in ``__post_init__``.
2. ``Json.__hash__`` / ``Struct.__hash__`` hashed the canonical JSON string.
That renders ``1`` and ``1.0`` as distinct strings, violating the
``__eq__`` / ``__hash__`` contract when users mix numeric types
(``1 == 1.0 == True`` in Python, but ``hash('1') != hash('1.0')``).
Replace with a recursive ``_make_hashable`` that converts dicts to
``frozenset`` of items and lists to ``tuple``s. Python's built-in
hashing then collapses ``1 == 1.0 == True`` to the same bucket, and
equal wrapped values produce equal hashes.
``_make_hashable`` lives in ``base.py`` so any future IOType wrapping
unhashable values can reuse it.
Regression tests added for:
- Frozen dataclass with ``init=False`` field round-trip.
- ``Json({'x': 1}) == Json({'x': 1.0})`` and ``hash()`` equality.
- Same for ``Struct({'x': 1})`` / ``Struct({'x': 1.0})``.
- ``Json({'x': True}) == Json({'x': 1})`` hash equality.
- ``Json([1, 2, 3]) == Json([1.0, 2.0, 3.0])`` hash equality.
0 commit comments