Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove extra space from the unparser #10551

Merged
merged 9 commits into from Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -16,6 +16,9 @@ Features added
Bugs fixed
----------

* #10031: pycode: Fix spurious whitespace in unparsing various operators (``+``,
AA-Turner marked this conversation as resolved.
Show resolved Hide resolved
``-``, ``~``, and ``**``). Patch by Adam Turner.

Testing
--------

Expand Down
9 changes: 8 additions & 1 deletion sphinx/pycode/ast.py
Expand Up @@ -141,6 +141,9 @@ def visit_Attribute(self, node: ast.Attribute) -> str:
return "%s.%s" % (self.visit(node.value), node.attr)

def visit_BinOp(self, node: ast.BinOp) -> str:
# Special case ``**`` to now have surrounding spaces.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Special case ``**`` to now have surrounding spaces.
# Special case ``**`` to not have surrounding spaces.

if isinstance(node.op, ast.Pow):
return "".join(map(self.visit, (node.left, node.op, node.right)))
return " ".join(self.visit(e) for e in [node.left, node.op, node.right])

def visit_BoolOp(self, node: ast.BoolOp) -> str:
Expand Down Expand Up @@ -202,7 +205,11 @@ def is_simple_tuple(value: ast.AST) -> bool:
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))
# UnaryOp is one of {UAdd, USub, Invert, Not}, which refer to ``+x``,
# ``-x``, ``~x``, and ``not x``. Only Not needs a space.
if isinstance(node.op, ast.Not):
return "%s %s" % (self.visit(node.op), self.visit(node.operand))
return "%s%s" % (self.visit(node.op), self.visit(node.operand))

def visit_Tuple(self, node: ast.Tuple) -> str:
if len(node.elts) == 0:
Expand Down
27 changes: 27 additions & 0 deletions tests/test_domain_py.py
Expand Up @@ -452,6 +452,33 @@ def test_pyfunction_signature_full(app):
[desc_sig_name, pending_xref, "str"])])])


def test_pyfunction_with_unary_operators(app):
text = ".. py:function:: menu(egg=+1, bacon=-1, sausage=~1, spam=not spam)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, ([desc_sig_name, "egg"],
[desc_sig_operator, "="],
[nodes.inline, "+1"])],
[desc_parameter, ([desc_sig_name, "bacon"],
[desc_sig_operator, "="],
[nodes.inline, "-1"])],
[desc_parameter, ([desc_sig_name, "sausage"],
[desc_sig_operator, "="],
[nodes.inline, "~1"])],
[desc_parameter, ([desc_sig_name, "spam"],
[desc_sig_operator, "="],
[nodes.inline, "not spam"])])])


def test_pyfunction_with_binary_operators(app):
text = ".. py:function:: menu(spam=2**64)"
doctree = restructuredtext.parse(app, text)
assert_node(doctree[1][0][1],
[desc_parameterlist, ([desc_parameter, ([desc_sig_name, "spam"],
[desc_sig_operator, "="],
[nodes.inline, "2**64"])])])


@pytest.mark.skipif(sys.version_info < (3, 8), reason='python 3.8+ is required.')
def test_pyfunction_signature_full_py38(app):
# case: separator at head
Expand Down
10 changes: 5 additions & 5 deletions tests/test_pycode_ast.py
Expand Up @@ -25,7 +25,7 @@
("...", "..."), # Ellipsis
("a // b", "a // b"), # FloorDiv
("Tuple[int, int]", "Tuple[int, int]"), # Index, Subscript
("~ 1", "~ 1"), # Invert
("~1", "~1"), # Invert
("lambda x, y: x + y",
"lambda x, y: ..."), # Lambda
("[1, 2, 3]", "[1, 2, 3]"), # List
Expand All @@ -37,14 +37,14 @@
("1234", "1234"), # Num
("not a", "not a"), # Not
("a or b", "a or b"), # Or
("a ** b", "a ** b"), # Pow
("a**b", "a**b"), # Pow
("a >> b", "a >> b"), # RShift
("{1, 2, 3}", "{1, 2, 3}"), # Set
("a - b", "a - b"), # Sub
("'str'", "'str'"), # Str
("+ a", "+ a"), # UAdd
("- 1", "- 1"), # UnaryOp
("- a", "- a"), # USub
("+a", "+a"), # UAdd
("-1", "-1"), # UnaryOp
("-a", "-a"), # USub
("(1, 2, 3)", "(1, 2, 3)"), # Tuple
("()", "()"), # Tuple (empty)
("(1,)", "(1,)"), # Tuple (single item)
Expand Down