-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[Bug]: FuncAnimation function not typed properly #29960
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
Comments
I am against making any change here. The documented function signature is to return a list of artists that have been updated and in the case of not blitting we currently do not leverage that does not mean we should accept callbacks with the incorrect signature. As a side note, that callback is a bit counter to the design of |
I would say that this is a very widespread use-case. Even in your examples you have at least one case where nothing is returned in your update function: https://matplotlib.org/stable/gallery/animation/rain.html#sphx-glr-gallery-animation-rain-py To be fair, when I encountered this error I tried to change the update functions in the way you suggested, and I was able to improve some of them. However for some artists the contortions and the repetition of code that are needed to modify them vs creating a new one, make that a difficult and unreadable choice. |
Also, for those not getting the reference: https://www.joelonsoftware.com/2001/12/11/back-to-basics/ |
I've opened a PR to fix that example! I do not like the path of having a "valid" callback which is blessed by static analysis that is then rendered invalid by changing a kwarg. My understanding of the type analyzers is that they will miss these overrides when I also have some concerns that if we document via typing that we do not use the returned artists then we can not chose to start using them without a deprecation cycle (the counter argument to that is we would already be careful about starting to use them because, as you correctly note, there is a lot of user code floating around that does not return the artists). |
You have a point.
Even if they currently returned the artists, if they do not pass |
I've always felt it a bit cluncky that the user has to return the modified artists. Alternative ideas:
|
Bit that would counter the purpose of blitting? |
Yes, but it would make that signature acceptable when |
FWIW we already document in the docstring that
|
Here's an example where we swap which artist is returned import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
fig, ax = plt.subplots()
ax.set_ylim(0, 10)
ax.set_ylabel('Points')
bar_container = ax.bar(['Team 1', 'Team 2'], [0, 0])
rng = np.random.default_rng()
def update(frame):
win_index = rng.integers(0, 2)
winner = bar_container.patches[win_index]
winner.set_height(winner.get_height() + 1)
return [winner]
anim = FuncAnimation(fig, update, 20, blit=True)
anim.save('bar_race.gif') However, if I Edit: am also confused why the bars don't start from zero - this happens regardless of whether I return one or both of them 😕 |
It think we have to dig deeper, what's happening inside. matplotlib/lib/matplotlib/animation.py Lines 1806 to 1807 in 828ec6f
That's likely #29856 (comment). |
Just as expected, adding
So yes, once the artists are registered, they stay animated. Which makes sense because blitting creates a static background and you cannot selectively change the content of that background. Each artist has to be either part of the background or it must be rendered on every frame. A backwards compatible migration strategy could be:
This should cover all cases:
This feels slightly more sane. Additional remarks:
Edit: If we want to keep it small here, we could also do it the other way round: define |
`func` and `init_func` may return None (which is ok if `blit=False`). Since gating the allowed signature on the state of `blit` is not feasible, we err on the side on being too permissive in the type definition: Rather not flag a type error and only raise on runtime than complain on an actually working signature. Closes matplotlib#29960.
`func` and `init_func` may return None (which is ok if `blit=False`). Since gating the allowed signature on the state of `blit` is not feasible, we err on the side on being too permissive in the type definition: Rather not flag a type error and only raise on runtime than complain on an actually working signature. Closes matplotlib#29960.
Bug summary
Type checkers complain when one uses a function that returns
None
as the parameter ofFuncAnimation
. However, whenblit=False
, the return value of the function is ignored.Code for reproduction
Actual outcome
MyPy says
Argument 2 to "FuncAnimation" has incompatible type "Callable[[int], None]"; expected "Callable[..., Iterable[Artist]]"
, but the code executes without problems.Expected outcome
No MyPy error.
Additional information
I think is possible to allow functions that return arbitrary
object
by combiningoverload
andLiteral[True]
/Literal[False]
for theblit
argument.Operating system
Any
Matplotlib Version
3.10.0
Matplotlib Backend
No response
Python version
No response
Jupyter version
No response
Installation
pip
The text was updated successfully, but these errors were encountered: