6464class MovieWriterRegistry (object ):
6565 def __init__ (self ):
6666 self .avail = dict ()
67+ self ._registered = dict ()
68+ self ._dirty = False
69+
70+ def set_dirty (self ):
71+ """Sets a flag to re-setup the writers"""
72+ self ._dirty = True
6773
6874 # Returns a decorator that can be used on classes to register them under
6975 # a name. As in:
@@ -72,19 +78,36 @@ def __init__(self):
7278 # pass
7379 def register (self , name ):
7480 def wrapper (writerClass ):
81+ self ._registered [name ] = writerClass
7582 if writerClass .isAvailable ():
7683 self .avail [name ] = writerClass
7784 return writerClass
7885 return wrapper
7986
87+ def ensure_not_dirty (self ):
88+ """If dirty, reasks the writers if they are available"""
89+ if self ._dirty :
90+ self .reset_available_writers ()
91+
92+ def reset_available_writers (self ):
93+ """Reset the available state of all registered writers"""
94+ self .avail = {}
95+ for name , writerClass in self ._registered .items ():
96+ if writerClass .isAvailable ():
97+ self .avail [name ] = writerClass
98+ self ._dirty = False
99+
80100 def list (self ):
81101 ''' Get a list of available MovieWriters.'''
102+ self .ensure_not_dirty ()
82103 return list (self .avail .keys ())
83104
84105 def is_available (self , name ):
106+ self .ensure_not_dirty ()
85107 return name in self .avail
86108
87109 def __getitem__ (self , name ):
110+ self .ensure_not_dirty ()
88111 if not self .avail :
89112 raise RuntimeError ("No MovieWriters available!" )
90113 return self .avail [name ]
@@ -315,10 +338,11 @@ def isAvailable(cls):
315338 Check to see if a MovieWriter subclass is actually available by
316339 running the commandline tool.
317340 '''
318- if not cls .bin_path ():
341+ bin_path = cls .bin_path ()
342+ if not bin_path :
319343 return False
320344 try :
321- p = subprocess .Popen (cls . bin_path () ,
345+ p = subprocess .Popen (bin_path ,
322346 shell = False ,
323347 stdout = subprocess .PIPE ,
324348 stderr = subprocess .PIPE ,
@@ -432,9 +456,19 @@ def finish(self):
432456 # Check error code for creating file here, since we just run
433457 # the process here, rather than having an open pipe.
434458 if self ._proc .returncode :
435- raise RuntimeError ('Error creating movie, return code: '
436- + str (self ._proc .returncode )
437- + ' Try running with --verbose-debug' )
459+ try :
460+ stdout = [s .decode () for s in self ._proc ._stdout_buff ]
461+ stderr = [s .decode () for s in self ._proc ._stderr_buff ]
462+ verbose .report ("MovieWriter.finish: stdout: %s" % stdout ,
463+ level = 'helpful' )
464+ verbose .report ("MovieWriter.finish: stderr: %s" % stderr ,
465+ level = 'helpful' )
466+ except Exception as e :
467+ pass
468+ msg = ('Error creating movie, return code: ' +
469+ str (self ._proc .returncode ) +
470+ ' Try setting mpl.verbose.set_level("helpful")' )
471+ raise RuntimeError (msg )
438472
439473 def cleanup (self ):
440474 MovieWriter .cleanup (self )
@@ -619,12 +653,28 @@ def _init_from_registry(cls):
619653 binpath = ''
620654 rcParams [cls .exec_key ] = rcParamsDefault [cls .exec_key ] = binpath
621655
656+ @classmethod
657+ def isAvailable (cls ):
658+ '''
659+ Check to see if a ImageMagickWriter is actually available
660+
661+ Done by first checking the windows registry (if applicable) and then
662+ running the commandline tool.
663+ '''
664+ bin_path = cls .bin_path ()
665+ if bin_path == "convert" :
666+ cls ._init_from_registry ()
667+ return super (ImageMagickBase , cls ).isAvailable ()
622668
623669ImageMagickBase ._init_from_registry ()
624670
625671
672+ # Note: the base classes need to be in that order to get
673+ # isAvailable() from ImageMagickBase called and not the
674+ # one from MovieWriter. The latter is then called by the
675+ # former.
626676@writers .register ('imagemagick' )
627- class ImageMagickWriter (MovieWriter , ImageMagickBase ):
677+ class ImageMagickWriter (ImageMagickBase , MovieWriter ):
628678 def _a
C02E
rgs (self ):
629679 return ([self .bin_path (),
630680 '-size' , '%ix%i' % self .frame_size , '-depth' , '8' ,
@@ -633,8 +683,12 @@ def _args(self):
633683 + self .output_args )
634684
635685
686+ # Note: the base classes need to be in that order to get
687+ # isAvailable() from ImageMagickBase called and not the
688+ # one from MovieWriter. The latter is then called by the
689+ # former.
636690@writers .register ('imagemagick_file' )
637- class ImageMagickFileWriter (FileMovieWriter , ImageMagickBase ):
691+ class ImageMagickFileWriter (ImageMagickBase , FileMovieWriter ):
638692 supported_formats = ['png' , 'jpeg' , 'ppm' , 'tiff' , 'sgi' , 'bmp' ,
639693 'pbm' , 'raw' , 'rgba' ]
640694
0 commit comments