Allow the config to act as an extension.

This commit is contained in:
Georg Brandl 2008-04-06 17:38:55 +00:00
parent b016896c1c
commit ea2f87fc03
8 changed files with 62 additions and 48 deletions

View File

@ -13,6 +13,9 @@ Changes in trunk
* sphinx.builder, sphinx.environment: Gracefully handle some exception
cases.
* sphinx.config: The config file itself can be an extension (if it
provides a setup() function).
Release 0.1.61950 (Mar 26, 2008)
================================

View File

@ -11,17 +11,17 @@
# All configuration values have a default value; values that are commented out
# serve to show the default value.
import sys, os
import sys, os, re
# If your extensions are in another directory, add it here.
sys.path.append(os.path.dirname(__file__))
#sys.path.append(os.path.dirname(__file__))
# General configuration
# ---------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.addons.*') or your custom ones.
extensions = ['ext', 'sphinx.ext.autodoc', 'sphinx.ext.doctest']
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -125,3 +125,37 @@ latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
#latex_appendices = []
automodule_skip_lines = 4
# Extension interface
# -------------------
from sphinx import addnodes
dir_sig_re = re.compile(r'\.\. ([^:]+)::(.*)$')
def parse_directive(env, sig, signode):
if not sig.startswith('.'):
dec_sig = '.. %s::' % sig
signode += addnodes.desc_name(dec_sig, dec_sig)
return sig
m = dir_sig_re.match(sig)
if not m:
signode += addnodes.desc_name(sig, sig)
return sig
name, args = m.groups()
dec_name = '.. %s::' % name
signode += addnodes.desc_name(dec_name, dec_name)
signode += addnodes.desc_classname(args, args)
return name
def parse_role(env, sig, signode):
signode += addnodes.desc_name(':%s:' % sig, ':%s:' % sig)
return sig
def setup(app):
app.add_description_unit('directive', 'dir', 'pair: %s; directive', parse_directive)
app.add_description_unit('role', 'role', 'pair: %s; role', parse_role)
app.add_description_unit('confval', 'confval', 'pair: %s; configuration value')

View File

@ -50,6 +50,9 @@ General configuration
That way, you can load an extension called ``extname`` from the documentation
root's subdirectory ``sphinxext``.
The configuration file itself can be an extension; for that, you only need to
provide a :func:`setup` function in it.
.. confval:: templates_path
A list of paths that contain extra templates (or templates that overwrite

View File

@ -1,40 +0,0 @@
# -*- coding: utf-8 -*-
"""
ext.py -- Sphinx extension for the Sphinx documentation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: 2008 by Georg Brandl.
:license: BSD.
"""
import re
from sphinx import addnodes
dir_sig_re = re.compile(r'\.\. ([^:]+)::(.*)$')
def parse_directive(env, sig, signode):
if not sig.startswith('.'):
dec_sig = '.. %s::' % sig
signode += addnodes.desc_name(dec_sig, dec_sig)
return sig
m = dir_sig_re.match(sig)
if not m:
signode += addnodes.desc_name(sig, sig)
return sig
name, args = m.groups()
dec_name = '.. %s::' % name
signode += addnodes.desc_name(dec_name, dec_name)
signode += addnodes.desc_classname(args, args)
return name
def parse_role(env, sig, signode):
signode += addnodes.desc_name(':%s:' % sig, ':%s:' % sig)
return sig
def setup(app):
app.add_description_unit('directive', 'dir', 'pair: %s; directive', parse_directive)
app.add_description_unit('role', 'role', 'pair: %s; role', parse_role)
app.add_description_unit('confval', 'confval', 'pair: %s; configuration value')

View File

@ -15,6 +15,9 @@ reStructuredText roles and directives, extending the markup. And finally, there
are so-called "hook points" at strategic places throughout the build process,
where an extension can register a hook and run specialized code.
The configuration file itself can be an extension, see the :confval:`extensions`
configuration value docs.
.. toctree::
ext/appapi

View File

@ -79,6 +79,9 @@ class Sphinx(object):
# load all extension modules
for extension in getattr(self.config, 'extensions', ()):
self.setup_extension(extension)
# the config file itself can be an extension
if hasattr(self.config, 'setup'):
self.config.setup(self)
# this must happen after loading extension modules, since they
# can add custom config values

View File

@ -10,7 +10,6 @@
"""
import os
import types
from os import path
@ -77,10 +76,6 @@ class Config(object):
execfile(config['__file__'], config)
finally:
os.chdir(olddir)
# remove potentially pickling-problematic values
for key, val in config.items():
if key.startswith('_') or isinstance(val, types.ModuleType):
del config[key]
self.__dict__.update(config)
def init_defaults(self):
@ -91,5 +86,11 @@ class Config(object):
def __getitem__(self, name):
return getattr(self, name)
def __setitem__(self, name, value):
setattr(self, name, value)
def __delitem__(self, name):
delattr(self, name)
def __contains__(self, name):
return hasattr(self, name)

View File

@ -13,6 +13,7 @@ import re
import os
import time
import heapq
import types
import difflib
import itertools
import cPickle as pickle
@ -179,6 +180,12 @@ class BuildEnvironment:
warnfunc = self._warnfunc
self.set_warnfunc(None)
picklefile = open(filename, 'wb')
# remove potentially pickling-problematic values from config
for key, val in vars(self.config).items():
if key.startswith('_') or \
isinstance(val, types.ModuleType) or \
isinstance(val, types.FunctionType):
del self.config[key]
try:
pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL)
finally: