mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7363 from tk0miya/refactor_pydomain
refactor: py domain: Use namedtuple for python objects and modules
This commit is contained in:
commit
3a95fa7336
@ -14,7 +14,7 @@ import re
|
|||||||
import typing
|
import typing
|
||||||
import warnings
|
import warnings
|
||||||
from inspect import Parameter
|
from inspect import Parameter
|
||||||
from typing import Any, Dict, Iterable, Iterator, List, Tuple
|
from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Tuple
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
@ -67,6 +67,15 @@ pairindextypes = {
|
|||||||
'builtin': _('built-in function'),
|
'builtin': _('built-in function'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjectEntry = NamedTuple('ObjectEntry', [('docname', str),
|
||||||
|
('node_id', str),
|
||||||
|
('objtype', str)])
|
||||||
|
ModuleEntry = NamedTuple('ModuleEntry', [('docname', str),
|
||||||
|
('node_id', str),
|
||||||
|
('synopsis', str),
|
||||||
|
('platform', str),
|
||||||
|
('deprecated', bool)])
|
||||||
|
|
||||||
|
|
||||||
def _parse_annotation(annotation: str) -> List[Node]:
|
def _parse_annotation(annotation: str) -> List[Node]:
|
||||||
"""Parse type annotation."""
|
"""Parse type annotation."""
|
||||||
@ -1113,8 +1122,8 @@ class PythonDomain(Domain):
|
|||||||
]
|
]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def objects(self) -> Dict[str, Tuple[str, str, str]]:
|
def objects(self) -> Dict[str, ObjectEntry]:
|
||||||
return self.data.setdefault('objects', {}) # fullname -> docname, node_id, objtype
|
return self.data.setdefault('objects', {}) # fullname -> ObjectEntry
|
||||||
|
|
||||||
def note_object(self, name: str, objtype: str, node_id: str, location: Any = None) -> None:
|
def note_object(self, name: str, objtype: str, node_id: str, location: Any = None) -> None:
|
||||||
"""Note a python object for cross reference.
|
"""Note a python object for cross reference.
|
||||||
@ -1122,15 +1131,15 @@ class PythonDomain(Domain):
|
|||||||
.. versionadded:: 2.1
|
.. versionadded:: 2.1
|
||||||
"""
|
"""
|
||||||
if name in self.objects:
|
if name in self.objects:
|
||||||
docname = self.objects[name][0]
|
other = self.objects[name]
|
||||||
logger.warning(__('duplicate object description of %s, '
|
logger.warning(__('duplicate object description of %s, '
|
||||||
'other instance in %s, use :noindex: for one of them'),
|
'other instance in %s, use :noindex: for one of them'),
|
||||||
name, docname, location=location)
|
name, other.docname, location=location)
|
||||||
self.objects[name] = (self.env.docname, node_id, objtype)
|
self.objects[name] = ObjectEntry(self.env.docname, node_id, objtype)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def modules(self) -> Dict[str, Tuple[str, str, str, str, bool]]:
|
def modules(self) -> Dict[str, ModuleEntry]:
|
||||||
return self.data.setdefault('modules', {}) # modname -> docname, node_id, synopsis, platform, deprecated # NOQA
|
return self.data.setdefault('modules', {}) # modname -> ModuleEntry
|
||||||
|
|
||||||
def note_module(self, name: str, node_id: str, synopsis: str,
|
def note_module(self, name: str, node_id: str, synopsis: str,
|
||||||
platform: str, deprecated: bool) -> None:
|
platform: str, deprecated: bool) -> None:
|
||||||
@ -1138,28 +1147,29 @@ class PythonDomain(Domain):
|
|||||||
|
|
||||||
.. versionadded:: 2.1
|
.. versionadded:: 2.1
|
||||||
"""
|
"""
|
||||||
self.modules[name] = (self.env.docname, node_id, synopsis, platform, deprecated)
|
self.modules[name] = ModuleEntry(self.env.docname, node_id,
|
||||||
|
synopsis, platform, deprecated)
|
||||||
|
|
||||||
def clear_doc(self, docname: str) -> None:
|
def clear_doc(self, docname: str) -> None:
|
||||||
for fullname, (fn, _x, _x) in list(self.objects.items()):
|
for fullname, obj in list(self.objects.items()):
|
||||||
if fn == docname:
|
if obj.docname == docname:
|
||||||
del self.objects[fullname]
|
del self.objects[fullname]
|
||||||
for modname, (fn, _x, _x, _x, _y) in list(self.modules.items()):
|
for modname, mod in list(self.modules.items()):
|
||||||
if fn == docname:
|
if mod.docname == docname:
|
||||||
del self.modules[modname]
|
del self.modules[modname]
|
||||||
|
|
||||||
def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None:
|
def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None:
|
||||||
# XXX check duplicates?
|
# XXX check duplicates?
|
||||||
for fullname, (fn, node_id, objtype) in otherdata['objects'].items():
|
for fullname, obj in otherdata['objects'].items():
|
||||||
if fn in docnames:
|
if obj.docname in docnames:
|
||||||
self.objects[fullname] = (fn, node_id, objtype)
|
self.objects[fullname] = obj
|
||||||
for modname, data in otherdata['modules'].items():
|
for modname, mod in otherdata['modules'].items():
|
||||||
if data[0] in docnames:
|
if mod.docname in docnames:
|
||||||
self.modules[modname] = data
|
self.modules[modname] = mod
|
||||||
|
|
||||||
def find_obj(self, env: BuildEnvironment, modname: str, classname: str,
|
def find_obj(self, env: BuildEnvironment, modname: str, classname: str,
|
||||||
name: str, type: str, searchmode: int = 0
|
name: str, type: str, searchmode: int = 0
|
||||||
) -> List[Tuple[str, Tuple[str, str, str]]]:
|
) -> List[Tuple[str, ObjectEntry]]:
|
||||||
"""Find a Python object for "name", perhaps using the given module
|
"""Find a Python object for "name", perhaps using the given module
|
||||||
and/or classname. Returns a list of (name, object entry) tuples.
|
and/or classname. Returns a list of (name, object entry) tuples.
|
||||||
"""
|
"""
|
||||||
@ -1170,7 +1180,7 @@ class PythonDomain(Domain):
|
|||||||
if not name:
|
if not name:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
matches = [] # type: List[Tuple[str, Tuple[str, str, str]]]
|
matches = [] # type: List[Tuple[str, ObjectEntry]]
|
||||||
|
|
||||||
newname = None
|
newname = None
|
||||||
if searchmode == 1:
|
if searchmode == 1:
|
||||||
@ -1181,20 +1191,20 @@ 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 self.objects and self.objects[fullname][2] in objtypes:
|
if fullname in self.objects and self.objects[fullname].objtype in objtypes:
|
||||||
newname = fullname
|
newname = fullname
|
||||||
if not newname:
|
if not newname:
|
||||||
if modname and modname + '.' + name in self.objects and \
|
if modname and modname + '.' + name in self.objects and \
|
||||||
self.objects[modname + '.' + name][2] in objtypes:
|
self.objects[modname + '.' + name].objtype in objtypes:
|
||||||
newname = modname + '.' + name
|
newname = modname + '.' + name
|
||||||
elif name in self.objects and self.objects[name][2] in objtypes:
|
elif name in self.objects and self.objects[name].objtype in objtypes:
|
||||||
newname = name
|
newname = name
|
||||||
else:
|
else:
|
||||||
# "fuzzy" searching mode
|
# "fuzzy" searching mode
|
||||||
searchname = '.' + name
|
searchname = '.' + name
|
||||||
matches = [(oname, self.objects[oname]) for oname in self.objects
|
matches = [(oname, self.objects[oname]) for oname in self.objects
|
||||||
if oname.endswith(searchname) and
|
if oname.endswith(searchname) and
|
||||||
self.objects[oname][2] in objtypes]
|
self.objects[oname].objtype 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 self.objects:
|
if name in self.objects:
|
||||||
@ -1262,22 +1272,23 @@ class PythonDomain(Domain):
|
|||||||
def _make_module_refnode(self, builder: Builder, fromdocname: str, name: str,
|
def _make_module_refnode(self, builder: Builder, fromdocname: str, name: str,
|
||||||
contnode: Node) -> Element:
|
contnode: Node) -> Element:
|
||||||
# get additional info for modules
|
# get additional info for modules
|
||||||
docname, node_id, synopsis, platform, deprecated = self.modules[name]
|
module = self.modules[name]
|
||||||
title = name
|
title = name
|
||||||
if synopsis:
|
if module.synopsis:
|
||||||
title += ': ' + synopsis
|
title += ': ' + module.synopsis
|
||||||
if deprecated:
|
if module.deprecated:
|
||||||
title += _(' (deprecated)')
|
title += _(' (deprecated)')
|
||||||
if platform:
|
if module.platform:
|
||||||
title += ' (' + platform + ')'
|
title += ' (' + module.platform + ')'
|
||||||
return make_refnode(builder, fromdocname, docname, node_id, contnode, title)
|
return make_refnode(builder, fromdocname, module.docname, module.node_id,
|
||||||
|
contnode, title)
|
||||||
|
|
||||||
def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
|
def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
|
||||||
for modname, info in self.modules.items():
|
for modname, mod in self.modules.items():
|
||||||
yield (modname, modname, 'module', info[0], info[1], 0)
|
yield (modname, modname, 'module', mod.docname, mod.node_id, 0)
|
||||||
for refname, (docname, node_id, type) in self.objects.items():
|
for refname, obj in self.objects.items():
|
||||||
if type != 'module': # modules are already handled
|
if obj.objtype != 'module': # modules are already handled
|
||||||
yield (refname, refname, type, docname, node_id, 1)
|
yield (refname, refname, obj.objtype, obj.docname, obj.node_id, 1)
|
||||||
|
|
||||||
def get_full_qualified_name(self, node: Element) -> str:
|
def get_full_qualified_name(self, node: Element) -> str:
|
||||||
modname = node.get('py:module')
|
modname = node.get('py:module')
|
||||||
|
Loading…
Reference in New Issue
Block a user