Skip to content

Commit

Permalink
Fix sphinx-doc#9576: py domain: Literal typehint was converted to a c…
Browse files Browse the repository at this point in the history
…ross reference

The content of Literal typehint should not be converted to cross
references.
  • Loading branch information
tk0miya committed Sep 1, 2021
1 parent 80fbbb8 commit 0469b04
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES
Expand Up @@ -40,6 +40,7 @@ Bugs fixed
* #9267: html theme: CSS and JS files added by theme were loaded twice
* #9585: py domain: ``:type:`` option for :rst:dir:`py:property` directive does
not create a hyperlink
* #9576: py domain: Literal typehint was converted to a cross reference
* #9535 comment: C++, fix parsing of defaulted function parameters that are
function pointers.
* #9564: smartquotes: don't adjust typography for text with
Expand Down
12 changes: 10 additions & 2 deletions sphinx/domains/python.py
Expand Up @@ -123,7 +123,7 @@ def unparse(node: ast.AST) -> List[Node]:
if node.value is Ellipsis:
return [addnodes.desc_sig_punctuation('', "...")]
else:
return [nodes.Text(node.value)]
return [nodes.Text(repr(node.value))]
elif isinstance(node, ast.Expr):
return unparse(node.value)
elif isinstance(node, ast.Index):
Expand All @@ -149,6 +149,12 @@ def unparse(node: ast.AST) -> List[Node]:
result.append(addnodes.desc_sig_punctuation('', '['))
result.extend(unparse(node.slice))
result.append(addnodes.desc_sig_punctuation('', ']'))

# Wrap the Text nodes inside brackets by literal node if the subscript is a Literal
if result[0] in ('Literal', 'typing.Literal'):
for i, node in enumerate(result[1:], start=1):
if isinstance(node, nodes.Text):
result[i] = nodes.literal('', '', node)
return result
elif isinstance(node, ast.Tuple):
if node.elts:
Expand Down Expand Up @@ -179,7 +185,9 @@ def unparse(node: ast.AST) -> List[Node]:
tree = ast_parse(annotation)
result = unparse(tree)
for i, node in enumerate(result):
if isinstance(node, nodes.Text) and node.strip():
if isinstance(node, nodes.literal):
result[i] = node[0]
elif isinstance(node, nodes.Text) and node.strip():
result[i] = type_to_xref(str(node), env)
return result
except SyntaxError:
Expand Down
21 changes: 21 additions & 0 deletions tests/test_domain_py.py
Expand Up @@ -342,6 +342,27 @@ def test_parse_annotation(app):
assert_node(doctree[0], pending_xref, refdomain="py", reftype="obj", reftarget="None")


@pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.')
def test_parse_annotation_Literal(app):
doctree = _parse_annotation("Literal[True, False]", app.env)
assert_node(doctree, ([pending_xref, "Literal"],
[desc_sig_punctuation, "["],
"True",
[desc_sig_punctuation, ", "],
"False",
[desc_sig_punctuation, "]"]))

doctree = _parse_annotation("typing.Literal[0, 1, 'abc']", app.env)
assert_node(doctree, ([pending_xref, "typing.Literal"],
[desc_sig_punctuation, "["],
"0",
[desc_sig_punctuation, ", "],
"1",
[desc_sig_punctuation, ", "],
"'abc'",
[desc_sig_punctuation, "]"]))


def test_pyfunction_signature(app):
text = ".. py:function:: hello(name: str) -> str"
doctree = restructuredtext.parse(app, text)
Expand Down

0 comments on commit 0469b04

Please sign in to comment.