mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2026-10-14 17:32:12 -05:00
Merge remaining special cases into `Documenter` (#13959)
This commit is contained in:
1 parent
4c89a82c1d
commit
e281d26b5e
2 files changed
+40
-79
No files matched your search
@@ -27,7 +27,7 @@ from sphinx.util.inspect import safe_getattr
|
||||
from sphinx.util.typing import AnyTypeAliasType, restify, stringify_annotation
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator, Sequence
|
||||
from collections.abc import Iterator
|
||||
from types import ModuleType
|
||||
from typing import Any, ClassVar, Literal
|
||||
|
||||
@@ -135,6 +135,16 @@ class Documenter:
|
||||
|
||||
self._load_object_has_been_called = False
|
||||
|
||||
if isinstance(self, ModuleDocumenter):
|
||||
self.options = self.options.merge_member_options()
|
||||
elif isinstance(self, ClassDocumenter):
|
||||
if self.config.autodoc_class_signature == 'separated':
|
||||
# show __init__() method
|
||||
if self.options.special_members is None:
|
||||
self.options.special_members = []
|
||||
self.options.special_members += ['__new__', '__init__']
|
||||
self.options = self.options.merge_member_options()
|
||||
|
||||
@property
|
||||
def documenters(self) -> dict[str, type[Documenter]]:
|
||||
"""Returns registered Documenter classes"""
|
||||
@@ -501,17 +511,33 @@ class Documenter:
|
||||
# sort by group; alphabetically within groups
|
||||
documenters.sort(key=lambda e: (e[0].member_order, e[0].name))
|
||||
elif order == 'bysource':
|
||||
if (
|
||||
isinstance(self, ModuleDocumenter)
|
||||
and not self.options.ignore_module_all
|
||||
and (module_all := self.props.all)
|
||||
):
|
||||
# Sort by __all__
|
||||
module_all_idx = {name: idx for idx, name in enumerate(module_all)}
|
||||
module_all_len = len(module_all)
|
||||
|
||||
def key_func(entry: tuple[Documenter, bool]) -> int:
|
||||
fullname = entry[0].name.split('::')[1]
|
||||
return module_all_idx.get(fullname, module_all_len)
|
||||
|
||||
documenters.sort(key=key_func)
|
||||
|
||||
# By default, member discovery order matches source order,
|
||||
# as dicts are insertion-ordered from Python 3.7.
|
||||
if self.analyzer:
|
||||
elif self.analyzer is not None:
|
||||
# sort by source order, by virtue of the module analyzer
|
||||
tagorder = self.analyzer.tagorder
|
||||
tagorder_len = len(tagorder)
|
||||
|
||||
def keyfunc(entry: tuple[Documenter, bool]) -> int:
|
||||
def key_func(entry: tuple[Documenter, bool]) -> int:
|
||||
fullname = entry[0].name.split('::')[1]
|
||||
return tagorder.get(fullname, len(tagorder))
|
||||
return tagorder.get(fullname, tagorder_len)
|
||||
|
||||
documenters.sort(key=keyfunc)
|
||||
documenters.sort(key=key_func)
|
||||
else: # alphabetical
|
||||
documenters.sort(key=lambda e: e[0].name)
|
||||
|
||||
@@ -532,6 +558,14 @@ class Documenter:
|
||||
True, only generate if the object is defined in the module name it is
|
||||
imported from. If *all_members* is True, document all members.
|
||||
"""
|
||||
if isinstance(self, ClassDocumenter):
|
||||
# Do not pass real_modname and use the name from the __module__
|
||||
# attribute of the class.
|
||||
# If a class gets imported into the module real_modname
|
||||
# the analyzer won't find the source of the class, if
|
||||
# it looks in real_modname.
|
||||
real_modname = None
|
||||
|
||||
if self._load_object_by_name() is None:
|
||||
return
|
||||
|
||||
@@ -759,11 +793,6 @@ class ModuleDocumenter(Documenter):
|
||||
'noindex': bool_option,
|
||||
}
|
||||
|
||||
def __init__(self, *args: Any) -> None:
|
||||
super().__init__(*args)
|
||||
self.options = self.options.merge_member_options()
|
||||
self.__all__: Sequence[str] | None = None
|
||||
|
||||
@classmethod
|
||||
def can_document_member(
|
||||
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
|
||||
@@ -771,41 +800,6 @@ class ModuleDocumenter(Documenter):
|
||||
# don't document submodules automatically
|
||||
return False
|
||||
|
||||
def _module_all(self) -> Sequence[str] | None:
|
||||
if self.__all__ is None and not self.options.ignore_module_all:
|
||||
self.__all__ = self.props.all
|
||||
return self.__all__
|
||||
|
||||
def sort_members(
|
||||
self, documenters: list[tuple[Documenter, bool]], order: str
|
||||
) -> list[tuple[Documenter, bool]]:
|
||||
module_all = self.props.all
|
||||
if (
|
||||
order == 'bysource'
|
||||
and not self.options.ignore_module_all
|
||||
and module_all is not None
|
||||
):
|
||||
assert module_all is not None
|
||||
module_all_set = frozenset(module_all)
|
||||
module_all_len = len(module_all)
|
||||
|
||||
# Sort alphabetically first (for members not listed on the __all__)
|
||||
documenters.sort(key=lambda e: e[0].name)
|
||||
|
||||
# Sort by __all__
|
||||
def keyfunc(entry: tuple[Documenter, bool]) -> int:
|
||||
name = entry[0].name.split('::')[1]
|
||||
if name in module_all_set:
|
||||
return module_all.index(name)
|
||||
else:
|
||||
return module_all_len
|
||||
|
||||
documenters.sort(key=keyfunc)
|
||||
|
||||
return documenters
|
||||
else:
|
||||
return super().sort_members(documenters, order)
|
||||
|
||||
|
||||
class FunctionDocumenter(Documenter):
|
||||
"""Specialized Documenter subclass for functions."""
|
||||
@@ -865,21 +859,6 @@ class ClassDocumenter(Documenter):
|
||||
# after Python 3.10.
|
||||
priority = 15
|
||||
|
||||
def __init__(self, *args: Any) -> None:
|
||||
super().__init__(*args)
|
||||
|
||||
if self.config.autodoc_class_signature == 'separated':
|
||||
self.options = self.options.copy()
|
||||
|
||||
# show __init__() method
|
||||
if self.options.special_members is None:
|
||||
self.options.special_members = ['__new__', '__init__']
|
||||
else:
|
||||
self.options.special_members.append('__new__')
|
||||
self.options.special_members.append('__init__')
|
||||
|
||||
self.options = self.options.merge_member_options()
|
||||
|
||||
@classmethod
|
||||
def can_document_member(
|
||||
cls: type[Documenter], member: Any, membername: str, isattr: bool, parent: Any
|
||||
@@ -904,24 +883,6 @@ class ClassDocumenter(Documenter):
|
||||
else:
|
||||
return None
|
||||
|
||||
def generate(
|
||||
self,
|
||||
more_content: StringList | None = None,
|
||||
real_modname: str | None = None,
|
||||
check_module: bool = False,
|
||||
all_members: bool = False,
|
||||
) -> None:
|
||||
# Do not pass real_modname and use the name from the __module__
|
||||
# attribute of the class.
|
||||
# If a class gets imported into the module real_modname
|
||||
# the analyzer won't find the source of the class, if
|
||||
# it looks in real_modname.
|
||||
return super().generate(
|
||||
more_content=more_content,
|
||||
check_module=check_module,
|
||||
all_members=all_members,
|
||||
)
|
||||
|
||||
|
||||
class ExceptionDocumenter(ClassDocumenter):
|
||||
"""Specialized ClassDocumenter subclass for exceptions."""
|
||||
|
||||
@@ -64,7 +64,7 @@ if TYPE_CHECKING:
|
||||
ALL = enum.auto()
|
||||
|
||||
def __contains__(self, item: object) -> Literal[True]: return True
|
||||
def append(self, item: object) -> None: pass
|
||||
def __add__(self, other: object) -> Self: pass
|
||||
ALL_T: TypeAlias = Literal[_AllTC.ALL]
|
||||
ALL: Final[ALL_T] = _AllTC.ALL
|
||||
|
||||
|
||||
Reference in new issue
Block a user