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 * SphinxTranslator now calls visitor/departure method for super node class if
visitor/departure method for original node class not found visitor/departure method for original node class not found
* #6418: Add new event: :event:`object-description-transform` * #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 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 as "defined constants." Class and object attributes are not documented
using this environment. 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 .. rst:directive:: .. py:exception:: name
Describes an exception class. The signature can, but need not include 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 information about the type of the data to be expected and whether it may be
changed directly. 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) .. rst:directive:: .. py:method:: name(parameters)
Describes an object method. The parameters should not include the ``self`` Describes an object method. The parameters should not include the ``self``

View File

@ -446,6 +446,25 @@ class PyFunction(PyObject):
class PyVariable(PyObject): class PyVariable(PyObject):
"""Description of a variable.""" """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: def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
name, cls = name_cls name, cls = name_cls
if modname: if modname:
@ -638,6 +657,25 @@ class PyStaticMethod(PyMethod):
class PyAttribute(PyObject): class PyAttribute(PyObject):
"""Description of an attribute.""" """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: def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
name, cls = name_cls name, cls = name_cls
try: try:

View File

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