token.GREATEREQUAL,
}
MATH_OPERATORS = {
+ token.VBAR,
+ token.CIRCUMFLEX,
+ token.AMPER,
+ token.LEFTSHIFT,
+ token.RIGHTSHIFT,
token.PLUS,
token.MINUS,
token.STAR,
token.SLASH,
- token.VBAR,
- token.AMPER,
+ token.DOUBLESLASH,
token.PERCENT,
- token.CIRCUMFLEX,
+ token.AT,
token.TILDE,
- token.LEFTSHIFT,
- token.RIGHTSHIFT,
token.DOUBLESTAR,
- token.DOUBLESLASH,
}
STARS = {token.STAR, token.DOUBLESTAR}
VARARGS_PARENTS = {
syms.term,
syms.power,
}
+ASSIGNMENTS = {
+ "=",
+ "+=",
+ "-=",
+ "*=",
+ "@=",
+ "/=",
+ "%=",
+ "&=",
+ "|=",
+ "^=",
+ "<<=",
+ ">>=",
+ "**=",
+ "//=",
+}
COMPREHENSION_PRIORITY = 20
-COMMA_PRIORITY = 10
-TERNARY_PRIORITY = 7
-LOGIC_PRIORITY = 5
-STRING_PRIORITY = 4
-COMPARATOR_PRIORITY = 3
-MATH_PRIORITY = 1
+COMMA_PRIORITY = 18
+TERNARY_PRIORITY = 16
+LOGIC_PRIORITY = 14
+STRING_PRIORITY = 12
+COMPARATOR_PRIORITY = 10
+MATH_PRIORITIES = {
+ token.VBAR: 8,
+ token.CIRCUMFLEX: 7,
+ token.AMPER: 6,
+ token.LEFTSHIFT: 5,
+ token.RIGHTSHIFT: 5,
+ token.PLUS: 4,
+ token.MINUS: 4,
+ token.STAR: 3,
+ token.SLASH: 3,
+ token.DOUBLESLASH: 3,
+ token.PERCENT: 3,
+ token.AT: 3,
+ token.TILDE: 2,
+ token.DOUBLESTAR: 1,
+}
@dataclass
and subscript_start.type == syms.subscriptlist
):
subscript_start = child_towards(subscript_start, leaf)
- return subscript_start is not None and any(
- n.type in TEST_DESCENDANTS for n in subscript_start.pre_order()
+ return (
+ subscript_start is not None
+ and any(n.type in TEST_DESCENDANTS for n in subscript_start.pre_order())
)
def __str__(self) -> str:
"""Visit a statement.
This implementation is shared for `if`, `while`, `for`, `try`, `except`,
- `def`, `with`, `class`, and `assert`.
+ `def`, `with`, `class`, `assert` and assignments.
The relevant Python language `keywords` for a given statement will be
NAME leaves within it. This methods puts those on a separate line.
- `parens` holds pairs of nodes where invisible parentheses should be put.
- Keys hold nodes after which opening parentheses should be put, values
- hold nodes before which closing parentheses should be put.
+ `parens` holds a set of string leaf values immeditely after which
+ invisible parens should be put.
"""
normalize_invisible_parens(node, parens_after=parens)
for child in node.children:
self.visit_with_stmt = partial(v, keywords={"with"}, parens=Ø)
self.visit_funcdef = partial(v, keywords={"def"}, parens=Ø)
self.visit_classdef = partial(v, keywords={"class"}, parens=Ø)
+ self.visit_expr_stmt = partial(v, keywords=Ø, parens=ASSIGNMENTS)
+ self.visit_return_stmt = partial(v, keywords={"return"}, parens={"return"})
self.visit_async_funcdef = self.visit_async_stmt
self.visit_decorated = self.visit_decorators
and leaf.parent
and leaf.parent.type not in {syms.factor, syms.star_expr}
):
- return MATH_PRIORITY
+ return MATH_PRIORITIES[leaf.type]
if leaf.type in COMPARATORS:
return COMPARATOR_PRIORITY
def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
"""Make existing optional parentheses invisible or create new ones.
+ `parens_after` is a set of string leaf values immeditely after which parens
+ should be put.
+
Standardizes on visible parentheses for single-element tuples, and keeps
existing visible parentheses for other tuples and generator expressions.
"""
Currently looking for:
- f-strings; and
- - trailing commas after * or ** in function signatures.
+ - trailing commas after * or ** in function signatures and calls.
"""
for n in node.pre_order():
if n.type == token.STRING:
return True
elif (
- n.type == syms.typedargslist
+ n.type in {syms.typedargslist, syms.arglist}
and n.children
and n.children[-1].type == token.COMMA
):
if ch.type in STARS:
return True
+ if ch.type == syms.argument:
+ for argch in ch.children:
+ if argch.type in STARS:
+ return True
+
return False