Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 385dd94

Browse files
authored
Merge pull request #13567 from anntzer/moviewritercache
Deprecate MovieWriterRegistry cache-dirtyness system.
2 parents d511ab8 + 8d0b07b commit 385dd94

File tree

4 files changed

+66
-67
lines changed

4 files changed

+66
-67
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Deprecations
2+
````````````
3+
4+
The following methods and attributes of the `MovieWriterRegistry` class are
5+
deprecated: ``set_dirty``, ``ensure_not_dirty``, ``reset_available_writers``,
6+
``avail``.
7+
8+
The ``rcsetup.validate_animation_writer_path`` function is deprecated.
9+
10+
`MovieWriterRegistry` now always checks the availability of the writer classes
11+
before returning them. If one wishes, for example, to get the first available
12+
writer, without performing the availability check on subsequent writers, it is
13+
now possible to iterate over the registry, which will yield the names of the
14+
available classes.

lib/matplotlib/animation.py

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,11 @@ def correct_roundoff(x, dpi, n):
9696
class MovieWriterRegistry:
9797
'''Registry of available writer classes by human readable name.'''
9898
def __init__(self):
99-
self.avail = dict()
10099
self._registered = dict()
101-
self._dirty = False
102100

101+
@cbook.deprecated("3.2")
103102
def set_dirty(self):
104103
"""Sets a flag to re-setup the writers."""
105-
self._dirty = True
106104

107105
def register(self, name):
108106
"""Decorator for registering a class under a name.
@@ -113,32 +111,27 @@ def register(self, name):
113111
class Foo:
114112
pass
115113
"""
116-
def wrapper(writerClass):
117-
self._registered[name] = writerClass
118-
if writerClass.isAvailable():
119-
self.avail[name] = writerClass
120-
return writerClass
114+
def wrapper(writer_cls):
115+
self._registered[name] = writer_cls
116+
return writer_cls
121117
return wrapper
122118

119+
@cbook.deprecated("3.2")
123120
def ensure_not_dirty(self):
124121
"""If dirty, reasks the writers if they are available"""
125-
if self._dirty:
126-
self.reset_available_writers()
127122

123+
@cbook.deprecated("3.2")
128124
def reset_available_writers(self):
129125
"""Reset the available state of all registered writers"""
130-
self.avail = {name: writerClass
131-
for name, writerClass in self._registered.items()
132-
if writerClass.isAvailable()}
133-
self._dirty = False
134126

135-
def list(self):
136-
'''Get a list of available MovieWriters.'''
137-
self.ensure_not_dirty()
138-
return list(self.avail)
127+
@cbook.deprecated("3.2")
128+
@property
129+
def avail(self):
130+
return {name: self._registered[name] for name in self.list()}
139131

140132
def is_available(self, name):
141-
'''Check if given writer is available by name.
133+
"""
134+
Check if given writer is available by name.
142135
143136
Parameters
144137
----------
@@ -147,19 +140,28 @@ def is_available(self, name):
147140
Returns
148141
-------
149142
available : bool
150-
'''
151-
self.ensure_not_dirty()
152-
return name in self.avail
153-
154-
def __getitem__(self, name):
155-
self.ensure_not_dirty()
156-
if not self.avail:
157-
raise RuntimeError("No MovieWriters available!")
143+
"""
158144
try:
159-
return self.avail[name]
145+
cls = self._registered[name]
160146
except KeyError:
161-
raise RuntimeError(
162-
'Requested MovieWriter ({}) not available'.format(name))
147+
return False
148+
return cls.isAvailable()
149+
150+
def __iter__(self):
151+
"""Iterate over names of available writer class."""
152+
for name in self._registered:
153+
if self.is_available(name):
154+
yield name
155+
156+
def list(self):
157+
"""Get a list of available MovieWriters."""
158+
return [*self]
159+
160+
def __getitem__(self, name):
161+
"""Get an available writer class from its name."""
162+
if self.is_available(name):
163+
return self._registered[name]
164+
raise RuntimeError(f"Requested MovieWriter ({name}) not available")
163165

164166

165167
writers = MovieWriterRegistry()
@@ -1091,22 +1093,21 @@ def func(current_frame: int, total_frames: int) -> Any
10911093
# If we have the name of a writer, instantiate an instance of the
10921094
# registered class.
10931095
if isinstance(writer, str):
1094-
if writer in writers.avail:
1096+
if writers.is_available(writer):
10951097
writer = writers[writer](fps, codec, bitrate,
10961098
extra_args=extra_args,
10971099
metadata=metadata)
10981100
else:
1099-
if writers.list():
1100-
alt_writer = writers[writers.list()[0]]
1101-
_log.warning("MovieWriter %s unavailable; trying to use "
1102-
"%s instead.", writer, alt_writer)
1103-
writer = alt_writer(
1104-
fps, codec, bitrate,
1105-
extra_args=extra_args, metadata=metadata)
1106-
else:
1101+
alt_writer = next(writers, None)
1102+
if alt_writer is None:
11071103
raise ValueError("Cannot save animation: no writers are "
11081104
"available. Please install ffmpeg to "
11091105
"save animations.")
1106+
_log.warning("MovieWriter %s unavailable; trying to use %s "
1107+
"instead.", writer, alt_writer)
1108+
writer = alt_writer(
1109+
fps, codec, bitrate,
1110+
extra_args=extra_args, metadata=metadata)
11101111
_log.info('Animation.save using %s', type(writer))
11111112

11121113
if 'bbox_inches' in savefig_kwargs:

lib/matplotlib/rcsetup.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ def validate_hist_bins(s):
884884
" a sequence of floats".format(valid_strs))
885885

886886

887+
@cbook.deprecated("3.2")
887888
def validate_animation_writer_path(p):
888889
# Make sure it's a string and then figure out if the animations
889890
# are already loaded and reset the writers (which will validate
@@ -1410,15 +1411,15 @@ def _validate_linestyle(ls):
14101411
# Additional arguments for HTML writer
14111412
'animation.html_args': [[], validate_stringlist],
14121413
# Path to ffmpeg binary. If just binary name, subprocess uses $PATH.
1413-
'animation.ffmpeg_path': ['ffmpeg', validate_animation_writer_path],
1414+
'animation.ffmpeg_path': ['ffmpeg', validate_string],
14141415
# Additional arguments for ffmpeg movie writer (using pipes)
14151416
'animation.ffmpeg_args': [[], validate_stringlist],
14161417
# Path to AVConv binary. If just binary name, subprocess uses $PATH.
1417-
'animation.avconv_path': ['avconv', validate_animation_writer_path],
1418+
'animation.avconv_path': ['avconv', validate_string],
14181419
# Additional arguments for avconv movie writer (using pipes)
14191420
'animation.avconv_args': [[], validate_stringlist],
14201421
# Path to convert binary. If just binary name, subprocess uses $PATH.
1421-
'animation.convert_path': ['convert', validate_animation_writer_path],
1422+
'animation.convert_path': ['convert', validate_string],
14221423
# Additional arguments for convert movie writer (using pipes)
14231424
'animation.convert_args': [[], validate_stringlist],
14241425

lib/matplotlib/tests/test_animation.py

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -186,27 +186,14 @@ def test_no_length_frames():
186186

187187

188188
def test_movie_writer_registry():
189-
ffmpeg_path = mpl.rcParams['animation.ffmpeg_path']
190-
# Not sure about the first state as there could be some writer
191-
# which set rcparams
192-
# assert not animation.writers._dirty
193189
assert len(animation.writers._registered) > 0
194-
animation.writers.list() # resets dirty state
195-
assert not animation.writers._dirty
196190
mpl.rcParams['animation.ffmpeg_path'] = "not_available_ever_xxxx"
197-
assert animation.writers._dirty
198-
animation.writers.list() # resets
199-
assert not animation.writers._dirty
200191
assert not animation.writers.is_available("ffmpeg")
201192
# something which is guaranteed to be available in path
202193
# and exits immediately
203194
bin = "true" if sys.platform != 'win32' else "where"
204195
mpl.rcParams['animation.ffmpeg_path'] = bin
205-
assert animation.writers._dirty
206-
animation.writers.list() # resets
207-
assert not animation.writers._dirty
208196
assert animation.writers.is_available("ffmpeg")
209-
mpl.rcParams['animation.ffmpeg_path'] = ffmpeg_path
210197

211198

212199
@pytest.mark.parametrize(
@@ -247,18 +234,14 @@ def test_failing_ffmpeg(tmpdir, monkeypatch):
247234
succeeds when called with no arguments (so that it gets registered by
248235
`isAvailable`), but fails otherwise, and add it to the $PATH.
249236
"""
250-
try:
251-
with tmpdir.as_cwd():
252-
monkeypatch.setenv("PATH", ".:" + os.environ["PATH"])
253-
exe_path = Path(str(tmpdir), "ffmpeg")
254-
exe_path.write_text("#!/bin/sh\n"
255-
"[[ $@ -eq 0 ]]\n")
256-
os.chmod(str(exe_path), 0o755)
257-
animation.writers.reset_available_writers()
258-
with pytest.raises(subprocess.CalledProcessError):
259-
make_animation().save("test.mpeg")
260-
finally:
261-
animation.writers.reset_available_writers()
237+
with tmpdir.as_cwd():
238+
monkeypatch.setenv("PATH", ".:" + os.environ["PATH"])
239+
exe_path = Path(str(tmpdir), "ffmpeg")
240+
exe_path.write_text("#!/bin/sh\n"
241+
"[[ $@ -eq 0 ]]\n")
242+
os.chmod(str(exe_path), 0o755)
243+
with pytest.raises(subprocess.CalledProcessError):
244+
make_animation().save("test.mpeg")
262245

263246

264247
@pytest.mark.parametrize("cache_frame_data, weakref_assertion_fn", [

0 commit comments

Comments
 (0)