Closed AdrianSosic closed 3 months ago
I think this is the essence of the problem:
from functools import singledispatch
from typing import Protocol
from attrs import define
class MyProtocol(Protocol):
pass
@define
class MyClass:
x: int
s = singledispatch(lambda x: None)
s.register(MyProtocol, lambda x: 1)
print(s(MyClass(1))) # '1' on 3.12, 'None' otherwise
Looks like the behavior of singledispatch
was changed :/
Yes, exactly. What do you suggest? I think this is a bug, right? Because MyClass
is treated as a subclass of MyProtocol
, which should not be the case. Do we need to raise a python ticket in this case, or what is the best approach?
It's a difficult question. I would open an issue over there and see what they think.
As for cattrs, you might want to switch to register_structure_hook_func
instead - that uses a predicate function instead of singledispatch.
I'm trying to keep the number of open issues down so I'm going to close this. We lean on singledispatch a lot (by definition) so there's nothing we can do here I think. Let me know if you have any other feedback!
Thanks for your help. As you suggested, I've opened the ticket 👍🏼 Let's see what we get ...
Description
Hi, I think the following bug is not caused by
cattrs
but rather has something to do with howProtocol
s are handled in Python 3.12, but I stumbled upon it while working withcattrs
and I'm not exactly sure what is the root cause. Perhaps @Tinche has an idea?What I Did
Consider the following code, which works as intended before 3.12 but incorrectly dispatches to the defined
MyProtocol
in 3.12. I think it is caused by the fact that theissubclass
check withProtocol
s is handled different across these Python versions.Interestingly enough, when placing a breakpoint at the
is_related
function in_compose_mro
of the functools module, theissubclass
call there simply evaluates toTrue
in 3.12 (instead of throwing the exception), which causes the wrong dispatch.Any thoughts?