Merge branch '3.x'

This commit is contained in:
Takeshi KOMIYA 2020-12-31 14:33:09 +09:00
commit 62a0ee3fef
10 changed files with 52 additions and 38 deletions

View File

@ -66,6 +66,7 @@ Incompatible changes
Deprecated
----------
* ``sphinx.ext.autodoc.AttributeDocumenter.isinstanceattribute()``
* ``sphinx.ext.autodoc.importer.get_module_members()``
Features added
@ -85,6 +86,8 @@ Bugs fixed
* #8594: autodoc: empty __all__ attribute is ignored
* #8306: autosummary: mocked modules are documented as empty page when using
: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
copied

View File

@ -56,6 +56,11 @@ The following is a list of deprecated interfaces.
- 6.0
- ``docutils.utils.smartyquotes``
* - ``sphinx.ext.autodoc.AttributeDocumenter.isinstanceattribute()``
- 3.5
- 5.0
- N/A
* - ``sphinx.ext.autodoc.importer.get_module_members()``
- 3.5
- 5.0

View File

@ -138,10 +138,7 @@ Coding style
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
`Pocoo Styleguide`__ for more information.
__ http://flask.pocoo.org/docs/styleguide/
* Try to use the same code style as used in the rest of the project.
* For non-trivial changes, please update the :file:`CHANGES` file. If your
changes alter existing behavior, please document this.

View File

@ -60,6 +60,7 @@ filterwarnings =
all
ignore::DeprecationWarning:docutils.io
ignore::DeprecationWarning:pyximport.pyximport
ignore::ImportWarning:importlib._bootstrap
markers =
apidoc
setup_command

View File

@ -37,7 +37,7 @@ class KeyboardTransform(SphinxPostTransform):
"""
default_priority = 400
builders = ('html',)
pattern = re.compile(r'(-|\+|\^|\s+)')
pattern = re.compile(r'(?<=.)(-|\+|\^|\s+)(?=.)')
def run(self, **kwargs: Any) -> None:
matcher = NodeMatcher(nodes.literal, classes=["kbd"])

View File

@ -24,8 +24,8 @@ from sphinx.application import Sphinx
from sphinx.config import ENUM, Config
from sphinx.deprecation import RemovedInSphinx50Warning, RemovedInSphinx60Warning
from sphinx.environment import BuildEnvironment
from sphinx.ext.autodoc.importer import (ClassAttribute, get_class_members, get_object_members,
import_module, import_object)
from sphinx.ext.autodoc.importer import (get_class_members, get_object_members, import_module,
import_object)
from sphinx.ext.autodoc.mock import ismock, mock
from sphinx.locale import _, __
from sphinx.pycode import ModuleAnalyzer, PycodeError
@ -1602,10 +1602,6 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
self.add_line(' ' + _('Bases: %s') % ', '.join(bases), sourcename)
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)
if not want_all:
if not self.options.members:
@ -1614,15 +1610,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
selected = []
for name in self.options.members: # type: str
if name in members:
selected.append(convert(members[name]))
selected.append(members[name])
else:
logger.warning(__('missing attribute %s in object %s') %
(name, self.fullname), type='autodoc')
return False, selected
elif self.options.inherited_members:
return False, [convert(m) for m in members.values()]
return False, list(members.values())
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]]]:
if self.doc_as_attr:
@ -2341,6 +2337,8 @@ class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type:
def isinstanceattribute(self) -> bool:
"""Check the subject is an instance attribute."""
warnings.warn('AttributeDocumenter.isinstanceattribute() is deprecated.',
RemovedInSphinx50Warning)
# uninitialized instance variable (PEP-526)
with mock(self.config.autodoc_mock_imports):
try:

View File

@ -23,6 +23,8 @@ if False:
# For type annotation
from typing import Type # NOQA
from sphinx.ext.autodoc import ObjectMember
logger = logging.getLogger(__name__)
@ -233,37 +235,27 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
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
) -> Dict[str, ClassAttribute]:
) -> Dict[str, "ObjectMember"]:
"""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
obj_dict = attrgetter(subject, '__dict__', {})
members = {} # type: Dict[str, ClassAttribute]
members = {} # type: Dict[str, ObjectMember]
# enum members
if isenumclass(subject):
for name, value in subject.__members__.items():
if name not in members:
members[name] = ClassAttribute(subject, name, value)
members[name] = ObjectMember(name, value, class_=subject)
superclass = subject.__mro__[1]
for name in obj_dict:
if name not in superclass.__dict__:
value = safe_getattr(subject, name)
members[name] = ClassAttribute(subject, name, value)
members[name] = ObjectMember(name, value, class_=subject)
# members in __slots__
try:
@ -272,7 +264,8 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
from sphinx.ext.autodoc import SLOTSATTR
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):
pass
@ -283,9 +276,9 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
unmangled = unmangle(subject, name)
if unmangled and unmangled not in members:
if name in obj_dict:
members[unmangled] = ClassAttribute(subject, unmangled, value)
members[unmangled] = ObjectMember(unmangled, value, class_=subject)
else:
members[unmangled] = ClassAttribute(None, unmangled, value)
members[unmangled] = ObjectMember(unmangled, value)
except AttributeError:
continue
@ -296,7 +289,7 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
for name in getannotations(cls):
name = unmangle(cls, name)
if name and name not in members:
members[name] = ClassAttribute(cls, name, INSTANCEATTR)
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls)
except AttributeError:
pass
@ -308,8 +301,8 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
analyzer.analyze()
for (ns, name), docstring in analyzer.attr_docs.items():
if ns == qualname and name not in members:
members[name] = ClassAttribute(cls, name, INSTANCEATTR,
'\n'.join(docstring))
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls,
docstring='\n'.join(docstring))
except (AttributeError, PycodeError):
pass
except AttributeError:

View File

@ -86,12 +86,11 @@ def setup_documenters(app: Any) -> None:
DecoratorDocumenter, ExceptionDocumenter,
FunctionDocumenter, MethodDocumenter, ModuleDocumenter,
NewTypeAttributeDocumenter, NewTypeDataDocumenter,
PropertyDocumenter, SingledispatchFunctionDocumenter)
PropertyDocumenter)
documenters = [
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
FunctionDocumenter, MethodDocumenter, NewTypeAttributeDocumenter,
NewTypeDataDocumenter, AttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
SingledispatchFunctionDocumenter,
] # type: List[Type[Documenter]]
for documenter in documenters:
app.registry.add_documenter(documenter.objtype, documenter)

View File

@ -251,6 +251,17 @@ def get_verifier(verify, verify_re):
'</kbd></p>'),
'\\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
'verify',
@ -266,6 +277,13 @@ def get_verifier(verify, verify_re):
'</kbd></p>'),
'\\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
'verify_re',

View File

@ -23,7 +23,7 @@ deps =
extras =
test
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
commands=
python -X dev -m pytest --durations 25 {posargs}