Skip to content

Add DataclassSerializable mixin for @dataclass subclasses#13

Merged
iskandr merged 2 commits intomasterfrom
add-dataclass-serializable
Apr 20, 2026
Merged

Add DataclassSerializable mixin for @dataclass subclasses#13
iskandr merged 2 commits intomasterfrom
add-dataclass-serializable

Conversation

@iskandr
Copy link
Copy Markdown
Collaborator

@iskandr iskandr commented Apr 20, 2026

Resolves #11 (requested by vaxrank).

Summary

  • New DataclassSerializable mixin for @dataclass-decorated subclasses: supplies to_dict / from_dict / to_json / from_json without overriding the __init__ / __eq__ / __repr__ / __hash__ that @dataclass generates, so migrated classes get clean dataclass-native equality and repr.
  • Wire format is identical to the existing Serializable (both dispatch through to_serializable_reprobj.to_dict()), so mixed codebases round-trip JSON cleanly — verified in test_interop_with_legacy_serializable.
  • Preserves the _SERIALIZABLE_KEYWORD_ALIASES migration hook (rename or drop legacy field names).
  • Pickle goes through the same envelope via __reduce__.
  • Version bump: 1.0.0 → 1.1.0 (new public API, no breaking changes).

Test plan

  • ./lint.sh (ruff check + ruff format --check)
  • ./test.sh — 40 passed locally (13 new tests, dataclass_serializable.py at 100% coverage)
  • CI: lint + test matrix green on 3.9 / 3.10 / 3.11 / 3.12

Resolves #11. Provides a narrow mixin that gives
@dataclass-decorated classes the `to_dict` / `from_dict` / `to_json` /
`from_json` API without overriding the `__init__` / `__eq__` / `__repr__`
/ `__hash__` that `@dataclass` already generates.

Wire format is identical to `Serializable`: `to_serializable_repr`
dispatches on `obj.to_dict()`, so mixed codebases (some classes still
on `Serializable`, some migrated to `DataclassSerializable`) round-trip
JSON cleanly. Pickle routes through the same envelope via `__reduce__`.

Includes the `_SERIALIZABLE_KEYWORD_ALIASES` escape hatch so legacy
field names can be renamed or dropped across releases, mirroring the
same mechanism on `Serializable`.

Bumps version to 1.1.0 — new public API, no breaking changes.
@coveralls
Copy link
Copy Markdown

coveralls commented Apr 20, 2026

Coverage Report for CI Build 24681331550

Coverage increased (+1.4%) to 89.778%

Details

  • Coverage increased (+1.4%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 225
Covered Lines: 202
Line Coverage: 89.78%
Coverage Strength: 0.9 hits per line

💛 - Coveralls

…t, README

- Fix Tagged.tag annotation: LegacyTag -> LegacyTag | None to match the None default.
- Add test_frozen_dataclass_pickle_roundtrip covering __reduce__ on a frozen
  dataclass (cls(**kwargs) must work even with __setattr__ disabled).
  Promoted FrozenPoint to module level so pickle can look it up.
- Add test_keyword_aliases_inherited_from_parent to confirm alias dicts
  declared on a parent class fire for child loads — migrations can live on
  a shared base without every subclass restating them.
- README: new section documenting DataclassSerializable, including usage
  snippet and interop notes for vaxrank/pyensembl/varcode.
@iskandr iskandr merged commit f130320 into master Apr 20, 2026
5 checks passed
@iskandr iskandr deleted the add-dataclass-serializable branch April 20, 2026 17:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add DataclassSerializable mixin for @dataclass-based subclasses

2 participants