mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
getargspec moved to sphinx.util.inspect
This commit is contained in:
commit
0964f4f993
10
CHANGES
10
CHANGES
@ -5,6 +5,10 @@ Release 1.1 (in development)
|
|||||||
|
|
||||||
* Added a Texinfo builder.
|
* Added a Texinfo builder.
|
||||||
|
|
||||||
|
* Incompatibility: The :rst:dir:`py:module` directive doesn't output
|
||||||
|
its ``platform`` option value anymore. (It was the only thing that
|
||||||
|
the directive did output, and therefore quite inconsistent.)
|
||||||
|
|
||||||
* Added i18n support for content, a ``gettext`` builder and
|
* Added i18n support for content, a ``gettext`` builder and
|
||||||
related utilities.
|
related utilities.
|
||||||
|
|
||||||
@ -85,6 +89,12 @@ Release 1.1 (in development)
|
|||||||
Release 1.0.7 (in development)
|
Release 1.0.7 (in development)
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
* #572: Show warnings by default when reference labels cannot be
|
||||||
|
found.
|
||||||
|
|
||||||
|
* #536: Include line number when complaining about missing reference
|
||||||
|
targets in nitpicky mode.
|
||||||
|
|
||||||
* #590: Fix inline display of graphviz diagrams in LaTeX output.
|
* #590: Fix inline display of graphviz diagrams in LaTeX output.
|
||||||
|
|
||||||
* #589: Build using app.build() in setup command.
|
* #589: Build using app.build() in setup command.
|
||||||
|
@ -8,8 +8,9 @@ PAPER =
|
|||||||
|
|
||||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||||
PAPEROPT_letter = -D latex_paper_size=letter
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \
|
ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \
|
||||||
$(SPHINXOPTS) $(O) .
|
$(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
|
||||||
@ -116,7 +117,7 @@ latexpdf:
|
|||||||
@echo "pdflatex finished; the PDF files are in _build/latex."
|
@echo "pdflatex finished; the PDF files are in _build/latex."
|
||||||
|
|
||||||
gettext:
|
gettext:
|
||||||
$(SPHINXBUILD) -b gettext $(ALLSPHINXOPTS) _build/locale
|
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) _build/locale
|
||||||
@echo
|
@echo
|
||||||
@echo "Build finished. The message catalogs are in _build/locale."
|
@echo "Build finished. The message catalogs are in _build/locale."
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ Note that a direct PDF builder using ReportLab is available in `rst2pdf
|
|||||||
|
|
||||||
.. versionadded:: 0.5
|
.. versionadded:: 0.5
|
||||||
|
|
||||||
.. module:: sphinx.builders.intl
|
.. module:: sphinx.builders.gettext
|
||||||
.. class:: MessageCatalogBuilder
|
.. class:: MessageCatalogBuilder
|
||||||
|
|
||||||
This builder produces gettext-style message catalos. Each top-level file or
|
This builder produces gettext-style message catalos. Each top-level file or
|
||||||
|
@ -32,7 +32,7 @@ task to split up paragraphs which are too large as there is no sane automated
|
|||||||
way to do that.
|
way to do that.
|
||||||
|
|
||||||
After Sphinx successfully ran the
|
After Sphinx successfully ran the
|
||||||
:class:`~sphinx.builders.intl.MessageCatalogBuilder` you will find a collection
|
:class:`~sphinx.builders.gettext.MessageCatalogBuilder` you will find a collection
|
||||||
of ``.pot`` files in your output directory. These are **catalog templates**
|
of ``.pot`` files in your output directory. These are **catalog templates**
|
||||||
and contain messages in your original language *only*.
|
and contain messages in your original language *only*.
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ These themes are:
|
|||||||
*nosidebar*.
|
*nosidebar*.
|
||||||
|
|
||||||
* **pyramid** -- A theme from the Pyramid web framework project, designed by
|
* **pyramid** -- A theme from the Pyramid web framework project, designed by
|
||||||
Blais Laflamme. THere are currently no options beyond *nosidebar*.
|
Blaise Laflamme. THere are currently no options beyond *nosidebar*.
|
||||||
|
|
||||||
* **haiku** -- A theme without sidebar inspired by the `Haiku OS user guide
|
* **haiku** -- A theme without sidebar inspired by the `Haiku OS user guide
|
||||||
<http://www.haiku-os.org/docs/userguide/en/contents.html>`_. The following
|
<http://www.haiku-os.org/docs/userguide/en/contents.html>`_. The following
|
||||||
|
@ -31,9 +31,12 @@ class Builder(object):
|
|||||||
name = ''
|
name = ''
|
||||||
# builder's output format, or '' if no document output is produced
|
# builder's output format, or '' if no document output is produced
|
||||||
format = ''
|
format = ''
|
||||||
|
# doctree versioning method
|
||||||
|
versioning_method = 'none'
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
self.env = app.env
|
self.env = app.env
|
||||||
|
self.env.set_versioning_method(self.versioning_method)
|
||||||
self.srcdir = app.srcdir
|
self.srcdir = app.srcdir
|
||||||
self.confdir = app.confdir
|
self.confdir = app.confdir
|
||||||
self.outdir = app.outdir
|
self.outdir = app.outdir
|
||||||
@ -330,5 +333,5 @@ BUILTIN_BUILDERS = {
|
|||||||
'changes': ('changes', 'ChangesBuilder'),
|
'changes': ('changes', 'ChangesBuilder'),
|
||||||
'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
|
'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
|
||||||
'websupport': ('websupport', 'WebSupportBuilder'),
|
'websupport': ('websupport', 'WebSupportBuilder'),
|
||||||
'gettext': ('intl', 'MessageCatalogBuilder'),
|
'gettext': ('gettext', 'MessageCatalogBuilder'),
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
sphinx.builders.intl
|
sphinx.builders.gettext
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The MessageCatalogBuilder class.
|
The MessageCatalogBuilder class.
|
||||||
|
|
||||||
@ -48,6 +48,7 @@ class I18nBuilder(Builder):
|
|||||||
General i18n builder.
|
General i18n builder.
|
||||||
"""
|
"""
|
||||||
name = 'i18n'
|
name = 'i18n'
|
||||||
|
versioning_method = 'text'
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
Builder.init(self)
|
Builder.init(self)
|
@ -26,6 +26,7 @@ class WebSupportBuilder(PickleHTMLBuilder):
|
|||||||
Builds documents for the web support package.
|
Builds documents for the web support package.
|
||||||
"""
|
"""
|
||||||
name = 'websupport'
|
name = 'websupport'
|
||||||
|
versioning_method = 'commentable'
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
PickleHTMLBuilder.init(self)
|
PickleHTMLBuilder.init(self)
|
||||||
|
@ -131,6 +131,8 @@ class Domain(object):
|
|||||||
roles = {}
|
roles = {}
|
||||||
#: a list of Index subclasses
|
#: a list of Index subclasses
|
||||||
indices = []
|
indices = []
|
||||||
|
#: role name -> a warning message if reference is missing
|
||||||
|
dangling_warnings = {}
|
||||||
|
|
||||||
#: data value for a fresh environment
|
#: data value for a fresh environment
|
||||||
initial_data = {}
|
initial_data = {}
|
||||||
|
@ -1090,13 +1090,15 @@ class CPPDomain(Domain):
|
|||||||
contnode, name)
|
contnode, name)
|
||||||
|
|
||||||
parser = DefinitionParser(target)
|
parser = DefinitionParser(target)
|
||||||
# XXX: warn?
|
|
||||||
try:
|
try:
|
||||||
expr = parser.parse_type().get_name()
|
expr = parser.parse_type().get_name()
|
||||||
parser.skip_ws()
|
parser.skip_ws()
|
||||||
if not parser.eof or expr is None:
|
if not parser.eof or expr is None:
|
||||||
return None
|
raise DefinitionError('')
|
||||||
except DefinitionError:
|
except DefinitionError:
|
||||||
|
refdoc = node.get('refdoc', fromdocname)
|
||||||
|
env.warn(refdoc, 'unparseable C++ definition: %r' % target,
|
||||||
|
node.line)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
parent = node['cpp:parent']
|
parent = node['cpp:parent']
|
||||||
|
@ -419,15 +419,8 @@ class PyModule(Directive):
|
|||||||
targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
|
targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
|
||||||
self.state.document.note_explicit_target(targetnode)
|
self.state.document.note_explicit_target(targetnode)
|
||||||
ret = [targetnode]
|
ret = [targetnode]
|
||||||
# XXX this behavior of the module directive is a mess...
|
# the platform and synopsis aren't printed; in fact, they are only used
|
||||||
if 'platform' in self.options:
|
# in the modindex currently
|
||||||
platform = self.options['platform']
|
|
||||||
node = nodes.paragraph()
|
|
||||||
node += nodes.emphasis('', _('Platforms: '))
|
|
||||||
node += nodes.Text(platform, platform)
|
|
||||||
ret.append(node)
|
|
||||||
# the synopsis isn't printed; in fact, it is only used in the
|
|
||||||
# modindex currently
|
|
||||||
if not noindex:
|
if not noindex:
|
||||||
indextext = _('%s (module)') % modname
|
indextext = _('%s (module)') % modname
|
||||||
inode = addnodes.index(entries=[('single', indextext,
|
inode = addnodes.index(entries=[('single', indextext,
|
||||||
|
@ -411,11 +411,13 @@ class StandardDomain(Domain):
|
|||||||
# links to tokens in grammar productions
|
# links to tokens in grammar productions
|
||||||
'token': XRefRole(),
|
'token': XRefRole(),
|
||||||
# links to terms in glossary
|
# links to terms in glossary
|
||||||
'term': XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
|
'term': XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
|
||||||
|
warn_dangling=True),
|
||||||
# links to headings or arbitrary labels
|
# links to headings or arbitrary labels
|
||||||
'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis),
|
'ref': XRefRole(lowercase=True, innernodeclass=nodes.emphasis,
|
||||||
|
warn_dangling=True),
|
||||||
# links to labels, without a different title
|
# links to labels, without a different title
|
||||||
'keyword': XRefRole(),
|
'keyword': XRefRole(warn_dangling=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
initial_data = {
|
initial_data = {
|
||||||
@ -433,6 +435,13 @@ class StandardDomain(Domain):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dangling_warnings = {
|
||||||
|
'term': 'term not in glossary: %(target)s',
|
||||||
|
'ref': 'undefined label: %(target)s (if the link has no caption '
|
||||||
|
'the label must precede a section header)',
|
||||||
|
'keyword': 'unknown keyword: %(target)s',
|
||||||
|
}
|
||||||
|
|
||||||
def clear_doc(self, docname):
|
def clear_doc(self, docname):
|
||||||
for key, (fn, _) in self.data['progoptions'].items():
|
for key, (fn, _) in self.data['progoptions'].items():
|
||||||
if fn == docname:
|
if fn == docname:
|
||||||
@ -490,27 +499,16 @@ class StandardDomain(Domain):
|
|||||||
def resolve_xref(self, env, fromdocname, builder,
|
def resolve_xref(self, env, fromdocname, builder,
|
||||||
typ, target, node, contnode):
|
typ, target, node, contnode):
|
||||||
if typ == 'ref':
|
if typ == 'ref':
|
||||||
#refdoc = node.get('refdoc', fromdocname)
|
|
||||||
if node['refexplicit']:
|
if node['refexplicit']:
|
||||||
# reference to anonymous label; the reference uses
|
# reference to anonymous label; the reference uses
|
||||||
# the supplied link caption
|
# the supplied link caption
|
||||||
docname, labelid = self.data['anonlabels'].get(target, ('',''))
|
docname, labelid = self.data['anonlabels'].get(target, ('',''))
|
||||||
sectname = node.astext()
|
sectname = node.astext()
|
||||||
# XXX warn somehow if not resolved by intersphinx
|
|
||||||
#if not docname:
|
|
||||||
# env.warn(refdoc, 'undefined label: %s' %
|
|
||||||
# target, node.line)
|
|
||||||
else:
|
else:
|
||||||
# reference to named label; the final node will
|
# reference to named label; the final node will
|
||||||
# contain the section name after the label
|
# contain the section name after the label
|
||||||
docname, labelid, sectname = self.data['labels'].get(target,
|
docname, labelid, sectname = self.data['labels'].get(target,
|
||||||
('','',''))
|
('','',''))
|
||||||
# XXX warn somehow if not resolved by intersphinx
|
|
||||||
#if not docname:
|
|
||||||
# env.warn(refdoc,
|
|
||||||
# 'undefined label: %s' % target + ' -- if you '
|
|
||||||
# 'don\'t give a link caption the label must '
|
|
||||||
# 'precede a section header.', node.line)
|
|
||||||
if not docname:
|
if not docname:
|
||||||
return None
|
return None
|
||||||
newnode = nodes.reference('', '', internal=True)
|
newnode = nodes.reference('', '', internal=True)
|
||||||
@ -534,20 +532,17 @@ class StandardDomain(Domain):
|
|||||||
# keywords are oddballs: they are referenced by named labels
|
# keywords are oddballs: they are referenced by named labels
|
||||||
docname, labelid, _ = self.data['labels'].get(target, ('','',''))
|
docname, labelid, _ = self.data['labels'].get(target, ('','',''))
|
||||||
if not docname:
|
if not docname:
|
||||||
#env.warn(refdoc, 'unknown keyword: %s' % target)
|
|
||||||
return None
|
return None
|
||||||
else:
|
return make_refnode(builder, fromdocname, docname,
|
||||||
return make_refnode(builder, fromdocname, docname,
|
labelid, contnode)
|
||||||
labelid, contnode)
|
|
||||||
elif typ == 'option':
|
elif typ == 'option':
|
||||||
progname = node['refprogram']
|
progname = node['refprogram']
|
||||||
docname, labelid = self.data['progoptions'].get((progname, target),
|
docname, labelid = self.data['progoptions'].get((progname, target),
|
||||||
('', ''))
|
('', ''))
|
||||||
if not docname:
|
if not docname:
|
||||||
return None
|
return None
|
||||||
else:
|
return make_refnode(builder, fromdocname, docname,
|
||||||
return make_refnode(builder, fromdocname, docname,
|
labelid, contnode)
|
||||||
labelid, contnode)
|
|
||||||
else:
|
else:
|
||||||
objtypes = self.objtypes_for_role(typ) or []
|
objtypes = self.objtypes_for_role(typ) or []
|
||||||
for objtype in objtypes:
|
for objtype in objtypes:
|
||||||
@ -557,13 +552,9 @@ class StandardDomain(Domain):
|
|||||||
else:
|
else:
|
||||||
docname, labelid = '', ''
|
docname, labelid = '', ''
|
||||||
if not docname:
|
if not docname:
|
||||||
if typ == 'term':
|
|
||||||
env.warn(node.get('refdoc', fromdocname),
|
|
||||||
'term not in glossary: %s' % target, node.line)
|
|
||||||
return None
|
return None
|
||||||
else:
|
return make_refnode(builder, fromdocname, docname,
|
||||||
return make_refnode(builder, fromdocname, docname,
|
labelid, contnode)
|
||||||
labelid, contnode)
|
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
for (prog, option), info in self.data['progoptions'].iteritems():
|
for (prog, option), info in self.data['progoptions'].iteritems():
|
||||||
|
@ -43,6 +43,7 @@ from sphinx.util.nodes import clean_astext, make_refnode, extract_messages
|
|||||||
from sphinx.util.osutil import movefile, SEP, ustrftime
|
from sphinx.util.osutil import movefile, SEP, ustrftime
|
||||||
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 all, class_types
|
||||||
|
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 _, init as init_locale
|
||||||
from sphinx.versioning import add_uids, merge_doctrees
|
from sphinx.versioning import add_uids, merge_doctrees
|
||||||
@ -68,7 +69,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 = 39
|
ENV_VERSION = 40
|
||||||
|
|
||||||
|
|
||||||
default_substitutions = set([
|
default_substitutions = set([
|
||||||
@ -79,6 +80,12 @@ default_substitutions = set([
|
|||||||
|
|
||||||
dummy_reporter = Reporter('', 4, 4)
|
dummy_reporter = Reporter('', 4, 4)
|
||||||
|
|
||||||
|
versioning_conditions = {
|
||||||
|
'none': False,
|
||||||
|
'text': nodes.TextElement,
|
||||||
|
'commentable': is_commentable,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class WarningStream(object):
|
class WarningStream(object):
|
||||||
def __init__(self, warnfunc):
|
def __init__(self, warnfunc):
|
||||||
@ -182,7 +189,8 @@ class CitationReferences(Transform):
|
|||||||
for citnode in self.document.traverse(nodes.citation_reference):
|
for citnode in self.document.traverse(nodes.citation_reference):
|
||||||
cittext = citnode.astext()
|
cittext = citnode.astext()
|
||||||
refnode = addnodes.pending_xref(cittext, reftype='citation',
|
refnode = addnodes.pending_xref(cittext, reftype='citation',
|
||||||
reftarget=cittext)
|
reftarget=cittext, refwarn=True)
|
||||||
|
refnode.line = citnode.line or citnode.parent.line
|
||||||
refnode += nodes.Text('[' + cittext + ']')
|
refnode += nodes.Text('[' + cittext + ']')
|
||||||
citnode.parent.replace(citnode, refnode)
|
citnode.parent.replace(citnode, refnode)
|
||||||
|
|
||||||
@ -313,6 +321,9 @@ class BuildEnvironment:
|
|||||||
self.srcdir = srcdir
|
self.srcdir = srcdir
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
|
# the method of doctree versioning; see set_versioning_method
|
||||||
|
self.versioning_condition = None
|
||||||
|
|
||||||
# the application object; only set while update() runs
|
# the application object; only set while update() runs
|
||||||
self.app = None
|
self.app = None
|
||||||
|
|
||||||
@ -380,6 +391,23 @@ class BuildEnvironment:
|
|||||||
self._warnfunc = func
|
self._warnfunc = func
|
||||||
self.settings['warning_stream'] = WarningStream(func)
|
self.settings['warning_stream'] = WarningStream(func)
|
||||||
|
|
||||||
|
def set_versioning_method(self, method):
|
||||||
|
"""This sets the doctree versioning method for this environment.
|
||||||
|
|
||||||
|
Versioning methods are a builder property; only builders with the same
|
||||||
|
versioning method can share the same doctree directory. Therefore, we
|
||||||
|
raise an exception if the user tries to use an environment with an
|
||||||
|
incompatible versioning method.
|
||||||
|
"""
|
||||||
|
if method not in versioning_conditions:
|
||||||
|
raise ValueError('invalid versioning method: %r' % method)
|
||||||
|
condition = versioning_conditions[method]
|
||||||
|
if self.versioning_condition not in (None, condition):
|
||||||
|
raise SphinxError('This environment is incompatible with the '
|
||||||
|
'selected builder, please choose another '
|
||||||
|
'doctree directory.')
|
||||||
|
self.versioning_condition = condition
|
||||||
|
|
||||||
def warn(self, docname, msg, lineno=None):
|
def warn(self, docname, msg, lineno=None):
|
||||||
# strange argument order is due to backwards compatibility
|
# strange argument order is due to backwards compatibility
|
||||||
self._warnfunc(msg, (docname, lineno))
|
self._warnfunc(msg, (docname, lineno))
|
||||||
@ -754,25 +782,24 @@ class BuildEnvironment:
|
|||||||
# store time of build, for outdated files detection
|
# store time of build, for outdated files detection
|
||||||
self.all_docs[docname] = time.time()
|
self.all_docs[docname] = time.time()
|
||||||
|
|
||||||
# get old doctree
|
if self.versioning_condition:
|
||||||
old_doctree_path = self.doc2path(docname, self.doctreedir, '.doctree')
|
# get old doctree
|
||||||
try:
|
|
||||||
f = open(old_doctree_path, 'rb')
|
|
||||||
try:
|
try:
|
||||||
old_doctree = pickle.load(f)
|
f = open(self.doc2path(docname,
|
||||||
finally:
|
self.doctreedir, '.doctree'), 'rb')
|
||||||
f.close()
|
try:
|
||||||
old_doctree.settings.env = self
|
old_doctree = pickle.load(f)
|
||||||
old_doctree.reporter = Reporter(self.doc2path(docname), 2, 5,
|
finally:
|
||||||
stream=WarningStream(self._warnfunc))
|
f.close()
|
||||||
except EnvironmentError:
|
except EnvironmentError:
|
||||||
old_doctree = None
|
old_doctree = None
|
||||||
|
|
||||||
# add uids for versioning
|
# add uids for versioning
|
||||||
if old_doctree is None:
|
if old_doctree is None:
|
||||||
list(add_uids(doctree, nodes.TextElement))
|
list(add_uids(doctree, self.versioning_condition))
|
||||||
else:
|
else:
|
||||||
list(merge_doctrees(old_doctree, doctree, nodes.TextElement))
|
list(merge_doctrees(
|
||||||
|
old_doctree, doctree, self.versioning_condition))
|
||||||
|
|
||||||
# make it picklable
|
# make it picklable
|
||||||
doctree.reporter = None
|
doctree.reporter = None
|
||||||
@ -1385,10 +1412,10 @@ class BuildEnvironment:
|
|||||||
typ = node['reftype']
|
typ = node['reftype']
|
||||||
target = node['reftarget']
|
target = node['reftarget']
|
||||||
refdoc = node.get('refdoc', fromdocname)
|
refdoc = node.get('refdoc', fromdocname)
|
||||||
warned = False
|
domain = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if node.has_key('refdomain') and node['refdomain']:
|
if 'refdomain' in node and node['refdomain']:
|
||||||
# let the domain try to resolve the reference
|
# let the domain try to resolve the reference
|
||||||
try:
|
try:
|
||||||
domain = self.domains[node['refdomain']]
|
domain = self.domains[node['refdomain']]
|
||||||
@ -1401,11 +1428,7 @@ class BuildEnvironment:
|
|||||||
# directly reference to document by source name;
|
# directly reference to document by source name;
|
||||||
# can be absolute or relative
|
# can be absolute or relative
|
||||||
docname = docname_join(refdoc, target)
|
docname = docname_join(refdoc, target)
|
||||||
if docname not in self.all_docs:
|
if docname in self.all_docs:
|
||||||
self.warn(refdoc,
|
|
||||||
'unknown document: %s' % docname, node.line)
|
|
||||||
warned = True
|
|
||||||
else:
|
|
||||||
if node['refexplicit']:
|
if node['refexplicit']:
|
||||||
# reference with explicit title
|
# reference with explicit title
|
||||||
caption = node.astext()
|
caption = node.astext()
|
||||||
@ -1418,11 +1441,7 @@ class BuildEnvironment:
|
|||||||
newnode.append(innernode)
|
newnode.append(innernode)
|
||||||
elif typ == 'citation':
|
elif typ == 'citation':
|
||||||
docname, labelid = self.citations.get(target, ('', ''))
|
docname, labelid = self.citations.get(target, ('', ''))
|
||||||
if not docname:
|
if docname:
|
||||||
self.warn(refdoc,
|
|
||||||
'citation not found: %s' % target, node.line)
|
|
||||||
warned = True
|
|
||||||
else:
|
|
||||||
newnode = make_refnode(builder, fromdocname, docname,
|
newnode = make_refnode(builder, fromdocname, docname,
|
||||||
labelid, contnode)
|
labelid, contnode)
|
||||||
# no new node found? try the missing-reference event
|
# no new node found? try the missing-reference event
|
||||||
@ -1430,16 +1449,40 @@ class BuildEnvironment:
|
|||||||
newnode = builder.app.emit_firstresult(
|
newnode = builder.app.emit_firstresult(
|
||||||
'missing-reference', self, node, contnode)
|
'missing-reference', self, node, contnode)
|
||||||
# still not found? warn if in nit-picky mode
|
# still not found? warn if in nit-picky mode
|
||||||
if newnode is None and not warned and self.config.nitpicky:
|
if newnode is None:
|
||||||
self.warn(refdoc,
|
self._warn_missing_reference(
|
||||||
'reference target not found: %stype %s, target %s'
|
fromdocname, typ, target, node, domain)
|
||||||
% (node.get('refdomain') and
|
|
||||||
'domain %s, ' % node['refdomain'] or '',
|
|
||||||
typ, target))
|
|
||||||
except NoUri:
|
except NoUri:
|
||||||
newnode = contnode
|
newnode = contnode
|
||||||
node.replace_self(newnode or contnode)
|
node.replace_self(newnode or contnode)
|
||||||
|
|
||||||
|
# remove only-nodes that do not belong to our builder
|
||||||
|
self.process_only_nodes(doctree, fromdocname, builder)
|
||||||
|
|
||||||
|
# allow custom references to be resolved
|
||||||
|
builder.app.emit('doctree-resolved', doctree, fromdocname)
|
||||||
|
|
||||||
|
def _warn_missing_reference(self, fromdoc, typ, target, node, domain):
|
||||||
|
warn = node.get('refwarn')
|
||||||
|
if self.config.nitpicky:
|
||||||
|
warn = True # XXX process exceptions here
|
||||||
|
if not warn:
|
||||||
|
return
|
||||||
|
refdoc = node.get('refdoc', fromdoc)
|
||||||
|
if domain and typ in domain.dangling_warnings:
|
||||||
|
msg = domain.dangling_warnings[typ]
|
||||||
|
elif typ == 'doc':
|
||||||
|
msg = 'unknown document: %(target)s'
|
||||||
|
elif typ == 'citation':
|
||||||
|
msg = 'citation not found: %(target)s'
|
||||||
|
elif node.get('refdomain', 'std') != 'std':
|
||||||
|
msg = '%s:%s reference target not found: %%(target)s' % \
|
||||||
|
(node['refdomain'], typ)
|
||||||
|
else:
|
||||||
|
msg = '%s reference target not found: %%(target)s' % typ
|
||||||
|
self.warn(refdoc, msg % {'target': target}, node.line)
|
||||||
|
|
||||||
|
def process_only_nodes(self, doctree, fromdocname, builder):
|
||||||
for node in doctree.traverse(addnodes.only):
|
for node in doctree.traverse(addnodes.only):
|
||||||
try:
|
try:
|
||||||
ret = builder.tags.eval_condition(node['expr'])
|
ret = builder.tags.eval_condition(node['expr'])
|
||||||
@ -1455,9 +1498,6 @@ class BuildEnvironment:
|
|||||||
# if there is a target node before the only node
|
# if there is a target node before the only node
|
||||||
node.replace_self(nodes.comment())
|
node.replace_self(nodes.comment())
|
||||||
|
|
||||||
# allow custom references to be resolved
|
|
||||||
builder.app.emit('doctree-resolved', doctree, fromdocname)
|
|
||||||
|
|
||||||
def assign_section_numbers(self):
|
def assign_section_numbers(self):
|
||||||
"""Assign a section number to each heading under a numbered toctree."""
|
"""Assign a section number to each heading under a numbered toctree."""
|
||||||
# a list of all docnames whose section numbers changed
|
# a list of all docnames whose section numbers changed
|
||||||
|
@ -27,7 +27,8 @@ from sphinx.pycode import ModuleAnalyzer, PycodeError
|
|||||||
from sphinx.application import ExtensionError
|
from sphinx.application import ExtensionError
|
||||||
from sphinx.util.nodes import nested_parse_with_titles
|
from sphinx.util.nodes import nested_parse_with_titles
|
||||||
from sphinx.util.compat import Directive
|
from sphinx.util.compat import Directive
|
||||||
from sphinx.util.inspect import isdescriptor, safe_getmembers, safe_getattr
|
from sphinx.util.inspect import (getargspec, isdescriptor, safe_getmembers, \
|
||||||
|
safe_getattr)
|
||||||
from sphinx.util.pycompat import base_exception, class_types
|
from sphinx.util.pycompat import base_exception, class_types
|
||||||
from sphinx.util.docstrings import prepare_docstring
|
from sphinx.util.docstrings import prepare_docstring
|
||||||
|
|
||||||
@ -1284,36 +1285,6 @@ def add_documenter(cls):
|
|||||||
AutoDirective._registry[cls.objtype] = cls
|
AutoDirective._registry[cls.objtype] = cls
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info >= (2, 5):
|
|
||||||
from functools import partial
|
|
||||||
def getargspec(func):
|
|
||||||
"""Like inspect.getargspec but supports functools.partial as well."""
|
|
||||||
if inspect.ismethod(func):
|
|
||||||
func = func.im_func
|
|
||||||
parts = 0, ()
|
|
||||||
if type(func) is partial:
|
|
||||||
parts = len(func.args), func.keywords.keys()
|
|
||||||
func = func.func
|
|
||||||
if not inspect.isfunction(func):
|
|
||||||
raise TypeError('{!r} is not a Python function'.format(func))
|
|
||||||
args, varargs, varkw = inspect.getargs(func.func_code)
|
|
||||||
func_defaults = func.func_defaults
|
|
||||||
if func_defaults:
|
|
||||||
func_defaults = list(func_defaults)
|
|
||||||
if parts[0]:
|
|
||||||
args = args[parts[0]:]
|
|
||||||
if parts[1]:
|
|
||||||
for arg in parts[1]:
|
|
||||||
i = args.index(arg) - len(args)
|
|
||||||
del args[i]
|
|
||||||
try:
|
|
||||||
del func_defaults[i]
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
return inspect.ArgSpec(args, varargs, varkw, func_defaults)
|
|
||||||
else:
|
|
||||||
getargspec = inspect.getargspec
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
app.add_autodocumenter(ModuleDocumenter)
|
app.add_autodocumenter(ModuleDocumenter)
|
||||||
app.add_autodocumenter(ClassDocumenter)
|
app.add_autodocumenter(ClassDocumenter)
|
||||||
|
@ -361,6 +361,8 @@ PAPEROPT_a4 = -D latex_paper_size=a4
|
|||||||
PAPEROPT_letter = -D latex_paper_size=letter
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) \
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) \
|
||||||
$(SPHINXOPTS) %(rsrcdir)s
|
$(SPHINXOPTS) %(rsrcdir)s
|
||||||
|
# the i18n builder cannot share the environment and doctrees with the others
|
||||||
|
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) %(rsrcdir)s
|
||||||
|
|
||||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp \
|
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp \
|
||||||
epub latex latexpdf text man changes linkcheck doctest gettext
|
epub latex latexpdf text man changes linkcheck doctest gettext
|
||||||
@ -483,7 +485,7 @@ info:
|
|||||||
\t@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
\t@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||||
|
|
||||||
gettext:
|
gettext:
|
||||||
\t$(SPHINXBUILD) -b gettext $(ALLSPHINXOPTS) $(BUILDDIR)/locale
|
\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||||
\t@echo
|
\t@echo
|
||||||
\t@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
\t@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||||
|
|
||||||
@ -514,8 +516,10 @@ if "%%SPHINXBUILD%%" == "" (
|
|||||||
)
|
)
|
||||||
set BUILDDIR=%(rbuilddir)s
|
set BUILDDIR=%(rbuilddir)s
|
||||||
set ALLSPHINXOPTS=-d %%BUILDDIR%%/doctrees %%SPHINXOPTS%% %(rsrcdir)s
|
set ALLSPHINXOPTS=-d %%BUILDDIR%%/doctrees %%SPHINXOPTS%% %(rsrcdir)s
|
||||||
|
set I18NSPHINXOPTS=%%SPHINXOPTS%% %(rsrcdir)s
|
||||||
if NOT "%%PAPER%%" == "" (
|
if NOT "%%PAPER%%" == "" (
|
||||||
\tset ALLSPHINXOPTS=-D latex_paper_size=%%PAPER%% %%ALLSPHINXOPTS%%
|
\tset ALLSPHINXOPTS=-D latex_paper_size=%%PAPER%% %%ALLSPHINXOPTS%%
|
||||||
|
\tset I18NSPHINXOPTS=-D latex_paper_size=%%PAPER%% %%I18NSPHINXOPTS%%
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%%1" == "" goto help
|
if "%%1" == "" goto help
|
||||||
@ -659,7 +663,7 @@ if "%%1" == "texinfo" (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if "%%1" == "gettext" (
|
if "%%1" == "gettext" (
|
||||||
\t%%SPHINXBUILD%% -b gettext %%ALLSPHINXOPTS%% %%BUILDDIR%%/locale
|
\t%%SPHINXBUILD%% -b gettext %%I18NSPHINXOPTS%% %%BUILDDIR%%/locale
|
||||||
\tif errorlevel 1 exit /b 1
|
\tif errorlevel 1 exit /b 1
|
||||||
\techo.
|
\techo.
|
||||||
\techo.Build finished. The message catalogs are in %%BUILDDIR%%/locale.
|
\techo.Build finished. The message catalogs are in %%BUILDDIR%%/locale.
|
||||||
@ -991,4 +995,3 @@ def main(argv=sys.argv):
|
|||||||
print
|
print
|
||||||
print '[Interrupted.]'
|
print '[Interrupted.]'
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -69,9 +69,10 @@ class XRefRole(object):
|
|||||||
innernodeclass = nodes.literal
|
innernodeclass = nodes.literal
|
||||||
|
|
||||||
def __init__(self, fix_parens=False, lowercase=False,
|
def __init__(self, fix_parens=False, lowercase=False,
|
||||||
nodeclass=None, innernodeclass=None):
|
nodeclass=None, innernodeclass=None, warn_dangling=False):
|
||||||
self.fix_parens = fix_parens
|
self.fix_parens = fix_parens
|
||||||
self.lowercase = lowercase
|
self.lowercase = lowercase
|
||||||
|
self.warn_dangling = warn_dangling
|
||||||
if nodeclass is not None:
|
if nodeclass is not None:
|
||||||
self.nodeclass = nodeclass
|
self.nodeclass = nodeclass
|
||||||
if innernodeclass is not None:
|
if innernodeclass is not None:
|
||||||
@ -133,6 +134,7 @@ class XRefRole(object):
|
|||||||
refnode += self.innernodeclass(rawtext, title, classes=classes)
|
refnode += self.innernodeclass(rawtext, title, classes=classes)
|
||||||
# we also need the source document
|
# we also need the source document
|
||||||
refnode['refdoc'] = env.docname
|
refnode['refdoc'] = env.docname
|
||||||
|
refnode['refwarn'] = self.warn_dangling
|
||||||
# result_nodes allow further modification of return values
|
# result_nodes allow further modification of return values
|
||||||
return self.result_nodes(inliner.document, env, refnode, is_ref=True)
|
return self.result_nodes(inliner.document, env, refnode, is_ref=True)
|
||||||
|
|
||||||
@ -298,7 +300,7 @@ specific_docroles = {
|
|||||||
# links to download references
|
# links to download references
|
||||||
'download': XRefRole(nodeclass=addnodes.download_reference),
|
'download': XRefRole(nodeclass=addnodes.download_reference),
|
||||||
# links to documents
|
# links to documents
|
||||||
'doc': XRefRole(),
|
'doc': XRefRole(warn_dangling=True),
|
||||||
|
|
||||||
'pep': indexmarkup_role,
|
'pep': indexmarkup_role,
|
||||||
'rfc': indexmarkup_role,
|
'rfc': indexmarkup_role,
|
||||||
|
@ -9,6 +9,40 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
inspect = __import__('inspect')
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if sys.version_info >= (2, 5):
|
||||||
|
from functools import partial
|
||||||
|
def getargspec(func):
|
||||||
|
"""Like inspect.getargspec but supports functools.partial as well."""
|
||||||
|
if inspect.ismethod(func):
|
||||||
|
func = func.im_func
|
||||||
|
parts = 0, ()
|
||||||
|
if type(func) is partial:
|
||||||
|
parts = len(func.args), func.keywords.keys()
|
||||||
|
func = func.func
|
||||||
|
if not inspect.isfunction(func):
|
||||||
|
raise TypeError('%r is not a Python function' % func)
|
||||||
|
args, varargs, varkw = inspect.getargs(func.func_code)
|
||||||
|
func_defaults = func.func_defaults
|
||||||
|
if func_defaults:
|
||||||
|
func_defaults = list(func_defaults)
|
||||||
|
if parts[0]:
|
||||||
|
args = args[parts[0]:]
|
||||||
|
if parts[1]:
|
||||||
|
for arg in parts[1]:
|
||||||
|
i = args.index(arg) - len(args)
|
||||||
|
del args[i]
|
||||||
|
try:
|
||||||
|
del func_defaults[i]
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
return inspect.ArgSpec(args, varargs, varkw, func_defaults)
|
||||||
|
else:
|
||||||
|
getargspec = inspect.getargspec
|
||||||
|
|
||||||
|
|
||||||
def isdescriptor(x):
|
def isdescriptor(x):
|
||||||
"""Check if the object is some kind of descriptor."""
|
"""Check if the object is some kind of descriptor."""
|
||||||
for item in '__get__', '__set__', '__delete__':
|
for item in '__get__', '__set__', '__delete__':
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
"""
|
"""
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
from sphinx.util.pycompat import product, zip_longest
|
from sphinx.util.pycompat import product, zip_longest
|
||||||
|
|
||||||
@ -49,7 +48,7 @@ def merge_doctrees(old, new, condition):
|
|||||||
new_iter = new.traverse(condition)
|
new_iter = new.traverse(condition)
|
||||||
old_nodes = []
|
old_nodes = []
|
||||||
new_nodes = []
|
new_nodes = []
|
||||||
ratios = defaultdict(list)
|
ratios = {}
|
||||||
seen = set()
|
seen = set()
|
||||||
# compare the nodes each doctree in order
|
# compare the nodes each doctree in order
|
||||||
for old_node, new_node in zip_longest(old_iter, new_iter):
|
for old_node, new_node in zip_longest(old_iter, new_iter):
|
||||||
|
Loading…
Reference in New Issue
Block a user