attrs
attrs copied to clipboard
`attr.filters.exclude` or `include` not simultaneously usable with `validators.in_` set.
When using one of the mentioned filter functions in attrs.as_dict or as_tuple on frozen nodes that have attributes with attrs.validators.in_ set as their validator, the following TypeError is thrown:
File "<>/venv/lib/python3.11/site-packages/attr/filters.py", line 63, in exclude_
or attribute in attrs
^^^^^^^^^^^^^^^^^^
File "<>/venv/lib/python3.11/site-packages/attr/_funcs.py", line 57, in asdict
if filter is not None and not filter(a, v):
^^^^^^^^^^^^
File "<>/venv/lib/python3.11/site-packages/attr/_next_gen.py", line 211, in asdict
return _asdict(
^^^^^^^^
[...]
TypeError: unhashable type: 'set'
Trying to execute line 63, in exclude_ (top of traceback) resulted in the following error:
Traceback (most recent call last):
[...]
File "<attrs generated hash attr._make.Attribute>", line 2, in __hash__
return hash((
^^^^^^
File "<attrs generated hash attr.validators._InValidator>", line 2, in __hash__
return hash((
^^^^^^
TypeError: unhashable type: 'set'
Therefore I suspect, that the issue lies in hashing of attrs.validators.in_.
Looking further into it, I noticed that this issue occurs if the options passed to to the in_ function are not of a hashable type (in my case list objects), what made the corresponding attribute unhashable.
Casting the options into a hashable type such as tuple or frozenset might resolve this issue.
For posterity, this is what breaks:
import attrs
@attrs.define
class C:
x: int = attrs.field(validator=attrs.validators.in_({1, 2}))
i = C(2)
attrs.asdict(i, filter=attrs.filters.exclude(lambda val: True))
I believe this is fixed in https://github.com/python-attrs/attrs/pull/1320