Skip to content

Honor converter hooks in make_dict_unstructure_fn - #783

Open
Vinayak19112003 wants to merge 1 commit into
python-attrs:mainfrom
Vinayak19112003:fix-566-unstructure-honor-class-methods
Open

Vinayak19112003 wants to merge 1 commit into
python-attrs:mainfrom
Vinayak19112003:fix-566-unstructure-honor-class-methods

Conversation

@Vinayak19112003

Copy link
Copy Markdown

Closes #566.

What was wrong: make_dict_unstructure_fn always generated a fresh attribute-based unstructure function, ignoring hooks already registered on the converter. So a hook factory built on top of it (like the _type-tagging factory in #566) could not be combined with the use_class_methods strategy — the metamethod was silently dropped.

The fix: when no customizations are requested (no attribute overrides, no omit_if_default/include_init_false/explicit alias setting), make_dict_unstructure_fn first asks the converter for its own unstructure hook for the class and prefers it over generating one. That covers methods picked up by use_class_methods as well as hooks registered directly for the class. Factories already being evaluated for the class are skipped so lower-precedence ones get a chance instead of recursing; FunctionDispatch.dispatch now tracks in-progress factory invocations (thread-local, observational only, no change to dispatch behavior itself) to detect that.

How I tested:

  • Reproduced the exact script from make_unstructure_dict_unstructure_fn does not honor use_class_methods #566 on current main: before the fix the second converter produced {'a': 1, '_type': 'Thing'} (metamethod ignored); after the fix it produces {'a': '1', '_type': 'Thing'}.
  • Added test_make_dict_unstructure_fn_honors_class_methods in tests/strategies/test_class_methods.py (fails on main, passes with the fix).
  • Full test suite: 916 passed, 15 xfailed (two preconf modules needing bson/pyyaml extras couldn't be collected in this environment; unrelated).
  • ruff check and ruff format --check clean on all touched files.
  • Also added a HISTORY.md changelog entry.

make_dict_unstructure_fn ignored hooks registered on the converter (for
example methods picked up by the use_class_methods strategy), so hook
factories built on top of it could not compose with those customizations.

When no customizations are requested, prefer the converter's own
unstructure hook for the class over generating a new function. Factories
already being evaluated for the class are skipped so lower-precedence
factories get a chance; in-progress factory invocations are now tracked
(thread-local) in FunctionDispatch.dispatch for this.

Fixes python-attrs#566.

This branch has not been deployed

No deployments
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.

make_unstructure_dict_unstructure_fn does not honor use_class_methods

1 participant