Skip to content

✨ Make blocks and fields hashable#563

Merged
MiWeiss merged 4 commits into
mainfrom
537-block-hash
Jun 12, 2026
Merged

✨ Make blocks and fields hashable#563
MiWeiss merged 4 commits into
mainfrom
537-block-hash

Conversation

@MiWeiss

@MiWeiss MiWeiss commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Block.__eq__ and Field.__eq__ were defined without __hash__, making all blocks and fields unhashable (set(library.entries) raised TypeError). This PR decides and implements the hash/equality semantics:

  • Equality stays value-based (unchanged): same type + same __dict__.
  • Hashes use a stable subset of the eq-attributes(type, start_line, raw) for blocks, (type, start_line, key) for fields — so equal objects always hash equal (hash contract holds). Mutable/unhashable attributes (fields, parser_metadata, field values that may be lists/NameParts) are excluded, so a block doesn't lose its hash when middleware mutates values. As with any hashable-mutable design, mutating the hashed attributes while an object sits in a set/dict is unsupported.
  • Library.remove/replace are now identity-first: with two equal blocks in a library (e.g. identical comments), the exact instance passed is removed/replaced; equality matching remains as fallback, so existing code keeps working.

Tests

  • Equal entries/strings/fields hash equal; set deduplication and dict lookup work (including fields with unhashable list values).
  • remove/replace with two equal comments operate on the passed instance, verified via is.

Fixes #537

🤖 Generated with Claude Code

MiWeiss and others added 2 commits June 12, 2026 13:15
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MiWeiss MiWeiss merged commit fb2eb27 into main Jun 12, 2026
31 checks passed
@MiWeiss MiWeiss deleted the 537-block-hash branch June 12, 2026 12:18
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.

Blocks and Fields are unhashable (__eq__ without __hash__)

1 participant