summaryrefslogtreecommitdiff
path: root/sphinx/domains/std.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/domains/std.py')
-rw-r--r--sphinx/domains/std.py107
1 files changed, 65 insertions, 42 deletions
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py
index 937760c45..bc6b4de6c 100644
--- a/sphinx/domains/std.py
+++ b/sphinx/domains/std.py
@@ -11,23 +11,28 @@
import re
import unicodedata
+import warnings
+from copy import copy
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 iteritems
from sphinx import addnodes
+from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType
-from sphinx.locale import l_, _
+from sphinx.locale import _, __
from sphinx.roles import XRefRole
from sphinx.util import ws_re, logging, docname_join
+from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import clean_astext, make_refnode
if False:
# For type annotation
from typing import Any, Callable, Dict, Iterator, List, Tuple, Type, Union # NOQA
+ from docutils.parsers.rst import Directive # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
@@ -80,7 +85,7 @@ class GenericObject(ObjectDescription):
class EnvVar(GenericObject):
- indextemplate = l_('environment variable; %s')
+ indextemplate = _('environment variable; %s')
class EnvVarXRefRole(XRefRole):
@@ -104,7 +109,7 @@ class EnvVarXRefRole(XRefRole):
return [indexnode, targetnode, node], []
-class Target(Directive):
+class Target(SphinxDirective):
"""
Generic target for user-defined cross-reference types.
"""
@@ -118,7 +123,6 @@ class Target(Directive):
def run(self):
# type: () -> List[nodes.Node]
- env = self.state.document.settings.env
# normalize whitespace in fullname like XRefRole does
fullname = ws_re.sub(' ', self.arguments[0].strip())
targetname = '%s-%s' % (self.name, fullname)
@@ -138,8 +142,8 @@ class Target(Directive):
name = self.name
if ':' in self.name:
_, name = self.name.split(':', 1)
- env.domaindata['std']['objects'][name, fullname] = \
- env.docname, targetname
+ self.env.domaindata['std']['objects'][name, fullname] = \
+ self.env.docname, targetname
return ret
@@ -157,9 +161,9 @@ class Cmdoption(ObjectDescription):
potential_option = potential_option.strip()
m = option_desc_re.match(potential_option) # type: ignore
if not m:
- logger.warning('Malformed option description %r, should '
- 'look like "opt", "-opt args", "--opt args", '
- '"/opt args" or "+opt args"', potential_option,
+ logger.warning(__('Malformed option description %r, should '
+ 'look like "opt", "-opt args", "--opt args", '
+ '"/opt args" or "+opt args"'), potential_option,
location=(self.env.docname, self.lineno))
continue
optname, args = m.groups()
@@ -201,7 +205,7 @@ class Cmdoption(ObjectDescription):
signode['ids'][0], '', None))
-class Program(Directive):
+class Program(SphinxDirective):
"""
Directive to name the program for which options are documented.
"""
@@ -214,12 +218,11 @@ class Program(Directive):
def run(self):
# type: () -> List[nodes.Node]
- env = self.state.document.settings.env
program = ws_re.sub('-', self.arguments[0].strip())
if program == 'None':
- env.ref_context.pop('std:program', None)
+ self.env.ref_context.pop('std:program', None)
else:
- env.ref_context['std:program'] = program
+ self.env.ref_context['std:program'] = program
return []
@@ -267,7 +270,7 @@ def make_glossary_term(env, textnodes, index_key, source, lineno, new_id=None):
return term
-class Glossary(Directive):
+class Glossary(SphinxDirective):
"""
Directive to create a glossary with cross-reference targets for :term:
roles.
@@ -283,7 +286,6 @@ class Glossary(Directive):
def run(self):
# type: () -> List[nodes.Node]
- env = self.state.document.settings.env
node = addnodes.glossary()
node.document = self.state.document
@@ -355,7 +357,7 @@ class Glossary(Directive):
textnodes, sysmsg = self.state.inline_text(parts[0], lineno)
# use first classifier as a index key
- term = make_glossary_term(env, textnodes, parts[1], source, lineno)
+ term = make_glossary_term(self.env, textnodes, parts[1], source, lineno)
term.rawsource = line
system_messages.extend(sysmsg)
termtexts.append(term.astext())
@@ -400,7 +402,7 @@ def token_xrefs(text):
return retnodes
-class ProductionList(Directive):
+class ProductionList(SphinxDirective):
"""
Directive to list grammar productions.
"""
@@ -413,8 +415,7 @@ class ProductionList(Directive):
def run(self):
# type: () -> List[nodes.Node]
- env = self.state.document.settings.env
- objects = env.domaindata['std']['objects']
+ objects = self.env.domaindata['std']['objects']
node = addnodes.productionlist()
messages = [] # type: List[nodes.Node]
i = 0
@@ -435,7 +436,7 @@ class ProductionList(Directive):
if idname not in self.state.document.ids:
subnode['ids'].append(idname)
self.state.document.note_implicit_target(subnode, subnode)
- objects['token', subnode['tokenname']] = env.docname, idname
+ objects['token', subnode['tokenname']] = self.env.docname, idname
subnode.extend(token_xrefs(tokens))
node.append(subnode)
return [node] + messages
@@ -451,13 +452,13 @@ class StandardDomain(Domain):
label = 'Default'
object_types = {
- 'term': ObjType(l_('glossary term'), 'term', searchprio=-1),
- 'token': ObjType(l_('grammar token'), 'token', searchprio=-1),
- 'label': ObjType(l_('reference label'), 'ref', 'keyword',
+ 'term': ObjType(_('glossary term'), 'term', searchprio=-1),
+ 'token': ObjType(_('grammar token'), 'token', searchprio=-1),
+ 'label': ObjType(_('reference label'), 'ref', 'keyword',
searchprio=-1),
- 'envvar': ObjType(l_('environment variable'), 'envvar'),
- 'cmdoption': ObjType(l_('program option'), 'option'),
- 'doc': ObjType(l_('document'), 'doc', searchprio=-1)
+ 'envvar': ObjType(_('environment variable'), 'envvar'),
+ 'cmdoption': ObjType(_('program option'), 'option'),
+ 'doc': ObjType(_('document'), 'doc', searchprio=-1)
} # type: Dict[unicode, ObjType]
directives = {
@@ -494,9 +495,9 @@ class StandardDomain(Domain):
'citations': {}, # citation_name -> docname, labelid, lineno
'citation_refs': {}, # citation_name -> list of docnames
'labels': { # labelname -> docname, labelid, sectionname
- 'genindex': ('genindex', '', l_('Index')),
- 'modindex': ('py-modindex', '', l_('Module Index')),
- 'search': ('search', '', l_('Search Page')),
+ 'genindex': ('genindex', '', _('Index')),
+ 'modindex': ('py-modindex', '', _('Module Index')),
+ 'search': ('search', '', _('Search Page')),
},
'anonlabels': { # labelname -> docname, labelid
'genindex': ('genindex', ''),
@@ -522,6 +523,15 @@ class StandardDomain(Domain):
nodes.container: ('code-block', None),
} # type: Dict[nodes.Node, Tuple[unicode, Callable]]
+ def __init__(self, env):
+ # type: (BuildEnvironment) -> None
+ super(StandardDomain, self).__init__(env)
+
+ # set up enumerable nodes
+ self.enumerable_nodes = copy(self.enumerable_nodes) # create a copy for this instance
+ for node, settings in iteritems(env.app.registry.enumerable_nodes):
+ self.enumerable_nodes[node] = settings
+
def clear_doc(self, docname):
# type: (unicode) -> None
for key, (fn, _l) in list(self.data['progoptions'].items()):
@@ -578,10 +588,11 @@ class StandardDomain(Domain):
def note_citations(self, env, docname, document):
# type: (BuildEnvironment, unicode, nodes.Node) -> None
for node in document.traverse(nodes.citation):
+ node['docname'] = docname
label = node[0].astext()
if label in self.data['citations']:
path = env.doc2path(self.data['citations'][label][0])
- logger.warning('duplicate citation %s, other instance in %s', label, path,
+ logger.warning(__('duplicate citation %s, other instance in %s'), label, path,
location=node, type='ref', subtype='citation')
self.data['citations'][label] = (docname, node['ids'][0], node.line)
@@ -613,8 +624,8 @@ class StandardDomain(Domain):
# link and object descriptions
continue
if name in labels:
- logger.warning('duplicate label %s, ' % name + 'other instance '
- 'in ' + env.doc2path(labels[name][0]),
+ logger.warning(__('duplicate label %s, other instance in %s'),
+ name, env.doc2path(labels[name][0]),
location=node)
anonlabels[name] = docname, labelid
if node.tagname in ('section', 'rubric'):
@@ -638,7 +649,7 @@ class StandardDomain(Domain):
# type: () -> None
for name, (docname, labelid, lineno) in iteritems(self.data['citations']):
if name not in self.data['citation_refs']:
- logger.warning('Citation [%s] is not referenced.', name,
+ logger.warning(__('Citation [%s] is not referenced.'), name,
type='ref', subtype='citation',
location=(docname, lineno))
@@ -716,12 +727,12 @@ class StandardDomain(Domain):
return None
target_node = env.get_doctree(docname).ids.get(labelid)
- figtype = self.get_figtype(target_node)
+ figtype = self.get_enumerable_node_type(target_node)
if figtype is None:
return None
if figtype != 'section' and env.config.numfig is False:
- logger.warning('numfig is disabled. :numref: is ignored.', location=node)
+ logger.warning(__('numfig is disabled. :numref: is ignored.'), location=node)
return contnode
try:
@@ -729,7 +740,7 @@ class StandardDomain(Domain):
if fignumber is None:
return contnode
except ValueError:
- logger.warning("no number is assigned for %s: %s", figtype, labelid,
+ logger.warning(__("no number is assigned for %s: %s"), figtype, labelid,
location=node)
return contnode
@@ -740,7 +751,7 @@ class StandardDomain(Domain):
title = env.config.numfig_format.get(figtype, '')
if figname is None and '{name}' in title:
- logger.warning('the link has no caption: %s', title, location=node)
+ logger.warning(__('the link has no caption: %s'), title, location=node)
return contnode
else:
fignum = '.'.join(map(str, fignumber))
@@ -754,10 +765,10 @@ class StandardDomain(Domain):
# old style format (cf. "Fig.%s")
newtitle = title % fignum
except KeyError as exc:
- logger.warning('invalid numfig_format: %s (%r)', title, exc, location=node)
+ logger.warning(__('invalid numfig_format: %s (%r)'), title, exc, location=node)
return contnode
except TypeError:
- logger.warning('invalid numfig_format: %s', title, location=node)
+ logger.warning(__('invalid numfig_format: %s'), title, location=node)
return contnode
return self.build_reference_node(fromdocname, builder,
@@ -916,9 +927,9 @@ class StandardDomain(Domain):
return None
- def get_figtype(self, node):
+ def get_enumerable_node_type(self, node):
# type: (nodes.Node) -> unicode
- """Get figure type of nodes."""
+ """Get type of enumerable nodes."""
def has_child(node, cls):
# type: (nodes.Node, Type) -> bool
return any(isinstance(child, cls) for child in node)
@@ -934,6 +945,17 @@ class StandardDomain(Domain):
figtype, _ = self.enumerable_nodes.get(node.__class__, (None, None))
return figtype
+ def get_figtype(self, node):
+ # type: (nodes.Node) -> unicode
+ """Get figure type of nodes.
+
+ .. deprecated:: 1.8
+ """
+ warnings.warn('StandardDomain.get_figtype() is deprecated. '
+ 'Please use get_enumerable_node_type() instead.',
+ RemovedInSphinx30Warning)
+ return self.get_enumerable_node_type(node)
+
def get_fignumber(self, env, builder, figtype, docname, target_node):
# type: (BuildEnvironment, Builder, unicode, unicode, nodes.Node) -> Tuple[int, ...]
if figtype == 'section':
@@ -979,6 +1001,7 @@ def setup(app):
return {
'version': 'builtin',
+ 'env_version': 1,
'parallel_read_safe': True,
'parallel_write_safe': True,
}