Skip to content
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

address FuncAnimantion trying to take lengths of generators #2634

Merged
merged 4 commits into from Jan 6, 2014

Conversation

tacaswell
Copy link
Member

If an iterable is passed into FuncAnimation check if it has
__len__ before trying to take it's length

closes #1769

@efiring
Copy link
Member

efiring commented Nov 30, 2013

The "closes" part of the commit message is pointing to the wrong issue.

If an iterable is passed into `FuncAnimation` check if it has
`__len__` before trying to take it's length

closes matplotlib#1769
@tacaswell
Copy link
Member Author

fixed, transposed the last two digits.

@WeatherGod
Copy link
Member

From my experience with this module, I think this is just fine. However, I think this clashes with the new single-dispatch generic functions: http://www.python.org/dev/peps/pep-0443/ (or at least, we may be needing to rethink how we duck-type.

@tacaswell
Copy link
Member Author

Would it be better to do this with a try/catch block? I was trying to be clever and was looking for the moral equivalent of callable.

@WeatherGod
Copy link
Member

I think so. And I certainly don't think it is "wrong", per se, as I have
done the same in the past. I just simply learned about this feature
recently and am trying to make sure we are being forward-compatible. Note,
I am not exactly sure what the exception would be to catch.

@tacaswell
Copy link
Member Author

As the only thing this is setting is the number of frames to cache, and it behaves sensibly if save_count is not set, we can just catch everything. If there are other problems with the iterator they should be dealt with else where.

@@ -1000,7 +1000,8 @@ def __init__(self, fig, func, frames=None, init_func=None, fargs=None,
self._iter_gen = frames
elif iterable(frames):
self._iter_gen = lambda: iter(frames)
self.save_count = len(frames)
if hasattr(frames, '__len__'):
self.save_count = len(frames)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if save_count isn't set. Is this a problem?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh. Urgh, it defaults to 100. Perhaps we are better assuming that the generator isn't infinite and casting it to a list?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why that is a problem, it will just keep a rolling buffer of that length. It isn't useful, but it's not really harmful. I might also be confused.

I think it is important to keep the ability to have infinite generators, this is a quick way to spin up realtime-ish diagnostic displays.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, thanks @tacaswell - I misunderstood what thee save count was doing. Ignore me 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, I have never figured out where the saved frames are used....

I am not sure if it is precursor work for a feature that never got finished or I just don't understand what it is doing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tacaswell - I think we should try to add a test case (hopefully it will be quite straight forward) which exercises this code path.

@tacaswell
Copy link
Member Author

@pelson Test added


anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=iter(range(5)))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be an assertion here? I appreciate the fact that you're calling the constructor, and that before it was raising an Exception, but it'd be nice to test the attributes which you expect to have been set.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the discussion above about the value it defaults to and my confusion of what this value actually does (does it make sense to keep a rolling buffer of an infinite generator?) I think it is better to just test 'does it blow up' here due to the high chance of what it defaults to changing in the (near) future.

@tacaswell
Copy link
Member Author

@pelson any further thoughts on this PR?

pelson added a commit that referenced this pull request Jan 6, 2014
address FuncAnimantion trying to take lengths of generators
@pelson pelson merged commit 397c27a into matplotlib:master Jan 6, 2014
@pelson
Copy link
Member

pelson commented Jan 6, 2014

Yep. It's good to go! Cheers @tacaswell.

@tacaswell tacaswell deleted the animation_iter_length branch January 6, 2014 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

FunctionAnimator tries to take length of iterator
4 participants