refactor: Add data accessors to MathDomain

This commit is contained in:
Takeshi KOMIYA 2019-06-03 21:45:52 +09:00
parent e5881c2344
commit 9b0f415e21
4 changed files with 65 additions and 25 deletions

View File

@ -10,6 +10,8 @@ Incompatible changes
Deprecated Deprecated
---------- ----------
* ``sphinx.domains.math.MathDomain.add_equation()``
* ``sphinx.domains.math.MathDomain.get_next_equation_number()``
* The ``info`` and ``warn`` arguments of * The ``info`` and ``warn`` arguments of
``sphinx.ext.autosummary.generate.generate_autosummary_docs()`` ``sphinx.ext.autosummary.generate.generate_autosummary_docs()``
* ``sphinx.ext.autosummary.generate._simple_info()`` * ``sphinx.ext.autosummary.generate._simple_info()``

View File

@ -26,6 +26,16 @@ The following is a list of deprecated interfaces.
- (will be) Removed - (will be) Removed
- Alternatives - Alternatives
* - ``sphinx.domains.math.MathDomain.add_equation()``
- 2.2
- 4.0
- ``sphinx.domains.math.MathDomain.note_equation()``
* - ``sphinx.domains.math.MathDomain.get_next_equation_number()``
- 2.2
- 4.0
- ``sphinx.domains.math.MathDomain.note_equation()``
* - The ``info`` and ``warn`` arguments of * - The ``info`` and ``warn`` arguments of
``sphinx.ext.autosummary.generate.generate_autosummary_docs()`` ``sphinx.ext.autosummary.generate.generate_autosummary_docs()``
- 2.2 - 2.2

View File

@ -16,6 +16,7 @@ from docutils.parsers.rst.directives import images, html, tables
from sphinx import addnodes from sphinx import addnodes
from sphinx.directives import optional_int from sphinx.directives import optional_int
from sphinx.domains.math import MathDomain
from sphinx.util.docutils import SphinxDirective from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import set_source_info from sphinx.util.nodes import set_source_info
@ -194,18 +195,15 @@ class MathDirective(SphinxDirective):
return return
# register label to domain # register label to domain
domain = self.env.get_domain('math') domain = cast(MathDomain, self.env.get_domain('math'))
try: domain.note_equation(self.env.docname, node['label'], location=node)
eqno = domain.add_equation(self.env, self.env.docname, node['label']) # type: ignore # NOQA node['number'] = domain.get_equation_number_for(node['label'])
node['number'] = eqno
# add target node # add target node
node_id = make_id('equation-%s' % node['label']) node_id = make_id('equation-%s' % node['label'])
target = nodes.target('', '', ids=[node_id]) target = nodes.target('', '', ids=[node_id])
self.state.document.note_explicit_target(target) self.state.document.note_explicit_target(target)
ret.insert(0, target) ret.insert(0, target)
except UserWarning as exc:
self.state_machine.reporter.warning(exc, line=self.lineno)
def setup(app: "Sphinx") -> Dict[str, Any]: def setup(app: "Sphinx") -> Dict[str, Any]:

View File

@ -8,10 +8,13 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import warnings
from docutils import nodes from docutils import nodes
from docutils.nodes import make_id from docutils.nodes import make_id
from sphinx.addnodes import math_block as displaymath from sphinx.addnodes import math_block as displaymath
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.domains import Domain from sphinx.domains import Domain
from sphinx.locale import __ from sphinx.locale import __
from sphinx.roles import XRefRole from sphinx.roles import XRefRole
@ -44,7 +47,7 @@ class MathDomain(Domain):
initial_data = { initial_data = {
'objects': {}, # labelid -> (docname, eqno) 'objects': {}, # labelid -> (docname, eqno)
'has_equations': {}, # docname -> bool 'has_equations': {}, # docname -> bool
} # type: Dict[str, Dict[str, Tuple[str, int]]] } # type: Dict
dangling_warnings = { dangling_warnings = {
'eq': 'equation not found: %(target)s', 'eq': 'equation not found: %(target)s',
} }
@ -56,6 +59,27 @@ class MathDomain(Domain):
'numref': MathReferenceRole(), 'numref': MathReferenceRole(),
} }
@property
def equations(self):
# type: () -> Dict[str, Tuple[str, int]]
return self.data.setdefault('objects', {}) # labelid -> (docname, eqno)
def note_equation(self, docname, labelid, location=None):
# type: (str, str, Any) -> None
if labelid in self.equations:
other = self.equations[labelid][0]
logger.warning(__('duplicate label of equation %s, other instance in %s') %
(labelid, other), location=location)
self.equations[labelid] = (docname, self.env.new_serialno('eqno') + 1)
def get_equation_number_for(self, labelid):
# type: (str) -> int
if labelid in self.equations:
return self.equations[labelid][1]
else:
return None
def process_doc(self, env, docname, document): def process_doc(self, env, docname, document):
# type: (BuildEnvironment, str, nodes.document) -> None # type: (BuildEnvironment, str, nodes.document) -> None
def math_node(node): def math_node(node):
@ -66,9 +90,9 @@ class MathDomain(Domain):
def clear_doc(self, docname): def clear_doc(self, docname):
# type: (str) -> None # type: (str) -> None
for equation_id, (doc, eqno) in list(self.data['objects'].items()): for equation_id, (doc, eqno) in list(self.equations.items()):
if doc == docname: if doc == docname:
del self.data['objects'][equation_id] del self.equations[equation_id]
self.data['has_equations'].pop(docname, None) self.data['has_equations'].pop(docname, None)
@ -76,7 +100,7 @@ class MathDomain(Domain):
# type: (Iterable[str], Dict) -> None # type: (Iterable[str], Dict) -> None
for labelid, (doc, eqno) in otherdata['objects'].items(): for labelid, (doc, eqno) in otherdata['objects'].items():
if doc in docnames: if doc in docnames:
self.data['objects'][labelid] = (doc, eqno) self.equations[labelid] = (doc, eqno)
for docname in docnames: for docname in docnames:
self.data['has_equations'][docname] = otherdata['has_equations'][docname] self.data['has_equations'][docname] = otherdata['has_equations'][docname]
@ -84,19 +108,22 @@ class MathDomain(Domain):
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
# type: (BuildEnvironment, str, Builder, str, str, addnodes.pending_xref, nodes.Element) -> nodes.Element # NOQA # type: (BuildEnvironment, str, Builder, str, str, addnodes.pending_xref, nodes.Element) -> nodes.Element # NOQA
assert typ in ('eq', 'numref') assert typ in ('eq', 'numref')
docname, number = self.data['objects'].get(target, (None, None)) docname, number = self.equations.get(target, (None, None))
if docname: if docname:
# TODO: perhaps use rather a sphinx-core provided prefix here? # TODO: perhaps use rather a sphinx-core provided prefix here?
node_id = make_id('equation-%s' % target) node_id = make_id('equation-%s' % target)
if env.config.math_numfig and env.config.numfig: if env.config.math_numfig and env.config.numfig:
if docname in env.toc_fignumbers: if docname in env.toc_fignumbers:
number = env.toc_fignumbers[docname]['displaymath'].get(node_id, ()) numbers = env.toc_fignumbers[docname]['displaymath'].get(node_id, ())
number = '.'.join(map(str, number)) eqno = '.'.join(map(str, numbers))
else: else:
number = '' eqno = ''
else:
eqno = str(number)
try: try:
eqref_format = env.config.math_eqref_format or "({number})" eqref_format = env.config.math_eqref_format or "({number})"
title = nodes.Text(eqref_format.format(number=number)) title = nodes.Text(eqref_format.format(number=eqno))
except KeyError as exc: except KeyError as exc:
logger.warning(__('Invalid math_eqref_format: %r'), exc, logger.warning(__('Invalid math_eqref_format: %r'), exc,
location=node) location=node)
@ -120,19 +147,22 @@ class MathDomain(Domain):
def add_equation(self, env, docname, labelid): def add_equation(self, env, docname, labelid):
# type: (BuildEnvironment, str, str) -> int # type: (BuildEnvironment, str, str) -> int
equations = self.data['objects'] warnings.warn('MathDomain.add_equation() is deprecated.',
if labelid in equations: RemovedInSphinx40Warning)
path = env.doc2path(equations[labelid][0]) if labelid in self.equations:
path = env.doc2path(self.equations[labelid][0])
msg = __('duplicate label of equation %s, other instance in %s') % (labelid, path) msg = __('duplicate label of equation %s, other instance in %s') % (labelid, path)
raise UserWarning(msg) raise UserWarning(msg)
else: else:
eqno = self.get_next_equation_number(docname) eqno = self.get_next_equation_number(docname)
equations[labelid] = (docname, eqno) self.equations[labelid] = (docname, eqno)
return eqno return eqno
def get_next_equation_number(self, docname): def get_next_equation_number(self, docname):
# type: (str) -> int # type: (str) -> int
targets = [eq for eq in self.data['objects'].values() if eq[0] == docname] warnings.warn('MathDomain.get_next_equation_number() is deprecated.',
RemovedInSphinx40Warning)
targets = [eq for eq in self.equations.values() if eq[0] == docname]
return len(targets) + 1 return len(targets) + 1
def has_equations(self): def has_equations(self):