py domain: Support type annotations for variables

This adds ``:type:`` and ``:value:`` options to both ``py:data``
and ``py:attribute`` directives.  It allows to describe its
annotation in detail.
This commit is contained in:
Takeshi KOMIYA 2020-01-30 13:09:10 +09:00
parent a0a4eaad4e
commit 179a1f9cc2
4 changed files with 84 additions and 2 deletions

View File

@ -59,6 +59,8 @@ Features added
* SphinxTranslator now calls visitor/departure method for super node class if
visitor/departure method for original node class not found
* #6418: Add new event: :event:`object-description-transform`
* py domain: :rst:dir:`py:data` and :rst:dir:`py:attribute` take new options
named ``:type:`` and ``:value:`` to describe its type and initial value
Bugs fixed
----------

View File

@ -195,6 +195,18 @@ The following directives are provided for module and class contents:
as "defined constants." Class and object attributes are not documented
using this environment.
.. rubric:: options
.. rst:directive:option:: type: type of the variable
:type: text
.. versionadded:: 2.4
.. rst:directive:option:: value: initial value of the variable
:type: text
.. versionadded:: 2.4
.. rst:directive:: .. py:exception:: name
Describes an exception class. The signature can, but need not include
@ -229,6 +241,18 @@ The following directives are provided for module and class contents:
information about the type of the data to be expected and whether it may be
changed directly.
.. rubric:: options
.. rst:directive:option:: type: type of the attribute
:type: text
.. versionadded:: 2.4
.. rst:directive:option:: value: initial value of the attribute
:type: text
.. versionadded:: 2.4
.. rst:directive:: .. py:method:: name(parameters)
Describes an object method. The parameters should not include the ``self``

View File

@ -446,6 +446,25 @@ class PyFunction(PyObject):
class PyVariable(PyObject):
"""Description of a variable."""
option_spec = PyObject.option_spec.copy()
option_spec.update({
'type': directives.unchanged,
'value': directives.unchanged,
})
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
fullname, prefix = super().handle_signature(sig, signode)
typ = self.options.get('type')
if typ:
signode += addnodes.desc_annotation(typ, ': ' + typ)
value = self.options.get('value')
if value:
signode += addnodes.desc_annotation(value, ' = ' + value)
return fullname, prefix
def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
name, cls = name_cls
if modname:
@ -638,6 +657,25 @@ class PyStaticMethod(PyMethod):
class PyAttribute(PyObject):
"""Description of an attribute."""
option_spec = PyObject.option_spec.copy()
option_spec.update({
'type': directives.unchanged,
'value': directives.unchanged,
})
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
fullname, prefix = super().handle_signature(sig, signode)
typ = self.options.get('type')
if typ:
signode += addnodes.desc_annotation(typ, ': ' + typ)
value = self.options.get('value')
if value:
signode += addnodes.desc_annotation(value, ' = ' + value)
return fullname, prefix
def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
name, cls = name_cls
try:

View File

@ -267,6 +267,20 @@ def test_exceptions_module_is_ignored(app):
def test_pydata_signature(app):
text = (".. py:data:: version\n"
" :type: int\n"
" :value: 1\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_name, "version"],
[desc_annotation, ": int"],
[desc_annotation, " = 1"])],
desc_content)]))
assert_node(doctree[1], addnodes.desc, desctype="data",
domain="py", objtype="data", noindex=False)
def test_pydata_signature_old(app):
text = (".. py:data:: version\n"
" :annotation: = 1\n")
doctree = restructuredtext.parse(app, text)
@ -463,7 +477,9 @@ def test_pystaticmethod(app):
def test_pyattribute(app):
text = (".. py:class:: Class\n"
"\n"
" .. py:attribute:: attr\n")
" .. py:attribute:: attr\n"
" :type: str\n"
" :value: ''\n")
domain = app.env.get_domain('py')
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
@ -473,7 +489,9 @@ def test_pyattribute(app):
desc)])]))
assert_node(doctree[1][1][0], addnodes.index,
entries=[('single', 'attr (Class attribute)', 'Class.attr', '', None)])
assert_node(doctree[1][1][1], ([desc_signature, desc_name, "attr"],
assert_node(doctree[1][1][1], ([desc_signature, ([desc_name, "attr"],
[desc_annotation, ": str"],
[desc_annotation, " = ''"])],
[desc_content, ()]))
assert 'Class.attr' in domain.objects
assert domain.objects['Class.attr'] == ('index', 'attribute')