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']`` * ``desc_signature['first']``
* ``sphinx.directives.DescDirective`` * ``sphinx.directives.DescDirective``
* ``sphinx.domains.std.StandardDomain.add_object()`` * ``sphinx.domains.std.StandardDomain.add_object()``
* ``sphinx.domains.python.PyDecoratorMixin``
* ``sphinx.parsers.Parser.app`` * ``sphinx.parsers.Parser.app``
* ``sphinx.testing.path.Path.text()`` * ``sphinx.testing.path.Path.text()``
* ``sphinx.testing.path.Path.bytes()`` * ``sphinx.testing.path.Path.bytes()``

View File

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

View File

@ -25,7 +25,7 @@ from sphinx import addnodes
from sphinx.addnodes import pending_xref, desc_signature from sphinx.addnodes import pending_xref, desc_signature
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.deprecation import RemovedInSphinx40Warning from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.directives import ObjectDescription from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType, Index, IndexEntry from sphinx.domains import Domain, ObjType, Index, IndexEntry
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment
@ -489,6 +489,23 @@ class PyFunction(PyObject):
return _('%s() (built-in function)') % name 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): class PyVariable(PyObject):
"""Description of a variable.""" """Description of a variable."""
@ -700,6 +717,22 @@ class PyStaticMethod(PyMethod):
return super().run() 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): class PyAttribute(PyObject):
"""Description of an attribute.""" """Description of an attribute."""
@ -742,6 +775,15 @@ class PyDecoratorMixin:
Mixin for decorator directives. Mixin for decorator directives.
""" """
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]: 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 ret = super().handle_signature(sig, signode) # type: ignore
signode.insert(0, addnodes.desc_addname('@', '@')) signode.insert(0, addnodes.desc_addname('@', '@'))
return ret return ret
@ -750,25 +792,6 @@ class PyDecoratorMixin:
return False 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): class PyModule(SphinxDirective):
""" """
Directive to mark description of a new module. 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') 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) @pytest.mark.sphinx(freshenv=True)
def test_module_index(app): def test_module_index(app):
text = (".. py:module:: docutils\n" text = (".. py:module:: docutils\n"