Merge pull request #7275 from tk0miya/refactor_pydecorator

py domain: refactor PyDecoratorFunction and PyDecoratorMethod
This commit is contained in:
Takeshi KOMIYA 2020-03-08 15:07:09 +09:00 committed by GitHub
commit a73617c51b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 20 deletions

View File

@ -41,6 +41,7 @@ Deprecated
* ``desc_signature['first']``
* ``sphinx.directives.DescDirective``
* ``sphinx.domains.std.StandardDomain.add_object()``
* ``sphinx.domains.python.PyDecoratorMixin``
* ``sphinx.parsers.Parser.app``
* ``sphinx.testing.path.Path.text()``
* ``sphinx.testing.path.Path.bytes()``

View File

@ -41,6 +41,11 @@ The following is a list of deprecated interfaces.
- 5.0
- ``sphinx.domains.std.StandardDomain.note_object()``
* - ``sphinx.domains.python.PyDecoratorMixin``
- 3.0
- 5.0
- N/A
* - ``sphinx.parsers.Parser.app``
- 3.0
- 5.0

View File

@ -25,7 +25,7 @@ from sphinx import addnodes
from sphinx.addnodes import pending_xref, desc_signature
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType, Index, IndexEntry
from sphinx.environment import BuildEnvironment
@ -489,6 +489,23 @@ class PyFunction(PyObject):
return _('%s() (built-in function)') % name
class PyDecoratorFunction(PyFunction):
"""Description of a decorator."""
def run(self) -> List[Node]:
# a decorator function is a function after all
self.name = 'py:function'
return super().run()
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
ret = super().handle_signature(sig, signode)
signode.insert(0, addnodes.desc_addname('@', '@'))
return ret
def needs_arglist(self) -> bool:
return False
class PyVariable(PyObject):
"""Description of a variable."""
@ -700,6 +717,22 @@ class PyStaticMethod(PyMethod):
return super().run()
class PyDecoratorMethod(PyMethod):
"""Description of a decoratormethod."""
def run(self) -> List[Node]:
self.name = 'py:method'
return super().run()
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
ret = super().handle_signature(sig, signode)
signode.insert(0, addnodes.desc_addname('@', '@'))
return ret
def needs_arglist(self) -> bool:
return False
class PyAttribute(PyObject):
"""Description of an attribute."""
@ -742,6 +775,15 @@ class PyDecoratorMixin:
Mixin for decorator directives.
"""
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
for cls in self.__class__.__mro__:
if cls.__name__ != 'DirectiveAdapter':
warnings.warn('PyDecoratorMixin is deprecated. '
'Please check the implementation of %s' % cls,
RemovedInSphinx50Warning)
break
else:
warnings.warn('PyDecoratorMixin is deprecated', RemovedInSphinx50Warning)
ret = super().handle_signature(sig, signode) # type: ignore
signode.insert(0, addnodes.desc_addname('@', '@'))
return ret
@ -750,25 +792,6 @@ class PyDecoratorMixin:
return False
class PyDecoratorFunction(PyDecoratorMixin, PyModulelevel):
"""
Directive to mark functions meant to be used as decorators.
"""
def run(self) -> List[Node]:
# a decorator function is a function after all
self.name = 'py:function'
return super().run()
class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
"""
Directive to mark methods meant to be used as decorators.
"""
def run(self) -> List[Node]:
self.name = 'py:method'
return super().run()
class PyModule(SphinxDirective):
"""
Directive to mark description of a new module.

View File

@ -585,6 +585,36 @@ def test_pyattribute(app):
assert domain.objects['Class.attr'] == ('index', 'class-attr', 'attribute')
def test_pydecorator_signature(app):
text = ".. py:decorator:: deco"
domain = app.env.get_domain('py')
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_addname, "@"],
[desc_name, "deco"])],
desc_content)]))
assert_node(doctree[1], addnodes.desc, desctype="function",
domain="py", objtype="function", noindex=False)
assert 'deco' in domain.objects
assert domain.objects['deco'] == ('index', 'deco', 'function')
def test_pydecoratormethod_signature(app):
text = ".. py:decoratormethod:: deco"
domain = app.env.get_domain('py')
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_addname, "@"],
[desc_name, "deco"])],
desc_content)]))
assert_node(doctree[1], addnodes.desc, desctype="method",
domain="py", objtype="method", noindex=False)
assert 'deco' in domain.objects
assert domain.objects['deco'] == ('index', 'deco', 'method')
@pytest.mark.sphinx(freshenv=True)
def test_module_index(app):
text = (".. py:module:: docutils\n"