diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py new file mode 100644 index 0000000000000..1677400431dd0 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py @@ -0,0 +1,3 @@ +from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py new file mode 100644 index 0000000000000..335e91036abf9 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py @@ -0,0 +1,16 @@ +from a import aksjdhflsakhdflkjsadlfajkslhf +from a import ( + aksjdhflsakhdflkjsadlfajkslhf, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd, +) +from aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa import * diff --git a/crates/ruff_python_formatter/src/other/alias.rs b/crates/ruff_python_formatter/src/other/alias.rs index 8a1501e09c66b..f59dd012bdebf 100644 --- a/crates/ruff_python_formatter/src/other/alias.rs +++ b/crates/ruff_python_formatter/src/other/alias.rs @@ -1,5 +1,6 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; +use crate::{AsFormat, FormatNodeRule, PyFormatter}; +use ruff_formatter::prelude::{space, text}; +use ruff_formatter::{write, Buffer, Format, FormatResult}; use rustpython_parser::ast::Alias; #[derive(Default)] @@ -7,6 +8,15 @@ pub struct FormatAlias; impl FormatNodeRule for FormatAlias { fn fmt_fields(&self, item: &Alias, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let Alias { + range: _, + name, + asname, + } = item; + name.format().fmt(f)?; + if let Some(asname) = asname { + write!(f, [space(), text("as"), space(), asname.format()])?; + } + Ok(()) } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_import.rs b/crates/ruff_python_formatter/src/statement/stmt_import.rs index 2585dfade7c35..10aec39721759 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_import.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_import.rs @@ -1,4 +1,5 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; +use crate::{FormatNodeRule, FormattedIterExt, PyFormatter}; +use ruff_formatter::prelude::{format_args, format_with, space, text}; use ruff_formatter::{write, Buffer, FormatResult}; use rustpython_parser::ast::StmtImport; @@ -7,6 +8,12 @@ pub struct FormatStmtImport; impl FormatNodeRule for FormatStmtImport { fn fmt_fields(&self, item: &StmtImport, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let StmtImport { names, range: _ } = item; + let names = format_with(|f| { + f.join_with(&format_args![text(","), space()]) + .entries(names.iter().formatted()) + .finish() + }); + write!(f, [text("import"), space(), names]) } } diff --git a/crates/ruff_python_formatter/src/statement/stmt_import_from.rs b/crates/ruff_python_formatter/src/statement/stmt_import_from.rs index bdae4d56bab37..ef8cc13584492 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_import_from.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_import_from.rs @@ -1,5 +1,7 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; +use crate::builders::{optional_parentheses, PyFormatterExtensions}; +use crate::{AsFormat, FormatNodeRule, PyFormatter}; +use ruff_formatter::prelude::{dynamic_text, format_with, space, text}; +use ruff_formatter::{write, Buffer, Format, FormatResult}; use rustpython_parser::ast::StmtImportFrom; #[derive(Default)] @@ -7,6 +9,40 @@ pub struct FormatStmtImportFrom; impl FormatNodeRule for FormatStmtImportFrom { fn fmt_fields(&self, item: &StmtImportFrom, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let StmtImportFrom { + module, + names, + range: _, + level, + } = item; + + let level_str = level + .map(|level| ".".repeat(level.to_usize())) + .unwrap_or(String::default()); + + write!( + f, + [ + text("from"), + space(), + dynamic_text(&level_str, None), + module.as_ref().map(AsFormat::format), + space(), + text("import"), + space(), + ] + )?; + if let [name] = names.as_slice() { + // star can't be surrounded by parentheses + if name.name.as_str() == "*" { + return text("*").fmt(f); + } + } + let names = format_with(|f| { + f.join_comma_separated() + .entries(names.iter().map(|name| (name, name.format()))) + .finish() + }); + optional_parentheses(&names).fmt(f) } } diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__force_pyi.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__force_pyi.py.snap index 52fbac942f99d..f8f00344e54de 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__force_pyi.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@miscellaneous__force_pyi.py.snap @@ -43,21 +43,20 @@ def eggs() -> Union[str, int]: ... --- Black +++ Ruff @@ -1,32 +1,58 @@ --from typing import Union -+NOT_YET_IMPLEMENTED_StmtImportFrom -+ + from typing import Union ++ @bird -def zoo(): ... +def zoo(): + ... -+ -+ -+class A: -+ ... -class A: ... ++class A: ++ ... ++ ++ @bar class B: - def BMethod(self) -> None: ... @@ -94,14 +93,14 @@ def eggs() -> Union[str, int]: ... + +class F(A, C): + ... ++ ++ ++def spam() -> None: ++ ... -class F(A, C): ... -def spam() -> None: ... -+def spam() -> None: -+ ... -+ -+ @overload -def spam(arg: str) -> str: ... +def spam(arg: str) -> str: @@ -120,7 +119,7 @@ def eggs() -> Union[str, int]: ... ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImportFrom +from typing import Union @bird diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap index 9afb2c247d9b1..8752abc340822 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@py_310__pattern_matching_extras.py.snap @@ -132,8 +132,7 @@ match bar1: --- Black +++ Ruff @@ -1,119 +1,43 @@ --import match -+NOT_YET_IMPLEMENTED_StmtImport + import match -match something: - case [a as b]: @@ -208,10 +207,11 @@ match bar1: - ), - ): - pass -- ++NOT_YET_IMPLEMENTED_StmtMatch + - case [a as match]: - pass -- + - case case: - pass +NOT_YET_IMPLEMENTED_StmtMatch @@ -220,8 +220,9 @@ match bar1: -match match: - case case: - pass -- -- ++NOT_YET_IMPLEMENTED_StmtMatch + + -match a, *b(), c: - case d, *f, g: - pass @@ -236,30 +237,28 @@ match bar1: - pass - case {"maybe": something(complicated as this) as that}: - pass +- +NOT_YET_IMPLEMENTED_StmtMatch - -match something: - case 1 as a: - pass -+NOT_YET_IMPLEMENTED_StmtMatch - case 2 as b, 3 as c: - pass ++NOT_YET_IMPLEMENTED_StmtMatch - case 4 as d, (5 as e), (6 | 7 as g), *h: - pass -+NOT_YET_IMPLEMENTED_StmtMatch - +- -match bar1: - case Foo(aa=Callable() as aa, bb=int()): - print(bar1.aa, bar1.bb) - case _: - print("no match", "\n") -+NOT_YET_IMPLEMENTED_StmtMatch - - +- +- -match bar1: - case Foo( - normal=x, perhaps=[list, {"x": d, "y": 1.0}] as y, otherwise=something, q=t as u @@ -271,7 +270,7 @@ match bar1: ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImport +import match NOT_YET_IMPLEMENTED_StmtMatch diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__collections.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__collections.py.snap index 51c59c4e9d7b1..cf6666738208c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__collections.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__collections.py.snap @@ -83,31 +83,9 @@ if True: ```diff --- Black +++ Ruff -@@ -1,40 +1,22 @@ --import core, time, a -+NOT_YET_IMPLEMENTED_StmtImport - --from . import A, B, C -+NOT_YET_IMPLEMENTED_StmtImportFrom - - # keeps existing trailing comma --from foo import ( -- bar, --) -+NOT_YET_IMPLEMENTED_StmtImportFrom - - # also keeps existing structure --from foo import ( -- baz, -- qux, --) -+NOT_YET_IMPLEMENTED_StmtImportFrom - - # `as` works as well --from foo import ( -- xyzzy as magic, --) -+NOT_YET_IMPLEMENTED_StmtImportFrom +@@ -18,23 +18,12 @@ + xyzzy as magic, + ) -a = { - 1, @@ -132,7 +110,7 @@ if True: nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)} nested_long_lines = [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", -@@ -52,10 +34,7 @@ +@@ -52,10 +41,7 @@ y = { "oneple": (1,), } @@ -149,18 +127,25 @@ if True: ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImport +import core, time, a -NOT_YET_IMPLEMENTED_StmtImportFrom +from . import A, B, C # keeps existing trailing comma -NOT_YET_IMPLEMENTED_StmtImportFrom +from foo import ( + bar, +) # also keeps existing structure -NOT_YET_IMPLEMENTED_StmtImportFrom +from foo import ( + baz, + qux, +) # `as` works as well -NOT_YET_IMPLEMENTED_StmtImportFrom +from foo import ( + xyzzy as magic, +) a = {1, 2, 3} b = {1, 2, 3} diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments.py.snap deleted file mode 100644 index d78df8d356e01..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments.py.snap +++ /dev/null @@ -1,347 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments.py ---- -## Input - -```py -#!/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.""" - - -#'

This is pweave!

- - -@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. -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -9,16 +9,16 @@ - Possibly also many, many lines. - """ - --import os.path --import sys -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport - --import a --from b.c import X # some noqa comment -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImportFrom # some noqa comment - - try: -- import fast -+ NOT_YET_IMPLEMENTED_StmtImport - except ImportError: -- import slow as fast -+ NOT_YET_IMPLEMENTED_StmtImport - - - # Some comment before a function. -@@ -35,7 +35,7 @@ - Possibly many lines. - """ - # FIXME: Some comment about why this function is crap but still in production. -- import inner_imports -+ NOT_YET_IMPLEMENTED_StmtImport - - if inner_imports.are_evil(): - # Explains why we have this if. -``` - -## Ruff Output - -```py -#!/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. -""" - -NOT_YET_IMPLEMENTED_StmtImport -NOT_YET_IMPLEMENTED_StmtImport - -NOT_YET_IMPLEMENTED_StmtImport -NOT_YET_IMPLEMENTED_StmtImportFrom # some noqa comment - -try: - NOT_YET_IMPLEMENTED_StmtImport -except ImportError: - NOT_YET_IMPLEMENTED_StmtImport - - -# 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. - NOT_YET_IMPLEMENTED_StmtImport - - 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.""" - - -#'

This is pweave!

- - -@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. -``` - -## Black Output - -```py -#!/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.""" - - -#'

This is pweave!

- - -@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. -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments2.py.snap index 23020bfa282f5..e7ae03c930383 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments2.py.snap @@ -177,19 +177,18 @@ instruction()#comment with bad spacing ```diff --- Black +++ Ruff -@@ -1,9 +1,5 @@ --from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( +@@ -1,8 +1,8 @@ + 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 # NOT DRY + ) + from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent as component, # DRY --) -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom ++ MyLovelyCompanyTeamProjectComponent as component # DRY + ) # Please keep __all__ alphabetized within each category. - -@@ -45,7 +41,7 @@ +@@ -45,7 +45,7 @@ # user-defined types and objects Cheese, Cheese("Wensleydale"), @@ -198,7 +197,7 @@ instruction()#comment with bad spacing ] if "PYTHON" in os.environ: -@@ -60,8 +56,12 @@ +@@ -60,8 +60,12 @@ # Comment before function. def inline_comments_in_brackets_ruin_everything(): if typedargslist: @@ -212,7 +211,7 @@ instruction()#comment with bad spacing children[0], body, children[-1], # type: ignore -@@ -72,7 +72,11 @@ +@@ -72,7 +76,11 @@ body, parameters.children[-1], # )2 ] @@ -225,7 +224,7 @@ instruction()#comment with bad spacing if ( self._proc is not None # has the child process finished? -@@ -114,25 +118,9 @@ +@@ -114,25 +122,9 @@ # yup arg3=True, ) @@ -254,7 +253,7 @@ instruction()#comment with bad spacing while True: if False: continue -@@ -143,7 +131,10 @@ +@@ -143,7 +135,10 @@ # let's return return Node( syms.simple_stmt, @@ -266,7 +265,7 @@ instruction()#comment with bad spacing ) -@@ -158,7 +149,11 @@ +@@ -158,7 +153,11 @@ class Test: def _init_host(self, parsed) -> None: @@ -284,8 +283,12 @@ instruction()#comment with bad spacing ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom +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. diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments4.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments4.py.snap index 2358992e6cfe4..7a1948330ffe6 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments4.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments4.py.snap @@ -106,19 +106,7 @@ def foo3(list_a, list_b): ```diff --- Black +++ Ruff -@@ -1,9 +1,5 @@ --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 --) -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom - - - class C: -@@ -58,37 +54,28 @@ +@@ -58,37 +58,28 @@ def foo(list_a, list_b): results = ( @@ -172,8 +160,12 @@ def foo3(list_a, list_b): ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom +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: diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments5.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments5.py.snap deleted file mode 100644 index 28f4426951396..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments5.py.snap +++ /dev/null @@ -1,255 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/comments5.py ---- -## Input - -```py -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() -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -27,7 +27,7 @@ - except OSError: - print("problems") - --import sys -+NOT_YET_IMPLEMENTED_StmtImport - - - # leading function comment -``` - -## Ruff Output - -```py -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") - -NOT_YET_IMPLEMENTED_StmtImport - - -# 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() -``` - -## Black Output - -```py -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() -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments6.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments6.py.snap index 511d9fe1b1673..a27f99c5bf93e 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments6.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments6.py.snap @@ -130,12 +130,6 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite ```diff --- Black +++ Ruff -@@ -1,4 +1,4 @@ --from typing import Any, Tuple -+NOT_YET_IMPLEMENTED_StmtImportFrom - - - def f( @@ -49,9 +49,7 @@ element = 0 # type: int another_element = 1 # type: float @@ -192,7 +186,7 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImportFrom +from typing import Any, Tuple def f( diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments_non_breaking_space.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments_non_breaking_space.py.snap index 12fd5c1269dca..e8c73055d0c21 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments_non_breaking_space.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__comments_non_breaking_space.py.snap @@ -31,18 +31,7 @@ def function(a:int=42): ```diff --- Black +++ Ruff -@@ -1,9 +1,4 @@ --from .config import ( -- ConfigTypeAttributes, -- Int, -- Path, # String, -- # DEFAULT_TYPE_ATTRIBUTES, --) -+NOT_YET_IMPLEMENTED_StmtImportFrom - - result = 1 # A simple comment - result = (1,) # Another one -@@ -14,9 +9,9 @@ +@@ -14,9 +14,9 @@ def function(a: int = 42): @@ -60,7 +49,12 @@ def function(a:int=42): ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImportFrom +from .config import ( + ConfigTypeAttributes, + Int, + Path, # String, + # DEFAULT_TYPE_ATTRIBUTES, +) result = 1 # A simple comment result = (1,) # Another one diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff.py.snap index 32082f2da9457..013a97677be58 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff.py.snap @@ -198,22 +198,13 @@ d={'a':1, ```diff --- Black +++ Ruff -@@ -1,15 +1,14 @@ - #!/usr/bin/env python3 --import asyncio --import sys -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport +@@ -6,10 +6,9 @@ --from third_party import X, Y, Z -+NOT_YET_IMPLEMENTED_StmtImportFrom - --from library import some_connection, some_decorator -+NOT_YET_IMPLEMENTED_StmtImportFrom + from library import some_connection, some_decorator # fmt: off -from third_party import (X, - Y, Z) -+NOT_YET_IMPLEMENTED_StmtImportFrom ++from third_party import X, Y, Z # fmt: on -f"trigger 3.6 mode" +NOT_YET_IMPLEMENTED_ExprJoinedStr @@ -336,7 +327,7 @@ d={'a':1, # fmt: off - from hello import a, b - 'unformatted' -+ NOT_YET_IMPLEMENTED_StmtImportFrom ++ from hello import a, b + "unformatted" # fmt: on @@ -433,14 +424,14 @@ d={'a':1, ```py #!/usr/bin/env python3 -NOT_YET_IMPLEMENTED_StmtImport -NOT_YET_IMPLEMENTED_StmtImport +import asyncio +import sys -NOT_YET_IMPLEMENTED_StmtImportFrom +from third_party import X, Y, Z -NOT_YET_IMPLEMENTED_StmtImportFrom +from library import some_connection, some_decorator # fmt: off -NOT_YET_IMPLEMENTED_StmtImportFrom +from third_party import X, Y, Z # fmt: on NOT_YET_IMPLEMENTED_ExprJoinedStr # Comment 1 @@ -539,7 +530,7 @@ def subscriptlist(): def import_as_names(): # fmt: off - NOT_YET_IMPLEMENTED_StmtImportFrom + from hello import a, b "unformatted" # fmt: on diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff2.py.snap index 56b345fae1b2d..abdfcb6d563f9 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtonoff2.py.snap @@ -52,12 +52,7 @@ def test_calculate_fades(): ```diff --- Black +++ Ruff -@@ -1,40 +1,44 @@ --import pytest -+NOT_YET_IMPLEMENTED_StmtImport - - TmSt = 1 - TmEx = 2 +@@ -5,36 +5,40 @@ # fmt: off @@ -113,7 +108,7 @@ def test_calculate_fades(): ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImport +import pytest TmSt = 1 TmEx = 2 diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtpass_imports.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtpass_imports.py.snap deleted file mode 100644 index 5a0bfd673fc08..0000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__fmtpass_imports.py.snap +++ /dev/null @@ -1,114 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtpass_imports.py ---- -## Input - -```py -# 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 -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,19 +1,19 @@ - # Regression test for https://github.com/psf/black/issues/3438 - --import ast --import collections # fmt: skip --import dataclasses -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport # fmt: skip -+NOT_YET_IMPLEMENTED_StmtImport - # fmt: off --import os -+NOT_YET_IMPLEMENTED_StmtImport - # fmt: on --import pathlib -+NOT_YET_IMPLEMENTED_StmtImport - --import re # fmt: skip --import secrets -+NOT_YET_IMPLEMENTED_StmtImport # fmt: skip -+NOT_YET_IMPLEMENTED_StmtImport - - # fmt: off --import sys -+NOT_YET_IMPLEMENTED_StmtImport - # fmt: on - --import tempfile --import zoneinfo -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport -``` - -## Ruff Output - -```py -# Regression test for https://github.com/psf/black/issues/3438 - -NOT_YET_IMPLEMENTED_StmtImport -NOT_YET_IMPLEMENTED_StmtImport # fmt: skip -NOT_YET_IMPLEMENTED_StmtImport -# fmt: off -NOT_YET_IMPLEMENTED_StmtImport -# fmt: on -NOT_YET_IMPLEMENTED_StmtImport - -NOT_YET_IMPLEMENTED_StmtImport # fmt: skip -NOT_YET_IMPLEMENTED_StmtImport - -# fmt: off -NOT_YET_IMPLEMENTED_StmtImport -# fmt: on - -NOT_YET_IMPLEMENTED_StmtImport -NOT_YET_IMPLEMENTED_StmtImport -``` - -## Black Output - -```py -# 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 -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function.py.snap index 771b8b6398197..3536f09059fcd 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function.py.snap @@ -107,20 +107,12 @@ def __await__(): return (yield) ```diff --- Black +++ Ruff -@@ -1,12 +1,11 @@ - #!/usr/bin/env python3 --import asyncio --import sys -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport +@@ -5,8 +5,7 @@ + from third_party import X, Y, Z --from third_party import X, Y, Z -+NOT_YET_IMPLEMENTED_StmtImportFrom - --from library import some_connection, some_decorator + from library import some_connection, some_decorator - -f"trigger 3.6 mode" -+NOT_YET_IMPLEMENTED_StmtImportFrom +NOT_YET_IMPLEMENTED_ExprJoinedStr @@ -221,12 +213,12 @@ def __await__(): return (yield) ```py #!/usr/bin/env python3 -NOT_YET_IMPLEMENTED_StmtImport -NOT_YET_IMPLEMENTED_StmtImport +import asyncio +import sys -NOT_YET_IMPLEMENTED_StmtImportFrom +from third_party import X, Y, Z -NOT_YET_IMPLEMENTED_StmtImportFrom +from library import some_connection, some_decorator NOT_YET_IMPLEMENTED_ExprJoinedStr diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap index 3fd47e2167c3f..23da8b63513e6 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__function2.py.snap @@ -65,22 +65,15 @@ with hmm_but_this_should_get_two_preceding_newlines(): ```diff --- Black +++ Ruff -@@ -32,34 +32,28 @@ - - - if os.name == "posix": -- import termios -+ NOT_YET_IMPLEMENTED_StmtImport +@@ -36,7 +36,6 @@ def i_should_be_followed_by_only_one_newline(): pass - elif os.name == "nt": try: -- import msvcrt -+ NOT_YET_IMPLEMENTED_StmtImport - - def i_should_be_followed_by_only_one_newline(): + import msvcrt +@@ -45,21 +44,16 @@ pass except ImportError: @@ -141,13 +134,13 @@ def h(): if os.name == "posix": - NOT_YET_IMPLEMENTED_StmtImport + import termios def i_should_be_followed_by_only_one_newline(): pass elif os.name == "nt": try: - NOT_YET_IMPLEMENTED_StmtImport + import msvcrt def i_should_be_followed_by_only_one_newline(): pass diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__import_spacing.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__import_spacing.py.snap index 6b2e7df8f35f7..f08a097d01e43 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__import_spacing.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__import_spacing.py.snap @@ -61,79 +61,15 @@ __all__ = ( ```diff --- Black +++ Ruff -@@ -2,53 +2,31 @@ - - # flake8: noqa - --from logging import WARNING --from logging import ( -- ERROR, --) --import sys -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImport - - # This relies on each of the submodules having an __all__ variable. --from .base_events import * --from .coroutines import * --from .events import * # comment here -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom # comment here - --from .futures import * --from .locks import * # comment here --from .protocols import * -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom # comment here -+NOT_YET_IMPLEMENTED_StmtImportFrom - --from ..runners import * # comment here --from ..queues import * --from ..streams import * -+NOT_YET_IMPLEMENTED_StmtImportFrom # comment here -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom - --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 ( +@@ -38,7 +38,7 @@ + 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 * -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom - --from .a.b.c.subprocess import * --from . import tasks --from . import A, B, C --from . import ( -- SomeVeryLongNameAndAllOfItsAdditionalLetters1, -- SomeVeryLongNameAndAllOfItsAdditionalLetters2, --) -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_StmtImportFrom ++ CuteLittleServiceHandlerFactoryyy + ) + from name_of_a_company.extremely_long_project_name.extremely_long_component_name.ttypes import * - __all__ = ( - base_events.__all__ ``` ## Ruff Output @@ -143,31 +79,53 @@ __all__ = ( # flake8: noqa -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImport +from logging import WARNING +from logging import ( + ERROR, +) +import sys # This relies on each of the submodules having an __all__ variable. -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom # comment here - -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom # comment here -NOT_YET_IMPLEMENTED_StmtImportFrom - -NOT_YET_IMPLEMENTED_StmtImportFrom # comment here -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom - -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom - -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom -NOT_YET_IMPLEMENTED_StmtImportFrom +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__ diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_await_parens.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_await_parens.py.snap index e77d6934e304c..d529f18f49088 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_await_parens.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_await_parens.py.snap @@ -93,12 +93,6 @@ async def main(): ```diff --- Black +++ Ruff -@@ -1,4 +1,4 @@ --import asyncio -+NOT_YET_IMPLEMENTED_StmtImport - - - # Control example @@ -8,59 +8,70 @@ # Remove brackets for short coroutine/task @@ -219,7 +213,7 @@ async def main(): ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImport +import asyncio # Control example diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_newline_after_code_block_open.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_newline_after_code_block_open.py.snap index f9095f8b6ff68..c97f2a11d6187 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_newline_after_code_block_open.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@simple_cases__remove_newline_after_code_block_open.py.snap @@ -120,12 +120,6 @@ with open("/path/to/file.txt", mode="r") as read_file: ```diff --- Black +++ Ruff -@@ -1,4 +1,4 @@ --import random -+NOT_YET_IMPLEMENTED_StmtImport - - - def foo1(): @@ -27,16 +27,16 @@ @@ -151,7 +145,7 @@ with open("/path/to/file.txt", mode="r") as read_file: ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtImport +import random def foo1(): diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap index bbff73657c9a9..2b48c542e5020 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap @@ -111,7 +111,7 @@ x53 = ( ## Output ```py -NOT_YET_IMPLEMENTED_StmtImportFrom +from argparse import Namespace a = Namespace() diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap index 408588813cb8b..f8a09bc04e07f 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__call.py.snap @@ -96,7 +96,7 @@ f( ## Output ```py -NOT_YET_IMPLEMENTED_StmtImportFrom +from unittest.mock import MagicMock def f(*args, **kwargs): diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__import.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__import.py.snap new file mode 100644 index 0000000000000..020860638336b --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__import.py.snap @@ -0,0 +1,28 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import.py +--- +## Input +```py +from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +from a import aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd +``` + +## Output +```py +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd, +) +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__import_from.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__import_from.py.snap new file mode 100644 index 0000000000000..0d8c90572e987 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__import_from.py.snap @@ -0,0 +1,46 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/import_from.py +--- +## Input +```py +from a import aksjdhflsakhdflkjsadlfajkslhf +from a import ( + aksjdhflsakhdflkjsadlfajkslhf, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd, +) +from aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa import * +``` + +## Output +```py +from a import aksjdhflsakhdflkjsadlfajkslhf +from a import ( + aksjdhflsakhdflkjsadlfajkslhf, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa, +) +from a import ( + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as dfgsdfgsd, + aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa as sdkjflsdjlahlfd, +) +from aksjdhflsakhdflkjsadlfajkslhfdkjsaldajlahflashdfljahlfksajlhfajfjfsaahflakjslhdfkjalhdskjfa import * +``` + + +