Merged birkenfeld/sphinx into default

This commit is contained in:
Jeff Klukas 2013-02-10 15:19:16 -06:00
commit 00ce20ee17
335 changed files with 6402 additions and 1287 deletions

7
.travis.yml Normal file
View File

@ -0,0 +1,7 @@
language: python
python:
- "2.7"
- "3.3"
script: make test
install:
- python setup.py -q install

View File

@ -13,6 +13,7 @@ Other contributors, listed alphabetically, are:
* Charles Duffy -- original graphviz extension * Charles Duffy -- original graphviz extension
* Kevin Dunn -- MathJax extension * Kevin Dunn -- MathJax extension
* Josip Dzolonga -- coverage builder * Josip Dzolonga -- coverage builder
* Hernan Grecco -- search improvements
* Horst Gutmann -- internationalization support * Horst Gutmann -- internationalization support
* Martin Hans -- autodoc improvements * Martin Hans -- autodoc improvements
* Doug Hellmann -- graphviz improvements * Doug Hellmann -- graphviz improvements

116
CHANGES
View File

@ -1,6 +1,74 @@
Release 1.2 (in development) Release 1.2 (in development)
============================ ============================
* New locales: #1097: Added Basque locale.
* Fix text builder did not respect wide/fullwidth characters:
title underline width, table layout width and text wrap width.
* #1062: sphinx.ext.autodoc use __init__ method signature for class signature.
* PR#111: Respect add_autodoc_attrgetter() even when inherited-members is set.
Thanks to A. Jesse Jiryu Davis.
* #1090: Fix gettext does not extract glossary terms.
* #1070: Avoid un-pickling issues when running Python 3 and the saved
environment was created under Python 2.
* #1069: Fixed error caused when autodoc would try to format signatures of
"partial" functions without keyword arguments (patch by Artur Gaspar).
* The :confval:`latex_documents`, :confval:`texinfo_documents`, and
:confval:`man_pages` configuration values will be set to default values based
on the :confval:`master_doc` if not explicitly set in :file:`conf.py`.
Previously, if these values were not set, no output would be genereted by
their respective builders.
* The :rst:dir:`toctree` directive and the ``toctree()`` template function now
have an ``includehidden`` option that includes hidden toctree entries (bugs
#790 and #1047). A bug in the ``maxdepth`` option for the ``toctree()``
template function has been fixed (bug #1046).
* PR#99: Strip down seealso directives to normal admonitions. This removes
their unusual CSS classes (admonition-see-also), inconsistent LaTeX
admonition title ("See Also" instead of "See also"), and spurious indentation
in the text builder.
* sphinx-build now has a verbose option :option:`-v` which can be
repeated for greater effect. A single occurrance provides a
slightly more verbose output than normal. Two or more occurrences
of this option provides more detailed output which may be useful for
debugging.
* sphinx-build now provides more specific error messages when called with
invalid options or arguments.
* sphinx-build now supports the standard :option:`--help` and
:option:`--version` options.
* #869: sphinx-build now has the option :option:`-T` for printing the full
traceback after an unhandled exception.
* #976: Fix gettext does not extract index entries.
* #940: Fix gettext does not extract figure caption.
* #1067: Improve the ordering of the JavaScript search results: matches in titles
come before matches in full text, and object results are better categorized.
Also implement a pluggable search scorer.
* Fix text writer can not handle visit_legend for figure directive contents.
* PR#72: #975: Fix gettext does not extract definition terms before docutils 0.10.0
* PR#25: In inheritance diagrams, the first line of the class docstring
is now the tooltip for the class.
* PR#47: Added :mod:`sphinx.ext.linkcode` extension.
* PR#75: Added ``--follow-links`` option to sphinx-apidoc.
* PR#45: The linkcheck builder now checks ``#anchor``\ s for existence. * PR#45: The linkcheck builder now checks ``#anchor``\ s for existence.
* PR#28: Added Hungarian translation. * PR#28: Added Hungarian translation.
@ -11,11 +79,55 @@ Release 1.2 (in development)
* PR#52: ``special_members`` flag to autodoc now behaves like ``members``. * PR#52: ``special_members`` flag to autodoc now behaves like ``members``.
* #955: Fix i18n transformation.
* Handle duplicate domain indices in texinfo.
* PR#74: Fix some Russian translation.
* PR#97: Fix footnote handling in translated documents.
* Update to jQuery 1.7.1 and Underscore.js 1.3.1. * Update to jQuery 1.7.1 and Underscore.js 1.3.1.
* #1055: Fix web support with relative path to source directory.
Release 1.1.4 (in development) * #1053: The "rightsidebar" and "collapsiblesidebar" HTML theme options now work together.
==============================
* #1015: Stop overriding jQuery contains() in the JavaScript.
* #1028: Fix line block output in the text builder.
* #1018: Fix "container" directive handling in the text builder.
* #1012: Update Estonian translation.
* #1010: Make pngmath images transparent by default; IE7+ should handle it.
* #440: Fix coarse timestamp resolution in some filesystem generate wrong outdated file-list.
* #1008: Fix test failures with Python 3.3.
* #1029: Fix intersphinx_mapping values are not stable if mapping have plural key/value set with Python 3.3.
* #920: Rescue PIL packaging issue that allow import Image without PIL namespace. Thanks to Marc Schlaich.
* #1024: Improve Makefile/make.bat error message if Sphinx is not found. Thanks to anatoly techtonik.
* #1037: Fix typos in Polish translation. Thanks to Jakub Wilk.
* #1038: Fix cpp domain parser fails to parse C+11 "static constexpr" declarations. Thanks to Jakub Wilk.
* #1043: Fix sphinx-quickstart asks again and again Y|N because input() return value with extra '\r' on Python-3.2.0 + Windows. Thanks to Régis Décamps.
* #1041: Fix cpp domain parser fails to parse a const type with a modifier.
* #958: Do not preserve ``environment.pickle`` after a failed build.
* PR#88: Added the "Sphinx Developer's Guide" (:file:`doc/devguide.rst`)
which outlines the basic development process of the Sphinx project.
* Added the Docutils-native XML and pseudo-XML builders. See
:class:`XMLBuilder` and :class:`PseudoXMLBuilder`.
Release 1.1.3 (Mar 10, 2012) Release 1.1.3 (Mar 10, 2012)

View File

@ -4,7 +4,7 @@ Projects using Sphinx
This is an (incomplete) alphabetic list of projects that use Sphinx or This is an (incomplete) alphabetic list of projects that use Sphinx or
are experimenting with using it for their documentation. If you like to are experimenting with using it for their documentation. If you like to
be included, please mail to `the Google group be included, please mail to `the Google group
<http://groups.google.com/group/sphinx-dev>`_. <http://groups.google.com/group/sphinx-users>`_.
I've grouped the list into sections to make it easier to find I've grouped the list into sections to make it easier to find
interesting examples. interesting examples.
@ -70,6 +70,7 @@ Documentation using a customized version of the default theme
* Chaco: http://code.enthought.com/projects/chaco/docs/html/ * Chaco: http://code.enthought.com/projects/chaco/docs/html/
* Djagios: http://djagios.org/ * Djagios: http://djagios.org/
* GetFEM++: http://home.gna.org/getfem/ * GetFEM++: http://home.gna.org/getfem/
* Google or-tools: https://or-tools.googlecode.com/svn/trunk/documentation/user_manual/index.html
* GPAW: https://wiki.fysik.dtu.dk/gpaw/ * GPAW: https://wiki.fysik.dtu.dk/gpaw/
* Grok: http://grok.zope.org/doc/current/ * Grok: http://grok.zope.org/doc/current/
* IFM: http://fluffybunny.memebot.com/ifm-docs/index.html * IFM: http://fluffybunny.memebot.com/ifm-docs/index.html
@ -105,10 +106,11 @@ Documentation using the sphinxdoc theme
http://www.tango-controls.org/static/PyTango/latest/doc/html/index.html http://www.tango-controls.org/static/PyTango/latest/doc/html/index.html
* Reteisi: http://www.reteisi.org/contents.html * Reteisi: http://www.reteisi.org/contents.html
* Satchmo: http://www.satchmoproject.com/docs/dev/ * Satchmo: http://www.satchmoproject.com/docs/dev/
* Sphinx: http://sphinx.pocoo.org/ * Sphinx: http://sphinx-doc.org/
* Sqlkit: http://sqlkit.argolinux.org/ * Sqlkit: http://sqlkit.argolinux.org/
* Tau: http://www.tango-controls.org/static/tau/latest/doc/html/index.html * Tau: http://www.tango-controls.org/static/tau/latest/doc/html/index.html
* Total Open Station: http://tops.berlios.de/ * Total Open Station: http://tops.berlios.de/
* Turbulenz: http://docs.turbulenz.com/
* WebFaction: http://docs.webfaction.com/ * WebFaction: http://docs.webfaction.com/
@ -128,6 +130,7 @@ Documentation using another builtin theme
(agogo) (agogo)
* Sylli: http://sylli.sourceforge.net/ (nature) * Sylli: http://sylli.sourceforge.net/ (nature)
* libLAS: http://liblas.org/ (nature) * libLAS: http://liblas.org/ (nature)
* Valence: http://docs.valence.desire2learn.com/ (haiku)
Documentation using a custom theme/integrated in a site Documentation using a custom theme/integrated in a site
@ -135,7 +138,8 @@ Documentation using a custom theme/integrated in a site
* Blender: http://www.blender.org/documentation/250PythonDoc/ * Blender: http://www.blender.org/documentation/250PythonDoc/
* Blinker: http://discorporate.us/projects/Blinker/docs/ * Blinker: http://discorporate.us/projects/Blinker/docs/
* Classy: classy: http://classy.pocoo.org/ * Classy: http://classy.pocoo.org/
* DEAP: http://deap.gel.ulaval.ca/doc/0.8/index.html
* Django: http://docs.djangoproject.com/ * Django: http://docs.djangoproject.com/
* e-cidadania: http://e-cidadania.readthedocs.org/en/latest/ * e-cidadania: http://e-cidadania.readthedocs.org/en/latest/
* Flask: http://flask.pocoo.org/docs/ * Flask: http://flask.pocoo.org/docs/
@ -143,13 +147,17 @@ Documentation using a custom theme/integrated in a site
* Gameduino: http://excamera.com/sphinx/gameduino/ * Gameduino: http://excamera.com/sphinx/gameduino/
* GeoServer: http://docs.geoserver.org/ * GeoServer: http://docs.geoserver.org/
* Glashammer: http://glashammer.org/ * Glashammer: http://glashammer.org/
* Istihza (Turkish Python documentation project): http://www.istihza.com/py2/icindekiler_python.html
* MathJax: http://docs.mathjax.org/en/latest/
* MirrorBrain: http://mirrorbrain.org/docs/ * MirrorBrain: http://mirrorbrain.org/docs/
* nose: http://somethingaboutorange.com/mrl/projects/nose/ * nose: http://somethingaboutorange.com/mrl/projects/nose/
* ObjectListView: http://objectlistview.sourceforge.net/python * ObjectListView: http://objectlistview.sourceforge.net/python
* Open ERP: http://doc.openerp.com/ * Open ERP: http://doc.openerp.com/
* OpenCV: http://docs.opencv.org/
* OpenLayers: http://docs.openlayers.org/ * OpenLayers: http://docs.openlayers.org/
* PyEphem: http://rhodesmill.org/pyephem/ * PyEphem: http://rhodesmill.org/pyephem/
* German Plone 4.0 user manual: http://www.hasecke.com/plone-benutzerhandbuch/4.0/ * German Plone 4.0 user manual: http://www.hasecke.com/plone-benutzerhandbuch/4.0/
* PSI4: http://sirius.chem.vt.edu/psi4manual/latest/index.html
* Pylons: http://pylonshq.com/docs/en/0.9.7/ * Pylons: http://pylonshq.com/docs/en/0.9.7/
* PyMOTW: http://www.doughellmann.com/PyMOTW/ * PyMOTW: http://www.doughellmann.com/PyMOTW/
* pypol: http://pypol.altervista.org/ (celery) * pypol: http://pypol.altervista.org/ (celery)
@ -161,6 +169,7 @@ Documentation using a custom theme/integrated in a site
* SQLAlchemy: http://www.sqlalchemy.org/docs/ * SQLAlchemy: http://www.sqlalchemy.org/docs/
* tinyTiM: http://tinytim.sourceforge.net/docs/2.0/ * tinyTiM: http://tinytim.sourceforge.net/docs/2.0/
* tipfy: http://www.tipfy.org/docs/ * tipfy: http://www.tipfy.org/docs/
* Ubuntu packaging guide: http://developer.ubuntu.com/packaging/html/
* Werkzeug: http://werkzeug.pocoo.org/docs/ * Werkzeug: http://werkzeug.pocoo.org/docs/
* WFront: http://discorporate.us/projects/WFront/ * WFront: http://discorporate.us/projects/WFront/

View File

@ -1,7 +1,7 @@
License for Sphinx License for Sphinx
================== ==================
Copyright (c) 2007-2011 by the Sphinx team (see AUTHORS file). Copyright (c) 2007-2013 by the Sphinx team (see AUTHORS file).
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View File

@ -21,7 +21,7 @@ After installing::
Then, direct your browser to ``_build/html/index.html``. Then, direct your browser to ``_build/html/index.html``.
Or read them online at <http://sphinx.pocoo.org/>. Or read them online at <http://sphinx-doc.org/>.
Testing Testing

View File

@ -14,11 +14,14 @@ the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools. This file can also be run as a script to install or upgrade setuptools.
""" """
import os import os
import shutil
import sys import sys
import time import time
import fnmatch import fnmatch
import tempfile import tempfile
import tarfile import tarfile
import optparse
from distutils import log from distutils import log
try: try:
@ -46,7 +49,7 @@ except ImportError:
args = [quote(arg) for arg in args] args = [quote(arg) for arg in args]
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
DEFAULT_VERSION = "0.6.13" DEFAULT_VERSION = "0.6.30"
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
SETUPTOOLS_FAKED_VERSION = "0.6c11" SETUPTOOLS_FAKED_VERSION = "0.6c11"
@ -63,7 +66,7 @@ Description: xxx
""" % SETUPTOOLS_FAKED_VERSION """ % SETUPTOOLS_FAKED_VERSION
def _install(tarball): def _install(tarball, install_args=()):
# extracting the tarball # extracting the tarball
tmpdir = tempfile.mkdtemp() tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir) log.warn('Extracting in %s', tmpdir)
@ -81,11 +84,14 @@ def _install(tarball):
# installing # installing
log.warn('Installing Distribute') log.warn('Installing Distribute')
if not _python_cmd('setup.py', 'install'): if not _python_cmd('setup.py', 'install', *install_args):
log.warn('Something went wrong during the installation.') log.warn('Something went wrong during the installation.')
log.warn('See the error message above.') log.warn('See the error message above.')
# exitcode will be 2
return 2
finally: finally:
os.chdir(old_wd) os.chdir(old_wd)
shutil.rmtree(tmpdir)
def _build_egg(egg, tarball, to_dir): def _build_egg(egg, tarball, to_dir):
@ -110,6 +116,7 @@ def _build_egg(egg, tarball, to_dir):
finally: finally:
os.chdir(old_wd) os.chdir(old_wd)
shutil.rmtree(tmpdir)
# returning the result # returning the result
log.warn(egg) log.warn(egg)
if not os.path.exists(egg): if not os.path.exists(egg):
@ -144,7 +151,7 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
except ImportError: except ImportError:
return _do_download(version, download_base, to_dir, download_delay) return _do_download(version, download_base, to_dir, download_delay)
try: try:
pkg_resources.require("distribute>="+version) pkg_resources.require("distribute>=" + version)
return return
except pkg_resources.VersionConflict: except pkg_resources.VersionConflict:
e = sys.exc_info()[1] e = sys.exc_info()[1]
@ -167,6 +174,7 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
if not no_fake: if not no_fake:
_create_fake_setuptools_pkg_info(to_dir) _create_fake_setuptools_pkg_info(to_dir)
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, delay=15): to_dir=os.curdir, delay=15):
"""Download distribute from a specified location and return its filename """Download distribute from a specified location and return its filename
@ -203,6 +211,7 @@ def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
dst.close() dst.close()
return os.path.realpath(saveto) return os.path.realpath(saveto)
def _no_sandbox(function): def _no_sandbox(function):
def __no_sandbox(*args, **kw): def __no_sandbox(*args, **kw):
try: try:
@ -227,6 +236,7 @@ def _no_sandbox(function):
return __no_sandbox return __no_sandbox
def _patch_file(path, content): def _patch_file(path, content):
"""Will backup the file then patch it""" """Will backup the file then patch it"""
existing_content = open(path).read() existing_content = open(path).read()
@ -245,15 +255,18 @@ def _patch_file(path, content):
_patch_file = _no_sandbox(_patch_file) _patch_file = _no_sandbox(_patch_file)
def _same_content(path, content): def _same_content(path, content):
return open(path).read() == content return open(path).read() == content
def _rename_path(path): def _rename_path(path):
new_name = path + '.OLD.%s' % time.time() new_name = path + '.OLD.%s' % time.time()
log.warn('Renaming %s into %s', path, new_name) log.warn('Renaming %s to %s', path, new_name)
os.rename(path, new_name) os.rename(path, new_name)
return new_name return new_name
def _remove_flat_installation(placeholder): def _remove_flat_installation(placeholder):
if not os.path.isdir(placeholder): if not os.path.isdir(placeholder):
log.warn('Unkown installation at %s', placeholder) log.warn('Unkown installation at %s', placeholder)
@ -267,7 +280,7 @@ def _remove_flat_installation(placeholder):
log.warn('Could not locate setuptools*.egg-info') log.warn('Could not locate setuptools*.egg-info')
return return
log.warn('Removing elements out of the way...') log.warn('Moving elements out of the way...')
pkg_info = os.path.join(placeholder, file) pkg_info = os.path.join(placeholder, file)
if os.path.isdir(pkg_info): if os.path.isdir(pkg_info):
patched = _patch_egg_dir(pkg_info) patched = _patch_egg_dir(pkg_info)
@ -289,11 +302,13 @@ def _remove_flat_installation(placeholder):
_remove_flat_installation = _no_sandbox(_remove_flat_installation) _remove_flat_installation = _no_sandbox(_remove_flat_installation)
def _after_install(dist): def _after_install(dist):
log.warn('After install bootstrap.') log.warn('After install bootstrap.')
placeholder = dist.get_command_obj('install').install_purelib placeholder = dist.get_command_obj('install').install_purelib
_create_fake_setuptools_pkg_info(placeholder) _create_fake_setuptools_pkg_info(placeholder)
def _create_fake_setuptools_pkg_info(placeholder): def _create_fake_setuptools_pkg_info(placeholder):
if not placeholder or not os.path.exists(placeholder): if not placeholder or not os.path.exists(placeholder):
log.warn('Could not find the install location') log.warn('Could not find the install location')
@ -307,7 +322,11 @@ def _create_fake_setuptools_pkg_info(placeholder):
return return
log.warn('Creating %s', pkg_info) log.warn('Creating %s', pkg_info)
f = open(pkg_info, 'w') try:
f = open(pkg_info, 'w')
except EnvironmentError:
log.warn("Don't have permissions to write %s, skipping", pkg_info)
return
try: try:
f.write(SETUPTOOLS_PKG_INFO) f.write(SETUPTOOLS_PKG_INFO)
finally: finally:
@ -321,7 +340,10 @@ def _create_fake_setuptools_pkg_info(placeholder):
finally: finally:
f.close() f.close()
_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info) _create_fake_setuptools_pkg_info = _no_sandbox(
_create_fake_setuptools_pkg_info
)
def _patch_egg_dir(path): def _patch_egg_dir(path):
# let's check if it's already patched # let's check if it's already patched
@ -343,6 +365,7 @@ def _patch_egg_dir(path):
_patch_egg_dir = _no_sandbox(_patch_egg_dir) _patch_egg_dir = _no_sandbox(_patch_egg_dir)
def _before_install(): def _before_install():
log.warn('Before install bootstrap.') log.warn('Before install bootstrap.')
_fake_setuptools() _fake_setuptools()
@ -351,7 +374,7 @@ def _before_install():
def _under_prefix(location): def _under_prefix(location):
if 'install' not in sys.argv: if 'install' not in sys.argv:
return True return True
args = sys.argv[sys.argv.index('install')+1:] args = sys.argv[sys.argv.index('install') + 1:]
for index, arg in enumerate(args): for index, arg in enumerate(args):
for option in ('--root', '--prefix'): for option in ('--root', '--prefix'):
if arg.startswith('%s=' % option): if arg.startswith('%s=' % option):
@ -359,7 +382,7 @@ def _under_prefix(location):
return location.startswith(top_dir) return location.startswith(top_dir)
elif arg == option: elif arg == option:
if len(args) > index: if len(args) > index:
top_dir = args[index+1] top_dir = args[index + 1]
return location.startswith(top_dir) return location.startswith(top_dir)
if arg == '--user' and USER_SITE is not None: if arg == '--user' and USER_SITE is not None:
return location.startswith(USER_SITE) return location.startswith(USER_SITE)
@ -376,11 +399,14 @@ def _fake_setuptools():
return return
ws = pkg_resources.working_set ws = pkg_resources.working_set
try: try:
setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools', setuptools_dist = ws.find(
replacement=False)) pkg_resources.Requirement.parse('setuptools', replacement=False)
)
except TypeError: except TypeError:
# old distribute API # old distribute API
setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools')) setuptools_dist = ws.find(
pkg_resources.Requirement.parse('setuptools')
)
if setuptools_dist is None: if setuptools_dist is None:
log.warn('No setuptools distribution found') log.warn('No setuptools distribution found')
@ -414,7 +440,7 @@ def _fake_setuptools():
res = _patch_egg_dir(setuptools_location) res = _patch_egg_dir(setuptools_location)
if not res: if not res:
return return
log.warn('Patched done.') log.warn('Patching complete.')
_relaunch() _relaunch()
@ -422,7 +448,9 @@ def _relaunch():
log.warn('Relaunching...') log.warn('Relaunching...')
# we have to relaunch the process # we have to relaunch the process
# pip marker to avoid a relaunch bug # pip marker to avoid a relaunch bug
if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']: _cmd1 = ['-c', 'install', '--single-version-externally-managed']
_cmd2 = ['-c', 'install', '--record']
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
sys.argv[0] = 'setup.py' sys.argv[0] = 'setup.py'
args = [sys.executable] + sys.argv args = [sys.executable] + sys.argv
sys.exit(subprocess.call(args)) sys.exit(subprocess.call(args))
@ -448,7 +476,7 @@ def _extractall(self, path=".", members=None):
# Extract directories with a safe mode. # Extract directories with a safe mode.
directories.append(tarinfo) directories.append(tarinfo)
tarinfo = copy.copy(tarinfo) tarinfo = copy.copy(tarinfo)
tarinfo.mode = 448 # decimal for oct 0700 tarinfo.mode = 448 # decimal for oct 0700
self.extract(tarinfo, path) self.extract(tarinfo, path)
# Reverse sort directories. # Reverse sort directories.
@ -475,11 +503,39 @@ def _extractall(self, path=".", members=None):
self._dbg(1, "tarfile: %s" % e) self._dbg(1, "tarfile: %s" % e)
def main(argv, version=DEFAULT_VERSION): def _build_install_args(options):
"""Install or upgrade setuptools and EasyInstall""" """
tarball = download_setuptools() Build the arguments to 'python setup.py install' on the distribute package
_install(tarball) """
install_args = []
if options.user_install:
if sys.version_info < (2, 6):
log.warn("--user requires Python 2.6 or later")
raise SystemExit(1)
install_args.append('--user')
return install_args
def _parse_args():
"""
Parse the command line for options
"""
parser = optparse.OptionParser()
parser.add_option(
'--user', dest='user_install', action='store_true', default=False,
help='install in user site package (requires Python 2.6 or later)')
parser.add_option(
'--download-base', dest='download_base', metavar="URL",
default=DEFAULT_URL,
help='alternative URL from where to download the distribute package')
options, args = parser.parse_args()
# positional arguments are ignored
return options
def main(version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall"""
options = _parse_args()
tarball = download_setuptools(download_base=options.download_base)
return _install(tarball, _build_install_args(options))
if __name__ == '__main__': if __name__ == '__main__':
main(sys.argv[1:]) sys.exit(main())

View File

@ -13,7 +13,8 @@ ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) . I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) .
.PHONY: help clean html dirhtml singlehtml text man pickle json htmlhelp \ .PHONY: help clean html dirhtml singlehtml text man pickle json htmlhelp \
qthelp devhelp epub latex latexpdf changes linkcheck doctest qthelp devhelp epub latex latexpdf changes linkcheck doctest xml \
pseudoxml
help: help:
@echo "Please use \`make <target>' where <target> is one of" @echo "Please use \`make <target>' where <target> is one of"
@ -37,7 +38,7 @@ help:
@echo " linkcheck to check all external links for integrity" @echo " linkcheck to check all external links for integrity"
clean: clean:
-rm -rf _build/* rm -rf _build/*
html: html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
@ -147,3 +148,13 @@ info:
@echo "Running Texinfo files through makeinfo..." @echo "Running Texinfo files through makeinfo..."
make -C _build/texinfo info make -C _build/texinfo info
@echo "makeinfo finished; the Info files are in _build/texinfo." @echo "makeinfo finished; the Info files are in _build/texinfo."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) _build/xml
@echo
@echo "Build finished. The XML files are in _build/XML."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) _build/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in _build/pseudoxml."

BIN
doc/_static/pocoo.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -17,25 +17,23 @@
documentation of Python projects, but C/C++ is already supported as well, documentation of Python projects, but C/C++ is already supported as well,
and it is planned to add special support for other languages as well. Of and it is planned to add special support for other languages as well. Of
course, this site is also created from reStructuredText sources using course, this site is also created from reStructuredText sources using
Sphinx! Sphinx! The following features should be highlighted:
</p>
<p>
Sphinx is under constant development. The following features are present,
work fine and can be seen &#8220;in action&#8221; in the Python docs:
</p> </p>
<ul> <ul>
<li><b>Output formats:</b> HTML (including Windows HTML Help), LaTeX (for <li><b>Output formats:</b> HTML (including Windows HTML Help), LaTeX (for
printable PDF versions), manual pages, plain text</li> printable PDF versions), Texinfo, manual pages, plain text</li>
<li><b>Extensive cross-references:</b> semantic markup and automatic links <li><b>Extensive cross-references:</b> semantic markup and automatic links
for functions, classes, citations, glossary terms and similar pieces of for functions, classes, citations, glossary terms and similar pieces of
information</li> information</li>
<li><b>Hierarchical structure:</b> easy definition of a document tree, with <li><b>Hierarchical structure:</b> easy definition of a document tree, with
automatic links to siblings, parents and children</li> automatic links to siblings, parents and children</li>
<li><b>Automatic indices:</b> general index as well as a module index</li> <li><b>Automatic indices:</b> general index as well as a language-specific
module indices</li>
<li><b>Code handling:</b> automatic highlighting using the <a <li><b>Code handling:</b> automatic highlighting using the <a
href="http://pygments.org">Pygments</a> highlighter</li> href="http://pygments.org">Pygments</a> highlighter</li>
<li><b>Extensions:</b> automatic testing of code snippets, inclusion of <li><b>Extensions:</b> automatic testing of code snippets, inclusion of
docstrings from Python modules (API docs), and more</li> docstrings from Python modules (API docs), and
<a href="{{ pathto('extensions') }}#builtin-sphinx-extensions">more</a></li>
</ul> </ul>
<p> <p>
Sphinx uses <a href="http://docutils.sf.net/rst.html">reStructuredText</a> Sphinx uses <a href="http://docutils.sf.net/rst.html">reStructuredText</a>
@ -44,7 +42,7 @@
suite, the <a href="http://docutils.sf.net/">Docutils</a>. suite, the <a href="http://docutils.sf.net/">Docutils</a>.
</p> </p>
<h2>Documentation</h2> <h2 style="margin-bottom: 0">Documentation</h2>
<table class="contentstable" align="center" style="margin-left: 30px"><tr> <table class="contentstable" align="center" style="margin-left: 30px"><tr>
<td width="50%"> <td width="50%">
@ -62,9 +60,9 @@
<p> <p>
You can also download PDF versions of the Sphinx documentation: You can also download PDF versions of the Sphinx documentation:
a <a href="http://sphinx.pocoo.org/sphinx.pdf">version</a> generated from a <a href="http://sphinx-doc.org/sphinx.pdf">version</a> generated from
the LaTeX Sphinx produces, and the LaTeX Sphinx produces, and
a <a href="http://sphinx.pocoo.org/sphinx-rst2pdf.pdf">version</a> generated a <a href="http://sphinx-doc.org/sphinx-rst2pdf.pdf">version</a> generated
by rst2pdf. by rst2pdf.
</p> </p>
@ -86,14 +84,4 @@
<p>There is a <a href="http://sphinx-users.jp/doc10/">Japanese translation</a> <p>There is a <a href="http://sphinx-users.jp/doc10/">Japanese translation</a>
of this documentation, thanks to Yoshiki Shibukawa.</p> of this documentation, thanks to Yoshiki Shibukawa.</p>
<h2>Get Sphinx</h2>
<p>
Sphinx is available as an <a
href="http://peak.telecommunity.com/DevCenter/EasyInstall">easy-install</a>able
package on the <a href="http://pypi.python.org/pypi/Sphinx">Python Package
Index</a>.
</p>
<p>The code can be found in a Mercurial repository, at
<tt>http://bitbucket.org/birkenfeld/sphinx/</tt>.</p>
{% endblock %} {% endblock %}

View File

@ -1,5 +1,5 @@
<p class="logo"><a href="http://pocoo.org/"> <p class="logo">A <a href="http://pocoo.org/">
<img src="{{ pathto("_static/pocoo.png", 1) }}" /></a></p> <img src="{{ pathto("_static/pocoo.png", 1) }}" /></a> project</a></p>
<h3>Download</h3> <h3>Download</h3>
{% if version.endswith('(hg)') %} {% if version.endswith('(hg)') %}
@ -14,17 +14,18 @@
<p>Get Sphinx from the <a href="http://pypi.python.org/pypi/Sphinx">Python Package <p>Get Sphinx from the <a href="http://pypi.python.org/pypi/Sphinx">Python Package
Index</a>, or install it with:</p> Index</a>, or install it with:</p>
<pre>easy_install -U Sphinx</pre> <pre>easy_install -U Sphinx</pre>
<p>Latest <a href="http://sphinx.pocoo.org/latest/">development version docs</a> <p>Latest <a href="http://sphinx-doc.org/latest/">development version docs</a>
are also available.</p> are also available.</p>
{% endif %} {% endif %}
<h3>Questions? Suggestions?</h3> <h3>Questions? Suggestions?</h3>
<p>Join the <a href="http://groups.google.com/group/sphinx-dev">Google group</a>:</p> <p>Join the <a href="http://groups.google.com/group/sphinx-users">Google group</a>:</p>
<form action="http://groups.google.com/group/sphinx-dev/boxsubscribe" <form action="http://groups.google.com/group/sphinx-users/boxsubscribe"
style="padding-left: 1em"> style="padding-left: 0.5em">
<input type="text" name="email" value="your@email"/> <input type="text" name="email" value="your@email" style="font-size: 90%; width: 120px"
<input type="submit" name="sub" value="Subscribe" /> onfocus="$(this).val('');"/>
<input type="submit" name="sub" value="Subscribe" style="font-size: 90%; width: 70px"/>
</form> </form>
<p>or come to the <tt>#pocoo</tt> channel on FreeNode.</p> <p>or come to the <tt>#pocoo</tt> channel on FreeNode.</p>
<p>You can also open an issue at the <p>You can also open an issue at the

View File

@ -1,23 +0,0 @@
{% extends "!layout.html" %}
{% block extrahead %}
{{ super() }}
{%- if not embedded %}
<style type="text/css">
table.right { float: right; margin-left: 20px; }
table.right td { border: 1px solid #ccc; }
</style>
{%- endif %}
{% endblock %}
{% block rootrellink %}
<li><a href="{{ pathto('index') }}">Sphinx home</a>&nbsp;|&nbsp;</li>
<li><a href="{{ pathto('contents') }}">Documentation</a>
&raquo;</li>
{% endblock %}
{% block header %}
<div style="background-color: white; text-align: left; padding: 10px 10px 15px 15px">
<img src="{{ pathto("_static/sphinx.png", 1) }}" alt="Sphinx logo" />
</div>
{% endblock %}

78
doc/_themes/sphinx13/layout.html vendored Normal file
View File

@ -0,0 +1,78 @@
{#
sphinxdoc/layout.html
~~~~~~~~~~~~~~~~~~~~~
Sphinx layout template for the sphinxdoc theme.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- extends "basic/layout.html" %}
{# put the sidebar before the body #}
{% block sidebar1 %}{{ sidebar() }}{% endblock %}
{% block sidebar2 %}{% endblock %}
{% block extrahead %}
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,700'
rel='stylesheet' type='text/css'>
{{ super() }}
{%- if not embedded %}
<style type="text/css">
table.right { float: right; margin-left: 20px; }
table.right td { border: 1px solid #ccc; }
{% if pagename == 'index' %}
.related { display: none; }
{% endif %}
</style>
<script type="text/javascript">
// intelligent scrolling of the sidebar content
$(window).scroll(function() {
var sb = $('.sphinxsidebarwrapper');
var win = $(window);
var sbh = sb.height();
var offset = $('.sphinxsidebar').position()['top'];
var wintop = win.scrollTop();
var winbot = wintop + win.innerHeight();
var curtop = sb.position()['top'];
var curbot = curtop + sbh;
// does sidebar fit in window?
if (sbh < win.innerHeight()) {
// yes: easy case -- always keep at the top
sb.css('top', $u.min([$u.max([0, wintop - offset - 10]),
$(document).height() - sbh - 200]));
} else {
// no: only scroll if top/bottom edge of sidebar is at
// top/bottom edge of window
if (curtop > wintop && curbot > winbot) {
sb.css('top', $u.max([wintop - offset - 10, 0]));
} else if (curtop < wintop && curbot < winbot) {
sb.css('top', $u.min([winbot - sbh - offset - 20,
$(document).height() - sbh - 200]));
}
}
});
</script>
{%- endif %}
{% endblock %}
{% block rootrellink %}
<li><a href="{{ pathto('index') }}">Sphinx home</a>&nbsp;|</li>
<li><a href="{{ pathto('contents') }}">Documentation</a> &raquo;</li>
{% endblock %}
{% block header %}
<div class="pageheader">
<ul>
<li><a href="{{ pathto('index') }}">Home</a></li>
<li><a href="{{ pathto('install') }}">Get it</a></li>
<li><a href="{{ pathto('contents') }}">Docs</a></li>
<li><a href="{{ pathto('develop') }}">Extend/Develop</a></li>
</ul>
<div>
<a href="{{ pathto('index') }}">
<img src="{{ pathto('_static/sphinxheader.png', 1) }}" alt="SPHINX" />
</a>
</div>
</div>
{% endblock %}

BIN
doc/_themes/sphinx13/static/bodybg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

BIN
doc/_themes/sphinx13/static/footerbg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

BIN
doc/_themes/sphinx13/static/headerbg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

BIN
doc/_themes/sphinx13/static/listitem.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

BIN
doc/_themes/sphinx13/static/relbg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

396
doc/_themes/sphinx13/static/sphinx13.css vendored Normal file
View File

@ -0,0 +1,396 @@
/*
* sphinx13.css
* ~~~~~~~~~~~~
*
* Sphinx stylesheet -- sphinx13 theme.
*
* :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
'Verdana', sans-serif;
font-size: 14px;
text-align: center;
background-image: url(bodybg.png);
color: black;
padding: 0;
border-right: 1px solid #0a507a;
border-left: 1px solid #0a507a;
margin: 0 auto;
min-width: 780px;
max-width: 1080px;
}
.pageheader {
background-image: url(headerbg.png);
text-align: left;
padding: 10px 15px;
}
.pageheader ul {
float: right;
color: white;
list-style-type: none;
padding-left: 0;
margin-top: 30px;
margin-right: 10px;
}
.pageheader li {
float: left;
margin: 0 0 0 10px;
}
.pageheader li a {
border-radius: 1px;
padding: 8px 12px;
color: #f9f9f0;
text-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
}
.pageheader li a:hover {
background-color: #f9f9f0;
color: #0a507a;
text-shadow: none;
}
div.document {
background-color: white;
text-align: left;
}
div.bodywrapper {
margin: 0 240px 0 0;
border-right: 1px solid #0a507a;
}
div.body {
margin: 0;
padding: 0.5em 20px 20px 20px;
}
div.related {
font-size: 1em;
color: white;
}
div.related ul {
background-image: url(relbg.png);
height: 1.9em;
border-top: 1px solid #002e50;
border-bottom: 1px solid #002e50;
}
div.related ul li {
margin: 0 5px 0 0;
padding: 0;
float: left;
}
div.related ul li.right {
float: right;
margin-right: 5px;
}
div.related ul li a {
margin: 0;
padding: 0 5px 0 5px;
line-height: 1.75em;
color: #f9f9f0;
text-shadow: 0px 0px 1px rgba(0, 0, 0, 0.5);
}
div.related ul li a:hover {
color: white;
/*text-decoration: underline;*/
text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.5);
}
div.sphinxsidebarwrapper {
position: relative;
top: 0px;
padding: 0;
}
div.sphinxsidebar {
margin: 0;
padding: 0 15px 15px 0;
width: 210px;
float: right;
font-size: 1em;
text-align: left;
}
div.sphinxsidebar .logo {
font-size: 1.8em;
color: #0A507A;
font-weight: 300;
text-align: center;
}
div.sphinxsidebar .logo img {
vertical-align: middle;
}
div.sphinxsidebar input {
border: 1px solid #aaa;
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
'Verdana', sans-serif;
font-size: 1em;
}
div.sphinxsidebar h3 {
font-size: 1.5em;
border-top: 1px solid #0a507a;
margin-top: 1em;
margin-bottom: 0.5em;
padding-top: 0.5em;
}
div.sphinxsidebar h4 {
font-size: 1.2em;
margin-bottom: 0;
}
div.sphinxsidebar h3, div.sphinxsidebar h4 {
margin-right: -15px;
margin-left: -15px;
padding-right: 14px;
padding-left: 14px;
color: #333;
font-weight: 300;
/*text-shadow: 0px 0px 0.5px rgba(0, 0, 0, 0.4);*/
}
div.sphinxsidebarwrapper > h3:first-child {
margin-top: 0.5em;
border: none;
}
div.sphinxsidebar h3 a {
color: #333;
}
div.sphinxsidebar ul {
color: #444;
margin-top: 7px;
padding: 0;
line-height: 130%;
}
div.sphinxsidebar ul ul {
margin-left: 20px;
list-style-image: url(listitem.png);
}
div.footer {
background-image: url(footerbg.png);
color: #ccc;
text-shadow: 0 0 .2px rgba(255, 255, 255, 0.8);
padding: 3px 8px 3px 0;
clear: both;
font-size: 0.8em;
text-align: right;
}
/* no need to make a visible link to Sphinx on the Sphinx page */
div.footer a {
color: #ccc;
}
/* -- body styles ----------------------------------------------------------- */
p {
margin: 0.8em 0 0.5em 0;
}
a {
color: #A2881D;
text-decoration: none;
}
a:hover {
color: #E1C13F;
}
div.body a {
text-decoration: underline;
}
h1 {
margin: 10px 0 0 0;
font-size: 2.4em;
color: #0A507A;
font-weight: 300;
}
h2 {
margin: 1.em 0 0.2em 0;
font-size: 1.5em;
font-weight: 300;
padding: 0;
color: #174967;
}
h3 {
margin: 1em 0 -0.3em 0;
font-size: 1.3em;
font-weight: 300;
}
div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
text-decoration: none;
}
div.body h1 a tt, div.body h2 a tt, div.body h3 a tt, div.body h4 a tt, div.body h5 a tt, div.body h6 a tt {
color: #0A507A !important;
font-size: inherit !important;
}
a.headerlink {
color: #0A507A !important;
font-size: 12px;
margin-left: 6px;
padding: 0 4px 0 4px;
text-decoration: none !important;
float: right;
}
a.headerlink:hover {
background-color: #ccc;
color: white!important;
}
cite, code, tt {
font-family: 'Consolas', 'DejaVu Sans Mono',
'Bitstream Vera Sans Mono', monospace;
font-size: 14px;
letter-spacing: -0.02em;
}
tt {
background-color: #f2f2f2;
border: 1px solid #ddd;
border-radius: 2px;
color: #333;
padding: 1px;
}
tt.descname, tt.descclassname, tt.xref {
border: 0;
}
hr {
border: 1px solid #abc;
margin: 2em;
}
a tt {
border: 0;
color: #a2881d;
}
a tt:hover {
color: #e1c13f;
}
pre {
font-family: 'Consolas', 'DejaVu Sans Mono',
'Bitstream Vera Sans Mono', monospace;
font-size: 13px;
letter-spacing: 0.015em;
line-height: 120%;
padding: 0.5em;
border: 1px solid #ccc;
border-radius: 2px;
background-color: #f8f8f8;
}
pre a {
color: inherit;
text-decoration: underline;
}
td.linenos pre {
padding: 0.5em 0;
}
div.quotebar {
background-color: #f8f8f8;
max-width: 250px;
float: right;
padding: 0px 7px;
border: 1px solid #ccc;
margin-left: 1em;
}
div.topic {
background-color: #f8f8f8;
}
table {
border-collapse: collapse;
margin: 0 -0.5em 0 -0.5em;
}
table td, table th {
padding: 0.2em 0.5em 0.2em 0.5em;
}
div.admonition, div.warning {
font-size: 0.9em;
margin: 1em 0 1em 0;
border: 1px solid #86989B;
border-radius: 2px;
background-color: #f7f7f7;
padding: 0;
}
div.admonition p, div.warning p {
margin: 0.5em 1em 0.5em 1em;
padding: 0;
}
div.admonition pre, div.warning pre {
margin: 0.4em 1em 0.4em 1em;
}
div.admonition p.admonition-title,
div.warning p.admonition-title {
margin-top: 1em;
padding-top: 0.5em;
font-weight: bold;
}
div.warning {
border: 1px solid #940000;
/* background-color: #FFCCCF;*/
}
div.warning p.admonition-title {
}
div.admonition ul, div.admonition ol,
div.warning ul, div.warning ol {
margin: 0.1em 0.5em 0.5em 3em;
padding: 0;
}
.viewcode-back {
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
'Verdana', sans-serif;
}
div.viewcode-block:target {
background-color: #f4debf;
border-top: 1px solid #ac9;
border-bottom: 1px solid #ac9;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

4
doc/_themes/sphinx13/theme.conf vendored Normal file
View File

@ -0,0 +1,4 @@
[theme]
inherit = basic
stylesheet = sphinx13.css
pygments_style = trac

View File

@ -272,6 +272,29 @@ Note that a direct PDF builder using ReportLab is available in `rst2pdf
Its name is ``linkcheck``. Its name is ``linkcheck``.
.. module:: sphinx.builders.xml
.. class:: XMLBuilder
This builder produces Docutils-native XML files. The output can be
transformed with standard XML tools such as XSLT processors into arbitrary
final forms.
Its name is ``xml``.
.. versionadded:: 1.2
.. class:: PseudoXMLBuilder
This builder is used for debugging the Sphinx/Docutils "Reader to Transform
to Writer" pipeline. It produces compact pretty-printed "pseudo-XML", files
where nesting is indicated by indentation (no end-tags). External
attributes for all elements are output, and internal attributes for any
leftover "pending" elements are also given.
Its name is ``pseudoxml``.
.. versionadded:: 1.2
Built-in Sphinx extensions that offer more builders are: Built-in Sphinx extensions that offer more builders are:

View File

@ -13,24 +13,25 @@ templates_path = ['_templates']
exclude_patterns = ['_build'] exclude_patterns = ['_build']
project = 'Sphinx' project = 'Sphinx'
copyright = '2007-2011, Georg Brandl' copyright = '2007-2013, Georg Brandl'
version = sphinx.__released__ version = sphinx.__released__
release = version release = version
show_authors = True show_authors = True
html_theme = 'sphinxdoc' html_theme = 'sphinx13'
html_theme_path = ['_themes']
modindex_common_prefix = ['sphinx.'] modindex_common_prefix = ['sphinx.']
html_static_path = ['_static'] html_static_path = ['_static']
html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']} html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']}
html_additional_pages = {'index': 'index.html'} html_additional_pages = {'index': 'index.html'}
html_use_opensearch = 'http://sphinx.pocoo.org' html_use_opensearch = 'http://sphinx-doc.org'
htmlhelp_basename = 'Sphinxdoc' htmlhelp_basename = 'Sphinxdoc'
epub_theme = 'epub' epub_theme = 'epub'
epub_basename = 'sphinx' epub_basename = 'sphinx'
epub_author = 'Georg Brandl' epub_author = 'Georg Brandl'
epub_publisher = 'http://sphinx.pocoo.org/' epub_publisher = 'http://sphinx-doc.org/'
epub_scheme = 'url' epub_scheme = 'url'
epub_identifier = epub_publisher epub_identifier = epub_publisher
epub_pre_files = [('index.html', 'Welcome')] epub_pre_files = [('index.html', 'Welcome')]
@ -39,6 +40,7 @@ epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
'_static/basic.css', 'search.html', '_static/websupport.js'] '_static/basic.css', 'search.html', '_static/websupport.js']
epub_fix_images = False epub_fix_images = False
epub_max_image_width = 0 epub_max_image_width = 0
epub_show_urls = 'inline'
latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation', latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
'Georg Brandl', 'manual', 1)] 'Georg Brandl', 'manual', 1)]

View File

@ -373,6 +373,7 @@ documentation on :ref:`intl` for details.
* ``en`` -- English * ``en`` -- English
* ``es`` -- Spanish * ``es`` -- Spanish
* ``et`` -- Estonian * ``et`` -- Estonian
* ``eu`` -- Basque
* ``fa`` -- Iranian * ``fa`` -- Iranian
* ``fi`` -- Finnish * ``fi`` -- Finnish
* ``fr`` -- French * ``fr`` -- French
@ -383,6 +384,7 @@ documentation on :ref:`intl` for details.
* ``ko`` -- Korean * ``ko`` -- Korean
* ``lt`` -- Lithuanian * ``lt`` -- Lithuanian
* ``lv`` -- Latvian * ``lv`` -- Latvian
* ``nb_NO`` -- Norwegian Bokmal
* ``ne`` -- Nepali * ``ne`` -- Nepali
* ``nl`` -- Dutch * ``nl`` -- Dutch
* ``pl`` -- Polish * ``pl`` -- Polish
@ -759,6 +761,15 @@ that use Sphinx' HTMLWriter class.
.. versionadded:: 1.1 .. versionadded:: 1.1
.. confval:: html_search_scorer
The name of a javascript file (relative to the configuration directory) that
implements a search results scorer. If empty, the default will be used.
.. XXX describe interface for scorer here
.. versionadded:: 1.2
.. confval:: htmlhelp_basename .. confval:: htmlhelp_basename
Output file base name for HTML help builder. Default is ``'pydoc'``. Output file base name for HTML help builder. Default is ``'pydoc'``.
@ -926,6 +937,17 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
.. versionadded:: 1.2 .. versionadded:: 1.2
.. confval:: epub_show_urls
Control whether to display URL addresses. This is very useful for
readers that have no other means to display the linked URL. The
settings can have the following values:
* ``'inline'`` -- display URLs inline in parentheses (default)
* ``'no'`` -- do not display URLs
.. versionadded:: 1.2
.. _latex-options: .. _latex-options:
@ -1341,6 +1363,16 @@ Options for the linkcheck builder
.. versionadded:: 1.2 .. versionadded:: 1.2
Options for the XML builder
---------------------------
.. confval:: xml_pretty
If True, pretty-print the XML. Default is ``True``.
.. versionadded:: 1.2
.. rubric:: Footnotes .. rubric:: Footnotes
.. [1] A note on available globbing syntax: you can use the standard shell .. [1] A note on available globbing syntax: you can use the standard shell

View File

@ -22,6 +22,7 @@ Sphinx documentation contents
faq faq
glossary glossary
devguide
changes changes
examples examples

103
doc/develop.rst Normal file
View File

@ -0,0 +1,103 @@
:orphan:
Sphinx development
==================
Sphinx is a maintained by a group of volunteers. We value every contribution!
* The code can be found in a Mercurial repository, at
http://bitbucket.org/birkenfeld/sphinx/.
* Issues and feature requests should be raised in the `tracker
<http://bitbucket.org/birkenfeld/sphinx/issues/>`_.
* The mailing list for development is at `Google Groups
<http://groups.google.com/group/sphinx-dev/>`_.
For more about our development process and methods, see the :doc:`devguide`.
Extensions
==========
The `sphinx-contrib <http://bitbucket.org/birkenfeld/sphinx-contrib/>`_
repository contains many contributed extensions. Some of them have their own
releases on PyPI, others you can install from a checkout.
This is the current list of contributed extensions in that repository:
- aafig: render embeded ASCII art as nice images using aafigure_.
- actdiag: embed activity diagrams by using actdiag_
- adadomain: an extension for Ada support (Sphinx 1.0 needed)
- ansi: parse ANSI color sequences inside documents
- autorun: Execute code in a runblock directive.
- blockdiag: embed block diagrams by using blockdiag_
- cheeseshop: easily link to PyPI packages
- clearquest: create tables from ClearQuest_ queries.
- coffeedomain: a domain for (auto)documenting CoffeeScript source code.
- context: a builder for ConTeXt.
- doxylink: Link to external Doxygen-generated HTML documentation
- email: obfuscate email addresses
- erlangdomain: an extension for Erlang support (Sphinx 1.0 needed)
- exceltable: embed Excel spreadsheets into documents using exceltable_
- feed: an extension for creating syndication feeds and time-based overviews
from your site content
- gnuplot: produces images using gnuplot_ language.
- googleanalytics: track html visitors statistics
- googlechart: embed charts by using `Google Chart`_
- googlemaps: embed maps by using `Google Maps`_
- httpdomain: a domain for documenting RESTful HTTP APIs.
- hyphenator: client-side hyphenation of HTML using hyphenator_
- lilypond: an extension inserting music scripts from Lilypond_ in PNG format.
- mscgen: embed mscgen-formatted MSC (Message Sequence Chart)s.
- nicoviceo: embed videos from nicovideo
- nwdiag: embed network diagrams by using nwdiag_
- omegat: support tools to collaborate with OmegaT_ (Sphinx 1.1 needed)
- osaka: convert standard Japanese doc to Osaka dialect (it is joke extension)
- paverutils: an alternate integration of Sphinx with Paver_.
- phpdomain: an extension for PHP support
- plantuml: embed UML diagram by using PlantUML_
- rawfiles: copy raw files, like a CNAME.
- requirements: declare requirements wherever you need (e.g. in test
docstrings), mark statuses and collect them in a single list
- rubydomain: an extension for Ruby support (Sphinx 1.0 needed)
- sadisplay: display SqlAlchemy model sadisplay_
- sdedit: an extension inserting sequence diagram by using Quick Sequence.
Diagram Editor (sdedit_)
- seqdiag: embed sequence diagrams by using seqdiag_
- slide: embed presentation slides on slideshare_ and other sites.
- swf: embed flash files
- sword: an extension inserting Bible verses from Sword_.
- tikz: draw pictures with the `TikZ/PGF LaTeX package`_.
- traclinks: create TracLinks_ to a Trac_ instance from within Sphinx
- whooshindex: whoosh indexer extension
- youtube: embed videos from YouTube_
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_.
See the :ref:`extension tutorial <exttut>` on getting started with writing your
own extensions.
.. _aafigure: https://launchpad.net/aafigure
.. _gnuplot: http://www.gnuplot.info/
.. _paver: http://www.blueskyonmars.com/projects/paver/
.. _Sword: http://www.crosswire.org/sword/
.. _Lilypond: http://lilypond.org/web/
.. _sdedit: http://sdedit.sourceforge.net/
.. _Trac: http://trac.edgewall.org
.. _TracLinks: http://trac.edgewall.org/wiki/TracLinks
.. _OmegaT: http://www.omegat.org/
.. _PlantUML: http://plantuml.sourceforge.net/
.. _PyEnchant: http://www.rfk.id.au/software/pyenchant/
.. _sadisplay: http://bitbucket.org/estin/sadisplay/wiki/Home
.. _blockdiag: http://blockdiag.com/
.. _seqdiag: http://blockdiag.com/
.. _actdiag: http://blockdiag.com/
.. _nwdiag: http://blockdiag.com/
.. _Google Chart: http://code.google.com/intl/ja/apis/chart/
.. _Google Maps: http://maps.google.com/
.. _hyphenator: http://code.google.com/p/hyphenator/
.. _exceltable: http://packages.python.org/sphinxcontrib-exceltable/
.. _YouTube: http://www.youtube.com/
.. _ClearQuest: http://www-01.ibm.com/software/awdtools/clearquest/
.. _Zope interfaces: http://docs.zope.org/zope.interface/README.html
.. _slideshare: http://www.slideshare.net/
.. _TikZ/PGF LaTeX package: http://sourceforge.net/projects/pgf/

214
doc/devguide.rst Normal file
View File

@ -0,0 +1,214 @@
Sphinx Developer's Guide
========================
.. topic:: Abstract
This document describes the development process of Sphinx, a documentation
system used by developers to document systems used by other developers to
develop other systems that may also be documented using Sphinx.
The Sphinx source code is managed using `Mercurial`_ and is hosted on
`BitBucket`_.
hg clone https://bitbucket.org/birkenfeld/sphinx
.. rubric:: Community
sphinx-users <sphinx-users@googlegroups.com>
Mailing list for user support.
sphinx-dev <sphinx-dev@googlegroups.com>
Mailing list for development related discussions.
#pocoo on irc.freenode.net
IRC channel for development questions and user support.
This channel is shared with other Pocoo projects. Archived logs are
available `here <http://dev.pocoo.org/irclogs/>`_.
.. _`BitBucket`: http://bitbucket.org
.. _`Mercurial`: http://mercurial.selenic.com/
Bug Reports and Feature Requests
--------------------------------
If you have encountered a problem with Sphinx or have an idea for a new
feature, please submit it to the `issue tracker`_ on BitBucket or discuss it
on the sphinx-dev mailing list.
For bug reports, please include the output produced during the build process
and also the log file Sphinx creates after it encounters an un-handled
exception. The location of this file should be shown towards the end of the
error message.
Including or providing a link to the source files involved may help us fix the
issue. If possible, try to create a minimal project that produces the error
and post that instead.
.. _`issue tracker`: http://bitbucket.org/birkenfeld/sphinx/issues
Contributing to Sphinx
----------------------
The recommended way for new contributors to submit code to Sphinx is to fork
the Mercurial repository on BitBucket and then submit a pull request after
committing the changes. The pull request will then need to be approved by one
of the core developers before it is merged into the main repository.
Getting Started
~~~~~~~~~~~~~~~
These are the basic steps needed to start developing on Sphinx.
#. Create an account on BitBucket.
#. Fork the main Sphinx repository (`birkenfeld/sphinx
<https://bitbucket.org/birkenfeld/sphinx>`_) using the BitBucket interface.
#. Clone the forked repository to your machine. ::
hg clone https://bitbucket.org/USERNAME/sphinx-fork
cd sphinx-fork
#. Checkout the appropriate branch.
For changes that should be included in the next minor release (namely bug
fixes), use the ``stable`` branch. ::
hg checkout stable
For new features or other substantial changes that should wait until the
next major release, use the ``default`` branch.
#. Setup your Python environment. ::
virtualenv ~/sphinxenv
. ~/sphinxenv/bin/activate
pip install -e .
#. Hack, hack, hack.
For tips on working with the code, see the `Coding Guide`_.
#. Test, test, test.
Run the unit tests::
pip install nose
make test
Build the documentation and check the output for different builders::
cd docs
make clean html text man info latexpdf
Run the unit tests under different Python environments using
:program:`tox`::
pip install tox
tox -v
Add a new unit test in the ``tests`` directory if you can.
For bug fixes, first add a test that fails without your changes and passes
after they are applied.
#. Commit your changes. ::
hg commit -m 'Add useful new feature that does this.'
BitBucket recognizes `certain phrases`__ that can be used to automatically
update the issue tracker.
For example::
hg commit -m 'Closes #42: Fix invalid markup in docstring of Foo.bar.'
would close issue #42.
__ https://confluence.atlassian.com/display/BITBUCKET/Automatically+Resolving+Issues+when+Users+Push+Code
#. Push changes to your forked repository on BitBucket. ::
hg push
#. Submit a pull request from your repository to ``birkenfeld/sphinx`` using
the BitBucket interface.
#. Wait for a core developer to review your changes.
Core Developers
~~~~~~~~~~~~~~~
The core developers of Sphinx have write access to the main repository. They
can commit changes, accept/reject pull requests, and manage items on the issue
tracker.
You do not need to be a core developer or have write access to be involved in
the development of Sphinx. You can submit patches or create pull requests
from forked repositories and have a core developer add the changes for you.
The following are some general guidelines for core developers:
* Questionable or extensive changes should be submitted as a pull request
instead of being committed directly to the main repository. The pull
request should be reviewed by another core developer before it is merged.
* Trivial changes can be committed directly but be sure to keep the repository
in a good working state and that all tests pass before pushing your changes.
* When committing code written by someone else, please attribute the original
author in the commit message and any relevant :file:`CHANGES` entry.
* Using Mercurial named branches other than ``default`` and ``stable`` is not
encouraged.
Coding Guide
------------
* Try to use the same code style as used in the rest of the project. See the
`Pocoo Styleguide`__ for more information.
__ http://flask.pocoo.org/docs/styleguide/
* For non-trivial changes, please update the :file:`CHANGES` file. If your
changes alter existing behavior, please document this.
* New features should be documented. Include examples and use cases where
appropriate. If possible, include a sample that is displayed in the
generated output.
* When adding a new configuration variable, be sure to document it and update
:file:`sphinx/quickstart.py`.
* Use the included :program:`utils/check_sources.py` script to check for
common formatting issues (trailing whitespace, lengthy lines, etc).
* Add appropriate unit tests.
Debugging Tips
~~~~~~~~~~~~~~
* Delete the build cache before building documents if you make changes in the
code by running the command ``make clean`` or using the
:option:`sphinx-build -E` option.
* Use the :option:`sphinx-build -P` option to run Pdb on exceptions.
* Use ``node.pformat()`` and ``node.asdom().toxml()`` to generate a printable
representation of the document structure.
* Set the configuration variable :confval:`keep_warnings` to True so warnings
will be displayed in the generated output.
* Set the configuration variable :confval:`nitpicky` to True so that Sphinx
will complain about references without a known target.
* Set the debugging options in the `Docutils configuration file
<http://docutils.sourceforge.net/docs/user/config.html>`_.

View File

@ -812,7 +812,15 @@ More domains
------------ ------------
The sphinx-contrib_ repository contains more domains available as extensions; The sphinx-contrib_ repository contains more domains available as extensions;
currently Ada, Erlang, HTTP, PHP, and Ruby domains. currently Ada, CoffeeScript_, Erlang_, HTTP_, Jinja_, PHP_, Ruby, and Scala_
domains.
.. _sphinx-contrib: https://bitbucket.org/birkenfeld/sphinx-contrib/ .. _sphinx-contrib: https://bitbucket.org/birkenfeld/sphinx-contrib/
.. _CoffeeScript: http://pypi.python.org/pypi/sphinxcontrib-coffee
.. _Erlang: http://pypi.python.org/pypi/sphinxcontrib-erlangdomain
.. _HTTP: http://pypi.python.org/pypi/sphinxcontrib-httpdomain
.. _Jinja: http://pypi.python.org/pypi/sphinxcontrib-jinjadomain
.. _Scala: http://pypi.python.org/pypi/sphinxcontrib-scaladomain
.. _PHP: http://pypi.python.org/pypi/sphinxcontrib-phpdomain

46
doc/ext/linkcode.rst Normal file
View File

@ -0,0 +1,46 @@
:mod:`sphinx.ext.linkcode` -- Add external links to source code
===============================================================
.. module:: sphinx.ext.linkcode
:synopsis: Add external links to source code.
.. moduleauthor:: Pauli Virtanen
.. versionadded:: 1.2
This extension looks at your object descriptions (``.. class::``,
``.. function::`` etc.) and adds external links to code hosted
somewhere on the web. The intent is similar to the
``sphinx.ext.viewcode`` extension, but assumes the source code can be
found somewhere on the Internet.
In your configuration, you need to specify a :confval:`linkcode_resolve`
function that returns an URL based on the object.
.. confval:: linkcode_resolve
This is a function ``linkcode_resolve(domain, info)``,
which should return the URL to source code corresponding to
the object in given domain with given information.
The function should return ``None`` if no link is to be added.
The argument ``domain`` specifies the language domain the object is
in. ``info`` is a dictionary with the following keys guaranteed to
be present (dependent on the domain):
- ``py``: ``module`` (name of the module), ``fullname`` (name of the object)
- ``c``: ``names`` (list of names for the object)
- ``cpp``: ``names`` (list of names for the object)
- ``javascript``: ``object`` (name of the object), ``fullname`` (name of the item)
Example:
.. code-block:: python
def linkcode_resolve(domain, info):
if domain != 'py':
return None
if not info['module']:
return None
filename = info['module'].replace('.', '/')
return "http://somesite/sourcerepo/%s.py" % filename

View File

@ -148,19 +148,12 @@ built:
.. confval:: pngmath_dvipng_args .. confval:: pngmath_dvipng_args
Additional arguments to give to dvipng, as a list. The default value is Additional arguments to give to dvipng, as a list. The default value is
``['-gamma 1.5', '-D 110']`` which makes the image a bit darker and larger ``['-gamma', '1.5', '-D', '110', '-bg', 'Transparent']`` which makes the
then it is by default. image a bit darker and larger then it is by default, and produces PNGs with a
transparent background.
An arguments you might want to add here is e.g. ``'-bg Transparent'``, .. versionchanged:: 1.2
which produces PNGs with a transparent background. This is not enabled by Now includes ``-bg Transparent`` by default.
default because some Internet Explorer versions don't like transparent PNGs.
.. note::
When you "add" an argument, you need to reproduce the default arguments if
you want to keep them; that is, like this::
pngmath_dvipng_args = ['-gamma 1.5', '-D 110', '-bg Transparent']
.. confval:: pngmath_use_preview .. confval:: pngmath_use_preview

View File

@ -53,6 +53,7 @@ These extensions are built in and can be activated by respective entries in the
ext/todo ext/todo
ext/extlinks ext/extlinks
ext/viewcode ext/viewcode
ext/linkcode
ext/oldcmarkup ext/oldcmarkup

View File

@ -36,6 +36,13 @@ How do I...
still need to mark up classes and such, but the headings and code examples still need to mark up classes and such, but the headings and code examples
come through cleanly. come through cleanly.
... create HTML slides from Sphinx documents?
See the "Hieroglyph" package at http://github.com/nyergler/hieroglyph.
For many more extensions and other contributed stuff, see the sphinx-contrib_
repository.
.. _sphinx-contrib: https://bitbucket.org/birkenfeld/sphinx-contrib/
.. _usingwith: .. _usingwith:

166
doc/install.rst Normal file
View File

@ -0,0 +1,166 @@
:orphan:
Installing Sphinx
==================
Sphinx is written by Python, you need to install Python and Sphinx.
Sphinx package is available as a package on the `Python Package Index
<http://pypi.python.org/pypi/Sphinx>`_.
You can also download a snapshot from the Mercurial development repository:
* as a `.tar.bz2 <https://bitbucket.org/birkenfeld/sphinx/get/default.tar.bz2>`_
file or
* as a `.zip <https://bitbucket.org/birkenfeld/sphinx/get/default.zip>`_ file
There is introductions for each environments:
.. contents::
:depth: 1
:local:
:backlinks: none
Install by your own
--------------------
If you use system installed Python or build your own Python, you can
use that python to install Sphinx. The actual command list is same as
these install.
* `Install easy_install command`_
* `Install Sphinx`_
Debian/Ubuntu: Install Sphinx using packaging system
-----------------------------------------------------
You may install using this command if you use Debian/Ubuntu.
.. code-block:: bash
$ aptitude install python-sphinx
Mac OS X: Install Sphinx using MacPorts
----------------------------------------
If you use Mac OS X `MacPorts <http://www.macports.org/>`_ , use this
command to install all software.
.. code-block:: bash
$ sudo port install py27-sphinx
However, the execution path is not added, use select command to use
Python2.7 as default.
.. code-block:: bash
$ sudo port select --set python python27
$ sudo port select --set sphinx py27-sphinx
Type :command:`which sphinx-quickstart` to check the installation.
Windows: Install Python and Sphinx
-----------------------------------
Intall Python
^^^^^^^^^^^^^^
Almost every Windows user do not have Python, we begin Python
installation. If you already install python, please skip this section.
Go to http://python.org . This site is a headquarter of the
Python. Look at Left sidebar and "Quick Links", Click "Windows
Installer" to download.
.. image:: pythonorg.jpg
.. note::
Currently, Python has two version, 2.X and 3.X. Sphinx-1.2 can
run under Python-2.5, 2.6, 2.7, 3.1, 3.2, 3.3.
You may get some advice from ML or other places.
This chapter assumes Python-2.7.
Follow the normal Windows installer, the Python install will be completed.
.. image:: installpython.jpg
After installation, you have better to add PATH to the Environment
Variable in order to run Python from Command Prompt.
* Right-Click the My Computer Icon and open Property Dialog
* Click Environment Variable button under detail tab
* Edit and add the path to the system variables PATH
Add these variables. This is for Python-2.7. If you use another version
of Python, change the "27" number. Add these pathes separeted by ";".
.. list-table:: Adding PATH
:widths: 10 40
:header-rows: 1
* - PATH
- description
* - C:\\Python27
- Folder which includes Python Command
* - C:\\Python27\\Scripts
- Folder which includes easy_install (described later) or sphinx commands
Run **Command Prompt** or enter ``cmd`` to the "search program and
files" text box. After command prompt window appear, type
``python[Enter]``. If you can get installed python version and prompt
about ``>>>``, the Python installation is succeeded. Enter ``Ctrl+Z``
key to quit.
Install easy_install command
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Python has very useful :command:`easy_install` command which install 3rd
party library.
* http://pypi.python.org/pypi/distribute
easy_install downloads and install software which you want to need by only
one command.
Save http://distribute.org/distribute_setup.py link by Right-click.
Some browsers can download just open the URL.
If you can read the file iteslf, calm down, Right-click and choose "Save".
After download, invoke command prompt, go to the distribute_setup.py saved
directory and run this command:
.. code-block:: bat
C:\> python distribute_setup.py
Now :command:`easy_insall` command is installed. OK, Let's go to the Sphinx
install!
Install Sphinx
^^^^^^^^^^^^^^^
If you finshed easy_install install, for the rest is just a moment.
Type this line.
.. code-block:: bat
C:\> easy_install sphinx
After installation, type :command:`sphinx-quickstart` on the command
prompt. If you get interactive messages which starts with
``Welcome to the Sphinx <version> quickstart utility.``,
installation is succeeded. Quit by hitting ``Ctrl+C``.
That it. Install is over. Let's go to :doc:`tutorial` to make Sphinx project.

BIN
doc/installpython.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -50,19 +50,15 @@ See the :ref:`pertinent section in the FAQ list <usingwith>`.
Prerequisites Prerequisites
------------- -------------
Sphinx needs at least **Python 2.4** or **Python 3.1** to run, as well as the Sphinx needs at least **Python 2.5** or **Python 3.1** to run, as well as the
docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.7 docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.7
or some (not broken) SVN trunk snapshot. If you like to have source code or some (not broken) SVN trunk snapshot. If you like to have source code
highlighting support, you must also install the Pygments_ library. highlighting support, you must also install the Pygments_ library.
If you use **Python 2.4** you also need uuid_.
.. _reStructuredText: http://docutils.sf.net/rst.html .. _reStructuredText: http://docutils.sf.net/rst.html
.. _docutils: http://docutils.sf.net/ .. _docutils: http://docutils.sf.net/
.. _Jinja2: http://jinja.pocoo.org/ .. _Jinja2: http://jinja.pocoo.org/
.. _Pygments: http://pygments.org/ .. _Pygments: http://pygments.org/
.. The given homepage is only a directory listing so I'm using the pypi site.
.. _uuid: http://pypi.python.org/pypi/uuid/
Usage Usage

View File

@ -59,6 +59,13 @@ The :program:`sphinx-build` script has several options:
**linkcheck** **linkcheck**
Check the integrity of all external links. Check the integrity of all external links.
**xml**
Build Docutils-native XML files.
**pseudoxml**
Build compact pretty-printed "pseudo-XML" files displaying the
internal structure of the intermediate document trees.
See :ref:`builders` for a list of all builders shipped with Sphinx. See :ref:`builders` for a list of all builders shipped with Sphinx.
Extensions can add their own builders. Extensions can add their own builders.
@ -131,6 +138,13 @@ The :program:`sphinx-build` script has several options:
Do not emit colored output. (On Windows, colored output is disabled in any Do not emit colored output. (On Windows, colored output is disabled in any
case.) case.)
.. option:: -v
Increase verbosity. This option can be given up to three times to get more
debug output. It implies :option:`-T`.
.. versionadded:: 1.2
.. option:: -q .. option:: -q
Do not output anything on standard output, only write warnings and errors to Do not output anything on standard output, only write warnings and errors to
@ -150,11 +164,24 @@ The :program:`sphinx-build` script has several options:
Turn warnings into errors. This means that the build stops at the first Turn warnings into errors. This means that the build stops at the first
warning and ``sphinx-build`` exits with exit status 1. warning and ``sphinx-build`` exits with exit status 1.
.. option:: -T
Display the full traceback when an unhandled exception occurs. Otherwise,
only a summary is displayed and the traceback information is saved to a file
for further analysis.
.. versionadded:: 1.2
.. option:: -P .. option:: -P
(Useful for debugging only.) Run the Python debugger, :mod:`pdb`, if an (Useful for debugging only.) Run the Python debugger, :mod:`pdb`, if an
unhandled exception occurs while building. unhandled exception occurs while building.
.. option:: -h, --help, --version
Display usage summary or Sphinx version.
.. versionadded:: 1.2
You can also give one or more filenames on the command line after the source and You can also give one or more filenames on the command line after the source and
build directories. Sphinx will then try to build only these output files (and build directories. Sphinx will then try to build only these output files (and
@ -227,6 +254,17 @@ The :program:`sphinx-apidoc` script has several options:
This sets the maximum depth of the table of contents, if one is generated. This sets the maximum depth of the table of contents, if one is generated.
.. option:: -l, --follow-links
This option makes sphinx-apidoc follow symbolic links when recursing the
filesystem to discover packages and modules. You may need it if you want
to generate documentation from a source directory managed by
`collective.recipe.omelette
<http://pypi.python.org/pypi/collective.recipe.omelette/>`_.
By default, symbolic links are skipped.
.. versionadded:: 1.2
.. option:: -T, --no-toc .. option:: -T, --no-toc
This prevents the generation of a table-of-contents file ``modules.rst``. This prevents the generation of a table-of-contents file ``modules.rst``.

View File

@ -64,6 +64,13 @@ linkcheck
pickle / json pickle / json
Generates serialized HTML files for use in web applications. Generates serialized HTML files for use in web applications.
xml
Generates Docutils-native XML files.
pseudoxml
Generates compact pretty-printed "pseudo-XML" files displaying the
internal structure of the intermediate document trees.
Options Options
------- -------

View File

@ -182,13 +182,6 @@ Including content based on tags
The format of the current builder (``html``, ``latex`` or ``text``) is always The format of the current builder (``html``, ``latex`` or ``text``) is always
set as a tag. set as a tag.
.. note::
Due to docutils' specifics of parsing of directive content, you cannot put
a section with the same level as the main document heading inside an
``only`` directive. Such sections will appear to be ignored in the parsed
document.
.. versionadded:: 0.6 .. versionadded:: 0.6

View File

@ -126,6 +126,18 @@ tables of contents. The ``toctree`` directive is the central element.
intend to insert these links yourself, in a different style, or in the HTML intend to insert these links yourself, in a different style, or in the HTML
sidebar. sidebar.
In cases where you want to have only one top-level toctree and hide all other
lower level toctrees you can add the "includehidden" option to the top-level
toctree entry::
.. toctree::
:includehidden:
doc_1
doc_2
All other toctree entries can then be eliminated by the "hidden" option.
In the end, all documents in the :term:`source directory` (or subdirectories) In the end, all documents in the :term:`source directory` (or subdirectories)
must occur in some ``toctree`` directive; Sphinx will emit a warning if it must occur in some ``toctree`` directive; Sphinx will emit a warning if it
finds a file that is not included, because that means that this file will not finds a file that is not included, because that means that this file will not
@ -150,6 +162,8 @@ tables of contents. The ``toctree`` directive is the central element.
.. versionchanged:: 1.1 .. versionchanged:: 1.1
Added numeric argument to "numbered". Added numeric argument to "numbered".
.. versionchanged:: 1.2
Added "includehidden" option.
Special names Special names
------------- -------------

BIN
doc/pythonorg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

View File

@ -391,3 +391,6 @@ are in HTML form), these variables are also available:
* ``titles_only`` (false by default): if true, put only toplevel document * ``titles_only`` (false by default): if true, put only toplevel document
titles in the tree titles in the tree
* ``includehidden`` (false by default): if true, the TOC tree will also
contain hidden entries.

View File

@ -111,8 +111,7 @@ These themes are:
- **collapsiblesidebar** (true or false): Add an *experimental* JavaScript - **collapsiblesidebar** (true or false): Add an *experimental* JavaScript
snippet that makes the sidebar collapsible via a button on its side. snippet that makes the sidebar collapsible via a button on its side.
*Doesn't work together with "rightsidebar" or "stickysidebar".* Defaults to *Doesn't work with "stickysidebar".* Defaults to false.
false.
- **externalrefs** (true or false): Display external links differently from - **externalrefs** (true or false): Display external links differently from
internal links. Defaults to false. internal links. Defaults to false.

View File

@ -13,10 +13,10 @@ the described task.
Setting up the documentation sources Setting up the documentation sources
------------------------------------ ------------------------------------
The root directory of a documentation collection is called the :term:`source The root directory of a Sphinx collection of reStructuredText document sources
directory`. This directory also contains the Sphinx configuration file is called the :term:`source directory`. This directory also contains the Sphinx
:file:`conf.py`, where you can configure all aspects of how Sphinx reads your configuration file :file:`conf.py`, where you can configure all aspects of how
sources and builds your documentation. [#]_ Sphinx reads your sources and builds your documentation. [#]_
Sphinx comes with a script called :program:`sphinx-quickstart` that sets up a Sphinx comes with a script called :program:`sphinx-quickstart` that sets up a
source directory and creates a default :file:`conf.py` with the most useful source directory and creates a default :file:`conf.py` with the most useful

View File

@ -4,6 +4,7 @@ tag_date = true
[aliases] [aliases]
release = egg_info -RDb '' release = egg_info -RDb ''
upload = upload --sign --identity=36580288
[extract_messages] [extract_messages]
mapping_file = babel.cfg mapping_file = babel.cfg

View File

@ -46,26 +46,20 @@ A development egg can be found `here
requires = ['Pygments>=1.2', 'Jinja2>=2.3', 'docutils>=0.7'] requires = ['Pygments>=1.2', 'Jinja2>=2.3', 'docutils>=0.7']
if sys.version_info < (2, 4): if sys.version_info[:3] >= (3, 3, 0):
print('ERROR: Sphinx requires at least Python 2.4 to run.') requires[2] = 'docutils>=0.10'
sys.exit(1)
if sys.version_info < (2, 5): if sys.version_info < (2, 5):
# Python 2.4's distutils doesn't automatically install an egg-info, print('ERROR: Sphinx requires at least Python 2.5 to run.')
# so an existing docutils install won't be detected -- in that case, sys.exit(1)
# remove the dependency from setup.py
try:
import docutils
if int(docutils.__version__[2]) < 4:
raise ValueError('docutils not recent enough')
except:
pass
else:
del requires[-1]
# The uuid module is new in the stdlib in 2.5
requires.append('uuid>=1.30')
# tell distribute to use 2to3 with our own fixers
extra = {}
if sys.version_info >= (3, 0):
extra.update(
use_2to3=True,
use_2to3_fixers=['custom_fixers']
)
# Provide a "compile_catalog" command that also creates the translated # Provide a "compile_catalog" command that also creates the translated
# JavaScript files if Babel is available. # JavaScript files if Babel is available.
@ -164,7 +158,7 @@ else:
setup( setup(
name='Sphinx', name='Sphinx',
version=sphinx.__version__, version=sphinx.__version__,
url='http://sphinx.pocoo.org/', url='http://sphinx-doc.org/',
download_url='http://pypi.python.org/pypi/Sphinx', download_url='http://pypi.python.org/pypi/Sphinx',
license='BSD', license='BSD',
author='Georg Brandl', author='Georg Brandl',
@ -203,6 +197,5 @@ setup(
}, },
install_requires=requires, install_requires=requires,
cmdclass=cmdclass, cmdclass=cmdclass,
use_2to3=True, **extra
use_2to3_fixers=['custom_fixers'],
) )

View File

@ -4,7 +4,7 @@
Sphinx - Python documentation toolchain Sphinx - Python documentation toolchain
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -4,7 +4,7 @@
Sphinx - Python documentation toolchain Sphinx - Python documentation toolchain
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -4,7 +4,7 @@
Sphinx - Python documentation toolchain Sphinx - Python documentation toolchain
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -4,7 +4,7 @@
Sphinx - Python documentation toolchain Sphinx - Python documentation toolchain
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
The Sphinx documentation toolchain. The Sphinx documentation toolchain.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -38,11 +38,20 @@ if '+' in __version__ or 'pre' in __version__:
def main(argv=sys.argv): def main(argv=sys.argv):
"""Sphinx build "main" command-line entry.""" """Sphinx build "main" command-line entry."""
if sys.version_info[:3] < (2, 4, 0): if sys.version_info[:3] < (2, 5, 0):
sys.stderr.write('Error: Sphinx requires at least ' sys.stderr.write('Error: Sphinx requires at least '
'Python 2.4 to run.\n') 'Python 2.5 to run.\n')
return 1 return 1
if sys.version_info[:3] >= (3, 3, 0):
try:
import docutils
x, y = docutils.__version__.split('.')[:2]
if (int(x), int(y)) < (0, 10):
sys.stderr.write('Error: Sphinx requires at least '
'Docutils 0.10 for Python 3.3 and above.\n')
return 1
except Exception:
pass
try: try:
from sphinx import cmdline from sphinx import cmdline
except ImportError: except ImportError:

View File

@ -5,7 +5,7 @@
Additional docutils nodes. Additional docutils nodes.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -11,7 +11,7 @@
Copyright 2008 Société des arts technologiques (SAT), Copyright 2008 Société des arts technologiques (SAT),
http://www.sat.qc.ca/ http://www.sat.qc.ca/
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import os import os
@ -157,7 +157,8 @@ def recurse_tree(rootpath, excludes, opts):
root_package = None root_package = None
toplevels = [] toplevels = []
for root, subs, files in os.walk(rootpath): followlinks = getattr(opts, 'followlinks', False)
for root, subs, files in os.walk(rootpath, followlinks=followlinks):
if is_excluded(root, excludes): if is_excluded(root, excludes):
del subs[:] del subs[:]
continue continue
@ -246,6 +247,10 @@ Note: By default this script will not overwrite already created files.""")
'(default: 4)', type='int', default=4) '(default: 4)', type='int', default=4)
parser.add_option('-f', '--force', action='store_true', dest='force', parser.add_option('-f', '--force', action='store_true', dest='force',
help='Overwrite all files') help='Overwrite all files')
parser.add_option('-l', '--follow-links', action='store_true',
dest='followlinks', default=False,
help='Follow symbolic links. Powerful when combined '
'with collective.recipe.omelette.')
parser.add_option('-n', '--dry-run', action='store_true', dest='dryrun', parser.add_option('-n', '--dry-run', action='store_true', dest='dryrun',
help='Run the script without creating files') help='Run the script without creating files')
parser.add_option('-T', '--no-toc', action='store_true', dest='notoc', parser.add_option('-T', '--no-toc', action='store_true', dest='notoc',

View File

@ -7,10 +7,11 @@
Gracefully adapted from the TextPress system by Armin. Gracefully adapted from the TextPress system by Armin.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import os
import sys import sys
import types import types
import posixpath import posixpath
@ -34,7 +35,7 @@ from sphinx.environment import BuildEnvironment, SphinxStandaloneReader
from sphinx.util import pycompat # imported for side-effects from sphinx.util import pycompat # imported for side-effects
from sphinx.util.tags import Tags from sphinx.util.tags import Tags
from sphinx.util.osutil import ENOENT from sphinx.util.osutil import ENOENT
from sphinx.util.console import bold from sphinx.util.console import bold, lightgray, darkgray
# List of all known core events. Maps name to arguments description. # List of all known core events. Maps name to arguments description.
@ -60,7 +61,8 @@ class Sphinx(object):
def __init__(self, srcdir, confdir, outdir, doctreedir, buildername, def __init__(self, srcdir, confdir, outdir, doctreedir, buildername,
confoverrides=None, status=sys.stdout, warning=sys.stderr, confoverrides=None, status=sys.stdout, warning=sys.stderr,
freshenv=False, warningiserror=False, tags=None): freshenv=False, warningiserror=False, tags=None, verbosity=0):
self.verbosity = verbosity
self.next_listener_id = 0 self.next_listener_id = 0
self._extensions = {} self._extensions = {}
self._listeners = {} self._listeners = {}
@ -194,6 +196,8 @@ class Sphinx(object):
self.builder = builderclass(self) self.builder = builderclass(self)
self.emit('builder-inited') self.emit('builder-inited')
# ---- main "build" method -------------------------------------------------
def build(self, force_all=False, filenames=None): def build(self, force_all=False, filenames=None):
try: try:
if force_all: if force_all:
@ -203,12 +207,29 @@ class Sphinx(object):
else: else:
self.builder.build_update() self.builder.build_update()
except Exception, err: except Exception, err:
# delete the saved env to force a fresh build next time
envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
if path.isfile(envfile):
os.unlink(envfile)
self.emit('build-finished', err) self.emit('build-finished', err)
raise raise
else: else:
self.emit('build-finished', None) self.emit('build-finished', None)
self.builder.cleanup() self.builder.cleanup()
# ---- logging handling ----------------------------------------------------
def _log(self, message, wfile, nonl=False):
try:
wfile.write(message)
except UnicodeEncodeError:
encoding = getattr(wfile, 'encoding', 'ascii') or 'ascii'
wfile.write(message.encode(encoding, 'replace'))
if not nonl:
wfile.write('\n')
if hasattr(wfile, 'flush'):
wfile.flush()
def warn(self, message, location=None, prefix='WARNING: '): def warn(self, message, location=None, prefix='WARNING: '):
if isinstance(location, tuple): if isinstance(location, tuple):
docname, lineno = location docname, lineno = location
@ -221,26 +242,37 @@ class Sphinx(object):
if self.warningiserror: if self.warningiserror:
raise SphinxWarning(warntext) raise SphinxWarning(warntext)
self._warncount += 1 self._warncount += 1
try: self._log(warntext, self._warning, True)
self._warning.write(warntext)
except UnicodeEncodeError:
encoding = getattr(self._warning, 'encoding', 'ascii') or 'ascii'
self._warning.write(warntext.encode(encoding, 'replace'))
def info(self, message='', nonl=False): def info(self, message='', nonl=False):
try: self._log(message, self._status, nonl)
self._status.write(message)
except UnicodeEncodeError:
encoding = getattr(self._status, 'encoding', 'ascii') or 'ascii'
self._status.write(message.encode(encoding, 'replace'))
if not nonl:
self._status.write('\n')
self._status.flush()
# general extensibility interface def verbose(self, message, *args, **kwargs):
if self.verbosity < 1:
return
if args or kwargs:
message = message % (args or kwargs)
self._log(message, self._status)
def debug(self, message, *args, **kwargs):
if self.verbosity < 2:
return
if args or kwargs:
message = message % (args or kwargs)
self._log(darkgray(message), self._status)
def debug2(self, message, *args, **kwargs):
if self.verbosity < 3:
return
if args or kwargs:
message = message % (args or kwargs)
self._log(lightgray(message), self._status)
# ---- general extensibility interface -------------------------------------
def setup_extension(self, extension): def setup_extension(self, extension):
"""Import and setup a Sphinx extension module. No-op if called twice.""" """Import and setup a Sphinx extension module. No-op if called twice."""
self.debug('[app] setting up extension: %r', extension)
if extension in self._extensions: if extension in self._extensions:
return return
try: try:
@ -301,13 +333,17 @@ class Sphinx(object):
else: else:
self._listeners[event][listener_id] = callback self._listeners[event][listener_id] = callback
self.next_listener_id += 1 self.next_listener_id += 1
self.debug('[app] connecting event %r: %r [id=%s]',
event, callback, listener_id)
return listener_id return listener_id
def disconnect(self, listener_id): def disconnect(self, listener_id):
self.debug('[app] disconnecting event: [id=%s]', listener_id)
for event in self._listeners.itervalues(): for event in self._listeners.itervalues():
event.pop(listener_id, None) event.pop(listener_id, None)
def emit(self, event, *args): def emit(self, event, *args):
self.debug2('[app] emitting event: %r%s', event, repr(args)[:100])
results = [] results = []
if event in self._listeners: if event in self._listeners:
for _, callback in self._listeners[event].iteritems(): for _, callback in self._listeners[event].iteritems():
@ -323,6 +359,7 @@ class Sphinx(object):
# registering addon parts # registering addon parts
def add_builder(self, builder): def add_builder(self, builder):
self.debug('[app] adding builder: %r', builder)
if not hasattr(builder, 'name'): if not hasattr(builder, 'name'):
raise ExtensionError('Builder class %s has no "name" attribute' raise ExtensionError('Builder class %s has no "name" attribute'
% builder) % builder)
@ -337,6 +374,7 @@ class Sphinx(object):
self.builderclasses[builder.name] = builder self.builderclasses[builder.name] = builder
def add_config_value(self, name, default, rebuild): def add_config_value(self, name, default, rebuild):
self.debug('[app] adding config value: %r', (name, default, rebuild))
if name in self.config.values: if name in self.config.values:
raise ExtensionError('Config value %r already present' % name) raise ExtensionError('Config value %r already present' % name)
if rebuild in (False, True): if rebuild in (False, True):
@ -344,11 +382,13 @@ class Sphinx(object):
self.config.values[name] = (default, rebuild) self.config.values[name] = (default, rebuild)
def add_event(self, name): def add_event(self, name):
self.debug('[app] adding event: %r', name)
if name in self._events: if name in self._events:
raise ExtensionError('Event %r already present' % name) raise ExtensionError('Event %r already present' % name)
self._events[name] = '' self._events[name] = ''
def add_node(self, node, **kwds): def add_node(self, node, **kwds):
self.debug('[app] adding node: %r', (node, kwds))
nodes._add_node_class_names([node.__name__]) nodes._add_node_class_names([node.__name__])
for key, val in kwds.iteritems(): for key, val in kwds.iteritems():
try: try:
@ -388,44 +428,54 @@ class Sphinx(object):
return obj return obj
def add_directive(self, name, obj, content=None, arguments=None, **options): def add_directive(self, name, obj, content=None, arguments=None, **options):
self.debug('[app] adding directive: %r',
(name, obj, content, arguments, options))
directives.register_directive( directives.register_directive(
name, self._directive_helper(obj, content, arguments, **options)) name, self._directive_helper(obj, content, arguments, **options))
def add_role(self, name, role): def add_role(self, name, role):
self.debug('[app] adding role: %r', (name, role))
roles.register_local_role(name, role) roles.register_local_role(name, role)
def add_generic_role(self, name, nodeclass): def add_generic_role(self, name, nodeclass):
# don't use roles.register_generic_role because it uses # don't use roles.register_generic_role because it uses
# register_canonical_role # register_canonical_role
self.debug('[app] adding generic role: %r', (name, nodeclass))
role = roles.GenericRole(name, nodeclass) role = roles.GenericRole(name, nodeclass)
roles.register_local_role(name, role) roles.register_local_role(name, role)
def add_domain(self, domain): def add_domain(self, domain):
self.debug('[app] adding domain: %r', domain)
if domain.name in self.domains: if domain.name in self.domains:
raise ExtensionError('domain %s already registered' % domain.name) raise ExtensionError('domain %s already registered' % domain.name)
self.domains[domain.name] = domain self.domains[domain.name] = domain
def override_domain(self, domain): def override_domain(self, domain):
self.debug('[app] overriding domain: %r', domain)
if domain.name not in self.domains: if domain.name not in self.domains:
raise ExtensionError('domain %s not yet registered' % domain.name) raise ExtensionError('domain %s not yet registered' % domain.name)
if not issubclass(domain, self.domains[domain.name]): if not issubclass(domain, self.domains[domain.name]):
raise ExtensionError('new domain not a subclass of registered ' raise ExtensionError('new domain not a subclass of registered %s '
'domain' % domain.name) 'domain' % domain.name)
self.domains[domain.name] = domain self.domains[domain.name] = domain
def add_directive_to_domain(self, domain, name, obj, def add_directive_to_domain(self, domain, name, obj,
content=None, arguments=None, **options): content=None, arguments=None, **options):
self.debug('[app] adding directive to domain: %r',
(domain, name, obj, content, arguments, options))
if domain not in self.domains: if domain not in self.domains:
raise ExtensionError('domain %s not yet registered' % domain) raise ExtensionError('domain %s not yet registered' % domain)
self.domains[domain].directives[name] = \ self.domains[domain].directives[name] = \
self._directive_helper(obj, content, arguments, **options) self._directive_helper(obj, content, arguments, **options)
def add_role_to_domain(self, domain, name, role): def add_role_to_domain(self, domain, name, role):
self.debug('[app] adding role to domain: %r', (domain, name, role))
if domain not in self.domains: if domain not in self.domains:
raise ExtensionError('domain %s not yet registered' % domain) raise ExtensionError('domain %s not yet registered' % domain)
self.domains[domain].roles[name] = role self.domains[domain].roles[name] = role
def add_index_to_domain(self, domain, index): def add_index_to_domain(self, domain, index):
self.debug('[app] adding index to domain: %r', (domain, index))
if domain not in self.domains: if domain not in self.domains:
raise ExtensionError('domain %s not yet registered' % domain) raise ExtensionError('domain %s not yet registered' % domain)
self.domains[domain].indices.append(index) self.domains[domain].indices.append(index)
@ -433,6 +483,9 @@ class Sphinx(object):
def add_object_type(self, directivename, rolename, indextemplate='', def add_object_type(self, directivename, rolename, indextemplate='',
parse_node=None, ref_nodeclass=None, objname='', parse_node=None, ref_nodeclass=None, objname='',
doc_field_types=[]): doc_field_types=[]):
self.debug('[app] adding object type: %r',
(directivename, rolename, indextemplate, parse_node,
ref_nodeclass, objname, doc_field_types))
StandardDomain.object_types[directivename] = \ StandardDomain.object_types[directivename] = \
ObjType(objname or directivename, rolename) ObjType(objname or directivename, rolename)
# create a subclass of GenericObject as the new directive # create a subclass of GenericObject as the new directive
@ -449,6 +502,9 @@ class Sphinx(object):
def add_crossref_type(self, directivename, rolename, indextemplate='', def add_crossref_type(self, directivename, rolename, indextemplate='',
ref_nodeclass=None, objname=''): ref_nodeclass=None, objname=''):
self.debug('[app] adding crossref type: %r',
(directivename, rolename, indextemplate, ref_nodeclass,
objname))
StandardDomain.object_types[directivename] = \ StandardDomain.object_types[directivename] = \
ObjType(objname or directivename, rolename) ObjType(objname or directivename, rolename)
# create a subclass of Target as the new directive # create a subclass of Target as the new directive
@ -459,9 +515,11 @@ class Sphinx(object):
StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass) StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
def add_transform(self, transform): def add_transform(self, transform):
self.debug('[app] adding transform: %r', transform)
SphinxStandaloneReader.transforms.append(transform) SphinxStandaloneReader.transforms.append(transform)
def add_javascript(self, filename): def add_javascript(self, filename):
self.debug('[app] adding javascript: %r', filename)
from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder
if '://' in filename: if '://' in filename:
StandaloneHTMLBuilder.script_files.append(filename) StandaloneHTMLBuilder.script_files.append(filename)
@ -470,6 +528,7 @@ class Sphinx(object):
posixpath.join('_static', filename)) posixpath.join('_static', filename))
def add_stylesheet(self, filename): def add_stylesheet(self, filename):
self.debug('[app] adding stylesheet: %r', filename)
from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder
if '://' in filename: if '://' in filename:
StandaloneHTMLBuilder.css_files.append(filename) StandaloneHTMLBuilder.css_files.append(filename)
@ -478,21 +537,25 @@ class Sphinx(object):
posixpath.join('_static', filename)) posixpath.join('_static', filename))
def add_lexer(self, alias, lexer): def add_lexer(self, alias, lexer):
self.debug('[app] adding lexer: %r', (alias, lexer))
from sphinx.highlighting import lexers from sphinx.highlighting import lexers
if lexers is None: if lexers is None:
return return
lexers[alias] = lexer lexers[alias] = lexer
def add_autodocumenter(self, cls): def add_autodocumenter(self, cls):
self.debug('[app] adding autodocumenter: %r', cls)
from sphinx.ext import autodoc from sphinx.ext import autodoc
autodoc.add_documenter(cls) autodoc.add_documenter(cls)
self.add_directive('auto' + cls.objtype, autodoc.AutoDirective) self.add_directive('auto' + cls.objtype, autodoc.AutoDirective)
def add_autodoc_attrgetter(self, type, getter): def add_autodoc_attrgetter(self, type, getter):
self.debug('[app] adding autodoc attrgetter: %r', (type, getter))
from sphinx.ext import autodoc from sphinx.ext import autodoc
autodoc.AutoDirective._special_attrgetters[type] = getter autodoc.AutoDirective._special_attrgetters[type] = getter
def add_search_language(self, cls): def add_search_language(self, cls):
self.debug('[app] adding search language: %r', cls)
from sphinx.search import languages, SearchLanguage from sphinx.search import languages, SearchLanguage
assert isinstance(cls, SearchLanguage) assert isinstance(cls, SearchLanguage)
languages[cls.lang] = cls languages[cls.lang] = cls

View File

@ -5,7 +5,7 @@
Builder superclass for all builders. Builder superclass for all builders.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -119,9 +119,13 @@ class Builder(object):
summary = bold(summary) summary = bold(summary)
for item in iterable: for item in iterable:
l += 1 l += 1
self.info(term_width_line('%s[%3d%%] %s' % s = '%s[%3d%%] %s' % (summary, 100*l/length,
(summary, 100*l/length, colorfunc(item))
colorfunc(item))), nonl=1) if self.app.verbosity:
s += '\n'
else:
s = term_width_line(s)
self.info(s, nonl=1)
yield item yield item
if l > 0: if l > 0:
self.info() self.info()
@ -334,4 +338,6 @@ BUILTIN_BUILDERS = {
'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'), 'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
'websupport': ('websupport', 'WebSupportBuilder'), 'websupport': ('websupport', 'WebSupportBuilder'),
'gettext': ('gettext', 'MessageCatalogBuilder'), 'gettext': ('gettext', 'MessageCatalogBuilder'),
'xml': ('xml', 'XMLBuilder'),
'pseudoxml': ('xml', 'PseudoXMLBuilder'),
} }

View File

@ -5,7 +5,7 @@
Changelog builder. Changelog builder.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -7,9 +7,10 @@
.. _Devhelp: http://live.gnome.org/devhelp .. _Devhelp: http://live.gnome.org/devhelp
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
from __future__ import absolute_import
import re import re
from os import path from os import path

View File

@ -6,7 +6,7 @@
Build epub files. Build epub files.
Originally derived from qthelp.py. Originally derived from qthelp.py.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -30,7 +30,7 @@ from docutils import nodes
from sphinx import addnodes from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util.osutil import ensuredir, EEXIST from sphinx.util.osutil import ensuredir, copyfile, EEXIST
from sphinx.util.smartypants import sphinx_smarty_pants as ssp from sphinx.util.smartypants import sphinx_smarty_pants as ssp
from sphinx.util.console import brown from sphinx.util.console import brown
@ -281,8 +281,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
newids.append(self.fix_fragment('', id)) newids.append(self.fix_fragment('', id))
node.attributes['ids'] = newids node.attributes['ids'] = newids
def add_visible_links(self, tree): def add_visible_links(self, tree, show_urls='inline'):
"""Append visible link targets after external links.""" """Append visible link targets after external links"""
if show_urls == 'no':
return
for node in tree.traverse(nodes.reference): for node in tree.traverse(nodes.reference):
uri = node.get('refuri', '') uri = node.get('refuri', '')
if (uri.startswith('http:') or uri.startswith('https:') or if (uri.startswith('http:') or uri.startswith('https:') or
@ -290,9 +293,10 @@ class EpubBuilder(StandaloneHTMLBuilder):
uri = _link_target_template % {'uri': uri} uri = _link_target_template % {'uri': uri}
if uri: if uri:
idx = node.parent.index(node) + 1 idx = node.parent.index(node) + 1
link = nodes.inline(uri, uri) if show_urls == 'inline':
link['classes'].append(_css_link_target_class) link = nodes.inline(uri, uri)
node.parent.insert(idx, link) link['classes'].append(_css_link_target_class)
node.parent.insert(idx, link)
def write_doc(self, docname, doctree): def write_doc(self, docname, doctree):
"""Write one document file. """Write one document file.
@ -301,7 +305,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
and to add visible external links. and to add visible external links.
""" """
self.fix_ids(doctree) self.fix_ids(doctree)
self.add_visible_links(doctree) self.add_visible_links(doctree, self.config.epub_show_urls)
return StandaloneHTMLBuilder.write_doc(self, docname, doctree) return StandaloneHTMLBuilder.write_doc(self, docname, doctree)
def fix_genindex(self, tree): def fix_genindex(self, tree):
@ -662,7 +666,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
zipfile.ZIP_STORED) zipfile.ZIP_STORED)
for file in projectfiles: for file in projectfiles:
fp = path.join(outdir, file) fp = path.join(outdir, file)
if isinstance(fp, unicode): if sys.version_info < (2, 6):
fp = fp.encode(sys.getfilesystemencoding()) # When zipile.ZipFile.write call with unicode filename, ZipFile
# encode filename to 'utf-8' (only after Python-2.6).
if isinstance(file, unicode):
# OEBPS Container Format (OCF) 2.0.1 specification require
# "File Names MUST be UTF-8 encoded".
file = file.encode('utf-8')
epub.write(fp, file, zipfile.ZIP_DEFLATED) epub.write(fp, file, zipfile.ZIP_DEFLATED)
epub.close() epub.close()

View File

@ -5,7 +5,7 @@
The MessageCatalogBuilder class. The MessageCatalogBuilder class.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -15,9 +15,11 @@ from datetime import datetime
from collections import defaultdict from collections import defaultdict
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.util.nodes import extract_messages from sphinx.util import split_index_msg
from sphinx.util.osutil import SEP, safe_relpath, ensuredir, find_catalog from sphinx.util.nodes import extract_messages, traverse_translatable_index
from sphinx.util.osutil import safe_relpath, ensuredir, find_catalog
from sphinx.util.console import darkgreen from sphinx.util.console import darkgreen
from sphinx.locale import pairindextypes
POHEADER = ur""" POHEADER = ur"""
# SOME DESCRIPTIVE TITLE. # SOME DESCRIPTIVE TITLE.
@ -82,6 +84,16 @@ class I18nBuilder(Builder):
for node, msg in extract_messages(doctree): for node, msg in extract_messages(doctree):
catalog.add(msg, node) catalog.add(msg, node)
# Extract translatable messages from index entries.
for node, entries in traverse_translatable_index(doctree):
for typ, msg, tid, main in entries:
for m in split_index_msg(typ, msg):
if typ == 'pair' and m in pairindextypes.values():
# avoid built-in translated message was incorporated
# in 'sphinx.util.nodes.process_index_entry'
continue
catalog.add(m, node)
class MessageCatalogBuilder(I18nBuilder): class MessageCatalogBuilder(I18nBuilder):
""" """

View File

@ -5,7 +5,7 @@
Several HTML builders. Several HTML builders.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -53,6 +53,23 @@ INVENTORY_FILENAME = 'objects.inv'
LAST_BUILD_FILENAME = 'last_build' LAST_BUILD_FILENAME = 'last_build'
def get_object_hash(obj):
"""
In python3.3, unicode(dict_instance) retun another string per process.
get_object_hash(dict_instance) return same hash for same dict_instance.
"""
if isinstance(obj, dict):
return get_object_hash(list(obj.items()))
elif isinstance(obj, (list, tuple)):
obj = sorted(get_object_hash(o) for o in obj)
else: # int or other objects
pass
return md5(unicode(obj).encode('utf8')).hexdigest()
class StandaloneHTMLBuilder(Builder): class StandaloneHTMLBuilder(Builder):
""" """
Builds standalone HTML docs. Builds standalone HTML docs.
@ -156,9 +173,8 @@ class StandaloneHTMLBuilder(Builder):
cfgdict = dict((name, self.config[name]) cfgdict = dict((name, self.config[name])
for (name, desc) in self.config.values.iteritems() for (name, desc) in self.config.values.iteritems()
if desc[1] == 'html') if desc[1] == 'html')
self.config_hash = md5(unicode(cfgdict).encode('utf-8')).hexdigest() self.config_hash = get_object_hash(cfgdict)
self.tags_hash = md5(unicode(sorted(self.tags)).encode('utf-8')) \ self.tags_hash = get_object_hash(sorted(self.tags))
.hexdigest()
old_config_hash = old_tags_hash = '' old_config_hash = old_tags_hash = ''
try: try:
fp = open(path.join(self.outdir, '.buildinfo')) fp = open(path.join(self.outdir, '.buildinfo'))
@ -240,7 +256,8 @@ class StandaloneHTMLBuilder(Builder):
if not lang or lang not in languages: if not lang or lang not in languages:
lang = 'en' lang = 'en'
self.indexer = IndexBuilder(self.env, lang, self.indexer = IndexBuilder(self.env, lang,
self.config.html_search_options) self.config.html_search_options,
self.config.html_search_scorer)
self.load_indexer(docnames) self.load_indexer(docnames)
self.docwriter = HTMLWriter(self) self.docwriter = HTMLWriter(self)
@ -653,6 +670,8 @@ class StandaloneHTMLBuilder(Builder):
self.indexer.feed(pagename, title, doctree) self.indexer.feed(pagename, title, doctree)
def _get_local_toctree(self, docname, collapse=True, **kwds): def _get_local_toctree(self, docname, collapse=True, **kwds):
if 'includehidden' not in kwds:
kwds['includehidden'] = False
return self.render_partial(self.env.get_toctree_for( return self.render_partial(self.env.get_toctree_for(
docname, self, collapse, **kwds))['fragment'] docname, self, collapse, **kwds))['fragment']

View File

@ -6,7 +6,7 @@
Build HTML help support files. Build HTML help support files.
Parts adapted from Python's Doc/tools/prechm.py. Parts adapted from Python's Doc/tools/prechm.py.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
LaTeX builder. LaTeX builder.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
The CheckExternalLinksBuilder class. The CheckExternalLinksBuilder class.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -102,7 +102,8 @@ class CheckExternalLinksBuilder(Builder):
def check(): def check():
# check for various conditions without bothering the network # check for various conditions without bothering the network
if len(uri) == 0 or uri[0] == '#' or uri[0:7] == 'mailto:' or uri[0:4] == 'ftp:': if len(uri) == 0 or uri[0] == '#' or \
uri[0:7] == 'mailto:' or uri[0:4] == 'ftp:':
return 'unchecked', '' return 'unchecked', ''
elif not (uri[0:5] == 'http:' or uri[0:6] == 'https:'): elif not (uri[0:5] == 'http:' or uri[0:6] == 'https:'):
return 'local', '' return 'local', ''

View File

@ -5,7 +5,7 @@
Manual pages builder. Manual pages builder.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
Build input files for the Qt collection generator. Build input files for the Qt collection generator.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
Texinfo builder. Texinfo builder.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -72,9 +72,9 @@ uninstall-info: info
\t-$(TEXI2PDF) '$<' \t-$(TEXI2PDF) '$<'
clean: clean:
\t-rm -f *.info *.pdf *.txt *.html \trm -f *.info *.pdf *.txt *.html
\t-rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ky *.pg \trm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ky *.pg
\t-rm -f *.vr *.tp *.fn *.fns *.def *.defs *.cp *.cps *.ge *.ges *.mo \trm -f *.vr *.tp *.fn *.fns *.def *.defs *.cp *.cps *.ge *.ges *.mo
.PHONY: all info plaintext html pdf install-info uninstall-info clean .PHONY: all info plaintext html pdf install-info uninstall-info clean
''' '''

View File

@ -5,7 +5,7 @@
Plain-text Sphinx builder. Plain-text Sphinx builder.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
Builder for the web support package. Builder for the web support package.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

98
sphinx/builders/xml.py Normal file
View File

@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
"""
sphinx.builders.xml
~~~~~~~~~~~~~~~~~~~
Docutils-native XML and pseudo-XML builders.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import codecs
from os import path
from docutils import nodes
from docutils.io import StringOutput
from sphinx.builders import Builder
from sphinx.util.osutil import ensuredir, os_path
from sphinx.writers.xml import XMLWriter, PseudoXMLWriter
class XMLBuilder(Builder):
"""
Builds Docutils-native XML.
"""
name = 'xml'
format = 'xml'
out_suffix = '.xml'
_writer_class = XMLWriter
def init(self):
pass
def get_outdated_docs(self):
for docname in self.env.found_docs:
if docname not in self.env.all_docs:
yield docname
continue
targetname = self.env.doc2path(docname, self.outdir,
self.out_suffix)
try:
targetmtime = path.getmtime(targetname)
except Exception:
targetmtime = 0
try:
srcmtime = path.getmtime(self.env.doc2path(docname))
if srcmtime > targetmtime:
yield docname
except EnvironmentError:
# source doesn't exist anymore
pass
def get_target_uri(self, docname, typ=None):
return ''
def prepare_writing(self, docnames):
self.writer = self._writer_class(self)
def write_doc(self, docname, doctree):
# work around multiple string % tuple issues in docutils;
# replace tuples in attribute values with lists
doctree = doctree.deepcopy()
for node in doctree.traverse(nodes.Element):
for att, value in node.attributes.items():
if isinstance(value, tuple):
node.attributes[att] = list(value)
value = node.attributes[att]
if isinstance(value, list):
for i, val in enumerate(value):
if isinstance(val, tuple):
value[i] = list(val)
destination = StringOutput(encoding='utf-8')
self.writer.write(doctree, destination)
outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
ensuredir(path.dirname(outfilename))
try:
f = codecs.open(outfilename, 'w', 'utf-8')
try:
f.write(self.writer.output)
finally:
f.close()
except (IOError, OSError), err:
self.warn("error writing file %s: %s" % (outfilename, err))
def finish(self):
pass
class PseudoXMLBuilder(XMLBuilder):
"""
Builds pseudo-XML for display purposes.
"""
name = 'pseudoxml'
format = 'pseudoxml'
out_suffix = '.pseudoxml'
_writer_class = PseudoXMLWriter

View File

@ -5,7 +5,7 @@
sphinx-build command-line handling. sphinx-build command-line handling.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -22,9 +22,17 @@ from sphinx.errors import SphinxError
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.util import Tee, format_exception_cut_frames, save_traceback from sphinx.util import Tee, format_exception_cut_frames, save_traceback
from sphinx.util.console import red, nocolor, color_terminal from sphinx.util.console import red, nocolor, color_terminal
from sphinx.util.osutil import fs_encoding
from sphinx.util.pycompat import terminal_safe, bytes from sphinx.util.pycompat import terminal_safe, bytes
def abspath(pathdir):
pathdir = path.abspath(pathdir)
if isinstance(pathdir, bytes):
pathdir = pathdir.decode(fs_encoding)
return pathdir
def usage(argv, msg=None): def usage(argv, msg=None):
if msg: if msg:
print >>sys.stderr, msg print >>sys.stderr, msg
@ -32,29 +40,47 @@ def usage(argv, msg=None):
print >>sys.stderr, """\ print >>sys.stderr, """\
Sphinx v%s Sphinx v%s
Usage: %s [options] sourcedir outdir [filenames...] Usage: %s [options] sourcedir outdir [filenames...]
Options: -b <builder> -- builder to use; default is html
-a -- write all files; default is to only write \ General options
new and changed files ^^^^^^^^^^^^^^^
-E -- don't use a saved environment, always read all files -b <builder> builder to use; default is html
-t <tag> -- include "only" blocks with <tag> -a write all files; default is to only write new and changed files
-d <path> -- path for the cached environment and doctree files -E don't use a saved environment, always read all files
(default: outdir/.doctrees) -d <path> path for the cached environment and doctree files
-c <path> -- path where configuration file (conf.py) is located (default: outdir/.doctrees)
Build configuration options
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-c <path> path where configuration file (conf.py) is located
(default: same as sourcedir) (default: same as sourcedir)
-C -- use no config file at all, only -D options -C use no config file at all, only -D options
-D <setting=value> -- override a setting in configuration -D <setting=value> override a setting in configuration file
-A <name=value> -- pass a value into the templates, for HTML builder -t <tag> define tag: include "only" blocks with <tag>
-n -- nit-picky mode, warn about all missing references -A <name=value> pass a value into the templates, for HTML builder
-N -- do not do colored output -n nit-picky mode, warn about all missing references
-q -- no output on stdout, just warnings on stderr
-Q -- no output at all, not even warnings Console output options
-w <file> -- write warnings (and errors) to given file ^^^^^^^^^^^^^^^^^^^^^^
-W -- turn warnings into errors -v increase verbosity (can be repeated)
-P -- run Pdb on exception -q no output on stdout, just warnings on stderr
Modi: -Q no output at all, not even warnings
-w <file> write warnings (and errors) to given file
-W turn warnings into errors
-T show full traceback on exception
-N do not emit colored output
-P run Pdb on exception
Filename arguments
^^^^^^^^^^^^^^^^^^
* without -a and without filenames, write new and changed files. * without -a and without filenames, write new and changed files.
* with -a, write all files. * with -a, write all files.
* with filenames, write these.""" % (__version__, argv[0]) * with filenames, write these.
Standard options
^^^^^^^^^^^^^^^^
-h, --help show this help and exit
--version show version information and exit
""" % (__version__, argv[0])
def main(argv): def main(argv):
@ -63,9 +89,19 @@ def main(argv):
nocolor() nocolor()
try: try:
opts, args = getopt.getopt(argv[1:], 'ab:t:d:c:CD:A:ng:NEqQWw:P') opts, args = getopt.getopt(argv[1:], 'ab:t:d:c:CD:A:nNEqQWw:PThv',
['help', 'version'])
allopts = set(opt[0] for opt in opts) allopts = set(opt[0] for opt in opts)
srcdir = confdir = path.abspath(args[0]) if '-h' in allopts or '--help' in allopts:
usage(argv)
print >>sys.stderr
print >>sys.stderr, 'For more information, see '\
'<http://sphinx-doc.org/>.'
return 0
if '--version' in allopts:
print 'Sphinx (sphinx-build) %s' % __version__
return 0
srcdir = confdir = abspath(args[0])
if not path.isdir(srcdir): if not path.isdir(srcdir):
print >>sys.stderr, 'Error: Cannot find source directory `%s\'.' % ( print >>sys.stderr, 'Error: Cannot find source directory `%s\'.' % (
srcdir,) srcdir,)
@ -75,19 +111,19 @@ def main(argv):
print >>sys.stderr, ('Error: Source directory doesn\'t ' print >>sys.stderr, ('Error: Source directory doesn\'t '
'contain conf.py file.') 'contain conf.py file.')
return 1 return 1
outdir = path.abspath(args[1]) outdir = abspath(args[1])
if not path.isdir(outdir): except getopt.error, err:
print >>sys.stderr, 'Making output directory...' usage(argv, 'Error: %s' % err)
os.makedirs(outdir) return 1
except (IndexError, getopt.error): except IndexError:
usage(argv) usage(argv, 'Error: Insufficient arguments.')
return 1 return 1
filenames = args[2:] filenames = args[2:]
err = 0 err = 0
for filename in filenames: for filename in filenames:
if not path.isfile(filename): if not path.isfile(filename):
print >>sys.stderr, 'Cannot find file %r.' % filename print >>sys.stderr, 'Error: Cannot find file %r.' % filename
err = 1 err = 1
if err: if err:
return 1 return 1
@ -101,6 +137,8 @@ def main(argv):
buildername = None buildername = None
force_all = freshenv = warningiserror = use_pdb = False force_all = freshenv = warningiserror = use_pdb = False
show_traceback = False
verbosity = 0
status = sys.stdout status = sys.stdout
warning = sys.stderr warning = sys.stderr
error = sys.stderr error = sys.stderr
@ -113,15 +151,15 @@ def main(argv):
buildername = val buildername = val
elif opt == '-a': elif opt == '-a':
if filenames: if filenames:
usage(argv, 'Cannot combine -a option and filenames.') usage(argv, 'Error: Cannot combine -a option and filenames.')
return 1 return 1
force_all = True force_all = True
elif opt == '-t': elif opt == '-t':
tags.append(val) tags.append(val)
elif opt == '-d': elif opt == '-d':
doctreedir = path.abspath(val) doctreedir = abspath(val)
elif opt == '-c': elif opt == '-c':
confdir = path.abspath(val) confdir = abspath(val)
if not path.isfile(path.join(confdir, 'conf.py')): if not path.isfile(path.join(confdir, 'conf.py')):
print >>sys.stderr, ('Error: Configuration directory ' print >>sys.stderr, ('Error: Configuration directory '
'doesn\'t contain conf.py file.') 'doesn\'t contain conf.py file.')
@ -177,26 +215,29 @@ def main(argv):
warnfile = val warnfile = val
elif opt == '-P': elif opt == '-P':
use_pdb = True use_pdb = True
elif opt == '-T':
show_traceback = True
elif opt == '-v':
verbosity += 1
show_traceback = True
if warning and warnfile: if warning and warnfile:
warnfp = open(warnfile, 'w') warnfp = open(warnfile, 'w')
warning = Tee(warning, warnfp) warning = Tee(warning, warnfp)
error = warning error = warning
if not path.isdir(outdir):
if status:
print >>status, 'Making output directory...'
os.makedirs(outdir)
try: try:
app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername, app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername,
confoverrides, status, warning, freshenv, confoverrides, status, warning, freshenv,
warningiserror, tags) warningiserror, tags, verbosity)
app.build(force_all, filenames) app.build(force_all, filenames)
return app.statuscode return app.statuscode
except KeyboardInterrupt: except (Exception, KeyboardInterrupt), err:
if use_pdb:
import pdb
print >>error, red('Interrupted while building, starting debugger:')
traceback.print_exc()
pdb.post_mortem(sys.exc_info()[2])
return 1
except Exception, err:
if use_pdb: if use_pdb:
import pdb import pdb
print >>error, red('Exception occurred while building, ' print >>error, red('Exception occurred while building, '
@ -205,7 +246,12 @@ def main(argv):
pdb.post_mortem(sys.exc_info()[2]) pdb.post_mortem(sys.exc_info()[2])
else: else:
print >>error print >>error
if isinstance(err, SystemMessage): if show_traceback:
traceback.print_exc(None, error)
print >>error
if isinstance(err, KeyboardInterrupt):
print >>error, 'interrupted!'
elif isinstance(err, SystemMessage):
print >>error, red('reST markup error:') print >>error, red('reST markup error:')
print >>error, terminal_safe(err.args[0]) print >>error, terminal_safe(err.args[0])
elif isinstance(err, SphinxError): elif isinstance(err, SphinxError):
@ -223,7 +269,7 @@ def main(argv):
'can be provided next time.') 'can be provided next time.')
print >>error, ( print >>error, (
'Either send bugs to the mailing list at ' 'Either send bugs to the mailing list at '
'<http://groups.google.com/group/sphinx-dev/>,\n' '<http://groups.google.com/group/sphinx-users/>,\n'
'or report them in the tracker at ' 'or report them in the tracker at '
'<http://bitbucket.org/birkenfeld/sphinx/issues/>. Thanks!') '<http://bitbucket.org/birkenfeld/sphinx/issues/>. Thanks!')
return 1 return 1

View File

@ -5,7 +5,7 @@
Build configuration file handling. Build configuration file handling.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -17,7 +17,7 @@ from os import path
from sphinx.errors import ConfigError from sphinx.errors import ConfigError
from sphinx.locale import l_ from sphinx.locale import l_
from sphinx.util.osutil import make_filename from sphinx.util.osutil import make_filename
from sphinx.util.pycompat import bytes, b, convert_with_2to3 from sphinx.util.pycompat import bytes, b, execfile_
nonascii_re = re.compile(b(r'[\x80-\xff]')) nonascii_re = re.compile(b(r'[\x80-\xff]'))
@ -110,6 +110,7 @@ class Config(object):
html_secnumber_suffix = ('. ', 'html'), html_secnumber_suffix = ('. ', 'html'),
html_search_language = (None, 'html'), html_search_language = (None, 'html'),
html_search_options = ({}, 'html'), html_search_options = ({}, 'html'),
html_search_scorer = ('', None),
# HTML help only options # HTML help only options
htmlhelp_basename = (lambda self: make_filename(self.project), None), htmlhelp_basename = (lambda self: make_filename(self.project), None),
@ -141,9 +142,14 @@ class Config(object):
epub_tocdup = (True, 'env'), epub_tocdup = (True, 'env'),
epub_fix_images = (False, 'env'), epub_fix_images = (False, 'env'),
epub_max_image_width = (0, 'env'), epub_max_image_width = (0, 'env'),
epub_show_urls = ('inline', 'html'),
# LaTeX options # LaTeX options
latex_documents = ([], None), latex_documents = (lambda self: [(self.master_doc,
make_filename(self.project) + '.tex',
self.project,
'', 'manual')],
None),
latex_logo = (None, None), latex_logo = (None, None),
latex_appendices = ([], None), latex_appendices = ([], None),
latex_use_parts = (False, None), latex_use_parts = (False, None),
@ -166,11 +172,22 @@ class Config(object):
text_newlines = ('unix', 'env'), text_newlines = ('unix', 'env'),
# manpage options # manpage options
man_pages = ([], None), man_pages = (lambda self: [(self.master_doc,
make_filename(self.project).lower(),
'%s %s' % (self.project, self.release),
[], 1)],
None),
man_show_urls = (False, None), man_show_urls = (False, None),
# Texinfo options # Texinfo options
texinfo_documents = ([], None), texinfo_documents = (lambda self: [(self.master_doc,
make_filename(self.project).lower(),
self.project, '',
make_filename(self.project),
'The %s reference manual.' %
make_filename(self.project),
'Python')],
None),
texinfo_appendices = ([], None), texinfo_appendices = ([], None),
texinfo_elements = ({}, None), texinfo_elements = ({}, None),
texinfo_domain_indices = (True, None), texinfo_domain_indices = (True, None),
@ -184,6 +201,9 @@ class Config(object):
# gettext options # gettext options
gettext_compact = (True, 'gettext'), gettext_compact = (True, 'gettext'),
# XML options
xml_pretty = (True, 'env'),
) )
def __init__(self, dirname, filename, overrides, tags): def __init__(self, dirname, filename, overrides, tags):
@ -199,26 +219,8 @@ class Config(object):
# we promise to have the config dir as current dir while the # we promise to have the config dir as current dir while the
# config file is executed # config file is executed
os.chdir(dirname) os.chdir(dirname)
# get config source -- 'b' is a no-op under 2.x, while 'U' is
# ignored under 3.x (but 3.x compile() accepts \r\n newlines)
f = open(config_file, 'rbU')
try: try:
source = f.read() execfile_(filename, config)
finally:
f.close()
try:
# compile to a code object, handle syntax errors
try:
code = compile(source, config_file, 'exec')
except SyntaxError:
if convert_with_2to3:
# maybe the file uses 2.x syntax; try to refactor to
# 3.x syntax using 2to3
source = convert_with_2to3(config_file)
code = compile(source, config_file, 'exec')
else:
raise
exec code in config
except SyntaxError, err: except SyntaxError, err:
raise ConfigError(CONFIG_SYNTAX_ERROR % err) raise ConfigError(CONFIG_SYNTAX_ERROR % err)
finally: finally:

View File

@ -5,7 +5,7 @@
Handlers for additional ReST directives. Handlers for additional ReST directives.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -3,7 +3,7 @@
sphinx.directives.code sphinx.directives.code
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -3,14 +3,13 @@
sphinx.directives.other sphinx.directives.other
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import os
from docutils import nodes from docutils import nodes
from docutils.parsers.rst import Directive, directives from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
from docutils.parsers.rst.directives.misc import Class from docutils.parsers.rst.directives.misc import Class
from docutils.parsers.rst.directives.misc import Include as BaseInclude from docutils.parsers.rst.directives.misc import Include as BaseInclude
@ -19,7 +18,6 @@ from sphinx.locale import _
from sphinx.util import url_re, docname_join from sphinx.util import url_re, docname_join
from sphinx.util.nodes import explicit_title_re, set_source_info, \ from sphinx.util.nodes import explicit_title_re, set_source_info, \
process_index_entry process_index_entry
from sphinx.util.compat import make_admonition
from sphinx.util.matching import patfilter from sphinx.util.matching import patfilter
@ -42,6 +40,7 @@ class TocTree(Directive):
'maxdepth': int, 'maxdepth': int,
'glob': directives.flag, 'glob': directives.flag,
'hidden': directives.flag, 'hidden': directives.flag,
'includehidden': directives.flag,
'numbered': int_or_nothing, 'numbered': int_or_nothing,
'titlesonly': directives.flag, 'titlesonly': directives.flag,
} }
@ -107,6 +106,7 @@ class TocTree(Directive):
subnode['maxdepth'] = self.options.get('maxdepth', -1) subnode['maxdepth'] = self.options.get('maxdepth', -1)
subnode['glob'] = glob subnode['glob'] = glob
subnode['hidden'] = 'hidden' in self.options subnode['hidden'] = 'hidden' in self.options
subnode['includehidden'] = 'includehidden' in self.options
subnode['numbered'] = self.options.get('numbered', 0) subnode['numbered'] = self.options.get('numbered', 0)
subnode['titlesonly'] = 'titlesonly' in self.options subnode['titlesonly'] = 'titlesonly' in self.options
set_source_info(self, subnode) set_source_info(self, subnode)
@ -168,6 +168,7 @@ class Index(Directive):
indexnode = addnodes.index() indexnode = addnodes.index()
indexnode['entries'] = ne = [] indexnode['entries'] = ne = []
indexnode['inline'] = False indexnode['inline'] = False
set_source_info(self, indexnode)
for entry in arguments: for entry in arguments:
ne.extend(process_index_entry(entry, targetid)) ne.extend(process_index_entry(entry, targetid))
return [indexnode, targetnode] return [indexnode, targetnode]
@ -204,29 +205,11 @@ class VersionChange(Directive):
return ret return ret
class SeeAlso(Directive): class SeeAlso(BaseAdmonition):
""" """
An admonition mentioning things to look at as reference. An admonition mentioning things to look at as reference.
""" """
has_content = True node_class = addnodes.seealso
required_arguments = 0
optional_arguments = 1
final_argument_whitespace = True
option_spec = {}
def run(self):
ret = make_admonition(
addnodes.seealso, self.name, [_('See also')], self.options,
self.content, self.lineno, self.content_offset, self.block_text,
self.state, self.state_machine)
if self.arguments:
argnodes, msgs = self.state.inline_text(self.arguments[0],
self.lineno)
para = nodes.paragraph()
para += argnodes
para += msgs
ret[0].insert(1, para)
return ret
class TabularColumns(Directive): class TabularColumns(Directive):
@ -338,9 +321,46 @@ class Only(Directive):
node.document = self.state.document node.document = self.state.document
set_source_info(self, node) set_source_info(self, node)
node['expr'] = self.arguments[0] node['expr'] = self.arguments[0]
self.state.nested_parse(self.content, self.content_offset, node,
match_titles=1) # Same as util.nested_parse_with_titles but try to handle nested
return [node] # sections which should be raised higher up the doctree.
surrounding_title_styles = self.state.memo.title_styles
surrounding_section_level = self.state.memo.section_level
self.state.memo.title_styles = []
self.state.memo.section_level = 0
try:
self.state.nested_parse(self.content, self.content_offset,
node, match_titles=1)
title_styles = self.state.memo.title_styles
if (not surrounding_title_styles
or not title_styles
or title_styles[0] not in surrounding_title_styles
or not self.state.parent):
# No nested sections so no special handling needed.
return [node]
# Calculate the depths of the current and nested sections.
current_depth = 0
parent = self.state.parent
while parent:
current_depth += 1
parent = parent.parent
current_depth -= 2
title_style = title_styles[0]
nested_depth = len(surrounding_title_styles)
if title_style in surrounding_title_styles:
nested_depth = surrounding_title_styles.index(title_style)
# Use these depths to determine where the nested sections should
# be placed in the doctree.
n_sects_to_raise = current_depth - nested_depth + 1
parent = self.state.parent
for i in xrange(n_sects_to_raise):
if parent.parent:
parent = parent.parent
parent.append(node)
return []
finally:
self.state.memo.title_styles = surrounding_title_styles
self.state.memo.section_level = surrounding_section_level
class Include(BaseInclude): class Include(BaseInclude):

View File

@ -6,7 +6,7 @@
Support for domains, which are groupings of description directives Support for domains, which are groupings of description directives
and roles describing e.g. constructs of one programming language. and roles describing e.g. constructs of one programming language.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
The C language domain. The C language domain.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
The C++ language domain. The C++ language domain.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -672,8 +672,9 @@ class DefinitionParser(object):
except ValueError: except ValueError:
return False return False
def _parse_builtin(self, modifier): def _parse_builtin(self, modifiers):
path = [modifier] modifier = modifiers[-1]
path = modifiers
following = self._modifiers[modifier] following = self._modifiers[modifier]
while 1: while 1:
self.skip_ws() self.skip_ws()
@ -730,9 +731,10 @@ class DefinitionParser(object):
# impossible for a template to follow, so what # impossible for a template to follow, so what
# we do is go to a different function that just # we do is go to a different function that just
# eats types # eats types
if following is not None:
return self._parse_builtin(modifier)
modifiers.append(modifier) modifiers.append(modifier)
if following is not None:
return self._parse_builtin(modifiers)
self.skip_ws()
else: else:
self.backout() self.backout()
break break
@ -760,17 +762,33 @@ class DefinitionParser(object):
self.skip_ws() self.skip_ws()
if self.match(_string_re): if self.match(_string_re):
return self.matched_text return self.matched_text
idx1 = self.definition.find(',', self.pos) paren_stack_depth = 0
idx2 = self.definition.find(')', self.pos) max_pos = len(self.definition)
if idx1 < 0: rv_start = self.pos
idx = idx2 while 1:
elif idx2 < 0: idx0 = self.definition.find('(', self.pos)
idx = idx1 idx1 = self.definition.find(',', self.pos)
else: idx2 = self.definition.find(')', self.pos)
idx = min(idx1, idx2) if idx0 < 0:
if idx < 0: idx0 = max_pos
self.fail('unexpected end in default expression') if idx1 < 0:
rv = self.definition[self.pos:idx] idx1 = max_pos
if idx2 < 0:
idx2 = max_pos
idx = min(idx0, idx1, idx2)
if idx >= max_pos:
self.fail('unexpected end in default expression')
if idx == idx0:
paren_stack_depth += 1
elif idx == idx2:
paren_stack_depth -= 1
if paren_stack_depth < 0:
break
elif paren_stack_depth == 0:
break
self.pos = idx+1
rv = self.definition[rv_start:idx]
self.pos = idx self.pos = idx
return rv return rv
@ -836,7 +854,7 @@ class DefinitionParser(object):
visibility = 'public' visibility = 'public'
if self.match(_visibility_re): if self.match(_visibility_re):
visibility = self.matched_text visibility = self.matched_text
static = self.skip_word('static') static = self.skip_word_and_ws('static')
return visibility, static return visibility, static
def parse_type(self): def parse_type(self):

View File

@ -5,7 +5,7 @@
The JavaScript domain. The JavaScript domain.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
The Python domain. The Python domain.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
The reStructuredText domain. The reStructuredText domain.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
The standard domain. The standard domain.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -307,12 +307,18 @@ class Glossary(Directive):
# add an index entry too # add an index entry too
indexnode = addnodes.index() indexnode = addnodes.index()
indexnode['entries'] = [('single', termtext, new_id, 'main')] indexnode['entries'] = [('single', termtext, new_id, 'main')]
termnodes.append(indexnode) _termnodes = []
termnodes.extend(res[0]) _termnodes.append(indexnode)
termnodes.append(addnodes.termsep()) _termnodes.extend(res[0])
_termnodes.append(addnodes.termsep())
for termnode in _termnodes:
termnode.source, termnode.line = source, lineno
termnodes.extend(_termnodes)
# make a single "term" node with all the terms, separated by termsep # make a single "term" node with all the terms, separated by termsep
# nodes (remove the dangling trailing separator) # nodes (remove the dangling trailing separator)
term = nodes.term('', '', *termnodes[:-1]) term = nodes.term('', '', *termnodes[:-1])
term.source, term.line = termnodes[0].source, termnodes[0].line
term.rawsource = term.astext()
term['ids'].extend(ids) term['ids'].extend(ids)
term['names'].extend(ids) term['names'].extend(ids)
term += system_messages term += system_messages

View File

@ -5,7 +5,7 @@
Global creation environment. Global creation environment.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -26,30 +26,27 @@ from itertools import izip, groupby
from docutils import nodes from docutils import nodes
from docutils.io import FileInput, NullOutput from docutils.io import FileInput, NullOutput
from docutils.core import Publisher from docutils.core import Publisher
from docutils.utils import Reporter, relative_path, new_document, \ from docutils.utils import Reporter, relative_path, get_source_line
get_source_line
from docutils.readers import standalone from docutils.readers import standalone
from docutils.parsers.rst import roles, directives, Parser as RSTParser from docutils.parsers.rst import roles, directives
from docutils.parsers.rst.languages import en as english from docutils.parsers.rst.languages import en as english
from docutils.parsers.rst.directives.html import MetaBody from docutils.parsers.rst.directives.html import MetaBody
from docutils.writers import UnfilteredWriter from docutils.writers import UnfilteredWriter
from docutils.transforms import Transform
from docutils.transforms.parts import ContentsFilter
from sphinx import addnodes from sphinx import addnodes
from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \ from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
FilenameUniqDict FilenameUniqDict
from sphinx.util.nodes import clean_astext, make_refnode, extract_messages, \ from sphinx.util.nodes import clean_astext, make_refnode, WarningStream
WarningStream from sphinx.util.osutil import SEP, fs_encoding
from sphinx.util.osutil import movefile, SEP, ustrftime, find_catalog
from sphinx.util.matching import compile_matchers from sphinx.util.matching import compile_matchers
from sphinx.util.pycompat import all, class_types from sphinx.util.pycompat import class_types
from sphinx.util.websupport import is_commentable from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError from sphinx.errors import SphinxError, ExtensionError
from sphinx.locale import _, init as init_locale from sphinx.locale import _
from sphinx.versioning import add_uids, merge_doctrees from sphinx.versioning import add_uids, merge_doctrees
from sphinx.transforms import DefaultSubstitutions, MoveModuleTargets, \
HandleCodeBlocks, SortIds, CitationReferences, Locale, SphinxContentsFilter
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
orig_role_function = roles.role orig_role_function = roles.role
orig_directive_function = directives.directive orig_directive_function = directives.directive
@ -66,19 +63,14 @@ default_settings = {
'doctitle_xform': False, 'doctitle_xform': False,
'sectsubtitle_xform': False, 'sectsubtitle_xform': False,
'halt_level': 5, 'halt_level': 5,
'file_insertion_enabled': True,
} }
# This is increased every time an environment attribute is added # This is increased every time an environment attribute is added
# or changed to properly invalidate pickle files. # or changed to properly invalidate pickle files.
ENV_VERSION = 41 ENV_VERSION = 42 + (sys.version_info[0] - 2)
default_substitutions = set([
'version',
'release',
'today',
])
dummy_reporter = Reporter('', 4, 4) dummy_reporter = Reporter('', 4, 4)
versioning_conditions = { versioning_conditions = {
@ -93,141 +85,6 @@ class NoUri(Exception):
pass pass
class DefaultSubstitutions(Transform):
"""
Replace some substitutions if they aren't defined in the document.
"""
# run before the default Substitutions
default_priority = 210
def apply(self):
config = self.document.settings.env.config
# only handle those not otherwise defined in the document
to_handle = default_substitutions - set(self.document.substitution_defs)
for ref in self.document.traverse(nodes.substitution_reference):
refname = ref['refname']
if refname in to_handle:
text = config[refname]
if refname == 'today' and not text:
# special handling: can also specify a strftime format
text = ustrftime(config.today_fmt or _('%B %d, %Y'))
ref.replace_self(nodes.Text(text, text))
class MoveModuleTargets(Transform):
"""
Move module targets that are the first thing in a section to the section
title.
XXX Python specific
"""
default_priority = 210
def apply(self):
for node in self.document.traverse(nodes.target):
if not node['ids']:
continue
if (node.has_key('ismod') and
node.parent.__class__ is nodes.section and
# index 0 is the section title node
node.parent.index(node) == 1):
node.parent['ids'][0:0] = node['ids']
node.parent.remove(node)
class HandleCodeBlocks(Transform):
"""
Several code block related transformations.
"""
default_priority = 210
def apply(self):
# move doctest blocks out of blockquotes
for node in self.document.traverse(nodes.block_quote):
if all(isinstance(child, nodes.doctest_block) for child
in node.children):
node.replace_self(node.children)
# combine successive doctest blocks
#for node in self.document.traverse(nodes.doctest_block):
# if node not in node.parent.children:
# continue
# parindex = node.parent.index(node)
# while len(node.parent) > parindex+1 and \
# isinstance(node.parent[parindex+1], nodes.doctest_block):
# node[0] = nodes.Text(node[0] + '\n\n' +
# node.parent[parindex+1][0])
# del node.parent[parindex+1]
class SortIds(Transform):
"""
Sort secion IDs so that the "id[0-9]+" one comes last.
"""
default_priority = 261
def apply(self):
for node in self.document.traverse(nodes.section):
if len(node['ids']) > 1 and node['ids'][0].startswith('id'):
node['ids'] = node['ids'][1:] + [node['ids'][0]]
class CitationReferences(Transform):
"""
Replace citation references by pending_xref nodes before the default
docutils transform tries to resolve them.
"""
default_priority = 619
def apply(self):
for citnode in self.document.traverse(nodes.citation_reference):
cittext = citnode.astext()
refnode = addnodes.pending_xref(cittext, reftype='citation',
reftarget=cittext, refwarn=True)
refnode.line = citnode.line or citnode.parent.line
refnode += nodes.Text('[' + cittext + ']')
citnode.parent.replace(citnode, refnode)
class Locale(Transform):
"""
Replace translatable nodes with their translated doctree.
"""
default_priority = 0
def apply(self):
env = self.document.settings.env
settings, source = self.document.settings, self.document['source']
# XXX check if this is reliable
assert source.startswith(env.srcdir)
docname = path.splitext(relative_path(env.srcdir, source))[0]
textdomain = find_catalog(docname,
self.document.settings.gettext_compact)
# fetch translations
dirs = [path.join(env.srcdir, directory)
for directory in env.config.locale_dirs]
catalog, has_catalog = init_locale(dirs, env.config.language,
textdomain)
if not has_catalog:
return
parser = RSTParser()
for node, msg in extract_messages(self.document):
patch = new_document(source, settings)
msgstr = catalog.gettext(msg)
# XXX add marker to untranslated parts
if not msgstr or msgstr == msg: # as-of-yet untranslated
continue
parser.parse(msgstr, patch)
patch = patch[0]
# XXX doctest and other block markup
if not isinstance(patch, nodes.paragraph):
continue # skip for now
for child in patch.children: # update leaves
child.parent = node
node.children = patch.children
class SphinxStandaloneReader(standalone.Reader): class SphinxStandaloneReader(standalone.Reader):
""" """
Add our own transforms. Add our own transforms.
@ -246,20 +103,6 @@ class SphinxDummyWriter(UnfilteredWriter):
pass pass
class SphinxContentsFilter(ContentsFilter):
"""
Used with BuildEnvironment.add_toc_from() to discard cross-file links
within table-of-contents link nodes.
"""
def visit_pending_xref(self, node):
text = node.astext()
self.parent.append(nodes.literal(text, text))
raise nodes.SkipNode
def visit_image(self, node):
raise nodes.SkipNode
class BuildEnvironment: class BuildEnvironment:
""" """
The environment in which the ReST files are translated. The environment in which the ReST files are translated.
@ -289,9 +132,7 @@ class BuildEnvironment:
del self.config.values del self.config.values
domains = self.domains domains = self.domains
del self.domains del self.domains
# first write to a temporary file, so that if dumping fails, picklefile = open(filename, 'wb')
# the existing environment won't be overwritten
picklefile = open(filename + '.tmp', 'wb')
# remove potentially pickling-problematic values from config # remove potentially pickling-problematic values from config
for key, val in vars(self.config).items(): for key, val in vars(self.config).items():
if key.startswith('_') or \ if key.startswith('_') or \
@ -303,7 +144,6 @@ class BuildEnvironment:
pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL) pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL)
finally: finally:
picklefile.close() picklefile.close()
movefile(filename + '.tmp', filename)
# reset attributes # reset attributes
self.domains = domains self.domains = domains
self.config.values = values self.config.values = values
@ -782,7 +622,11 @@ class BuildEnvironment:
app.emit('doctree-read', doctree) app.emit('doctree-read', doctree)
# store time of build, for outdated files detection # store time of build, for outdated files detection
self.all_docs[docname] = time.time() # (Some filesystems have coarse timestamp resolution;
# therefore time.time() can be older than filesystem's timestamp.
# For example, FAT32 has 2sec timestamp resolution.)
self.all_docs[docname] = max(
time.time(), path.getmtime(self.doc2path(docname)))
if self.versioning_condition: if self.versioning_condition:
# get old doctree # get old doctree
@ -874,6 +718,7 @@ class BuildEnvironment:
filterlevel = self.config.keep_warnings and 2 or 5 filterlevel = self.config.keep_warnings and 2 or 5
for node in doctree.traverse(nodes.system_message): for node in doctree.traverse(nodes.system_message):
if node['level'] < filterlevel: if node['level'] < filterlevel:
self.app.debug('%s [filtered system message]', node.astext())
node.parent.remove(node) node.parent.remove(node)
@ -1149,8 +994,9 @@ class BuildEnvironment:
anchorname=anchorname, *nodetext) anchorname=anchorname, *nodetext)
para = addnodes.compact_paragraph('', '', reference) para = addnodes.compact_paragraph('', '', reference)
item = nodes.list_item('', para) item = nodes.list_item('', para)
sub_item = build_toc(sectionnode, depth + 1)
if maxdepth == 0 or depth < maxdepth: if maxdepth == 0 or depth < maxdepth:
item += build_toc(sectionnode, depth+1) item += sub_item
entries.append(item) entries.append(item)
if entries: if entries:
return nodes.bullet_list('', *entries) return nodes.bullet_list('', *entries)
@ -1259,46 +1105,56 @@ class BuildEnvironment:
if toctree.get('hidden', False) and not includehidden: if toctree.get('hidden', False) and not includehidden:
return None return None
def _walk_depth(node, depth, maxdepth): # For reading the following two helper function, it is useful to keep
# in mind the node structure of a toctree (using HTML-like node names
# for brevity):
#
# <ul>
# <li>
# <p><a></p>
# <p><a></p>
# ...
# <ul>
# ...
# </ul>
# </li>
# </ul>
#
# The transformation is made in two passes in order to avoid
# interactions between marking and pruning the tree (see bug #1046).
def _toctree_prune(node, depth, maxdepth):
"""Utility: Cut a TOC at a specified depth.""" """Utility: Cut a TOC at a specified depth."""
# For reading this function, it is useful to keep in mind the node
# structure of a toctree (using HTML-like node names for brevity):
#
# <ul>
# <li>
# <p><a></p>
# <p><a></p>
# ...
# <ul>
# ...
# </ul>
# </li>
# </ul>
for subnode in node.children[:]: for subnode in node.children[:]:
if isinstance(subnode, (addnodes.compact_paragraph, if isinstance(subnode, (addnodes.compact_paragraph,
nodes.list_item)): nodes.list_item)):
# for <p> and <li>, just indicate the depth level and # for <p> and <li>, just recurse
# recurse to children _toctree_prune(subnode, depth, maxdepth)
subnode['classes'].append('toctree-l%d' % (depth-1))
_walk_depth(subnode, depth, maxdepth)
elif isinstance(subnode, nodes.bullet_list): elif isinstance(subnode, nodes.bullet_list):
# for <ul>, determine if the depth is too large or if the # for <ul>, determine if the depth is too large or if the
# entry is to be collapsed # entry is to be collapsed
if maxdepth > 0 and depth > maxdepth: if maxdepth > 0 and depth > maxdepth:
subnode.parent.replace(subnode, []) subnode.parent.replace(subnode, [])
else: else:
# to find out what to collapse, *first* walk subitems,
# since that determines which children point to the
# current page
_walk_depth(subnode, depth+1, maxdepth)
# cull sub-entries whose parents aren't 'current' # cull sub-entries whose parents aren't 'current'
if (collapse and depth > 1 and if (collapse and depth > 1 and
'iscurrent' not in subnode.parent): 'iscurrent' not in subnode.parent):
subnode.parent.remove(subnode) subnode.parent.remove(subnode)
else:
# recurse on visible children
_toctree_prune(subnode, depth+1, maxdepth)
def _toctree_add_classes(node, depth):
"""Add 'toctree-l%d' and 'current' classes to the toctree."""
for subnode in node.children:
if isinstance(subnode, (addnodes.compact_paragraph,
nodes.list_item)):
# for <p> and <li>, indicate the depth level and recurse
subnode['classes'].append('toctree-l%d' % (depth-1))
_toctree_add_classes(subnode, depth)
elif isinstance(subnode, nodes.bullet_list):
# for <ul>, just recurse
_toctree_add_classes(subnode, depth+1)
elif isinstance(subnode, nodes.reference): elif isinstance(subnode, nodes.reference):
# for <a>, identify which entries point to the current # for <a>, identify which entries point to the current
# document and therefore may not be collapsed # document and therefore may not be collapsed
@ -1321,7 +1177,7 @@ class BuildEnvironment:
def _entries_from_toctree(toctreenode, parents, def _entries_from_toctree(toctreenode, parents,
separate=False, subtree=False): separate=False, subtree=False):
"""Return TOC entries for a toctree node.""" """Return TOC entries for a toctree node."""
refs = [(e[0], str(e[1])) for e in toctreenode['entries']] refs = [(e[0], e[1]) for e in toctreenode['entries']]
entries = [] entries = []
for (title, ref) in refs: for (title, ref) in refs:
try: try:
@ -1408,6 +1264,8 @@ class BuildEnvironment:
maxdepth = maxdepth or toctree.get('maxdepth', -1) maxdepth = maxdepth or toctree.get('maxdepth', -1)
if not titles_only and toctree.get('titlesonly', False): if not titles_only and toctree.get('titlesonly', False):
titles_only = True titles_only = True
if not includehidden and toctree.get('includehidden', False):
includehidden = True
# NOTE: previously, this was separate=True, but that leads to artificial # NOTE: previously, this was separate=True, but that leads to artificial
# separation when two or more toctree entries form a logical unit, so # separation when two or more toctree entries form a logical unit, so
@ -1419,8 +1277,9 @@ class BuildEnvironment:
newnode = addnodes.compact_paragraph('', '', *tocentries) newnode = addnodes.compact_paragraph('', '', *tocentries)
newnode['toctree'] = True newnode['toctree'] = True
# prune the tree to maxdepth and replace titles, also set level classes # prune the tree to maxdepth, also set toc depth and current classes
_walk_depth(newnode, 1, prune and maxdepth or 0) _toctree_add_classes(newnode, 1)
_toctree_prune(newnode, 1, prune and maxdepth or 0)
# set the target paths in the toctrees (they are not known at TOC # set the target paths in the toctrees (they are not known at TOC
# generation time) # generation time)
@ -1468,8 +1327,16 @@ class BuildEnvironment:
elif typ == 'citation': elif typ == 'citation':
docname, labelid = self.citations.get(target, ('', '')) docname, labelid = self.citations.get(target, ('', ''))
if docname: if docname:
newnode = make_refnode(builder, fromdocname, docname, try:
labelid, contnode) newnode = make_refnode(builder, fromdocname,
docname, labelid, contnode)
except NoUri:
# remove the ids we added in the CitationReferences
# transform since they can't be transfered to
# the contnode (if it's a Text node)
if not isinstance(contnode, nodes.Element):
del node['ids'][:]
raise
# no new node found? try the missing-reference event # no new node found? try the missing-reference event
if newnode is None: if newnode is None:
newnode = builder.app.emit_firstresult( newnode = builder.app.emit_firstresult(
@ -1759,4 +1626,3 @@ class BuildEnvironment:
if 'orphan' in self.metadata[docname]: if 'orphan' in self.metadata[docname]:
continue continue
self.warn(docname, 'document isn\'t included in any toctree') self.warn(docname, 'document isn\'t included in any toctree')

View File

@ -6,7 +6,7 @@
Contains SphinxError and a few subclasses (in an extra module to avoid Contains SphinxError and a few subclasses (in an extra module to avoid
circular import problems). circular import problems).
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,6 +5,6 @@
Contains Sphinx features not activated by default. Contains Sphinx features not activated by default.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -7,7 +7,7 @@
the doctree, thus avoiding duplication between docstrings and documentation the doctree, thus avoiding duplication between docstrings and documentation
for those who like elaborate docstrings. for those who like elaborate docstrings.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -317,26 +317,38 @@ class Documenter(object):
Returns True if successful, False if an error occurred. Returns True if successful, False if an error occurred.
""" """
dbg = self.env.app.debug
if self.objpath:
dbg('[autodoc] from %s import %s',
self.modname, '.'.join(self.objpath))
try: try:
dbg('[autodoc] import %s', self.modname)
__import__(self.modname) __import__(self.modname)
parent = None parent = None
obj = self.module = sys.modules[self.modname] obj = self.module = sys.modules[self.modname]
dbg('[autodoc] => %r', obj)
for part in self.objpath: for part in self.objpath:
parent = obj parent = obj
dbg('[autodoc] getattr(_, %r)', part)
obj = self.get_attr(obj, part) obj = self.get_attr(obj, part)
dbg('[autodoc] => %r', obj)
self.object_name = part self.object_name = part
self.parent = parent self.parent = parent
self.object = obj self.object = obj
return True return True
# this used to only catch SyntaxError, ImportError and AttributeError, # this used to only catch SyntaxError, ImportError and AttributeError,
# but importing modules with side effects can raise all kinds of errors # but importing modules with side effects can raise all kinds of errors
except Exception, err: except Exception:
if self.env.app and not self.env.app.quiet: if self.objpath:
self.env.app.info(traceback.format_exc().rstrip()) errmsg = 'autodoc: failed to import %s %r from module %r' % \
self.directive.warn( (self.objtype, '.'.join(self.objpath), self.modname)
'autodoc can\'t import/find %s %r, it reported error: ' else:
'"%s", please check your spelling and sys.path' % errmsg = 'autodoc: failed to import %s %r' % \
(self.objtype, str(self.fullname), err)) (self.objtype, self.fullname)
errmsg += '; the following exception was raised:\n%s' % \
traceback.format_exc()
dbg(errmsg)
self.directive.warn(errmsg)
self.env.note_reread() self.env.note_reread()
return False return False
@ -489,23 +501,29 @@ class Documenter(object):
If *want_all* is True, return all members. Else, only return those If *want_all* is True, return all members. Else, only return those
members given by *self.options.members* (which may also be none). members given by *self.options.members* (which may also be none).
""" """
analyzed_member_names = set()
if self.analyzer:
attr_docs = self.analyzer.find_attr_docs()
namespace = '.'.join(self.objpath)
for item in attr_docs.iteritems():
if item[0][0] == namespace:
analyzed_member_names.add(item[0][1])
if not want_all: if not want_all:
if not self.options.members: if not self.options.members:
return False, [] return False, []
# specific members given # specific members given
ret = [] members = []
for mname in self.options.members: for mname in self.options.members:
try: try:
ret.append((mname, self.get_attr(self.object, mname))) members.append((mname, self.get_attr(self.object, mname)))
except AttributeError: except AttributeError:
self.directive.warn('missing attribute %s in object %s' if mname not in analyzed_member_names:
% (mname, self.fullname)) self.directive.warn('missing attribute %s in object %s'
return False, ret % (mname, self.fullname))
elif self.options.inherited_members:
if self.options.inherited_members:
# safe_getmembers() uses dir() which pulls in members from all # safe_getmembers() uses dir() which pulls in members from all
# base classes # base classes
members = safe_getmembers(self.object) members = safe_getmembers(self.object, attr_getter=self.get_attr)
else: else:
# __dict__ contains only the members directly defined in # __dict__ contains only the members directly defined in
# the class (but get them via getattr anyway, to e.g. get # the class (but get them via getattr anyway, to e.g. get
@ -521,13 +539,10 @@ class Documenter(object):
for mname in obj_dict.keys()] for mname in obj_dict.keys()]
membernames = set(m[0] for m in members) membernames = set(m[0] for m in members)
# add instance attributes from the analyzer # add instance attributes from the analyzer
if self.analyzer: for aname in analyzed_member_names:
attr_docs = self.analyzer.find_attr_docs() if aname not in membernames and \
namespace = '.'.join(self.objpath) (want_all or aname in self.options.members):
for item in attr_docs.iteritems(): members.append((aname, INSTANCEATTR))
if item[0][0] == namespace:
if item[0][1] not in membernames:
members.append((item[0][1], INSTANCEATTR))
return False, sorted(members) return False, sorted(members)
def filter_members(self, members, want_all): def filter_members(self, members, want_all):
@ -577,6 +592,7 @@ class Documenter(object):
membername != '__doc__': membername != '__doc__':
keep = has_doc or self.options.undoc_members keep = has_doc or self.options.undoc_members
elif self.options.special_members and \ elif self.options.special_members and \
self.options.special_members is not ALL and \
membername in self.options.special_members: membername in self.options.special_members:
keep = has_doc or self.options.undoc_members keep = has_doc or self.options.undoc_members
elif want_all and membername.startswith('_'): elif want_all and membername.startswith('_'):
@ -702,7 +718,8 @@ class Documenter(object):
# parse right now, to get PycodeErrors on parsing (results will # parse right now, to get PycodeErrors on parsing (results will
# be cached anyway) # be cached anyway)
self.analyzer.find_attr_docs() self.analyzer.find_attr_docs()
except PycodeError: except PycodeError, err:
self.env.app.debug('[autodoc] module analyzer failed: %s', err)
# no source file -- e.g. for builtin and C modules # no source file -- e.g. for builtin and C modules
self.analyzer = None self.analyzer = None
# at least add the module.__file__ as a dependency # at least add the module.__file__ as a dependency
@ -866,7 +883,7 @@ class DocstringSignatureMixin(object):
""" """
def _find_signature(self, encoding=None): def _find_signature(self, encoding=None):
docstrings = Documenter.get_doc(self, encoding, 2) docstrings = Documenter.get_doc(self, encoding)
if len(docstrings) != 1: if len(docstrings) != 1:
return return
doclines = docstrings[0] doclines = docstrings[0]
@ -881,6 +898,9 @@ class DocstringSignatureMixin(object):
# the base name must match ours # the base name must match ours
if not self.objpath or base != self.objpath[-1]: if not self.objpath or base != self.objpath[-1]:
return return
# re-prepare docstring to ignore indentation after signature
docstrings = Documenter.get_doc(self, encoding, 2)
doclines = docstrings[0]
# ok, now jump over remaining empty lines and set the remaining # ok, now jump over remaining empty lines and set the remaining
# lines as the new doclines # lines as the new doclines
i = 1 i = 1
@ -992,6 +1012,18 @@ class ClassDocumenter(ModuleLevelDocumenter):
def format_signature(self): def format_signature(self):
if self.doc_as_attr: if self.doc_as_attr:
return '' return ''
# get __init__ method signature from __init__.__doc__
if self.env.config.autodoc_docstring_signature:
# only act if the feature is enabled
init_doc = MethodDocumenter(self.directive, '__init__')
init_doc.object = self.get_attr(self.object, '__init__', None)
init_doc.objpath = ['__init__']
result = init_doc._find_signature()
if result is not None:
# use args only for Class signature
return '(%s)' % result[0]
return ModuleLevelDocumenter.format_signature(self) return ModuleLevelDocumenter.format_signature(self)
def add_directive_header(self, sig): def add_directive_header(self, sig):
@ -1102,7 +1134,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter):
""" """
objtype = 'method' objtype = 'method'
member_order = 50 member_order = 50
priority = 0 priority = 1 # must be more than FunctionDocumenter
@classmethod @classmethod
def can_document_member(cls, member, membername, isattr, parent): def can_document_member(cls, member, membername, isattr, parent):
@ -1173,7 +1205,7 @@ class AttributeDocumenter(ClassLevelDocumenter):
def can_document_member(cls, member, membername, isattr, parent): def can_document_member(cls, member, membername, isattr, parent):
isdatadesc = isdescriptor(member) and not \ isdatadesc = isdescriptor(member) and not \
isinstance(member, cls.method_types) and not \ isinstance(member, cls.method_types) and not \
type(member).__name__ == "method_descriptor" type(member).__name__ in ("type", "method_descriptor")
return isdatadesc or (not isinstance(parent, ModuleDocumenter) return isdatadesc or (not isinstance(parent, ModuleDocumenter)
and not inspect.isroutine(member) and not inspect.isroutine(member)
and not isinstance(member, class_types)) and not isinstance(member, class_types))
@ -1288,6 +1320,13 @@ class AutoDirective(Directive):
self.warnings = [] self.warnings = []
self.result = ViewList() self.result = ViewList()
try:
source, lineno = self.reporter.get_source_and_line(self.lineno)
except AttributeError:
source = lineno = None
self.env.app.debug('[autodoc] %s:%s: input:\n%s',
source, lineno, self.block_text)
# find out what documenter to call # find out what documenter to call
objtype = self.name[4:] objtype = self.name[4:]
doc_class = self._registry[objtype] doc_class = self._registry[objtype]
@ -1308,6 +1347,8 @@ class AutoDirective(Directive):
if not self.result: if not self.result:
return self.warnings return self.warnings
self.env.app.debug2('[autodoc] output:\n%s', '\n'.join(self.result))
# record all filenames as dependencies -- this will at least # record all filenames as dependencies -- this will at least
# partially make automatic invalidation possible # partially make automatic invalidation possible
for fn in self.filename_set: for fn in self.filename_set:

View File

@ -49,7 +49,7 @@
resolved to a Python object, and otherwise it becomes simple emphasis. resolved to a Python object, and otherwise it becomes simple emphasis.
This can be used as the default role to make links 'smart'. This can be used as the default role to make links 'smart'.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -14,7 +14,7 @@
generate: generate:
sphinx-autogen -o source/generated source/*.rst sphinx-autogen -o source/generated source/*.rst
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -6,7 +6,7 @@
Check Python modules and C API for coverage. Mostly written by Josip Check Python modules and C API for coverage. Mostly written by Josip
Dzolonga for the Google Highly Open Participation contest. Dzolonga for the Google Highly Open Participation contest.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -6,7 +6,7 @@
Mimic doctest by automatically executing code snippets and checking Mimic doctest by automatically executing code snippets and checking
their results. their results.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -20,7 +20,7 @@
You can also give an explicit caption, e.g. :exmpl:`Foo <foo>`. You can also give an explicit caption, e.g. :exmpl:`Foo <foo>`.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -6,7 +6,7 @@
Allow graphviz-formatted graphs to be included in Sphinx-generated Allow graphviz-formatted graphs to be included in Sphinx-generated
documents inline. documents inline.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -14,7 +14,6 @@ import re
import codecs import codecs
import posixpath import posixpath
from os import path from os import path
from math import ceil
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
try: try:
from hashlib import sha1 as sha from hashlib import sha1 as sha
@ -125,7 +124,7 @@ def render_dot(self, code, options, format, prefix='graphviz'):
str(self.builder.config.graphviz_dot) + \ str(self.builder.config.graphviz_dot) + \
str(self.builder.config.graphviz_dot_args) str(self.builder.config.graphviz_dot_args)
).encode('utf-8') ).encode('utf-8')
fname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), format) fname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), format)
if hasattr(self.builder, 'imgpath'): if hasattr(self.builder, 'imgpath'):
# HTML # HTML

View File

@ -16,7 +16,7 @@
namespace of the project configuration (that is, all variables from namespace of the project configuration (that is, all variables from
``conf.py`` are available.) ``conf.py`` are available.)
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -32,7 +32,7 @@ r"""
The graph is inserted as a PNG+image map into HTML and a PDF in The graph is inserted as a PNG+image map into HTML and a PDF in
LaTeX. LaTeX.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -168,7 +168,7 @@ class InheritanceGraph(object):
for cls in classes: for cls in classes:
recurse(cls) recurse(cls)
return all_classes.values() return all_classes
def class_name(self, cls, parts=0): def class_name(self, cls, parts=0):
"""Given a class object, return a fully-qualified name. """Given a class object, return a fully-qualified name.
@ -188,7 +188,7 @@ class InheritanceGraph(object):
def get_all_class_names(self): def get_all_class_names(self):
"""Get all of the class names involved in the graph.""" """Get all of the class names involved in the graph."""
return [fullname for (_, fullname, _) in self.class_info] return [fullname for (_, fullname, _) in self.class_info.values()]
# These are the default attrs for graphviz # These are the default attrs for graphviz
default_graph_attrs = { default_graph_attrs = {
@ -199,8 +199,8 @@ class InheritanceGraph(object):
'shape': 'box', 'shape': 'box',
'fontsize': 10, 'fontsize': 10,
'height': 0.25, 'height': 0.25,
'fontname': 'Vera Sans, DejaVu Sans, Liberation Sans, ' 'fontname': '"Vera Sans, DejaVu Sans, Liberation Sans, '
'Arial, Helvetica, sans', 'Arial, Helvetica, sans"',
'style': '"setlinewidth(0.5)"', 'style': '"setlinewidth(0.5)"',
} }
default_edge_attrs = { default_edge_attrs = {
@ -241,12 +241,16 @@ class InheritanceGraph(object):
res.append('digraph %s {\n' % name) res.append('digraph %s {\n' % name)
res.append(self._format_graph_attrs(g_attrs)) res.append(self._format_graph_attrs(g_attrs))
for name, fullname, bases in self.class_info: for cls, (name, fullname, bases) in self.class_info.items():
# Write the node # Write the node
this_node_attrs = n_attrs.copy() this_node_attrs = n_attrs.copy()
url = urls.get(fullname) if fullname in urls:
if url is not None: this_node_attrs['URL'] = '"%s"' % urls[fullname]
this_node_attrs['URL'] = '"%s"' % url # Use first line of docstring as tooltip, if available
if cls.__doc__:
doc = cls.__doc__.strip().split("\n")[0]
if doc:
this_node_attrs['tooltip'] = '"%s"' % doc
res.append(' "%s" [%s];\n' % res.append(' "%s" [%s];\n' %
(name, self._format_node_attrs(this_node_attrs))) (name, self._format_node_attrs(this_node_attrs)))

View File

@ -20,7 +20,7 @@
also be specified individually, e.g. if the docs should be buildable also be specified individually, e.g. if the docs should be buildable
without Internet access. without Internet access.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -188,7 +188,17 @@ def load_mappings(app):
if update: if update:
env.intersphinx_inventory = {} env.intersphinx_inventory = {}
env.intersphinx_named_inventory = {} env.intersphinx_named_inventory = {}
for name, _, invdata in cache.itervalues(): # Duplicate values in different inventories will shadow each
# other; which one will override which can vary between builds
# since they are specified using an unordered dict. To make
# it more consistent, we sort the named inventories and then
# add the unnamed inventories last. This means that the
# unnamed inventories will shadow the named ones but the named
# ones can still be accessed when the name is specified.
cached_vals = list(cache.itervalues())
named_vals = sorted(v for v in cached_vals if v[0])
unnamed_vals = [v for v in cached_vals if not v[0]]
for name, _, invdata in named_vals + unnamed_vals:
if name: if name:
env.intersphinx_named_inventory[name] = invdata env.intersphinx_named_inventory[name] = invdata
for type, objects in invdata.iteritems(): for type, objects in invdata.iteritems():

View File

@ -6,7 +6,7 @@
Set up everything for use of JSMath to display math in HTML Set up everything for use of JSMath to display math in HTML
via JavaScript. via JavaScript.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

72
sphinx/ext/linkcode.py Normal file
View File

@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
"""
sphinx.ext.linkcode
~~~~~~~~~~~~~~~~~~~
Add external links to module code in Python object descriptions.
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from docutils import nodes
from sphinx import addnodes
from sphinx.locale import _
from sphinx.errors import SphinxError
class LinkcodeError(SphinxError):
category = "linkcode error"
def doctree_read(app, doctree):
env = app.builder.env
resolve_target = getattr(env.config, 'linkcode_resolve', None)
if not callable(env.config.linkcode_resolve):
raise LinkcodeError(
"Function `linkcode_resolve` is not given in conf.py")
domain_keys = dict(
py=['module', 'fullname'],
c=['names'],
cpp=['names'],
js=['object', 'fullname'],
)
for objnode in doctree.traverse(addnodes.desc):
domain = objnode.get('domain')
uris = set()
for signode in objnode:
if not isinstance(signode, addnodes.desc_signature):
continue
# Convert signode to a specified format
info = {}
for key in domain_keys.get(domain, []):
value = signode.get(key)
if not value:
value = ''
info[key] = value
if not info:
continue
# Call user code to resolve the link
uri = resolve_target(domain, info)
if not uri:
# no source
continue
if uri in uris or not uri:
# only one link per name, please
continue
uris.add(uri)
onlynode = addnodes.only(expr='html')
onlynode += nodes.reference('', '', internal=False, refuri=uri)
onlynode[0] += nodes.inline('', _('[source]'),
classes=['viewcode-link'])
signode += onlynode
def setup(app):
app.connect('doctree-read', doctree_read)
app.add_config_value('linkcode_resolve', None, '')

View File

@ -5,7 +5,7 @@
Set up math support in source files and LaTeX/text output. Set up math support in source files and LaTeX/text output.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -7,7 +7,7 @@
Sphinx's HTML writer -- requires the MathJax JavaScript library on your Sphinx's HTML writer -- requires the MathJax JavaScript library on your
webserver/computer. webserver/computer.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """

View File

@ -5,7 +5,7 @@
Extension for compatibility with old C markup (directives and roles). Extension for compatibility with old C markup (directives and roles).
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -16,7 +16,7 @@ from sphinx.util.compat import Directive
_warned_oldcmarkup = False _warned_oldcmarkup = False
WARNING_MSG = 'using old C markup; please migrate to new-style markup ' \ WARNING_MSG = 'using old C markup; please migrate to new-style markup ' \
'(e.g. c:function instead of cfunction), see ' \ '(e.g. c:function instead of cfunction), see ' \
'http://sphinx.pocoo.org/domains.html' 'http://sphinx-doc.org/domains.html'
class OldCDirective(Directive): class OldCDirective(Directive):

View File

@ -5,7 +5,7 @@
Render math in HTML via dvipng. Render math in HTML via dvipng.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -32,6 +32,13 @@ from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
class MathExtError(SphinxError): class MathExtError(SphinxError):
category = 'Math extension error' category = 'Math extension error'
def __init__(self, msg, stderr=None, stdout=None):
if stderr:
msg += '\n[stderr]\n' + stderr
if stdout:
msg += '\n[stdout]\n' + stdout
SphinxError.__init__(self, msg)
DOC_HEAD = r''' DOC_HEAD = r'''
\documentclass[12pt]{article} \documentclass[12pt]{article}
@ -130,8 +137,7 @@ def render_math(self, math):
stdout, stderr = p.communicate() stdout, stderr = p.communicate()
if p.returncode != 0: if p.returncode != 0:
raise MathExtError('latex exited with error:\n[stderr]\n%s\n' raise MathExtError('latex exited with error', stderr, stdout)
'[stdout]\n%s' % (stderr, stdout))
ensuredir(path.dirname(outfn)) ensuredir(path.dirname(outfn))
# use some standard dvipng arguments # use some standard dvipng arguments
@ -155,8 +161,7 @@ def render_math(self, math):
return None, None return None, None
stdout, stderr = p.communicate() stdout, stderr = p.communicate()
if p.returncode != 0: if p.returncode != 0:
raise MathExtError('dvipng exited with error:\n[stderr]\n%s\n' raise MathExtError('dvipng exited with error', stderr, stdout)
'[stdout]\n%s' % (stderr, stdout))
depth = None depth = None
if use_preview: if use_preview:
for line in stdout.splitlines(): for line in stdout.splitlines():
@ -237,7 +242,8 @@ def setup(app):
app.add_config_value('pngmath_latex', 'latex', 'html') app.add_config_value('pngmath_latex', 'latex', 'html')
app.add_config_value('pngmath_use_preview', False, 'html') app.add_config_value('pngmath_use_preview', False, 'html')
app.add_config_value('pngmath_dvipng_args', app.add_config_value('pngmath_dvipng_args',
['-gamma 1.5', '-D 110'], 'html') ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent'],
'html')
app.add_config_value('pngmath_latex_args', [], 'html') app.add_config_value('pngmath_latex_args', [], 'html')
app.add_config_value('pngmath_latex_preamble', '', 'html') app.add_config_value('pngmath_latex_preamble', '', 'html')
app.add_config_value('pngmath_add_tooltips', True, 'html') app.add_config_value('pngmath_add_tooltips', True, 'html')

View File

@ -9,7 +9,7 @@
Usage: Set the `refcount_file` config value to the path to the reference Usage: Set the `refcount_file` config value to the path to the reference
count data file. count data file.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
@ -17,6 +17,7 @@ from os import path
from docutils import nodes from docutils import nodes
from sphinx import addnodes from sphinx import addnodes
from sphinx.locale import _
# refcount annotation # refcount annotation
@ -78,12 +79,12 @@ class Refcounts(dict):
continue continue
elif entry.result_type not in ("PyObject*", "PyVarObject*"): elif entry.result_type not in ("PyObject*", "PyVarObject*"):
continue continue
rc = 'Return value: '
if entry.result_refs is None: if entry.result_refs is None:
rc += "Always NULL." rc = _('Return value: Always NULL.')
elif entry.result_refs:
rc = _('Return value: New reference.')
else: else:
rc += (entry.result_refs and "New" or "Borrowed") + \ rc = _('Return value: Borrowed reference.')
" reference."
node.insert(0, refcount(rc, rc)) node.insert(0, refcount(rc, rc))

Some files were not shown because too many files have changed in this diff Show More