Update black tests (#10166)

This commit is contained in:
Micha Reiser 2024-02-29 10:00:51 +01:00 committed by GitHub
parent a6f32ddc5e
commit dcc92f50cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
139 changed files with 5480 additions and 1389 deletions

View file

@ -0,0 +1,82 @@
def foo():
"""
Docstring
"""
# Here we go
if x:
# This is also now fine
a = 123
else:
# But not necessary
a = 123
if y:
while True:
"""
Long comment here
"""
a = 123
if z:
for _ in range(100):
a = 123
else:
try:
# this should be ok
a = 123
except:
"""also this"""
a = 123
def bar():
if x:
a = 123
def baz():
# OK
if x:
a = 123
def quux():
new_line = here
class Cls:
def method(self):
pass
async def async_fn():
"""Docstring."""
@decorated
async def async_fn():
"""Docstring."""
def top_level(
a: int,
b: str,
) -> Whatever[Generic, Something]:
def nested(x: int) -> int:
pass

View file

@ -0,0 +1,81 @@
def foo():
"""
Docstring
"""
# Here we go
if x:
# This is also now fine
a = 123
else:
# But not necessary
a = 123
if y:
while True:
"""
Long comment here
"""
a = 123
if z:
for _ in range(100):
a = 123
else:
try:
# this should be ok
a = 123
except:
"""also this"""
a = 123
def bar():
if x:
a = 123
def baz():
# OK
if x:
a = 123
def quux():
new_line = here
class Cls:
def method(self):
pass
async def async_fn():
"""Docstring."""
@decorated
async def async_fn():
"""Docstring."""
def top_level(
a: int,
b: str,
) -> Whatever[Generic, Something]:
def nested(x: int) -> int:
pass

View file

@ -0,0 +1,11 @@
async def func() -> (int):
return 0
@decorated
async def func() -> (int):
return 0
async for (item) in async_iter:
pass

View file

@ -0,0 +1,11 @@
async def func() -> int:
return 0
@decorated
async def func() -> int:
return 0
async for item in async_iter:
pass

View file

@ -45,8 +45,7 @@ def wat():
@deco2(with_args=True)
# leading 3
@deco3
def decorated1():
...
def decorated1(): ...
# leading 1
@ -54,8 +53,7 @@ def decorated1():
# leading 2
@deco2(with_args=True)
# leading function comment
def decorated1():
...
def decorated1(): ...
# Note: this is fixed in
@ -65,8 +63,7 @@ some_instruction
# This comment should be split from `some_instruction` by two lines but isn't.
def g():
...
def g(): ...
if __name__ == "__main__":

View file

@ -45,8 +45,7 @@ def wat():
@deco2(with_args=True)
# leading 3
@deco3
def decorated1():
...
def decorated1(): ...
# leading 1
@ -54,8 +53,7 @@ def decorated1():
# leading 2
@deco2(with_args=True)
# leading function comment
def decorated1():
...
def decorated1(): ...
# Note: this is fixed in
@ -65,8 +63,7 @@ some_instruction
# This comment should be split from `some_instruction` by two lines but isn't.
def g():
...
def g(): ...
if __name__ == "__main__":

View file

@ -0,0 +1,56 @@
if (
True
# sdf
):
print("hw")
if ((
True
# sdf
)):
print("hw")
if ((
# type: ignore
True
)):
print("hw")
if ((
True
# type: ignore
)):
print("hw")
if (
# a long comment about
# the condition below
(a or b)
):
pass
def return_true():
return (
(
True # this comment gets removed accidentally
)
)
def return_true():
return (True) # this comment gets removed accidentally
if (
# huh comment
(True)
):
...
if (
# huh
(
# comment
True
)
):
...

View file

@ -0,0 +1,53 @@
if (
True
# sdf
):
print("hw")
if (
True
# sdf
):
print("hw")
if (
# type: ignore
True
):
print("hw")
if (
True
# type: ignore
):
print("hw")
if (
# a long comment about
# the condition below
a
or b
):
pass
def return_true():
return True # this comment gets removed accidentally
def return_true():
return True # this comment gets removed accidentally
if (
# huh comment
True
):
...
if (
# huh
# comment
True
):
...

View file

@ -104,7 +104,9 @@ def foo(wait: bool = True):
time.sleep(1) if wait else None
a = "".join((
"", # comment
"" if True else "",
))
a = "".join(
(
"", # comment
"" if True else "",
)
)

View file

@ -0,0 +1 @@
{"target_version": "py38"}

View file

@ -0,0 +1,31 @@
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
with \
make_context_manager1() as cm1, \
make_context_manager2(), \
make_context_manager3() as cm3, \
make_context_manager4() \
:
pass
with \
new_new_new1() as cm1, \
new_new_new2() \
:
pass
with mock.patch.object(
self.my_runner, "first_method", autospec=True
) as mock_run_adb, mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
):
pass

View file

@ -0,0 +1,18 @@
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
with make_context_manager1() as cm1, make_context_manager2(), make_context_manager3() as cm3, make_context_manager4():
pass
with new_new_new1() as cm1, new_new_new2():
pass
with mock.patch.object(
self.my_runner, "first_method", autospec=True
) as mock_run_adb, mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
):
pass

View file

@ -0,0 +1 @@
{"target_version": "py39"}

View file

@ -0,0 +1,84 @@
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
# Leading comment
with \
make_context_manager1() as cm1, \
make_context_manager2(), \
make_context_manager3() as cm3, \
make_context_manager4() \
:
pass
with \
new_new_new1() as cm1, \
new_new_new2() \
:
pass
with (
new_new_new1() as cm1,
new_new_new2()
):
pass
# Leading comment.
with (
# First comment.
new_new_new1() as cm1,
# Second comment.
new_new_new2()
# Last comment.
):
pass
with \
this_is_a_very_long_call(looong_arg1=looong_value1, looong_arg2=looong_value2) as cm1, \
this_is_a_very_long_call(looong_arg1=looong_value1, looong_arg2=looong_value2, looong_arg3=looong_value3, looong_arg4=looong_value4) as cm2 \
:
pass
with mock.patch.object(
self.my_runner, "first_method", autospec=True
) as mock_run_adb, mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
):
pass
with xxxxxxxx.some_kind_of_method(
some_argument=[
"first",
"second",
"third",
]
).another_method() as cmd:
pass
async def func():
async with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
async with some_function(
argument1, argument2, argument3="some_value"
) as some_cm, some_other_function(
argument1, argument2, argument3="some_value"
):
pass

View file

@ -0,0 +1,85 @@
with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass
# Leading comment
with (
make_context_manager1() as cm1,
make_context_manager2(),
make_context_manager3() as cm3,
make_context_manager4(),
):
pass
with new_new_new1() as cm1, new_new_new2():
pass
with new_new_new1() as cm1, new_new_new2():
pass
# Leading comment.
with (
# First comment.
new_new_new1() as cm1,
# Second comment.
new_new_new2(),
# Last comment.
):
pass
with (
this_is_a_very_long_call(
looong_arg1=looong_value1, looong_arg2=looong_value2
) as cm1,
this_is_a_very_long_call(
looong_arg1=looong_value1,
looong_arg2=looong_value2,
looong_arg3=looong_value3,
looong_arg4=looong_value4,
) as cm2,
):
pass
with (
mock.patch.object(self.my_runner, "first_method", autospec=True) as mock_run_adb,
mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
),
):
pass
with xxxxxxxx.some_kind_of_method(
some_argument=[
"first",
"second",
"third",
]
).another_method() as cmd:
pass
async def func():
async with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass
async with (
some_function(argument1, argument2, argument3="some_value") as some_cm,
some_other_function(argument1, argument2, argument3="some_value"),
):
pass

View file

@ -0,0 +1 @@
{"target_version": "py310"}

View file

@ -0,0 +1,15 @@
# This file uses pattern matching introduced in Python 3.10.
match http_code:
case 404:
print("Not found")
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass

View file

@ -0,0 +1,15 @@
# This file uses pattern matching introduced in Python 3.10.
match http_code:
case 404:
print("Not found")
with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass

View file

@ -0,0 +1 @@
{"target_version": "py311"}

View file

@ -0,0 +1,16 @@
# This file uses except* clause in Python 3.11.
try:
some_call()
except* Error as e:
pass
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass

View file

@ -0,0 +1,16 @@
# This file uses except* clause in Python 3.11.
try:
some_call()
except* Error as e:
pass
with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass

View file

@ -0,0 +1,24 @@
# This file doesn't use any Python 3.9+ only grammars.
# Make sure parens around a single context manager don't get autodetected as
# Python 3.9+.
with (a):
pass
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
with mock.patch.object(
self.my_runner, "first_method", autospec=True
) as mock_run_adb, mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
):
pass

View file

@ -0,0 +1,19 @@
# This file doesn't use any Python 3.9+ only grammars.
# Make sure parens around a single context manager don't get autodetected as
# Python 3.9+.
with a:
pass
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
pass
with mock.patch.object(
self.my_runner, "first_method", autospec=True
) as mock_run_adb, mock.patch.object(
self.my_runner, "second_method", autospec=True, return_value="foo"
):
pass

View file

@ -0,0 +1 @@
{"target_version": "py39"}

View file

@ -0,0 +1,17 @@
# This file uses parenthesized context managers introduced in Python 3.9.
with \
make_context_manager1() as cm1, \
make_context_manager2() as cm2, \
make_context_manager3() as cm3, \
make_context_manager4() as cm4 \
:
pass
with (
new_new_new1() as cm1,
new_new_new2()
):
pass

View file

@ -0,0 +1,14 @@
# This file uses parenthesized context managers introduced in Python 3.9.
with (
make_context_manager1() as cm1,
make_context_manager2() as cm2,
make_context_manager3() as cm3,
make_context_manager4() as cm4,
):
pass
with new_new_new1() as cm1, new_new_new2():
pass

View file

@ -0,0 +1,3 @@
"""
87 characters ............................................................................
"""

View file

@ -0,0 +1,3 @@
"""
87 characters ............................................................................
"""

View file

@ -0,0 +1,69 @@
from typing import NoReturn, Protocol, Union, overload
class Empty:
...
def dummy(a): ...
async def other(b): ...
@overload
def a(arg: int) -> int: ...
@overload
def a(arg: str) -> str: ...
@overload
def a(arg: object) -> NoReturn: ...
def a(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
class Proto(Protocol):
def foo(self, a: int) -> int:
...
def bar(self, b: str) -> str: ...
def baz(self, c: bytes) -> str:
...
def dummy_two():
...
@dummy
def dummy_three():
...
def dummy_four():
...
@overload
def b(arg: int) -> int: ...
@overload
def b(arg: str) -> str: ...
@overload
def b(arg: object) -> NoReturn: ...
def b(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
def has_comment():
... # still a dummy
if some_condition:
...
if already_dummy: ...
class AsyncCls:
async def async_method(self):
...
async def async_function(self):
...
@decorated
async def async_function(self):
...

View file

@ -0,0 +1,72 @@
from typing import NoReturn, Protocol, Union, overload
class Empty: ...
def dummy(a): ...
async def other(b): ...
@overload
def a(arg: int) -> int: ...
@overload
def a(arg: str) -> str: ...
@overload
def a(arg: object) -> NoReturn: ...
def a(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
class Proto(Protocol):
def foo(self, a: int) -> int: ...
def bar(self, b: str) -> str: ...
def baz(self, c: bytes) -> str: ...
def dummy_two(): ...
@dummy
def dummy_three(): ...
def dummy_four(): ...
@overload
def b(arg: int) -> int: ...
@overload
def b(arg: str) -> str: ...
@overload
def b(arg: object) -> NoReturn: ...
def b(arg: Union[int, str, object]) -> Union[int, str]:
if not isinstance(arg, (int, str)):
raise TypeError
return arg
def has_comment(): ... # still a dummy
if some_condition:
...
if already_dummy:
...
class AsyncCls:
async def async_method(self): ...
async def async_function(self): ...
@decorated
async def async_function(self): ...

View file

@ -22,6 +22,7 @@ def f():
if not prev:
prevp = preceding_leaf(p)
if not prevp or prevp.type in OPENING_BRACKETS:
return NO
if prevp.type == token.EQUAL:

View file

@ -53,12 +53,8 @@ def spaces_types(
g: int = 1 if False else 2,
h: str = "",
i: str = r"",
):
...
def spaces2(result=_core.Value(None)):
...
): ...
def spaces2(result=_core.Value(None)): ...
something = {

View file

@ -72,8 +72,7 @@ class Named(t.Protocol):
class Factory(t.Protocol):
def this_will_be_formatted(self, **kwargs) -> Named:
...
def this_will_be_formatted(self, **kwargs) -> Named: ...
# fmt: on

View file

@ -0,0 +1,2 @@
print () # fmt: skip
print () # fmt:skip

View file

@ -0,0 +1,2 @@
print () # fmt: skip
print () # fmt:skip

View file

@ -0,0 +1,116 @@
# Warning! This file contains form feeds (ASCII 0x0C, often represented by \f or ^L).
# These may be invisible in your editor: ensure you can see them before making changes here.
# There's one at the start that'll get stripped
# Comment and statement processing is different enough that we'll test variations of both
# contexts here
#
#
#
#
#
#
#
#
#
#
\
#
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
# form feed after a dedent
def foo():
pass
pass
# form feeds are prohibited inside blocks, or on a line with nonwhitespace
def bar( a = 1 ,b : bool = False ) :
pass
class Baz:
def __init__(self):
pass
def something(self):
pass
#
pass
pass #
a = 1
#
pass
a = 1
a = [
]
# as internal whitespace of a comment is allowed but why
"form feed literal in a string is okay "
# form feeds at the very end get removed.

View file

@ -0,0 +1,103 @@
# Warning! This file contains form feeds (ASCII 0x0C, often represented by \f or ^L).
# These may be invisible in your editor: ensure you can see them before making changes here.
# There's one at the start that'll get stripped
# Comment and statement processing is different enough that we'll test variations of both
# contexts here
#
#
#
#
#
#
#
#
#
#
#
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
pass
# form feed after a dedent
def foo():
pass
pass
# form feeds are prohibited inside blocks, or on a line with nonwhitespace
def bar(a=1, b: bool = False):
pass
class Baz:
def __init__(self):
pass
def something(self):
pass
#
pass
pass #
a = 1
#
pass
a = 1
a = []
# as internal whitespace of a comment is allowed but why
"form feed literal in a string is okay "
# form feeds at the very end get removed.

View file

@ -59,10 +59,7 @@ def spaces_types(
g: int = 1 if False else 2,
h: str = "",
i: str = r"",
):
...
): ...
def spaces2(result=_core.Value(None)):
assert fut is self._read_fut, (fut, self._read_fut)

View file

@ -0,0 +1,5 @@
m2 = None if not isinstance(dist, Normal) else m** 2 + s * 2
m3 = None if not isinstance(dist, Normal) else m ** 2 + s * 2
m4 = None if not isinstance(dist, Normal) else m**2 + s * 2
m5 = obj.method(another_obj.method()).attribute **2
m6 = None if ... else m**2 + s**2

View file

@ -0,0 +1,5 @@
m2 = None if not isinstance(dist, Normal) else m**2 + s * 2
m3 = None if not isinstance(dist, Normal) else m**2 + s * 2
m4 = None if not isinstance(dist, Normal) else m**2 + s * 2
m5 = obj.method(another_obj.method()).attribute ** 2
m6 = None if ... else m**2 + s**2

View file

@ -0,0 +1 @@
{"target_version": "py310"}

View file

@ -0,0 +1,19 @@
def http_status(status):
match status:
case 400:
return "Bad request"
case 401:
return "Unauthorized"
case 403:
return "Forbidden"
case 404:
return "Not found"

View file

@ -0,0 +1,19 @@
def http_status(status):
match status:
case 400:
return "Bad request"
case 401:
return "Unauthorized"
case 403:
return "Forbidden"
case 404:
return "Not found"

View file

@ -43,8 +43,10 @@ D4 = {
% (
"formatted",
"string",
): "This is a really really really long string that has to go inside of a dictionary. It is %s bad (#%d)."
% ("soooo", 2),
): (
"This is a really really really long string that has to go inside of a dictionary. It is %s bad (#%d)."
% ("soooo", 2)
),
}
func_with_keywords(
@ -254,10 +256,12 @@ annotated_variable: Final = (
+ CONCATENATED
+ "using the '+' operator."
)
annotated_variable: Final = "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
annotated_variable: Literal[
"fakse_literal"
] = "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
annotated_variable: Final = (
"This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
)
annotated_variable: Literal["fakse_literal"] = (
"This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
)
backslashes = "This is a really long string with \"embedded\" double quotes and 'single' quotes that also handles checking for an even number of backslashes \\"
backslashes = "This is a really long string with \"embedded\" double quotes and 'single' quotes that also handles checking for an even number of backslashes \\\\"

View file

@ -43,8 +43,10 @@ D4 = {
% (
"formatted",
"string",
): "This is a really really really long string that has to go inside of a dictionary. It is %s bad (#%d)."
% ("soooo", 2),
): (
"This is a really really really long string that has to go inside of a dictionary. It is %s bad (#%d)."
% ("soooo", 2)
),
}
func_with_keywords(
@ -254,10 +256,12 @@ annotated_variable: Final = (
+ CONCATENATED
+ "using the '+' operator."
)
annotated_variable: Final = "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
annotated_variable: Literal[
"fakse_literal"
] = "This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
annotated_variable: Final = (
"This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
)
annotated_variable: Literal["fakse_literal"] = (
"This is a large string that has a type annotation attached to it. A type annotation should NOT stop a long string from being wrapped."
)
backslashes = "This is a really long string with \"embedded\" double quotes and 'single' quotes that also handles checking for an even number of backslashes \\"
backslashes = "This is a really long string with \"embedded\" double quotes and 'single' quotes that also handles checking for an even number of backslashes \\\\"

View file

@ -1,6 +1,6 @@
"""I am a very helpful module docstring.
With trailing spaces:
With trailing spaces (only removed with unify_docstring_detection on):
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,

View file

@ -1,6 +1,6 @@
"""I am a very helpful module docstring.
With trailing spaces:
With trailing spaces (only removed with unify_docstring_detection on):
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam,

View file

@ -1 +0,0 @@
{"preview": "enabled", "source_type": "Stub"}

View file

@ -0,0 +1,33 @@
def line_before_docstring():
"""Please move me up"""
class LineBeforeDocstring:
"""Please move me up"""
class EvenIfThereIsAMethodAfter:
"""I'm the docstring"""
def method(self):
pass
class TwoLinesBeforeDocstring:
"""I want to be treated the same as if I were closer"""
class MultilineDocstringsAsWell:
"""I'm so far
and on so many lines...
"""
class SingleQuotedDocstring:
"I'm a docstring but I don't even get triple quotes."

View file

@ -0,0 +1,29 @@
def line_before_docstring():
"""Please move me up"""
class LineBeforeDocstring:
"""Please move me up"""
class EvenIfThereIsAMethodAfter:
"""I'm the docstring"""
def method(self):
pass
class TwoLinesBeforeDocstring:
"""I want to be treated the same as if I were closer"""
class MultilineDocstringsAsWell:
"""I'm so far
and on so many lines...
"""
class SingleQuotedDocstring:
"I'm a docstring but I don't even get triple quotes."

View file

@ -0,0 +1 @@
{"target_version": "py310"}

View file

@ -0,0 +1,7 @@
match x:
case "abcd" | "abcd" | "abcd" :
pass
case "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd":
pass
case xxxxxxxxxxxxxxxxxxxxxxx:
pass

View file

@ -0,0 +1,23 @@
match x:
case "abcd" | "abcd" | "abcd":
pass
case (
"abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
| "abcd"
):
pass
case xxxxxxxxxxxxxxxxxxxxxxx:
pass

View file

@ -0,0 +1 @@
{"target_version": "py310"}

View file

@ -0,0 +1,14 @@
match maybe, multiple:
case perhaps, 5:
pass
case perhaps, 6,:
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case [[5], (6)], [7],:
pass
case _:
pass

View file

@ -0,0 +1,20 @@
match maybe, multiple:
case perhaps, 5:
pass
case (
perhaps,
6,
):
pass
match more := (than, one), indeed,:
case _, (5, 6):
pass
case (
[[5], (6)],
[7],
):
pass
case _:
pass

View file

@ -1 +1 @@
{"preview": "enabled", "target_version": "py310"}
{"target_version": "py310"}

View file

@ -1,7 +1,7 @@
# Unparenthesized walruses are now allowed in indices since Python 3.10.
x[a:=0]
x[a:=0, b:=1]
x[5, b:=0]
x[a := 0]
x[a := 0, b := 1]
x[5, b := 0]
# Walruses are allowed inside generator expressions on function calls since 3.10.
if any(match := pattern_error.match(s) for s in buffer):

View file

@ -1,7 +1,7 @@
# Unparenthesized walruses are now allowed in indices since Python 3.10.
x[a:=0]
x[a:=0, b:=1]
x[5, b:=0]
x[a := 0]
x[a := 0, b := 1]
x[5, b := 0]
# Walruses are allowed inside generator expressions on function calls since 3.10.
if any(match := pattern_error.match(s) for s in buffer):

View file

@ -23,18 +23,16 @@ assert (foo := 42 - 12)
foo(x=(y := f(x)))
def foo(answer=(p := 42)):
...
def foo(answer=(p := 42)): ...
def foo2(answer: (p := 42) = 5):
...
def foo2(answer: (p := 42) = 5): ...
lambda: (x := 1)
a[(x := 12)]
a[:(x := 13)]
a[: (x := 13)]
# we don't touch expressions in f-strings but if we do one day, don't break 'em
f"{(x:=10)}"

View file

@ -0,0 +1,2 @@
x[(a:=0):]
x[:(a:=0)]

View file

@ -0,0 +1,2 @@
x[(a := 0) :]
x[: (a := 0)]

View file

@ -0,0 +1,20 @@
("" % a) ** 2
("" % a)[0]
("" % a)()
("" % a).b
2 * ("" % a)
2 @ ("" % a)
2 / ("" % a)
2 // ("" % a)
2 % ("" % a)
+("" % a)
b + ("" % a)
-("" % a)
b - ("" % a)
b + -("" % a)
~("" % a)
2 ** ("" % a)
await ("" % a)
b[("" % a)]
b(("" % a))

View file

@ -0,0 +1,20 @@
("" % a) ** 2
("" % a)[0]
("" % a)()
("" % a).b
2 * ("" % a)
2 @ ("" % a)
2 / ("" % a)
2 // ("" % a)
2 % ("" % a)
+("" % a)
b + ("" % a)
-("" % a)
b - ("" % a)
b + -("" % a)
~("" % a)
2 ** ("" % a)
await ("" % a)
b[("" % a)]
b(("" % a))

View file

@ -0,0 +1,11 @@
a = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
b = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
c = 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1 ** 1
d = 1**1 ** 1**1 ** 1**1 ** 1**1 ** 1**1**1 ** 1 ** 1**1 ** 1**1**1**1**1 ** 1 ** 1**1**1 **1**1** 1 ** 1 ** 1
e = 𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟
f = 𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟
a = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
b = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
c = 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0 ** 1.0
d = 1.0**1.0 ** 1.0**1.0 ** 1.0**1.0 ** 1.0**1.0 ** 1.0**1.0**1.0 ** 1.0 ** 1.0**1.0 ** 1.0**1.0**1.0

View file

@ -0,0 +1,83 @@
a = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
b = (
1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
** 1
)
c = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
d = 1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1**1
e = 𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟**𨉟
f = (
𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
** 𨉟
)
a = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
b = (
1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
** 1.0
)
c = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0
d = 1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0**1.0

View file

@ -0,0 +1,106 @@
first_item, second_item = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
some_dict["with_a_long_key"] = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
# Make sure it works when the RHS only has one pair of (optional) parens.
first_item, second_item = (
some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
)
some_dict["with_a_long_key"] = (
some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
)
# Make sure chaining assignments work.
first_item, second_item, third_item, forth_item = m["everything"] = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
# Make sure when the RHS's first split at the non-optional paren fits,
# we split there instead of the outer RHS optional paren.
first_item, second_item = some_looooooooong_module.some_loooooog_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = everything = some_looooong_function_name(
first_argument, second_argument, third_argument
)
# Make sure unsplittable type ignore won't be moved.
some_kind_of_table[some_key] = util.some_function( # type: ignore # noqa: E501
some_arg
).intersection(pk_cols)
some_kind_of_table[
some_key
] = lambda obj: obj.some_long_named_method() # type: ignore # noqa: E501
some_kind_of_table[
some_key # type: ignore # noqa: E501
] = lambda obj: obj.some_long_named_method()
# Make when when the left side of assignment plus the opening paren "... = (" is
# exactly line length limit + 1, it won't be split like that.
xxxxxxxxx_yyy_zzzzzzzz[
xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1)
] = 1
# Right side of assignment contains un-nested pairs of inner parens.
some_kind_of_instance.some_kind_of_map[a_key] = (
isinstance(some_var, SomeClass)
and table.something_and_something != table.something_else
) or (
isinstance(some_other_var, BaseClass) and table.something != table.some_other_thing
)
# Multiple targets
a = b = (
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
)
a = b = c = d = e = f = g = (
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
) = i = j = (
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
)
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = c
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = (
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
) = ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd

View file

@ -0,0 +1,106 @@
first_item, second_item = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
some_dict["with_a_long_key"] = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
# Make sure it works when the RHS only has one pair of (optional) parens.
first_item, second_item = (
some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
)
some_dict["with_a_long_key"] = (
some_looooooooong_module.SomeClass.some_looooooooooooooong_variable_name
)
# Make sure chaining assignments work.
first_item, second_item, third_item, forth_item = m["everything"] = (
some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
)
# Make sure when the RHS's first split at the non-optional paren fits,
# we split there instead of the outer RHS optional paren.
first_item, second_item = some_looooooooong_module.some_loooooog_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = some_looooooooong_module.some_looooooooooooooong_function_name(
first_argument, second_argument, third_argument
)
(
first_item,
second_item,
third_item,
forth_item,
fifth_item,
last_item_very_loooooong,
) = everything = some_looooong_function_name(
first_argument, second_argument, third_argument
)
# Make sure unsplittable type ignore won't be moved.
some_kind_of_table[some_key] = util.some_function( # type: ignore # noqa: E501
some_arg
).intersection(pk_cols)
some_kind_of_table[
some_key
] = lambda obj: obj.some_long_named_method() # type: ignore # noqa: E501
some_kind_of_table[
some_key # type: ignore # noqa: E501
] = lambda obj: obj.some_long_named_method()
# Make when when the left side of assignment plus the opening paren "... = (" is
# exactly line length limit + 1, it won't be split like that.
xxxxxxxxx_yyy_zzzzzzzz[
xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1)
] = 1
# Right side of assignment contains un-nested pairs of inner parens.
some_kind_of_instance.some_kind_of_map[a_key] = (
isinstance(some_var, SomeClass)
and table.something_and_something != table.something_else
) or (
isinstance(some_other_var, BaseClass) and table.something != table.some_other_thing
)
# Multiple targets
a = b = (
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
)
a = b = c = d = e = f = g = (
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
) = i = j = (
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
)
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = c
a = (
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
) = (
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
) = ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd

View file

@ -19,12 +19,6 @@ normal_name = but_the_function_name_is_now_ridiculously_long_and_it_is_still_sup
normal_name = but_the_function_name_is_now_ridiculously_long_and_it_is_still_super_annoying(
[1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3
)
# long arguments
normal_name = normal_function_name(
"but with super long string arguments that on their own exceed the line limit so there's no way it can ever fit",
"eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs",
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it=0,
)
string_variable_name = (
"a string that is waaaaaaaayyyyyyyy too long, even in parens, there's nothing you can do" # noqa
)

View file

@ -33,14 +33,6 @@ normal_name = (
[1, 2, 3], arg1, [1, 2, 3], arg2, [1, 2, 3], arg3
)
)
# long arguments
normal_name = normal_function_name(
"but with super long string arguments that on their own exceed the line limit so"
" there's no way it can ever fit",
"eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs"
" with spam and eggs and spam with eggs",
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it=0,
)
string_variable_name = "a string that is waaaaaaaayyyyyyyy too long, even in parens, there's nothing you can do" # noqa
for key in """
hostname

View file

@ -0,0 +1,6 @@
# long arguments
normal_name = normal_function_name(
"but with super long string arguments that on their own exceed the line limit so there's no way it can ever fit",
"eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs",
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it=0,
)

View file

@ -0,0 +1,8 @@
# long arguments
normal_name = normal_function_name(
"but with super long string arguments that on their own exceed the line limit so"
" there's no way it can ever fit",
"eggs with spam and eggs and spam with eggs with spam and eggs and spam with eggs"
" with spam and eggs and spam with eggs",
this_is_a_ridiculously_long_name_and_nobody_in_their_right_mind_would_use_one_like_it=0,
)

View file

@ -1 +1 @@
{"preview": "enabled", "target_version": "py310"}
{"target_version": "py310"}

View file

@ -1,17 +1,14 @@
@relaxed_decorator[0]
def f():
...
def f(): ...
@relaxed_decorator[
extremely_long_name_that_definitely_will_not_fit_on_one_line_of_standard_length
]
def f():
...
def f(): ...
@extremely_long_variable_name_that_doesnt_fit := complex.expression(
with_long="arguments_value_that_wont_fit_at_the_end_of_the_line"
)
def f():
...
def f(): ...

View file

@ -0,0 +1,10 @@
def do_not_touch_this_prefix():
R"""There was a bug where docstring prefixes would be normalized even with -S."""
def do_not_touch_this_prefix2():
FR'There was a bug where docstring prefixes would be normalized even with -S.'
def do_not_touch_this_prefix3():
u'''There was a bug where docstring prefixes would be normalized even with -S.'''

View file

@ -0,0 +1,10 @@
def do_not_touch_this_prefix():
R"""There was a bug where docstring prefixes would be normalized even with -S."""
def do_not_touch_this_prefix2():
FR'There was a bug where docstring prefixes would be normalized even with -S.'
def do_not_touch_this_prefix3():
u'''There was a bug where docstring prefixes would be normalized even with -S.'''

View file

@ -3,14 +3,14 @@ import random
def foo1():
print("The newline above me should be deleted!")
print("The newline above me should be kept!")
def foo2():
print("All the newlines above me should be deleted!")
print("All the newlines above me should be kept!")
def foo3():
@ -30,31 +30,31 @@ def foo4():
class Foo:
def bar(self):
print("The newline above me should be deleted!")
print("The newline above me should be kept!")
for i in range(5):
print(f"{i}) The line above me should be removed!")
print(f"{i}) The line above me should be kept!")
for i in range(5):
print(f"{i}) The lines above me should be removed!")
print(f"{i}) The lines above me should be kept!")
for i in range(5):
for j in range(7):
print(f"{i}) The lines above me should be removed!")
print(f"{i}) The lines above me should be kept!")
if random.randint(0, 3) == 0:
print("The new line above me is about to be removed!")
print("The new line above me will be kept!")
if random.randint(0, 3) == 0:
@ -62,43 +62,45 @@ if random.randint(0, 3) == 0:
print("The new lines above me is about to be removed!")
print("The new lines above me will be kept!")
if random.randint(0, 3) == 0:
if random.uniform(0, 1) > 0.5:
print("Two lines above me are about to be removed!")
print("Two lines above me will be kept!")
while True:
print("The newline above me should be deleted!")
print("The newline above me should be kept!")
while True:
print("The newlines above me should be deleted!")
print("The newlines above me should be kept!")
while True:
while False:
print("The newlines above me should be deleted!")
print("The newlines above me should be kept!")
with open("/path/to/file.txt", mode="w") as file:
file.write("The new line above me is about to be removed!")
file.write("The new line above me will be kept!")
with open("/path/to/file.txt", mode="w") as file:
file.write("The new lines above me is about to be removed!")
file.write("The new lines above me will be kept!")
with open("/path/to/file.txt", mode="r") as read_file:

View file

@ -2,20 +2,24 @@ import random
def foo1():
print("The newline above me should be deleted!")
print("The newline above me should be kept!")
def foo2():
print("All the newlines above me should be deleted!")
print("All the newlines above me should be kept!")
def foo3():
print("No newline above me!")
print("There is a newline above me, and that's OK!")
def foo4():
# There is a comment here
print("The newline above me should not be deleted!")
@ -23,56 +27,73 @@ def foo4():
class Foo:
def bar(self):
print("The newline above me should be deleted!")
print("The newline above me should be kept!")
for i in range(5):
print(f"{i}) The line above me should be removed!")
print(f"{i}) The line above me should be kept!")
for i in range(5):
print(f"{i}) The lines above me should be removed!")
print(f"{i}) The lines above me should be kept!")
for i in range(5):
for j in range(7):
print(f"{i}) The lines above me should be removed!")
print(f"{i}) The lines above me should be kept!")
if random.randint(0, 3) == 0:
print("The new line above me is about to be removed!")
print("The new line above me will be kept!")
if random.randint(0, 3) == 0:
print("The new lines above me is about to be removed!")
print("The new lines above me will be kept!")
if random.randint(0, 3) == 0:
if random.uniform(0, 1) > 0.5:
print("Two lines above me are about to be removed!")
print("Two lines above me will be kept!")
while True:
print("The newline above me should be deleted!")
print("The newline above me should be kept!")
while True:
print("The newlines above me should be deleted!")
print("The newlines above me should be kept!")
while True:
while False:
print("The newlines above me should be deleted!")
print("The newlines above me should be kept!")
with open("/path/to/file.txt", mode="w") as file:
file.write("The new line above me is about to be removed!")
file.write("The new line above me will be kept!")
with open("/path/to/file.txt", mode="w") as file:
file.write("The new lines above me is about to be removed!")
file.write("The new lines above me will be kept!")
with open("/path/to/file.txt", mode="r") as read_file:
with open("/path/to/output_file.txt", mode="w") as write_file:
write_file.writelines(read_file.readlines())

View file

@ -0,0 +1 @@
{"preview": "enabled", "line_width": 79, "target_version": "py310"}

View file

@ -0,0 +1,57 @@
match 1:
case _ if (True):
pass
match 1:
case _ if (
True
):
pass
match 1:
case _ if (
# this is a comment
True
):
pass
match 1:
case _ if (
True
# this is a comment
):
pass
match 1:
case _ if (
True # this is a comment
):
pass
match 1:
case _ if ( # this is a comment
True
):
pass
match 1:
case _ if (
True
): # this is a comment
pass
match 1:
case _ if (True): # comment over the line limit unless parens are removed x
pass
match 1:
case _ if (True): # comment over the line limit and parens should go to next line
pass

View file

@ -0,0 +1,51 @@
match 1:
case _ if True:
pass
match 1:
case _ if True:
pass
match 1:
case _ if (
# this is a comment
True
):
pass
match 1:
case _ if (
True
# this is a comment
):
pass
match 1:
case _ if True: # this is a comment
pass
match 1:
case _ if True: # this is a comment
pass
match 1:
case _ if True: # this is a comment
pass
match 1:
case _ if True: # comment over the line limit unless parens are removed x
pass
match 1:
case (
_
) if True: # comment over the line limit and parens should go to next line
pass

View file

@ -88,6 +88,5 @@ def foo() -> tuple[int, int, int,]:
return 2
# Magic trailing comma example, with params
# this is broken - the trailing comma is transferred to the param list. Fixed in preview
def foo(a,b) -> tuple[int, int, int,]:
return 2

View file

@ -99,30 +99,27 @@ def foo() -> tuple[int, int, int]:
return 2
def foo() -> (
tuple[
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
]
):
def foo() -> tuple[
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong,
]:
return 2
# Magic trailing comma example
def foo() -> (
tuple[
int,
int,
int,
]
):
def foo() -> tuple[
int,
int,
int,
]:
return 2
# Magic trailing comma example, with params
# this is broken - the trailing comma is transferred to the param list. Fixed in preview
def foo(
a, b
) -> tuple[int, int, int,]:
def foo(a, b) -> tuple[
int,
int,
int,
]:
return 2

View file

@ -0,0 +1,8 @@
foo = 123 # fmt: skip # noqa: E501 # pylint
bar = (
123 ,
( 1 + 5 ) # pylint # fmt:skip
)
baz = "a" + "b" # pylint; fmt: skip; noqa: E501
skip_will_not_work = "a" + "b" # pylint fmt:skip
skip_will_not_work2 = "a" + "b" # some text; fmt:skip happens to be part of it

Some files were not shown because too many files have changed in this diff Show more