Update Black tests (#5438)

This commit is contained in:
Micha Reiser 2023-06-30 08:32:50 +02:00 committed by GitHub
parent f7969cf23c
commit ae25638b0b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
166 changed files with 11066 additions and 237 deletions

View file

@ -0,0 +1,67 @@
long_kwargs_single_line = my_function(
foo="test, this is a sample value",
bar=some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)
multiline_kwargs_indented = my_function(
foo="test, this is a sample value",
bar=some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz,
baz="hello, this is a another value",
)
imploding_kwargs = my_function(
foo="test, this is a sample value",
bar=a
if foo
else b,
baz="hello, this is a another value",
)
imploding_line = (
1
if 1 + 1 == 2
else 0
)
exploding_line = "hello this is a slightly long string" if some_long_value_name_foo_bar_baz else "this one is a little shorter"
positional_argument_test(some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz)
def weird_default_argument(x=some_long_value_name_foo_bar_baz
if SOME_CONSTANT
else some_fallback_value_foo_bar_baz):
pass
nested = "hello this is a slightly long string" if (some_long_value_name_foo_bar_baz if
nesting_test_expressions else some_fallback_value_foo_bar_baz) \
else "this one is a little shorter"
generator_expression = (
some_long_value_name_foo_bar_baz if some_boolean_variable else some_fallback_value_foo_bar_baz for some_boolean_variable in some_iterable
)
def limit_offset_sql(self, low_mark, high_mark):
"""Return LIMIT/OFFSET SQL clause."""
limit, offset = self._get_limit_offset_params(low_mark, high_mark)
return " ".join(
sql
for sql in (
"LIMIT %d" % limit if limit else None,
("OFFSET %d" % offset) if offset else None,
)
if sql
)
def something():
clone._iterable_class = (
NamedValuesListIterable
if named
else FlatValuesListIterable
if flat
else ValuesListIterable
)

View file

@ -0,0 +1,90 @@
long_kwargs_single_line = my_function(
foo="test, this is a sample value",
bar=(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
),
baz="hello, this is a another value",
)
multiline_kwargs_indented = my_function(
foo="test, this is a sample value",
bar=(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
),
baz="hello, this is a another value",
)
imploding_kwargs = my_function(
foo="test, this is a sample value",
bar=a if foo else b,
baz="hello, this is a another value",
)
imploding_line = 1 if 1 + 1 == 2 else 0
exploding_line = (
"hello this is a slightly long string"
if some_long_value_name_foo_bar_baz
else "this one is a little shorter"
)
positional_argument_test(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
)
def weird_default_argument(
x=(
some_long_value_name_foo_bar_baz
if SOME_CONSTANT
else some_fallback_value_foo_bar_baz
),
):
pass
nested = (
"hello this is a slightly long string"
if (
some_long_value_name_foo_bar_baz
if nesting_test_expressions
else some_fallback_value_foo_bar_baz
)
else "this one is a little shorter"
)
generator_expression = (
(
some_long_value_name_foo_bar_baz
if some_boolean_variable
else some_fallback_value_foo_bar_baz
)
for some_boolean_variable in some_iterable
)
def limit_offset_sql(self, low_mark, high_mark):
"""Return LIMIT/OFFSET SQL clause."""
limit, offset = self._get_limit_offset_params(low_mark, high_mark)
return " ".join(
sql
for sql in (
"LIMIT %d" % limit if limit else None,
("OFFSET %d" % offset) if offset else None,
)
if sql
)
def something():
clone._iterable_class = (
NamedValuesListIterable
if named
else FlatValuesListIterable if flat else ValuesListIterable
)

View file

@ -0,0 +1,6 @@
def abc ():
return ["hello", "world",
"!"]
print( "Incorrect formatting"
)

View file

@ -0,0 +1,6 @@
def abc ():
return ["hello", "world",
"!"]
print( "Incorrect formatting"
)

View file

@ -0,0 +1,32 @@
@dataclass
class DebugVisitor(Visitor[T]):
tree_depth: int = 0
def visit_default(self, node: LN) -> Iterator[T]:
indent = ' ' * (2 * self.tree_depth)
if isinstance(node, Node):
_type = type_repr(node.type)
out(f'{indent}{_type}', fg='yellow')
self.tree_depth += 1
for child in node.children:
yield from self.visit(child)
self.tree_depth -= 1
out(f'{indent}/{_type}', fg='yellow', bold=False)
else:
_type = token.tok_name.get(node.type, str(node.type))
out(f'{indent}{_type}', fg='blue', nl=False)
if node.prefix:
# We don't have to handle prefixes for `Node` objects since
# that delegates to the first child anyway.
out(f' {node.prefix!r}', fg='green', bold=False, nl=False)
out(f' {node.value!r}', fg='blue', bold=False)
@classmethod
def show(cls, code: str) -> None:
"""Pretty-prints a given string of `code`.
Convenience method for debugging.
"""
v: DebugVisitor[None] = DebugVisitor()
list(v.visit(lib2to3_parse(code)))

View file

@ -0,0 +1,32 @@
@dataclass
class DebugVisitor(Visitor[T]):
tree_depth: int = 0
def visit_default(self, node: LN) -> Iterator[T]:
indent = ' ' * (2 * self.tree_depth)
if isinstance(node, Node):
_type = type_repr(node.type)
out(f'{indent}{_type}', fg='yellow')
self.tree_depth += 1
for child in node.children:
yield from self.visit(child)
self.tree_depth -= 1
out(f'{indent}/{_type}', fg='yellow', bold=False)
else:
_type = token.tok_name.get(node.type, str(node.type))
out(f'{indent}{_type}', fg='blue', nl=False)
if node.prefix:
# We don't have to handle prefixes for `Node` objects since
# that delegates to the first child anyway.
out(f' {node.prefix!r}', fg='green', bold=False, nl=False)
out(f' {node.value!r}', fg='blue', bold=False)
@classmethod
def show(cls, code: str) -> None:
"""Pretty-prints a given string of `code`.
Convenience method for debugging.
"""
v: DebugVisitor[None] = DebugVisitor()
list(v.visit(lib2to3_parse(code)))

View file

@ -0,0 +1,150 @@
# This file doesn't use the standard decomposition.
# Decorator syntax test cases are separated by double # comments.
# Those before the 'output' comment are valid under the old syntax.
# Those after the 'ouput' comment require PEP614 relaxed syntax.
# Do not remove the double # separator before the first test case, it allows
# the comment before the test case to be ignored.
##
@decorator
def f():
...
##
@decorator()
def f():
...
##
@decorator(arg)
def f():
...
##
@decorator(kwarg=0)
def f():
...
##
@decorator(*args)
def f():
...
##
@decorator(**kwargs)
def f():
...
##
@decorator(*args, **kwargs)
def f():
...
##
@decorator(*args, **kwargs,)
def f():
...
##
@dotted.decorator
def f():
...
##
@dotted.decorator(arg)
def f():
...
##
@dotted.decorator(kwarg=0)
def f():
...
##
@dotted.decorator(*args)
def f():
...
##
@dotted.decorator(**kwargs)
def f():
...
##
@dotted.decorator(*args, **kwargs)
def f():
...
##
@dotted.decorator(*args, **kwargs,)
def f():
...
##
@double.dotted.decorator
def f():
...
##
@double.dotted.decorator(arg)
def f():
...
##
@double.dotted.decorator(kwarg=0)
def f():
...
##
@double.dotted.decorator(*args)
def f():
...
##
@double.dotted.decorator(**kwargs)
def f():
...
##
@double.dotted.decorator(*args, **kwargs)
def f():
...
##
@double.dotted.decorator(*args, **kwargs,)
def f():
...
##
@_(sequence["decorator"])
def f():
...
##
@eval("sequence['decorator']")
def f():
...

View file

@ -0,0 +1,29 @@
##
@decorator()()
def f():
...
##
@(decorator)
def f():
...
##
@sequence["decorator"]
def f():
...
##
@decorator[List[str]]
def f():
...
##
@var := decorator
def f():
...

View file

@ -0,0 +1,123 @@
class ALonelyClass:
'''
A multiline class docstring.
'''
def AnEquallyLonelyMethod(self):
'''
A multiline method docstring'''
pass
def one_function():
'''This is a docstring with a single line of text.'''
pass
def shockingly_the_quotes_are_normalized():
'''This is a multiline docstring.
This is a multiline docstring.
This is a multiline docstring.
'''
pass
def foo():
"""This is a docstring with
some lines of text here
"""
return
def baz():
'''"This" is a string with some
embedded "quotes"'''
return
def poit():
"""
Lorem ipsum dolor sit amet.
Consectetur adipiscing elit:
- sed do eiusmod tempor incididunt ut labore
- dolore magna aliqua
- enim ad minim veniam
- quis nostrud exercitation ullamco laboris nisi
- aliquip ex ea commodo consequat
"""
pass
def under_indent():
"""
These lines are indented in a way that does not
make sense.
"""
pass
def over_indent():
"""
This has a shallow indent
- But some lines are deeper
- And the closing quote is too deep
"""
pass
def single_line():
"""But with a newline after it!
"""
pass
def this():
r"""
'hey ho'
"""
def that():
""" "hey yah" """
def and_that():
"""
"hey yah" """
def and_this():
'''
"hey yah"'''
def believe_it_or_not_this_is_in_the_py_stdlib(): '''
"hey yah"'''
def shockingly_the_quotes_are_normalized_v2():
'''
Docstring Docstring Docstring
'''
pass
def backslash_space():
'\ '
def multiline_backslash_1():
'''
hey\there\
\ '''
def multiline_backslash_2():
'''
hey there \ '''
def multiline_backslash_3():
'''
already escaped \\ '''

View file

@ -0,0 +1,123 @@
class ALonelyClass:
'''
A multiline class docstring.
'''
def AnEquallyLonelyMethod(self):
'''
A multiline method docstring'''
pass
def one_function():
'''This is a docstring with a single line of text.'''
pass
def shockingly_the_quotes_are_normalized():
'''This is a multiline docstring.
This is a multiline docstring.
This is a multiline docstring.
'''
pass
def foo():
"""This is a docstring with
some lines of text here
"""
return
def baz():
'''"This" is a string with some
embedded "quotes"'''
return
def poit():
"""
Lorem ipsum dolor sit amet.
Consectetur adipiscing elit:
- sed do eiusmod tempor incididunt ut labore
- dolore magna aliqua
- enim ad minim veniam
- quis nostrud exercitation ullamco laboris nisi
- aliquip ex ea commodo consequat
"""
pass
def under_indent():
"""
These lines are indented in a way that does not
make sense.
"""
pass
def over_indent():
"""
This has a shallow indent
- But some lines are deeper
- And the closing quote is too deep
"""
pass
def single_line():
"""But with a newline after it!"""
pass
def this():
r"""
'hey ho'
"""
def that():
""" "hey yah" """
def and_that():
"""
"hey yah" """
def and_this():
'''
"hey yah"'''
def believe_it_or_not_this_is_in_the_py_stdlib():
'''
"hey yah"'''
def shockingly_the_quotes_are_normalized_v2():
'''
Docstring Docstring Docstring
'''
pass
def backslash_space():
'\ '
def multiline_backslash_1():
'''
hey\there\
\ '''
def multiline_backslash_2():
'''
hey there \ '''
def multiline_backslash_3():
'''
already escaped \\'''

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

@ -0,0 +1,3 @@
# The input source must not contain any Py36-specific syntax (e.g. argument type
# annotations, trailing comma after *rest) or this test becomes invalid.
def long_function_name(argument_one, argument_two, argument_three, argument_four, argument_five, argument_six, *rest): ...

View file

@ -0,0 +1,12 @@
# The input source must not contain any Py36-specific syntax (e.g. argument type
# annotations, trailing comma after *rest) or this test becomes invalid.
def long_function_name(
argument_one,
argument_two,
argument_three,
argument_four,
argument_five,
argument_six,
*rest,
):
...

View file

@ -0,0 +1,30 @@
from typing import Union
@bird
def zoo(): ...
class A: ...
@bar
class B:
def BMethod(self) -> None: ...
@overload
def BMethod(self, arg : List[str]) -> None: ...
class C: ...
@hmm
class D: ...
class E: ...
@baz
def foo() -> None:
...
class F (A , C): ...
def spam() -> None: ...
@overload
def spam(arg: str) -> str: ...
var : int = 1
def eggs() -> Union[str, int]: ...

View file

@ -0,0 +1,32 @@
from typing import Union
@bird
def zoo(): ...
class A: ...
@bar
class B:
def BMethod(self) -> None: ...
@overload
def BMethod(self, arg: List[str]) -> None: ...
class C: ...
@hmm
class D: ...
class E: ...
@baz
def foo() -> None: ...
class F(A, C): ...
def spam() -> None: ...
@overload
def spam(arg: str) -> str: ...
var: int = 1
def eggs() -> Union[str, int]: ...

View file

@ -0,0 +1,5 @@
# Regression test for #3427, which reproes only with line length <= 6
def f():
"""
x
"""

View file

@ -0,0 +1,5 @@
# Regression test for #3427, which reproes only with line length <= 6
def f():
"""
x
"""

View file

@ -0,0 +1,292 @@
x = "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
x += "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
y = "Short string"
print(
"This is a really long string inside of a print statement with extra arguments attached at the end of it.",
x,
y,
z,
)
print(
"This is a really long string inside of a print statement with no extra arguments attached at the end of it."
)
D1 = {
"The First": "This is a really long string that can't possibly be expected to fit all together on one line. Also it is inside a dictionary, so formatting is more difficult.",
"The Second": "This is another really really (not really) long string that also can't be expected to fit on one line and is, like the other string, inside a dictionary.",
}
D2 = {
1.0: "This is a really long string that can't possibly be expected to fit all together on one line. Also it is inside a dictionary, so formatting is more difficult.",
2.0: "This is another really really (not really) long string that also can't be expected to fit on one line and is, like the other string, inside a dictionary.",
}
D3 = {
x: "This is a really long string that can't possibly be expected to fit all together on one line. Also it is inside a dictionary, so formatting is more difficult.",
y: "This is another really really (not really) long string that also can't be expected to fit on one line and is, like the other string, inside a dictionary.",
}
D4 = {
"A long and ridiculous {}".format(
string_key
): "This is a really really really long string that has to go i,side of a dictionary. It is soooo bad.",
some_func(
"calling", "some", "stuff"
): "This is a really really really long string that has to go inside of a dictionary. It is {soooo} bad (#{x}).".format(
sooo="soooo", x=2
),
"A %s %s"
% (
"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),
}
func_with_keywords(
my_arg,
my_kwarg="Long keyword strings also need to be wrapped, but they will probably need to be handled a little bit differently.",
)
bad_split1 = (
"But what should happen when code has already been formatted but in the wrong way? Like"
" with a space at the end instead of the beginning. Or what about when it is split too soon?"
)
bad_split2 = (
"But what should happen when code has already "
"been formatted but in the wrong way? Like "
"with a space at the end instead of the "
"beginning. Or what about when it is split too "
"soon? In the case of a split that is too "
"short, black will try to honer the custom "
"split."
)
bad_split3 = (
"What if we have inline comments on " # First Comment
"each line of a bad split? In that " # Second Comment
"case, we should just leave it alone." # Third Comment
)
bad_split_func1(
"But what should happen when code has already "
"been formatted but in the wrong way? Like "
"with a space at the end instead of the "
"beginning. Or what about when it is split too "
"soon? In the case of a split that is too "
"short, black will try to honer the custom "
"split.",
xxx,
yyy,
zzz,
)
bad_split_func2(
xxx,
yyy,
zzz,
long_string_kwarg="But what should happen when code has already been formatted but in the wrong way? Like "
"with a space at the end instead of the beginning. Or what about when it is split too "
"soon?",
)
bad_split_func3(
(
"But what should happen when code has already "
r"been formatted but in the wrong way? Like "
"with a space at the end instead of the "
r"beginning. Or what about when it is split too "
r"soon? In the case of a split that is too "
"short, black will try to honer the custom "
"split."
),
xxx,
yyy,
zzz,
)
raw_string = r"This is a long raw string. When re-formatting this string, black needs to make sure it prepends the 'r' onto the new string."
fmt_string1 = "We also need to be sure to preserve any and all {} which may or may not be attached to the string in question.".format(
"method calls"
)
fmt_string2 = "But what about when the string is {} but {}".format(
"short",
"the method call is really really really really really really really really long?",
)
old_fmt_string1 = (
"While we are on the topic of %s, we should also note that old-style formatting must also be preserved, since some %s still uses it."
% ("formatting", "code")
)
old_fmt_string2 = "This is a %s %s %s %s" % (
"really really really really really",
"old",
"way to format strings!",
"Use f-strings instead!",
)
old_fmt_string3 = (
"Whereas only the strings after the percent sign were long in the last example, this example uses a long initial string as well. This is another %s %s %s %s"
% (
"really really really really really",
"old",
"way to format strings!",
"Use f-strings instead!",
)
)
fstring = f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one."
fstring_with_no_fexprs = f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever."
comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top.
arg_comment_string = print(
"Long lines with inline comments which are apart of (and not the only member of) an argument list should have their comments appended to the reformatted string's enclosing left parentheses.", # This comment stays on the bottom.
"Arg #2",
"Arg #3",
"Arg #4",
"Arg #5",
)
pragma_comment_string1 = "Lines which end with an inline pragma comment of the form `# <pragma>: <...>` should be left alone." # noqa: E501
pragma_comment_string2 = "Lines which end with an inline pragma comment of the form `# <pragma>: <...>` should be left alone." # noqa
"""This is a really really really long triple quote string and it should not be touched."""
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
assert (
some_type_of_boolean_expression
), "Followed by a really really really long string that is used to provide context to the AssertionError exception."
assert (
some_type_of_boolean_expression
), "Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string {}.".format(
"formatting"
)
assert some_type_of_boolean_expression, (
"Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string %s."
% "formatting"
)
assert some_type_of_boolean_expression, (
"Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic %s %s."
% ("string", "formatting")
)
some_function_call(
"With a reallly generic name and with a really really long string that is, at some point down the line, "
+ added
+ " to a variable and then added to another string."
)
some_function_call(
"With a reallly generic name and with a really really long string that is, at some point down the line, "
+ added
+ " to a variable and then added to another string. But then what happens when the final string is also supppppperrrrr long?! Well then that second (realllllllly long) string should be split too.",
"and a second argument",
and_a_third,
)
return "A really really really really really really really really really really really really really long {} {}".format(
"return", "value"
)
func_with_bad_comma(
"This is a really long string argument to a function that has a trailing comma which should NOT be there.",
)
func_with_bad_comma(
"This is a really long string argument to a function that has a trailing comma which should NOT be there.", # comment after comma
)
func_with_bad_comma(
(
"This is a really long string argument to a function that has a trailing comma"
" which should NOT be there."
),
)
func_with_bad_comma(
(
"This is a really long string argument to a function that has a trailing comma"
" which should NOT be there."
), # comment after comma
)
func_with_bad_parens_that_wont_fit_in_one_line(
("short string that should have parens stripped"), x, y, z
)
func_with_bad_parens_that_wont_fit_in_one_line(
x, y, ("short string that should have parens stripped"), z
)
func_with_bad_parens(
("short string that should have parens stripped"),
x,
y,
z,
)
func_with_bad_parens(
x,
y,
("short string that should have parens stripped"),
z,
)
annotated_variable: Final = (
"This is a large "
+ STRING
+ " that has been "
+ 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."
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 \\\\"
backslashes = "This is a really 'long' string with \"embedded double quotes\" and 'single' quotes that also handles checking for an odd number of backslashes \\\", like this...\\\\\\"
short_string = "Hi" " there."
func_call(short_string=("Hi" " there."))
raw_strings = r"Don't" " get" r" merged" " unless they are all raw."
def foo():
yield "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
x = f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four."
long_unmergable_string_with_pragma = (
"This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore
" of it."
)
long_unmergable_string_with_pragma = (
"This is a really long string that can't be merged because it has a likely pragma at the end" # noqa
" of it."
)
long_unmergable_string_with_pragma = (
"This is a really long string that can't be merged because it has a likely pragma at the end" # pylint: disable=some-pylint-check
" of it."
)

View file

@ -0,0 +1,292 @@
x = "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
x += "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
y = "Short string"
print(
"This is a really long string inside of a print statement with extra arguments attached at the end of it.",
x,
y,
z,
)
print(
"This is a really long string inside of a print statement with no extra arguments attached at the end of it."
)
D1 = {
"The First": "This is a really long string that can't possibly be expected to fit all together on one line. Also it is inside a dictionary, so formatting is more difficult.",
"The Second": "This is another really really (not really) long string that also can't be expected to fit on one line and is, like the other string, inside a dictionary.",
}
D2 = {
1.0: "This is a really long string that can't possibly be expected to fit all together on one line. Also it is inside a dictionary, so formatting is more difficult.",
2.0: "This is another really really (not really) long string that also can't be expected to fit on one line and is, like the other string, inside a dictionary.",
}
D3 = {
x: "This is a really long string that can't possibly be expected to fit all together on one line. Also it is inside a dictionary, so formatting is more difficult.",
y: "This is another really really (not really) long string that also can't be expected to fit on one line and is, like the other string, inside a dictionary.",
}
D4 = {
"A long and ridiculous {}".format(
string_key
): "This is a really really really long string that has to go i,side of a dictionary. It is soooo bad.",
some_func(
"calling", "some", "stuff"
): "This is a really really really long string that has to go inside of a dictionary. It is {soooo} bad (#{x}).".format(
sooo="soooo", x=2
),
"A %s %s"
% (
"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),
}
func_with_keywords(
my_arg,
my_kwarg="Long keyword strings also need to be wrapped, but they will probably need to be handled a little bit differently.",
)
bad_split1 = (
"But what should happen when code has already been formatted but in the wrong way? Like"
" with a space at the end instead of the beginning. Or what about when it is split too soon?"
)
bad_split2 = (
"But what should happen when code has already "
"been formatted but in the wrong way? Like "
"with a space at the end instead of the "
"beginning. Or what about when it is split too "
"soon? In the case of a split that is too "
"short, black will try to honer the custom "
"split."
)
bad_split3 = (
"What if we have inline comments on " # First Comment
"each line of a bad split? In that " # Second Comment
"case, we should just leave it alone." # Third Comment
)
bad_split_func1(
"But what should happen when code has already "
"been formatted but in the wrong way? Like "
"with a space at the end instead of the "
"beginning. Or what about when it is split too "
"soon? In the case of a split that is too "
"short, black will try to honer the custom "
"split.",
xxx,
yyy,
zzz,
)
bad_split_func2(
xxx,
yyy,
zzz,
long_string_kwarg="But what should happen when code has already been formatted but in the wrong way? Like "
"with a space at the end instead of the beginning. Or what about when it is split too "
"soon?",
)
bad_split_func3(
(
"But what should happen when code has already "
r"been formatted but in the wrong way? Like "
"with a space at the end instead of the "
r"beginning. Or what about when it is split too "
r"soon? In the case of a split that is too "
"short, black will try to honer the custom "
"split."
),
xxx,
yyy,
zzz,
)
raw_string = r"This is a long raw string. When re-formatting this string, black needs to make sure it prepends the 'r' onto the new string."
fmt_string1 = "We also need to be sure to preserve any and all {} which may or may not be attached to the string in question.".format(
"method calls"
)
fmt_string2 = "But what about when the string is {} but {}".format(
"short",
"the method call is really really really really really really really really long?",
)
old_fmt_string1 = (
"While we are on the topic of %s, we should also note that old-style formatting must also be preserved, since some %s still uses it."
% ("formatting", "code")
)
old_fmt_string2 = "This is a %s %s %s %s" % (
"really really really really really",
"old",
"way to format strings!",
"Use f-strings instead!",
)
old_fmt_string3 = (
"Whereas only the strings after the percent sign were long in the last example, this example uses a long initial string as well. This is another %s %s %s %s"
% (
"really really really really really",
"old",
"way to format strings!",
"Use f-strings instead!",
)
)
fstring = f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one."
fstring_with_no_fexprs = f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever."
comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top.
arg_comment_string = print(
"Long lines with inline comments which are apart of (and not the only member of) an argument list should have their comments appended to the reformatted string's enclosing left parentheses.", # This comment stays on the bottom.
"Arg #2",
"Arg #3",
"Arg #4",
"Arg #5",
)
pragma_comment_string1 = "Lines which end with an inline pragma comment of the form `# <pragma>: <...>` should be left alone." # noqa: E501
pragma_comment_string2 = "Lines which end with an inline pragma comment of the form `# <pragma>: <...>` should be left alone." # noqa
"""This is a really really really long triple quote string and it should not be touched."""
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
assert (
some_type_of_boolean_expression
), "Followed by a really really really long string that is used to provide context to the AssertionError exception."
assert (
some_type_of_boolean_expression
), "Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string {}.".format(
"formatting"
)
assert some_type_of_boolean_expression, (
"Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic string %s."
% "formatting"
)
assert some_type_of_boolean_expression, (
"Followed by a really really really long string that is used to provide context to the AssertionError exception, which uses dynamic %s %s."
% ("string", "formatting")
)
some_function_call(
"With a reallly generic name and with a really really long string that is, at some point down the line, "
+ added
+ " to a variable and then added to another string."
)
some_function_call(
"With a reallly generic name and with a really really long string that is, at some point down the line, "
+ added
+ " to a variable and then added to another string. But then what happens when the final string is also supppppperrrrr long?! Well then that second (realllllllly long) string should be split too.",
"and a second argument",
and_a_third,
)
return "A really really really really really really really really really really really really really long {} {}".format(
"return", "value"
)
func_with_bad_comma(
"This is a really long string argument to a function that has a trailing comma which should NOT be there.",
)
func_with_bad_comma(
"This is a really long string argument to a function that has a trailing comma which should NOT be there.", # comment after comma
)
func_with_bad_comma(
(
"This is a really long string argument to a function that has a trailing comma"
" which should NOT be there."
),
)
func_with_bad_comma(
(
"This is a really long string argument to a function that has a trailing comma"
" which should NOT be there."
), # comment after comma
)
func_with_bad_parens_that_wont_fit_in_one_line(
("short string that should have parens stripped"), x, y, z
)
func_with_bad_parens_that_wont_fit_in_one_line(
x, y, ("short string that should have parens stripped"), z
)
func_with_bad_parens(
("short string that should have parens stripped"),
x,
y,
z,
)
func_with_bad_parens(
x,
y,
("short string that should have parens stripped"),
z,
)
annotated_variable: Final = (
"This is a large "
+ STRING
+ " that has been "
+ 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."
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 \\\\"
backslashes = "This is a really 'long' string with \"embedded double quotes\" and 'single' quotes that also handles checking for an odd number of backslashes \\\", like this...\\\\\\"
short_string = "Hi" " there."
func_call(short_string=("Hi" " there."))
raw_strings = r"Don't" " get" r" merged" " unless they are all raw."
def foo():
yield "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
x = f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four."
long_unmergable_string_with_pragma = (
"This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore
" of it."
)
long_unmergable_string_with_pragma = (
"This is a really long string that can't be merged because it has a likely pragma at the end" # noqa
" of it."
)
long_unmergable_string_with_pragma = (
"This is a really long string that can't be merged because it has a likely pragma at the end" # pylint: disable=some-pylint-check
" of it."
)

View file

@ -0,0 +1,3 @@
# A comment-only file, with no final EOL character
# This triggers https://bugs.python.org/issue2142
# This is the line without the EOL character

View file

@ -0,0 +1,3 @@
# A comment-only file, with no final EOL character
# This triggers https://bugs.python.org/issue2142
# This is the line without the EOL character

View file

@ -0,0 +1 @@
importA;()<<0**0#

View file

@ -0,0 +1,6 @@
importA
(
()
<< 0
** 0
) #

View file

@ -0,0 +1,57 @@
''''''
'\''
'"'
"'"
"\""
"Hello"
"Don't do that"
'Here is a "'
'What\'s the deal here?'
"What's the deal \"here\"?"
"And \"here\"?"
"""Strings with "" in them"""
'''Strings with "" in them'''
'''Here's a "'''
'''Here's a " '''
'''Just a normal triple
quote'''
f"just a normal {f} string"
f'''This is a triple-quoted {f}-string'''
f'MOAR {" ".join([])}'
f"MOAR {' '.join([])}"
r"raw string ftw"
r'Date d\'expiration:(.*)'
r'Tricky "quote'
r'Not-so-tricky \"quote'
rf'{yay}'
'\n\
The \"quick\"\n\
brown fox\n\
jumps over\n\
the \'lazy\' dog.\n\
'
re.compile(r'[\\"]')
"x = ''; y = \"\""
"x = '''; y = \"\""
"x = ''''; y = \"\""
"x = '' ''; y = \"\""
"x = ''; y = \"\"\""
"x = '''; y = \"\"\"\""
"x = ''''; y = \"\"\"\"\""
"x = '' ''; y = \"\"\"\"\""
'unnecessary \"\"escaping'
"unnecessary \'\'escaping"
'\\""'
"\\''"
'Lots of \\\\\\\\\'quotes\''
f'{y * " "} \'{z}\''
f'{{y * " "}} \'{z}\''
f'\'{z}\' {y * " "}'
f'{y * x} \'{z}\''
'\'{z}\' {y * " "}'
'{y * x} \'{z}\''
# We must bail out if changing the quotes would introduce backslashes in f-string
# expressions. xref: https://github.com/psf/black/issues/2348
f"\"{b}\"{' ' * (long-len(b)+1)}: \"{sts}\",\n"
f"\"{a}\"{'hello' * b}\"{c}\""

View file

@ -0,0 +1,52 @@
""""""
"'"
'"'
"'"
'"'
"Hello"
"Don't do that"
'Here is a "'
"What's the deal here?"
'What\'s the deal "here"?'
'And "here"?'
"""Strings with "" in them"""
"""Strings with "" in them"""
'''Here's a "'''
"""Here's a " """
"""Just a normal triple
quote"""
f"just a normal {f} string"
f"""This is a triple-quoted {f}-string"""
f'MOAR {" ".join([])}'
f"MOAR {' '.join([])}"
r"raw string ftw"
r"Date d\'expiration:(.*)"
r'Tricky "quote'
r"Not-so-tricky \"quote"
rf"{yay}"
"\nThe \"quick\"\nbrown fox\njumps over\nthe 'lazy' dog.\n"
re.compile(r'[\\"]')
"x = ''; y = \"\""
"x = '''; y = \"\""
"x = ''''; y = \"\""
"x = '' ''; y = \"\""
'x = \'\'; y = """'
'x = \'\'\'; y = """"'
'x = \'\'\'\'; y = """""'
'x = \'\' \'\'; y = """""'
'unnecessary ""escaping'
"unnecessary ''escaping"
'\\""'
"\\''"
"Lots of \\\\\\\\'quotes'"
f'{y * " "} \'{z}\''
f"{{y * \" \"}} '{z}'"
f'\'{z}\' {y * " "}'
f"{y * x} '{z}'"
"'{z}' {y * \" \"}"
"{y * x} '{z}'"
# We must bail out if changing the quotes would introduce backslashes in f-string
# expressions. xref: https://github.com/psf/black/issues/2348
f"\"{b}\"{' ' * (long-len(b)+1)}: \"{sts}\",\n"
f"\"{a}\"{'hello' * b}\"{c}\""

View file

@ -0,0 +1,21 @@
with (CtxManager() as example):
...
with (CtxManager1(), CtxManager2()):
...
with (CtxManager1() as example, CtxManager2()):
...
with (CtxManager1(), CtxManager2() as example):
...
with (CtxManager1() as example1, CtxManager2() as example2):
...
with (
CtxManager1() as example1,
CtxManager2() as example2,
CtxManager3() as example3,
):
...

View file

@ -0,0 +1,21 @@
with CtxManager() as example:
...
with CtxManager1(), CtxManager2():
...
with CtxManager1() as example, CtxManager2():
...
with CtxManager1(), CtxManager2() as example:
...
with CtxManager1() as example1, CtxManager2() as example2:
...
with (
CtxManager1() as example1,
CtxManager2() as example2,
CtxManager3() as example3,
):
...

View file

@ -0,0 +1,144 @@
# Cases sampled from Lib/test/test_patma.py
# case black_test_patma_098
match x:
case -0j:
y = 0
# case black_test_patma_142
match x:
case bytes(z):
y = 0
# case black_test_patma_073
match x:
case 0 if 0:
y = 0
case 0 if 1:
y = 1
# case black_test_patma_006
match 3:
case 0 | 1 | 2 | 3:
x = True
# case black_test_patma_049
match x:
case [0, 1] | [1, 0]:
y = 0
# case black_check_sequence_then_mapping
match x:
case [*_]:
return "seq"
case {}:
return "map"
# case black_test_patma_035
match x:
case {0: [1, 2, {}]}:
y = 0
case {0: [1, 2, {}] | True} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}:
y = 1
case []:
y = 2
# case black_test_patma_107
match x:
case 0.25 + 1.75j:
y = 0
# case black_test_patma_097
match x:
case -0j:
y = 0
# case black_test_patma_007
match 4:
case 0 | 1 | 2 | 3:
x = True
# case black_test_patma_154
match x:
case 0 if x:
y = 0
# case black_test_patma_134
match x:
case {1: 0}:
y = 0
case {0: 0}:
y = 1
case {**z}:
y = 2
# case black_test_patma_185
match Seq():
case [*_]:
y = 0
# case black_test_patma_063
match x:
case 1:
y = 0
case 1:
y = 1
# case black_test_patma_248
match x:
case {"foo": bar}:
y = bar
# case black_test_patma_019
match (0, 1, 2):
case [0, 1, *x, 2]:
y = 0
# case black_test_patma_052
match x:
case [0]:
y = 0
case [1, 0] if (x := x[:0]):
y = 1
case [1, 0]:
y = 2
# case black_test_patma_191
match w:
case [x, y, *_]:
z = 0
# case black_test_patma_110
match x:
case -0.25 - 1.75j:
y = 0
# case black_test_patma_151
match (x,):
case [y]:
z = 0
# case black_test_patma_114
match x:
case A.B.C.D:
y = 0
# case black_test_patma_232
match x:
case None:
y = 0
# case black_test_patma_058
match x:
case 0:
y = 0
# case black_test_patma_233
match x:
case False:
y = 0
# case black_test_patma_078
match x:
case []:
y = 0
case [""]:
y = 1
case "":
y = 2
# case black_test_patma_156
match x:
case z:
y = 0
# case black_test_patma_189
match w:
case [x, y, *rest]:
z = 0
# case black_test_patma_042
match x:
case (0 as z) | (1 as z) | (2 as z) if z == x % 2:
y = 0
# case black_test_patma_034
match x:
case {0: [1, 2, {}]}:
y = 0
case {0: [1, 2, {}] | False} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}:
y = 1
case []:
y = 2

View file

@ -0,0 +1,144 @@
# Cases sampled from Lib/test/test_patma.py
# case black_test_patma_098
match x:
case -0j:
y = 0
# case black_test_patma_142
match x:
case bytes(z):
y = 0
# case black_test_patma_073
match x:
case 0 if 0:
y = 0
case 0 if 1:
y = 1
# case black_test_patma_006
match 3:
case 0 | 1 | 2 | 3:
x = True
# case black_test_patma_049
match x:
case [0, 1] | [1, 0]:
y = 0
# case black_check_sequence_then_mapping
match x:
case [*_]:
return "seq"
case {}:
return "map"
# case black_test_patma_035
match x:
case {0: [1, 2, {}]}:
y = 0
case {0: [1, 2, {}] | True} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}:
y = 1
case []:
y = 2
# case black_test_patma_107
match x:
case 0.25 + 1.75j:
y = 0
# case black_test_patma_097
match x:
case -0j:
y = 0
# case black_test_patma_007
match 4:
case 0 | 1 | 2 | 3:
x = True
# case black_test_patma_154
match x:
case 0 if x:
y = 0
# case black_test_patma_134
match x:
case {1: 0}:
y = 0
case {0: 0}:
y = 1
case {**z}:
y = 2
# case black_test_patma_185
match Seq():
case [*_]:
y = 0
# case black_test_patma_063
match x:
case 1:
y = 0
case 1:
y = 1
# case black_test_patma_248
match x:
case {"foo": bar}:
y = bar
# case black_test_patma_019
match (0, 1, 2):
case [0, 1, *x, 2]:
y = 0
# case black_test_patma_052
match x:
case [0]:
y = 0
case [1, 0] if (x := x[:0]):
y = 1
case [1, 0]:
y = 2
# case black_test_patma_191
match w:
case [x, y, *_]:
z = 0
# case black_test_patma_110
match x:
case -0.25 - 1.75j:
y = 0
# case black_test_patma_151
match (x,):
case [y]:
z = 0
# case black_test_patma_114
match x:
case A.B.C.D:
y = 0
# case black_test_patma_232
match x:
case None:
y = 0
# case black_test_patma_058
match x:
case 0:
y = 0
# case black_test_patma_233
match x:
case False:
y = 0
# case black_test_patma_078
match x:
case []:
y = 0
case [""]:
y = 1
case "":
y = 2
# case black_test_patma_156
match x:
case z:
y = 0
# case black_test_patma_189
match w:
case [x, y, *rest]:
z = 0
# case black_test_patma_042
match x:
case (0 as z) | (1 as z) | (2 as z) if z == x % 2:
y = 0
# case black_test_patma_034
match x:
case {0: [1, 2, {}]}:
y = 0
case {0: [1, 2, {}] | False} | {1: [[]]} | {0: [1, 2, {}]} | [] | "X" | {}:
y = 1
case []:
y = 2

View file

@ -0,0 +1,119 @@
import match
match something:
case [a as b]:
print(b)
case [a as b, c, d, e as f]:
print(f)
case Point(a as b):
print(b)
case Point(int() as x, int() as y):
print(x, y)
match = 1
case: int = re.match(something)
match re.match(case):
case type("match", match):
pass
case match:
pass
def func(match: case, case: match) -> case:
match Something():
case func(match, case):
...
case another:
...
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
match a, *b, c:
case [*_]:
assert "seq" == _
case {}:
assert "map" == b
match match(
case,
match(
match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match
),
case,
):
case case(
match=case,
case=re.match(
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
),
):
pass
case [a as match]:
pass
case case:
pass
match match:
case case:
pass
match a, *b(), c:
case d, *f, g:
pass
match something:
case {
"key": key as key_1,
"password": PASS.ONE | PASS.TWO | PASS.THREE as password,
}:
pass
case {"maybe": something(complicated as this) as that}:
pass
match something:
case 1 as a:
pass
case 2 as b, 3 as c:
pass
case 4 as d, (5 as e), (6 | 7 as g), *h:
pass
match bar1:
case Foo(aa=Callable() as aa, bb=int()):
print(bar1.aa, bar1.bb)
case _:
print("no match", "\n")
match bar1:
case Foo(
normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u
):
pass

View file

@ -0,0 +1,119 @@
import match
match something:
case [a as b]:
print(b)
case [a as b, c, d, e as f]:
print(f)
case Point(a as b):
print(b)
case Point(int() as x, int() as y):
print(x, y)
match = 1
case: int = re.match(something)
match re.match(case):
case type("match", match):
pass
case match:
pass
def func(match: case, case: match) -> case:
match Something():
case func(match, case):
...
case another:
...
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
match a, *b, c:
case [*_]:
assert "seq" == _
case {}:
assert "map" == b
match match(
case,
match(
match, case, match, looooooooooooooooooooooooooooooooooooong, match, case, match
),
case,
):
case case(
match=case,
case=re.match(
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
),
):
pass
case [a as match]:
pass
case case:
pass
match match:
case case:
pass
match a, *b(), c:
case d, *f, g:
pass
match something:
case {
"key": key as key_1,
"password": PASS.ONE | PASS.TWO | PASS.THREE as password,
}:
pass
case {"maybe": something(complicated as this) as that}:
pass
match something:
case 1 as a:
pass
case 2 as b, 3 as c:
pass
case 4 as d, (5 as e), (6 | 7 as g), *h:
pass
match bar1:
case Foo(aa=Callable() as aa, bb=int()):
print(bar1.aa, bar1.bb)
case _:
print("no match", "\n")
match bar1:
case Foo(
normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u
):
pass

View file

@ -0,0 +1,107 @@
re.match()
match = a
with match() as match:
match = f"{match}"
re.match()
match = a
with match() as match:
match = f"{match}"
def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
if not target_versions:
# No target_version specified, so try all grammars.
return [
# Python 3.7+
pygram.python_grammar_no_print_statement_no_exec_statement_async_keywords,
# Python 3.0-3.6
pygram.python_grammar_no_print_statement_no_exec_statement,
# Python 2.7 with future print_function import
pygram.python_grammar_no_print_statement,
# Python 2.7
pygram.python_grammar,
]
match match:
case case:
match match:
case case:
pass
if all(version.is_python2() for version in target_versions):
# Python 2-only code, so try Python 2 grammars.
return [
# Python 2.7 with future print_function import
pygram.python_grammar_no_print_statement,
# Python 2.7
pygram.python_grammar,
]
re.match()
match = a
with match() as match:
match = f"{match}"
def test_patma_139(self):
x = False
match x:
case bool(z):
y = 0
self.assertIs(x, False)
self.assertEqual(y, 0)
self.assertIs(z, x)
# Python 3-compatible code, so only try Python 3 grammar.
grammars = []
if supports_feature(target_versions, Feature.PATTERN_MATCHING):
# Python 3.10+
grammars.append(pygram.python_grammar_soft_keywords)
# If we have to parse both, try to parse async as a keyword first
if not supports_feature(
target_versions, Feature.ASYNC_IDENTIFIERS
) and not supports_feature(target_versions, Feature.PATTERN_MATCHING):
# Python 3.7-3.9
grammars.append(
pygram.python_grammar_no_print_statement_no_exec_statement_async_keywords
)
if not supports_feature(target_versions, Feature.ASYNC_KEYWORDS):
# Python 3.0-3.6
grammars.append(pygram.python_grammar_no_print_statement_no_exec_statement)
def test_patma_155(self):
x = 0
y = None
match x:
case 1e1000:
y = 0
self.assertEqual(x, 0)
self.assertIs(y, None)
x = range(3)
match x:
case [y, case as x, z]:
w = 0
# At least one of the above branches must have been taken, because every Python
# version has exactly one of the two 'ASYNC_*' flags
return grammars
def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -> Node:
"""Given a string with source, return the lib2to3 Node."""
if not src_txt.endswith("\n"):
src_txt += "\n"
grammars = get_grammars(set(target_versions))
re.match()
match = a
with match() as match:
match = f"{match}"
re.match()
match = a
with match() as match:
match = f"{match}"

View file

@ -0,0 +1,107 @@
re.match()
match = a
with match() as match:
match = f"{match}"
re.match()
match = a
with match() as match:
match = f"{match}"
def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
if not target_versions:
# No target_version specified, so try all grammars.
return [
# Python 3.7+
pygram.python_grammar_no_print_statement_no_exec_statement_async_keywords,
# Python 3.0-3.6
pygram.python_grammar_no_print_statement_no_exec_statement,
# Python 2.7 with future print_function import
pygram.python_grammar_no_print_statement,
# Python 2.7
pygram.python_grammar,
]
match match:
case case:
match match:
case case:
pass
if all(version.is_python2() for version in target_versions):
# Python 2-only code, so try Python 2 grammars.
return [
# Python 2.7 with future print_function import
pygram.python_grammar_no_print_statement,
# Python 2.7
pygram.python_grammar,
]
re.match()
match = a
with match() as match:
match = f"{match}"
def test_patma_139(self):
x = False
match x:
case bool(z):
y = 0
self.assertIs(x, False)
self.assertEqual(y, 0)
self.assertIs(z, x)
# Python 3-compatible code, so only try Python 3 grammar.
grammars = []
if supports_feature(target_versions, Feature.PATTERN_MATCHING):
# Python 3.10+
grammars.append(pygram.python_grammar_soft_keywords)
# If we have to parse both, try to parse async as a keyword first
if not supports_feature(
target_versions, Feature.ASYNC_IDENTIFIERS
) and not supports_feature(target_versions, Feature.PATTERN_MATCHING):
# Python 3.7-3.9
grammars.append(
pygram.python_grammar_no_print_statement_no_exec_statement_async_keywords
)
if not supports_feature(target_versions, Feature.ASYNC_KEYWORDS):
# Python 3.0-3.6
grammars.append(pygram.python_grammar_no_print_statement_no_exec_statement)
def test_patma_155(self):
x = 0
y = None
match x:
case 1e1000:
y = 0
self.assertEqual(x, 0)
self.assertIs(y, None)
x = range(3)
match x:
case [y, case as x, z]:
w = 0
# At least one of the above branches must have been taken, because every Python
# version has exactly one of the two 'ASYNC_*' flags
return grammars
def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -> Node:
"""Given a string with source, return the lib2to3 Node."""
if not src_txt.endswith("\n"):
src_txt += "\n"
grammars = get_grammars(set(target_versions))
re.match()
match = a
with match() as match:
match = f"{match}"
re.match()
match = a
with match() as match:
match = f"{match}"

View file

@ -0,0 +1,92 @@
# Cases sampled from PEP 636 examples
match command.split():
case [action, obj]:
... # interpret action, obj
match command.split():
case [action]:
... # interpret single-verb action
case [action, obj]:
... # interpret action, obj
match command.split():
case ["quit"]:
print("Goodbye!")
quit_game()
case ["look"]:
current_room.describe()
case ["get", obj]:
character.get(obj, current_room)
case ["go", direction]:
current_room = current_room.neighbor(direction)
# The rest of your commands go here
match command.split():
case ["drop", *objects]:
for obj in objects:
character.drop(obj, current_room)
# The rest of your commands go here
match command.split():
case ["quit"]:
pass
case ["go", direction]:
print("Going:", direction)
case ["drop", *objects]:
print("Dropping: ", *objects)
case _:
print(f"Sorry, I couldn't understand {command!r}")
match command.split():
case ["north"] | ["go", "north"]:
current_room = current_room.neighbor("north")
case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]:
... # Code for picking up the given object
match command.split():
case ["go", ("north" | "south" | "east" | "west")]:
current_room = current_room.neighbor(...)
# how do I know which direction to go?
match command.split():
case ["go", ("north" | "south" | "east" | "west") as direction]:
current_room = current_room.neighbor(direction)
match command.split():
case ["go", direction] if direction in current_room.exits:
current_room = current_room.neighbor(direction)
case ["go", _]:
print("Sorry, you can't go that way")
match event.get():
case Click(position=(x, y)):
handle_click_at(x, y)
case KeyPress(key_name="Q") | Quit():
game.quit()
case KeyPress(key_name="up arrow"):
game.go_north()
case KeyPress():
pass # Ignore other keystrokes
case other_event:
raise ValueError(f"Unrecognized event: {other_event}")
match event.get():
case Click((x, y), button=Button.LEFT): # This is a left click
handle_click_at(x, y)
case Click():
pass # ignore other clicks
def where_is(point):
match point:
case Point(x=0, y=0):
print("Origin")
case Point(x=0, y=y):
print(f"Y={y}")
case Point(x=x, y=0):
print(f"X={x}")
case Point():
print("Somewhere else")
case _:
print("Not a point")

View file

@ -0,0 +1,92 @@
# Cases sampled from PEP 636 examples
match command.split():
case [action, obj]:
... # interpret action, obj
match command.split():
case [action]:
... # interpret single-verb action
case [action, obj]:
... # interpret action, obj
match command.split():
case ["quit"]:
print("Goodbye!")
quit_game()
case ["look"]:
current_room.describe()
case ["get", obj]:
character.get(obj, current_room)
case ["go", direction]:
current_room = current_room.neighbor(direction)
# The rest of your commands go here
match command.split():
case ["drop", *objects]:
for obj in objects:
character.drop(obj, current_room)
# The rest of your commands go here
match command.split():
case ["quit"]:
pass
case ["go", direction]:
print("Going:", direction)
case ["drop", *objects]:
print("Dropping: ", *objects)
case _:
print(f"Sorry, I couldn't understand {command!r}")
match command.split():
case ["north"] | ["go", "north"]:
current_room = current_room.neighbor("north")
case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]:
... # Code for picking up the given object
match command.split():
case ["go", ("north" | "south" | "east" | "west")]:
current_room = current_room.neighbor(...)
# how do I know which direction to go?
match command.split():
case ["go", ("north" | "south" | "east" | "west") as direction]:
current_room = current_room.neighbor(direction)
match command.split():
case ["go", direction] if direction in current_room.exits:
current_room = current_room.neighbor(direction)
case ["go", _]:
print("Sorry, you can't go that way")
match event.get():
case Click(position=(x, y)):
handle_click_at(x, y)
case KeyPress(key_name="Q") | Quit():
game.quit()
case KeyPress(key_name="up arrow"):
game.go_north()
case KeyPress():
pass # Ignore other keystrokes
case other_event:
raise ValueError(f"Unrecognized event: {other_event}")
match event.get():
case Click((x, y), button=Button.LEFT): # This is a left click
handle_click_at(x, y)
case Click():
pass # ignore other clicks
def where_is(point):
match point:
case Point(x=0, y=0):
print("Origin")
case Point(x=0, y=y):
print(f"Y={y}")
case Point(x=x, y=0):
print(f"X={x}")
case Point():
print("Somewhere else")
case _:
print("Not a point")

View file

@ -0,0 +1,53 @@
match something:
case b(): print(1+1)
case c(
very_complex=True,
perhaps_even_loooooooooooooooooooooooooooooooooooooong=- 1
): print(1)
case c(
very_complex=True,
perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1,
): print(2)
case a: pass
match(
arg # comment
)
match(
)
match(
)
case(
arg # comment
)
case(
)
case(
)
re.match(
something # fast
)
re.match(
)
match match(
):
case case(
arg, # comment
):
pass

View file

@ -0,0 +1,35 @@
match something:
case b():
print(1 + 1)
case c(
very_complex=True, perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1
):
print(1)
case c(
very_complex=True,
perhaps_even_loooooooooooooooooooooooooooooooooooooong=-1,
):
print(2)
case a:
pass
match(arg) # comment
match()
match()
case(arg) # comment
case()
case()
re.match(something) # fast
re.match()
match match():
case case(
arg, # comment
):
pass

View file

@ -0,0 +1,15 @@
# Unparenthesized walruses are now allowed in indices since Python 3.10.
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):
if match.group(2) == data_not_available:
# Error OK to ignore.
pass
f(a := b + c for c in range(10))
f((a := b + c for c in range(10)), x)
f(y=(a := b + c for c in range(10)))
f(x, (a := b + c for c in range(10)), y=z, **q)

View file

@ -0,0 +1,15 @@
# Unparenthesized walruses are now allowed in indices since Python 3.10.
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):
if match.group(2) == data_not_available:
# Error OK to ignore.
pass
f(a := b + c for c in range(10))
f((a := b + c for c in range(10)), x)
f(y=(a := b + c for c in range(10)))
f(x, (a := b + c for c in range(10)), y=z, **q)

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,13 @@
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,27 @@
for x in *a, *b:
print(x)
for x in a, b, *c:
print(x)
for x in *a, b, c:
print(x)
for x in *a, b, *c:
print(x)
async for x in *a, *b:
print(x)
async for x in *a, b, *c:
print(x)
async for x in a, b, *c:
print(x)
async for x in (
*loooooooooooooooooooooong,
very,
*loooooooooooooooooooooooooooooooooooooooooooooooong,
):
print(x)

View file

@ -0,0 +1,27 @@
for x in *a, *b:
print(x)
for x in a, b, *c:
print(x)
for x in *a, b, c:
print(x)
for x in *a, b, *c:
print(x)
async for x in *a, *b:
print(x)
async for x in *a, b, *c:
print(x)
async for x in a, b, *c:
print(x)
async for x in (
*loooooooooooooooooooooong,
very,
*loooooooooooooooooooooooooooooooooooooooooooooooong,
):
print(x)

View file

@ -0,0 +1,53 @@
try:
raise OSError("blah")
except* ExceptionGroup as e:
pass
try:
async with trio.open_nursery() as nursery:
# Make two concurrent calls to child()
nursery.start_soon(child)
nursery.start_soon(child)
except* ValueError:
pass
try:
try:
raise ValueError(42)
except:
try:
raise TypeError(int)
except* Exception:
pass
1 / 0
except Exception as e:
exc = e
try:
try:
raise FalsyEG("eg", [TypeError(1), ValueError(2)])
except* TypeError as e:
tes = e
raise
except* ValueError as e:
ves = e
pass
except Exception as e:
exc = e
try:
try:
raise orig
except* (TypeError, ValueError) as e:
raise SyntaxError(3) from e
except BaseException as e:
exc = e
try:
try:
raise orig
except* OSError as e:
raise TypeError(3) from e
except ExceptionGroup as e:
exc = e

View file

@ -0,0 +1,53 @@
try:
raise OSError("blah")
except* ExceptionGroup as e:
pass
try:
async with trio.open_nursery() as nursery:
# Make two concurrent calls to child()
nursery.start_soon(child)
nursery.start_soon(child)
except* ValueError:
pass
try:
try:
raise ValueError(42)
except:
try:
raise TypeError(int)
except* Exception:
pass
1 / 0
except Exception as e:
exc = e
try:
try:
raise FalsyEG("eg", [TypeError(1), ValueError(2)])
except* TypeError as e:
tes = e
raise
except* ValueError as e:
ves = e
pass
except Exception as e:
exc = e
try:
try:
raise orig
except* (TypeError, ValueError) as e:
raise SyntaxError(3) from e
except BaseException as e:
exc = e
try:
try:
raise orig
except* OSError as e:
raise TypeError(3) from e
except ExceptionGroup as e:
exc = e

View file

@ -0,0 +1,55 @@
try:
raise OSError("blah")
except * ExceptionGroup as e:
pass
try:
async with trio.open_nursery() as nursery:
# Make two concurrent calls to child()
nursery.start_soon(child)
nursery.start_soon(child)
except *ValueError:
pass
try:
try:
raise ValueError(42)
except:
try:
raise TypeError(int)
except *(Exception):
pass
1 / 0
except Exception as e:
exc = e
try:
try:
raise FalsyEG("eg", [TypeError(1), ValueError(2)])
except \
*TypeError as e:
tes = e
raise
except * ValueError as e:
ves = e
pass
except Exception as e:
exc = e
try:
try:
raise orig
except *(TypeError, ValueError, *OTHER_EXCEPTIONS) as e:
raise SyntaxError(3) from e
except BaseException as e:
exc = e
try:
try:
raise orig
except\
* OSError as e:
raise TypeError(3) from e
except ExceptionGroup as e:
exc = e

View file

@ -0,0 +1,53 @@
try:
raise OSError("blah")
except* ExceptionGroup as e:
pass
try:
async with trio.open_nursery() as nursery:
# Make two concurrent calls to child()
nursery.start_soon(child)
nursery.start_soon(child)
except* ValueError:
pass
try:
try:
raise ValueError(42)
except:
try:
raise TypeError(int)
except* Exception:
pass
1 / 0
except Exception as e:
exc = e
try:
try:
raise FalsyEG("eg", [TypeError(1), ValueError(2)])
except* TypeError as e:
tes = e
raise
except* ValueError as e:
ves = e
pass
except Exception as e:
exc = e
try:
try:
raise orig
except* (TypeError, ValueError, *OTHER_EXCEPTIONS) as e:
raise SyntaxError(3) from e
except BaseException as e:
exc = e
try:
try:
raise orig
except* OSError as e:
raise TypeError(3) from e
except ExceptionGroup as e:
exc = e

View file

@ -0,0 +1,20 @@
#!/usr/bin/env python3.6
x = 123456789
x = 123456
x = .1
x = 1.
x = 1E+1
x = 1E-1
x = 1.000_000_01
x = 123456789.123456789
x = 123456789.123456789E123456789
x = 123456789E123456789
x = 123456789J
x = 123456789.123456789J
x = 0XB1ACC
x = 0B1011
x = 0O777
x = 0.000000006
x = 10000
x = 133333

View file

@ -0,0 +1,20 @@
#!/usr/bin/env python3.6
x = 123456789
x = 123456
x = 0.1
x = 1.0
x = 1e1
x = 1e-1
x = 1.000_000_01
x = 123456789.123456789
x = 123456789.123456789e123456789
x = 123456789e123456789
x = 123456789j
x = 123456789.123456789j
x = 0xB1ACC
x = 0b1011
x = 0o777
x = 0.000000006
x = 10000
x = 133333

View file

@ -0,0 +1,10 @@
#!/usr/bin/env python3.6
x = 123456789
x = 1_2_3_4_5_6_7
x = 1E+1
x = 0xb1acc
x = 0.00_00_006
x = 12_34_567J
x = .1_2
x = 1_2.

View file

@ -0,0 +1,10 @@
#!/usr/bin/env python3.6
x = 123456789
x = 1_2_3_4_5_6_7
x = 1e1
x = 0xB1ACC
x = 0.00_00_006
x = 12_34_567j
x = 0.1_2
x = 1_2.0

View file

@ -0,0 +1,30 @@
#!/usr/bin/env python3.7
def f():
return (i * 2 async for i in arange(42))
def g():
return (
something_long * something_long
async for something_long in async_generator(with_an_argument)
)
async def func():
if test:
out_batched = [
i
async for i in aitertools._async_map(
self.async_inc, arange(8), batch_size=3
)
]
def awaited_generator_value(n):
return (await awaitable for awaitable in awaitable_list)
def make_arange(n):
return (i * 2 for i in range(n) if await wrap(i))

View file

@ -0,0 +1,30 @@
#!/usr/bin/env python3.7
def f():
return (i * 2 async for i in arange(42))
def g():
return (
something_long * something_long
async for something_long in async_generator(with_an_argument)
)
async def func():
if test:
out_batched = [
i
async for i in aitertools._async_map(
self.async_inc, arange(8), batch_size=3
)
]
def awaited_generator_value(n):
return (await awaitable for awaitable in awaitable_list)
def make_arange(n):
return (i * 2 for i in range(n) if await wrap(i))

View file

@ -0,0 +1,44 @@
def positional_only_arg(a, /):
pass
def all_markers(a, b, /, c, d, *, e, f):
pass
def all_markers_with_args_and_kwargs(
a_long_one,
b_long_one,
/,
c_long_one,
d_long_one,
*args,
e_long_one,
f_long_one,
**kwargs,
):
pass
def all_markers_with_defaults(a, b=1, /, c=2, d=3, *, e=4, f=5):
pass
def long_one_with_long_parameter_names(
but_all_of_them,
are_positional_only,
arguments_mmmmkay,
so_this_is_only_valid_after,
three_point_eight,
/,
):
pass
lambda a, /: a
lambda a, b, /, c, d, *, e, f: a
lambda a, b, /, c, d, *args, e, f, **kwargs: args
lambda a, b=1, /, c=2, d=3, *, e=4, f=5: 1

View file

@ -0,0 +1,44 @@
def positional_only_arg(a, /):
pass
def all_markers(a, b, /, c, d, *, e, f):
pass
def all_markers_with_args_and_kwargs(
a_long_one,
b_long_one,
/,
c_long_one,
d_long_one,
*args,
e_long_one,
f_long_one,
**kwargs,
):
pass
def all_markers_with_defaults(a, b=1, /, c=2, d=3, *, e=4, f=5):
pass
def long_one_with_long_parameter_names(
but_all_of_them,
are_positional_only,
arguments_mmmmkay,
so_this_is_only_valid_after,
three_point_eight,
/,
):
pass
lambda a, /: a
lambda a, b, /, c, d, *, e, f: a
lambda a, b, /, c, d, *args, e, f, **kwargs: args
lambda a, b=1, /, c=2, d=3, *, e=4, f=5: 1

View file

@ -0,0 +1,47 @@
(a := 1)
(a := a)
if (match := pattern.search(data)) is None:
pass
if match := pattern.search(data):
pass
[y := f(x), y**2, y**3]
filtered_data = [y for x in data if (y := f(x)) is None]
(y := f(x))
y0 = (y1 := f(x))
foo(x=(y := f(x)))
def foo(answer=(p := 42)):
pass
def foo(answer: (p := 42) = 5):
pass
lambda: (x := 1)
(x := lambda: 1)
(x := lambda: (y := 1))
lambda line: (m := re.match(pattern, line)) and m.group(1)
x = (y := 0)
(z := (y := (x := 0)))
(info := (name, phone, *rest))
(x := 1, 2)
(total := total + tax)
len(lines := f.readlines())
foo(x := 3, cat="vector")
foo(cat=(category := "vector"))
if any(len(longline := l) >= 100 for l in lines):
print(longline)
if env_base := os.environ.get("PYTHONUSERBASE", None):
return env_base
if self._is_special and (ans := self._check_nans(context=context)):
return ans
foo(b := 2, a=1)
foo((b := 2), a=1)
foo(c=(b := 2), a=1)
while x := f(x):
pass
while x := f(x):
pass

View file

@ -0,0 +1,47 @@
(a := 1)
(a := a)
if (match := pattern.search(data)) is None:
pass
if match := pattern.search(data):
pass
[y := f(x), y**2, y**3]
filtered_data = [y for x in data if (y := f(x)) is None]
(y := f(x))
y0 = (y1 := f(x))
foo(x=(y := f(x)))
def foo(answer=(p := 42)):
pass
def foo(answer: (p := 42) = 5):
pass
lambda: (x := 1)
(x := lambda: 1)
(x := lambda: (y := 1))
lambda line: (m := re.match(pattern, line)) and m.group(1)
x = (y := 0)
(z := (y := (x := 0)))
(info := (name, phone, *rest))
(x := 1, 2)
(total := total + tax)
len(lines := f.readlines())
foo(x := 3, cat="vector")
foo(cat=(category := "vector"))
if any(len(longline := l) >= 100 for l in lines):
print(longline)
if env_base := os.environ.get("PYTHONUSERBASE", None):
return env_base
if self._is_special and (ans := self._check_nans(context=context)):
return ans
foo(b := 2, a=1)
foo((b := 2), a=1)
foo(c=(b := 2), a=1)
while x := f(x):
pass
while x := f(x):
pass

View file

@ -0,0 +1,19 @@
#!/usr/bin/env python3.8
def starred_return():
my_list = ["value2", "value3"]
return "value1", *my_list
def starred_yield():
my_list = ["value2", "value3"]
yield "value1", *my_list
# all right hand side expressions allowed in regular assignments are now also allowed in
# annotated assignments
a : Tuple[ str, int] = "1", 2
a: Tuple[int , ... ] = b, *c, d
def t():
a : str = yield "a"

View file

@ -0,0 +1,21 @@
#!/usr/bin/env python3.8
def starred_return():
my_list = ["value2", "value3"]
return "value1", *my_list
def starred_yield():
my_list = ["value2", "value3"]
yield "value1", *my_list
# all right hand side expressions allowed in regular assignments are now also allowed in
# annotated assignments
a: Tuple[str, int] = "1", 2
a: Tuple[int, ...] = b, *c, d
def t():
a: str = yield "a"

View file

@ -0,0 +1,7 @@
# Unparenthesized walruses are now allowed in set literals & set comprehensions
# since Python 3.9
{x := 1, 2, 3}
{x4 := x**5 for x in range(7)}
# We better not remove the parentheses here (since it's a 3.10 feature)
x[(a := 1)]
x[(a := 1), (b := 3)]

View file

@ -0,0 +1,7 @@
# Unparenthesized walruses are now allowed in set literals & set comprehensions
# since Python 3.9
{x := 1, 2, 3}
{x4 := x**5 for x in range(7)}
# We better not remove the parentheses here (since it's a 3.10 feature)
x[(a := 1)]
x[(a := 1), (b := 3)]

View file

@ -0,0 +1,13 @@
#!/usr/bin/env python3.9
@relaxed_decorator[0]
def f():
...
@relaxed_decorator[extremely_long_name_that_definitely_will_not_fit_on_one_line_of_standard_length]
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():
...

View file

@ -0,0 +1,20 @@
#!/usr/bin/env python3.9
@relaxed_decorator[0]
def f():
...
@relaxed_decorator[
extremely_long_name_that_definitely_will_not_fit_on_one_line_of_standard_length
]
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():
...

View file

@ -0,0 +1,54 @@
with (open("bla.txt")):
pass
with (open("bla.txt")), (open("bla.txt")):
pass
with (open("bla.txt") as f):
pass
# Remove brackets within alias expression
with (open("bla.txt")) as f:
pass
# Remove brackets around one-line context managers
with (open("bla.txt") as f, (open("x"))):
pass
with ((open("bla.txt")) as f, open("x")):
pass
with (CtxManager1() as example1, CtxManager2() as example2):
...
# Brackets remain when using magic comma
with (CtxManager1() as example1, CtxManager2() as example2,):
...
# Brackets remain for multi-line context managers
with (CtxManager1() as example1, CtxManager2() as example2, CtxManager2() as example2, CtxManager2() as example2, CtxManager2() as example2):
...
# Don't touch assignment expressions
with (y := open("./test.py")) as f:
pass
# Deeply nested examples
# N.B. Multiple brackets are only possible
# around the context manager itself.
# Only one brackets is allowed around the
# alias expression or comma-delimited context managers.
with (((open("bla.txt")))):
pass
with (((open("bla.txt")))), (((open("bla.txt")))):
pass
with (((open("bla.txt")))) as f:
pass
with ((((open("bla.txt")))) as f):
pass
with ((((CtxManager1()))) as example1, (((CtxManager2()))) as example2):
...

View file

@ -0,0 +1,63 @@
with open("bla.txt"):
pass
with open("bla.txt"), open("bla.txt"):
pass
with open("bla.txt") as f:
pass
# Remove brackets within alias expression
with open("bla.txt") as f:
pass
# Remove brackets around one-line context managers
with open("bla.txt") as f, open("x"):
pass
with open("bla.txt") as f, open("x"):
pass
with CtxManager1() as example1, CtxManager2() as example2:
...
# Brackets remain when using magic comma
with (
CtxManager1() as example1,
CtxManager2() as example2,
):
...
# Brackets remain for multi-line context managers
with (
CtxManager1() as example1,
CtxManager2() as example2,
CtxManager2() as example2,
CtxManager2() as example2,
CtxManager2() as example2,
):
...
# Don't touch assignment expressions
with (y := open("./test.py")) as f:
pass
# Deeply nested examples
# N.B. Multiple brackets are only possible
# around the context manager itself.
# Only one brackets is allowed around the
# alias expression or comma-delimited context managers.
with open("bla.txt"):
pass
with open("bla.txt"), open("bla.txt"):
pass
with open("bla.txt") as f:
pass
with open("bla.txt") as f:
pass
with CtxManager1() as example1, CtxManager2() as example2:
...

View file

@ -93,4 +93,4 @@ async def wat():
# Some closing comments.
# Maybe Vim or Emacs directives for formatting.
# Who knows.
# Who knows.

View file

@ -1,3 +1,4 @@
...
"some_string"
b"\\xa3"
Name
@ -114,7 +115,7 @@ call(
arg,
another,
kwarg="hey",
**kwargs,
**kwargs
) # note: no trailing comma pre-3.6
call(*gidgets[:2])
call(a, *gidgets[:2])

View file

@ -5,7 +5,6 @@ import sys
from third_party import X, Y, Z
from library import some_connection, some_decorator
# fmt: off
from third_party import (X,
Y, Z)

View file

@ -0,0 +1,19 @@
# Regression test for https://github.com/psf/black/issues/3438
import ast
import collections # fmt: skip
import dataclasses
# fmt: off
import os
# fmt: on
import pathlib
import re # fmt: skip
import secrets
# fmt: off
import sys
# fmt: on
import tempfile
import zoneinfo

View file

@ -0,0 +1,19 @@
# Regression test for https://github.com/psf/black/issues/3438
import ast
import collections # fmt: skip
import dataclasses
# fmt: off
import os
# fmt: on
import pathlib
import re # fmt: skip
import secrets
# fmt: off
import sys
# fmt: on
import tempfile
import zoneinfo

View file

@ -7,3 +7,5 @@ f"{f'''{'nested'} inner'''} outer"
f"\"{f'{nested} inner'}\" outer"
f"space between opening braces: { {a for a in (1, 2, 3)}}"
f'Hello \'{tricky + "example"}\''
f"Tried directories {str(rootdirs)} \
but none started with prefix {parentdir_prefix}"

View file

@ -7,3 +7,5 @@ f"{f'''{'nested'} inner'''} outer"
f"\"{f'{nested} inner'}\" outer"
f"space between opening braces: { {a for a in (1, 2, 3)}}"
f'Hello \'{tricky + "example"}\''
f"Tried directories {str(rootdirs)} \
but none started with prefix {parentdir_prefix}"

View file

@ -34,7 +34,7 @@ def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r''
def spaces_types(a: int = 1, b: tuple = (), c: list = [], d: dict = {}, e: bool = True, f: int = -1, 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)
# EMPTY LINE WITH WHITESPACE (this comment will be removed)
def example(session):
result = session.query(models.Customer.id).filter(
models.Customer.account_id == account_id,

View file

@ -0,0 +1,6 @@
def some_very_long_name_function() -> my_module.Asdf | my_module.AnotherType | my_module.YetAnotherType | None:
pass
def some_very_long_name_function() -> my_module.Asdf | my_module.AnotherType | my_module.YetAnotherType | my_module.EvenMoreType | None:
pass

View file

@ -0,0 +1,14 @@
def some_very_long_name_function() -> (
my_module.Asdf | my_module.AnotherType | my_module.YetAnotherType | None
):
pass
def some_very_long_name_function() -> (
my_module.Asdf
| my_module.AnotherType
| my_module.YetAnotherType
| my_module.EvenMoreType
| None
):
pass

View file

@ -29,35 +29,3 @@ ham[lower:upper], ham[lower:upper:], ham[lower::step]
# ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
slice[::, ::]
slice[
# A
:
# B
:
# C
]
slice[
# A
1:
# B
2:
# C
3
]
slice[
# A
1
+ 2 :
# B
3 :
# C
4
]
x[
1: # A
2: # B
3 # C
]

View file

@ -29,31 +29,3 @@ ham[lower:upper], ham[lower:upper:], ham[lower::step]
# ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
slice[::, ::]
slice[
# A
:
# B
:
# C
]
slice[
# A
1:
# B
2:
# C
3
]
slice[
# A
1
+ 2 :
# B
3 :
# C
4
]
x[1:2:3] # A # B # C

View file

@ -0,0 +1,3 @@
def foo(
# type: Foo
x): pass

View file

@ -0,0 +1,5 @@
def foo(
# type: Foo
x,
):
pass

View file

@ -0,0 +1,113 @@
#!/usr/bin/python3
from __future__ import annotations
import argparse
from pathlib import Path
def import_fixture(fixture: Path, fixture_set: str):
"""
Imports a single fixture by writing the input and expected output to the black directory.
"""
output_directory = Path(__file__).parent.joinpath("black").joinpath(fixture_set)
output_directory.mkdir(parents=True, exist_ok=True)
fixture_path = output_directory.joinpath(fixture.name)
expect_path = fixture_path.with_suffix(".py.expect")
with (
fixture.open("r") as black_file,
fixture_path.open("w") as fixture_file,
expect_path.open("w") as expect_file
):
lines = iter(black_file)
expected = []
input = []
for line in lines:
if line.rstrip() == "# output":
expected = list(lines)
break
else:
input.append(line)
if not expected:
# If there's no output marker, tread the whole file as already pre-formatted
expected = input
fixture_file.write("".join(input).strip() + "\n")
expect_file.write("".join(expected).strip() + "\n")
# The name of the folders in the `data` for which the tests should be imported
FIXTURE_SETS = [
"py_36",
"py_37",
"py_38",
"py_39",
"py_310",
"py_311",
"simple_cases",
"miscellaneous",
".",
"type_comments"
]
# Tests that ruff doesn't fully support yet and, therefore, should not be imported
IGNORE_LIST = [
"pep_572_remove_parens.py", # Reformatting bugs
"pep_646.py", # Rust Python parser bug
# Contain syntax errors
"async_as_identifier.py",
"invalid_header.py",
"pattern_matching_invalid.py",
# Python 2
"python2_detection.py"
]
def import_fixtures(black_dir: str):
"""Imports all the black fixtures"""
test_directory = Path(black_dir, "tests/data")
if not test_directory.exists():
print(
"Black directory does not contain a 'tests/data' directory. Does the directory point to a full black "
"checkout (git clone https://github.com/psf/black.git)?")
return
for fixture_set in FIXTURE_SETS:
fixture_directory = test_directory.joinpath(fixture_set)
fixtures = fixture_directory.glob("*.py")
if not fixtures:
print(f"Fixture set '{fixture_set}' contains no python files")
return
for fixture in fixtures:
if fixture.name in IGNORE_LIST:
print(f"Ignoring fixture '{fixture}")
continue
print(f"Importing fixture '{fixture}")
import_fixture(fixture, fixture_set)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description="Imports the test suite from black.",
epilog="import_black_tests.py <path_to_black_repository>"
)
parser.add_argument("black_dir", type=Path)
args = parser.parse_args()
black_dir = args.black_dir
import_fixtures(black_dir)