From 785f4d695cfca0eeb537c92166808bc9f187d8c0 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 3 Oct 2020 12:00:33 +0900 Subject: [PATCH] Fix #7964: autodoc: Tuple in default value is wrongly rendered This implements tuple literal support to sphinx.pycode.ast.unparse(). --- CHANGES | 1 + sphinx/pycode/ast.py | 18 ++++++++++++++++-- tests/test_pycode_ast.py | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 22876d43b1c..bfe8910d16b 100644 --- a/CHANGES +++ b/CHANGES @@ -34,6 +34,7 @@ Bugs fixed by string not ending with blank lines * #8142: autodoc: Wrong constructor signature for the class derived from typing.Generic +* #7964: autodoc: Tuple in default value is wrongly rendered * #8192: napoleon: description is disappeared when it contains inline literals * #8142: napoleon: Potential of regex denial of service in google style docs * #8169: LaTeX: pxjahyper loaded even when latex_engine is not platex diff --git a/sphinx/pycode/ast.py b/sphinx/pycode/ast.py index 9bafff11c1a..2583448d5d7 100644 --- a/sphinx/pycode/ast.py +++ b/sphinx/pycode/ast.py @@ -166,14 +166,28 @@ def visit_Set(self, node: ast.Set) -> str: return "{" + ", ".join(self.visit(e) for e in node.elts) + "}" def visit_Subscript(self, node: ast.Subscript) -> str: - return "%s[%s]" % (self.visit(node.value), self.visit(node.slice)) + def is_simple_tuple(value: ast.AST) -> bool: + return ( + isinstance(value, ast.Tuple) and + bool(value.elts) and + not any(isinstance(elt, ast.Starred) for elt in value.elts) + ) + + if is_simple_tuple(node.slice): + elts = ", ".join(self.visit(e) for e in node.slice.elts) # type: ignore + return "%s[%s]" % (self.visit(node.value), elts) + elif isinstance(node.slice, ast.Index) and is_simple_tuple(node.slice.value): + elts = ", ".join(self.visit(e) for e in node.slice.value.elts) # type: ignore + return "%s[%s]" % (self.visit(node.value), elts) + else: + return "%s[%s]" % (self.visit(node.value), self.visit(node.slice)) def visit_UnaryOp(self, node: ast.UnaryOp) -> str: return "%s %s" % (self.visit(node.op), self.visit(node.operand)) def visit_Tuple(self, node: ast.Tuple) -> str: if node.elts: - return ", ".join(self.visit(e) for e in node.elts) + return "(" + ", ".join(self.visit(e) for e in node.elts) + ")" else: return "()" diff --git a/tests/test_pycode_ast.py b/tests/test_pycode_ast.py index 9b12d24d5f6..32a784b7419 100644 --- a/tests/test_pycode_ast.py +++ b/tests/test_pycode_ast.py @@ -53,7 +53,7 @@ ("+ a", "+ a"), # UAdd ("- 1", "- 1"), # UnaryOp ("- a", "- a"), # USub - ("(1, 2, 3)", "1, 2, 3"), # Tuple + ("(1, 2, 3)", "(1, 2, 3)"), # Tuple ("()", "()"), # Tuple (empty) ]) def test_unparse(source, expected):