mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add SphinxDirective as a helper
This commit is contained in:
@@ -16,6 +16,7 @@ from docutils.parsers.rst import Directive, directives, roles
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.util.docfields import DocFieldTransformer
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
|
||||
# import all directives sphinx provides
|
||||
from sphinx.directives.code import ( # noqa
|
||||
@@ -33,6 +34,7 @@ if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
|
||||
|
||||
@@ -41,7 +43,7 @@ nl_escape_re = re.compile(r'\\\n')
|
||||
strip_backslash_re = re.compile(r'\\(.)')
|
||||
|
||||
|
||||
class ObjectDescription(Directive):
|
||||
class ObjectDescription(SphinxDirective):
|
||||
"""
|
||||
Directive to describe a class, function or similar object. Not used
|
||||
directly, but subclassed (in domain-specific directives) to add custom
|
||||
@@ -135,7 +137,6 @@ class ObjectDescription(Directive):
|
||||
self.domain, self.objtype = self.name.split(':', 1)
|
||||
else:
|
||||
self.domain, self.objtype = '', self.name
|
||||
self.env = self.state.document.settings.env # type: BuildEnvironment
|
||||
self.indexnode = addnodes.index(entries=[])
|
||||
|
||||
node = addnodes.desc()
|
||||
@@ -187,7 +188,7 @@ class ObjectDescription(Directive):
|
||||
DescDirective = ObjectDescription
|
||||
|
||||
|
||||
class DefaultRole(Directive):
|
||||
class DefaultRole(SphinxDirective):
|
||||
"""
|
||||
Set the default interpreted text role. Overridden from docutils.
|
||||
"""
|
||||
@@ -212,7 +213,7 @@ class DefaultRole(Directive):
|
||||
line=self.lineno)
|
||||
return messages + [error]
|
||||
roles._roles[''] = role
|
||||
self.state.document.settings.env.temp_data['default_role'] = role_name
|
||||
self.env.temp_data['default_role'] = role_name
|
||||
return messages
|
||||
|
||||
|
||||
@@ -229,7 +230,6 @@ class DefaultDomain(Directive):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
domain_name = self.arguments[0].lower()
|
||||
# if domain_name not in env.domains:
|
||||
# # try searching by label
|
||||
@@ -237,7 +237,7 @@ class DefaultDomain(Directive):
|
||||
# if domain.label.lower() == domain_name:
|
||||
# domain_name = domain.name
|
||||
# break
|
||||
env.temp_data['default_domain'] = env.domains.get(domain_name)
|
||||
self.env.temp_data['default_domain'] = self.env.domains.get(domain_name)
|
||||
return []
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import sys
|
||||
from difflib import unified_diff
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.statemachine import ViewList
|
||||
from six import text_type
|
||||
|
||||
@@ -20,6 +20,7 @@ from sphinx import addnodes
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util import parselinenos
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.nodes import set_source_info
|
||||
|
||||
if False:
|
||||
@@ -31,7 +32,7 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Highlight(Directive):
|
||||
class Highlight(SphinxDirective):
|
||||
"""
|
||||
Directive to set the highlighting language for code blocks, as well
|
||||
as the threshold for line numbers.
|
||||
@@ -77,7 +78,7 @@ def dedent_lines(lines, dedent, location=None):
|
||||
|
||||
|
||||
def container_wrapper(directive, literal_node, caption):
|
||||
# type: (Directive, nodes.Node, unicode) -> nodes.container
|
||||
# type: (SphinxDirective, nodes.Node, unicode) -> nodes.container
|
||||
container_node = nodes.container('', literal_block=True,
|
||||
classes=['literal-block-wrapper'])
|
||||
parsed = nodes.Element()
|
||||
@@ -95,7 +96,7 @@ def container_wrapper(directive, literal_node, caption):
|
||||
return container_node
|
||||
|
||||
|
||||
class CodeBlock(Directive):
|
||||
class CodeBlock(SphinxDirective):
|
||||
"""
|
||||
Directive for a code block with special highlighting or line numbering
|
||||
settings.
|
||||
@@ -372,7 +373,7 @@ class LiteralIncludeReader(object):
|
||||
return lines
|
||||
|
||||
|
||||
class LiteralInclude(Directive):
|
||||
class LiteralInclude(SphinxDirective):
|
||||
"""
|
||||
Like ``.. include:: :literal:``, but only warns if the include file is
|
||||
not found, and does not raise errors. Also has several options for
|
||||
@@ -412,19 +413,17 @@ class LiteralInclude(Directive):
|
||||
if not document.settings.file_insertion_enabled:
|
||||
return [document.reporter.warning('File insertion disabled',
|
||||
line=self.lineno)]
|
||||
env = document.settings.env
|
||||
|
||||
# convert options['diff'] to absolute path
|
||||
if 'diff' in self.options:
|
||||
_, path = env.relfn2path(self.options['diff'])
|
||||
_, path = self.env.relfn2path(self.options['diff'])
|
||||
self.options['diff'] = path
|
||||
|
||||
try:
|
||||
location = self.state_machine.get_source_and_line(self.lineno)
|
||||
rel_filename, filename = env.relfn2path(self.arguments[0])
|
||||
env.note_dependency(rel_filename)
|
||||
rel_filename, filename = self.env.relfn2path(self.arguments[0])
|
||||
self.env.note_dependency(rel_filename)
|
||||
|
||||
reader = LiteralIncludeReader(filename, self.options, env.config)
|
||||
reader = LiteralIncludeReader(filename, self.options, self.config)
|
||||
text, lines = reader.read(location=location)
|
||||
|
||||
retnode = nodes.literal_block(text, text, source=filename)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
|
||||
from docutils.parsers.rst.directives.misc import Class
|
||||
from docutils.parsers.rst.directives.misc import Include as BaseInclude
|
||||
@@ -18,6 +18,7 @@ from sphinx import addnodes, locale
|
||||
from sphinx.deprecation import DeprecatedDict, RemovedInSphinx30Warning
|
||||
from sphinx.locale import _
|
||||
from sphinx.util import url_re, docname_join
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.matching import patfilter
|
||||
from sphinx.util.nodes import explicit_title_re, set_source_info, \
|
||||
process_index_entry
|
||||
@@ -49,7 +50,7 @@ def int_or_nothing(argument):
|
||||
return int(argument)
|
||||
|
||||
|
||||
class TocTree(Directive):
|
||||
class TocTree(SphinxDirective):
|
||||
"""
|
||||
Directive to notify Sphinx about the hierarchical structure of the docs,
|
||||
and to include a table-of-contents like tree in the current document.
|
||||
@@ -72,8 +73,7 @@ class TocTree(Directive):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
suffixes = env.config.source_suffix
|
||||
suffixes = self.config.source_suffix
|
||||
glob = 'glob' in self.options
|
||||
|
||||
ret = []
|
||||
@@ -81,17 +81,17 @@ class TocTree(Directive):
|
||||
# and title may be None if the document's title is to be used
|
||||
entries = [] # type: List[Tuple[unicode, unicode]]
|
||||
includefiles = []
|
||||
all_docnames = env.found_docs.copy()
|
||||
all_docnames = self.env.found_docs.copy()
|
||||
# don't add the currently visited file in catch-all patterns
|
||||
all_docnames.remove(env.docname)
|
||||
all_docnames.remove(self.env.docname)
|
||||
for entry in self.content:
|
||||
if not entry:
|
||||
continue
|
||||
# look for explicit titles ("Some Title <document>")
|
||||
explicit = explicit_title_re.match(entry)
|
||||
if glob and ('*' in entry or '?' in entry or '[' in entry) and not explicit:
|
||||
patname = docname_join(env.docname, entry)
|
||||
docnames = sorted(patfilter(all_docnames, patname))
|
||||
patname = docname_join(self.env.docname, entry)
|
||||
docnames = sorted(patfilter(all_docnames, patname)) # type: ignore
|
||||
for docname in docnames:
|
||||
all_docnames.remove(docname) # don't include it again
|
||||
entries.append((None, docname))
|
||||
@@ -114,20 +114,20 @@ class TocTree(Directive):
|
||||
docname = docname[:-len(suffix)]
|
||||
break
|
||||
# absolutize filenames
|
||||
docname = docname_join(env.docname, docname)
|
||||
docname = docname_join(self.env.docname, docname)
|
||||
if url_re.match(ref) or ref == 'self':
|
||||
entries.append((title, ref))
|
||||
elif docname not in env.found_docs:
|
||||
elif docname not in self.env.found_docs:
|
||||
ret.append(self.state.document.reporter.warning(
|
||||
'toctree contains reference to nonexisting '
|
||||
'document %r' % docname, line=self.lineno))
|
||||
env.note_reread()
|
||||
self.env.note_reread()
|
||||
else:
|
||||
all_docnames.discard(docname)
|
||||
entries.append((title, docname))
|
||||
includefiles.append(docname)
|
||||
subnode = addnodes.toctree()
|
||||
subnode['parent'] = env.docname
|
||||
subnode['parent'] = self.env.docname
|
||||
# entries contains all entries (self references, external links etc.)
|
||||
if 'reversed' in self.options:
|
||||
entries.reverse()
|
||||
@@ -149,7 +149,7 @@ class TocTree(Directive):
|
||||
return ret
|
||||
|
||||
|
||||
class Author(Directive):
|
||||
class Author(SphinxDirective):
|
||||
"""
|
||||
Directive to give the name of the author of the current document
|
||||
or section. Shown in the output only if the show_authors option is on.
|
||||
@@ -162,8 +162,7 @@ class Author(Directive):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
if not env.config.show_authors:
|
||||
if not self.config.show_authors:
|
||||
return []
|
||||
para = nodes.paragraph(translatable=False)
|
||||
emph = nodes.emphasis()
|
||||
@@ -183,7 +182,7 @@ class Author(Directive):
|
||||
return [para] + messages
|
||||
|
||||
|
||||
class Index(Directive):
|
||||
class Index(SphinxDirective):
|
||||
"""
|
||||
Directive to add entries to the index.
|
||||
"""
|
||||
@@ -196,8 +195,7 @@ class Index(Directive):
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
arguments = self.arguments[0].split('\n')
|
||||
env = self.state.document.settings.env
|
||||
targetid = 'index-%s' % env.new_serialno('index')
|
||||
targetid = 'index-%s' % self.env.new_serialno('index')
|
||||
targetnode = nodes.target('', '', ids=[targetid])
|
||||
self.state.document.note_explicit_target(targetnode)
|
||||
indexnode = addnodes.index()
|
||||
@@ -209,7 +207,7 @@ class Index(Directive):
|
||||
return [indexnode, targetnode]
|
||||
|
||||
|
||||
class VersionChange(Directive):
|
||||
class VersionChange(SphinxDirective):
|
||||
"""
|
||||
Directive to describe a change/addition/deprecation in a specific version.
|
||||
"""
|
||||
@@ -252,9 +250,8 @@ class VersionChange(Directive):
|
||||
classes=['versionmodified']),
|
||||
translatable=False)
|
||||
node.append(para)
|
||||
env = self.state.document.settings.env
|
||||
# XXX should record node.source as well
|
||||
env.note_versionchange(node['type'], node['version'], node, node.line)
|
||||
self.env.note_versionchange(node['type'], node['version'], node, node.line)
|
||||
return [node] + messages
|
||||
|
||||
|
||||
@@ -265,7 +262,7 @@ class SeeAlso(BaseAdmonition):
|
||||
node_class = addnodes.seealso
|
||||
|
||||
|
||||
class TabularColumns(Directive):
|
||||
class TabularColumns(SphinxDirective):
|
||||
"""
|
||||
Directive to give an explicit tabulary column definition to LaTeX.
|
||||
"""
|
||||
@@ -283,7 +280,7 @@ class TabularColumns(Directive):
|
||||
return [node]
|
||||
|
||||
|
||||
class Centered(Directive):
|
||||
class Centered(SphinxDirective):
|
||||
"""
|
||||
Directive to create a centered line of bold text.
|
||||
"""
|
||||
@@ -304,7 +301,7 @@ class Centered(Directive):
|
||||
return [subnode] + messages
|
||||
|
||||
|
||||
class Acks(Directive):
|
||||
class Acks(SphinxDirective):
|
||||
"""
|
||||
Directive for a list of names.
|
||||
"""
|
||||
@@ -326,7 +323,7 @@ class Acks(Directive):
|
||||
return [node]
|
||||
|
||||
|
||||
class HList(Directive):
|
||||
class HList(SphinxDirective):
|
||||
"""
|
||||
Directive for a list that gets compacted horizontally.
|
||||
"""
|
||||
@@ -363,7 +360,7 @@ class HList(Directive):
|
||||
return [newnode]
|
||||
|
||||
|
||||
class Only(Directive):
|
||||
class Only(SphinxDirective):
|
||||
"""
|
||||
Directive to only include text if the given tag(s) are enabled.
|
||||
"""
|
||||
@@ -421,7 +418,7 @@ class Only(Directive):
|
||||
self.state.memo.section_level = surrounding_section_level
|
||||
|
||||
|
||||
class Include(BaseInclude):
|
||||
class Include(BaseInclude, SphinxDirective):
|
||||
"""
|
||||
Like the standard "Include" directive, but interprets absolute paths
|
||||
"correctly", i.e. relative to source directory.
|
||||
@@ -429,14 +426,13 @@ class Include(BaseInclude):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
if self.arguments[0].startswith('<') and \
|
||||
self.arguments[0].endswith('>'):
|
||||
# docutils "standard" includes, do not do path processing
|
||||
return BaseInclude.run(self)
|
||||
rel_filename, filename = env.relfn2path(self.arguments[0])
|
||||
rel_filename, filename = self.env.relfn2path(self.arguments[0])
|
||||
self.arguments[0] = filename
|
||||
env.note_included(filename)
|
||||
self.env.note_included(filename)
|
||||
return BaseInclude.run(self)
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst.directives import images, html, tables
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.nodes import set_source_info
|
||||
|
||||
if False:
|
||||
@@ -44,16 +45,15 @@ class Figure(images.Figure):
|
||||
return [figure_node]
|
||||
|
||||
|
||||
class Meta(html.Meta):
|
||||
class Meta(html.Meta, SphinxDirective):
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
result = html.Meta.run(self)
|
||||
for node in result:
|
||||
if (isinstance(node, nodes.pending) and
|
||||
isinstance(node.details['nodes'][0], html.MetaBody.meta)):
|
||||
meta = node.details['nodes'][0]
|
||||
meta.source = env.doc2path(env.docname)
|
||||
meta.source = self.env.doc2path(self.env.docname)
|
||||
meta.line = self.lineno
|
||||
meta.rawcontent = meta['content']
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ from distutils.version import LooseVersion
|
||||
import docutils
|
||||
from docutils import nodes
|
||||
from docutils.languages import get_language
|
||||
from docutils.parsers.rst import directives, roles, convert_directive_function
|
||||
from docutils.parsers.rst import Directive, directives, roles, convert_directive_function
|
||||
from docutils.statemachine import StateMachine
|
||||
from docutils.utils import Reporter
|
||||
|
||||
@@ -36,6 +36,7 @@ if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Generator, Iterator, List, Set, Tuple # NOQA
|
||||
from docutils.statemachine import State, ViewList # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
from sphinx.io import SphinxFileInput # NOQA
|
||||
|
||||
@@ -273,6 +274,26 @@ def switch_source_input(state, content):
|
||||
state.memo.reporter.get_source_and_line = get_source_and_line
|
||||
|
||||
|
||||
class SphinxDirective(Directive):
|
||||
"""A base class for Directives.
|
||||
|
||||
Compared with ``docutils.parsers.rst.Directive``, this class improves
|
||||
accessibility to Sphinx APIs.
|
||||
"""
|
||||
|
||||
@property
|
||||
def env(self):
|
||||
# type: () -> BuildEnvironment
|
||||
"""Reference to the :class:`.BuildEnvironment` object."""
|
||||
return self.state.document.settings.env
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
# type: () -> Config
|
||||
"""Reference to the :class:`.Config` object."""
|
||||
return self.env.config
|
||||
|
||||
|
||||
# cache a vanilla instance of nodes.document
|
||||
# Used in new_document() function
|
||||
__document_cache__ = None # type: nodes.document
|
||||
|
||||
Reference in New Issue
Block a user