merge with 1.0

This commit is contained in:
Georg Brandl
2011-01-07 19:04:53 +01:00
14 changed files with 97 additions and 29 deletions

17
CHANGES
View File

@@ -78,6 +78,23 @@ Release 1.1 (in development)
Release 1.0.7 (in development) Release 1.0.7 (in development)
============================== ==============================
* Fix general index links for C++ domain objects.
* #332: Make admonition boundaries in LaTeX output visible.
* #573: Fix KeyErrors occurring on rebuild after removing a file.
* Fix a traceback when removing files with globbed toctrees.
* If an autodoc object cannot be imported, always re-read the
document containing the directive on next build.
* If an autodoc object cannot be imported, show the full traceback
of the import error.
* Fix a bug where the removal of download files and images wasn't
noticed.
* #571: Implement ``~`` cross-reference prefix for the C domain. * #571: Implement ``~`` cross-reference prefix for the C domain.
* Fix regression of LaTeX output with the fix of #556. * Fix regression of LaTeX output with the fix of #556.

View File

@@ -20,6 +20,7 @@ Documentation using the default theme
* Cython: http://docs.cython.org/ * Cython: http://docs.cython.org/
* C\\C++ Python language binding project: http://language-binding.net/index.html * C\\C++ Python language binding project: http://language-binding.net/index.html
* Director: http://packages.python.org/director/ * Director: http://packages.python.org/director/
* Dirigible: http://www.projectdirigible.com/documentation/
* F2py: http://f2py.sourceforge.net/docs/ * F2py: http://f2py.sourceforge.net/docs/
* GeoDjango: http://geodjango.org/docs/ * GeoDjango: http://geodjango.org/docs/
* gevent: http://www.gevent.org/ * gevent: http://www.gevent.org/

View File

@@ -99,8 +99,12 @@ def parse_event(env, sig, signode):
def setup(app): def setup(app):
from sphinx.ext.autodoc import cut_lines from sphinx.ext.autodoc import cut_lines
from sphinx.util.docfields import GroupedField
app.connect('autodoc-process-docstring', cut_lines(4, what=['module'])) app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
app.add_description_unit('confval', 'confval', app.add_object_type('confval', 'confval',
objname='configuration value', objname='configuration value',
indextemplate='pair: %s; configuration value') indextemplate='pair: %s; configuration value')
app.add_description_unit('event', 'event', 'pair: %s; event', parse_event) fdesc = GroupedField('parameter', label='Parameters',
names=['param'], can_collapse=True)
app.add_object_type('event', 'event', 'pair: %s; event', parse_event,
doc_field_types=[fdesc])

View File

@@ -163,7 +163,8 @@ the following public API:
.. versionadded:: 0.6 .. versionadded:: 0.6
.. method:: Sphinx.add_object_type(directivename, rolename, indextemplate='', parse_node=None, ref_nodeclass=None, objname='') .. method:: Sphinx.add_object_type(directivename, rolename, indextemplate='', parse_node=None, \
ref_nodeclass=None, objname='', doc_field_types=[])
This method is a very convenient way to add a new :term:`object` type that This method is a very convenient way to add a new :term:`object` type that
can be cross-referenced. It will do this: can be cross-referenced. It will do this:

View File

@@ -432,13 +432,15 @@ class Sphinx(object):
setattr(self.domains[domain], 'get_%s_index' % name, func) setattr(self.domains[domain], 'get_%s_index' % name, func)
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=[]):
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
new_directive = type(directivename, (GenericObject, object), new_directive = type(directivename, (GenericObject, object),
{'indextemplate': indextemplate, {'indextemplate': indextemplate,
'parse_node': staticmethod(parse_node)}) 'parse_node': staticmethod(parse_node),
'doc_field_types': doc_field_types})
StandardDomain.directives[directivename] = new_directive StandardDomain.directives[directivename] = new_directive
# XXX support more options? # XXX support more options?
StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass) StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)

View File

@@ -272,7 +272,8 @@ class Builder(object):
# add all toctree-containing files that may have changed # add all toctree-containing files that may have changed
for docname in list(docnames): for docname in list(docnames):
for tocdocname in self.env.files_to_rebuild.get(docname, []): for tocdocname in self.env.files_to_rebuild.get(docname, []):
docnames.add(tocdocname) if tocdocname in self.env.found_docs:
docnames.add(tocdocname)
docnames.add(self.config.master_doc) docnames.add(self.config.master_doc)
self.info(bold('preparing documents... '), nonl=True) self.info(bold('preparing documents... '), nonl=True)

View File

@@ -62,6 +62,7 @@ class CodeBlock(Directive):
literal = nodes.literal_block(code, code) literal = nodes.literal_block(code, code)
literal['language'] = self.arguments[0] literal['language'] = self.arguments[0]
literal['linenos'] = 'linenos' in self.options literal['linenos'] = 'linenos' in self.options
literal.line = self.lineno
return [literal] return [literal]
@@ -166,6 +167,7 @@ class LiteralInclude(Directive):
text = text.expandtabs(self.options['tab-width']) text = text.expandtabs(self.options['tab-width'])
retnode = nodes.literal_block(text, text, source=filename) retnode = nodes.literal_block(text, text, source=filename)
retnode.line = 1 retnode.line = 1
retnode.attributes['line_number'] = self.lineno
if self.options.get('language', ''): if self.options.get('language', ''):
retnode['language'] = self.options['language'] retnode['language'] = self.options['language']
if 'linenos' in self.options: if 'linenos' in self.options:

View File

@@ -80,8 +80,9 @@ class TocTree(Directive):
entries.append((title, ref)) entries.append((title, ref))
elif docname not in env.found_docs: elif docname not in env.found_docs:
ret.append(self.state.document.reporter.warning( ret.append(self.state.document.reporter.warning(
'toctree references unknown document %r' % docname, 'toctree contains reference to nonexisting '
line=self.lineno)) 'document %r' % docname, line=self.lineno))
env.note_reread()
else: else:
entries.append((title, docname)) entries.append((title, docname))
includefiles.append(docname) includefiles.append(docname)
@@ -237,6 +238,7 @@ class TabularColumns(Directive):
def run(self): def run(self):
node = addnodes.tabular_col_spec() node = addnodes.tabular_col_spec()
node['spec'] = self.arguments[0] node['spec'] = self.arguments[0]
node.line = self.lineno
return [node] return [node]

View File

@@ -67,7 +67,7 @@ default_settings = {
# 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 = 38 ENV_VERSION = 39
default_substitutions = set([ default_substitutions = set([
@@ -336,6 +336,8 @@ class BuildEnvironment:
# contains all built docnames # contains all built docnames
self.dependencies = {} # docname -> set of dependent file self.dependencies = {} # docname -> set of dependent file
# names, relative to documentation root # names, relative to documentation root
self.reread_always = set() # docnames to re-read unconditionally on
# next build
# File metadata # File metadata
self.metadata = {} # docname -> dict of metadata items self.metadata = {} # docname -> dict of metadata items
@@ -385,6 +387,7 @@ class BuildEnvironment:
"""Remove all traces of a source file in the inventory.""" """Remove all traces of a source file in the inventory."""
if docname in self.all_docs: if docname in self.all_docs:
self.all_docs.pop(docname, None) self.all_docs.pop(docname, None)
self.reread_always.discard(docname)
self.metadata.pop(docname, None) self.metadata.pop(docname, None)
self.dependencies.pop(docname, None) self.dependencies.pop(docname, None)
self.titles.pop(docname, None) self.titles.pop(docname, None)
@@ -486,6 +489,10 @@ class BuildEnvironment:
'.doctree')): '.doctree')):
changed.add(docname) changed.add(docname)
continue continue
# check the "reread always" list
if docname in self.reread_always:
changed.add(docname)
continue
# check the mtime of the document # check the mtime of the document
mtime = self.all_docs[docname] mtime = self.all_docs[docname]
newmtime = path.getmtime(self.doc2path(docname)) newmtime = path.getmtime(self.doc2path(docname))
@@ -555,7 +562,8 @@ class BuildEnvironment:
# if files were added or removed, all documents with globbed toctrees # if files were added or removed, all documents with globbed toctrees
# must be reread # must be reread
if added or removed: if added or removed:
changed.update(self.glob_toctrees) # ... but not those that already were removed
changed.update(self.glob_toctrees & self.found_docs)
msg += '%s added, %s changed, %s removed' % (len(added), len(changed), msg += '%s added, %s changed, %s removed' % (len(added), len(changed),
len(removed)) len(removed))
@@ -687,6 +695,11 @@ class BuildEnvironment:
codecs.register_error('sphinx', self.warn_and_replace) codecs.register_error('sphinx', self.warn_and_replace)
class SphinxSourceClass(FileInput): class SphinxSourceClass(FileInput):
def __init__(self_, *args, **kwds):
# don't call sys.exit() on IOErrors
kwds['handle_io_errors'] = False
FileInput.__init__(self_, *args, **kwds)
def decode(self_, data): def decode(self_, data):
if isinstance(data, unicode): if isinstance(data, unicode):
return data return data
@@ -795,6 +808,9 @@ class BuildEnvironment:
def note_dependency(self, filename): def note_dependency(self, filename):
self.dependencies.setdefault(self.docname, set()).add(filename) self.dependencies.setdefault(self.docname, set()).add(filename)
def note_reread(self):
self.reread_always.add(self.docname)
def note_versionchange(self, type, version, node, lineno): def note_versionchange(self, type, version, node, lineno):
self.versionchanges.setdefault(version, []).append( self.versionchanges.setdefault(version, []).append(
(type, self.temp_data['docname'], lineno, (type, self.temp_data['docname'], lineno,
@@ -1280,11 +1296,12 @@ class BuildEnvironment:
self.warn(docname, self.warn(docname,
'toctree contains reference to document ' 'toctree contains reference to document '
'%r that doesn\'t have a title: no link ' '%r that doesn\'t have a title: no link '
'will be generated' % ref) 'will be generated' % ref, toctreenode.line)
except KeyError: except KeyError:
# this is raised if the included file does not exist # this is raised if the included file does not exist
self.warn(docname, 'toctree contains reference to ' self.warn(docname, 'toctree contains reference to '
'nonexisting document %r' % ref) 'nonexisting document %r' % ref,
toctreenode.line)
else: else:
# if titles_only is given, only keep the main title and # if titles_only is given, only keep the main title and
# sub-toctrees # sub-toctrees

View File

@@ -14,6 +14,7 @@
import re import re
import sys import sys
import inspect import inspect
import traceback
from types import FunctionType, BuiltinFunctionType, MethodType from types import FunctionType, BuiltinFunctionType, MethodType
from docutils import nodes from docutils import nodes
@@ -216,6 +217,8 @@ class Documenter(object):
priority = 0 priority = 0
#: order if autodoc_member_order is set to 'groupwise' #: order if autodoc_member_order is set to 'groupwise'
member_order = 0 member_order = 0
#: true if the generated content may contain titles
titles_allowed = False
option_spec = {'noindex': bool_option} option_spec = {'noindex': bool_option}
@@ -327,10 +330,13 @@ class Documenter(object):
# 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, err:
if self.env.app and not self.env.app.quiet:
self.env.app.info(traceback.format_exc().rstrip())
self.directive.warn( self.directive.warn(
'autodoc can\'t import/find %s %r, it reported error: ' 'autodoc can\'t import/find %s %r, it reported error: '
'"%s", please check your spelling and sys.path' % '"%s", please check your spelling and sys.path' %
(self.objtype, str(self.fullname), err)) (self.objtype, str(self.fullname), err))
self.env.note_reread()
return False return False
def get_real_modname(self): def get_real_modname(self):
@@ -718,6 +724,7 @@ class ModuleDocumenter(Documenter):
""" """
objtype = 'module' objtype = 'module'
content_indent = u'' content_indent = u''
titles_allowed = True
option_spec = { option_spec = {
'members': members_option, 'undoc-members': bool_option, 'members': members_option, 'undoc-members': bool_option,
@@ -1252,7 +1259,7 @@ class AutoDirective(Directive):
self.state.memo.reporter = AutodocReporter(self.result, self.state.memo.reporter = AutodocReporter(self.result,
self.state.memo.reporter) self.state.memo.reporter)
if self.name == 'automodule': if documenter.titles_allowed:
node = nodes.section() node = nodes.section()
# necessary so that the child nodes get the right source/line set # necessary so that the child nodes get the right source/line set
node.document = self.state.document node.document = self.state.document

View File

@@ -70,6 +70,8 @@ class MathDirective(Directive):
node['nowrap'] = 'nowrap' in self.options node['nowrap'] = 'nowrap' in self.options
node['docname'] = self.state.document.settings.env.docname node['docname'] = self.state.document.settings.env.docname
ret = [node] ret = [node]
node.line = self.lineno
node.source = self.src
if node['label']: if node['label']:
tnode = nodes.target('', '', ids=['equation-' + node['label']]) tnode = nodes.target('', '', ids=['equation-' + node['label']])
self.state.document.note_explicit_target(tnode) self.state.document.note_explicit_target(tnode)

View File

@@ -248,11 +248,11 @@
\newcommand{\py@heavybox}{ \newcommand{\py@heavybox}{
\setlength{\fboxrule}{1pt} \setlength{\fboxrule}{1pt}
\setlength{\fboxsep}{7pt} \setlength{\fboxsep}{6pt}
\setlength{\py@noticelength}{\linewidth} \setlength{\py@noticelength}{\linewidth}
\addtolength{\py@noticelength}{-2\fboxsep} \addtolength{\py@noticelength}{-2\fboxsep}
\addtolength{\py@noticelength}{-2\fboxrule} \addtolength{\py@noticelength}{-2\fboxrule}
\setlength{\shadowsize}{3pt} %\setlength{\shadowsize}{3pt}
\Sbox \Sbox
\minipage{\py@noticelength} \minipage{\py@noticelength}
} }
@@ -262,15 +262,26 @@
\fbox{\TheSbox} \fbox{\TheSbox}
} }
\newcommand{\py@lightbox}{{%
\setlength\parskip{0pt}\par
\rule[0ex]{\linewidth}{0.5pt}%
\par\vspace{-0.5ex}%
}}
\newcommand{\py@endlightbox}{{%
\setlength{\parskip}{0pt}%
\par\rule[0.5ex]{\linewidth}{0.5pt}%
\par\vspace{-0.5ex}%
}}
% Some are quite plain: % Some are quite plain:
\newcommand{\py@noticestart@note}{} \newcommand{\py@noticestart@note}{\py@lightbox}
\newcommand{\py@noticeend@note}{} \newcommand{\py@noticeend@note}{\py@endlightbox}
\newcommand{\py@noticestart@hint}{} \newcommand{\py@noticestart@hint}{\py@lightbox}
\newcommand{\py@noticeend@hint}{} \newcommand{\py@noticeend@hint}{\py@endlightbox}
\newcommand{\py@noticestart@important}{} \newcommand{\py@noticestart@important}{\py@lightbox}
\newcommand{\py@noticeend@important}{} \newcommand{\py@noticeend@important}{\py@endlightbox}
\newcommand{\py@noticestart@tip}{} \newcommand{\py@noticestart@tip}{\py@lightbox}
\newcommand{\py@noticeend@tip}{} \newcommand{\py@noticeend@tip}{\py@endlightbox}
% Others gets more visible distinction: % Others gets more visible distinction:
\newcommand{\py@noticestart@warning}{\py@heavybox} \newcommand{\py@noticestart@warning}{\py@heavybox}
@@ -287,7 +298,7 @@
\newenvironment{notice}[2]{ \newenvironment{notice}[2]{
\def\py@noticetype{#1} \def\py@noticetype{#1}
\csname py@noticestart@#1\endcsname \csname py@noticestart@#1\endcsname
\par\strong{#2} \strong{#2}
}{\csname py@noticeend@\py@noticetype\endcsname} }{\csname py@noticeend@\py@noticetype\endcsname}
% Allow the release number to be specified independently of the % Allow the release number to be specified independently of the

View File

@@ -114,9 +114,9 @@ class FilenameUniqDict(dict):
def purge_doc(self, docname): def purge_doc(self, docname):
for filename, (docs, _) in self.items(): for filename, (docs, _) in self.items():
docs.discard(docname) docs.discard(docname)
#if not docs: if not docs:
# del self[filename] del self[filename]
# self._existing.discard(filename) self._existing.discard(filename)
def __getstate__(self): def __getstate__(self):
return self._existing return self._existing

View File

@@ -24,6 +24,7 @@ def setup_module():
app = TestApp() app = TestApp()
app.builder.env.app = app app.builder.env.app = app
app.builder.env.temp_data['docname'] = 'dummy'
app.connect('autodoc-process-docstring', process_docstring) app.connect('autodoc-process-docstring', process_docstring)
app.connect('autodoc-process-signature', process_signature) app.connect('autodoc-process-signature', process_signature)
app.connect('autodoc-skip-member', skip_member) app.connect('autodoc-skip-member', skip_member)