python-attrs / python-attrs/cattrs
Documentation does not explain unstruct_collection_overrides' input
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 159
- Avg merge
- 12h 21m
- Merged PRs (30d)
- 6
Description
- cattrs version: 23.2.3
- Python version: 3.11.4
- Operating System: MacOS
Description
I am trying to unstructure sets into something that JSON can cope with and that is canonical (equal for any two equal sets; set iteration order can differ for equal sets). I tried unstruct_collection_overrides={Set: sorted} and obtained a very confusing error ("< not supported between dict and dict"). It turns out that the problem is that the functions in unstruct_collection_overrides receive a generator that emits the unstructured contents of the collection (at least for Set; I'm not sure for dicts). Since the objects in my set are frozen attrs objects, they themselves work fine in a Set (and being sorted), but once unstructured they become dictionaries, which can't be sorted.
[Edited to add: my conclusion is that this isn't really possible; that's not the bug, that's just an unfortunate limitation.]
The problem: the documentation at https://catt.rs/en/stable/unstructuring.html#customizing-collection-unstructuring never specifies what the unstructuring functions receive as input. Neither does the docstring for Converter (https://catt.rs/en/stable/cattrs.html#cattrs.Converter). A little explanation would have helped tremendously in tracking down the mysterious error.
What I Did
@frozen
class A:
x: int = 0
y: int = 0
def convert_set(s):
list_s = list(s)
print(f"{list_s=}")
return sorted(list_s)
converter = Converter(unstruct_collection_overrides={Set: convert_set})
converter.unstructure({A(x=1), A(x=2), A(x=3)})
gives
list_s=[{'x': 3, 'y': 0}, {'x': 1, 'y': 0}, {'x': 2, 'y': 0}]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[12], [line 15](vscode-notebook-cell:?execution_count=12&line=15)
[10](vscode-notebook-cell:?execution_count=12&line=10) return sorted(list_s)
[13](vscode-notebook-cell:?execution_count=12&line=13) converter = Converter(unstruct_collection_overrides={Set: convert_set})
---> [15](vscode-notebook-cell:?execution_count=12&line=15) converter.unstructure({A(x=1), A(x=2), A(x=3)})
File [~/Library/Caches/pypoetry/virtualenvs/da-dropper-wire-data-l5CQQYIb-py3.11/lib/python3.11/site-packages/cattrs/converters.py:238](https://file+.vscode-resource.vscode-cdn.net/Users/annearchibald/projects/da-dropper-wire-data/analysis/~/Library/Caches/pypoetry/virtualenvs/da-dropper-wire-data-l5CQQYIb-py3.11/lib/python3.11/site-packages/cattrs/converters.py:238), in BaseConverter.unstructure(self, obj, unstructure_as)
[237](https://file+.vscode-resource.vscode-cdn.net/Users/annearchibald/projects/da-dropper-wire-data/analysis/~/Library/Caches/pypoetry/virtualenvs/da-dropper-wire-data-l5CQQYIb-py3.11/lib/python3.11/site-packages/cattrs/converters.py:237) def unstructure(self, obj: Any, unstructure_as: Any = None) -> Any:
--> [238](https://file+.vscode-resource.vscode-cdn.net/Users/annearchibald/projects/da-dropper-wire-data/analysis/~/Library/Caches/pypoetry/virtualenvs/da-dropper-wire-data-l5CQQYIb-py3.11/lib/python3.11/site-packages/cattrs/converters.py:238) return self._unstructure_func.dispatch(
[239](https://file+.vscode-resource.vscode-cdn.net/Users/annearchibald/projects/da-dropper-wire-data/analysis/~/Library/Caches/pypoetry/virtualenvs/da-dropper-wire-data-l5CQQYIb-py3.11/lib/python3.11/site-packages/cattrs/converters.py:239) obj.__class__ if unstructure_as is None else unstructure_as
[240](https://file+.vscode-resource.vscode-cdn.net/Users/annearchibald/projects/da-dropper-wire-data/analysis/~/Library/Caches/pypoetry/virtualenvs/da-dropper-wire-data-l5CQQYIb-py3.11/lib/python3.11/site-packages/cattrs/converters.py:240) )(obj)
File :2, in unstructure_iterable(iterable)
Cell In[12], [line 10](vscode-notebook-cell:?execution_count=12&line=10)
[8](vscode-notebook-cell:?execution_count=12&line=8) list_s = list(s)
[9](vscode-notebook-cell:?execution_count=12&line=9) print(f"{list_s=}")
---> [10](vscode-notebook-cell:?execution_count=12&line=10) return sorted(list_s)
TypeError: '<' not supported between instances of 'dict' and 'dict'
as opposed to some kind of canonically sorted list.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the “Customizing collection unstructuring” section in the unstructuring documentation and the Converter docstring. Document what input functions in unstruct_collection_overrides receive, including the unstructured collection contents, and make the explanation consistent in both locations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 64/100