KotlinIsland / basedmypy

Based Python static type checker with baseline, sane default settings and based typing features
https://kotlinisland.github.io/basedmypy/
Other
146 stars 4 forks source link

`stubtest` false positive with `@type_check_only` subtype #816

Open jorenham opened 1 week ago

jorenham commented 1 week ago

Describe the problem

In scipy.special there are a lot of "ufuncs", which are callables numpy.ufunc instances that have a bunch of extra attributes, methods, and automatically convert an vectorize the input. But the numpy.ufunc annotations are very limited, and not very helpfull when it comes to annotating the ufuncs in scipy.special. So instead of annotating e.g. beta: np.ufunc, I created a private @type_check_only subtype of np.ufunc, and annotated it to match the type-signatures of scipy.special.beta. But running stubtest on it, gives the following error:

error: scipy.special.beta variable differs from runtime type numpy.ufunc
Stub: in file /home/joren/Workspace/scipy-stubs/scipy-stubs/special/__init__.pyi:590
scipy.special._ufuncs._UFunc21f['beta', 0]
Runtime:
def (*args, **kwargs)

(scipy.special._ufuncs._UFunc21f is the ufunc subtype)

The error message here isn't very helpful, and I don't see why it shouldn't be allowed. Because such a subtype is basically an intersection of ufunc and the beta-specific annotations (but in a way that pyright and cringe mypy also understand).

See jorenham/scipy-stubs#189 for the gory details.

Maybe I'm missing something, but I tried this a bunch of different ways, and none of them seemed to get rid of this error, so this looks like a false positive to me 🤷🏻.

Gist to reproduce

No response

Severity

annoying but workaround is available

Your Environment

basedmypy 2.7.0 (compiled: yes)
Based on mypy 1.13.0
jorenham commented 3 days ago

some of the relevant code:

https://github.com/KotlinIsland/basedmypy/blob/0935784ab77e91c869bae67be01ba0f420678620/mypy/stubtest.py#L1098-L1122

https://github.com/KotlinIsland/basedmypy/blob/0935784ab77e91c869bae67be01ba0f420678620/mypy/stubtest.py#L1564-L1584

Perhaps this mypy.types.get_proper_type function should return the supertype of a @type_check_only type 🤔? Or maybe it should use the return type of the overridden __class__ property (which I did in this case as well, but that didn't do much) if present?

https://github.com/KotlinIsland/basedmypy/blob/0935784ab77e91c869bae67be01ba0f420678620/mypy/types.py#L3498-L3514