mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #6236 from tk0miya/refactor_pydomain3
Add data accessors and helper methods to PythonDomain
This commit is contained in:
commit
e05e349277
7
CHANGES
7
CHANGES
@ -50,7 +50,12 @@ Features added
|
|||||||
--------------
|
--------------
|
||||||
|
|
||||||
* Add a helper class ``sphinx.transforms.post_transforms.SphinxPostTransform``
|
* Add a helper class ``sphinx.transforms.post_transforms.SphinxPostTransform``
|
||||||
* Add a helper method ``SphinxDirective.set_source_info()``
|
* Add helper methods
|
||||||
|
|
||||||
|
- ``PythonDomain.note_module()``
|
||||||
|
- ``PythonDomain.note_object()``
|
||||||
|
- ``SphinxDirective.set_source_info()``
|
||||||
|
|
||||||
* #6180: Support ``--keep-going`` with BuildDoc setup command
|
* #6180: Support ``--keep-going`` with BuildDoc setup command
|
||||||
* ``math`` directive now supports ``:class:`` option
|
* ``math`` directive now supports ``:class:`` option
|
||||||
* todo: ``todo`` directive now supports ``:name:`` option
|
* todo: ``todo`` directive now supports ``:name:`` option
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.parsers.rst import directives
|
from docutils.parsers.rst import directives
|
||||||
@ -331,15 +332,9 @@ class PyObject(ObjectDescription):
|
|||||||
signode['ids'].append(fullname)
|
signode['ids'].append(fullname)
|
||||||
signode['first'] = (not self.names)
|
signode['first'] = (not self.names)
|
||||||
self.state.document.note_explicit_target(signode)
|
self.state.document.note_explicit_target(signode)
|
||||||
objects = self.env.domaindata['py']['objects']
|
|
||||||
if fullname in objects:
|
domain = cast(PythonDomain, self.env.get_domain('py'))
|
||||||
self.state_machine.reporter.warning(
|
domain.note_object(fullname, self.objtype)
|
||||||
'duplicate object description of %s, ' % fullname +
|
|
||||||
'other instance in ' +
|
|
||||||
self.env.doc2path(objects[fullname][0]) +
|
|
||||||
', use :noindex: for one of them',
|
|
||||||
line=self.lineno)
|
|
||||||
objects[fullname] = (self.env.docname, self.objtype)
|
|
||||||
|
|
||||||
indextext = self.get_index_text(modname, name_cls)
|
indextext = self.get_index_text(modname, name_cls)
|
||||||
if indextext:
|
if indextext:
|
||||||
@ -582,18 +577,20 @@ class PyModule(SphinxDirective):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# type: () -> List[nodes.Node]
|
# type: () -> List[nodes.Node]
|
||||||
|
domain = cast(PythonDomain, self.env.get_domain('py'))
|
||||||
|
|
||||||
modname = self.arguments[0].strip()
|
modname = self.arguments[0].strip()
|
||||||
noindex = 'noindex' in self.options
|
noindex = 'noindex' in self.options
|
||||||
self.env.ref_context['py:module'] = modname
|
self.env.ref_context['py:module'] = modname
|
||||||
ret = [] # type: List[nodes.Node]
|
ret = [] # type: List[nodes.Node]
|
||||||
if not noindex:
|
if not noindex:
|
||||||
self.env.domaindata['py']['modules'][modname] = (self.env.docname,
|
# note module to the domain
|
||||||
|
domain.note_module(modname,
|
||||||
self.options.get('synopsis', ''),
|
self.options.get('synopsis', ''),
|
||||||
self.options.get('platform', ''),
|
self.options.get('platform', ''),
|
||||||
'deprecated' in self.options)
|
'deprecated' in self.options)
|
||||||
# make a duplicate entry in 'objects' to facilitate searching for
|
domain.note_object(modname, 'module')
|
||||||
# the module in PythonDomain.find_obj()
|
|
||||||
self.env.domaindata['py']['objects'][modname] = (self.env.docname, 'module')
|
|
||||||
targetnode = nodes.target('', '', ids=['module-' + modname],
|
targetnode = nodes.target('', '', ids=['module-' + modname],
|
||||||
ismod=True)
|
ismod=True)
|
||||||
self.state.document.note_explicit_target(targetnode)
|
self.state.document.note_explicit_target(targetnode)
|
||||||
@ -776,24 +773,55 @@ class PythonDomain(Domain):
|
|||||||
PythonModuleIndex,
|
PythonModuleIndex,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def objects(self):
|
||||||
|
# type: () -> Dict[str, Tuple[str, str]]
|
||||||
|
return self.data.setdefault('objects', {}) # fullname -> docname, objtype
|
||||||
|
|
||||||
|
def note_object(self, name, objtype, location=None):
|
||||||
|
# type: (str, str, Any) -> None
|
||||||
|
"""Note a python object for cross reference.
|
||||||
|
|
||||||
|
.. versionadded:: 2.1
|
||||||
|
"""
|
||||||
|
if name in self.objects:
|
||||||
|
docname = self.objects[name][0]
|
||||||
|
logger.warning(__('duplicate object description of %s, '
|
||||||
|
'other instance in %s, use :noindex: for one of them'),
|
||||||
|
name, docname, location=location)
|
||||||
|
self.objects[name] = (self.env.docname, objtype)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def modules(self):
|
||||||
|
# type: () -> Dict[str, Tuple[str, str, str, bool]]
|
||||||
|
return self.data.setdefault('modules', {}) # modname -> docname, synopsis, platform, deprecated # NOQA
|
||||||
|
|
||||||
|
def note_module(self, name, synopsis, platform, deprecated):
|
||||||
|
# type: (str, str, str, bool) -> None
|
||||||
|
"""Note a python module for cross reference.
|
||||||
|
|
||||||
|
.. versionadded:: 2.1
|
||||||
|
"""
|
||||||
|
self.modules[name] = (self.env.docname, synopsis, platform, deprecated)
|
||||||
|
|
||||||
def clear_doc(self, docname):
|
def clear_doc(self, docname):
|
||||||
# type: (str) -> None
|
# type: (str) -> None
|
||||||
for fullname, (fn, _l) in list(self.data['objects'].items()):
|
for fullname, (fn, _l) in list(self.objects.items()):
|
||||||
if fn == docname:
|
if fn == docname:
|
||||||
del self.data['objects'][fullname]
|
del self.objects[fullname]
|
||||||
for modname, (fn, _x, _x, _x) in list(self.data['modules'].items()):
|
for modname, (fn, _x, _x, _y) in list(self.modules.items()):
|
||||||
if fn == docname:
|
if fn == docname:
|
||||||
del self.data['modules'][modname]
|
del self.modules[modname]
|
||||||
|
|
||||||
def merge_domaindata(self, docnames, otherdata):
|
def merge_domaindata(self, docnames, otherdata):
|
||||||
# type: (List[str], Dict) -> None
|
# type: (List[str], Dict) -> None
|
||||||
# XXX check duplicates?
|
# XXX check duplicates?
|
||||||
for fullname, (fn, objtype) in otherdata['objects'].items():
|
for fullname, (fn, objtype) in otherdata['objects'].items():
|
||||||
if fn in docnames:
|
if fn in docnames:
|
||||||
self.data['objects'][fullname] = (fn, objtype)
|
self.objects[fullname] = (fn, objtype)
|
||||||
for modname, data in otherdata['modules'].items():
|
for modname, data in otherdata['modules'].items():
|
||||||
if data[0] in docnames:
|
if data[0] in docnames:
|
||||||
self.data['modules'][modname] = data
|
self.modules[modname] = data
|
||||||
|
|
||||||
def find_obj(self, env, modname, classname, name, type, searchmode=0):
|
def find_obj(self, env, modname, classname, name, type, searchmode=0):
|
||||||
# type: (BuildEnvironment, str, str, str, str, int) -> List[Tuple[str, Any]]
|
# type: (BuildEnvironment, str, str, str, str, int) -> List[Tuple[str, Any]]
|
||||||
@ -807,7 +835,6 @@ class PythonDomain(Domain):
|
|||||||
if not name:
|
if not name:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
objects = self.data['objects']
|
|
||||||
matches = [] # type: List[Tuple[str, Any]]
|
matches = [] # type: List[Tuple[str, Any]]
|
||||||
|
|
||||||
newname = None
|
newname = None
|
||||||
@ -819,44 +846,44 @@ class PythonDomain(Domain):
|
|||||||
if objtypes is not None:
|
if objtypes is not None:
|
||||||
if modname and classname:
|
if modname and classname:
|
||||||
fullname = modname + '.' + classname + '.' + name
|
fullname = modname + '.' + classname + '.' + name
|
||||||
if fullname in objects and objects[fullname][1] in objtypes:
|
if fullname in self.objects and self.objects[fullname][1] in objtypes:
|
||||||
newname = fullname
|
newname = fullname
|
||||||
if not newname:
|
if not newname:
|
||||||
if modname and modname + '.' + name in objects and \
|
if modname and modname + '.' + name in self.objects and \
|
||||||
objects[modname + '.' + name][1] in objtypes:
|
self.objects[modname + '.' + name][1] in objtypes:
|
||||||
newname = modname + '.' + name
|
newname = modname + '.' + name
|
||||||
elif name in objects and objects[name][1] in objtypes:
|
elif name in self.objects and self.objects[name][1] in objtypes:
|
||||||
newname = name
|
newname = name
|
||||||
else:
|
else:
|
||||||
# "fuzzy" searching mode
|
# "fuzzy" searching mode
|
||||||
searchname = '.' + name
|
searchname = '.' + name
|
||||||
matches = [(oname, objects[oname]) for oname in objects
|
matches = [(oname, self.objects[oname]) for oname in self.objects
|
||||||
if oname.endswith(searchname) and
|
if oname.endswith(searchname) and
|
||||||
objects[oname][1] in objtypes]
|
self.objects[oname][1] in objtypes]
|
||||||
else:
|
else:
|
||||||
# NOTE: searching for exact match, object type is not considered
|
# NOTE: searching for exact match, object type is not considered
|
||||||
if name in objects:
|
if name in self.objects:
|
||||||
newname = name
|
newname = name
|
||||||
elif type == 'mod':
|
elif type == 'mod':
|
||||||
# only exact matches allowed for modules
|
# only exact matches allowed for modules
|
||||||
return []
|
return []
|
||||||
elif classname and classname + '.' + name in objects:
|
elif classname and classname + '.' + name in self.objects:
|
||||||
newname = classname + '.' + name
|
newname = classname + '.' + name
|
||||||
elif modname and modname + '.' + name in objects:
|
elif modname and modname + '.' + name in self.objects:
|
||||||
newname = modname + '.' + name
|
newname = modname + '.' + name
|
||||||
elif modname and classname and \
|
elif modname and classname and \
|
||||||
modname + '.' + classname + '.' + name in objects:
|
modname + '.' + classname + '.' + name in self.objects:
|
||||||
newname = modname + '.' + classname + '.' + name
|
newname = modname + '.' + classname + '.' + name
|
||||||
# special case: builtin exceptions have module "exceptions" set
|
# special case: builtin exceptions have module "exceptions" set
|
||||||
elif type == 'exc' and '.' not in name and \
|
elif type == 'exc' and '.' not in name and \
|
||||||
'exceptions.' + name in objects:
|
'exceptions.' + name in self.objects:
|
||||||
newname = 'exceptions.' + name
|
newname = 'exceptions.' + name
|
||||||
# special case: object methods
|
# special case: object methods
|
||||||
elif type in ('func', 'meth') and '.' not in name and \
|
elif type in ('func', 'meth') and '.' not in name and \
|
||||||
'object.' + name in objects:
|
'object.' + name in self.objects:
|
||||||
newname = 'object.' + name
|
newname = 'object.' + name
|
||||||
if newname is not None:
|
if newname is not None:
|
||||||
matches.append((newname, objects[newname]))
|
matches.append((newname, self.objects[newname]))
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
def resolve_xref(self, env, fromdocname, builder,
|
def resolve_xref(self, env, fromdocname, builder,
|
||||||
@ -903,7 +930,7 @@ class PythonDomain(Domain):
|
|||||||
def _make_module_refnode(self, builder, fromdocname, name, contnode):
|
def _make_module_refnode(self, builder, fromdocname, name, contnode):
|
||||||
# type: (Builder, str, str, nodes.Node) -> nodes.Element
|
# type: (Builder, str, str, nodes.Node) -> nodes.Element
|
||||||
# get additional info for modules
|
# get additional info for modules
|
||||||
docname, synopsis, platform, deprecated = self.data['modules'][name]
|
docname, synopsis, platform, deprecated = self.modules[name]
|
||||||
title = name
|
title = name
|
||||||
if synopsis:
|
if synopsis:
|
||||||
title += ': ' + synopsis
|
title += ': ' + synopsis
|
||||||
@ -916,9 +943,9 @@ class PythonDomain(Domain):
|
|||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
# type: () -> Iterator[Tuple[str, str, str, str, str, int]]
|
# type: () -> Iterator[Tuple[str, str, str, str, str, int]]
|
||||||
for modname, info in self.data['modules'].items():
|
for modname, info in self.modules.items():
|
||||||
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
|
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
|
||||||
for refname, (docname, type) in self.data['objects'].items():
|
for refname, (docname, type) in self.objects.items():
|
||||||
if type != 'module': # modules are already handled
|
if type != 'module': # modules are already handled
|
||||||
yield (refname, refname, type, docname, refname, 1)
|
yield (refname, refname, type, docname, refname, 1)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user