-
-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
signal
: Add type stubs to _waveforms.pyi
.
#195
signal
: Add type stubs to _waveforms.pyi
.
#195
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not used to the new optype.numpy types so tell me if I did anything suboptimally or wrong.
That's of course no problem. I'm actually didn't expect you to notice the new optype
at all haha.
You're already using the ToFloat
and ToInt
correctly 👌🏻.
For the ToInt{1,2,N}D
array-like aliases, there's only one (subtle) difference with the np._typing._ArrayLike{}_co
analogues which you might have missed, namely that they don't accept "bare" scalars like float
or np.float16
. That way, the e.g. ToFloat
and ToFloatND
types don't overload, which can help a lot when writing overloads. It does so by additionally requiring a __len__
method to be implemented in the new onp.CanArrayND
protocol, instead of just __array__
like with np._typing._SupportsArray
.
Also for chirp I found that for the float dtypes, float16 and float32 that the output dtype is same as the input dtype but for everything else that is float64. I wanted to make an overload to cover this behaviour but I don't know how to do it without the overloads overlapping.
I left a suggestion on a possible way to deal with that. But it's also fine by me without any overloads. Because usually functions that accept e.g. float64
arrays, also accept float16
arrays (although there are a couple of exceptions to this as you know).
Technically for some of functions you can pass in complex dtypes and it will work fine, but the functions want times and I don't think they were expecting imaginary times i.e. some functions return just the real part but the array would be complex dtype if the input is complex. For this reason I didn't allow complex arrays.
Ah yes I commented on one such case before I read this. As I also said there; I have no idea what "complex time" is used for, and have never seen it used in statistical and econometric literature. But if you decide to allow it, be sure to use a separate overload, so that real input results in real output.
Anyway, I'll leave this decision up to you.
The |
It seems for some reason, the literal |
I think mypy gets confused because of the definition of ToFloatND: TypeAlias = _To1D[_f_co, float] | Sequence["ToFloatND"] The self-referential type is ignored by mypy and it substitutes "ToFloatND" with ... meaning str fits because it is a |
Yea you're right: from collections.abc import Sequence
from typing import TypeAlias
FloatVector: TypeAlias = Sequence[float]
FloatTensor: TypeAlias = FloatVector | Sequence["FloatTensor"]
rejected_float_vector: FloatVector = "ok" # OK: rejected
accepted_float_tensor: FloatTensor = [[[3.14]]] # OK: accepted
rejected_float_vector1: FloatTensor = object() # OK: rejected
rejected_float_vector2: FloatTensor = "fail" # FAIL: accepted So even though recursive types should be supported since mypy 1.7 (python/mypy#731), in this case, it results in a false negative |
As it turns out, this isn't limited to I raised it at python/mypy#18184 In the meantime, I'll try to figure out a workaround for this and publish a new |
@pavyamsiri I released a new |
…yi`. Some notes: 1. It seems the scipy implementation for `sawtooth` and `square` has a bug. The intention is that the dtype of the `t` array when it is `float32` or `float64` determines the output dtype but because the check wrongly uses a list instead of just a string this code path never runs. Therefore the output dtype is fixed to always be `float64`. This makes typing simpler however. This bug has been in the code for 19 years!
Wanted to add overloads depending on input dtype but because complex is a superclass of float, the overloads overlap and so we can't do it
Add type tests as well to check overloads are complete
float16, float32 preserve their while everything else becomes float64. Not sure how to represent this though.
In `_waveforms.pyi`
Ruff complains that we can only use simple values and `float` (the type) is not a simple value.
In `_waveforms.pyi`
`t` can be either an array or a scalar or "cutoff". Add corresponding tests
This doesn't fix `stubtest` however but it does fix `typetest`.
633310c
to
4d74dc8
Compare
Thanks for the help with the mypy bug. There's an issue remaining with the overloads for |
The simplest fix would be to just leave one of the overloads out, unless you know of a way to avoid this. |
Well, I suppose that'd be correct; they actually overlap. I'm not sure why before this it wasn't detected though 🤷🏻. I had to change quite a lot of overloads because of this as well in #197. So maybe you a similar approach I used there to solve it in this case. |
I managed to avoid the overlap but I am not convinced the overloads work as intended. I tried making some type tests like passing |
hmmm 🤔 |
Yeah I think I will go with the Any approach because I fear the brute force approach will be combinatorially explosive due to the other parameters. I added an overload to differentiate between scalar and non scalar array likes. Should be able to be merged now. |
Thanks Pavadol! |
Contributes to closing #99.
Adds type stubs to the file
_waveforms.pyi
and corresponding type tests to test overload coverage for the functiongausspulse
.Notes
I am not used to the new optype.numpy types so tell me if I did anything suboptimally or wrong.
Also for
chirp
I found that for the float dtypes,float16
andfloat32
that the output dtype is same as the input dtype but for everything else that isfloat64
. I wanted to make an overload to cover this behaviour but I don't know how to do it without the overloads overlapping.Technically for some of functions you can pass in complex dtypes and it will work fine, but the functions want times and I don't think they were expecting imaginary times i.e. some functions return just the real part but the array would be complex dtype if the input is complex. For this reason I didn't allow complex arrays.
Funny Bug
Also I discovered a 19 year old bug in scipy. The intention of
sawtooth
andsquare
is that the output dtype is the same as the inputt
's dtype if the dtype isfloat32
orfloat64
otherwise it is alwaysfloat64
. But the check forfloat32
can never pass becauseis checking if a single character string is an element of a list of a single string instead of checking if the character is part of the string like
t.dtype.char in 'fFdD'
.This makes the type checking easier because the return type is only a single possible type, but I find it a bit funny that this has been here for so long.