[Python-checkins] r64295 - in doctools/trunk: CHANGES TODO doc/rest.rst sphinx/builder.py sphinx/environment.py sphinx/htmlwriter.py sphinx/latexwriter.py
georg.brandl
python-checkins at python.org
Sun Jun 15 16:31:17 CEST 2008
Author: georg.brandl
Date: Sun Jun 15 16:31:16 2008
New Revision: 64295
Log:
Add image format handling.
Modified:
doctools/trunk/CHANGES
doctools/trunk/TODO
doctools/trunk/doc/rest.rst
doctools/trunk/sphinx/builder.py
doctools/trunk/sphinx/environment.py
doctools/trunk/sphinx/htmlwriter.py
doctools/trunk/sphinx/latexwriter.py
Modified: doctools/trunk/CHANGES
==============================================================================
--- doctools/trunk/CHANGES (original)
+++ doctools/trunk/CHANGES Sun Jun 15 16:31:16 2008
@@ -38,6 +38,9 @@
- The directories in the `html_static_path` can now contain
subdirectories.
+* The image directive now supports specifying the extension as ``.*``,
+ which makes the builder select the one that matches best.
+
* The new config value `exclude_trees` can be used to exclude whole
subtrees from the search for source files.
Modified: doctools/trunk/TODO
==============================================================================
--- doctools/trunk/TODO (original)
+++ doctools/trunk/TODO Sun Jun 15 16:31:16 2008
@@ -13,12 +13,3 @@
- "often used" combo box in sidebar
- source file cross-references?
-Web App
-*******
-
-- fix /download
-
-- discuss and debug comments system
-- prepare for databases other than sqlite for comments
-- add search via Xapian or Nucular (Python indexer - nucular.sf.net)
-- optionally have a contents tree view in the sidebar (AJAX based)?
Modified: doctools/trunk/doc/rest.rst
==============================================================================
--- doctools/trunk/doc/rest.rst (original)
+++ doctools/trunk/doc/rest.rst Sun Jun 15 16:31:16 2008
@@ -72,7 +72,7 @@
A. First item
B. Second item
-
+
Nested lists are possible, but be aware that they must be separated from the
parent list items by blank lines::
@@ -214,12 +214,27 @@
reST supports an image directive, used like so::
- .. image:: filename
+ .. image:: gnu.png
(options)
-When used within Sphinx, the ``filename`` given must be relative to the source
-file, and Sphinx will automatically copy image files over to a subdirectory of
-the output directory on building.
+When used within Sphinx, the file name given (here ``gnu.png``) must be relative
+to the source file, and Sphinx will automatically copy image files over to a
+subdirectory of the output directory on building (e.g. the ``_static`` directory
+for HTML output.)
+
+Sphinx extends the standard docutils behavior by allowing an asterisk for the
+extension::
+
+ .. image:: gnu.*
+
+Sphinx then searches for all images matching the provided pattern and determines
+their type. Each builder then chooses the best image out of these candidates.
+For instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`
+and :file:`gnu.png` existed in the source tree, the LaTeX builder would choose
+the former, while the HTML builder would prefer the latter.
+
+.. versionchanged:: 0.4
+ Added the support for file names ending in an asterisk.
Footnotes
Modified: doctools/trunk/sphinx/builder.py
==============================================================================
--- doctools/trunk/sphinx/builder.py (original)
+++ doctools/trunk/sphinx/builder.py Sun Jun 15 16:31:16 2008
@@ -62,6 +62,9 @@
self.info = app.info
self.config = app.config
+ # images that need to be copied over (source -> dest)
+ self.images = {}
+
# if None, this is set in load_env()
self.env = env
self.freshenv = freshenv
@@ -118,6 +121,28 @@
if l == 0:
self.info()
+ supported_image_types = []
+
+ def post_process_images(self, doctree):
+ """
+ Pick the best candidate for all image URIs.
+ """
+ for node in doctree.traverse(nodes.image):
+ uri = node['candidates'].get('*', None)
+ if not uri:
+ for imgtype in self.supported_image_types:
+ uri = node['candidates'].get(imgtype, None)
+ if uri:
+ node['uri'] = uri
+ break
+ else:
+ self.warn('%s:%s: %s' %
+ (node.source, node.lineno,
+ 'No matching candidate for uri: %(uri)s' % node))
+ continue
+ if uri in self.env.images:
+ self.images[uri] = self.env.images[uri][1]
+
# build methods
def load_env(self):
@@ -271,6 +296,8 @@
copysource = True
out_suffix = '.html'
indexer_format = 'json'
+ supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
+ 'image/jpeg']
def init(self):
"""Load templates."""
@@ -323,7 +350,7 @@
favicon = self.config.html_favicon and \
path.basename(self.config.html_favicon) or ''
- if os.path.splitext(favicon)[1] != '.ico':
+ if favicon and os.path.splitext(favicon)[1] != '.ico':
self.warn('html_favicon is not an .ico file')
if not isinstance(self.config.html_use_opensearch, basestring):
@@ -407,6 +434,7 @@
)
def write_doc(self, docname, doctree):
+ self.post_process_images(doctree)
destination = StringOutput(encoding='utf-8')
doctree.settings = self.docsettings
@@ -504,10 +532,10 @@
self.info()
# copy image files
- if self.env.images:
+ if self.images:
self.info(bold('copying images...'), nonl=1)
ensuredir(path.join(self.outdir, '_images'))
- for src, (_, dest) in self.env.images.iteritems():
+ for src, dest in self.images.iteritems():
self.info(' '+src, nonl=1)
shutil.copyfile(path.join(self.srcdir, src),
path.join(self.outdir, '_images', dest))
@@ -636,6 +664,8 @@
name = 'pickle'
out_suffix = '.fpickle'
indexer_format = 'pickle'
+ supported_image_types = ('image/svg+xml', 'image/png', 'image/gif',
+ 'image/jpeg')
def init(self):
self.init_translator_class()
@@ -711,6 +741,7 @@
# don't copy the reST source
copysource = False
+ supported_image_types = ['image/png', 'image/gif', 'image/jpeg']
def init(self):
StandaloneHTMLBuilder.init(self)
@@ -726,6 +757,8 @@
Builds LaTeX output to create PDF.
"""
name = 'latex'
+ supported_image_types = ['application/pdf', 'image/png', 'image/gif',
+ 'image/jpeg']
def init(self):
self.docnames = []
@@ -787,6 +820,7 @@
self.info("processing " + targetname + "... ", nonl=1)
doctree = self.assemble_doctree(docname, toctree_only,
appendices=(docclass == 'manual') and appendices or [])
+ self.post_process_images(doctree)
self.info("writing... ", nonl=1)
doctree.settings = docsettings
doctree.settings.author = author
@@ -852,9 +886,9 @@
def finish(self):
# copy image files
- if self.env.images:
+ if self.images:
self.info(bold('copying images...'), nonl=1)
- for src, (_, dest) in self.env.images.iteritems():
+ for src, dest in self.images.iteritems():
self.info(' '+src, nonl=1)
shutil.copyfile(path.join(self.srcdir, src),
path.join(self.outdir, dest))
Modified: doctools/trunk/sphinx/environment.py
==============================================================================
--- doctools/trunk/sphinx/environment.py (original)
+++ doctools/trunk/sphinx/environment.py Sun Jun 15 16:31:16 2008
@@ -14,9 +14,11 @@
import time
import heapq
import types
+import imghdr
import difflib
import cPickle as pickle
from os import path
+from glob import glob
from string import uppercase
from itertools import izip, groupby
try:
@@ -511,25 +513,43 @@
existing_names = set(v[1] for v in self.images.itervalues())
docdir = path.dirname(self.doc2path(docname, base=None))
for node in doctree.traverse(nodes.image):
+ # Map the mimetype to the corresponding image. The writer may
+ # choose the best image from these candidates. The special key * is
+ # set if there is only single candiate to be used by a writer.
+ node['candidates'] = candidates = {}
imguri = node['uri']
if imguri.find('://') != -1:
self.warn(docname, 'Nonlocal image URI found: %s' % imguri, node.line)
+ candidates['*'] = imguri
+ continue
+ imgpath = path.normpath(path.join(docdir, imguri))
+ if imgpath.endswith(os.extsep + '*'):
+ for filename in glob(imgpath):
+ basename, ext = os.path.splitext(filename)
+ if ext == '.pdf':
+ candidates['application/pdf'] = filename
+ elif ext == '.svg':
+ candidates['image/svg+xml'] = filename
+ else:
+ imgtype = imghdr.what(filename)
+ if imgtype:
+ candidates['image/' + imgtype] = filename
else:
- imgpath = path.normpath(path.join(docdir, imguri))
- node['uri'] = imgpath
- self.dependencies.setdefault(docname, set()).add(imgpath)
- if not os.access(path.join(self.srcdir, imgpath), os.R_OK):
- self.warn(docname, 'Image file not readable: %s' % imguri, node.line)
- if imgpath in self.images:
- self.images[imgpath][0].add(docname)
+ candidates['*'] = imgpath
+ for img in candidates.itervalues():
+ self.dependencies.setdefault(docname, set()).add(img)
+ if not os.access(path.join(self.srcdir, img), os.R_OK):
+ self.warn(docname, 'Image file not readable: %s' % img, node.line)
+ if img in self.images:
+ self.images[img][0].add(docname)
continue
- uniquename = path.basename(imgpath)
+ uniquename = path.basename(img)
base, ext = path.splitext(uniquename)
i = 0
while uniquename in existing_names:
i += 1
uniquename = '%s%s%s' % (base, i, ext)
- self.images[imgpath] = (set([docname]), uniquename)
+ self.images[img] = (set([docname]), uniquename)
existing_names.add(uniquename)
def process_metadata(self, docname, doctree):
Modified: doctools/trunk/sphinx/htmlwriter.py
==============================================================================
--- doctools/trunk/sphinx/htmlwriter.py (original)
+++ doctools/trunk/sphinx/htmlwriter.py Sun Jun 15 16:31:16 2008
@@ -250,9 +250,9 @@
def visit_image(self, node):
olduri = node['uri']
# rewrite the URI if the environment knows about it
- if olduri in self.builder.env.images:
+ if olduri in self.builder.images:
node['uri'] = posixpath.join(self.builder.imgpath,
- self.builder.env.images[olduri][1])
+ self.builder.images[olduri])
BaseTranslator.visit_image(self, node)
def visit_toctree(self, node):
Modified: doctools/trunk/sphinx/latexwriter.py
==============================================================================
--- doctools/trunk/sphinx/latexwriter.py (original)
+++ doctools/trunk/sphinx/latexwriter.py Sun Jun 15 16:31:16 2008
@@ -630,8 +630,8 @@
pre.append('\n')
post.append('\n')
pre.reverse()
- if node['uri'] in self.builder.env.images:
- uri = self.builder.env.images[node['uri']][1]
+ if node['uri'] in self.builder.images:
+ uri = self.builder.images[node['uri']]
else:
uri = node['uri']
if uri.find('://') != -1:
More information about the Python-checkins
mailing list