mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add `py:type` directive and role for documenting type aliases (#11989)
Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
@@ -92,19 +92,21 @@ def test_domain_py_xrefs(app, status, warning):
|
||||
refnodes = list(doctree.findall(pending_xref))
|
||||
assert_refnode(refnodes[0], None, None, 'TopLevel', 'class')
|
||||
assert_refnode(refnodes[1], None, None, 'top_level', 'meth')
|
||||
assert_refnode(refnodes[2], None, 'NestedParentA', 'child_1', 'meth')
|
||||
assert_refnode(refnodes[3], None, 'NestedParentA', 'NestedChildA.subchild_2', 'meth')
|
||||
assert_refnode(refnodes[4], None, 'NestedParentA', 'child_2', 'meth')
|
||||
assert_refnode(refnodes[5], False, 'NestedParentA', 'any_child', domain='')
|
||||
assert_refnode(refnodes[6], None, 'NestedParentA', 'NestedChildA', 'class')
|
||||
assert_refnode(refnodes[7], None, 'NestedParentA.NestedChildA', 'subchild_2', 'meth')
|
||||
assert_refnode(refnodes[8], None, 'NestedParentA.NestedChildA',
|
||||
assert_refnode(refnodes[2], None, None, 'TopLevelType', 'type')
|
||||
assert_refnode(refnodes[3], None, 'NestedParentA', 'child_1', 'meth')
|
||||
assert_refnode(refnodes[4], None, 'NestedParentA', 'NestedChildA.subchild_2', 'meth')
|
||||
assert_refnode(refnodes[5], None, 'NestedParentA', 'child_2', 'meth')
|
||||
assert_refnode(refnodes[6], False, 'NestedParentA', 'any_child', domain='')
|
||||
assert_refnode(refnodes[7], None, 'NestedParentA', 'NestedChildA', 'class')
|
||||
assert_refnode(refnodes[8], None, 'NestedParentA.NestedChildA', 'subchild_2', 'meth')
|
||||
assert_refnode(refnodes[9], None, 'NestedParentA.NestedChildA',
|
||||
'NestedParentA.child_1', 'meth')
|
||||
assert_refnode(refnodes[9], None, 'NestedParentA', 'NestedChildA.subchild_1', 'meth')
|
||||
assert_refnode(refnodes[10], None, 'NestedParentB', 'child_1', 'meth')
|
||||
assert_refnode(refnodes[11], None, 'NestedParentB', 'NestedParentB', 'class')
|
||||
assert_refnode(refnodes[12], None, None, 'NestedParentA.NestedChildA', 'class')
|
||||
assert len(refnodes) == 13
|
||||
assert_refnode(refnodes[10], None, 'NestedParentA', 'NestedChildA.subchild_1', 'meth')
|
||||
assert_refnode(refnodes[11], None, 'NestedParentB', 'child_1', 'meth')
|
||||
assert_refnode(refnodes[12], None, 'NestedParentB', 'NestedParentB', 'class')
|
||||
assert_refnode(refnodes[13], None, None, 'NestedParentA.NestedChildA', 'class')
|
||||
assert_refnode(refnodes[14], None, None, 'NestedParentA.NestedTypeA', 'type')
|
||||
assert len(refnodes) == 15
|
||||
|
||||
doctree = app.env.get_doctree('module')
|
||||
refnodes = list(doctree.findall(pending_xref))
|
||||
@@ -135,7 +137,10 @@ def test_domain_py_xrefs(app, status, warning):
|
||||
assert_refnode(refnodes[15], False, False, 'index', 'doc', domain='std')
|
||||
assert_refnode(refnodes[16], False, False, 'typing.Literal', 'obj', domain='py')
|
||||
assert_refnode(refnodes[17], False, False, 'typing.Literal', 'obj', domain='py')
|
||||
assert len(refnodes) == 18
|
||||
assert_refnode(refnodes[18], False, False, 'list', 'class', domain='py')
|
||||
assert_refnode(refnodes[19], False, False, 'int', 'class', domain='py')
|
||||
assert_refnode(refnodes[20], False, False, 'str', 'class', domain='py')
|
||||
assert len(refnodes) == 21
|
||||
|
||||
doctree = app.env.get_doctree('module_option')
|
||||
refnodes = list(doctree.findall(pending_xref))
|
||||
@@ -191,7 +196,9 @@ def test_domain_py_objects(app, status, warning):
|
||||
|
||||
assert objects['TopLevel'][2] == 'class'
|
||||
assert objects['top_level'][2] == 'method'
|
||||
assert objects['TopLevelType'][2] == 'type'
|
||||
assert objects['NestedParentA'][2] == 'class'
|
||||
assert objects['NestedParentA.NestedTypeA'][2] == 'type'
|
||||
assert objects['NestedParentA.child_1'][2] == 'method'
|
||||
assert objects['NestedParentA.any_child'][2] == 'method'
|
||||
assert objects['NestedParentA.NestedChildA'][2] == 'class'
|
||||
@@ -233,6 +240,9 @@ def test_domain_py_find_obj(app, status, warning):
|
||||
assert (find_obj(None, None, 'NONEXISTANT', 'class') == [])
|
||||
assert (find_obj(None, None, 'NestedParentA', 'class') ==
|
||||
[('NestedParentA', ('roles', 'NestedParentA', 'class', False))])
|
||||
assert (find_obj(None, None, 'NestedParentA.NestedTypeA', 'type') ==
|
||||
[('NestedParentA.NestedTypeA',
|
||||
('roles', 'NestedParentA.NestedTypeA', 'type', False))])
|
||||
assert (find_obj(None, None, 'NestedParentA.NestedChildA', 'class') ==
|
||||
[('NestedParentA.NestedChildA',
|
||||
('roles', 'NestedParentA.NestedChildA', 'class', False))])
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx import addnodes
|
||||
@@ -362,6 +363,76 @@ def test_pyproperty(app):
|
||||
assert domain.objects['Class.prop2'] == ('index', 'Class.prop2', 'property', False)
|
||||
|
||||
|
||||
def test_py_type_alias(app):
|
||||
text = (".. py:module:: example\n"
|
||||
".. py:type:: Alias1\n"
|
||||
" :canonical: list[str | int]\n"
|
||||
"\n"
|
||||
".. py:class:: Class\n"
|
||||
"\n"
|
||||
" .. py:type:: Alias2\n"
|
||||
" :canonical: int\n")
|
||||
domain = app.env.get_domain('py')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
[desc, ([desc_signature, ([desc_annotation, ('type', desc_sig_space)],
|
||||
[desc_addname, 'example.'],
|
||||
[desc_name, 'Alias1'],
|
||||
[desc_annotation, (desc_sig_space,
|
||||
[desc_sig_punctuation, '='],
|
||||
desc_sig_space,
|
||||
[pending_xref, 'list'],
|
||||
[desc_sig_punctuation, '['],
|
||||
[pending_xref, 'str'],
|
||||
desc_sig_space,
|
||||
[desc_sig_punctuation, '|'],
|
||||
desc_sig_space,
|
||||
[pending_xref, 'int'],
|
||||
[desc_sig_punctuation, ']'],
|
||||
)])],
|
||||
[desc_content, ()])],
|
||||
addnodes.index,
|
||||
[desc, ([desc_signature, ([desc_annotation, ('class', desc_sig_space)],
|
||||
[desc_addname, 'example.'],
|
||||
[desc_name, 'Class'])],
|
||||
[desc_content, (addnodes.index,
|
||||
desc)])]))
|
||||
assert_node(doctree[5][1][0], addnodes.index,
|
||||
entries=[('single', 'Alias2 (type alias in example.Class)', 'example.Class.Alias2', '', None)])
|
||||
assert_node(doctree[5][1][1], ([desc_signature, ([desc_annotation, ('type', desc_sig_space)],
|
||||
[desc_name, 'Alias2'],
|
||||
[desc_annotation, (desc_sig_space,
|
||||
[desc_sig_punctuation, '='],
|
||||
desc_sig_space,
|
||||
[pending_xref, 'int'])])],
|
||||
[desc_content, ()]))
|
||||
assert 'example.Alias1' in domain.objects
|
||||
assert domain.objects['example.Alias1'] == ('index', 'example.Alias1', 'type', False)
|
||||
assert 'example.Class.Alias2' in domain.objects
|
||||
assert domain.objects['example.Class.Alias2'] == ('index', 'example.Class.Alias2', 'type', False)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='domain-py', freshenv=True)
|
||||
def test_domain_py_type_alias(app, status, warning):
|
||||
app.build(force_all=True)
|
||||
|
||||
content = (app.outdir / 'type_alias.html').read_text(encoding='utf8')
|
||||
assert ('<em class="property"><span class="pre">type</span><span class="w"> </span></em>'
|
||||
'<span class="sig-prename descclassname"><span class="pre">module_one.</span></span>'
|
||||
'<span class="sig-name descname"><span class="pre">MyAlias</span></span>'
|
||||
'<em class="property"><span class="w"> </span><span class="p"><span class="pre">=</span></span>'
|
||||
'<span class="w"> </span><span class="pre">list</span>'
|
||||
'<span class="p"><span class="pre">[</span></span>'
|
||||
'<span class="pre">int</span><span class="w"> </span>'
|
||||
'<span class="p"><span class="pre">|</span></span><span class="w"> </span>'
|
||||
'<a class="reference internal" href="#module_two.SomeClass" title="module_two.SomeClass">'
|
||||
'<span class="pre">module_two.SomeClass</span></a>'
|
||||
'<span class="p"><span class="pre">]</span></span></em>' in content)
|
||||
assert warning.getvalue() == ''
|
||||
|
||||
|
||||
def test_pydecorator_signature(app):
|
||||
text = ".. py:decorator:: deco"
|
||||
domain = app.env.get_domain('py')
|
||||
|
||||
Reference in New Issue
Block a user