reflow-parentheses
LayoutRemoves a grouping parenthesis pair that changes nothing, and breaks one whose joined form overflows code-line-length into a row per operand.
shed-super-args removes the arguments from a super(Button, self) call, leaving super(), which behaves the same and reads at a glance. The two arguments restate the enclosing class and the bound instance the interpreter already resolves from the method the call sits in, so the reader parses them to learn nothing the surrounding def did not already say, and the restatement goes stale the moment the class is renamed.
The rewrite runs only where the bare call resolves the same pair, so the first argument has to name the one enclosing class (or the __class__ cell directly) and the second has to name the enclosing callable's first positional parameter, whether that reads self, cls, or a positional-only receiver. A call keeps its arguments wherever one of these applies:
@dataclass(slots=True), whose generated replacement the bare call's cell does not follow.super or __class__ itself.Removing the arguments pulls every token after them leftward. Where the author aligned a later line of the same statement to a column at or past those arguments, that line moves left by the width of the removed span and keeps pointing at the column it was measured against. A line hanging one indent step under the statement keeps its depth, since nothing it was measured against moved. A row inside a multi-line string is the one continuation no move can shift without changing the string's value, so a call whose rewrite would have to move such a row keeps its arguments.
The rule runs ahead of reflow-calls, so the bare super() is the text every later width measurement reads, and a call the rewrite brings within its budget settles in the same pass.
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Turns the rule on or off. |
Button.render calls super(Button, self).render(), naming both the enclosing class and its own receiver. Both arguments drop, leaving super().render(), because the interpreter resolves the same class and instance from the enclosing method.
class Widget:
def render(self):
return ""
class Button(Widget):
def render(self):
return super().render() + "!"
Entry.build, a classmethod naming cls, calls super(Entry, cls).build(), and Entry.merge(self, /, other) calls super(Entry, self).merge(other) with self ahead of the / marker. Both shorten to super(), because the rewrite reads whichever parameter fills the leading positional slot.
Child.label returns f"{super(Child, self).label()}!", calling super(Child, self) inside the f-string's replacement field. The interpolated call shortens to super(), the same way one outside a string would.
super(CachedLoader, self).ready sits in an if header, above a body whose merge(primary, call wraps onto a second line. The call shortens to super().ready and every line of the body keeps the indentation it already had, because the shift stops at the end of the header's own logical line.
super(SecureConnection, self).__init__( opens a call whose host, port, and timeout arguments hang one step under the statement rather than aligning to the open parenthesis. SecureConnection, self drops from the call and every hanging argument line keeps the indentation it already had, because a hanging line is indented from the statement rather than from the text that moved.
Logger.dispatch calls super( with Logger and self each on its own line before ).dispatch(event). The call collapses to super().dispatch(event) on the callee's own line, because everything between the parentheses is deleted in one span.
Child.items, defined async def, calls super(Child, self).items(), and the inner(self) closure nested in wrapped calls it too. Both shorten to super().items(), the async method the same way a synchronous one would and the closure because its own first positional parameter, self, is the receiver, since the rewrite reads the innermost callable rather than wrapped around it.
super(Invoice, self).render(body, sits inside a wrap( call, with footer hanging under body on the next line and the closing ) of wrap( on its own line below.
Only the rows aligned to text that moved follow it. Shedding Invoice, self pulls the text after it leftward, so footer shifts left with body, whereas the closing ) of wrap( hangs from its own opener and stays exactly where it was written.
Leaf.clone calls super(__class__, self).clone(), naming the closure cell __class__ directly rather than the class by name. It shortens to super().clone() the same way the named form would, because __class__ already names the cell the bare call reads.
Tag.label calls super(Tag, self).label() on a class decorated @dataclass(slots=True). The call stays written, because that decorator builds a replacement class the bare call's __class__ cell does not follow.
deferred's lambda: super(Child, self).items(), gathered's list comprehension, and wrapped's inner() closure each call super(Child, self).items() from a frame with no parameters of its own. Every call stays exactly as written, because none of those frames carries the leading positional argument the bare call would read.
super(Child, self) in Child.apply spans three lines, with # the defining class commenting the first argument. The call stays exactly as written, because deleting the argument span would take that comment with it.
Invoice.render calls super(Invoice, self).render(body, """ with a triple-quoted string as the second argument, its indented interior spanning the next two lines. Invoice, self stays written rather than collapsing to super(), because a later row of the call that opens at or past the column Invoice, self occupies moves left with the shed, and a row inside a string cannot move without changing the string's value, so the rule leaves the call alone instead.
Child.run(self, other) calls super(Child, other).run(), naming other rather than the receiver self as its second argument, and super(Other, self).run(), naming Other rather than the enclosing class Child as its first. Both calls stay exactly as written, because the bare form would resolve a different class and instance pair in each.
SecureConnection.__init__ calls super(SecureConnection, self).__init__(...) with host, port, and timeout wrapped one per line under the open parenthesis. reflow-calls joins the three onto one row, and shed-super-args then removes SecureConnection and self from the call, leaving super().__init__(host, port, timeout), because the hand-aligned continuation lines are gone by the time the shortened call is measured.
add_exception calls super(Waiter, self).add_exception(future) on a row past the 40-column budget. shed-super-args runs ahead of reflow-calls, so the bare super() is the text the length trigger measures, and the add_exception call explodes on that width rather than on the wider text the shed removes.
Removes a grouping parenthesis pair that changes nothing, and breaks one whose joined form overflows code-line-length into a row per operand.
Removes a bare -> None return annotation, since an omitted one already reads as returning nothing.
Rewrites Optional[T], Union[X, Y], and the typing generics to the T | None, X | Y, and builtin forms the target runtime supports.
For per-statement opt-outs, the Suppression chapter covers the # prose: skip[shed-super-args] directive, which covers every line a wrapped statement spans.