mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '3.x'
This commit is contained in:
commit
62a0ee3fef
3
CHANGES
3
CHANGES
@ -66,6 +66,7 @@ Incompatible changes
|
|||||||
Deprecated
|
Deprecated
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
* ``sphinx.ext.autodoc.AttributeDocumenter.isinstanceattribute()``
|
||||||
* ``sphinx.ext.autodoc.importer.get_module_members()``
|
* ``sphinx.ext.autodoc.importer.get_module_members()``
|
||||||
|
|
||||||
Features added
|
Features added
|
||||||
@ -85,6 +86,8 @@ Bugs fixed
|
|||||||
* #8594: autodoc: empty __all__ attribute is ignored
|
* #8594: autodoc: empty __all__ attribute is ignored
|
||||||
* #8306: autosummary: mocked modules are documented as empty page when using
|
* #8306: autosummary: mocked modules are documented as empty page when using
|
||||||
:recursive: option
|
:recursive: option
|
||||||
|
* #8618: html: kbd role produces incorrect HTML when compound-key separators (-,
|
||||||
|
+ or ^) are used as keystrokes
|
||||||
* #8094: texinfo: image files on the different directory with document are not
|
* #8094: texinfo: image files on the different directory with document are not
|
||||||
copied
|
copied
|
||||||
|
|
||||||
|
@ -56,6 +56,11 @@ The following is a list of deprecated interfaces.
|
|||||||
- 6.0
|
- 6.0
|
||||||
- ``docutils.utils.smartyquotes``
|
- ``docutils.utils.smartyquotes``
|
||||||
|
|
||||||
|
* - ``sphinx.ext.autodoc.AttributeDocumenter.isinstanceattribute()``
|
||||||
|
- 3.5
|
||||||
|
- 5.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
* - ``sphinx.ext.autodoc.importer.get_module_members()``
|
* - ``sphinx.ext.autodoc.importer.get_module_members()``
|
||||||
- 3.5
|
- 3.5
|
||||||
- 5.0
|
- 5.0
|
||||||
|
@ -138,10 +138,7 @@ Coding style
|
|||||||
|
|
||||||
Please follow these guidelines when writing code for Sphinx:
|
Please follow these guidelines when writing code for Sphinx:
|
||||||
|
|
||||||
* Try to use the same code style as used in the rest of the project. See the
|
* Try to use the same code style as used in the rest of the project.
|
||||||
`Pocoo Styleguide`__ for more information.
|
|
||||||
|
|
||||||
__ http://flask.pocoo.org/docs/styleguide/
|
|
||||||
|
|
||||||
* For non-trivial changes, please update the :file:`CHANGES` file. If your
|
* For non-trivial changes, please update the :file:`CHANGES` file. If your
|
||||||
changes alter existing behavior, please document this.
|
changes alter existing behavior, please document this.
|
||||||
|
@ -60,6 +60,7 @@ filterwarnings =
|
|||||||
all
|
all
|
||||||
ignore::DeprecationWarning:docutils.io
|
ignore::DeprecationWarning:docutils.io
|
||||||
ignore::DeprecationWarning:pyximport.pyximport
|
ignore::DeprecationWarning:pyximport.pyximport
|
||||||
|
ignore::ImportWarning:importlib._bootstrap
|
||||||
markers =
|
markers =
|
||||||
apidoc
|
apidoc
|
||||||
setup_command
|
setup_command
|
||||||
|
@ -37,7 +37,7 @@ class KeyboardTransform(SphinxPostTransform):
|
|||||||
"""
|
"""
|
||||||
default_priority = 400
|
default_priority = 400
|
||||||
builders = ('html',)
|
builders = ('html',)
|
||||||
pattern = re.compile(r'(-|\+|\^|\s+)')
|
pattern = re.compile(r'(?<=.)(-|\+|\^|\s+)(?=.)')
|
||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
matcher = NodeMatcher(nodes.literal, classes=["kbd"])
|
matcher = NodeMatcher(nodes.literal, classes=["kbd"])
|
||||||
|
@ -24,8 +24,8 @@ from sphinx.application import Sphinx
|
|||||||
from sphinx.config import ENUM, Config
|
from sphinx.config import ENUM, Config
|
||||||
from sphinx.deprecation import RemovedInSphinx50Warning, RemovedInSphinx60Warning
|
from sphinx.deprecation import RemovedInSphinx50Warning, RemovedInSphinx60Warning
|
||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.ext.autodoc.importer import (ClassAttribute, get_class_members, get_object_members,
|
from sphinx.ext.autodoc.importer import (get_class_members, get_object_members, import_module,
|
||||||
import_module, import_object)
|
import_object)
|
||||||
from sphinx.ext.autodoc.mock import ismock, mock
|
from sphinx.ext.autodoc.mock import ismock, mock
|
||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
||||||
@ -1602,10 +1602,6 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
|||||||
self.add_line(' ' + _('Bases: %s') % ', '.join(bases), sourcename)
|
self.add_line(' ' + _('Bases: %s') % ', '.join(bases), sourcename)
|
||||||
|
|
||||||
def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:
|
def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:
|
||||||
def convert(m: ClassAttribute) -> ObjectMember:
|
|
||||||
"""Convert ClassAttribute object to ObjectMember."""
|
|
||||||
return ObjectMember(m.name, m.value, class_=m.class_, docstring=m.docstring)
|
|
||||||
|
|
||||||
members = get_class_members(self.object, self.objpath, self.get_attr)
|
members = get_class_members(self.object, self.objpath, self.get_attr)
|
||||||
if not want_all:
|
if not want_all:
|
||||||
if not self.options.members:
|
if not self.options.members:
|
||||||
@ -1614,15 +1610,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
|||||||
selected = []
|
selected = []
|
||||||
for name in self.options.members: # type: str
|
for name in self.options.members: # type: str
|
||||||
if name in members:
|
if name in members:
|
||||||
selected.append(convert(members[name]))
|
selected.append(members[name])
|
||||||
else:
|
else:
|
||||||
logger.warning(__('missing attribute %s in object %s') %
|
logger.warning(__('missing attribute %s in object %s') %
|
||||||
(name, self.fullname), type='autodoc')
|
(name, self.fullname), type='autodoc')
|
||||||
return False, selected
|
return False, selected
|
||||||
elif self.options.inherited_members:
|
elif self.options.inherited_members:
|
||||||
return False, [convert(m) for m in members.values()]
|
return False, list(members.values())
|
||||||
else:
|
else:
|
||||||
return False, [convert(m) for m in members.values() if m.class_ == self.object]
|
return False, [m for m in members.values() if m.class_ == self.object]
|
||||||
|
|
||||||
def get_doc(self, ignore: int = None) -> Optional[List[List[str]]]:
|
def get_doc(self, ignore: int = None) -> Optional[List[List[str]]]:
|
||||||
if self.doc_as_attr:
|
if self.doc_as_attr:
|
||||||
@ -2341,6 +2337,8 @@ class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type:
|
|||||||
|
|
||||||
def isinstanceattribute(self) -> bool:
|
def isinstanceattribute(self) -> bool:
|
||||||
"""Check the subject is an instance attribute."""
|
"""Check the subject is an instance attribute."""
|
||||||
|
warnings.warn('AttributeDocumenter.isinstanceattribute() is deprecated.',
|
||||||
|
RemovedInSphinx50Warning)
|
||||||
# uninitialized instance variable (PEP-526)
|
# uninitialized instance variable (PEP-526)
|
||||||
with mock(self.config.autodoc_mock_imports):
|
with mock(self.config.autodoc_mock_imports):
|
||||||
try:
|
try:
|
||||||
|
@ -23,6 +23,8 @@ if False:
|
|||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Type # NOQA
|
from typing import Type # NOQA
|
||||||
|
|
||||||
|
from sphinx.ext.autodoc import ObjectMember
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -233,37 +235,27 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
|
|||||||
return members
|
return members
|
||||||
|
|
||||||
|
|
||||||
class ClassAttribute:
|
|
||||||
"""The attribute of the class."""
|
|
||||||
|
|
||||||
def __init__(self, cls: Any, name: str, value: Any, docstring: Optional[str] = None):
|
|
||||||
self.class_ = cls
|
|
||||||
self.name = name
|
|
||||||
self.value = value
|
|
||||||
self.docstring = docstring
|
|
||||||
|
|
||||||
|
|
||||||
def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
|
def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
|
||||||
) -> Dict[str, ClassAttribute]:
|
) -> Dict[str, "ObjectMember"]:
|
||||||
"""Get members and attributes of target class."""
|
"""Get members and attributes of target class."""
|
||||||
from sphinx.ext.autodoc import INSTANCEATTR
|
from sphinx.ext.autodoc import INSTANCEATTR, ObjectMember
|
||||||
|
|
||||||
# the members directly defined in the class
|
# the members directly defined in the class
|
||||||
obj_dict = attrgetter(subject, '__dict__', {})
|
obj_dict = attrgetter(subject, '__dict__', {})
|
||||||
|
|
||||||
members = {} # type: Dict[str, ClassAttribute]
|
members = {} # type: Dict[str, ObjectMember]
|
||||||
|
|
||||||
# enum members
|
# enum members
|
||||||
if isenumclass(subject):
|
if isenumclass(subject):
|
||||||
for name, value in subject.__members__.items():
|
for name, value in subject.__members__.items():
|
||||||
if name not in members:
|
if name not in members:
|
||||||
members[name] = ClassAttribute(subject, name, value)
|
members[name] = ObjectMember(name, value, class_=subject)
|
||||||
|
|
||||||
superclass = subject.__mro__[1]
|
superclass = subject.__mro__[1]
|
||||||
for name in obj_dict:
|
for name in obj_dict:
|
||||||
if name not in superclass.__dict__:
|
if name not in superclass.__dict__:
|
||||||
value = safe_getattr(subject, name)
|
value = safe_getattr(subject, name)
|
||||||
members[name] = ClassAttribute(subject, name, value)
|
members[name] = ObjectMember(name, value, class_=subject)
|
||||||
|
|
||||||
# members in __slots__
|
# members in __slots__
|
||||||
try:
|
try:
|
||||||
@ -272,7 +264,8 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
|
|||||||
from sphinx.ext.autodoc import SLOTSATTR
|
from sphinx.ext.autodoc import SLOTSATTR
|
||||||
|
|
||||||
for name, docstring in __slots__.items():
|
for name, docstring in __slots__.items():
|
||||||
members[name] = ClassAttribute(subject, name, SLOTSATTR, docstring)
|
members[name] = ObjectMember(name, SLOTSATTR, class_=subject,
|
||||||
|
docstring=docstring)
|
||||||
except (AttributeError, TypeError, ValueError):
|
except (AttributeError, TypeError, ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -283,9 +276,9 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
|
|||||||
unmangled = unmangle(subject, name)
|
unmangled = unmangle(subject, name)
|
||||||
if unmangled and unmangled not in members:
|
if unmangled and unmangled not in members:
|
||||||
if name in obj_dict:
|
if name in obj_dict:
|
||||||
members[unmangled] = ClassAttribute(subject, unmangled, value)
|
members[unmangled] = ObjectMember(unmangled, value, class_=subject)
|
||||||
else:
|
else:
|
||||||
members[unmangled] = ClassAttribute(None, unmangled, value)
|
members[unmangled] = ObjectMember(unmangled, value)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -296,7 +289,7 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
|
|||||||
for name in getannotations(cls):
|
for name in getannotations(cls):
|
||||||
name = unmangle(cls, name)
|
name = unmangle(cls, name)
|
||||||
if name and name not in members:
|
if name and name not in members:
|
||||||
members[name] = ClassAttribute(cls, name, INSTANCEATTR)
|
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -308,8 +301,8 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
|
|||||||
analyzer.analyze()
|
analyzer.analyze()
|
||||||
for (ns, name), docstring in analyzer.attr_docs.items():
|
for (ns, name), docstring in analyzer.attr_docs.items():
|
||||||
if ns == qualname and name not in members:
|
if ns == qualname and name not in members:
|
||||||
members[name] = ClassAttribute(cls, name, INSTANCEATTR,
|
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls,
|
||||||
'\n'.join(docstring))
|
docstring='\n'.join(docstring))
|
||||||
except (AttributeError, PycodeError):
|
except (AttributeError, PycodeError):
|
||||||
pass
|
pass
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
@ -86,12 +86,11 @@ def setup_documenters(app: Any) -> None:
|
|||||||
DecoratorDocumenter, ExceptionDocumenter,
|
DecoratorDocumenter, ExceptionDocumenter,
|
||||||
FunctionDocumenter, MethodDocumenter, ModuleDocumenter,
|
FunctionDocumenter, MethodDocumenter, ModuleDocumenter,
|
||||||
NewTypeAttributeDocumenter, NewTypeDataDocumenter,
|
NewTypeAttributeDocumenter, NewTypeDataDocumenter,
|
||||||
PropertyDocumenter, SingledispatchFunctionDocumenter)
|
PropertyDocumenter)
|
||||||
documenters = [
|
documenters = [
|
||||||
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
|
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
|
||||||
FunctionDocumenter, MethodDocumenter, NewTypeAttributeDocumenter,
|
FunctionDocumenter, MethodDocumenter, NewTypeAttributeDocumenter,
|
||||||
NewTypeDataDocumenter, AttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
|
NewTypeDataDocumenter, AttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
|
||||||
SingledispatchFunctionDocumenter,
|
|
||||||
] # type: List[Type[Documenter]]
|
] # type: List[Type[Documenter]]
|
||||||
for documenter in documenters:
|
for documenter in documenters:
|
||||||
app.registry.add_documenter(documenter.objtype, documenter)
|
app.registry.add_documenter(documenter.objtype, documenter)
|
||||||
|
@ -251,6 +251,17 @@ def get_verifier(verify, verify_re):
|
|||||||
'</kbd></p>'),
|
'</kbd></p>'),
|
||||||
'\\sphinxkeyboard{\\sphinxupquote{Control+X}}',
|
'\\sphinxkeyboard{\\sphinxupquote{Control+X}}',
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
# kbd role
|
||||||
|
'verify',
|
||||||
|
':kbd:`Alt+^`',
|
||||||
|
('<p><kbd class="kbd docutils literal notranslate">'
|
||||||
|
'<kbd class="kbd docutils literal notranslate">Alt</kbd>'
|
||||||
|
'+'
|
||||||
|
'<kbd class="kbd docutils literal notranslate">^</kbd>'
|
||||||
|
'</kbd></p>'),
|
||||||
|
'\\sphinxkeyboard{\\sphinxupquote{Alt+\\textasciicircum{}}}',
|
||||||
|
),
|
||||||
(
|
(
|
||||||
# kbd role
|
# kbd role
|
||||||
'verify',
|
'verify',
|
||||||
@ -266,6 +277,13 @@ def get_verifier(verify, verify_re):
|
|||||||
'</kbd></p>'),
|
'</kbd></p>'),
|
||||||
'\\sphinxkeyboard{\\sphinxupquote{M\\sphinxhyphen{}x M\\sphinxhyphen{}s}}',
|
'\\sphinxkeyboard{\\sphinxupquote{M\\sphinxhyphen{}x M\\sphinxhyphen{}s}}',
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
# kbd role
|
||||||
|
'verify',
|
||||||
|
':kbd:`-`',
|
||||||
|
'<p><kbd class="kbd docutils literal notranslate">-</kbd></p>',
|
||||||
|
'\\sphinxkeyboard{\\sphinxupquote{\\sphinxhyphen{}}}',
|
||||||
|
),
|
||||||
(
|
(
|
||||||
# non-interpolation of dashes in option role
|
# non-interpolation of dashes in option role
|
||||||
'verify_re',
|
'verify_re',
|
||||||
|
2
tox.ini
2
tox.ini
@ -23,7 +23,7 @@ deps =
|
|||||||
extras =
|
extras =
|
||||||
test
|
test
|
||||||
setenv =
|
setenv =
|
||||||
PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils
|
PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils,ignore::DeprecationWarning:pip._vendor.packaging.version
|
||||||
PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:} --color yes
|
PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:} --color yes
|
||||||
commands=
|
commands=
|
||||||
python -X dev -m pytest --durations 25 {posargs}
|
python -X dev -m pytest --durations 25 {posargs}
|
||||||
|
Loading…
Reference in New Issue
Block a user