From dfab94066b33e409205e36dac33bc091b7b63ee6 Mon Sep 17 00:00:00 2001 From: Chen Jui Ray Chu Date: Mon, 6 Mar 2017 23:45:57 -0500 Subject: [PATCH 1/7] Issue 1656 fixed --- lib/matplotlib/animation.py | 8 ++++++- lib/matplotlib/tests/test_animation.py | 33 +++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index fa03f90d7ad8..f36cd55e20a6 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -874,6 +874,12 @@ def __init__(self, fig, event_source=None, blit=False): if self._blit: self._setup_blit() + # Saves the animation is the figure class to prevent Python's garbage + # collection from deleteing the animation. + if (not hasattr(fig, 'animations')): + fig.animations = [] + fig.animations.append(self) + def _start(self, *args): ''' Starts interactive animation. Adds the draw frame command to the GUI @@ -1571,4 +1577,4 @@ def _draw_frame(self, framedata): raise RuntimeError('The animation function must return a ' 'sequence of Artist objects.') for a in self._drawn_artists: - a.set_animated(self._blit) + a.set_animated(self._blit) \ No newline at end of file diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index 5f1d8a5ebf8c..f5a2ae9cbcfa 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -164,7 +164,38 @@ def animate(i): except UnicodeDecodeError: pytest.xfail("There can be errors in the numpy import stack, " "see issues #1891 and #2679") + try: + length = len(fig.animations) + assert(length != 0) + except AttributeError: + pytest.fail("animations save failed, python garbage collector may " + "delete the animation objects.") + + +def test_animation_on_save(): + fig = plt.figure() + def update_line(num, data, line): + line.set_data(data[..., :num]) + return line, + + # Fixing random state for reproducibility + np.random.seed(19680801) + + data = np.random.rand(2, 25) + l, = plt.plot([], [], 'r-') + plt.xlim(0, 1) + plt.ylim(0, 1) + plt.xlabel('x') + plt.title('test') + animation.FuncAnimation(fig, update_line, + 25, fargs=(data, l), interval=50, blit=True) + try: + length = len(fig.animations) + assert(length != 0) + except AttributeError: + pytest.fail("animations save failed, python garbage collector may" + " delete the animation objects.") def test_no_length_frames(): fig, ax = plt.subplots() @@ -207,4 +238,4 @@ def test_movie_writer_registry(): animation.writers.list() # resets assert not animation.writers._dirty assert animation.writers.is_available("ffmpeg") - mpl.rcParams['animation.ffmpeg_path'] = ffmpeg_path + mpl.rcParams['animation.ffmpeg_path'] = ffmpeg_path \ No newline at end of file From 31c8eec5b1df4b486754e868af47dcca57a22f09 Mon Sep 17 00:00:00 2001 From: raychut Date: Tue, 7 Mar 2017 00:01:14 -0500 Subject: [PATCH 2/7] Add missing whitespace --- lib/matplotlib/animation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index f36cd55e20a6..d4b8cf4d68e2 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -1577,4 +1577,4 @@ def _draw_frame(self, framedata): raise RuntimeError('The animation function must return a ' 'sequence of Artist objects.') for a in self._drawn_artists: - a.set_animated(self._blit) \ No newline at end of file + a.set_animated(self._blit) From 6a48b261ce59059cfb383137eec34eea265c278b Mon Sep 17 00:00:00 2001 From: raychut Date: Tue, 7 Mar 2017 00:01:34 -0500 Subject: [PATCH 3/7] Add missing whitespace --- lib/matplotlib/tests/test_animation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index f5a2ae9cbcfa..8ee572e6bbe5 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -238,4 +238,4 @@ def test_movie_writer_registry(): animation.writers.list() # resets assert not animation.writers._dirty assert animation.writers.is_available("ffmpeg") - mpl.rcParams['animation.ffmpeg_path'] = ffmpeg_path \ No newline at end of file + mpl.rcParams['animation.ffmpeg_path'] = ffmpeg_path From 8ed048ba1ddb5e333f5310c92dbbf097d41ff584 Mon Sep 17 00:00:00 2001 From: Chen Jui Ray Chu Date: Tue, 7 Mar 2017 00:22:24 -0500 Subject: [PATCH 4/7] Replaced hasattr with a attribute call in Figure --- lib/matplotlib/animation.py | 2 -- lib/matplotlib/figure.py | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index f36cd55e20a6..b1a29c02381b 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -876,8 +876,6 @@ def __init__(self, fig, event_source=None, blit=False): # Saves the animation is the figure class to prevent Python's garbage # collection from deleteing the animation. - if (not hasattr(fig, 'animations')): - fig.animations = [] fig.animations.append(self) def _start(self, *args): diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index f6184fd2cfcb..a6b719db1598 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -354,6 +354,7 @@ def __init__(self, self._axstack = AxesStack() # track all figure axes and current axes self.clf() self._cachedRenderer = None + self.animations = [] @cbook.deprecated("2.1", alternative="Figure.patch") def figurePatch(self): From 338c8613dd7ba7b329120a0e1d8e8768e9f72d52 Mon Sep 17 00:00:00 2001 From: Chen Jui Ray Chu Date: Tue, 7 Mar 2017 00:50:44 -0500 Subject: [PATCH 5/7] Removed redundant try except statement --- lib/matplotlib/tests/test_animation.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index 8ee572e6bbe5..e9bb1ec98852 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -167,9 +167,6 @@ def animate(i): try: length = len(fig.animations) assert(length != 0) - except AttributeError: - pytest.fail("animations save failed, python garbage collector may " - "delete the animation objects.") def test_animation_on_save(): @@ -193,9 +190,7 @@ def update_line(num, data, line): try: length = len(fig.animations) assert(length != 0) - except AttributeError: - pytest.fail("animations save failed, python garbage collector may" - " delete the animation objects.") + def test_no_length_frames(): fig, ax = plt.subplots() From 036f46ae1c10ffa7bd1d77a47c5033bd6a05da36 Mon Sep 17 00:00:00 2001 From: Chen Jui Ray Chu Date: Tue, 7 Mar 2017 21:06:36 -0500 Subject: [PATCH 6/7] Removed redundant try statement --- lib/matplotlib/tests/test_animation.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index e9bb1ec98852..4542f068db2e 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -164,9 +164,8 @@ def animate(i): except UnicodeDecodeError: pytest.xfail("There can be errors in the numpy import stack, " "see issues #1891 and #2679") - try: - length = len(fig.animations) - assert(length != 0) + length = len(fig.animations) + assert(length != 0) def test_animation_on_save(): @@ -187,9 +186,8 @@ def update_line(num, data, line): plt.title('test') animation.FuncAnimation(fig, update_line, 25, fargs=(data, l), interval=50, blit=True) - try: - length = len(fig.animations) - assert(length != 0) + length = len(fig.animations) + assert(length != 0) def test_no_length_frames(): From d7a3c77c512773556599f45340f46ed0f18b86b0 Mon Sep 17 00:00:00 2001 From: Chen Jui Ray Chu Date: Wed, 8 Mar 2017 22:45:32 -0500 Subject: [PATCH 7/7] renamed fig.animation to fig._keep_alives --- lib/matplotlib/animation.py | 2 +- lib/matplotlib/figure.py | 2 +- lib/matplotlib/tests/test_animation.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index 41009df77271..3727a2d3caba 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -876,7 +876,7 @@ def __init__(self, fig, event_source=None, blit=False): # Saves the animation is the figure class to prevent Python's garbage # collection from deleteing the animation. - fig.animations.append(self) + fig._keep_alives.append(self) def _start(self, *args): ''' diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index a6b719db1598..6d44bfe4c184 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -354,7 +354,7 @@ def __init__(self, self._axstack = AxesStack() # track all figure axes and current axes self.clf() self._cachedRenderer = None - self.animations = [] + self._keep_alives = [] @cbook.deprecated("2.1", alternative="Figure.patch") def figurePatch(self): diff --git a/lib/matplotlib/tests/test_animation.py b/lib/matplotlib/tests/test_animation.py index 4542f068db2e..85a1862315f6 100644 --- a/lib/matplotlib/tests/test_animation.py +++ b/lib/matplotlib/tests/test_animation.py @@ -164,7 +164,7 @@ def animate(i): except UnicodeDecodeError: pytest.xfail("There can be errors in the numpy import stack, " "see issues #1891 and #2679") - length = len(fig.animations) + length = len(fig._keep_alives) assert(length != 0) @@ -186,7 +186,7 @@ def update_line(num, data, line): plt.title('test') animation.FuncAnimation(fig, update_line, 25, fargs=(data, l), interval=50, blit=True) - length = len(fig.animations) + length = len(fig._keep_alives) assert(length != 0)