Allow the configuration directory to be set differently from the source directory.

Also don't import docutils on importing sphinx.
This commit is contained in:
Georg Brandl 2008-05-02 10:32:08 +00:00
parent 5a6e3b61d1
commit e2158213e8
9 changed files with 101 additions and 72 deletions

View File

@ -11,10 +11,10 @@ Document names
Since the reST source files can have different extensions (some people like Since the reST source files can have different extensions (some people like
``.txt``, some like ``.rst`` -- the extension can be configured with ``.txt``, some like ``.rst`` -- the extension can be configured with
:confval:`source_suffix`) and different OSes have different path separators, :confval:`source_suffix`) and different OSes have different path separators,
Sphinx abstracts them: all "document names" are relative to the Sphinx abstracts them: all "document names" are relative to the :term:`source
:term:`documentation root`, the extension is stripped, and path separators are directory`, the extension is stripped, and path separators are converted to
converted to slashes. All values, parameters and suchlike referring to slashes. All values, parameters and suchlike referring to "documents" expect
"documents" expect such a document name. such a document name.
The TOC tree The TOC tree
@ -71,11 +71,12 @@ tables of contents. The ``toctree`` directive is the central element.
The second line above will link to the ``strings`` document, but will use the The second line above will link to the ``strings`` document, but will use the
title "All about strings" instead of the title of the ``strings`` document. title "All about strings" instead of the title of the ``strings`` document.
In the end, all documents under the :term:`documentation root` must occur in In the end, all documents in the :term:`source directory` (or subdirectories)
some ``toctree`` directive; Sphinx will emit a warning if it finds a file must occur in some ``toctree`` directive; Sphinx will emit a warning if it
that is not included, because that means that this file will not be reachable finds a file that is not included, because that means that this file will not
through standard navigation. Use :confval:`unused_documents` to explicitly be reachable through standard navigation. Use :confval:`unused_documents` to
exclude documents from this check. explicitly exclude documents from this check, and :confval:`exclude_dirs` to
exclude whole directories.
The "master document" (selected by :confval:`master_doc`) is the "root" of The "master document" (selected by :confval:`master_doc`) is the "root" of
the TOC tree hierarchy. It can be used as the documentation's main page, or the TOC tree hierarchy. It can be used as the documentation's main page, or

View File

@ -6,30 +6,32 @@ The build configuration file
.. module:: conf .. module:: conf
:synopsis: Build configuration file. :synopsis: Build configuration file.
The :term:`documentation root` must contain a file named :file:`conf.py`. This The :term:`configuration directory` must contain a file named :file:`conf.py`.
file (containing Python code) is called the "build configuration file" and This file (containing Python code) is called the "build configuration file" and
contains all configuration needed to customize Sphinx input and output behavior. contains all configuration needed to customize Sphinx input and output behavior.
The configuration file if executed as Python code at build time (using The configuration file if executed as Python code at build time (using
:func:`execfile`, and with the current directory set to the documentation root), :func:`execfile`, and with the current directory set to its containing
and therefore can execute arbitrarily complex code. Sphinx then reads simple directory), and therefore can execute arbitrarily complex code. Sphinx then
names from the file's namespace as its configuration. reads simple names from the file's namespace as its configuration.
Some conventions are important to keep in mind here: Relative paths are always Important points to note:
used relative to the documentation root, and document names must always be given
without file name extension.
The term "fully-qualified name" refers to a string that names an importable * If not otherwise documented, values must be strings, and their default is the
Python object inside a module; for example, the FQN ``"sphinx.builder.Builder"`` empty string.
means the ``Builder`` class in the ``sphinx.builder`` module.
The contents of the namespace are pickled (so that Sphinx can find out when * The term "fully-qualified name" refers to a string that names an importable
configuration changes), so it may not contain unpickleable values -- delete them Python object inside a module; for example, the FQN
from the namespace with ``del`` if appropriate. Modules are removed ``"sphinx.builder.Builder"`` means the ``Builder`` class in the
automatically, so you don't need to ``del`` your imports after use. ``sphinx.builder`` module.
The configuration values can be separated in several groups. If not otherwise * Remember that document names use ``/`` as the path separator and don't contain
documented, values must be strings, and their default is the empty string. the file name extension.
* The contents of the config namespace are pickled (so that Sphinx can find out
when configuration changes), so it may not contain unpickleable values --
delete them from the namespace with ``del`` if appropriate. Modules are
removed automatically, so you don't need to ``del`` your imports after use.
General configuration General configuration
@ -41,9 +43,9 @@ General configuration
extensions coming with Sphinx (named ``sphinx.addons.*``) or custom ones. extensions coming with Sphinx (named ``sphinx.addons.*``) or custom ones.
Note that you can extend :data:`sys.path` within the conf file if your Note that you can extend :data:`sys.path` within the conf file if your
extensions live in another directory -- but make sure you use absolute extensions live in another directory -- but make sure you use absolute paths.
paths. If your extension path is relative to the documentation root, use If your extension path is relative to the :term:`configuration directory`,
:func:`os.path.abspath` like so:: use :func:`os.path.abspath` like so::
import sys, os import sys, os
@ -51,8 +53,8 @@ General configuration
extensions = ['extname'] extensions = ['extname']
That way, you can load an extension called ``extname`` from the documentation That way, you can load an extension called ``extname`` from the subdirectory
root's subdirectory ``sphinxext``. ``sphinxext``.
The configuration file itself can be an extension; for that, you only need to The configuration file itself can be an extension; for that, you only need to
provide a :func:`setup` function in it. provide a :func:`setup` function in it.
@ -128,7 +130,8 @@ General configuration
.. confval:: templates_path .. confval:: templates_path
A list of paths that contain extra templates (or templates that overwrite A list of paths that contain extra templates (or templates that overwrite
builtin templates). builtin templates). Relative paths are taken as relative to the
configuration directory.
.. confval:: template_bridge .. confval:: template_bridge
@ -186,8 +189,9 @@ that use Sphinx' HTMLWriter class.
.. confval:: html_static_path .. confval:: html_static_path
A list of paths that contain custom static files (such as style sheets or A list of paths that contain custom static files (such as style sheets or
script files). They are copied to the output directory after the builtin script files). Relative paths are taken as relative to the configuration
static files, so a file named :file:`default.css` will overwrite the builtin directory. They are copied to the output directory after the builtin static
files, so a file named :file:`default.css` will overwrite the builtin
:file:`default.css`. :file:`default.css`.
.. confval:: html_last_updated_fmt .. confval:: html_last_updated_fmt
@ -303,8 +307,8 @@ These options influence LaTeX output.
.. confval:: latex_logo .. confval:: latex_logo
If given, this must be the name of an image file (relative to the If given, this must be the name of an image file (relative to the
documentation root) that is the logo of the docs. It is placed at the top of configuration directory) that is the logo of the docs. It is placed at the
the title page. Default: ``None``. top of the title page. Default: ``None``.
.. confval:: latex_appendices .. confval:: latex_appendices

View File

@ -14,17 +14,22 @@ Glossary
See :ref:`builders` for an overview over Sphinx' built-in builders. See :ref:`builders` for an overview over Sphinx' built-in builders.
configuration directory
The directory containing :file:`conf.py`. By default, this is the same as
the :term:`source directory`, but can be set differently with the **-c**
command-line option.
description unit description unit
The basic building block of Sphinx documentation. Every "description The basic building block of Sphinx documentation. Every "description
directive" (e.g. :dir:`function` or :dir:`describe`) creates such a unit; directive" (e.g. :dir:`function` or :dir:`describe`) creates such a unit;
and most units can be cross-referenced to. and most units can be cross-referenced to.
documentation root
The directory which contains the documentation's :file:`conf.py` file and
is therefore seen as one Sphinx project.
environment environment
A structure where information about all documents under the root is saved, A structure where information about all documents under the root is saved,
and used for cross-referencing. The environment is pickled after the and used for cross-referencing. The environment is pickled after the
parsing stage, so that successive runs only need to read and parse new and parsing stage, so that successive runs only need to read and parse new and
changed documents. changed documents.
source directory
The directory which, including its subdirectories, contains all source
files for one Sphinx project.

View File

@ -31,16 +31,20 @@ or some (not broken) SVN trunk snapshot.
.. _Pygments: http://pygments.org .. _Pygments: http://pygments.org
Setting up a documentation root Setting up the documentation sources
------------------------------- ------------------------------------
The root directory of a documentation collection is called the The root directory of a documentation collection is called the :dfn:`source
:dfn:`documentation root`. There's nothing special about it; it just needs to directory`. Normally, this directory also contains the Sphinx configuration
contain the Sphinx configuration file, :file:`conf.py`. file :file:`conf.py`, but that file can also live in another directory, the
:dfn:`configuration directory`.
.. versionadded:: 0.2.1
Support for a different configuration directory.
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
documentation root and creates a default :file:`conf.py` from a few questions source directory and creates a default :file:`conf.py` from a few questions it
it asks you. Just run :: asks you. Just run ::
$ sphinx-quickstart $ sphinx-quickstart
@ -55,7 +59,7 @@ like this::
$ sphinx-build -b latex sourcedir builddir $ sphinx-build -b latex sourcedir builddir
where *sourcedir* is the :term:`documentation root`, and *builddir* is the where *sourcedir* is the :term:`source directory`, and *builddir* is the
directory in which you want to place the built documentation (it must be an directory in which you want to place the built documentation (it must be an
existing directory). The :option:`-b` option selects a builder; in this example existing directory). The :option:`-b` option selects a builder; in this example
Sphinx will build LaTeX files. Sphinx will build LaTeX files.
@ -79,6 +83,15 @@ The :program:`sphinx-build` script has several more options:
the build directory; with this option you can select a different cache the build directory; with this option you can select a different cache
directory (the doctrees can be shared between all builders). directory (the doctrees can be shared between all builders).
**-c** *path*
Don't look for the :file:`conf.py` in the source directory, but use the given
configuration directory instead. Note that various other files and paths
given by configuration values are expected to be relative to the
configuration directory, so they will have to be present at this location
too.
.. versionadded:: 0.2.1
**-D** *setting=value* **-D** *setting=value*
Override a configuration value set in the :file:`conf.py` file. (The value Override a configuration value set in the :file:`conf.py` file. (The value
must be a string value.) must be a string value.)

View File

@ -169,16 +169,15 @@ Glossary
.. glossary:: .. glossary::
documentation root
The directory which contains the documentation's :file:`conf.py` file and
is therefore seen as one Sphinx project.
environment environment
A structure where information about all documents under the root is saved, A structure where information about all documents under the root is saved,
and used for cross-referencing. The environment is pickled after the and used for cross-referencing. The environment is pickled after the
parsing stage, so that successive runs only need to read and parse new and parsing stage, so that successive runs only need to read and parse new and
changed documents. changed documents.
source directory
The directory which, including its subdirectories, contains all source
files for one Sphinx project.
Grammar production displays Grammar production displays

View File

@ -16,10 +16,7 @@ import traceback
from os import path from os import path
from cStringIO import StringIO from cStringIO import StringIO
from docutils.utils import SystemMessage
from sphinx.util import format_exception_cut_frames, save_traceback from sphinx.util import format_exception_cut_frames, save_traceback
from sphinx.application import Sphinx
from sphinx.util.console import darkred, nocolor from sphinx.util.console import darkred, nocolor
__revision__ = '$Revision$' __revision__ = '$Revision$'
@ -37,8 +34,10 @@ Options: -b <builder> -- builder to use; default is html
-a -- write all files; default is to only write new and changed files -a -- write all files; default is to only write new and changed files
-E -- don't use a saved environment, always read all files -E -- don't use a saved environment, always read all files
-d <path> -- path for the cached environment and doctree files -d <path> -- path for the cached environment and doctree files
(default outdir/.doctrees) (default: outdir/.doctrees)
-D <setting=value> -- override a setting in sourcedir/conf.py -c <path> -- path where configuration file (conf.py) is located
(default: same as sourcedir)
-D <setting=value> -- override a setting in configuration
-N -- do not do colored output -N -- do not do colored output
-q -- no output on stdout, just warnings on stderr -q -- no output on stdout, just warnings on stderr
-P -- run Pdb on exception -P -- run Pdb on exception
@ -49,17 +48,23 @@ Modi:
def main(argv=sys.argv): def main(argv=sys.argv):
# delay-import these to be able to get sphinx.__version__ from setup.py
# even without docutils installed
from sphinx.application import Sphinx
from docutils.utils import SystemMessage
if not sys.stdout.isatty() or sys.platform == 'win32': if not sys.stdout.isatty() or sys.platform == 'win32':
# Windows' poor cmd box doesn't understand ANSI sequences # Windows' poor cmd box doesn't understand ANSI sequences
nocolor() nocolor()
try: try:
opts, args = getopt.getopt(argv[1:], 'ab:d:D:NEqP') opts, args = getopt.getopt(argv[1:], 'ab:d:c:D:NEqP')
srcdir = path.abspath(args[0]) srcdir = confdir = path.abspath(args[0])
if not path.isdir(srcdir): if not path.isdir(srcdir):
print >>sys.stderr, 'Error: Cannot find source directory.' print >>sys.stderr, 'Error: Cannot find source directory.'
return 1 return 1
if not path.isfile(path.join(srcdir, 'conf.py')): if not path.isfile(path.join(srcdir, 'conf.py')) and \
'-c' not in (opt[0] for opt in opts):
print >>sys.stderr, 'Error: Source directory doesn\'t contain conf.py file.' print >>sys.stderr, 'Error: Source directory doesn\'t contain conf.py file.'
return 1 return 1
outdir = path.abspath(args[1]) outdir = path.abspath(args[1])
@ -94,6 +99,12 @@ def main(argv=sys.argv):
all_files = True all_files = True
elif opt == '-d': elif opt == '-d':
doctreedir = val doctreedir = val
elif opt == '-c':
confdir = path.abspath(val)
if not path.isfile(path.join(confdir, 'conf.py')):
print >>sys.stderr, \
'Error: Configuration directory doesn\'t contain conf.py file.'
return 1
elif opt == '-D': elif opt == '-D':
key, val = val.split('=') key, val = val.split('=')
try: try:
@ -110,7 +121,7 @@ def main(argv=sys.argv):
use_pdb = True use_pdb = True
try: try:
app = Sphinx(srcdir, outdir, doctreedir, buildername, app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername,
confoverrides, status, sys.stderr, freshenv) confoverrides, status, sys.stderr, freshenv)
if not app.builder: if not app.builder:
return 1 return 1

View File

@ -60,7 +60,7 @@ class BuiltinTemplates(TemplateBridge):
def init(self, builder): def init(self, builder):
self.templates = {} self.templates = {}
base_templates_path = path.join(path.dirname(__file__), 'templates') base_templates_path = path.join(path.dirname(__file__), 'templates')
ext_templates_path = [path.join(builder.srcdir, dir) ext_templates_path = [path.join(builder.confdir, dir)
for dir in builder.config.templates_path] for dir in builder.config.templates_path]
self.templates_path = [base_templates_path] + ext_templates_path self.templates_path = [base_templates_path] + ext_templates_path
loader = SphinxFileSystemLoader(base_templates_path, ext_templates_path) loader = SphinxFileSystemLoader(base_templates_path, ext_templates_path)

View File

@ -54,7 +54,7 @@ events = {
class Sphinx(object): class Sphinx(object):
def __init__(self, srcdir, outdir, doctreedir, buildername, def __init__(self, srcdir, confdir, outdir, doctreedir, buildername,
confoverrides, status, warning=sys.stderr, freshenv=False): confoverrides, status, warning=sys.stderr, freshenv=False):
self.next_listener_id = 0 self.next_listener_id = 0
self._listeners = {} self._listeners = {}
@ -62,6 +62,7 @@ class Sphinx(object):
self.builder = None self.builder = None
self.srcdir = srcdir self.srcdir = srcdir
self.confdir = confdir
self.outdir = outdir self.outdir = outdir
self.doctreedir = doctreedir self.doctreedir = doctreedir
@ -72,7 +73,7 @@ class Sphinx(object):
self._events = events.copy() self._events = events.copy()
# read config # read config
self.config = Config(srcdir, 'conf.py') self.config = Config(confdir, 'conf.py')
if confoverrides: if confoverrides:
for key, val in confoverrides.items(): for key, val in confoverrides.items():
setattr(self.config, key, val) setattr(self.config, key, val)

View File

@ -50,6 +50,7 @@ class Builder(object):
def __init__(self, app, env=None, freshenv=False): def __init__(self, app, env=None, freshenv=False):
self.srcdir = app.srcdir self.srcdir = app.srcdir
self.confdir = app.confdir
self.outdir = app.outdir self.outdir = app.outdir
self.doctreedir = app.doctreedir self.doctreedir = app.doctreedir
if not path.isdir(self.doctreedir): if not path.isdir(self.doctreedir):
@ -487,19 +488,13 @@ class StandaloneHTMLBuilder(Builder):
self.info(' '+src, nonl=1) self.info(' '+src, nonl=1)
shutil.copyfile(path.join(self.srcdir, src), shutil.copyfile(path.join(self.srcdir, src),
path.join(self.outdir, '_images', dest)) path.join(self.outdir, '_images', dest))
# the logo is handled differently
if self.config.html_logo:
logobase = path.basename(self.config.html_logo)
self.info(' '+logobase, nonl=1)
shutil.copyfile(path.join(self.srcdir, self.config.html_logo),
path.join(self.outdir, '_static', logobase))
self.info() self.info()
# copy static files # copy static files
self.info(bold('copying static files...')) self.info(bold('copying static files...'))
ensuredir(path.join(self.outdir, '_static')) ensuredir(path.join(self.outdir, '_static'))
staticdirnames = [path.join(path.dirname(__file__), 'static')] + \ staticdirnames = [path.join(path.dirname(__file__), 'static')] + \
[path.join(self.srcdir, spath) [path.join(self.confdir, spath)
for spath in self.config.html_static_path] for spath in self.config.html_static_path]
for staticdirname in staticdirnames: for staticdirname in staticdirnames:
for filename in os.listdir(staticdirname): for filename in os.listdir(staticdirname):
@ -819,7 +814,7 @@ class LaTeXBuilder(Builder):
if self.config.latex_logo: if self.config.latex_logo:
logobase = path.basename(self.config.latex_logo) logobase = path.basename(self.config.latex_logo)
self.info(' '+logobase, nonl=1) self.info(' '+logobase, nonl=1)
shutil.copyfile(path.join(self.srcdir, self.config.latex_logo), shutil.copyfile(path.join(self.confdir, self.config.latex_logo),
path.join(self.outdir, logobase)) path.join(self.outdir, logobase))
self.info(bold('copying TeX support files...')) self.info(bold('copying TeX support files...'))