[ty] Enforce that an attribute on a class X must be callable in order to satisfy a member on a protocol P by AlexWaygood · Pull Request #20142 · astral-sh/ruff (original) (raw)

freqtrade (https://github.com/freqtrade/freqtrade)

For these diagnostics, it looks like our eager simplification of unions is coming up against the fact that Hashable fundamentally doesn't make sense as a type in Python. (I wish pandas-stubs wouldn't use it quite so much!)

The relevant overload for pandas.DataFrame.drop() (inherited from its base class NDFrame) is here: https://github.com/pandas-dev/pandas-stubs/blob/e959fc933b024f7af6ad6efb5e8f07e8772ede61/pandas-stubs/core/generic.pyi#L341-L352. We can see that it is annotated with Hashable | Sequence[Hashable] | Index[Any], which I think ty then immediately simplifies to Hashable | Index[Any], since Sequence[Hashable] is a subtype of Hashable. The only trouble is, list[Unknown] and list[str] are both assignable to Sequence[Hashable] but not to Hashable (because list overrides __hash__ with None in typeshed's stubs to indicate that it is not hashable). That then leads us to reject this call here, even though it's clearly meant to be allowed.

I guess to fix this we could either simplify unions less or special-case Hashable in some way? Not sure.