mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-31 15:47:41 +00:00
Add initial formatter implementation (#2883)
# Summary This PR contains the code for the autoformatter proof-of-concept. ## Crate structure The primary formatting hook is the `fmt` function in `crates/ruff_python_formatter/src/lib.rs`. The current formatter approach is outlined in `crates/ruff_python_formatter/src/lib.rs`, and is structured as follows: - Tokenize the code using the RustPython lexer. - In `crates/ruff_python_formatter/src/trivia.rs`, extract a variety of trivia tokens from the token stream. These include comments, trailing commas, and empty lines. - Generate the AST via the RustPython parser. - In `crates/ruff_python_formatter/src/cst.rs`, convert the AST to a CST structure. As of now, the CST is nearly identical to the AST, except that every node gets a `trivia` vector. But we might want to modify it further. - In `crates/ruff_python_formatter/src/attachment.rs`, attach each trivia token to the corresponding CST node. The logic for this is mostly in `decorate_trivia` and is ported almost directly from Prettier (given each token, find its preceding, following, and enclosing nodes, then attach the token to the appropriate node in a second pass). - In `crates/ruff_python_formatter/src/newlines.rs`, normalize newlines to match Black’s preferences. This involves traversing the CST and inserting or removing `TriviaToken` values as we go. - Call `format!` on the CST, which delegates to type-specific formatter implementations (e.g., `crates/ruff_python_formatter/src/format/stmt.rs` for `Stmt` nodes, and similar for `Expr` nodes; the others are trivial). Those type-specific implementations delegate to kind-specific functions (e.g., `format_func_def`). ## Testing and iteration The formatter is being developed against the Black test suite, which was copied over in-full to `crates/ruff_python_formatter/resources/test/fixtures/black`. The Black fixtures had to be modified to create `[insta](https://github.com/mitsuhiko/insta)`-compatible snapshots, which now exist in the repo. My approach thus far has been to try and improve coverage by tackling fixtures one-by-one. ## What works, and what doesn’t - *Most* nodes are supported at a basic level (though there are a few stragglers at time of writing, like `StmtKind::Try`). - Newlines are properly preserved in most cases. - Magic trailing commas are properly preserved in some (but not all) cases. - Trivial leading and trailing standalone comments mostly work (although maybe not at the end of a file). - Inline comments, and comments within expressions, often don’t work -- they work in a few cases, but it’s one-off right now. (We’re probably associating them with the “right” nodes more often than we are actually rendering them in the right place.) - We don’t properly normalize string quotes. (At present, we just repeat any constants verbatim.) - We’re mishandling a bunch of wrapping cases (if we treat Black as the reference implementation). Here are a few examples (demonstrating Black's stable behavior): ```py # In some cases, if the end expression is "self-closing" (functions, # lists, dictionaries, sets, subscript accesses, and any length-two # boolean operations that end in these elments), Black # will wrap like this... if some_expression and f( b, c, d, ): pass # ...whereas we do this: if ( some_expression and f( b, c, d, ) ): pass # If function arguments can fit on a single line, then Black will # format them like this, rather than exploding them vertically. if f( a, b, c, d, e, f, g, ... ): pass ``` - We don’t properly preserve parentheses in all cases. Black preserves parentheses in some but not all cases.
This commit is contained in:
parent
f661c90bd7
commit
ca49b00e55
134 changed files with 12044 additions and 18 deletions
|
@ -0,0 +1,22 @@
|
|||
ax = 123456789 .bit_count()
|
||||
x = (123456).__abs__()
|
||||
x = .1.is_integer()
|
||||
x = 1. .imag
|
||||
x = 1E+1.imag
|
||||
x = 1E-1.real
|
||||
x = 123456789.123456789.hex()
|
||||
x = 123456789.123456789E123456789 .real
|
||||
x = 123456789E123456789 .conjugate()
|
||||
x = 123456789J.real
|
||||
x = 123456789.123456789J.__add__(0b1011.bit_length())
|
||||
x = 0XB1ACC.conjugate()
|
||||
x = 0B1011 .conjugate()
|
||||
x = 0O777 .real
|
||||
x = 0.000000006 .hex()
|
||||
x = -100.0000J
|
||||
|
||||
if 10 .real:
|
||||
...
|
||||
|
||||
y = 100[no]
|
||||
y = 100(no)
|
|
@ -0,0 +1,7 @@
|
|||
\
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
print("hello, world")
|
6
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/bracketmatch.py
vendored
Normal file
6
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/bracketmatch.py
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
for ((x in {}) or {})['a'] in x:
|
||||
pass
|
||||
pem_spam = lambda l, spam = {
|
||||
"x": 3
|
||||
}: not spam.get(l.strip())
|
||||
lambda x=lambda y={1: 3}: y['x':lambda y: {1: 2}]: x
|
|
@ -0,0 +1,23 @@
|
|||
class SimpleClassWithBlankParentheses():
|
||||
pass
|
||||
class ClassWithSpaceParentheses ( ):
|
||||
first_test_data = 90
|
||||
second_test_data = 100
|
||||
def test_func(self):
|
||||
return None
|
||||
class ClassWithEmptyFunc(object):
|
||||
|
||||
def func_with_blank_parentheses():
|
||||
return 5
|
||||
|
||||
|
||||
def public_func_with_blank_parentheses():
|
||||
return None
|
||||
def class_under_the_func_with_blank_parentheses():
|
||||
class InsideFunc():
|
||||
pass
|
||||
class NormalClass (
|
||||
):
|
||||
def func_for_testing(self, first, second):
|
||||
sum = first + second
|
||||
return sum
|
100
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/class_methods_new_line.py
vendored
Normal file
100
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/class_methods_new_line.py
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
class ClassSimplest:
|
||||
pass
|
||||
class ClassWithSingleField:
|
||||
a = 1
|
||||
class ClassWithJustTheDocstring:
|
||||
"""Just a docstring."""
|
||||
class ClassWithInit:
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithTheDocstringAndInit:
|
||||
"""Just a docstring."""
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithInitAndVars:
|
||||
cls_var = 100
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithInitAndVarsAndDocstring:
|
||||
"""Test class"""
|
||||
cls_var = 100
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithDecoInit:
|
||||
@deco
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithDecoInitAndVars:
|
||||
cls_var = 100
|
||||
@deco
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithDecoInitAndVarsAndDocstring:
|
||||
"""Test class"""
|
||||
cls_var = 100
|
||||
@deco
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassSimplestWithInner:
|
||||
class Inner:
|
||||
pass
|
||||
class ClassSimplestWithInnerWithDocstring:
|
||||
class Inner:
|
||||
"""Just a docstring."""
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithSingleFieldWithInner:
|
||||
a = 1
|
||||
class Inner:
|
||||
pass
|
||||
class ClassWithJustTheDocstringWithInner:
|
||||
"""Just a docstring."""
|
||||
class Inner:
|
||||
pass
|
||||
class ClassWithInitWithInner:
|
||||
class Inner:
|
||||
pass
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithInitAndVarsWithInner:
|
||||
cls_var = 100
|
||||
class Inner:
|
||||
pass
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithInitAndVarsAndDocstringWithInner:
|
||||
"""Test class"""
|
||||
cls_var = 100
|
||||
class Inner:
|
||||
pass
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithDecoInitWithInner:
|
||||
class Inner:
|
||||
pass
|
||||
@deco
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithDecoInitAndVarsWithInner:
|
||||
cls_var = 100
|
||||
class Inner:
|
||||
pass
|
||||
@deco
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithDecoInitAndVarsAndDocstringWithInner:
|
||||
"""Test class"""
|
||||
cls_var = 100
|
||||
class Inner:
|
||||
pass
|
||||
@deco
|
||||
def __init__(self):
|
||||
pass
|
||||
class ClassWithDecoInitAndVarsAndDocstringWithInner2:
|
||||
"""Test class"""
|
||||
class Inner:
|
||||
pass
|
||||
cls_var = 100
|
||||
@deco
|
||||
def __init__(self):
|
||||
pass
|
71
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/collections.py
vendored
Normal file
71
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/collections.py
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
import core, time, a
|
||||
|
||||
from . import A, B, C
|
||||
|
||||
# keeps existing trailing comma
|
||||
from foo import (
|
||||
bar,
|
||||
)
|
||||
|
||||
# also keeps existing structure
|
||||
from foo import (
|
||||
baz,
|
||||
qux,
|
||||
)
|
||||
|
||||
# `as` works as well
|
||||
from foo import (
|
||||
xyzzy as magic,
|
||||
)
|
||||
|
||||
a = {1,2,3,}
|
||||
b = {
|
||||
1,2,
|
||||
3}
|
||||
c = {
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
}
|
||||
x = 1,
|
||||
y = narf(),
|
||||
nested = {(1,2,3),(4,5,6),}
|
||||
nested_no_trailing_comma = {(1,2,3),(4,5,6)}
|
||||
nested_long_lines = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "cccccccccccccccccccccccccccccccccccccccc", (1, 2, 3), "dddddddddddddddddddddddddddddddddddddddd"]
|
||||
{"oneple": (1,),}
|
||||
{"oneple": (1,)}
|
||||
['ls', 'lsoneple/%s' % (foo,)]
|
||||
x = {"oneple": (1,)}
|
||||
y = {"oneple": (1,),}
|
||||
assert False, ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s" % bar)
|
||||
|
||||
# looping over a 1-tuple should also not get wrapped
|
||||
for x in (1,):
|
||||
pass
|
||||
for (x,) in (1,), (2,), (3,):
|
||||
pass
|
||||
|
||||
[1, 2, 3,]
|
||||
|
||||
division_result_tuple = (6/2,)
|
||||
print("foo %r", (foo.bar,))
|
||||
|
||||
if True:
|
||||
IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = (
|
||||
Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING
|
||||
| {pylons.controllers.WSGIController}
|
||||
)
|
||||
|
||||
if True:
|
||||
ec2client.get_waiter('instance_stopped').wait(
|
||||
InstanceIds=[instance.id],
|
||||
WaiterConfig={
|
||||
'Delay': 5,
|
||||
})
|
||||
ec2client.get_waiter("instance_stopped").wait(
|
||||
InstanceIds=[instance.id],
|
||||
WaiterConfig={"Delay": 5,},
|
||||
)
|
||||
ec2client.get_waiter("instance_stopped").wait(
|
||||
InstanceIds=[instance.id], WaiterConfig={"Delay": 5,},
|
||||
)
|
|
@ -0,0 +1,9 @@
|
|||
def bob(): \
|
||||
# pylint: disable=W9016
|
||||
pass
|
||||
|
||||
|
||||
def bobtwo(): \
|
||||
\
|
||||
# some comment here
|
||||
pass
|
96
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments.py
vendored
Normal file
96
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments.py
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
#!/usr/bin/env python3
|
||||
# fmt: on
|
||||
# Some license here.
|
||||
#
|
||||
# Has many lines. Many, many lines.
|
||||
# Many, many, many lines.
|
||||
"""Module docstring.
|
||||
|
||||
Possibly also many, many lines.
|
||||
"""
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
import a
|
||||
from b.c import X # some noqa comment
|
||||
|
||||
try:
|
||||
import fast
|
||||
except ImportError:
|
||||
import slow as fast
|
||||
|
||||
|
||||
# Some comment before a function.
|
||||
y = 1
|
||||
(
|
||||
# some strings
|
||||
y # type: ignore
|
||||
)
|
||||
|
||||
|
||||
def function(default=None):
|
||||
"""Docstring comes first.
|
||||
|
||||
Possibly many lines.
|
||||
"""
|
||||
# FIXME: Some comment about why this function is crap but still in production.
|
||||
import inner_imports
|
||||
|
||||
if inner_imports.are_evil():
|
||||
# Explains why we have this if.
|
||||
# In great detail indeed.
|
||||
x = X()
|
||||
return x.method1() # type: ignore
|
||||
|
||||
# This return is also commented for some reason.
|
||||
return default
|
||||
|
||||
|
||||
# Explains why we use global state.
|
||||
GLOBAL_STATE = {"a": a(1), "b": a(2), "c": a(3)}
|
||||
|
||||
|
||||
# Another comment!
|
||||
# This time two lines.
|
||||
|
||||
|
||||
class Foo:
|
||||
"""Docstring for class Foo. Example from Sphinx docs."""
|
||||
|
||||
#: Doc comment for class attribute Foo.bar.
|
||||
#: It can have multiple lines.
|
||||
bar = 1
|
||||
|
||||
flox = 1.5 #: Doc comment for Foo.flox. One line only.
|
||||
|
||||
baz = 2
|
||||
"""Docstring for class attribute Foo.baz."""
|
||||
|
||||
def __init__(self):
|
||||
#: Doc comment for instance attribute qux.
|
||||
self.qux = 3
|
||||
|
||||
self.spam = 4
|
||||
"""Docstring for instance attribute spam."""
|
||||
|
||||
|
||||
#' <h1>This is pweave!</h1>
|
||||
|
||||
|
||||
@fast(really=True)
|
||||
async def wat():
|
||||
# This comment, for some reason \
|
||||
# contains a trailing backslash.
|
||||
async with X.open_async() as x: # Some more comments
|
||||
result = await x.method1()
|
||||
# Comment after ending a block.
|
||||
if result:
|
||||
print("A OK", file=sys.stdout)
|
||||
# Comment between things.
|
||||
print()
|
||||
|
||||
|
||||
# Some closing comments.
|
||||
# Maybe Vim or Emacs directives for formatting.
|
||||
# Who knows.
|
165
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments2.py
vendored
Normal file
165
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments2.py
vendored
Normal file
|
@ -0,0 +1,165 @@
|
|||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
MyLovelyCompanyTeamProjectComponent # NOT DRY
|
||||
)
|
||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
MyLovelyCompanyTeamProjectComponent as component # DRY
|
||||
)
|
||||
|
||||
# Please keep __all__ alphabetized within each category.
|
||||
|
||||
__all__ = [
|
||||
# Super-special typing primitives.
|
||||
'Any',
|
||||
'Callable',
|
||||
'ClassVar',
|
||||
|
||||
# ABCs (from collections.abc).
|
||||
'AbstractSet', # collections.abc.Set.
|
||||
'ByteString',
|
||||
'Container',
|
||||
|
||||
# Concrete collection types.
|
||||
'Counter',
|
||||
'Deque',
|
||||
'Dict',
|
||||
'DefaultDict',
|
||||
'List',
|
||||
'Set',
|
||||
'FrozenSet',
|
||||
'NamedTuple', # Not really a type.
|
||||
'Generator',
|
||||
]
|
||||
|
||||
not_shareables = [
|
||||
# singletons
|
||||
True,
|
||||
False,
|
||||
NotImplemented, ...,
|
||||
# builtin types and objects
|
||||
type,
|
||||
object,
|
||||
object(),
|
||||
Exception(),
|
||||
42,
|
||||
100.0,
|
||||
"spam",
|
||||
# user-defined types and objects
|
||||
Cheese,
|
||||
Cheese("Wensleydale"),
|
||||
SubBytes(b"spam"),
|
||||
]
|
||||
|
||||
if 'PYTHON' in os.environ:
|
||||
add_compiler(compiler_from_env())
|
||||
else:
|
||||
# for compiler in compilers.values():
|
||||
# add_compiler(compiler)
|
||||
add_compiler(compilers[(7.0, 32)])
|
||||
# add_compiler(compilers[(7.1, 64)])
|
||||
|
||||
# Comment before function.
|
||||
def inline_comments_in_brackets_ruin_everything():
|
||||
if typedargslist:
|
||||
parameters.children = [
|
||||
children[0], # (1
|
||||
body,
|
||||
children[-1] # )1
|
||||
]
|
||||
parameters.children = [
|
||||
children[0],
|
||||
body,
|
||||
children[-1], # type: ignore
|
||||
]
|
||||
else:
|
||||
parameters.children = [
|
||||
parameters.children[0], # (2 what if this was actually long
|
||||
body,
|
||||
parameters.children[-1], # )2
|
||||
]
|
||||
parameters.children = [parameters.what_if_this_was_actually_long.children[0], body, parameters.children[-1]] # type: ignore
|
||||
if (self._proc is not None
|
||||
# has the child process finished?
|
||||
and self._returncode is None
|
||||
# the child process has finished, but the
|
||||
# transport hasn't been notified yet?
|
||||
and self._proc.poll() is None):
|
||||
pass
|
||||
# no newline before or after
|
||||
short = [
|
||||
# one
|
||||
1,
|
||||
# two
|
||||
2]
|
||||
|
||||
# no newline after
|
||||
call(arg1, arg2, """
|
||||
short
|
||||
""", arg3=True)
|
||||
|
||||
############################################################################
|
||||
|
||||
call2(
|
||||
#short
|
||||
arg1,
|
||||
#but
|
||||
arg2,
|
||||
#multiline
|
||||
"""
|
||||
short
|
||||
""",
|
||||
# yup
|
||||
arg3=True)
|
||||
lcomp = [
|
||||
element # yup
|
||||
for element in collection # yup
|
||||
if element is not None # right
|
||||
]
|
||||
lcomp2 = [
|
||||
# hello
|
||||
element
|
||||
# yup
|
||||
for element in collection
|
||||
# right
|
||||
if element is not None
|
||||
]
|
||||
lcomp3 = [
|
||||
# This one is actually too long to fit in a single line.
|
||||
element.split('\n', 1)[0]
|
||||
# yup
|
||||
for element in collection.select_elements()
|
||||
# right
|
||||
if element is not None
|
||||
]
|
||||
while True:
|
||||
if False:
|
||||
continue
|
||||
|
||||
# and round and round we go
|
||||
# and round and round we go
|
||||
|
||||
# let's return
|
||||
return Node(
|
||||
syms.simple_stmt,
|
||||
[
|
||||
Node(statement, result),
|
||||
Leaf(token.NEWLINE, '\n') # FIXME: \r\n?
|
||||
],
|
||||
)
|
||||
|
||||
CONFIG_FILES = [CONFIG_FILE, ] + SHARED_CONFIG_FILES + USER_CONFIG_FILES # type: Final
|
||||
|
||||
class Test:
|
||||
def _init_host(self, parsed) -> None:
|
||||
if (parsed.hostname is None or # type: ignore
|
||||
not parsed.hostname.strip()):
|
||||
pass
|
||||
|
||||
#######################
|
||||
### SECTION COMMENT ###
|
||||
#######################
|
||||
|
||||
|
||||
instruction()#comment with bad spacing
|
||||
|
||||
# END COMMENTS
|
||||
# MORE END COMMENTS
|
47
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments3.py
vendored
Normal file
47
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments3.py
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
# The percent-percent comments are Spyder IDE cells.
|
||||
|
||||
#%%
|
||||
def func():
|
||||
x = """
|
||||
a really long string
|
||||
"""
|
||||
lcomp3 = [
|
||||
# This one is actually too long to fit in a single line.
|
||||
element.split("\n", 1)[0]
|
||||
# yup
|
||||
for element in collection.select_elements()
|
||||
# right
|
||||
if element is not None
|
||||
]
|
||||
# Capture each of the exceptions in the MultiError along with each of their causes and contexts
|
||||
if isinstance(exc_value, MultiError):
|
||||
embedded = []
|
||||
for exc in exc_value.exceptions:
|
||||
if exc not in _seen:
|
||||
embedded.append(
|
||||
# This should be left alone (before)
|
||||
traceback.TracebackException.from_exception(
|
||||
exc,
|
||||
limit=limit,
|
||||
lookup_lines=lookup_lines,
|
||||
capture_locals=capture_locals,
|
||||
# copy the set of _seen exceptions so that duplicates
|
||||
# shared between sub-exceptions are not omitted
|
||||
_seen=set(_seen),
|
||||
)
|
||||
# This should be left alone (after)
|
||||
)
|
||||
|
||||
# everything is fine if the expression isn't nested
|
||||
traceback.TracebackException.from_exception(
|
||||
exc,
|
||||
limit=limit,
|
||||
lookup_lines=lookup_lines,
|
||||
capture_locals=capture_locals,
|
||||
# copy the set of _seen exceptions so that duplicates
|
||||
# shared between sub-exceptions are not omitted
|
||||
_seen=set(_seen),
|
||||
)
|
||||
|
||||
|
||||
#%%
|
94
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments4.py
vendored
Normal file
94
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments4.py
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
MyLovelyCompanyTeamProjectComponent, # NOT DRY
|
||||
)
|
||||
from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import (
|
||||
MyLovelyCompanyTeamProjectComponent as component, # DRY
|
||||
)
|
||||
|
||||
|
||||
class C:
|
||||
@pytest.mark.parametrize(
|
||||
("post_data", "message"),
|
||||
[
|
||||
# metadata_version errors.
|
||||
(
|
||||
{},
|
||||
"None is an invalid value for Metadata-Version. Error: This field is"
|
||||
" required. see"
|
||||
" https://packaging.python.org/specifications/core-metadata",
|
||||
),
|
||||
(
|
||||
{"metadata_version": "-1"},
|
||||
"'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata"
|
||||
" Version see"
|
||||
" https://packaging.python.org/specifications/core-metadata",
|
||||
),
|
||||
# name errors.
|
||||
(
|
||||
{"metadata_version": "1.2"},
|
||||
"'' is an invalid value for Name. Error: This field is required. see"
|
||||
" https://packaging.python.org/specifications/core-metadata",
|
||||
),
|
||||
(
|
||||
{"metadata_version": "1.2", "name": "foo-"},
|
||||
"'foo-' is an invalid value for Name. Error: Must start and end with a"
|
||||
" letter or numeral and contain only ascii numeric and '.', '_' and"
|
||||
" '-'. see https://packaging.python.org/specifications/core-metadata",
|
||||
),
|
||||
# version errors.
|
||||
(
|
||||
{"metadata_version": "1.2", "name": "example"},
|
||||
"'' is an invalid value for Version. Error: This field is required. see"
|
||||
" https://packaging.python.org/specifications/core-metadata",
|
||||
),
|
||||
(
|
||||
{"metadata_version": "1.2", "name": "example", "version": "dog"},
|
||||
"'dog' is an invalid value for Version. Error: Must start and end with"
|
||||
" a letter or numeral and contain only ascii numeric and '.', '_' and"
|
||||
" '-'. see https://packaging.python.org/specifications/core-metadata",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_fails_invalid_post_data(
|
||||
self, pyramid_config, db_request, post_data, message
|
||||
):
|
||||
pyramid_config.testing_securitypolicy(userid=1)
|
||||
db_request.POST = MultiDict(post_data)
|
||||
|
||||
|
||||
def foo(list_a, list_b):
|
||||
results = (
|
||||
User.query.filter(User.foo == "bar")
|
||||
.filter( # Because foo.
|
||||
db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b))
|
||||
)
|
||||
.filter(User.xyz.is_(None))
|
||||
# Another comment about the filtering on is_quux goes here.
|
||||
.filter(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True)))
|
||||
.order_by(User.created_at.desc())
|
||||
.with_for_update(key_share=True)
|
||||
.all()
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def foo2(list_a, list_b):
|
||||
# Standalone comment reasonably placed.
|
||||
return (
|
||||
User.query.filter(User.foo == "bar")
|
||||
.filter(
|
||||
db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b))
|
||||
)
|
||||
.filter(User.xyz.is_(None))
|
||||
)
|
||||
|
||||
|
||||
def foo3(list_a, list_b):
|
||||
return (
|
||||
# Standlone comment but weirdly placed.
|
||||
User.query.filter(User.foo == "bar")
|
||||
.filter(
|
||||
db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b))
|
||||
)
|
||||
.filter(User.xyz.is_(None))
|
||||
)
|
71
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments5.py
vendored
Normal file
71
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments5.py
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
while True:
|
||||
if something.changed:
|
||||
do.stuff() # trailing comment
|
||||
# Comment belongs to the `if` block.
|
||||
# This one belongs to the `while` block.
|
||||
|
||||
# Should this one, too? I guess so.
|
||||
|
||||
# This one is properly standalone now.
|
||||
|
||||
for i in range(100):
|
||||
# first we do this
|
||||
if i % 33 == 0:
|
||||
break
|
||||
|
||||
# then we do this
|
||||
print(i)
|
||||
# and finally we loop around
|
||||
|
||||
with open(some_temp_file) as f:
|
||||
data = f.read()
|
||||
|
||||
try:
|
||||
with open(some_other_file) as w:
|
||||
w.write(data)
|
||||
|
||||
except OSError:
|
||||
print("problems")
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
# leading function comment
|
||||
def wat():
|
||||
...
|
||||
# trailing function comment
|
||||
|
||||
|
||||
# SECTION COMMENT
|
||||
|
||||
|
||||
# leading 1
|
||||
@deco1
|
||||
# leading 2
|
||||
@deco2(with_args=True)
|
||||
# leading 3
|
||||
@deco3
|
||||
def decorated1():
|
||||
...
|
||||
|
||||
|
||||
# leading 1
|
||||
@deco1
|
||||
# leading 2
|
||||
@deco2(with_args=True)
|
||||
# leading function comment
|
||||
def decorated1():
|
||||
...
|
||||
|
||||
|
||||
# Note: this is fixed in
|
||||
# Preview.empty_lines_before_class_or_def_with_leading_comments.
|
||||
# In the current style, the user will have to split those lines by hand.
|
||||
some_instruction
|
||||
# This comment should be split from `some_instruction` by two lines but isn't.
|
||||
def g():
|
||||
...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
118
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments6.py
vendored
Normal file
118
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments6.py
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
from typing import Any, Tuple
|
||||
|
||||
|
||||
def f(
|
||||
a, # type: int
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
# test type comments
|
||||
def f(a, b, c, d, e, f, g, h, i):
|
||||
# type: (int, int, int, int, int, int, int, int, int) -> None
|
||||
pass
|
||||
|
||||
|
||||
def f(
|
||||
a, # type: int
|
||||
b, # type: int
|
||||
c, # type: int
|
||||
d, # type: int
|
||||
e, # type: int
|
||||
f, # type: int
|
||||
g, # type: int
|
||||
h, # type: int
|
||||
i, # type: int
|
||||
):
|
||||
# type: (...) -> None
|
||||
pass
|
||||
|
||||
|
||||
def f(
|
||||
arg, # type: int
|
||||
*args, # type: *Any
|
||||
default=False, # type: bool
|
||||
**kwargs, # type: **Any
|
||||
):
|
||||
# type: (...) -> None
|
||||
pass
|
||||
|
||||
|
||||
def f(
|
||||
a, # type: int
|
||||
b, # type: int
|
||||
c, # type: int
|
||||
d, # type: int
|
||||
):
|
||||
# type: (...) -> None
|
||||
|
||||
element = 0 # type: int
|
||||
another_element = 1 # type: float
|
||||
another_element_with_long_name = 2 # type: int
|
||||
another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = (
|
||||
3
|
||||
) # type: int
|
||||
an_element_with_a_long_value = calls() or more_calls() and more() # type: bool
|
||||
|
||||
tup = (
|
||||
another_element,
|
||||
another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style,
|
||||
) # type: Tuple[int, int]
|
||||
|
||||
a = (
|
||||
element
|
||||
+ another_element
|
||||
+ another_element_with_long_name
|
||||
+ element
|
||||
+ another_element
|
||||
+ another_element_with_long_name
|
||||
) # type: int
|
||||
|
||||
|
||||
def f(
|
||||
x, # not a type comment
|
||||
y, # type: int
|
||||
):
|
||||
# type: (...) -> None
|
||||
pass
|
||||
|
||||
|
||||
def f(
|
||||
x, # not a type comment
|
||||
): # type: (int) -> None
|
||||
pass
|
||||
|
||||
|
||||
def func(
|
||||
a=some_list[0], # type: int
|
||||
): # type: () -> int
|
||||
c = call(
|
||||
0.0123,
|
||||
0.0456,
|
||||
0.0789,
|
||||
0.0123,
|
||||
0.0456,
|
||||
0.0789,
|
||||
0.0123,
|
||||
0.0456,
|
||||
0.0789,
|
||||
a[-1], # type: ignore
|
||||
)
|
||||
|
||||
c = call(
|
||||
"aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa" # type: ignore
|
||||
)
|
||||
|
||||
|
||||
result = ( # aaa
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
)
|
||||
|
||||
AAAAAAAAAAAAA = [AAAAAAAAAAAAA] + SHARED_AAAAAAAAAAAAA + USER_AAAAAAAAAAAAA + AAAAAAAAAAAAA # type: ignore
|
||||
|
||||
call_to_some_function_asdf(
|
||||
foo,
|
||||
[AAAAAAAAAAAAAAAAAAAAAAA, AAAAAAAAAAAAAAAAAAAAAAA, AAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBB], # type: ignore
|
||||
)
|
||||
|
||||
aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*items))) # type: ignore[arg-type]
|
|
@ -0,0 +1,19 @@
|
|||
from .config import ( ConfigTypeAttributes, Int, Path, # String,
|
||||
# DEFAULT_TYPE_ATTRIBUTES,
|
||||
)
|
||||
|
||||
result = 1 # A simple comment
|
||||
result = ( 1, ) # Another one
|
||||
|
||||
result = 1 # type: ignore
|
||||
result = 1# This comment is talking about type: ignore
|
||||
square = Square(4) # type: Optional[Square]
|
||||
|
||||
def function(a:int=42):
|
||||
""" This docstring is already formatted
|
||||
a
|
||||
b
|
||||
"""
|
||||
# There's a NBSP + 3 spaces before
|
||||
# And 4 spaces on the next line
|
||||
pass
|
181
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/composition.py
vendored
Normal file
181
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/composition.py
vendored
Normal file
|
@ -0,0 +1,181 @@
|
|||
class C:
|
||||
def test(self) -> None:
|
||||
with patch("black.out", print):
|
||||
self.assertEqual(
|
||||
unstyle(str(report)), "1 file reformatted, 1 file failed to reformat."
|
||||
)
|
||||
self.assertEqual(
|
||||
unstyle(str(report)),
|
||||
"1 file reformatted, 1 file left unchanged, 1 file failed to reformat.",
|
||||
)
|
||||
self.assertEqual(
|
||||
unstyle(str(report)),
|
||||
"2 files reformatted, 1 file left unchanged, 1 file failed to"
|
||||
" reformat.",
|
||||
)
|
||||
self.assertEqual(
|
||||
unstyle(str(report)),
|
||||
"2 files reformatted, 2 files left unchanged, 2 files failed to"
|
||||
" reformat.",
|
||||
)
|
||||
for i in (a,):
|
||||
if (
|
||||
# Rule 1
|
||||
i % 2 == 0
|
||||
# Rule 2
|
||||
and i % 3 == 0
|
||||
):
|
||||
while (
|
||||
# Just a comment
|
||||
call()
|
||||
# Another
|
||||
):
|
||||
print(i)
|
||||
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
|
||||
push_manager=context.request.resource_manager,
|
||||
max_items_to_push=num_items,
|
||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE,
|
||||
).push(
|
||||
# Only send the first n items.
|
||||
items=items[:num_items]
|
||||
)
|
||||
return (
|
||||
'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||
% (test.name, test.filename, lineno, lname, err)
|
||||
)
|
||||
|
||||
def omitting_trailers(self) -> None:
|
||||
get_collection(
|
||||
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
|
||||
)[OneLevelIndex]
|
||||
get_collection(
|
||||
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
|
||||
)[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex]
|
||||
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
|
||||
22
|
||||
]
|
||||
assignment = (
|
||||
some.rather.elaborate.rule() and another.rule.ending_with.index[123]
|
||||
)
|
||||
|
||||
def easy_asserts(self) -> None:
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expected, "Not what we expected"
|
||||
|
||||
assert expected == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}, "Not what we expected"
|
||||
|
||||
assert expected == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
|
||||
def tricky_asserts(self) -> None:
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expected(
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
), "Not what we expected"
|
||||
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
} == expected, (
|
||||
"Not what we expected and the message is too long to fit in one line"
|
||||
)
|
||||
|
||||
assert expected(
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
) == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}, "Not what we expected"
|
||||
|
||||
assert expected == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}, (
|
||||
"Not what we expected and the message is too long to fit in one line"
|
||||
" because it's too long"
|
||||
)
|
||||
|
||||
dis_c_instance_method = """\
|
||||
%3d 0 LOAD_FAST 1 (x)
|
||||
2 LOAD_CONST 1 (1)
|
||||
4 COMPARE_OP 2 (==)
|
||||
6 LOAD_FAST 0 (self)
|
||||
8 STORE_ATTR 0 (x)
|
||||
10 LOAD_CONST 0 (None)
|
||||
12 RETURN_VALUE
|
||||
""" % (
|
||||
_C.__init__.__code__.co_firstlineno + 1,
|
||||
)
|
||||
|
||||
assert (
|
||||
expectedexpectedexpectedexpectedexpectedexpectedexpectedexpectedexpect
|
||||
== {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9,
|
||||
}
|
||||
)
|
|
@ -0,0 +1,181 @@
|
|||
class C:
|
||||
def test(self) -> None:
|
||||
with patch("black.out", print):
|
||||
self.assertEqual(
|
||||
unstyle(str(report)), "1 file reformatted, 1 file failed to reformat."
|
||||
)
|
||||
self.assertEqual(
|
||||
unstyle(str(report)),
|
||||
"1 file reformatted, 1 file left unchanged, 1 file failed to reformat.",
|
||||
)
|
||||
self.assertEqual(
|
||||
unstyle(str(report)),
|
||||
"2 files reformatted, 1 file left unchanged, 1 file failed to"
|
||||
" reformat.",
|
||||
)
|
||||
self.assertEqual(
|
||||
unstyle(str(report)),
|
||||
"2 files reformatted, 2 files left unchanged, 2 files failed to"
|
||||
" reformat.",
|
||||
)
|
||||
for i in (a,):
|
||||
if (
|
||||
# Rule 1
|
||||
i % 2 == 0
|
||||
# Rule 2
|
||||
and i % 3 == 0
|
||||
):
|
||||
while (
|
||||
# Just a comment
|
||||
call()
|
||||
# Another
|
||||
):
|
||||
print(i)
|
||||
xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy(
|
||||
push_manager=context.request.resource_manager,
|
||||
max_items_to_push=num_items,
|
||||
batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE
|
||||
).push(
|
||||
# Only send the first n items.
|
||||
items=items[:num_items]
|
||||
)
|
||||
return (
|
||||
'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s'
|
||||
% (test.name, test.filename, lineno, lname, err)
|
||||
)
|
||||
|
||||
def omitting_trailers(self) -> None:
|
||||
get_collection(
|
||||
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
|
||||
)[OneLevelIndex]
|
||||
get_collection(
|
||||
hey_this_is_a_very_long_call, it_has_funny_attributes, really=True
|
||||
)[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex]
|
||||
d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][
|
||||
22
|
||||
]
|
||||
assignment = (
|
||||
some.rather.elaborate.rule() and another.rule.ending_with.index[123]
|
||||
)
|
||||
|
||||
def easy_asserts(self) -> None:
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9
|
||||
} == expected, "Not what we expected"
|
||||
|
||||
assert expected == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9
|
||||
}, "Not what we expected"
|
||||
|
||||
assert expected == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9
|
||||
}
|
||||
|
||||
def tricky_asserts(self) -> None:
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9
|
||||
} == expected(
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
), "Not what we expected"
|
||||
|
||||
assert {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9
|
||||
} == expected, (
|
||||
"Not what we expected and the message is too long to fit in one line"
|
||||
)
|
||||
|
||||
assert expected(
|
||||
value, is_going_to_be="too long to fit in a single line", srsly=True
|
||||
) == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9
|
||||
}, "Not what we expected"
|
||||
|
||||
assert expected == {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9
|
||||
}, (
|
||||
"Not what we expected and the message is too long to fit in one line"
|
||||
" because it's too long"
|
||||
)
|
||||
|
||||
dis_c_instance_method = """\
|
||||
%3d 0 LOAD_FAST 1 (x)
|
||||
2 LOAD_CONST 1 (1)
|
||||
4 COMPARE_OP 2 (==)
|
||||
6 LOAD_FAST 0 (self)
|
||||
8 STORE_ATTR 0 (x)
|
||||
10 LOAD_CONST 0 (None)
|
||||
12 RETURN_VALUE
|
||||
""" % (
|
||||
_C.__init__.__code__.co_firstlineno + 1,
|
||||
)
|
||||
|
||||
assert (
|
||||
expectedexpectedexpectedexpectedexpectedexpectedexpectedexpectedexpect
|
||||
== {
|
||||
key1: value1,
|
||||
key2: value2,
|
||||
key3: value3,
|
||||
key4: value4,
|
||||
key5: value5,
|
||||
key6: value6,
|
||||
key7: value7,
|
||||
key8: value8,
|
||||
key9: value9
|
||||
}
|
||||
)
|
221
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/docstring.py
vendored
Normal file
221
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/docstring.py
vendored
Normal file
|
@ -0,0 +1,221 @@
|
|||
class MyClass:
|
||||
""" Multiline
|
||||
class docstring
|
||||
"""
|
||||
|
||||
def method(self):
|
||||
"""Multiline
|
||||
method docstring
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def foo():
|
||||
"""This is a docstring with
|
||||
some lines of text here
|
||||
"""
|
||||
return
|
||||
|
||||
|
||||
def bar():
|
||||
'''This is another docstring
|
||||
with more lines of text
|
||||
'''
|
||||
return
|
||||
|
||||
|
||||
def baz():
|
||||
'''"This" is a string with some
|
||||
embedded "quotes"'''
|
||||
return
|
||||
|
||||
|
||||
def troz():
|
||||
'''Indentation with tabs
|
||||
is just as OK
|
||||
'''
|
||||
return
|
||||
|
||||
|
||||
def zort():
|
||||
"""Another
|
||||
multiline
|
||||
docstring
|
||||
"""
|
||||
pass
|
||||
|
||||
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 multiline_whitespace():
|
||||
'''
|
||||
|
||||
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
def oneline_whitespace():
|
||||
''' '''
|
||||
|
||||
|
||||
def empty():
|
||||
""""""
|
||||
|
||||
|
||||
def single_quotes():
|
||||
'testing'
|
||||
|
||||
|
||||
def believe_it_or_not_this_is_in_the_py_stdlib(): '''
|
||||
"hey yah"'''
|
||||
|
||||
|
||||
def ignored_docstring():
|
||||
"""a => \
|
||||
b"""
|
||||
|
||||
def single_line_docstring_with_whitespace():
|
||||
""" This should be stripped """
|
||||
|
||||
def docstring_with_inline_tabs_and_space_indentation():
|
||||
"""hey
|
||||
|
||||
tab separated value
|
||||
tab at start of line and then a tab separated value
|
||||
multiple tabs at the beginning and inline
|
||||
mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
|
||||
|
||||
line ends with some tabs
|
||||
"""
|
||||
|
||||
|
||||
def docstring_with_inline_tabs_and_tab_indentation():
|
||||
"""hey
|
||||
|
||||
tab separated value
|
||||
tab at start of line and then a tab separated value
|
||||
multiple tabs at the beginning and inline
|
||||
mixed tabs and spaces at beginning. next line has mixed tabs and spaces only.
|
||||
|
||||
line ends with some tabs
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def backslash_space():
|
||||
"""\ """
|
||||
|
||||
|
||||
def multiline_backslash_1():
|
||||
'''
|
||||
hey\there\
|
||||
\ '''
|
||||
|
||||
|
||||
def multiline_backslash_2():
|
||||
'''
|
||||
hey there \ '''
|
||||
|
||||
# Regression test for #3425
|
||||
def multiline_backslash_really_long_dont_crash():
|
||||
"""
|
||||
hey there hello guten tag hi hoow are you ola zdravstvuyte ciao como estas ca va \ """
|
||||
|
||||
|
||||
def multiline_backslash_3():
|
||||
'''
|
||||
already escaped \\ '''
|
||||
|
||||
|
||||
def my_god_its_full_of_stars_1():
|
||||
"I'm sorry Dave\u2001"
|
||||
|
||||
|
||||
# the space below is actually a \u2001, removed in output
|
||||
def my_god_its_full_of_stars_2():
|
||||
"I'm sorry Dave "
|
||||
|
||||
|
||||
def docstring_almost_at_line_limit():
|
||||
"""long docstring................................................................."""
|
||||
|
||||
|
||||
def docstring_almost_at_line_limit2():
|
||||
"""long docstring.................................................................
|
||||
|
||||
..................................................................................
|
||||
"""
|
||||
|
||||
|
||||
def docstring_at_line_limit():
|
||||
"""long docstring................................................................"""
|
||||
|
||||
|
||||
def multiline_docstring_at_line_limit():
|
||||
"""first line-----------------------------------------------------------------------
|
||||
|
||||
second line----------------------------------------------------------------------"""
|
||||
|
||||
|
||||
def stable_quote_normalization_with_immediate_inner_single_quote(self):
|
||||
''''<text here>
|
||||
|
||||
<text here, since without another non-empty line black is stable>
|
||||
'''
|
|
@ -0,0 +1,4 @@
|
|||
# Make sure when the file ends with class's docstring,
|
||||
# It doesn't add extra blank lines.
|
||||
class ClassWithDocstring:
|
||||
"""A docstring."""
|
92
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/empty_lines.py
vendored
Normal file
92
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/empty_lines.py
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
"""Docstring."""
|
||||
|
||||
|
||||
# leading comment
|
||||
def f():
|
||||
NO = ''
|
||||
SPACE = ' '
|
||||
DOUBLESPACE = ' '
|
||||
|
||||
t = leaf.type
|
||||
p = leaf.parent # trailing comment
|
||||
v = leaf.value
|
||||
|
||||
if t in ALWAYS_NO_SPACE:
|
||||
pass
|
||||
if t == token.COMMENT: # another trailing comment
|
||||
return DOUBLESPACE
|
||||
|
||||
|
||||
assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
|
||||
|
||||
|
||||
prev = leaf.prev_sibling
|
||||
if not prev:
|
||||
prevp = preceding_leaf(p)
|
||||
if not prevp or prevp.type in OPENING_BRACKETS:
|
||||
|
||||
|
||||
return NO
|
||||
|
||||
|
||||
if prevp.type == token.EQUAL:
|
||||
if prevp.parent and prevp.parent.type in {
|
||||
syms.typedargslist,
|
||||
syms.varargslist,
|
||||
syms.parameters,
|
||||
syms.arglist,
|
||||
syms.argument,
|
||||
}:
|
||||
return NO
|
||||
|
||||
elif prevp.type == token.DOUBLESTAR:
|
||||
if prevp.parent and prevp.parent.type in {
|
||||
syms.typedargslist,
|
||||
syms.varargslist,
|
||||
syms.parameters,
|
||||
syms.arglist,
|
||||
syms.dictsetmaker,
|
||||
}:
|
||||
return NO
|
||||
|
||||
###############################################################################
|
||||
# SECTION BECAUSE SECTIONS
|
||||
###############################################################################
|
||||
|
||||
def g():
|
||||
NO = ''
|
||||
SPACE = ' '
|
||||
DOUBLESPACE = ' '
|
||||
|
||||
t = leaf.type
|
||||
p = leaf.parent
|
||||
v = leaf.value
|
||||
|
||||
# Comment because comments
|
||||
|
||||
if t in ALWAYS_NO_SPACE:
|
||||
pass
|
||||
if t == token.COMMENT:
|
||||
return DOUBLESPACE
|
||||
|
||||
# Another comment because more comments
|
||||
assert p is not None, f'INTERNAL ERROR: hand-made leaf without parent: {leaf!r}'
|
||||
|
||||
prev = leaf.prev_sibling
|
||||
if not prev:
|
||||
prevp = preceding_leaf(p)
|
||||
|
||||
if not prevp or prevp.type in OPENING_BRACKETS:
|
||||
# Start of the line or a bracketed expression.
|
||||
# More than one line for the comment.
|
||||
return NO
|
||||
|
||||
if prevp.type == token.EQUAL:
|
||||
if prevp.parent and prevp.parent.type in {
|
||||
syms.typedargslist,
|
||||
syms.varargslist,
|
||||
syms.parameters,
|
||||
syms.arglist,
|
||||
syms.argument,
|
||||
}:
|
||||
return NO
|
254
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/expression.py
vendored
Normal file
254
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/expression.py
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
...
|
||||
'some_string'
|
||||
b'\\xa3'
|
||||
Name
|
||||
None
|
||||
True
|
||||
False
|
||||
1
|
||||
1.0
|
||||
1j
|
||||
True or False
|
||||
True or False or None
|
||||
True and False
|
||||
True and False and None
|
||||
(Name1 and Name2) or Name3
|
||||
Name1 and Name2 or Name3
|
||||
Name1 or (Name2 and Name3)
|
||||
Name1 or Name2 and Name3
|
||||
(Name1 and Name2) or (Name3 and Name4)
|
||||
Name1 and Name2 or Name3 and Name4
|
||||
Name1 or (Name2 and Name3) or Name4
|
||||
Name1 or Name2 and Name3 or Name4
|
||||
v1 << 2
|
||||
1 >> v2
|
||||
1 % finished
|
||||
1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8
|
||||
((1 + v2) - (v3 * 4)) ^ (((5 ** v6) / 7) // 8)
|
||||
not great
|
||||
~great
|
||||
+value
|
||||
-1
|
||||
~int and not v1 ^ 123 + v2 | True
|
||||
(~int) and (not ((v1 ^ (123 + v2)) | True))
|
||||
+really ** -confusing ** ~operator ** -precedence
|
||||
flags & ~ select.EPOLLIN and waiters.write_task is not None
|
||||
lambda arg: None
|
||||
lambda a=True: a
|
||||
lambda a, b, c=True: a
|
||||
lambda a, b, c=True, *, d=(1 << v2), e='str': a
|
||||
lambda a, b, c=True, *vararg, d=(v1 << 2), e='str', **kwargs: a + b
|
||||
manylambdas = lambda x=lambda y=lambda z=1: z: y(): x()
|
||||
foo = (lambda port_id, ignore_missing: {"port1": port1_resource, "port2": port2_resource}[port_id])
|
||||
1 if True else 2
|
||||
str or None if True else str or bytes or None
|
||||
(str or None) if True else (str or bytes or None)
|
||||
str or None if (1 if True else 2) else str or bytes or None
|
||||
(str or None) if (1 if True else 2) else (str or bytes or None)
|
||||
((super_long_variable_name or None) if (1 if super_long_test_name else 2) else (str or bytes or None))
|
||||
{'2.7': dead, '3.7': (long_live or die_hard)}
|
||||
{'2.7': dead, '3.7': (long_live or die_hard), **{'3.6': verygood}}
|
||||
{**a, **b, **c}
|
||||
{'2.7', '3.6', '3.7', '3.8', '3.9', ('4.0' if gilectomy else '3.10')}
|
||||
({'a': 'b'}, (True or False), (+value), 'string', b'bytes') or None
|
||||
()
|
||||
(1,)
|
||||
(1, 2)
|
||||
(1, 2, 3)
|
||||
[]
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)]
|
||||
[1, 2, 3,]
|
||||
[*a]
|
||||
[*range(10)]
|
||||
[*a, 4, 5,]
|
||||
[4, *a, 5,]
|
||||
[this_is_a_very_long_variable_which_will_force_a_delimiter_split, element, another, *more]
|
||||
{i for i in (1, 2, 3)}
|
||||
{(i ** 2) for i in (1, 2, 3)}
|
||||
{(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}
|
||||
{((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}
|
||||
[i for i in (1, 2, 3)]
|
||||
[(i ** 2) for i in (1, 2, 3)]
|
||||
[(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]
|
||||
[((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]
|
||||
{i: 0 for i in (1, 2, 3)}
|
||||
{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}
|
||||
{a: b * 2 for a, b in dictionary.items()}
|
||||
{a: b * -2 for a, b in dictionary.items()}
|
||||
{k: v for k, v in this_is_a_very_long_variable_which_will_cause_a_trailing_comma_which_breaks_the_comprehension}
|
||||
Python3 > Python2 > COBOL
|
||||
Life is Life
|
||||
call()
|
||||
call(arg)
|
||||
call(kwarg='hey')
|
||||
call(arg, kwarg='hey')
|
||||
call(arg, another, kwarg='hey', **kwargs)
|
||||
call(this_is_a_very_long_variable_which_will_force_a_delimiter_split, arg, another, kwarg='hey', **kwargs) # note: no trailing comma pre-3.6
|
||||
call(*gidgets[:2])
|
||||
call(a, *gidgets[:2])
|
||||
call(**self.screen_kwargs)
|
||||
call(b, **self.screen_kwargs)
|
||||
lukasz.langa.pl
|
||||
call.me(maybe)
|
||||
1 .real
|
||||
1.0 .real
|
||||
....__class__
|
||||
list[str]
|
||||
dict[str, int]
|
||||
tuple[str, ...]
|
||||
tuple[
|
||||
str, int, float, dict[str, int]
|
||||
]
|
||||
tuple[str, int, float, dict[str, int],]
|
||||
very_long_variable_name_filters: t.List[
|
||||
t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]],
|
||||
]
|
||||
xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore
|
||||
sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
|
||||
)
|
||||
xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore
|
||||
sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)
|
||||
)
|
||||
xxxx_xxx_xxxx_xxxxx_xxxx_xxx: Callable[
|
||||
..., List[SomeClass]
|
||||
] = classmethod(sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__)) # type: ignore
|
||||
slice[0]
|
||||
slice[0:1]
|
||||
slice[0:1:2]
|
||||
slice[:]
|
||||
slice[:-1]
|
||||
slice[1:]
|
||||
slice[::-1]
|
||||
slice[d :: d + 1]
|
||||
slice[:c, c - 1]
|
||||
numpy[:, 0:1]
|
||||
numpy[:, :-1]
|
||||
numpy[0, :]
|
||||
numpy[:, i]
|
||||
numpy[0, :2]
|
||||
numpy[:N, 0]
|
||||
numpy[:2, :4]
|
||||
numpy[2:4, 1:5]
|
||||
numpy[4:, 2:]
|
||||
numpy[:, (0, 1, 2, 5)]
|
||||
numpy[0, [0]]
|
||||
numpy[:, [i]]
|
||||
numpy[1 : c + 1, c]
|
||||
numpy[-(c + 1) :, d]
|
||||
numpy[:, l[-2]]
|
||||
numpy[:, ::-1]
|
||||
numpy[np.newaxis, :]
|
||||
(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)
|
||||
{'2.7': dead, '3.7': long_live or die_hard}
|
||||
{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]
|
||||
(SomeName)
|
||||
SomeName
|
||||
(Good, Bad, Ugly)
|
||||
(i for i in (1, 2, 3))
|
||||
((i ** 2) for i in (1, 2, 3))
|
||||
((i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))
|
||||
(((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3))
|
||||
(*starred,)
|
||||
{"id": "1","type": "type","started_at": now(),"ended_at": now() + timedelta(days=10),"priority": 1,"import_session_id": 1,**kwargs}
|
||||
a = (1,)
|
||||
b = 1,
|
||||
c = 1
|
||||
d = (1,) + a + (2,)
|
||||
e = (1,).count(1)
|
||||
f = 1, *range(10)
|
||||
g = 1, *"ten"
|
||||
what_is_up_with_those_new_coord_names = (coord_names + set(vars_to_create)) + set(vars_to_remove)
|
||||
what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set(vars_to_remove)
|
||||
result = session.query(models.Customer.id).filter(models.Customer.account_id == account_id, models.Customer.email == email_address).order_by(models.Customer.id.asc()).all()
|
||||
result = session.query(models.Customer.id).filter(models.Customer.account_id == account_id, models.Customer.email == email_address).order_by(models.Customer.id.asc(),).all()
|
||||
Ø = set()
|
||||
authors.łukasz.say_thanks()
|
||||
mapping = {
|
||||
A: 0.25 * (10.0 / 12),
|
||||
B: 0.1 * (10.0 / 12),
|
||||
C: 0.1 * (10.0 / 12),
|
||||
D: 0.1 * (10.0 / 12),
|
||||
}
|
||||
|
||||
def gen():
|
||||
yield from outside_of_generator
|
||||
a = (yield)
|
||||
b = ((yield))
|
||||
c = (((yield)))
|
||||
|
||||
async def f():
|
||||
await some.complicated[0].call(with_args=(True or (1 is not 1)))
|
||||
print(* [] or [1])
|
||||
print(**{1: 3} if False else {x: x for x in range(3)})
|
||||
print(* lambda x: x)
|
||||
assert(not Test),("Short message")
|
||||
assert this is ComplexTest and not requirements.fit_in_a_single_line(force=False), "Short message"
|
||||
assert(((parens is TooMany)))
|
||||
for x, in (1,), (2,), (3,): ...
|
||||
for y in (): ...
|
||||
for z in (i for i in (1, 2, 3)): ...
|
||||
for i in (call()): ...
|
||||
for j in (1 + (2 + 3)): ...
|
||||
while(this and that): ...
|
||||
for addr_family, addr_type, addr_proto, addr_canonname, addr_sockaddr in socket.getaddrinfo('google.com', 'http'):
|
||||
pass
|
||||
a = aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp in qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
|
||||
a = aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp not in qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
|
||||
a = aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp is qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
|
||||
a = aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp is not qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz
|
||||
if (
|
||||
threading.current_thread() != threading.main_thread() and
|
||||
threading.current_thread() != threading.main_thread() or
|
||||
signal.getsignal(signal.SIGINT) != signal.default_int_handler
|
||||
):
|
||||
return True
|
||||
if (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
):
|
||||
return True
|
||||
if (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
):
|
||||
return True
|
||||
if (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
):
|
||||
return True
|
||||
if (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
):
|
||||
return True
|
||||
if (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa *
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
):
|
||||
return True
|
||||
if (
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa /
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
):
|
||||
return True
|
||||
if (
|
||||
~ aaaa.a + aaaa.b - aaaa.c * aaaa.d / aaaa.e | aaaa.f & aaaa.g % aaaa.h ^ aaaa.i << aaaa.k >> aaaa.l ** aaaa.m // aaaa.n
|
||||
):
|
||||
return True
|
||||
if (
|
||||
~ aaaaaaaa.a + aaaaaaaa.b - aaaaaaaa.c @ aaaaaaaa.d / aaaaaaaa.e | aaaaaaaa.f & aaaaaaaa.g % aaaaaaaa.h ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l ** aaaaaaaa.m // aaaaaaaa.n
|
||||
):
|
||||
return True
|
||||
if (
|
||||
~ aaaaaaaaaaaaaaaa.a + aaaaaaaaaaaaaaaa.b - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e | aaaaaaaaaaaaaaaa.f & aaaaaaaaaaaaaaaa.g % aaaaaaaaaaaaaaaa.h ^ aaaaaaaaaaaaaaaa.i << aaaaaaaaaaaaaaaa.k >> aaaaaaaaaaaaaaaa.l ** aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n
|
||||
):
|
||||
return True
|
||||
aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa - aaaaaaaaaaaaaaaa * (aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa) / (aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa)
|
||||
aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa >> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa << aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
bbbb >> bbbb * bbbb
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ^bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
last_call()
|
||||
# standalone comment at ENDMARKER
|
186
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff.py
vendored
Normal file
186
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff.py
vendored
Normal file
|
@ -0,0 +1,186 @@
|
|||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
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)
|
||||
# fmt: on
|
||||
f'trigger 3.6 mode'
|
||||
# Comment 1
|
||||
|
||||
# Comment 2
|
||||
|
||||
# fmt: off
|
||||
def func_no_args():
|
||||
a; b; c
|
||||
if True: raise RuntimeError
|
||||
if False: ...
|
||||
for i in range(10):
|
||||
print(i)
|
||||
continue
|
||||
exec('new-style exec', {}, {})
|
||||
return None
|
||||
async def coroutine(arg, exec=False):
|
||||
'Single-line docstring. Multiline is harder to reformat.'
|
||||
async with some_connection() as conn:
|
||||
await conn.do_what_i_mean('SELECT bobby, tables FROM xkcd', timeout=2)
|
||||
await asyncio.sleep(1)
|
||||
@asyncio.coroutine
|
||||
@some_decorator(
|
||||
with_args=True,
|
||||
many_args=[1,2,3]
|
||||
)
|
||||
def function_signature_stress_test(number:int,no_annotation=None,text:str='default',* ,debug:bool=False,**kwargs) -> str:
|
||||
return text[number:-1]
|
||||
# fmt: on
|
||||
def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r''):
|
||||
offset = attr.ib(default=attr.Factory( lambda: _r.uniform(1, 2)))
|
||||
assert task._cancel_stack[:len(old_stack)] == old_stack
|
||||
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)):
|
||||
...
|
||||
something = {
|
||||
# fmt: off
|
||||
key: 'value',
|
||||
}
|
||||
|
||||
def subscriptlist():
|
||||
atom[
|
||||
# fmt: off
|
||||
'some big and',
|
||||
'complex subscript',
|
||||
# fmt: on
|
||||
goes + here, andhere,
|
||||
]
|
||||
|
||||
def import_as_names():
|
||||
# fmt: off
|
||||
from hello import a, b
|
||||
'unformatted'
|
||||
# fmt: on
|
||||
|
||||
def testlist_star_expr():
|
||||
# fmt: off
|
||||
a , b = *hello
|
||||
'unformatted'
|
||||
# fmt: on
|
||||
|
||||
def yield_expr():
|
||||
# fmt: off
|
||||
yield hello
|
||||
'unformatted'
|
||||
# fmt: on
|
||||
'formatted'
|
||||
# fmt: off
|
||||
( yield hello )
|
||||
'unformatted'
|
||||
# fmt: on
|
||||
|
||||
def example(session):
|
||||
# fmt: off
|
||||
result = session\
|
||||
.query(models.Customer.id)\
|
||||
.filter(models.Customer.account_id == account_id,
|
||||
models.Customer.email == email_address)\
|
||||
.order_by(models.Customer.id.asc())\
|
||||
.all()
|
||||
# fmt: on
|
||||
def off_and_on_without_data():
|
||||
"""All comments here are technically on the same prefix.
|
||||
|
||||
The comments between will be formatted. This is a known limitation.
|
||||
"""
|
||||
# fmt: off
|
||||
|
||||
|
||||
#hey, that won't work
|
||||
|
||||
|
||||
# fmt: on
|
||||
pass
|
||||
def on_and_off_broken():
|
||||
"""Another known limitation."""
|
||||
# fmt: on
|
||||
# fmt: off
|
||||
this=should.not_be.formatted()
|
||||
and_=indeed . it is not formatted
|
||||
because . the . handling . inside . generate_ignored_nodes()
|
||||
now . considers . multiple . fmt . directives . within . one . prefix
|
||||
# fmt: on
|
||||
# fmt: off
|
||||
# ...but comments still get reformatted even though they should not be
|
||||
# fmt: on
|
||||
def long_lines():
|
||||
if True:
|
||||
typedargslist.extend(
|
||||
gen_annotated_params(ast_args.kwonlyargs, ast_args.kw_defaults, parameters, implicit_default=True)
|
||||
)
|
||||
# fmt: off
|
||||
a = (
|
||||
unnecessary_bracket()
|
||||
)
|
||||
# fmt: on
|
||||
_type_comment_re = re.compile(
|
||||
r"""
|
||||
^
|
||||
[\t ]*
|
||||
\#[ ]type:[ ]*
|
||||
(?P<type>
|
||||
[^#\t\n]+?
|
||||
)
|
||||
(?<!ignore) # note: this will force the non-greedy + in <type> to match
|
||||
# a trailing space which is why we need the silliness below
|
||||
(?<!ignore[ ]{1})(?<!ignore[ ]{2})(?<!ignore[ ]{3})(?<!ignore[ ]{4})
|
||||
(?<!ignore[ ]{5})(?<!ignore[ ]{6})(?<!ignore[ ]{7})(?<!ignore[ ]{8})
|
||||
(?<!ignore[ ]{9})(?<!ignore[ ]{10})
|
||||
[\t ]*
|
||||
(?P<nl>
|
||||
(?:\#[^\n]*)?
|
||||
\n?
|
||||
)
|
||||
$
|
||||
""",
|
||||
# fmt: off
|
||||
re.MULTILINE|re.VERBOSE
|
||||
# fmt: on
|
||||
)
|
||||
def single_literal_yapf_disable():
|
||||
"""Black does not support this."""
|
||||
BAZ = {
|
||||
(1, 2, 3, 4),
|
||||
(5, 6, 7, 8),
|
||||
(9, 10, 11, 12)
|
||||
} # yapf: disable
|
||||
cfg.rule(
|
||||
"Default", "address",
|
||||
xxxx_xxxx=["xxx-xxxxxx-xxxxxxxxxx"],
|
||||
xxxxxx="xx_xxxxx", xxxxxxx="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
xxxxxxxxx_xxxx=True, xxxxxxxx_xxxxxxxxxx=False,
|
||||
xxxxxx_xxxxxx=2, xxxxxx_xxxxx_xxxxxxxx=70, xxxxxx_xxxxxx_xxxxx=True,
|
||||
# fmt: off
|
||||
xxxxxxx_xxxxxxxxxxxx={
|
||||
"xxxxxxxx": {
|
||||
"xxxxxx": False,
|
||||
"xxxxxxx": False,
|
||||
"xxxx_xxxxxx": "xxxxx",
|
||||
},
|
||||
"xxxxxxxx-xxxxx": {
|
||||
"xxxxxx": False,
|
||||
"xxxxxxx": True,
|
||||
"xxxx_xxxxxx": "xxxxxx",
|
||||
},
|
||||
},
|
||||
# fmt: on
|
||||
xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5
|
||||
)
|
||||
# fmt: off
|
||||
yield 'hello'
|
||||
# No formatting to the end of the file
|
||||
l=[1,2,3]
|
||||
d={'a':1,
|
||||
'b':2}
|
40
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff2.py
vendored
Normal file
40
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff2.py
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
import pytest
|
||||
|
||||
TmSt = 1
|
||||
TmEx = 2
|
||||
|
||||
# fmt: off
|
||||
|
||||
# Test data:
|
||||
# Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]]
|
||||
|
||||
@pytest.mark.parametrize('test', [
|
||||
|
||||
# Test don't manage the volume
|
||||
[
|
||||
('stuff', 'in')
|
||||
],
|
||||
])
|
||||
def test_fader(test):
|
||||
pass
|
||||
|
||||
def check_fader(test):
|
||||
|
||||
pass
|
||||
|
||||
def verify_fader(test):
|
||||
# misaligned comment
|
||||
pass
|
||||
|
||||
def verify_fader(test):
|
||||
"""Hey, ho."""
|
||||
assert test.passed()
|
||||
|
||||
def test_calculate_fades():
|
||||
calcs = [
|
||||
# one is zero/none
|
||||
(0, 4, 0, 0, 10, 0, 0, 6, 10),
|
||||
(None, 4, 0, 0, 10, 0, 0, 6, 10),
|
||||
]
|
||||
|
||||
# fmt: on
|
17
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff3.py
vendored
Normal file
17
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff3.py
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
# fmt: off
|
||||
x = [
|
||||
1, 2,
|
||||
3, 4,
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
# fmt: off
|
||||
x = [
|
||||
1, 2,
|
||||
3, 4,
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
x = [
|
||||
1, 2, 3, 4
|
||||
]
|
13
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff4.py
vendored
Normal file
13
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff4.py
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
# fmt: off
|
||||
@test([
|
||||
1, 2,
|
||||
3, 4,
|
||||
])
|
||||
# fmt: on
|
||||
def f(): pass
|
||||
|
||||
@test([
|
||||
1, 2,
|
||||
3, 4,
|
||||
])
|
||||
def f(): pass
|
84
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff5.py
vendored
Normal file
84
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtonoff5.py
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
# Regression test for https://github.com/psf/black/issues/3129.
|
||||
setup(
|
||||
entry_points={
|
||||
# fmt: off
|
||||
"console_scripts": [
|
||||
"foo-bar"
|
||||
"=foo.bar.:main",
|
||||
# fmt: on
|
||||
] # Includes an formatted indentation.
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
# Regression test for https://github.com/psf/black/issues/2015.
|
||||
run(
|
||||
# fmt: off
|
||||
[
|
||||
"ls",
|
||||
"-la",
|
||||
]
|
||||
# fmt: on
|
||||
+ path,
|
||||
check=True,
|
||||
)
|
||||
|
||||
|
||||
# Regression test for https://github.com/psf/black/issues/3026.
|
||||
def test_func():
|
||||
# yapf: disable
|
||||
if unformatted( args ):
|
||||
return True
|
||||
# yapf: enable
|
||||
elif b:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# Regression test for https://github.com/psf/black/issues/2567.
|
||||
if True:
|
||||
# fmt: off
|
||||
for _ in range( 1 ):
|
||||
# fmt: on
|
||||
print ( "This won't be formatted" )
|
||||
print ( "This won't be formatted either" )
|
||||
else:
|
||||
print ( "This will be formatted" )
|
||||
|
||||
|
||||
# Regression test for https://github.com/psf/black/issues/3184.
|
||||
class A:
|
||||
async def call(param):
|
||||
if param:
|
||||
# fmt: off
|
||||
if param[0:4] in (
|
||||
"ABCD", "EFGH"
|
||||
) :
|
||||
# fmt: on
|
||||
print ( "This won't be formatted" )
|
||||
|
||||
elif param[0:4] in ("ZZZZ",):
|
||||
print ( "This won't be formatted either" )
|
||||
|
||||
print ( "This will be formatted" )
|
||||
|
||||
|
||||
# Regression test for https://github.com/psf/black/issues/2985.
|
||||
class Named(t.Protocol):
|
||||
# fmt: off
|
||||
@property
|
||||
def this_wont_be_formatted ( self ) -> str: ...
|
||||
|
||||
class Factory(t.Protocol):
|
||||
def this_will_be_formatted ( self, **kwargs ) -> Named: ...
|
||||
# fmt: on
|
||||
|
||||
|
||||
# Regression test for https://github.com/psf/black/issues/3436.
|
||||
if x:
|
||||
return x
|
||||
# fmt: off
|
||||
elif unformatted:
|
||||
# fmt: on
|
||||
will_be_formatted ()
|
3
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip.py
vendored
Normal file
3
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip.py
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
a, b = 1, 2
|
||||
c = 6 # fmt: skip
|
||||
d = 5
|
3
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip2.py
vendored
Normal file
3
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip2.py
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
l1 = ["This list should be broken up", "into multiple lines", "because it is way too long"]
|
||||
l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip
|
||||
l3 = ["I have", "trailing comma", "so I should be braked",]
|
7
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip3.py
vendored
Normal file
7
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip3.py
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
a = 3
|
||||
# fmt: off
|
||||
b, c = 1, 2
|
||||
d = 6 # fmt: skip
|
||||
e = 5
|
||||
# fmt: on
|
||||
f = ["This is a very long line that should be formatted into a clearer line ", "by rearranging."]
|
3
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip4.py
vendored
Normal file
3
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip4.py
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
a = 2
|
||||
# fmt: skip
|
||||
l = [1, 2, 3,]
|
9
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip5.py
vendored
Normal file
9
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip5.py
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
a, b, c = 3, 4, 5
|
||||
if (
|
||||
a == 3
|
||||
and b != 9 # fmt: skip
|
||||
and c is not None
|
||||
):
|
||||
print("I'm good!")
|
||||
else:
|
||||
print("I'm bad")
|
5
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip6.py
vendored
Normal file
5
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip6.py
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
class A:
|
||||
def f(self):
|
||||
for line in range(10):
|
||||
if True:
|
||||
pass # fmt: skip
|
4
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip7.py
vendored
Normal file
4
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip7.py
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
a = "this is some code"
|
||||
b = 5 #fmt:skip
|
||||
c = 9 #fmt: skip
|
||||
d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" #fmt:skip
|
62
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip8.py
vendored
Normal file
62
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip8.py
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
# Make sure a leading comment is not removed.
|
||||
def some_func( unformatted, args ): # fmt: skip
|
||||
print("I am some_func")
|
||||
return 0
|
||||
# Make sure this comment is not removed.
|
||||
|
||||
|
||||
# Make sure a leading comment is not removed.
|
||||
async def some_async_func( unformatted, args): # fmt: skip
|
||||
print("I am some_async_func")
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
# Make sure a leading comment is not removed.
|
||||
class SomeClass( Unformatted, SuperClasses ): # fmt: skip
|
||||
def some_method( self, unformatted, args ): # fmt: skip
|
||||
print("I am some_method")
|
||||
return 0
|
||||
|
||||
async def some_async_method( self, unformatted, args ): # fmt: skip
|
||||
print("I am some_async_method")
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
# Make sure a leading comment is not removed.
|
||||
if unformatted_call( args ): # fmt: skip
|
||||
print("First branch")
|
||||
# Make sure this is not removed.
|
||||
elif another_unformatted_call( args ): # fmt: skip
|
||||
print("Second branch")
|
||||
else : # fmt: skip
|
||||
print("Last branch")
|
||||
|
||||
|
||||
while some_condition( unformatted, args ): # fmt: skip
|
||||
print("Do something")
|
||||
|
||||
|
||||
for i in some_iter( unformatted, args ): # fmt: skip
|
||||
print("Do something")
|
||||
|
||||
|
||||
async def test_async_for():
|
||||
async for i in some_async_iter( unformatted, args ): # fmt: skip
|
||||
print("Do something")
|
||||
|
||||
|
||||
try : # fmt: skip
|
||||
some_call()
|
||||
except UnformattedError as ex: # fmt: skip
|
||||
handle_exception()
|
||||
finally : # fmt: skip
|
||||
finally_call()
|
||||
|
||||
|
||||
with give_me_context( unformatted, args ): # fmt: skip
|
||||
print("Do something")
|
||||
|
||||
|
||||
async def test_async_with():
|
||||
async with give_me_async_context( unformatted, args ): # fmt: skip
|
||||
print("Do something")
|
9
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fstring.py
vendored
Normal file
9
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fstring.py
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
f"f-string without formatted values is just a string"
|
||||
f"{{NOT a formatted value}}"
|
||||
f"{{NOT 'a' \"formatted\" \"value\"}}"
|
||||
f"some f-string with {a} {few():.2f} {formatted.values!r}"
|
||||
f'some f-string with {a} {few(""):.2f} {formatted.values!r}'
|
||||
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"}\''
|
95
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/function.py
vendored
Normal file
95
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/function.py
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
from third_party import X, Y, Z
|
||||
|
||||
from library import some_connection, \
|
||||
some_decorator
|
||||
f'trigger 3.6 mode'
|
||||
def func_no_args():
|
||||
a; b; c
|
||||
if True: raise RuntimeError
|
||||
if False: ...
|
||||
for i in range(10):
|
||||
print(i)
|
||||
continue
|
||||
exec("new-style exec", {}, {})
|
||||
return None
|
||||
async def coroutine(arg, exec=False):
|
||||
"Single-line docstring. Multiline is harder to reformat."
|
||||
async with some_connection() as conn:
|
||||
await conn.do_what_i_mean('SELECT bobby, tables FROM xkcd', timeout=2)
|
||||
await asyncio.sleep(1)
|
||||
@asyncio.coroutine
|
||||
@some_decorator(
|
||||
with_args=True,
|
||||
many_args=[1,2,3]
|
||||
)
|
||||
def function_signature_stress_test(number:int,no_annotation=None,text:str="default",* ,debug:bool=False,**kwargs) -> str:
|
||||
return text[number:-1]
|
||||
def spaces(a=1, b=(), c=[], d={}, e=True, f=-1, g=1 if False else 2, h="", i=r''):
|
||||
offset = attr.ib(default=attr.Factory( lambda: _r.uniform(10000, 200000)))
|
||||
assert task._cancel_stack[:len(old_stack)] == old_stack
|
||||
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)
|
||||
|
||||
def example(session):
|
||||
result = session.query(models.Customer.id).filter(
|
||||
models.Customer.account_id == account_id,
|
||||
models.Customer.email == email_address,
|
||||
).order_by(
|
||||
models.Customer.id.asc()
|
||||
).all()
|
||||
def long_lines():
|
||||
if True:
|
||||
typedargslist.extend(
|
||||
gen_annotated_params(ast_args.kwonlyargs, ast_args.kw_defaults, parameters, implicit_default=True)
|
||||
)
|
||||
typedargslist.extend(
|
||||
gen_annotated_params(
|
||||
ast_args.kwonlyargs, ast_args.kw_defaults, parameters, implicit_default=True,
|
||||
# trailing standalone comment
|
||||
)
|
||||
)
|
||||
_type_comment_re = re.compile(
|
||||
r"""
|
||||
^
|
||||
[\t ]*
|
||||
\#[ ]type:[ ]*
|
||||
(?P<type>
|
||||
[^#\t\n]+?
|
||||
)
|
||||
(?<!ignore) # note: this will force the non-greedy + in <type> to match
|
||||
# a trailing space which is why we need the silliness below
|
||||
(?<!ignore[ ]{1})(?<!ignore[ ]{2})(?<!ignore[ ]{3})(?<!ignore[ ]{4})
|
||||
(?<!ignore[ ]{5})(?<!ignore[ ]{6})(?<!ignore[ ]{7})(?<!ignore[ ]{8})
|
||||
(?<!ignore[ ]{9})(?<!ignore[ ]{10})
|
||||
[\t ]*
|
||||
(?P<nl>
|
||||
(?:\#[^\n]*)?
|
||||
\n?
|
||||
)
|
||||
$
|
||||
""", re.MULTILINE | re.VERBOSE
|
||||
)
|
||||
def trailing_comma():
|
||||
mapping = {
|
||||
A: 0.25 * (10.0 / 12),
|
||||
B: 0.1 * (10.0 / 12),
|
||||
C: 0.1 * (10.0 / 12),
|
||||
D: 0.1 * (10.0 / 12),
|
||||
}
|
||||
def f(
|
||||
a,
|
||||
**kwargs,
|
||||
) -> A:
|
||||
return (
|
||||
yield from A(
|
||||
very_long_argument_name1=very_long_value_for_the_argument,
|
||||
very_long_argument_name2=very_long_value_for_the_argument,
|
||||
**kwargs,
|
||||
)
|
||||
)
|
||||
def __await__(): return (yield)
|
53
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/function2.py
vendored
Normal file
53
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/function2.py
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
def f(
|
||||
a,
|
||||
**kwargs,
|
||||
) -> A:
|
||||
with cache_dir():
|
||||
if something:
|
||||
result = (
|
||||
CliRunner().invoke(black.main, [str(src1), str(src2), "--diff", "--check"])
|
||||
)
|
||||
limited.append(-limited.pop()) # negate top
|
||||
return A(
|
||||
very_long_argument_name1=very_long_value_for_the_argument,
|
||||
very_long_argument_name2=-very.long.value.for_the_argument,
|
||||
**kwargs,
|
||||
)
|
||||
def g():
|
||||
"Docstring."
|
||||
def inner():
|
||||
pass
|
||||
print("Inner defs should breathe a little.")
|
||||
def h():
|
||||
def inner():
|
||||
pass
|
||||
print("Inner defs should breathe a little.")
|
||||
|
||||
|
||||
if os.name == "posix":
|
||||
import termios
|
||||
def i_should_be_followed_by_only_one_newline():
|
||||
pass
|
||||
elif os.name == "nt":
|
||||
try:
|
||||
import msvcrt
|
||||
def i_should_be_followed_by_only_one_newline():
|
||||
pass
|
||||
|
||||
except ImportError:
|
||||
|
||||
def i_should_be_followed_by_only_one_newline():
|
||||
pass
|
||||
|
||||
elif False:
|
||||
|
||||
class IHopeYouAreHavingALovelyDay:
|
||||
def __call__(self):
|
||||
print("i_should_be_followed_by_only_one_newline")
|
||||
else:
|
||||
|
||||
def foo():
|
||||
pass
|
||||
|
||||
with hmm_but_this_should_get_two_preceding_newlines():
|
||||
pass
|
|
@ -0,0 +1,61 @@
|
|||
def f(a,):
|
||||
d = {'key': 'value',}
|
||||
tup = (1,)
|
||||
|
||||
def f2(a,b,):
|
||||
d = {'key': 'value', 'key2': 'value2',}
|
||||
tup = (1,2,)
|
||||
|
||||
def f(a:int=1,):
|
||||
call(arg={'explode': 'this',})
|
||||
call2(arg=[1,2,3],)
|
||||
x = {
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
}["a"]
|
||||
if a == {"a": 1,"b": 2,"c": 3,"d": 4,"e": 5,"f": 6,"g": 7,"h": 8,}["a"]:
|
||||
pass
|
||||
|
||||
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
]:
|
||||
json = {"k": {"k2": {"k3": [1,]}}}
|
||||
|
||||
|
||||
|
||||
# The type annotation shouldn't get a trailing comma since that would change its type.
|
||||
# Relevant bug report: https://github.com/psf/black/issues/2381.
|
||||
def some_function_with_a_really_long_name() -> (
|
||||
returning_a_deeply_nested_import_of_a_type_i_suppose
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def some_method_with_a_really_long_name(very_long_parameter_so_yeah: str, another_long_parameter: int) -> (
|
||||
another_case_of_returning_a_deeply_nested_import_of_a_type_i_suppose_cause_why_not
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def func() -> (
|
||||
also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black(this_shouldn_t_get_a_trailing_comma_too)
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
def func() -> ((also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black(
|
||||
this_shouldn_t_get_a_trailing_comma_too
|
||||
))
|
||||
):
|
||||
pass
|
||||
|
||||
|
||||
# Make sure inner one-element tuple won't explode
|
||||
some_module.some_function(
|
||||
argument1, (one_element_tuple,), argument4, argument5, argument6
|
||||
)
|
||||
|
||||
# Inner trailing comma causes outer to explode
|
||||
some_module.some_function(
|
||||
argument1, (one, two,), argument4, argument5, argument6
|
||||
)
|
49
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/import_spacing.py
vendored
Normal file
49
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/import_spacing.py
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
"""The asyncio package, tracking PEP 3156."""
|
||||
|
||||
# flake8: noqa
|
||||
|
||||
from logging import (
|
||||
WARNING
|
||||
)
|
||||
from logging import (
|
||||
ERROR,
|
||||
)
|
||||
import sys
|
||||
|
||||
# This relies on each of the submodules having an __all__ variable.
|
||||
from .base_events import *
|
||||
from .coroutines import *
|
||||
from .events import * # comment here
|
||||
|
||||
from .futures import *
|
||||
from .locks import * # comment here
|
||||
from .protocols import *
|
||||
|
||||
from ..runners import * # comment here
|
||||
from ..queues import *
|
||||
from ..streams import *
|
||||
|
||||
from some_library import (
|
||||
Just, Enough, Libraries, To, Fit, In, This, Nice, Split, Which, We, No, Longer, Use
|
||||
)
|
||||
from name_of_a_company.extremely_long_project_name.component.ttypes import CuteLittleServiceHandlerFactoryyy
|
||||
from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import *
|
||||
|
||||
from .a.b.c.subprocess import *
|
||||
from . import (tasks)
|
||||
from . import (A, B, C)
|
||||
from . import SomeVeryLongNameAndAllOfItsAdditionalLetters1, \
|
||||
SomeVeryLongNameAndAllOfItsAdditionalLetters2
|
||||
|
||||
__all__ = (
|
||||
base_events.__all__
|
||||
+ coroutines.__all__
|
||||
+ events.__all__
|
||||
+ futures.__all__
|
||||
+ locks.__all__
|
||||
+ protocols.__all__
|
||||
+ runners.__all__
|
||||
+ queues.__all__
|
||||
+ streams.__all__
|
||||
+ tasks.__all__
|
||||
)
|
63
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/power_op_spacing.py
vendored
Normal file
63
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/power_op_spacing.py
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
def function(**kwargs):
|
||||
t = a**2 + b**3
|
||||
return t ** 2
|
||||
|
||||
|
||||
def function_replace_spaces(**kwargs):
|
||||
t = a **2 + b** 3 + c ** 4
|
||||
|
||||
|
||||
def function_dont_replace_spaces():
|
||||
{**a, **b, **c}
|
||||
|
||||
|
||||
a = 5**~4
|
||||
b = 5 ** f()
|
||||
c = -(5**2)
|
||||
d = 5 ** f["hi"]
|
||||
e = lazy(lambda **kwargs: 5)
|
||||
f = f() ** 5
|
||||
g = a.b**c.d
|
||||
h = 5 ** funcs.f()
|
||||
i = funcs.f() ** 5
|
||||
j = super().name ** 5
|
||||
k = [(2**idx, value) for idx, value in pairs]
|
||||
l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
|
||||
m = [([2**63], [1, 2**63])]
|
||||
n = count <= 10**5
|
||||
o = settings(max_examples=10**6)
|
||||
p = {(k, k**2): v**2 for k, v in pairs}
|
||||
q = [10**i for i in range(6)]
|
||||
r = x**y
|
||||
|
||||
a = 5.0**~4.0
|
||||
b = 5.0 ** f()
|
||||
c = -(5.0**2.0)
|
||||
d = 5.0 ** f["hi"]
|
||||
e = lazy(lambda **kwargs: 5)
|
||||
f = f() ** 5.0
|
||||
g = a.b**c.d
|
||||
h = 5.0 ** funcs.f()
|
||||
i = funcs.f() ** 5.0
|
||||
j = super().name ** 5.0
|
||||
k = [(2.0**idx, value) for idx, value in pairs]
|
||||
l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001)
|
||||
m = [([2.0**63.0], [1.0, 2**63.0])]
|
||||
n = count <= 10**5.0
|
||||
o = settings(max_examples=10**6.0)
|
||||
p = {(k, k**2): v**2.0 for k, v in pairs}
|
||||
q = [10.5**i for i in range(6)]
|
||||
|
||||
|
||||
# WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873)
|
||||
if hasattr(view, "sum_of_weights"):
|
||||
return np.divide( # type: ignore[no-any-return]
|
||||
view.variance, # type: ignore[union-attr]
|
||||
view.sum_of_weights, # type: ignore[union-attr]
|
||||
out=np.full(view.sum_of_weights.shape, np.nan), # type: ignore[union-attr]
|
||||
where=view.sum_of_weights**2 > view.sum_of_weights_squared, # type: ignore[union-attr]
|
||||
)
|
||||
|
||||
return np.divide(
|
||||
where=view.sum_of_weights_of_weight_long**2 > view.sum_of_weights_squared, # type: ignore
|
||||
)
|
55
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/remove_parens.py
vendored
Normal file
55
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/remove_parens.py
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
x = (1)
|
||||
x = (1.2)
|
||||
|
||||
data = (
|
||||
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
).encode()
|
||||
|
||||
async def show_status():
|
||||
while True:
|
||||
try:
|
||||
if report_host:
|
||||
data = (
|
||||
f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
).encode()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
def example():
|
||||
return (("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"))
|
||||
|
||||
|
||||
def example1():
|
||||
return ((1111111111111111111111111111111111111111111111111111111111111111111111111111111111111))
|
||||
|
||||
|
||||
def example1point5():
|
||||
return ((((((1111111111111111111111111111111111111111111111111111111111111111111111111111111111111))))))
|
||||
|
||||
|
||||
def example2():
|
||||
return (("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"))
|
||||
|
||||
|
||||
def example3():
|
||||
return ((1111111111111111111111111111111111111111111111111111111111111111111111111111111))
|
||||
|
||||
|
||||
def example4():
|
||||
return ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((True))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
||||
|
||||
|
||||
def example5():
|
||||
return ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
||||
|
||||
|
||||
def example6():
|
||||
return ((((((((({a:a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]})))))))))
|
||||
|
||||
|
||||
def example7():
|
||||
return ((((((((({a:a for a in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20000000000000000000]})))))))))
|
||||
|
||||
|
||||
def example8():
|
||||
return (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((None)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
|
31
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/slices.py
vendored
Normal file
31
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/slices.py
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
slice[a.b : c.d]
|
||||
slice[d :: d + 1]
|
||||
slice[d + 1 :: d]
|
||||
slice[d::d]
|
||||
slice[0]
|
||||
slice[-1]
|
||||
slice[:-1]
|
||||
slice[::-1]
|
||||
slice[:c, c - 1]
|
||||
slice[c, c + 1, d::]
|
||||
slice[ham[c::d] :: 1]
|
||||
slice[ham[cheese**2 : -1] : 1 : 1, ham[1:2]]
|
||||
slice[:-1:]
|
||||
slice[lambda: None : lambda: None]
|
||||
slice[lambda x, y, *args, really=2, **kwargs: None :, None::]
|
||||
slice[1 or 2 : True and False]
|
||||
slice[not so_simple : 1 < val <= 10]
|
||||
slice[(1 for i in range(42)) : x]
|
||||
slice[:: [i for i in range(42)]]
|
||||
|
||||
|
||||
async def f():
|
||||
slice[await x : [i async for i in arange(42)] : 42]
|
||||
|
||||
|
||||
# These are from PEP-8:
|
||||
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
|
||||
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]
|
20
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/string_prefixes.py
vendored
Normal file
20
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/string_prefixes.py
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
name = "Łukasz"
|
||||
(f"hello {name}", F"hello {name}")
|
||||
(b"", B"")
|
||||
(u"", U"")
|
||||
(r"", R"")
|
||||
|
||||
(rf"", fr"", Rf"", fR"", rF"", Fr"", RF"", FR"")
|
||||
(rb"", br"", Rb"", bR"", rB"", Br"", RB"", BR"")
|
||||
|
||||
|
||||
def docstring_singleline():
|
||||
R"""2020 was one hell of a year. The good news is that we were able to"""
|
||||
|
||||
|
||||
def docstring_multiline():
|
||||
R"""
|
||||
clear out all of the issues opened in that time :p
|
||||
"""
|
29
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/torture.py
vendored
Normal file
29
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/torture.py
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
importA;() << 0 ** 101234234242352525425252352352525234890264906820496920680926538059059209922523523525 #
|
||||
|
||||
assert sort_by_dependency(
|
||||
{
|
||||
"1": {"2", "3"}, "2": {"2a", "2b"}, "3": {"3a", "3b"},
|
||||
"2a": set(), "2b": set(), "3a": set(), "3b": set()
|
||||
}
|
||||
) == ["2a", "2b", "2", "3a", "3b", "3", "1"]
|
||||
|
||||
importA
|
||||
0;0^0#
|
||||
|
||||
class A:
|
||||
def foo(self):
|
||||
for _ in range(10):
|
||||
aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc( # pylint: disable=no-member
|
||||
xxxxxxxxxxxx
|
||||
)
|
||||
|
||||
def test(self, othr):
|
||||
return (1 == 2 and
|
||||
(name, description, self.default, self.selected, self.auto_generated, self.parameters, self.meta_data, self.schedule) ==
|
||||
(name, description, othr.default, othr.selected, othr.auto_generated, othr.parameters, othr.meta_data, othr.schedule))
|
||||
|
||||
|
||||
assert (
|
||||
a_function(very_long_arguments_that_surpass_the_limit, which_is_eighty_eight_in_this_case_plus_a_bit_more)
|
||||
== {"x": "this need to pass the line limit as well", "b": "but only by a little bit"}
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
if e1234123412341234.winerror not in (_winapi.ERROR_SEM_TIMEOUT,
|
||||
_winapi.ERROR_PIPE_BUSY) or _check_timeout(t):
|
||||
pass
|
||||
|
||||
if x:
|
||||
if y:
|
||||
new_id = max(Vegetable.objects.order_by('-id')[0].id,
|
||||
Mineral.objects.order_by('-id')[0].id) + 1
|
||||
|
||||
class X:
|
||||
def get_help_text(self):
|
||||
return ngettext(
|
||||
"Your password must contain at least %(min_length)d character.",
|
||||
"Your password must contain at least %(min_length)d characters.",
|
||||
self.min_length,
|
||||
) % {'min_length': self.min_length}
|
||||
|
||||
class A:
|
||||
def b(self):
|
||||
if self.connection.mysql_is_mariadb and (
|
||||
10,
|
||||
4,
|
||||
3,
|
||||
) < self.connection.mysql_version < (10, 5, 2):
|
||||
pass
|
|
@ -0,0 +1,3 @@
|
|||
if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or
|
||||
(8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
|
||||
pass
|
|
@ -0,0 +1,8 @@
|
|||
if True:
|
||||
if True:
|
||||
if True:
|
||||
return _(
|
||||
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas "
|
||||
+ "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.",
|
||||
"qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe",
|
||||
) % {"reported_username": reported_username, "report_reason": report_reason}
|
|
@ -0,0 +1,9 @@
|
|||
ä = 1
|
||||
µ = 2
|
||||
蟒 = 3
|
||||
x󠄀 = 4
|
||||
មុ = 1
|
||||
Q̇_per_meter = 4
|
||||
|
||||
A᧚ = 3
|
||||
A፩ = 8
|
7
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/tupleassign.py
vendored
Normal file
7
crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/tupleassign.py
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
# This is a standalone comment.
|
||||
sdfjklsdfsjldkflkjsf, sdfjsdfjlksdljkfsdlkf, sdfsdjfklsdfjlksdljkf, sdsfsdfjskdflsfsdf = 1, 2, 3
|
||||
|
||||
# This is as well.
|
||||
this_will_be_wrapped_in_parens, = struct.unpack(b"12345678901234567890")
|
||||
|
||||
(a,) = call()
|
Loading…
Add table
Add a link
Reference in a new issue