diff options
Diffstat (limited to 'sphinx/domains/std.py')
-rw-r--r-- | sphinx/domains/std.py | 107 |
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, } |