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 ]
@@ -275,10 +298,11 @@ def isAvailable(cls):
275298 Check to see if a MovieWriter subclass is actually available by
276299 running the commandline tool.
277300 '''
278- if not cls .bin_path ():
301+ bin_path = cls .bin_path ()
302+ if not bin_path :
279303 return False
280304 try :
281- p = subprocess .Popen (cls . bin_path () ,
305+ p = subprocess .Popen (bin_path ,
282306 shell = False ,
283307 stdout = subprocess .PIPE ,
284308 stderr = subprocess .PIPE ,
@@ -397,9 +421,19 @@ def finish(self):
397421 # Check error code for creating file here, since we just run
398422 # the process here, rather than having an open pipe.
399423 if self ._proc .returncode :
400- raise RuntimeError ('Error creating movie, return code: '
401- + str (self ._proc .returncode )
402- + ' Try running with --verbose-debug' )
424+ try :
425+ stdout = [s .decode () for s in self ._proc ._stdout_buff ]
426+ stderr = [s .decode () for s in self ._proc ._stderr_buff ]
427+ verbose .report ("MovieWriter.finish: stdout: %s" % stdout ,
428+ level = 'helpful' )
429+ verbose .report ("MovieWriter.finish: stderr: %s" % stderr ,
430+ level = 'helpful' )
431+ except Exception as e :
432+ pass
433+ msg = ('Error creating movie, return code: ' +
434+ str (self ._proc .returncode ) +
435+ ' Try setting mpl.verbose.set_level("helpful")' )
436+ raise RuntimeError (msg )
403437
404438 def cleanup (self ):
405439 MovieWriter .cleanup (self )
@@ -584,12 +618,28 @@ def _init_from_registry(cls):
584618 binpath = ''
585619 rcParams [cls .exec_key ] = rcParamsDefault [cls .exec_key ] = binpath
586620
621+ @classmethod
622+ def isAvailable (cls ):
623+ '''
624+ Check to see if a ImageMagickWriter is actually available
625+
626+ Done by first checking the windows registry (if applicable) and then
627+ running the commandline tool.
628+ '''
629+ bin_path = cls .bin_path ()
630+ if bin_path == "convert" :
631+ cls ._init_from_registry ()
632+ return super (ImageMagickBase , cls ).isAvailable ()
587633
588634ImageMagickBase ._init_from_registry ()
589635
590636
637+ # Note: the base classes need to be in that order to get
638+ # isAvailable() from ImageMagickBase called and not the
639+ # one from MovieWriter. The latter is then called by the
640+ # former.
591641@writers .register ('imagemagick' )
592- class ImageMagickWriter (MovieWriter , ImageMagickBase ):
642+ class ImageMagickWriter (ImageMagickBase , MovieWriter ):
593643 def _args (self ):
594644 return ([self .bin_path (),
595645 '-size' , '%ix%i' % self .frame_size , '-depth' , '8' ,
@@ -598,8 +648,12 @@ def _args(self):
598648 + self .output_args )
599649
600650
651+ # Note: the base classes need to be in that order to get
652+ # isAvailable() from ImageMagickBase called and not the
653+ # one from MovieWriter. The latter is then called by the
654+ # former.
601655@writers .register ('imagemagick_file' )
602- class ImageMagickFileWriter (FileMovieWriter , ImageMagickBase ):
656+ class ImageMagickFileWriter (ImageMagickBase , FileMovieWriter ):
603657 supported_formats = ['png' , 'jpeg' , 'ppm' , 'tiff' , 'sgi' , 'bmp' ,
604658 'pbm' , 'raw' , 'rgba' ]
605659
0 commit comments