[Numpy-svn] r6370 - trunk/doc/sphinxext

numpy-svn at scipy.org numpy-svn at scipy.org
Sun Feb 15 10:44:58 EST 2009


Author: ptvirtan
Date: 2009-02-15 09:44:47 -0600 (Sun, 15 Feb 2009)
New Revision: 6370

Modified:
   trunk/doc/sphinxext/plot_directive.py
Log:
sphinxext: clean up plot directive, and merge some features from matplotlib

Modified: trunk/doc/sphinxext/plot_directive.py
===================================================================
--- trunk/doc/sphinxext/plot_directive.py	2009-02-15 12:03:15 UTC (rev 6369)
+++ trunk/doc/sphinxext/plot_directive.py	2009-02-15 15:44:47 UTC (rev 6370)
@@ -57,6 +57,9 @@
     plot_include_source
         Default value for the include-source option
 
+    plot_formats
+        The set of files to generate. Default: ['png', 'pdf', 'hires.png'],
+        ie. everything.
 
 TODO
 ----
@@ -75,22 +78,27 @@
     setup.app = app
     setup.config = app.config
     setup.confdir = app.confdir
-    
-    app.add_config_value('plot_output_dir', '_static', True)
+
+    static_path = '_static'
+    if hasattr(app.config, 'html_static_path') and app.config.html_static_path:
+        static_path = app.config.html_static_path[0]
+
+    app.add_config_value('plot_output_dir', static_path, True)
     app.add_config_value('plot_pre_code', '', True)
     app.add_config_value('plot_rcparams', sane_rcparameters, True)
     app.add_config_value('plot_include_source', False, True)
+    app.add_config_value('plot_formats', ['png', 'hires.png', 'pdf'], True)
 
     app.add_directive('plot', plot_directive, True, (0, 1, False),
                       **plot_directive_options)
 
 sane_rcparameters = {
-    'font.size': 8,
-    'axes.titlesize': 8,
-    'axes.labelsize': 8,
-    'xtick.labelsize': 8,
-    'ytick.labelsize': 8,
-    'legend.fontsize': 8,
+    'font.size': 9,
+    'axes.titlesize': 9,
+    'axes.labelsize': 9,
+    'xtick.labelsize': 9,
+    'ytick.labelsize': 9,
+    'legend.fontsize': 9,
     'figure.figsize': (4, 3),
 }
 
@@ -134,10 +142,16 @@
     # Change the working directory to the directory of the example, so
     # it can get at its data files, if any.
     pwd = os.getcwd()
+    old_sys_path = list(sys.path)
     if code_path is not None:
-        os.chdir(os.path.dirname(code_path))
+        dirname = os.path.abspath(os.path.dirname(code_path))
+        os.chdir(dirname)
+        sys.path.insert(0, dirname)
+
+    # Redirect stdout
     stdout = sys.stdout
     sys.stdout = cStringIO.StringIO()
+    
     try:
         code = unescape_doctest(code)
         ns = {}
@@ -145,9 +159,11 @@
         exec code in ns
     finally:
         os.chdir(pwd)
+        sys.path[:] = old_sys_path
         sys.stdout = stdout
     return ns
 
+
 #------------------------------------------------------------------------------
 # Generating figures
 #------------------------------------------------------------------------------
@@ -160,16 +176,19 @@
     return (not os.path.exists(derived)
             or os.stat(derived).st_mtime < os.stat(original).st_mtime)
 
+
 def makefig(code, code_path, output_dir, output_base, config):
     """
     run a pyplot script and save the low and high res PNGs and a PDF in _static
 
     """
 
-    formats = [('png', 100),
-               ('hires.png', 200),
-               ('pdf', 50),
-               ]
+    included_formats = config.plot_formats
+    if type(included_formats) is str:
+        included_formats = eval(included_formats)
+    
+    formats = [x for x in [('png', 80), ('hires.png', 200), ('pdf', 50)]
+               if x[0] in config.plot_formats]
 
     all_exists = True
 
@@ -181,26 +200,25 @@
             break
 
     if all_exists:
-        return 1
+        return [output_base]
 
-    # Then look for multi-figure output files, assuming
-    # if we have some we have all...
-    i = 0
-    while True:
-        all_exists = True
+    # Then look for multi-figure output files
+    image_names = []
+    for i in xrange(1000):
+        image_names.append('%s_%02d' % (output_base, i))
         for format, dpi in formats:
             output_path = os.path.join(output_dir,
-                                       '%s_%02d.%s' % (output_base, i, format))
+                                       '%s.%s' % (image_names[-1], format))
             if out_of_date(code_path, output_path):
                 all_exists = False
                 break
-        if all_exists:
-            i += 1
-        else:
+        if not all_exists:
+            # assume that if we have one, we have them all
+            all_exists = (i > 0)
             break
 
-    if i != 0:
-        return i
+    if all_exists:
+        return image_names
 
     # We didn't find the files, so build them
     print "-- Plotting figures %s" % output_base
@@ -212,31 +230,24 @@
     matplotlib.rcdefaults()
     matplotlib.rcParams.update(config.plot_rcparams)
 
-    try:
-        run_code(code, code_path)
-    except:
-        raise
-	s = cbook.exception_to_str("Exception running plot %s" % code_path)
-        warnings.warn(s)
-        return 0
+    # Run code
+    run_code(code, code_path)
 
+    # Collect images
+    image_names = []
+
     fig_managers = _pylab_helpers.Gcf.get_all_fig_managers()
     for i, figman in enumerate(fig_managers):
+        if len(fig_managers) == 1:
+            name = output_base
+        else:
+            name = "%s_%02d" % (output_base, i)
+        image_names.append(name)
         for format, dpi in formats:
-            if len(fig_managers) == 1:
-                name = output_base
-            else:
-                name = "%s_%02d" % (output_base, i)
             path = os.path.join(output_dir, '%s.%s' % (name, format))
-            try:
-                figman.canvas.figure.savefig(path, dpi=dpi)
-            except:
-                s = cbook.exception_to_str("Exception running plot %s"
-                                           % code_path)
-                warnings.warn(s)
-                return 0
+            figman.canvas.figure.savefig(path, dpi=dpi)
 
-    return len(fig_managers)
+    return image_names
 
 #------------------------------------------------------------------------------
 # Generating output
@@ -303,7 +314,7 @@
         document.attributes['_plot_counter'] = counter
         output_base = '%d-%s' % (counter, os.path.basename(file_name))
 
-    rel_name = relative_path(file_name, setup.confdir)
+    rel_name = relpath(file_name, setup.confdir)
 
     base, ext = os.path.splitext(output_base)
     if ext in ('.py', '.rst', '.txt'):
@@ -334,13 +345,19 @@
     f.write(unescape_doctest(code))
     f.close()
 
-    source_link = relative_path(target_name, rst_dir)
+    source_link = relpath(target_name, rst_dir)
 
     # determine relative reference
-    link_dir = relative_path(output_dir, rst_dir)
+    link_dir = relpath(output_dir, rst_dir)
 
     # make figures
-    num_figs = makefig(code, file_name, output_dir, output_base, config)
+    try:
+        image_names = makefig(code, file_name, output_dir, output_base, config)
+    except RuntimeError, err:
+        reporter = state.memo.reporter
+        sm = reporter.system_message(3, "Exception occurred rendering plot",
+                                     line=lineno)
+        return [sm]
 
     # generate output
     if options['include-source']:
@@ -353,20 +370,6 @@
     else:
         source_code = ""
 
-    if num_figs > 0:
-        image_names = []
-        for i in range(num_figs):
-            if num_figs == 1:
-                image_names.append(output_base)
-            else:
-                image_names.append("%s_%02d" % (output_base, i))
-    else:
-        reporter = state.memo.reporter
-        sm = reporter.system_message(3, "Exception occurred rendering plot",
-                                     line=lineno)
-        return [sm]
-
-
     opts = [':%s: %s' % (key, val) for key, val in options.items()
             if key in ('alt', 'height', 'width', 'scale', 'align', 'class')]
 
@@ -381,24 +384,49 @@
     if len(lines):
         state_machine.insert_input(
             lines, state_machine.input_lines.source(0))
+
     return []
 
 
-def relative_path(target, base):
-    target = os.path.abspath(os.path.normpath(target))
-    base = os.path.abspath(os.path.normpath(base))
+if hasattr(os.path, 'relpath'):
+    relpath = os.path.relpath
+else:
+    def relpath(target, base=os.curdir):
+        """
+        Return a relative path to the target from either the current
+        dir or an optional base dir.  Base can be a directory
+        specified either as absolute or relative to current dir.
+        """
 
-    target_parts = target.split(os.path.sep)
-    base_parts = base.split(os.path.sep)
-    rel_parts = 0
+        if not os.path.exists(target):
+            raise OSError, 'Target does not exist: '+target
 
-    while target_parts and base_parts and target_parts[0] == base_parts[0]:
-        target_parts.pop(0)
-        base_parts.pop(0)
+        if not os.path.isdir(base):
+            raise OSError, 'Base is not a directory or does not exist: '+base
 
-    rel_parts += len(base_parts)
-    return os.path.sep.join([os.path.pardir] * rel_parts + target_parts)
+        base_list = (os.path.abspath(base)).split(os.sep)
+        target_list = (os.path.abspath(target)).split(os.sep)
 
+        # On the windows platform the target may be on a completely
+        # different drive from the base.
+        if os.name in ['nt','dos','os2'] and base_list[0] <> target_list[0]:
+            raise OSError, 'Target is on a different drive to base. Target: '+target_list[0].upper()+', base: '+base_list[0].upper()
+
+        # Starting from the filepath root, work out how much of the
+        # filepath is shared by base and target.
+        for i in range(min(len(base_list), len(target_list))):
+            if base_list[i] <> target_list[i]: break
+        else:
+            # If we broke out of the loop, i is pointing to the first
+            # differing path elements.  If we didn't break out of the
+            # loop, i is pointing to identical path elements.
+            # Increment i so that in all cases it points to the first
+            # differing path elements.
+            i+=1
+
+        rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:]
+        return os.path.join(*rel_list)
+
 #------------------------------------------------------------------------------
 # plot:: directive registration etc.
 #------------------------------------------------------------------------------
@@ -412,21 +440,11 @@
     from docutils.parsers.rst.directives.images import Image
     align = Image.align
 
-try:
-    from docutils.parsers.rst import Directive
-except ImportError:
-    from docutils.parsers.rst.directives import _directives
+def plot_directive(name, arguments, options, content, lineno,
+                   content_offset, block_text, state, state_machine):
+    return run(arguments, content, options, state_machine, state, lineno)
 
-    def plot_directive(name, arguments, options, content, lineno,
-                       content_offset, block_text, state, state_machine):
-        return run(arguments, content, options, state_machine, state, lineno)
-    plot_directive.__doc__ = __doc__
-else:
-    class plot_directive(Directive):
-        def run(self):
-            return run(self.arguments, self.content, self.options,
-                       self.state_machine, self.state, self.lineno)
-    plot_directive.__doc__ = __doc__
+plot_directive.__doc__ = __doc__
 
 def _option_boolean(arg):
     if not arg or not arg.strip():




More information about the Numpy-svn mailing list