sphinx/tests/test_domains/test_domain_py_fields.py

591 lines
17 KiB
Python

"""Tests the Python Domain"""
from __future__ import annotations
import pytest
from docutils import nodes
from sphinx import addnodes
from sphinx.addnodes import (
desc,
desc_addname,
desc_annotation,
desc_content,
desc_name,
desc_sig_keyword,
desc_sig_punctuation,
desc_sig_space,
desc_signature,
pending_xref,
)
from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node
@pytest.mark.sphinx('html', testroot='root')
def test_info_field_list(app):
text = (
'.. py:module:: example\n'
'.. py:class:: Class\n'
'\n'
' :meta blah: this meta-field must not show up in the toc-tree\n'
' :param str name: blah blah\n'
' :meta another meta field:\n'
' :param age: blah blah\n'
' :type age: int\n'
' :param items: blah blah\n'
' :type items: Tuple[str, ...]\n'
' :param Dict[str, str] params: blah blah\n'
)
doctree = restructuredtext.parse(app, text)
print(doctree)
assert_node(
doctree,
(
addnodes.index,
addnodes.index,
nodes.target,
[
desc,
(
[
desc_signature,
(
[
desc_annotation,
([desc_sig_keyword, 'class'], desc_sig_space),
],
[desc_addname, 'example.'],
[desc_name, 'Class'],
),
],
[desc_content, nodes.field_list, nodes.field],
),
],
),
)
assert_node(
doctree[3][1][0][0],
(
[nodes.field_name, 'Parameters'],
[
nodes.field_body,
nodes.bullet_list,
(
[nodes.list_item, nodes.paragraph],
[nodes.list_item, nodes.paragraph],
[nodes.list_item, nodes.paragraph],
[nodes.list_item, nodes.paragraph],
),
],
),
)
# :param str name:
assert_node(
doctree[3][1][0][0][1][0][0][0],
(
[addnodes.literal_strong, 'name'],
' (',
[pending_xref, addnodes.literal_emphasis, 'str'],
')',
' -- ',
'blah blah',
),
)
assert_node(
doctree[3][1][0][0][1][0][0][0][2],
pending_xref,
refdomain='py',
reftype='class',
reftarget='str',
**{'py:module': 'example', 'py:class': 'Class'},
)
# :param age: + :type age:
assert_node(
doctree[3][1][0][0][1][0][1][0],
(
[addnodes.literal_strong, 'age'],
' (',
[pending_xref, addnodes.literal_emphasis, 'int'],
')',
' -- ',
'blah blah',
),
)
assert_node(
doctree[3][1][0][0][1][0][1][0][2],
pending_xref,
refdomain='py',
reftype='class',
reftarget='int',
**{'py:module': 'example', 'py:class': 'Class'},
)
# :param items: + :type items:
assert_node(
doctree[3][1][0][0][1][0][2][0],
(
[addnodes.literal_strong, 'items'],
' (',
[pending_xref, addnodes.literal_emphasis, 'Tuple'],
[addnodes.literal_emphasis, '['],
[pending_xref, addnodes.literal_emphasis, 'str'],
[addnodes.literal_emphasis, ', '],
[addnodes.literal_emphasis, '...'],
[addnodes.literal_emphasis, ']'],
')',
' -- ',
'blah blah',
),
)
assert_node(
doctree[3][1][0][0][1][0][2][0][2],
pending_xref,
refdomain='py',
reftype='class',
reftarget='Tuple',
**{'py:module': 'example', 'py:class': 'Class'},
)
assert_node(
doctree[3][1][0][0][1][0][2][0][4],
pending_xref,
refdomain='py',
reftype='class',
reftarget='str',
**{'py:module': 'example', 'py:class': 'Class'},
)
# :param Dict[str, str] params:
assert_node(
doctree[3][1][0][0][1][0][3][0],
(
[addnodes.literal_strong, 'params'],
' (',
[pending_xref, addnodes.literal_emphasis, 'Dict'],
[addnodes.literal_emphasis, '['],
[pending_xref, addnodes.literal_emphasis, 'str'],
[addnodes.literal_emphasis, ', '],
[pending_xref, addnodes.literal_emphasis, 'str'],
[addnodes.literal_emphasis, ']'],
')',
' -- ',
'blah blah',
),
)
assert_node(
doctree[3][1][0][0][1][0][3][0][2],
pending_xref,
refdomain='py',
reftype='class',
reftarget='Dict',
**{'py:module': 'example', 'py:class': 'Class'},
)
assert_node(
doctree[3][1][0][0][1][0][3][0][4],
pending_xref,
refdomain='py',
reftype='class',
reftarget='str',
**{'py:module': 'example', 'py:class': 'Class'},
)
assert_node(
doctree[3][1][0][0][1][0][3][0][6],
pending_xref,
refdomain='py',
reftype='class',
reftarget='str',
**{'py:module': 'example', 'py:class': 'Class'},
)
@pytest.mark.sphinx('html', testroot='root')
def test_info_field_list_piped_type(app):
text = (
'.. py:module:: example\n'
'.. py:class:: Class\n'
'\n'
' :param age: blah blah\n'
' :type age: int | str\n'
)
doctree = restructuredtext.parse(app, text)
assert_node(
doctree,
(
addnodes.index,
addnodes.index,
nodes.target,
[
desc,
(
[
desc_signature,
(
[
desc_annotation,
([desc_sig_keyword, 'class'], desc_sig_space),
],
[desc_addname, 'example.'],
[desc_name, 'Class'],
),
],
[
desc_content,
nodes.field_list,
nodes.field,
(nodes.field_name, nodes.field_body),
],
),
],
),
)
assert_node(
doctree[3][1][0][0][1],
(
[
nodes.paragraph,
(
[addnodes.literal_strong, 'age'],
' (',
[pending_xref, addnodes.literal_emphasis, 'int'],
[addnodes.literal_emphasis, ' | '],
[pending_xref, addnodes.literal_emphasis, 'str'],
')',
' -- ',
'blah blah',
),
],
),
)
assert_node(
doctree[3][1][0][0][1][0][2],
pending_xref,
refdomain='py',
reftype='class',
reftarget='int',
**{'py:module': 'example', 'py:class': 'Class'},
)
assert_node(
doctree[3][1][0][0][1][0][4],
pending_xref,
refdomain='py',
reftype='class',
reftarget='str',
**{'py:module': 'example', 'py:class': 'Class'},
)
@pytest.mark.sphinx('html', testroot='root')
def test_info_field_list_Literal(app):
text = (
'.. py:module:: example\n'
'.. py:class:: Class\n'
'\n'
' :param age: blah blah\n'
" :type age: Literal['foo', 'bar', 'baz']\n"
)
doctree = restructuredtext.parse(app, text)
assert_node(
doctree,
(
addnodes.index,
addnodes.index,
nodes.target,
[
desc,
(
[
desc_signature,
(
[
desc_annotation,
([desc_sig_keyword, 'class'], desc_sig_space),
],
[desc_addname, 'example.'],
[desc_name, 'Class'],
),
],
[
desc_content,
nodes.field_list,
nodes.field,
(nodes.field_name, nodes.field_body),
],
),
],
),
)
assert_node(
doctree[3][1][0][0][1],
(
[
nodes.paragraph,
(
[addnodes.literal_strong, 'age'],
' (',
[pending_xref, addnodes.literal_emphasis, 'Literal'],
[addnodes.literal_emphasis, '['],
[addnodes.literal_emphasis, "'foo'"],
[addnodes.literal_emphasis, ', '],
[addnodes.literal_emphasis, "'bar'"],
[addnodes.literal_emphasis, ', '],
[addnodes.literal_emphasis, "'baz'"],
[addnodes.literal_emphasis, ']'],
')',
' -- ',
'blah blah',
),
],
),
)
assert_node(
doctree[3][1][0][0][1][0][2],
pending_xref,
refdomain='py',
reftype='class',
reftarget='Literal',
**{'py:module': 'example', 'py:class': 'Class'},
)
@pytest.mark.sphinx('html', testroot='root')
def test_info_field_list_var(app):
text = '.. py:class:: Class\n\n :var int attr: blah blah\n'
doctree = restructuredtext.parse(app, text)
assert_node(
doctree,
(
addnodes.index,
[desc, (desc_signature, [desc_content, nodes.field_list, nodes.field])],
),
)
assert_node(
doctree[1][1][0][0],
([nodes.field_name, 'Variables'], [nodes.field_body, nodes.paragraph]),
)
# :var int attr:
assert_node(
doctree[1][1][0][0][1][0],
(
[addnodes.literal_strong, 'attr'],
' (',
[pending_xref, addnodes.literal_emphasis, 'int'],
')',
' -- ',
'blah blah',
),
)
assert_node(
doctree[1][1][0][0][1][0][2],
pending_xref,
refdomain='py',
reftype='class',
reftarget='int',
**{'py:class': 'Class'},
)
@pytest.mark.sphinx('html', testroot='root')
def test_info_field_list_napoleon_deliminator_of(app):
text = (
'.. py:module:: example\n'
'.. py:class:: Class\n'
'\n'
' :param list_str_var: example description.\n'
' :type list_str_var: list of str\n'
' :param tuple_int_var: example description.\n'
' :type tuple_int_var: tuple of tuple of int\n'
)
doctree = restructuredtext.parse(app, text)
# :param list of str list_str_var:
assert_node(
doctree[3][1][0][0][1][0][0][0],
(
[addnodes.literal_strong, 'list_str_var'],
' (',
[pending_xref, addnodes.literal_emphasis, 'list'],
[addnodes.literal_emphasis, ' of '],
[pending_xref, addnodes.literal_emphasis, 'str'],
')',
' -- ',
'example description.',
),
)
# :param tuple of tuple of int tuple_int_var:
assert_node(
doctree[3][1][0][0][1][0][1][0],
(
[addnodes.literal_strong, 'tuple_int_var'],
' (',
[pending_xref, addnodes.literal_emphasis, 'tuple'],
[addnodes.literal_emphasis, ' of '],
[pending_xref, addnodes.literal_emphasis, 'tuple'],
[addnodes.literal_emphasis, ' of '],
[pending_xref, addnodes.literal_emphasis, 'int'],
')',
' -- ',
'example description.',
),
)
@pytest.mark.sphinx('html', testroot='root')
def test_info_field_list_napoleon_deliminator_or(app):
text = (
'.. py:module:: example\n'
'.. py:class:: Class\n'
'\n'
' :param bool_str_var: example description.\n'
' :type bool_str_var: bool or str\n'
' :param str_float_int_var: example description.\n'
' :type str_float_int_var: str or float or int\n'
)
doctree = restructuredtext.parse(app, text)
# :param bool or str bool_str_var:
assert_node(
doctree[3][1][0][0][1][0][0][0],
(
[addnodes.literal_strong, 'bool_str_var'],
' (',
[pending_xref, addnodes.literal_emphasis, 'bool'],
[addnodes.literal_emphasis, ' or '],
[pending_xref, addnodes.literal_emphasis, 'str'],
')',
' -- ',
'example description.',
),
)
# :param str or float or int str_float_int_var:
assert_node(
doctree[3][1][0][0][1][0][1][0],
(
[addnodes.literal_strong, 'str_float_int_var'],
' (',
[pending_xref, addnodes.literal_emphasis, 'str'],
[addnodes.literal_emphasis, ' or '],
[pending_xref, addnodes.literal_emphasis, 'float'],
[addnodes.literal_emphasis, ' or '],
[pending_xref, addnodes.literal_emphasis, 'int'],
')',
' -- ',
'example description.',
),
)
@pytest.mark.sphinx('html', testroot='root')
def test_type_field(app):
text = (
'.. py:data:: var1\n'
' :type: .int\n'
'.. py:data:: var2\n'
' :type: ~builtins.int\n'
'.. py:data:: var3\n'
' :type: typing.Optional[typing.Tuple[int, typing.Any]]\n'
)
doctree = restructuredtext.parse(app, text)
assert_node(
doctree,
(
addnodes.index,
[
desc,
(
[
desc_signature,
(
[desc_name, 'var1'],
[
desc_annotation,
(
[desc_sig_punctuation, ':'],
desc_sig_space,
[pending_xref, 'int'],
),
],
),
],
[desc_content, ()],
),
],
addnodes.index,
[
desc,
(
[
desc_signature,
(
[desc_name, 'var2'],
[
desc_annotation,
(
[desc_sig_punctuation, ':'],
desc_sig_space,
[pending_xref, 'int'],
),
],
),
],
[desc_content, ()],
),
],
addnodes.index,
[
desc,
(
[
desc_signature,
(
[desc_name, 'var3'],
[
desc_annotation,
(
[desc_sig_punctuation, ':'],
desc_sig_space,
[pending_xref, 'Optional'],
[desc_sig_punctuation, '['],
[pending_xref, 'Tuple'],
[desc_sig_punctuation, '['],
[pending_xref, 'int'],
[desc_sig_punctuation, ','],
desc_sig_space,
[pending_xref, 'Any'],
[desc_sig_punctuation, ']'],
[desc_sig_punctuation, ']'],
),
],
),
],
[desc_content, ()],
),
],
),
)
assert_node(doctree[1][0][1][2], pending_xref, reftarget='int', refspecific=True)
assert_node(
doctree[3][0][1][2], pending_xref, reftarget='builtins.int', refspecific=False
)
assert_node(
doctree[5][0][1][2],
pending_xref,
reftarget='typing.Optional',
refspecific=False,
)
assert_node(
doctree[5][0][1][4], pending_xref, reftarget='typing.Tuple', refspecific=False
)
assert_node(doctree[5][0][1][6], pending_xref, reftarget='int', refspecific=False)
assert_node(
doctree[5][0][1][9], pending_xref, reftarget='typing.Any', refspecific=False
)