Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump version to v0.3.0 #10151

Merged
merged 10 commits into from Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions BREAKING_CHANGES.md
@@ -1,5 +1,51 @@
# Breaking Changes

## 0.3.0

### Ruff 2024.2 style

The formatter now formats code according to the Ruff 2024.2 style guide. Read the [changelog](./CHANGELOG.md#030) for a detailed list of stabilized style changes.

### `isort`: Use one blank line after imports in typing stub files

Previously, Ruff used one or two blank lines (or the number configured by `isort.lines-after-imports`) after imports in typing stub files (`.pyi`).
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved
The [typing style guide](https://typing.readthedocs.io/en/latest/source/stubs.html#style-guide) recommends using at most 1 blank line in stub files for grouping.
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved
As of this release, `isort` now always uses one blank line after imports in typing stub files, the same as the formatter.
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

### Remove `build` from the default exclusion list
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

Ruff maintains a list of default exclusions, which now consists of the following patterns:
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

- `.bzr`
- `.direnv`
- `.eggs`
- `.git`
- `.git-rewrite`
- `.hg`
- `.ipynb_checkpoints`
- `.mypy_cache`
- `.nox`
- `.pants.d`
- `.pyenv`
- `.pytest_cache`
- `.pytype`
- `.ruff_cache`
- `.svn`
- `.tox`
- `.venv`
- `.vscode`
- `__pypackages__`
- `_build`
- `buck-out`
- `dist`
- `node_modules`
- `site-packages`
- `venv`

Previously, the `build` directory was excluded by default. However, the `build` directory tends to be a not un-popular directory
name and excluding it by default caused confusion. Ruff now no longer excludes `build` except if it is excluded by a `.gitignore` file
or because it is listed in`extend-exclude`.
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

## 0.1.9

### `site-packages` is now excluded by default ([#5513](https://github.com/astral-sh/ruff/pull/5513))
Expand Down
63 changes: 63 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,68 @@
# Changelog

## 0.3.0

This release introduces the new Ruff formatter 2024.2 style and adds a new lint rule to
detect invalid formatter suppression comments.

### Preview features

- \[`pycodestyle`\] Allow `os.environ` modifications between imports (`E402`) ([#10066](https://github.com/astral-sh/ruff/pull/10066))
- \[`pycodestyle`\] Don't warn about single whitespace before comma in tuple (`E203`) ([#10094](https://github.com/astral-sh/ruff/pull/10094))
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved
- \[`flake8-bandit`\] Remove suspicious-lxml-import (`S410`) ([#10154](https://github.com/astral-sh/ruff/pull/10154))

### Rule changes

- \[`isort`\]: Use one blank line after imports in typing stub files. ([#9971](https://github.com/astral-sh/ruff/pull/9971))
- \[`pylint`\] New Rule `dict-iter-missing-items` (`PLE1141`) ([#9845](https://github.com/astral-sh/ruff/pull/9845))
- \[`pylint`\] Ignore `sys.version` and `sys.platform` (`PLR1714`) ([#10054](https://github.com/astral-sh/ruff/pull/10054))
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved
- \[`ruff`\] Expand rule for `list(iterable).pop(0)` idiom (`RUF015`) ([#10148](https://github.com/astral-sh/ruff/pull/10148))
- \[`flake8-boolean-trap`\] Allow boolean positionals in `__post_init__` ([#10027](https://github.com/astral-sh/ruff/pull/10027))
- \[`flake8-copyright`\] Allow © in copyright notices ([#10065](https://github.com/astral-sh/ruff/pull/10065))
- \[`pyupgrade`\] Detect literals with unary operators (`UP018`) ([#10060](https://github.com/astral-sh/ruff/pull/10060))
- \[`eradicate`\] Detect commented out `case` statements (`ERA001`) ([#10055](https://github.com/astral-sh/ruff/pull/10055))
- \[`eradicate`\] detect single-line code for `try:`, `except:`, etc. (`ERA001`) ([#10057](https://github.com/astral-sh/ruff/pull/10057))
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

### Formatter

This release introduces the new Ruff 2024.2 style, stabilizing the following changes:
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

- Prefer splitting the assignment's value over the target or type annotation ([#8943](https://github.com/astral-sh/ruff/pull/8943))
- Remove blank lines before class docstrings ([#9154](https://github.com/astral-sh/ruff/pull/9154))
- Wrap multiple context managers in `with` parentheses when targeting Python 3.9 or newer ([#9222](https://github.com/astral-sh/ruff/pull/9222))
- Add a blank line after nested classes with a dummy body (`...`) in typing stub files ([#9155](https://github.com/astral-sh/ruff/pull/9155))
- Reduce vertical spacing for classes and functions with a dummy (`...`) body ([#7440](https://github.com/astral-sh/ruff/issues/7440), [#9240](https://github.com/astral-sh/ruff/pull/9240))
- Add a blank line after the module docstring ([#8283](https://github.com/astral-sh/ruff/pull/8283))
- Parenthesize long type hints in assignments ([#9210](https://github.com/astral-sh/ruff/pull/9210))
- Preserve indent for single multiline-string call-expressions ([#9673](https://github.com/astral-sh/ruff/pull/9637))
- Normalize hex escape and unicode escape sequences ([#9280](https://github.com/astral-sh/ruff/pull/9280))
- Format module docstrings ([#9725](https://github.com/astral-sh/ruff/pull/9725))

### CLI

- Explicitly disallow `extend` as part of a `--config` flag ([#10135](https://github.com/astral-sh/ruff/pull/10135))
- Remove `build` from the default exclusion list ([#10093](https://github.com/astral-sh/ruff/pull/10093))
- Deprecate `ruff <path>`, `ruff --explain`, `ruff --clean`, and `ruff --generate-shell-completion` in favor of `ruff check <path>`, `ruff rule`, `ruff clean`, and `ruff generate-shell-completion` ([#10169](https://github.com/astral-sh/ruff/pull/10169))

### Bug fixes

- \[`pycodestyle`\] Mark fixes overlapping with a multiline string as unsafe (`W293`) ([#10049](https://github.com/astral-sh/ruff/pull/10049))
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved
- \[`flake8-type-checking`\] Respect runtime-required decorators for function signatures ([#10091](https://github.com/astral-sh/ruff/pull/10091))
- Set PowerPC page size to 64KB ([#10080](https://github.com/astral-sh/ruff/pull/10080))
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved
- \[`ruff`\] Avoid f-string false positives in `gettext` calls (`RUF027`) ([#10118](https://github.com/astral-sh/ruff/pull/10118))
- \[`pylint`\] Delete entire statement, including semicolons (`PLR0203`) ([#10074](https://github.com/astral-sh/ruff/pull/10074))
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved
- \[`flake8-bugbear`\] Avoid adding default initializers to stubs (`B006`) ([#10152](https://github.com/astral-sh/ruff/pull/10152))

### Performance

- Add cold attribute to less likely printer queue branches in the formatter ([#10121](https://github.com/astral-sh/ruff/pull/10121))
- Skip unnecessary string normalization in the formatter ([#10116](https://github.com/astral-sh/ruff/pull/10116))

### Documentation

- Remove "Beta" Label from formatter documentation ([#10144](https://github.com/astral-sh/ruff/pull/10144))
- `line-length` option: fix link to `pycodestyle.max-line-length` ([#10136](https://github.com/astral-sh/ruff/pull/10136))

## 0.2.2

Highlights include:
Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -150,7 +150,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.2.2
rev: v0.3.0
hooks:
# Run the linter.
- id: ruff
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "ruff"
version = "0.2.2"
version = "0.3.0"
publish = false
authors = { workspace = true }
edition = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_linter/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "ruff_linter"
version = "0.2.2"
version = "0.3.0"
publish = false
authors = { workspace = true }
edition = { workspace = true }
Expand Down
199 changes: 144 additions & 55 deletions crates/ruff_python_formatter/README.md
Expand Up @@ -208,37 +208,167 @@ on both `first()` and `second()`:
]
```

#### Line width vs. line length
#### Parenthesizing long nested-expressions

Black 24 and newer parenthesizes long conditional expressions and type annotations in function parameters:

```python
# Black
[
"____________________________",
"foo",
"bar",
(
"baz"
if some_really_looooooooong_variable
else "some other looooooooooooooong value"
),
]

def foo(
i: int,
x: (
Loooooooooooooooooooooooong
| Looooooooooooooooong
| Looooooooooooooooooooong
| Looooooong
),
*,
s: str,
) -> None:
pass

# Ruff
[
"____________________________",
"foo",
"bar",
"baz" if some_really_looooooooong_variable else "some other looooooooooooooong value"
]

Ruff uses the Unicode width of a line to determine if a line fits. Black's stable style uses
character width, while Black's preview style uses Unicode width for strings ([#3445](https://github.com/psf/black/pull/3445)),
and character width for all other tokens. Ruff's behavior is closer to Black's preview style than
Black's stable style, although Ruff _also_ uses Unicode width for identifiers and comments.
def foo(
i: int,
x: Loooooooooooooooooooooooong
| Looooooooooooooooong
| Looooooooooooooooooooong
| Looooooong,
*,
s: str,
) -> None:
pass
```

We agree that Ruff's formatting (that matches Black's 23) is hard to read and needs improvement. But we aren't convinced that parenthesizing long nested expressions is the best solution, especially when considering expression formatting holistically. That's why we want to defer the decision until we've explored alternative nested expression formatting styles. See [psf/Black#4123](https://github.com/psf/black/issues/4123) for an in-depth explanation of our concerns and an outline of possible alternatives.

#### Walruses in slice expressions
#### Call expressions with a single multiline string argument

Black avoids inserting space around `:=` operators within slices. For example, the following adheres
to Black stable style:
Unlike Black, Ruff preserves the indentation of a single multiline-string argument in a call expression:

```python
# Input
x[y:=1]
call(
""""
A multiline
string
"""
)

dedent(""""
A multiline
string
""")

# Black
x[y:=1]
call(
""""
A multiline
string
"""
)

dedent(
""""
A multiline
string
"""
)


# Ruff
call(
""""
A multiline
string
"""
)

dedent(""""
A multiline
string
""")
```

Ruff will instead add space around the `:=` operator:
Black intended to ship a similar style change as part of the 2024 style that always removes the indent. It turned out that this change was too disruptive to justify the cases where it improved formatting. Ruff introduced the new heuristic of preserving the indent, and we believe it's a good compromise that improves formatting but isn't disruptive.
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

#### Blank lines at the start of a block

Black 24 and newer allow blank lines at the start of a block, where Ruff always removes them:
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

```python
# Black
if x:

a = 123

# Ruff
if x:
a = 123
```

We consider adopting Black's formatting at a later point with an improved heuristic because we're concerned that allowing blank lines at the start of a block leads [to unintentional blank lines when refactoring or moving code](https://github.com/astral-sh/ruff/issues/8893#issuecomment-1867259744). The style change is tracked in [#9745](https://github.com/astral-sh/ruff/issues/9745).
MichaReiser marked this conversation as resolved.
Show resolved Hide resolved

#### Hex codes and Unicode sequences

Ruff normalizes hex codes and Unicode sequences in strings ([#9280](https://github.com/astral-sh/ruff/pull/9280)). Black intended to ship this change as part of the 2024 style but accidentally didn't.

```python
# Black
a = "\x1B"
b = "\u200B"
c = "\U0001F977"
d = "\N{CYRILLIC small LETTER BYELORUSSIAN-UKRAINIAN I}"

# Ruff
a = "\x1b"
b = "\u200b"
c = "\U0001f977"
d = "\N{CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I}"
```

#### Module docstrings

Ruff formats module docstrings similar to class or function docstrings, whereas Black does not.

```python
# Input
x[y:=1]
"""Module docstring

"""

# Black
"""Module docstring

"""

# Ruff
x[y := 1]
"""Module docstring"""

```

This will likely be incorporated into Black's preview style ([#3823](https://github.com/psf/black/pull/3823)).
#### Line width vs. line length

Ruff uses the Unicode width of a line to determine if a line fits. Black uses Unicode width for strings,
and character width for all other tokens. Ruff _also_ uses Unicode width for identifiers and comments.

#### `global` and `nonlocal` names are broken across multiple lines by continuations

Expand Down Expand Up @@ -606,44 +736,3 @@ df.drop(columns=["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]).drop_duplicates(a).rename
}
).to_csv(path / "aaaaaa.csv", index=False).other(a)
```

#### Expressions with (non-pragma) trailing comments are split more often ([#7823](https://github.com/astral-sh/ruff/issues/7823))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We fixed this at some point


Both Ruff and Black will break the following expression over multiple lines, since it then allows
the expression to fit within the configured line width:

```python
# Input
some_long_variable_name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

# Black
some_long_variable_name = (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
)

# Ruff
some_long_variable_name = (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
)
```

However, if the expression ends in a trailing comment, Black will avoid wrapping the expression
in some cases, while Ruff will wrap as long as it allows the expanded lines to fit within the line
length limit:

```python
# Input
some_long_variable_name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # a trailing comment

# Black
some_long_variable_name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" # a trailing comment

# Ruff
some_long_variable_name = (
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
) # a trailing comment
```

Doing so leads to fewer overlong lines while retaining the comment's intent. As pragma comments
(like `# noqa` and `# type: ignore`) are ignored when computing line width, this behavior only
applies to non-pragma comments.