Files
sphinx/sphinx/domains/changeset.py
2018-11-06 00:26:29 +09:00

159 lines
5.5 KiB
Python

# -*- coding: utf-8 -*-
"""
sphinx.domains.changeset
~~~~~~~~~~~~~~~~~~~~~~~~
The changeset domain.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import NamedTuple
from docutils import nodes
from sphinx import addnodes
from sphinx import locale
from sphinx.deprecation import DeprecatedDict, RemovedInSphinx30Warning
from sphinx.domains import Domain
from sphinx.locale import _
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import set_source_info
if False:
# For type annotation
from typing import Any, Dict, List # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
versionlabels = {
'versionadded': _('New in version %s'),
'versionchanged': _('Changed in version %s'),
'deprecated': _('Deprecated since version %s'),
} # type: Dict[unicode, unicode]
locale.versionlabels = DeprecatedDict(
versionlabels,
'sphinx.locale.versionlabels is deprecated. '
'Please use sphinx.domains.changeset.versionlabels instead.',
RemovedInSphinx30Warning
)
ChangeSet = NamedTuple('ChangeSet', [('type', str),
('docname', str),
('lineno', int),
('module', str),
('descname', str),
('content', str)])
class VersionChange(SphinxDirective):
"""
Directive to describe a change/addition/deprecation in a specific version.
"""
has_content = True
required_arguments = 1
optional_arguments = 1
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
node = addnodes.versionmodified() # type: nodes.Node
node.document = self.state.document
set_source_info(self, node)
node['type'] = self.name
node['version'] = self.arguments[0]
text = versionlabels[self.name] % self.arguments[0]
if len(self.arguments) == 2:
inodes, messages = self.state.inline_text(self.arguments[1],
self.lineno + 1)
para = nodes.paragraph(self.arguments[1], '', *inodes, translatable=False)
set_source_info(self, para)
node.append(para)
else:
messages = []
if self.content:
self.state.nested_parse(self.content, self.content_offset, node)
if len(node):
if isinstance(node[0], nodes.paragraph) and node[0].rawsource:
content = nodes.inline(node[0].rawsource, translatable=True)
content.source = node[0].source
content.line = node[0].line
content += node[0].children
node[0].replace_self(nodes.paragraph('', '', content, translatable=False))
node[0].insert(0, nodes.inline('', '%s: ' % text,
classes=['versionmodified']))
else:
para = nodes.paragraph('', '',
nodes.inline('', '%s.' % text,
classes=['versionmodified']),
translatable=False)
node.append(para)
self.env.get_domain('changeset').note_changeset(node) # type: ignore
return [node] + messages
class ChangeSetDomain(Domain):
"""Domain for changesets."""
name = 'changeset'
label = 'changeset'
initial_data = {
'changes': {}, # version -> list of ChangeSet
} # type: Dict
def clear_doc(self, docname):
# type: (unicode) -> None
for version, changes in self.data['changes'].items():
for changeset in changes[:]:
if changeset.docname == docname:
changes.remove(changeset)
def merge_domaindata(self, docnames, otherdata):
# type: (List[unicode], Dict) -> None
# XXX duplicates?
for version, otherchanges in otherdata['changes'].items():
changes = self.data['changes'].setdefault(version, [])
for changeset in otherchanges:
if changeset.docname in docnames:
changes.append(changeset)
def process_doc(self, env, docname, document):
# type: (BuildEnvironment, unicode, nodes.Node) -> None
pass # nothing to do here. All changesets are registered on calling directive.
def note_changeset(self, node):
# type: (nodes.Node) -> None
version = node['version']
module = self.env.ref_context.get('py:module')
objname = self.env.temp_data.get('object')
changeset = ChangeSet(node['type'], self.env.docname, node.line, # type: ignore
module, objname, node.astext())
self.data['changes'].setdefault(version, []).append(changeset)
def get_changesets_for(self, version):
# type: (unicode) -> List[ChangeSet]
return self.data['changes'].get(version, [])
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_domain(ChangeSetDomain)
app.add_directive('deprecated', VersionChange)
app.add_directive('versionadded', VersionChange)
app.add_directive('versionchanged', VersionChange)
return {
'version': 'builtin',
'env_version': 1,
'parallel_read_safe': True,
'parallel_write_safe': True,
}