Skip to content

Commit

Permalink
Cloase sphinx-doc#9445: :py:property: directive now supports :classme…
Browse files Browse the repository at this point in the history
…thod: option

Since python 3.9, `classmethod` starts to support creating a "class
property".  This allows to describe it.
  • Loading branch information
tk0miya committed Jul 17, 2021
1 parent 939c7bb commit 1205255
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -13,6 +13,9 @@ Deprecated
Features added
--------------

* #9445: py domain: ``:py:property:`` directive supports ``:classmethod:``
option to describe the class property

Bugs fixed
----------

Expand Down
7 changes: 7 additions & 0 deletions doc/usage/restructuredtext/domains.rst
Expand Up @@ -329,6 +329,13 @@ The following directives are provided for module and class contents:
Indicate the property is abstract.
.. rst:directive:option:: classmethod
:type: no value
Indicate the property is a classmethod.
.. versionaddedd: 4.2
.. rst:directive:option:: type: type of the property
:type: text
Expand Down
8 changes: 6 additions & 2 deletions sphinx/domains/python.py
Expand Up @@ -852,6 +852,7 @@ class PyProperty(PyObject):
option_spec = PyObject.option_spec.copy()
option_spec.update({
'abstractmethod': directives.flag,
'classmethod': directives.flag,
'type': directives.unchanged,
})

Expand All @@ -865,10 +866,13 @@ def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]
return fullname, prefix

def get_signature_prefix(self, sig: str) -> str:
prefix = ['property']
prefix = []
if 'abstractmethod' in self.options:
prefix.insert(0, 'abstract')
prefix.append('abstract')
if 'classmethod' in self.options:
prefix.append('class')

prefix.append('property')
return ' '.join(prefix) + ' '

def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
Expand Down
24 changes: 19 additions & 5 deletions tests/test_domain_py.py
Expand Up @@ -813,24 +813,38 @@ def test_pyattribute(app):
def test_pyproperty(app):
text = (".. py:class:: Class\n"
"\n"
" .. py:property:: prop\n"
" .. py:property:: prop1\n"
" :abstractmethod:\n"
" :type: str\n"
"\n"
" .. py:property:: prop2\n"
" :classmethod:\n"
" :type: str\n")
domain = app.env.get_domain('py')
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_annotation, "class "],
[desc_name, "Class"])],
[desc_content, (addnodes.index,
desc,
addnodes.index,
desc)])]))
assert_node(doctree[1][1][0], addnodes.index,
entries=[('single', 'prop (Class property)', 'Class.prop', '', None)])
entries=[('single', 'prop1 (Class property)', 'Class.prop1', '', None)])
assert_node(doctree[1][1][1], ([desc_signature, ([desc_annotation, "abstract property "],
[desc_name, "prop"],
[desc_name, "prop1"],
[desc_annotation, ": str"])],
[desc_content, ()]))
assert_node(doctree[1][1][2], addnodes.index,
entries=[('single', 'prop2 (Class property)', 'Class.prop2', '', None)])
assert_node(doctree[1][1][3], ([desc_signature, ([desc_annotation, "class property "],
[desc_name, "prop2"],
[desc_annotation, ": str"])],
[desc_content, ()]))
assert 'Class.prop' in domain.objects
assert domain.objects['Class.prop'] == ('index', 'Class.prop', 'property', False)
assert 'Class.prop1' in domain.objects
assert domain.objects['Class.prop1'] == ('index', 'Class.prop1', 'property', False)
assert 'Class.prop2' in domain.objects
assert domain.objects['Class.prop2'] == ('index', 'Class.prop2', 'property', False)


def test_pydecorator_signature(app):
Expand Down

0 comments on commit 1205255

Please sign in to comment.