Commit Graph

2453 Commits

Author SHA1 Message Date
Chris Pryer fa25dabf17
Add comments option to playground (#6911)
Co-authored-by: Micha Reiser <micha@reiser.io>
2023-08-28 07:26:23 +00:00
konsti e615870659
Unify line size settings between ruff and the formatter (#6873) 2023-08-28 06:44:56 +00:00
Micha Reiser a6aa16630d
Move `Configuration` to `ruff_workspace` crate (#6920) 2023-08-28 06:21:35 +00:00
Chris Pryer 039694aaed
Add `LineSuffix` reserved width (#6830)
Thanks for working on this.
2023-08-28 07:46:54 +02:00
Charlie Marsh 6bc1ba6d62
Use stdin for formatter when `--stdin-filename` is provided (#6926)
## Summary

Just making the formatter CLI more consistent with the linter -- e.g.,
we now use stdin on invocations like `cat foo.py | cargo run -p ruff_cli
-- format -- --stdin-filename=foo.py`, instead of _only_ relying on the
`-` file (and use the same helper as the linter to facilitate this).
2023-08-27 20:32:18 +00:00
Charlie Marsh cd47368ae4
Use consistent formatting for user-facing formatter errors (#6925)
## Summary

This PR changes the alpha formatter CLI to use the same format for
errors as the linter, e.g.:

<img width="868" alt="Screen Shot 2023-08-27 at 4 03 30 PM"
src="https://github.com/astral-sh/ruff/assets/1309177/9f3dea37-593b-4788-a0c0-e64bcf0d0560">
2023-08-27 20:22:06 +00:00
Charlie Marsh a871714705
Collect result in format CLI (#6924) 2023-08-27 20:02:18 +00:00
Charlie Marsh 292fdd978e
Remove unnecessary generic (#6923) 2023-08-27 15:55:23 -04:00
konsti c2413dcd2c
Add prototype of `ruff format` for projects (#6871)
**Summary** Add recursive formatting based on `ruff check` file
discovery for `ruff format`, as a prototype for the formatter alpha.
This allows e.g. `format ../projects/django/`. It's still lacking
support for any settings except line length.

Note just like the existing `ruff format` this will become part of the
production build, i.e. you'll be able to use it - hidden by default and
with a prominent warning - with `ruff format .` after the next release.

Error handling works in my manual tests (the colors do also work):

```
$  target/debug/ruff format scripts/
warning: `ruff format` is a work-in-progress, subject to change at any time, and intended for internal use only.
```
(the above changes `add_rule.py` where we have the wrong bin op
breaking)

```
$ target/debug/ruff format ../projects/django/
warning: `ruff format` is a work-in-progress, subject to change at any time, and intended for internal use only.
Failed to format /home/konsti/projects/django/tests/test_runner_apps/tagged/tests_syntax_error.py: source contains syntax errors: ParseError { error: UnrecognizedToken(Name { name: "syntax_error" }, None), offset: 131, source_path: "<filename>" }
```

```
$ target/debug/ruff format a
warning: `ruff format` is a work-in-progress, subject to change at any time, and intended for internal use only.
Failed to read /home/konsti/ruff/a/d.py: Permission denied (os error 13)
```

**Test Plan** Missing! I'm not sure if it's worth building tests at this
stage or how they should look like.
2023-08-27 19:12:18 +00:00
Charlie Marsh 059757a8c8
Implement `Ranged` on more structs (#6921)
Now that it's in `ruff_text_size`, we can use it in a few places that we
couldn't before.
2023-08-27 19:03:08 +00:00
Charlie Marsh fc89976c24
Move `Ranged` into `ruff_text_size` (#6919)
## Summary

The motivation here is that this enables us to implement `Ranged` in
crates that don't depend on `ruff_python_ast`.

Largely a mechanical refactor with a lot of regex, Clippy help, and
manual fixups.

## Test Plan

`cargo test`
2023-08-27 14:12:51 -04:00
Charlie Marsh d0b051e447
Fix ranges for global usages (#6917)
## Summary

The range of the usage from `Globals` should be the range of the
identifier, not the range of the full `global pandas` statement.

Closes https://github.com/astral-sh/ruff/issues/6914.
2023-08-27 15:27:07 +00:00
Micha Reiser 7c480236e0
Use dyn dispatch for `any_over_*` (#6912) 2023-08-27 15:54:01 +02:00
Micha Reiser 3f3494ad44
Implement ConfigProcessor on non-ref type (#6915) 2023-08-27 15:03:11 +02:00
Micha Reiser eae59cf088
Optional source map generation (#6894) 2023-08-26 18:00:43 +02:00
Charlie Marsh 15b73bdb8a
Introduce AST nodes for `PatternMatchClass` arguments (#6881)
## Summary

This PR introduces two new AST nodes to improve the representation of
`PatternMatchClass`. As a reminder, `PatternMatchClass` looks like this:

```python
case Point2D(0, 0, x=1, y=2):
  ...
```

Historically, this was represented as a vector of patterns (for the `0,
0` portion) and parallel vectors of keyword names (for `x` and `y`) and
values (for `1` and `2`). This introduces a bunch of challenges for the
formatter, but importantly, it's also really different from how we
represent similar nodes, like arguments (`func(0, 0, x=1, y=2)`) or
parameters (`def func(x, y)`).

So, firstly, we now use a single node (`PatternArguments`) for the
entire parenthesized region, making it much more consistent with our
other nodes. So, above, `PatternArguments` would be `(0, 0, x=1, y=2)`.

Secondly, we now have a `PatternKeyword` node for `x=1` and `y=2`. This
is much more similar to the how `Keyword` is represented within
`Arguments` for call expressions.

Closes https://github.com/astral-sh/ruff/issues/6866.

Closes https://github.com/astral-sh/ruff/issues/6880.
2023-08-26 14:45:44 +00:00
Micha Reiser ed1b4122d0
Use Codspeed for continous benchmarking (#6896) 2023-08-26 16:34:35 +02:00
Micha Reiser 9d77552e18
Add tab width option (#6848) 2023-08-26 12:29:58 +02:00
Charlie Marsh f91bacbb94
Avoid PEP 604 upgrades that lead to invalid syntax (#6888)
Closes https://github.com/astral-sh/ruff/issues/6843.
2023-08-25 19:47:15 -04:00
Charlie Marsh 2883ae4d46
Insert space to avoid syntax error in RSE fixes (#6886)
Closes https://github.com/astral-sh/ruff/issues/6810.
2023-08-25 18:26:30 -04:00
Charlie Marsh bd625b1928
Update PT007 docs to mention row-type (#6885)
Closes https://github.com/astral-sh/ruff/issues/6859.
2023-08-25 22:14:39 +00:00
Charlie Marsh e0a40783ca
Update PTH122 documentation to include `Path.stem` and `Path.parent` (#6884)
Closes https://github.com/astral-sh/ruff/issues/6846.
2023-08-25 22:11:56 +00:00
konsti 0e79074c31
Update to Rust 1.72 (#6874)
Update to [Rust
1.72](https://blog.rust-lang.org/2023/08/24/Rust-1.72.0.html), fixed the
failing lints.
2023-08-25 17:42:03 -04:00
Charlie Marsh edb9b0c62a
Use the formatter prelude in more files (#6882)
Removes a bunch of imports that are made redundant by the prelude.
2023-08-25 16:51:07 -04:00
Victor Hugo Gomes 91a780c771
Format `PatternMatchClass` (#6860) 2023-08-25 19:03:37 +00:00
Charlie Marsh 91880b8273
Bump version to 0.0.286 (#6876) 2023-08-25 14:59:26 -04:00
Zanie Blue 100904adb9
Avoid parsing other parts of a format specification if replacements are present (#6858)
Closes #6767
Replaces https://github.com/astral-sh/ruff/pull/6773 (this cherry-picks
some parts from there)
Alternative to the approach introduced in #6616 which added support for
placeholders in format specifications while retaining parsing of other
format specification parts.

The idea is that if there are placeholders in a format specification we
will not attempt to glean semantic meaning from the other parts of the
format specification we'll just extract all of the placeholders ignoring
other characters. The dynamic content of placeholders can drastically
change the meaning of the format specification in ways unknowable by
static analysis. This change prevents false analysis and will ensure
safety if we build other rules on top of this at the cost of missing
detection of some bad specifications.

Minor note: I've use "replacements" and "placeholders" interchangeably
but am trying to go with "placeholder" as I think it's a better term for
the static analysis concept here
2023-08-25 17:42:57 +00:00
Zanie Blue 0bac7bd114
Update RUF100 test to reflect applicability (#6877)
Broken on merge of #6822 due to new test cases conflicting with the
addition of an applicability to RUF100 in #6827
2023-08-25 16:57:59 +00:00
Zanie Blue f2eb7bcacf
Update ERA100 to apply to commented dictionary items with trailing comments (#6822)
Closes https://github.com/astral-sh/ruff/issues/6821

ERA100 was not raising on commented parts of dictionaries if it included
another comment (such as a noqa clause). In cases where this comment was
a noqa clause, RUF100 to be emitted since the noqa would have no effect.
Here, we update ERA100 to raise even when there are trailing comments.
This resolves the linked issue _and_ increases the scope of ERA100. We
could narrow the regular expression to only apply to noqa comments if we
do not want to expand ERA100 however I think this change is within the
spirit of the rule.
2023-08-25 11:02:31 -05:00
Micha Reiser 29a0c1003b
Use `BestFit` layout even for attributes with a short name (#6872) 2023-08-25 17:47:02 +02:00
Micha Reiser 15b7525464
Rename parser goal 'All' to 'all' (#6867) 2023-08-25 12:00:57 +00:00
konsti 0b6dab5e3f
Add jupyter notebook cell ids in 4.5+ if missing (#6853)
**Summary** See
https://github.com/astral-sh/ruff/issues/6834#issuecomment-1691202417

**Test Plan** Added a new notebook
2023-08-25 08:34:42 +00:00
David Szotten 1c66bb80b7
fix is_raw_string for multiple prefixes (#6865)
fix `is_raw_string` in the presence of other prefixes (like `rb"foo"`)

fixes #6864
2023-08-25 09:58:26 +02:00
Dhruv Manilawala d1f07008f7
Rename Notebook related symbols (#6862)
This PR renames the following symbols:

* `PySourceType::Jupyter` -> `PySourceType::Ipynb`
* `SourceKind::Jupyter` -> `SourceKind::IpyNotebook`
* `JupyterIndex` -> `NotebookIndex`
2023-08-25 11:40:54 +05:30
Micha Reiser 61b2ffa8e8
Add assert test cases (#6855) 2023-08-25 07:51:55 +02:00
Charlie Marsh 1044d66c1c
Add support for PatternMatchMapping formatting (#6836)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Adds support for `PatternMatchMapping` -- i.e., cases like:

```python
match foo:
    case {"a": 1, "b": 2, **rest}:
        pass
```

Unfortunately, this node has _three_ kinds of dangling comments:

```python
{  # "open parenthesis comment"
   key: pattern,
   **  # end-of-line "double star comment"
   # own-line "double star comment"
   rest  # end-of-line "after rest comment"
   # own-line "after rest comment"
}
```

Some of the complexity comes from the fact that in `**rest`, `rest` is
an _identifier_, not a node, so we have to handle comments _after_ it as
dangling on the enclosing node, rather than trailing on `**rest`. (We
could change the AST to use `PatternMatchAs` there, which would be more
permissive than the grammar but not totally crazy -- `PatternMatchAs` is
used elsewhere to mean "a single identifier".)

Closes https://github.com/astral-sh/ruff/issues/6644.

## Test Plan

`cargo test`
2023-08-25 04:33:34 +00:00
Charlie Marsh 813d7da7ec
Respect own-line leading comments before parenthesized nodes (#6820)
## Summary

This PR ensures that if an expression has an own-line leading comment
_before_ its open parentheses, we render it as such.

For example, given:

```python
[ # foo
    # bar
    ( # baz
        1
    )
]
```

On `main`, we format as:

```python
[  # foo
    (
        # bar
        # baz
        1
    )
]
```

As of this PR, we format as:

```python
[  # foo
    # bar
    (  # baz
        1
    )
]
```

## Test Plan

`cargo test`
2023-08-25 00:18:05 -04:00
Charlie Marsh 59e70896c0
Fix formatting of comments between function and arguments (#6826)
## Summary

We now format comments between a function and its arguments as dangling.
Like with other strange placements, I've biased towards preserving the
existing formatting, rather than attempting to reorder the comments.

Closes https://github.com/astral-sh/ruff/issues/6818.

## Test Plan

`cargo test`

Before:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.76050          |
| django       | 0.99820          |
| transformers | 0.99800          |
| twine        | 0.99876          |
| typeshed     | 0.99953          |
| warehouse    | 0.99615          |
| zulip        | 0.99729          |

After:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.76050          |
| django       | 0.99820          |
| transformers | 0.99800          |
| twine        | 0.99876          |
| typeshed     | 0.99953          |
| warehouse    | 0.99615          |
| zulip        | 0.99729          |
2023-08-25 04:06:56 +00:00
Charlie Marsh f754ad5898
Handle bracketed comments on sequence patterns (#6801)
## Summary

This PR ensures that we handle bracketed comments on sequences, like `#
comment` here:

```python
match x:
    case [ # comment
        1, 2
    ]:
        pass
```

The handling is very similar to other, similar nodes, except that we do
need some special logic to determine whether the sequence is
parenthesized, similar to our logic for tuples.

## Test Plan

`cargo test`
2023-08-25 04:03:27 +00:00
Charlie Marsh 474e8fbcd4
Format all attribute dot comments manually (#6825)
## Summary

This PR modifies our formatting of comments around the `.` in an
attribute. Specifically, the goal here is to avoid _reordering_
comments, and the net effect is that we generally leave comments
where-they-are when dealing with comments between around the dot (which
you can also think of as comments between attributes).

All comments around the dot are now treated as dangling and formatted
manually, with the exception of end-of-line or parenthesized comments on
the value, like those marked as trailing here, which remain trailing:

```python
(
    (
        a # trailing end-of-line
        # trailing own-line
    ) # dangling before dot end-of-line
    .b # trailing end-of-line
)
```

Closes https://github.com/astral-sh/ruff/issues/6823.

## Test Plan

`cargo test`

Before:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.76050          |
| django       | 0.99820          |
| transformers | 0.99800          |
| twine        | 0.99876          |
| typeshed     | 0.99953          |
| warehouse    | 0.99615          |
| zulip        | 0.99729          |

After:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.76050          |
| django       | 0.99820   |
| transformers | 0.99800          |
| twine        | 0.99876          |
| typeshed     | 0.99953          |
| warehouse    | 0.99615          |
| zulip        | 0.99729          |
2023-08-25 03:50:56 +00:00
Charlie Marsh 6f23469e00
Handle pattern parentheses in `FormatPattern` (#6800)
## Summary

This PR fixes the duplicate-parenthesis problem that's visible in the
tests from https://github.com/astral-sh/ruff/pull/6799. The issue is
that we might have parentheses around the entire match-case pattern,
like in `(1)` here:

```python
match foo:
    case (1):
        y = 0
```

In this case, the inner expression (`1`) will _think_ it's
parenthesized, but we'll _also_ detect the parentheses at the case level
-- so they get rendered by the case, then again by the expression.
Instead, if we detect parentheses at the case level, we can force-off
the parentheses for the pattern using a design similar to the way we
handle parentheses on expressions.

Closes https://github.com/astral-sh/ruff/issues/6753.

## Test Plan

`cargo test`
2023-08-25 03:45:49 +00:00
Charlie Marsh 281ce56dc1
Make isort's `detect-same-package` behavior configurable (#6833)
## Summary

Our first-party import detection uses a heuristic that doesn't exist in
isort: if an import appears to be from within the same package as the
containing file, we mark it as first-party. For example, if you have a
directory `./foo/__init__.py`, and you import `from foo import bar` in
`./foo/baz.py`, we'll mark that as first-party. (See:
https://github.com/astral-sh/ruff/pull/1266.)

This is often unnecessary, and arguably should be removed (though it
does have some important use-cases that are otherwise unserved -- I
believe Dagster uses it to ensure that all packages mark imports from
within the same package as first-party, but not imports _across_
different first-party packages)... but it does exist, and it does help
in cases in which the `src` field is not properly configured.

This PR adds an option to turn off this behavior:

```toml
[tool.ruff.isort]
detect-same-package = false
```

This is being introduced to help codebases migrating over from isort
that may want more consistent behavior with their current sorting.

## Test Plan

`cargo test`
2023-08-24 14:09:26 -04:00
Zanie Blue 3bd199cdf6
Update `function-call-in-argument-default` (`B008`) to ignore arguments with immutable annotations (#6784)
Extends #6781 
Part of https://github.com/astral-sh/ruff/issues/3762
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
Allows calls in argument defaults if the argument is annotated as an
immutable type to avoid false positives.

## Test Plan

<!-- How was it tested? -->

Snapshots
2023-08-24 11:12:59 -05:00
Harutaka Kawamura 948cd29b23
Skip serializing cell ID if it's None (#6851)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Fix #6834 

## Test Plan

<!-- How was it tested? -->

Need tests?

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2023-08-24 13:20:25 +00:00
Micha Reiser 1e7d1968b1
Printer: Slice based queue and stack (#6819) 2023-08-24 14:49:27 +02:00
Micha Reiser 8b46b71038
Fix parenthesizing of implicit strings (#6852) 2023-08-24 12:31:02 +00:00
Micha Reiser 1cd7790a8a
Use BestFits for non-fluent attribute chains (#6817) 2023-08-24 14:09:25 +02:00
konsti d376cb4c2a
Improve formatter contributor docs (#6776)
The docs were out of date, and the new version incorporates some
feedback.

I tried to keep the language concise and the information ordered by how
early you need it, so people can get the relevant information quickly
before jumping into the code.

I did some minor format_dev changes for consistency in the docs.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2023-08-24 10:45:08 +00:00
Micha Reiser 04a9a8dd03
Maybe parenthesize long constants and names (#6816) 2023-08-24 09:47:57 +00:00
Micha Reiser e4c13846e3
Fix Printer group modes (#6815) 2023-08-24 08:42:59 +02:00
Harutaka Kawamura 205d234856
Format `PatternMatchStar` (#6653) 2023-08-24 01:58:05 +00:00
Charlie Marsh 4889b84338
Document `logger-objects` setting in `flake8-logging-format` rules (#6832)
Closes https://github.com/astral-sh/ruff/issues/6764.
2023-08-24 00:18:51 +00:00
Charlie Marsh 847432cacf
Avoid attempting to fix PT018 in multi-statement lines (#6829)
## Summary

These fixes will _always_ fail, so we should avoid trying to construct
them in the first place.

Closes https://github.com/astral-sh/ruff/issues/6812.
2023-08-23 19:09:34 -04:00
Charlie Marsh 9b6e008cf1
Remove remaining usages of `try_set_fix` (#6828)
There are just a few remaining usages of this deprecated method.
2023-08-23 22:36:09 +00:00
Charlie Marsh 39c6665ff9
Remove remaining usage of `set_fix_from_edit` (#6827)
This method is deprecated; we have one last usage, so removing it.
2023-08-23 18:25:39 -04:00
Zanie Blue 0688883404
Fix `uncessary-coding-comment` fix when there's leading content (#6775)
Closes https://github.com/astral-sh/ruff/issues/6756

Including whitespace, code, and continuations.
2023-08-23 12:00:06 -05:00
Zanie Blue 3bb638875f
Fix `native-literals` handling of int literal with attribute access (#6792)
Closes https://github.com/astral-sh/ruff/issues/6788 by special casing
integer literals with attribute access — either retaining parenthesis
for literals with values (e.g. `int(7).denominator` to
`(7).denominator)` or leaving calls without values (e.g.
`int().denominator`) unchanged.
2023-08-23 11:22:05 -05:00
Charlie Marsh 26e63ab137
Remove lexing from flake8-pytest-style (#6795)
## Summary

Another drive-by change to remove unnecessary custom lexing. We just
need to know the parenthesized range, so we can use...
`parenthesized_range`. I've also updated `parenthesized_range` to
support nested parentheses.

## Test Plan

`cargo test`
2023-08-23 15:54:11 +00:00
Zanie Blue 417a1d0717
Update `mutable-argument-default` (`B006`) to use `extend-immutable-calls` when determining if annotations are immutable (#6781)
Part of https://github.com/astral-sh/ruff/issues/3762
2023-08-23 15:44:35 +00:00
Micha Reiser 34b2ae73b4
Extend `BestFitting` with `mode` (#6814) 2023-08-23 17:23:45 +02:00
Charlie Marsh 71c25e4f9d
Implement `FormatPatternMatchValue` (#6799)
## Summary

This is effectively #6608, but with additional tests.

We aren't properly handling parenthesized patterns, but that needs to be
dealt with separately as it's somewhat involved.

Closes #6555
2023-08-23 14:01:14 +00:00
Micha Reiser 4bdd99f882
Fix: Re-add missing node start positions (#6780) 2023-08-23 09:59:36 +02:00
Charlie Marsh 1e6d1182bf
Improve comment handling around `PatternMatchAs` (#6797)
## Summary

Follows up on
https://github.com/astral-sh/ruff/pull/6652#discussion_r1300871033 with
some modifications to the `PatternMatchAs` comment handling.
Specifically, any comments between the `as` and the end are now
formatted as dangling, and we now insert some newlines in the
appropriate places.

## Test Plan

`cargo test`
2023-08-23 04:48:20 +00:00
Charlie Marsh d08f697a04
Remove lexing for colon-matching use cases (#6803)
It's much simpler to just search ahead for the first colon.
2023-08-23 04:44:51 +00:00
Charlie Marsh 4bc5eddf91
Handle open-parenthesis comments on match case (#6798)
## Summary

Ensures that we retain the open-parenthesis comment in cases like:
```python
match pattern_comments:
    case (  # leading
        only_leading
    ):
        ...
```

Previously, this was treated as a leading comment on `only_leading`.

## Test Plan

`cargo test`
2023-08-23 00:40:18 -04:00
Charlie Marsh 5f5de52aba
Confine repeated-equality-comparison-target to names and attributes (#6802)
Empirically, Pylint does this, so seems reasonable to follow.
2023-08-23 03:56:37 +00:00
Tom Kuson 1cb1bd731c
Extend `repeated-equality-comparison-target` to check for mixed orderings and Yoda conditions. (#6691) 2023-08-23 03:45:30 +00:00
Dhruv Manilawala db2e548f4f
Simplify `ANN204` autofix to use `Parameters` range (#6793)
## Summary

This PR fixes the bug where the decorator parentheses weren't being considered
when computing the autofix for `ANN204`. The existing logic would only look
for balanced parentheses and not multiple pairs of parentheses.

The solution is to remove the logic to generate the autofix and use the
`Parameters` end range directly which includes the parentheses as well.

## Test Plan

Add test case for `ANN204` with decorator being called

fixes: #6790
2023-08-23 09:05:46 +05:30
Harutaka Kawamura 94f5f18ddb
Format `PatternMatchSequence` (#6676) 2023-08-23 00:44:33 +00:00
Luc Khai Hai c34a342ab4
Format `PatternMatchAs` (#6652)
## Summary

Add formatting for `PatternMatchAs`.

This closes #6641.

## Test Plan

Add tests for comments.
2023-08-22 23:58:15 +00:00
Charlie Marsh 42ff833d00
Remove comment lexing from isort (#6794)
## Summary

No need to lex to find comments -- we already know their locations via
`Indexer`.
2023-08-22 21:26:38 +00:00
Konrad Listwan-Ciesielski e1f4438498
Add docs for `DTZ007` (#6757) 2023-08-22 21:12:50 +00:00
Charlie Marsh 1acdec3e29
Add a note on `__future__` imports and `keep-runtime-typing` to pyupgrade rules (#6746)
Closes https://github.com/astral-sh/ruff/issues/6740.
2023-08-22 17:04:00 -04:00
Charlie Marsh ca2bb20063
Fallback to end-of-file if ends in trailing continuation (#6789)
## Summary

Given:

```python
def end_of_file():
    if False:
        return 1
    x = 2 \

```

Then when searching for the end of the `x = 2` statement, we'd reach a
panic as we'd hit the last line (`\\`) and abort, since the universal
iterator doesn't return trailing newlines. Instead, we should just use
the end of the file as the fallback.

Closes https://github.com/astral-sh/ruff/issues/6787.

## Test Plan

`cargo test`
2023-08-22 15:12:26 -04:00
Dhruv Manilawala 2e00983762
Avoid `C417` for `lambda` with default and variadic parameters (#6752)
## Summary

Avoid `C417` for `lambda` with default and variadic parameters.

## Test Plan

`cargo test` and checking if it generates any autofix errors as test
cases
for `lambda` with default parameters already exists.

fixes: #6715
2023-08-23 00:38:08 +05:30
Dhruv Manilawala fb7caf43c8
Update lexer tests to use snapshots (#6658)
## Summary

This PR updates the lexer tests to use the snapshot testing framework.
It also
makes the following changes:
* Remove the use of macros in the lexer tests
* Use `test_case` for EOL tests

## Test Plan

```
cargo test --package ruff_python_parser --lib --all-features -- lexer::tests --no-capture
```
2023-08-22 18:23:19 +00:00
Charlie Marsh 214eb707a6
Parenthesize expressions prior to LibCST parsing (#6742)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR adds a utility for transforming expressions via LibCST that
automatically wraps the expression in parentheses, applies a
user-provided transformation, then strips the parentheses from the
generated code. LibCST can't parse arbitrary expression ranges, since
some expressions may require parenthesization in order to be parsed
properly. For example:

```python
option = (
    '{name}={value}'
    .format(nam=name, value=value)
)
```

In this case, the expression range is:

```python
'{name}={value}'
    .format(nam=name, value=value)
```

Which isn't valid on its own. So, instead, we add "fake" parentheses
around the expression.

We were already doing this in a few places, so this is mostly
formalizing and DRYing up that pattern.

Closes https://github.com/astral-sh/ruff/issues/6720.
2023-08-22 17:45:05 +00:00
Zanie Blue 5c1f7fd5dd
Add `networkx` to conventional aliases (#6778)
Closes https://github.com/astral-sh/ruff/issues/6763
2023-08-22 11:49:04 -05:00
Charlie Marsh cc278c24e2
Allow up to two empty lines after top-level imports (#6777)
## Summary

For imports, we enforce that there's _at least_ one empty line after an
import (assuming the next statement is _not_ an import), but allow up to
two at the module level.

Closes https://github.com/astral-sh/ruff/issues/6760.

## Test Plan

`cargo test`
2023-08-22 12:27:40 -04:00
Charlie Marsh 558b56f8a8
Avoid fixing D200 for docstrings that end in escapes (#6779)
Appease the fuzzers! Closes
https://github.com/astral-sh/ruff/issues/6755.
2023-08-22 16:25:37 +00:00
Charlie Marsh 749da6589a
Fix isolation groups for unused imports (#6774)
## Summary

The isolation group for unused imports was relying on
`checker.semantic().current_statement()`, which isn't valid for that
rule, since it runs over the _scope_, not the statement. Instead, we
need to lookup the isolation group based on the `NodeId` of the
statement.

Our tests didn't catch this, because we mostly have cases that look like
this:

```python
if TYPE_CHECKING:
    import shelve
    import importlib
```

In this case, the two fixes to remove the two unused imports are
considered overlapping (since we delete the _full_ line, and the two
_full_ lines touch, and we consider exactly-adjacent fixes to be
overlapping), and so they don't run in a single pass due to the
non-overlapping-fixes requirement. That is: the isolation groups aren't
required for this case. They are, however, required for cases like:

```python
if TYPE_CHECKING:
    import shelve

    import importlib
```

...where the fixes don't overlap.

Closes https://github.com/astral-sh/ruff/issues/6758.

## Test Plan

`cargo test`
2023-08-22 11:55:27 -04:00
Charlie Marsh d2eace3377
Prefer `range_*` edit methods (#6751) 2023-08-22 15:46:04 +00:00
Micha Reiser ccac9681e1
Preserve yield parentheses (#6766) 2023-08-22 10:27:20 +00:00
Micha Reiser b52cc84df6
Omit tuple parentheses in for statements except when absolutely necessary (#6765) 2023-08-22 12:18:59 +02:00
Micha Reiser fec6fc2fab
Preserve empty lines between try clause headers (#6759) 2023-08-22 11:50:28 +02:00
konsti ba4c27598a
Document IO Error (#6712)
`IOError` is special, it is not actually a lint but an error before
linting. I'm not entirely sure how to document it since it does not
match the general lint rule pattern (`Checks that the file can be read
in its entirety.` is imho worse).

I added the in my experience two most common reasons for io errors on
unix systems and linked two tutorials on how to fix them.

See https://github.com/astral-sh/ruff/issues/2646

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-08-22 11:46:18 +02:00
Victor Hugo Gomes 0f9ccfcad9
Format `PatternMatchSingleton` (#6741) 2023-08-22 08:23:47 +02:00
Charlie Marsh fa32cd9b6f
Truncate some messages in diagnostics (#6748)
## Summary

I noticed this in the ecosystem CI check from
https://github.com/astral-sh/ruff/pull/6742. If we include source code
directly in a diagnostic, we need to be careful to avoid rendering
multi-line diagnostics or even excessively long diagnostics.

## Test Plan

`cargo test`
2023-08-21 23:46:24 -04:00
Victor Hugo Gomes 0aad0c41f6
[`pylint`] Implement `no-self-use` (`R6301`) (#6574) 2023-08-22 03:44:38 +00:00
Charlie Marsh 424b8d4ad2
Use a single node hierarchy to track statements and expressions (#6709)
## Summary

This PR is a follow-up to the suggestion in
https://github.com/astral-sh/ruff/pull/6345#discussion_r1285470953 to
use a single stack to store all statements and expressions, rather than
using separate vectors for each, which gives us something closer to a
full-fidelity chain. (We can then generalize this concept to include all
other AST nodes too.)

This is in part made possible by the removal of the hash map from
`&Stmt` to `StatementId` (#6694), which makes it much cheaper to store
these using a single interface (since doing so no longer introduces the
requirement that we hash all expressions).

I'll follow-up with some profiling, but a few notes on how the data
requirements have changed:

- We now store a `BranchId` for every expression, not just every
statement, so that's an extra `u32`.
- We now store a single `NodeId` on every snapshot, rather than separate
`StatementId` and `ExpressionId` IDs, so that's one fewer `u32` for each
snapshot.
- We're probably doing a few more lookups in general, since any calls to
`current_statement()` etc. now have to iterate up the node hierarchy
until they identify the first statement.

## Test Plan

`cargo test`
2023-08-21 21:32:57 -04:00
Charlie Marsh abc5065fc7
Avoid E231 if comma is at end-of-line (#6747)
## Summary

I don't know how this could come up in valid Python, but anyway...

Closes https://github.com/astral-sh/ruff/issues/6738.
2023-08-21 20:47:20 -04:00
Victor Hugo Gomes 37f4920e1e
Don't trigger `eq-without-hash` when `__hash__` is explicitly set to `None` (#6739) 2023-08-21 23:51:21 +00:00
Charlie Marsh c0df99b965
Avoid attempting to fix unconventional submodule imports (#6745)
## Summary

Avoid attempting to rewrite `import matplotlib.pyplot` as `import
matplotlib.pyplot as plt`. We can't support these right now, since we
don't track references at the attribute level (like
`matplotlib.pyplot`).

Closes https://github.com/astral-sh/ruff/issues/6719.
2023-08-21 23:45:32 +00:00
Charlie Marsh 7650c6ee45
Support C419 autofixes for set comprehensions (#6744)
Closes https://github.com/astral-sh/ruff/issues/6713.
2023-08-21 23:41:13 +00:00
Charlie Marsh 7b14d17e39
Ignore star imports when importing symbols in fixes (#6743)
## Summary

Given:

```python
from sys import *

exit(0)
```

We can't add `exit` to `from sys import *`, so we should just ignore it.
Ideally, we'd just resolve `exit` in the first place (since it's
imported from `from sys import *`), but as long as we don't support
wildcard imports, this is more consistent.

Closes https://github.com/astral-sh/ruff/issues/6718.

## Test Plan

`cargo test`
2023-08-21 23:31:30 +00:00
Charlie Marsh 4678f7dafe
Remove parenthesis lexing in RSE102 (#6732)
## Summary

Now that we have an `Arguments` node, we can just use the range of the
arguments directly to find the parentheses in `raise Error()`.
2023-08-21 20:59:06 +00:00
konsti b182368008
Simplify suite formatting (#6722)
Avoid the nesting in a macro by using the new `WithNodeLevel` to
`PyFormatter` deref. No changes otherwise.

I wanted to follow this up with quickly fixing the typeshed empty line
rules but they turned out a lot more complex than i had anticipated.
2023-08-21 21:01:51 +02:00
Charlie Marsh e032fbd2e7
Remove `remove_super_arguments` (#6735)
Now that we have an `Arguments` node, we can use it directly to get the
range.
2023-08-21 13:04:07 -04:00
Micha Reiser 17a26e6ff3
Fix `fmt:skip` for function with return type (#6733) 2023-08-21 17:45:23 +02:00
Charlie Marsh d5a51b4e45
Allow `ctypes.WinError()` in flake8-raise (#6731)
Closes https://github.com/astral-sh/ruff/issues/6730.
2023-08-21 14:57:34 +00:00
Charlie Marsh 83f68891e0
Allow next in FBT exclusions (#6729)
Closes https://github.com/astral-sh/ruff/issues/6711.
2023-08-21 14:56:38 +00:00
konsti aafde6db28
Remove some indexing (#6728)
**Summary** A common pattern in the code used to be
```rust
if statements.len() != 1 {
    return;
}
use_single_entry(statements[0])?;
```
which can be better expressed as
```rust
let [statement] = statements else {
    return;
};
use_single_entry(statements)?;
```

Direct indexing can cause panics if you don't manually take care of
checking the length, while matching (such as if-let or let-else) can
never panic.

This isn't a complete refactor, i've just removed some of the obvious
cases. I've specifically looked for `.len() != 1` and fixed those.

**Test Plan** No functional changes
2023-08-21 16:56:15 +02:00
Charlie Marsh 2405536d03
Remove unnecessary LibCST usage in key-in-dict (#6727)
## Summary

We're using LibCST to ensure that we return the full parenthesized range
of an expression, for display purposes. We can just use
`parenthesized_range` which is more efficient and removes one LibCST
dependency.

## Test Plan

`cargo test`
2023-08-21 10:32:09 -04:00
Micha Reiser f017555d53
Parenthesize NamedExpr if target breaks (#6714) 2023-08-21 16:29:26 +02:00
Charlie Marsh be96e0041a
Accept empty inner calls in C414 (#6725)
Closes https://github.com/astral-sh/ruff/issues/6716.
2023-08-21 14:05:09 +00:00
Harutaka Kawamura 3c2dd5e42e
Remove confusing comment on `get_parametrize_name_range` (#6724) 2023-08-21 08:52:48 -04:00
Micha Reiser 8b347cdaa9
Simplify IfRequired needs parentheses condition (#6678) 2023-08-21 07:11:31 +00:00
Tom Kuson 2a8d24dd4b
Format function and class definitions into a single line if its body is an ellipsis (#6592) 2023-08-21 09:02:23 +02:00
Charlie Marsh bb5fbb1b5c
Use simple lexer for argument removal (#6710) 2023-08-21 04:16:29 +00:00
Harutaka Kawamura 086e11087f
[`flake8-pytest-style`] Autofix `PT014` (#6698) 2023-08-21 03:45:12 +00:00
Charlie Marsh 1b7e4a12a9
Refactor `remove_unused_variable` to take `&Binding` (#6707) 2023-08-20 15:50:57 +00:00
Charlie Marsh da1697121e
Add `BranchId` to the model snapshot (#6706)
This _probably_ never matters given the set of rules we support and in
fact I'm having trouble thinking of a test-case for it, but it's
definitely incorrect _not_ to pass on the `BranchId` here.
2023-08-20 15:35:49 +00:00
Harutaka Kawamura 419615f29b
Add docs for `E275`, `E231`, `E251`, and `E252` (#6700) 2023-08-20 14:51:50 +00:00
Charlie Marsh a742a562fd
Ignore multi-comparisons in `repeated-equality-comparison-target` (#6705)
Given `foo == "a" == "b" or foo == "c"`, we were suggesting `foo in
{"a", "b", "c"}`.
2023-08-20 14:41:10 +00:00
Harutaka Kawamura 129b19050a
Refactor `flake8_pytest_style/rules/parametrize.rs` (#6703) 2023-08-20 14:30:26 +00:00
Konrad Listwan-Ciesielski 0dc23da1d0
Add docs for `DTZ011` and `DTZ012` (#6688) 2023-08-20 10:21:10 -04:00
Harutaka Kawamura c62e544cba
Add doc for `E999` (#6699) 2023-08-20 14:14:22 +00:00
Charlie Marsh 7e9023b6f8
Use `typing_extensions.TypeAlias` for PYI026 fixes on pre-3.10 (#6696)
Closes https://github.com/astral-sh/ruff/issues/6695.
2023-08-19 22:16:44 +00:00
Harutaka Kawamura a489b96a65
[`flake8-pie`] Implement `unnecessary-range-start` (`PIE808`) (#6690) 2023-08-19 21:59:11 +00:00
Charlie Marsh 17af12e57c
Add branch detection to the semantic model (#6694)
## Summary

We have a few rules that rely on detecting whether two statements are in
different branches -- for example, different arms of an `if`-`else`.
Historically, the way this was implemented is that, given two statement
IDs, we'd find the common parent (by traversing upwards via our
`Statements` abstraction); then identify branches "manually" by matching
the parents against `try`, `if`, and `match`, and returning iterators
over the arms; then check if there's an arm for which one of the
statements is a child, and the other is not.

This has a few drawbacks:

1. First, the code is generally a bit hard to follow (Konsti mentioned
this too when working on the `ElifElseClause` refactor).

2. Second, this is the only place in the codebase where we need to go
from `&Stmt` to `StatementID` -- _everywhere_ else, we only need to go
in the _other_ direction. Supporting these lookups means we need to
maintain a mapping from `&Stmt` to `StatementID` that includes every
`&Stmt` in the program. (We _also_ end up maintaining a `depth` level
for every statement.) I'd like to get rid of these requirements to
improve efficiency, reduce complexity, and enable us to treat AST modes
more generically in the future. (When I looked at adding the `&Expr` to
our existing statement-tracking infrastructure, maintaining a hash map
with all the statements noticeably hurt performance.)

The solution implemented here instead makes branches a first-class
concept in the semantic model. Like with `Statements`, we now have a
`Branches` abstraction, where each branch points to its optional parent.
When we store statements, we store the `BranchID` alongside each
statement. When we need to detect whether two statements are in the same
branch, we just realize each statement's branch path and compare the
two. (Assuming that the two statements are in the same scope, then
they're on the same branch IFF one branch path is a subset of the other,
starting from the top.) We then add some calls to the visitor to push
and pop branches in the appropriate places, for `if`, `try`, and `match`
statements.

Note that a branch is not 1:1 with a statement; instead, each branch is
closer to a suite, but not _every_ suite is a branch. For example, each
arm in an `if`-`elif`-`else` is a branch, but the `else` in a `for` loop
is not considered a branch.

In addition to being much simpler, this should also be more efficient,
since we've shed the entire `&Stmt` hash map, plus the `depth` that we
track on `StatementWithParent` in favor of a single `Option<BranchID>`
on `StatementWithParent` plus a single vector for all branches. The
lookups should be faster too, since instead of doing a bunch of jumps
around with the hash map + repeated recursive calls to find the common
parents, we instead just do a few simple lookups in the `Branches`
vector to realize and compare the branch paths.

## Test Plan

`cargo test` -- we have a lot of coverage for this, which we inherited
from PyFlakes
2023-08-19 21:28:17 +00:00
Chris Pryer 648333b8b2
`ruff_formatter` crate doc comment fixes (#6677) 2023-08-19 17:42:02 +01:00
Charlie Marsh 3849fa0cf1
Rewrite `yield-in-for-loop` to avoid recursing over body (#6692)
## Summary

This is much simpler and avoids (1) multiple passes over the entire
function body, (2) requiring the rule to do its own binding tracking (we
can just use the semantic model), and (3) a usage of `StatementKey`.

In general, where we can, we should try to remove these kinds of custom
visitors that track name references, and instead rely on the semantic
model.

## Test Plan

`cargo test`
2023-08-19 11:25:29 -04:00
Victor Hugo Gomes 59e533047a
Fix typo in `ruff_python_formatter` documentation (#6687)
## Summary

In the documentation was written `Javascript` but we are working with
`Python` here :)

## Test Plan

n/a
2023-08-18 19:16:09 -04:00
Charlie Marsh 053b1145f0
Avoid panic in unused arguments rule for parameter-free lambda (#6679)
## Summary

This was just a mistake in pattern-matching with no test coverage.

## Test Plan

`cargo test`
2023-08-18 18:29:31 +00:00
Charlie Marsh 6a5acde226
Make `Parameters` an optional field on `ExprLambda` (#6669)
## Summary

If a lambda doesn't contain any parameters, or any parameter _tokens_
(like `*`), we can use `None` for the parameters. This feels like a
better representation to me, since, e.g., what should the `TextRange` be
for a non-existent set of parameters? It also allows us to remove
several sites where we check if the `Parameters` is empty by seeing if
it contains any arguments, so semantically, we're already trying to
detect and model around this elsewhere.

Changing this also fixes a number of issues with dangling comments in
parameter-less lambdas, since those comments are now automatically
marked as dangling on the lambda. (As-is, we were also doing something
not-great whereby the lambda was responsible for formatting dangling
comments on the parameters, which has been removed.)

Closes https://github.com/astral-sh/ruff/issues/6646.

Closes https://github.com/astral-sh/ruff/issues/6647.

## Test Plan

`cargo test`
2023-08-18 15:34:54 +00:00
Micha Reiser ea72d5feba
Refactor `SourceKind` to store file content (#6640) 2023-08-18 13:45:38 +00:00
Charlie Marsh 2aeb27334d
Avoid cloning source code multiple times (#6629)
## Summary

In working on https://github.com/astral-sh/ruff/pull/6628, I noticed
that we clone the source code contents, potentially multiple times,
prior to linting. The issue is that `SourceKind::Python` takes a
`String`, so we first have to provide it with a `String`. In the stdin
case, that means cloning. However, on top of this, we then have to clone
`source_kind.contents()` because `SourceKind` gets mutated. So for
stdin, we end up cloning twice. For non-stdin, we end up cloning once,
but unnecessarily (since the _contents_ don't get mutated, only the
kind).

This PR removes the `String` from `source_kind`, instead requiring that
we parse it out elsewhere. It reduces the number of clones down to 1 for
Jupyter Notebooks, and zero otherwise.
2023-08-18 09:32:18 -04:00
Micha Reiser 0cea4975fc
Rename Comments methods (#6649) 2023-08-18 06:37:01 +00:00
Charlie Marsh 3ceb6fbeb0
Remove some unnecessary ampersands in the formatter (#6667) 2023-08-18 04:18:26 +00:00
Charlie Marsh 8e18f8018f
Remove some trailing commas in write calls (#6666) 2023-08-18 00:14:44 -04:00
Charlie Marsh 8228429a70
Convert comment to rustdoc in placement.rs (#6665) 2023-08-18 04:11:38 +00:00
Charlie Marsh 1811312722
Improve `with` statement comment handling and expression breaking (#6621)
## Summary

The motivating code here was:

```python
with test as (
    # test
foo):
    pass
```

Which we were formatting as:

```python
with test as
# test
(foo):
    pass
```

`with` statements are oddly difficult. This PR makes a bunch of subtle
modifications and adds a more extensive test suite. For example, we now
only preserve parentheses if there's more than one `WithItem` _or_ a
trailing comma; before, we always preserved.

Our formatting is_not_ the same as Black, but here's a diff of our
formatted code vs. Black's for the `with.py` test suite. The primary
difference is that we tend to break parentheses when they contain
comments rather than move them to the end of the life (this is a
consistent difference that we make across the codebase):

```diff
diff --git a/crates/ruff_python_formatter/foo.py b/crates/ruff_python_formatter/foo.py
index 85e761080..31625c876 100644
--- a/crates/ruff_python_formatter/foo.py
+++ b/crates/ruff_python_formatter/foo.py
@@ -1,6 +1,4 @@
-with (
-    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-), aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
+with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
     ...
     # trailing
 
@@ -16,28 +14,33 @@ with (
     # trailing
 
 
-with a, b:  # a  # comma  # c  # colon
+with (
+    a,  # a  # comma
+    b,  # c
+):  # colon
     ...
 
 
 with (
-    a as  # a  # as
-    # own line
-    b,  # b  # comma
+    a as (  # a  # as
+        # own line
+        b
+    ),  # b  # comma
     c,  # c
 ):  # colon
     ...  # body
     # body trailing own
 
-with (
-    a as  # a  # as
+with a as (  # a  # as
     # own line
-    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb  # b
-):
+    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+):  # b
     pass
 
 
-with (a,):  # magic trailing comma
+with (
+    a,
+):  # magic trailing comma
     ...
 
 
@@ -47,6 +50,7 @@ with a:  # should remove brackets
 with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c:
     ...
 
+
 with (
     # leading comment
     a
@@ -74,8 +78,7 @@ with (
 with (
     a  # trailing same line comment
     # trailing own line comment
-    as b
-):
+) as b:
     ...
 
 with (
@@ -87,7 +90,9 @@ with (
 with (
     a
     # trailing own line comment
-) as b:  # trailing as same line comment  # trailing b same line comment
+) as (  # trailing as same line comment
+    b
+):  # trailing b same line comment
     ...
 
 with (
@@ -124,18 +129,24 @@ with (  # comment
     ...
 
 with (  # outer comment
-    CtxManager1() as example1,  # inner comment
+    (  # inner comment
+        CtxManager1()
+    ) as example1,
     CtxManager2() as example2,
     CtxManager3() as example3,
 ):
     ...
 
-with CtxManager() as example:  # outer comment
+with (  # outer comment
+    CtxManager()
+) as example:
     ...
 
 with (  # outer comment
     CtxManager()
-) as example, CtxManager2() as example2:  # inner comment
+) as example, (  # inner comment
+    CtxManager2()
+) as example2:
     ...
 
 with (  # outer comment
@@ -145,7 +156,9 @@ with (  # outer comment
     ...
 
 with (  # outer comment
-    (CtxManager1()),  # inner comment
+    (  # inner comment
+        CtxManager1()
+    ),
     CtxManager2(),
 ) as example:
     ...
@@ -179,7 +192,9 @@ with (
 ):
     pass
 
-with a as (b):  # foo
+with a as (  # foo
+    b
+):
     pass
 
 with f(
@@ -209,17 +224,13 @@ with f(
 ) as b, c as d:
     pass
 
-with (
-    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-) as b:
+with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b:
     pass
 
 with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b:
     pass
 
-with (
-    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-) as b, c as d:
+with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b, c as d:
     pass
 
 with (
@@ -230,6 +241,8 @@ with (
     pass
 
 with (
-    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-) as b, c as d:
+    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+    + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as b,
+    c as d,
+):
     pass
```

Closes https://github.com/astral-sh/ruff/issues/6600.
## Test Plan

Before:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.75473          |
| django       | 0.99804          |
| transformers | 0.99618          |
| twine        | 0.99876          |
| typeshed     | 0.74292          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |

After:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.75473          |
| django       | 0.99804          |
| transformers | 0.99618          |
| twine        | 0.99876          |
| typeshed     | 0.74292          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |

`cargo test`
2023-08-18 03:30:38 +00:00
Charlie Marsh 26bba11be6
Manually format comments around `:=` in named expressions (#6634)
## Summary

Attaches comments around the `:=` operator in a named expression as
dangling, and formats them manually in the `named_expr.rs` formatter.

Closes https://github.com/astral-sh/ruff/issues/5695.

## Test Plan

`cargo test`
2023-08-18 03:10:45 +00:00
Shantanu a128fe5148
Apply RUF017 when start is passed via position (#6664)
As discussed in
https://github.com/astral-sh/ruff/pull/6489#discussion_r1297858919.
Linking https://github.com/astral-sh/ruff/issues/5073
2023-08-17 20:10:07 -04:00
Zanie Blue 5892c691ea
Bump version to 0.0.285 (#6660)
Requires
- https://github.com/astral-sh/ruff/pull/6655
- https://github.com/astral-sh/ruff/pull/6657
2023-08-17 15:46:28 -05:00
Zanie Blue 82e0a97b34
Clarify behavior of `PLW3201` (#6657)
Otherwise it is unclear that violations will be raised for methods like
`_foo_`
2023-08-17 14:41:55 -05:00
Charlie Marsh 1050142a58
Expand expressions to include parentheses in E712 (#6575)
## Summary

This PR exposes our `is_expression_parenthesized` logic such that we can
use it to expand expressions when autofixing to include their
parenthesized ranges.

This solution has a few drawbacks: (1) we need to compute parenthesized
ranges in more places, which also relies on backwards lexing; and (2) we
need to make use of this in any relevant fixes.

However, I still think it's worth pursuing. On (1), the implementation
is very contained, so IMO we can easily swap this out for a more
performant solution in the future if needed. On (2), this improves
correctness and fixes some bad syntax errors detected by fuzzing, which
means it has value even if it's not as robust as an _actual_
`ParenthesizedExpression` node in the AST itself.

Closes https://github.com/astral-sh/ruff/issues/4925.

## Test Plan

`cargo test` with new cases that previously failed the fuzzer.
2023-08-17 15:51:09 +00:00
Charlie Marsh db1c556508
Implement `Ranged` on more structs (#6639)
## Summary

I noticed some inconsistencies around uses of `.range.start()`, structs
that have a `TextRange` field but don't implement `Ranged`, etc.

## Test Plan

`cargo test`
2023-08-17 11:22:39 -04:00
Charlie Marsh a70807e1e1
Expand `NamedExpr` range to include full range of parenthesized value (#6632)
## Summary

Given:

```python
if (
    x
    :=
    (  # 4
        y # 5
    )  # 6
):
    pass
```

It turns out the parser ended the range of the `NamedExpr` at the end of
`y`, rather than the end of the parenthesis that encloses `y`. This just
seems like a bug -- the range should be from the start of the name on
the left, to the end of the parenthesized node on the right.

## Test Plan

`cargo test`
2023-08-17 14:34:05 +00:00
Zanie Blue d0f2a8e424
Add support for nested replacements inside format specifications (#6616)
Closes https://github.com/astral-sh/ruff/issues/6442

Python string formatting like `"hello {place}".format(place="world")`
supports format specifications for replaced content such as `"hello
{place:>10}".format(place="world")` which will align the text to the
right in a container filled up to ten characters.

Ruff parses formatted strings into `FormatPart`s each of which is either
a `Field` (content in `{...}`) or a `Literal` (the normal content).
Fields are parsed into name and format specifier sections (we'll ignore
conversion specifiers for now).

There are a myriad of specifiers that can be used in a `FormatSpec`.
Unfortunately for linters, the specifier values can be dynamically set.
For example, `"hello {place:{align}{width}}".format(place="world",
align=">", width=10)` and `"hello {place:{fmt}}".format(place="world",
fmt=">10")` will yield the same string as before but variables can be
used to determine the formatting. In this case, when parsing the format
specifier we can't know what _kind_ of specifier is being used as their
meaning is determined by both position and value.

Ruff does not support nested replacements and our current data model
does not support the concept. Here the data model is updated to support
this concept, although linting of specifications with replacements will
be inherently limited. We could split format specifications into two
types, one without any replacements that we can perform lints with and
one with replacements that we cannot inspect. However, it seems
excessive to drop all parsing of format specifiers due to the presence
of a replacement. Instead, I've opted to parse replacements eagerly and
ignore their possible effect on other format specifiers. This will allow
us to retain a simple interface for `FormatSpec` and most syntax checks.
We may need to add some handling to relax errors if a replacement was
seen previously.

It's worth noting that the nested replacement _can_ also include a
format specification although it may fail at runtime if you produce an
invalid outer format specification. For example, `"hello
{place:{fmt:<2}}".format(place="world", fmt=">10")` is valid so we need
to represent each nested replacement as a full `FormatPart`.

## Test plan

Adding unit tests for `FormatSpec` parsing and snapshots for PLE1300
2023-08-17 09:07:30 -05:00
Charlie Marsh 1334232168
Introduce `ExpressionRef` (#6637)
## Summary

This PR revives the `ExpressionRef` concept introduced in
https://github.com/astral-sh/ruff/pull/5644, motivated by the change we
want to make in https://github.com/astral-sh/ruff/pull/6575 to narrow
the type of the expression that can be passed to `parenthesized_range`.

## Test Plan

`cargo test`
2023-08-17 10:07:16 -04:00
Micha Reiser fa7442da2f
Support `fmt: skip` on compound statements (#6593) 2023-08-17 06:05:41 +00:00
Micha Reiser 4dc32a00d0
Support `fmt: skip` for simple-statements and decorators (#6561) 2023-08-17 05:58:19 +00:00
Evan Rittenhouse e3ecbe660e
[`ruff`] Implement `quadratic-list-summation` rule (`RUF017`) (#6489)
## Summary

Adds `RUF017`. Closes #5073 

## Test Plan

`cargo t`
2023-08-16 23:13:05 -04:00
Harutaka Kawamura 8c3a8c4fc6
Support glob patterns for `raises_require_match_for` and `raises_require_match_for` (#6635)
## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Support glob patterns for `raises_require_match_for` and
`raises_require_match_for`. Resolve #6473

## Test Plan

New tests + existing tests
2023-08-17 02:15:50 +00:00
Charlie Marsh dcc7226685
Make lambda-assignment fix always-manual in class bodies (#6626)
## Summary

Related to https://github.com/astral-sh/ruff/issues/6620 (although that
will only be truly closed once we respect manual fixes on the CLI).
2023-08-16 21:24:48 -04:00
Charlie Marsh 036035bc50
Refactor literal-comparison and not-test rules (#6636)
## Summary

No behavior changes, but these need some refactoring to support
https://github.com/astral-sh/ruff/pull/6575 (namely, they need to take
the `ast::ExprCompare` or similar node instead of the attribute fields),
and I don't want to muddy that PR.

## Test Plan

`cargo test`
2023-08-17 01:02:30 +00:00
Charlie Marsh 97ae9e7433
Don't detect `pandas#values` for stores, deletes, or class accesses (#6631)
## Summary

Ensures we avoid cases like:

```python
x.values = 1
```

Since Pandas doesn't even expose a setter for that. We also avoid cases
like:

```python
print(self.values)
```

Since it's overwhelming likely to be a false positive.

Closes https://github.com/astral-sh/ruff/issues/6630.

## Test Plan

`cargo test`
2023-08-16 17:13:33 -04:00
Charlie Marsh 98b9f2e705
Respect .ipynb and .pyi sources when linting from stdin (#6628)
## Summary

When running Ruff from stdin, we were always falling back to the default
source type, even if the user specified a path (as is the case when
running from the LSP). This PR wires up the source type inference, which
means we now get the expected result when checking `.pyi` and `.ipynb`
files.

Closes #6627.

## Test Plan

Verified that `cat
crates/ruff/resources/test/fixtures/jupyter/valid.ipynb | cargo run -p
ruff_cli -- --force-exclude --no-cache --no-fix --isolated --select ALL
--stdin-filename foo.ipynb -` yielded the expected results (and differs
from the errors you get if you omit the filename).

Verified that `cat foo.pyi | cargo run -p ruff_cli -- --force-exclude
--no-cache --no-fix --format json --isolated --select TCH
--stdin-filename path/to/foo.pyi -` yielded no errors.
2023-08-16 20:33:59 +00:00
Zanie Blue 6253d8e2c8
Remove unused runtime string formatting logic (#6624)
In https://github.com/astral-sh/ruff/pull/6616 we are adding support for
nested replacements in format specifiers which makes actually formatting
strings infeasible without a great deal of complexity. Since we're not
using these functions (they just exist for runtime use in RustPython),
we can just remove them.
2023-08-16 17:38:33 +00:00
Micha Reiser fdbb2fbdba
Fix unreachable in playground (#6623) 2023-08-16 18:54:42 +02:00
Charlie Marsh d0b8e4f701
Update Black tests (#6618)
## Summary

Pulls in some tests that we previously couldn't support

## Test Plan

`cargo test`
2023-08-16 15:05:51 +00:00
Charlie Marsh 12f3c4c931
Fix comment formatting for yielded tuples (#6603)
## Summary
Closes https://github.com/astral-sh/ruff/issues/6384, although I think
the issue was fixed already on main, for the most part.

The linked issue is around formatting expressions like:

```python
def test():
    (
        yield 
        #comment 1
        * # comment 2
        # comment 3
        test # comment 4
    )

```

On main, prior to this PR, we now format like:

```python
def test():
    (
        yield (
            # comment 1
            # comment 2
            # comment 3
            *test
        )  # comment 4
    )
```

Which strikes me as reasonable. (We can't test this, since it's a syntax
error after for our parser, despite being a syntax error in both cases
from CPython's perspective.)

Meanwhile, Black does:

```python
def test():
    (
        yield
        # comment 1
        *  # comment 2
        # comment 3
        test  # comment 4
    )
```

So our formatting differs in that we move comments between the star and
the expression above the star.

As of this PR, we also support formatting this input, which is valid:

```python
def test():
    (
        yield 
        #comment 1
        * # comment 2
        # comment 3
        test, # comment 4
        1
    )
```

Like:

```python
def test():
    (
        yield (
            # comment 1
            (
                # comment 2
                # comment 3
                *test,  # comment 4
                1,
            )
        )
    )
```

There were two fixes here: (1) marking starred comments as dangling and
formatting them properly; and (2) supporting parenthesized comments for
tuples that don't contain their own parentheses, as is often the case
for yielded tuples (previously, we hit a debug assert).

Note that this diff

## Test Plan
cargo test
2023-08-16 13:41:07 +00:00
Micha Reiser 7ee2ae8395
Estimate expected `VecBuffer` size (#6612) 2023-08-16 15:31:31 +02:00
Charlie Marsh 95f78821ad
Fix parenthesized detection for tuples (#6599)
## Summary

This PR fixes our code for detecting whether a tuple has its own
parentheses, which is necessary when attempting to preserve parentheses.
As-is, we were getting some cases wrong, like `(a := 1), (b := 3))` --
the detection code inferred that this _was_ parenthesized, and so
wrapped the entire thing in an unnecessary set of parentheses.

## Test Plan

`cargo test`

Before:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.75472          |
| django       | 0.99804          |
| transformers | 0.99618          |
| twine        | 0.99876          |
| typeshed     | 0.74288          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |

After:
| project      | similarity index |
|--------------|------------------|
| cpython      | 0.75473          |
| django       | 0.99804 |
| transformers | 0.99618          |
| twine        | 0.99876          |
| typeshed     | 0.74288          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |
2023-08-16 13:20:48 +00:00
Micha Reiser daac31d2b9
Make `Buffer::write_element` non-failable (#6613) 2023-08-16 15:13:07 +02:00
Charlie Marsh 86ccdcc9d9
Add support for multi-character operator tokens to `SimpleTokenizer` (#6563)
## Summary

Allows for proper lexing of tokens like `->`.

The main challenge is to ensure that our forward and backwards
representations are the same for cases like `===`. Specifically, we want
that to lex as `==` followed by `=` regardless of whether it's a
forwards or backwards lex. To do so, we identify the range of the
sequential characters (the full span of `===`), lex it forwards, then
return the last token.

## Test Plan

`cargo test`
2023-08-16 09:09:19 -04:00
Micha Reiser e28858bb29
Fast path for ASCII only identifiers start (#6609) 2023-08-16 10:22:44 +02:00
Charlie Marsh 2d86e78bfc
Allow top-level `await` in Jupyter notebooks (#6607)
## Summary

Top-level `await` is allowed in Jupyter notebooks (see:
[autoawait](https://ipython.readthedocs.io/en/stable/interactive/autoawait.html)).

Closes https://github.com/astral-sh/ruff/issues/6584.

## Test Plan

Had to test this manually. Created a notebook, verified that the `yield`
was flagged but the `await` was not.

<img width="868" alt="Screen Shot 2023-08-15 at 11 40 19 PM"
src="https://github.com/astral-sh/ruff/assets/1309177/b2853651-30a6-4dc6-851c-9fe7f694b8e8">
2023-08-15 23:59:05 -04:00
Harutaka Kawamura d9a81f4fbb
[`flake8-pytest-style`] Implement duplicate parameterized fixture detection (`PT014`) (#6598) 2023-08-16 03:35:46 +00:00
Micha Reiser 897cce83b3
Call pattern formatting (#6594) 2023-08-16 08:31:25 +05:30
Charlie Marsh 3f1658a25b
Remove pylint's duplicate_value.rs (#6604)
This was moved to bugbear, but we forgot to delete the file.
2023-08-16 00:10:24 +00:00
Zanie Blue 097db2fcce
Fix docs for `PLW1508` (#6602) 2023-08-15 15:29:29 -05:00
Charlie Marsh a3d4f08f29
Add general support for parenthesized comments on expressions (#6485)
## Summary

This PR adds support for parenthesized comments. A parenthesized comment
is a comment that appears within a parenthesis, but not within the range
of the expression enclosed by the parenthesis. For example, the comment
here is a parenthesized comment:

```python
if (
    # comment
    True
):
    ...
```

The parentheses enclose the `True`, but the range of `True` doesn’t
include the `# comment`.

There are at least two problems associated with parenthesized comments:
(1) associating the comment with the correct (i.e., enclosed) node; and
(2) formatting the comment correctly, once it has been associated with
the enclosed node.

The solution proposed here for (1) is to search for parentheses between
preceding and following node, and use open and close parentheses to
break ties, rather than always assigning to the preceding node.

For (2), we handle these special parenthesized comments in `FormatExpr`.
The biggest risk with this approach is that we forget some codepath that
force-disables parenthesization (by passing in `Parentheses::Never`).
I've audited all usages of that enum and added additional handling +
test coverage for such cases.

Closes https://github.com/astral-sh/ruff/issues/6390.

## Test Plan

`cargo test` with new cases.

Before:

| project      | similarity index |
|--------------|------------------|
| build        | 0.75623          |
| cpython      | 0.75472          |
| django       | 0.99804          |
| transformers | 0.99618          |
| typeshed     | 0.74233          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |

After:

| project      | similarity index |
|--------------|------------------|
| build        | 0.75623          |
| cpython      | 0.75472          |
| django       | 0.99804          |
| transformers | 0.99618          |
| typeshed     | 0.74237          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |
2023-08-15 18:59:18 +00:00
Micha Reiser 29c0b9f91c
Use single lookup for leading, dangling, and trailing comments (#6589) 2023-08-15 17:39:45 +02:00
Harutaka Kawamura 81b1176f99
Fix PT005 doc (#6596) 2023-08-15 12:48:44 +00:00
Charlie Marsh b1c4c7be69
Add trailing comma for single-element import-from groups (#6583)
## Summary

Unlike other statements, Black always adds a trailing comma if an
import-from statement breaks with a single import member. I believe this
is for compatibility with isort -- see
09f5ee3a19,
https://github.com/psf/black/issues/127, or
66648c528a/src/black/linegen.py (L1452)
for the current version.

## Test Plan

`cargo test`, notice that a big chunk of the compatibility suite is
removed.

Before:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.75472          |
| django       | 0.99804          |
| transformers | 0.99618          |
| twine        | 0.99876          |
| typeshed     | 0.74233          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |

After:

| project      | similarity index |
|--------------|------------------|
| cpython      | 0.75472          |
| django       | 0.99804          |
| transformers | 0.99618          |
| twine        | 0.99876          |
| typeshed     | 0.74260          |
| warehouse    | 0.99601          |
| zulip        | 0.99727          |
2023-08-15 07:15:33 -04:00
Tom Kuson 84d178a219
Use one line between top-level items if formatting a stub file (#6501)
Co-authored-by: Micha Reiser <micha@reiser.io>
2023-08-15 09:33:57 +02:00
Micha Reiser 455db84a59
Replace `inline(always)` with `inline` (#6590) 2023-08-15 08:58:11 +02:00
Micha Reiser 232b44a8ca
Indent statements in suppressed ranges (#6507) 2023-08-15 08:00:35 +02:00
Harutaka Kawamura e1e213decf
Import `pytest` in `flake8-pytest-style` docs (#6580) 2023-08-14 23:08:15 -04:00
Charlie Marsh 17e7eae2f9
Avoid unused argument rules when functions call `locals()` (#6578)
Closes https://github.com/astral-sh/ruff/issues/6576.
2023-08-14 19:48:20 -04:00
Charlie Marsh 7f7df852e8
Remove some extraneous newlines in Cargo.toml (#6577) 2023-08-14 23:39:41 +00:00
Harutaka Kawamura ebda5fcd99
Add PT002 ~ PT005 docs (#6521) 2023-08-14 21:29:03 +00:00
Charlie Marsh b1870b2b16
Add deprecated unittest assertions to PT009 (#6572)
## Summary

This rule was missing `self.failIf` and friends.

## Test Plan

`cargo test`
2023-08-14 21:08:02 +00:00
Harutaka Kawamura a51d1ac980
Add `PT006` and `PT007` docs (#6531) 2023-08-14 17:03:42 -04:00
Evan Rittenhouse 1a52b548e7
Ignore PERF203 if `try` contains loop control flow statements (#6536) 2023-08-14 20:47:37 +00:00
Harutaka Kawamura 70696061cd
[`flake8-pytest-style`] Implement `pytest-unittest-raises-assertion` (`PT027`) (#6554) 2023-08-14 20:25:23 +00:00
Charlie Marsh cd634a9489
Expand documentation around flake8-type-checking rules for SQLAlchemy (#6570)
## Summary

Not addressing the root issue as much as improving the documentation.

Closes https://github.com/astral-sh/ruff/issues/6510.
2023-08-14 19:47:10 +00:00
Charlie Marsh 5ddf143cae
Clarify FBT documentation and refine rule names (#6567)
Closes https://github.com/astral-sh/ruff/issues/6530.
2023-08-14 15:24:16 -04:00
Charlie Marsh 46862473b9
Omit `NotImplementedError` from `TRY003` (#6568)
Closes https://github.com/astral-sh/ruff/issues/6528.
2023-08-14 18:24:44 +00:00
Charlie Marsh 96d310fbab
Remove `Stmt::TryStar` (#6566)
## Summary

Instead, we set an `is_star` flag on `Stmt::Try`. This is similar to the
pattern we've migrated towards for `Stmt::For` (removing
`Stmt::AsyncFor`) and friends. While these are significant differences
for an interpreter, we tend to handle these cases identically or nearly
identically.

## Test Plan

`cargo test`
2023-08-14 13:39:44 -04:00
Micha Reiser 09c8b17661
`fmt: off..on` suppression comments (#6477) 2023-08-14 15:57:36 +00:00
qdegraaf 278a4f6e14
Formatter: Fix posonlyargs for `expr_lambda` (#6562) 2023-08-14 17:38:56 +02:00
Charlie Marsh c3a9151eb5
Handle comments on open parentheses in with statements (#6515)
## Summary

This PR adds handling for comments on open parentheses in parenthesized
context managers. For example, given:

```python
with (  # comment
    CtxManager1() as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...
```

We want to preserve that formatting. (Black does the same.) On `main`,
we format as:

```python
with (
    # comment
    CtxManager1() as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...
```

It's very similar to how `StmtImportFrom` is handled.

Note that this case _isn't_ covered by the "parenthesized comment"
proposal, since this is a common on the statement that would typically
be attached to the first `WithItem`, and the `WithItem` _itself_ can
have parenthesized comments, like:

```python
with (  # comment
    (
        CtxManager1()  # comment
    ) as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...
```

## Test Plan

`cargo test`

Confirmed no change in similarity score.
2023-08-14 15:11:03 +00:00
Charlie Marsh 3711f8ad59
Expand `SimpleTokenizer` to all keywords and single-character tokens (#6518)
## Summary

For #6485, I need to be able to use the `SimpleTokenizer` to lex the
space between any two adjacent expressions (i.e., the space between a
preceding and following node). This requires that we support a wider
range of keywords (like `and`, to connect the pieces of `x and y`), and
some additional single-character tokens (like `-` and `>`, to support
`->`). Note that the `SimpleTokenizer` does not support multi-character
tokens, so the `->` in a function signature is lexed as a `-` followed
by a `>` -- but this is fine for our purposes.
2023-08-14 10:35:31 -04:00
Charlie Marsh a7cf8f0b77
Replace dynamic implicit concatenation detection with parser flag (#6513)
## Summary

In https://github.com/astral-sh/ruff/pull/6512, we added a flag to the
AST to mark implicitly-concatenated string expressions. This PR makes
use of that flag to remove the `is_implicit_concatenation` method.

## Test Plan

`cargo test`
2023-08-14 10:27:17 -04:00
Charlie Marsh 40407dcce5
Avoid marking inner-parenthesized comments as dangling bracket comments (#6517)
## Summary

The bracketed-end-of-line comment rule is meant to assign comments like
this as "immediately following the bracket":

```python
f(  # comment
    1
)
```

However, the logic was such that we treated this equivalently:

```python
f(
    (  # comment
        1
    )
)
```

This PR modifies the placement logic to ensure that we only skip the
opening bracket, and not any nested brackets. The above is now formatted
as:

```python
f(
    (
        # comment
        1
    )
)
```

(But will be corrected once we handle parenthesized comments properly.)

## Test Plan

`cargo test`

Confirmed no change in similarity score.
2023-08-14 09:52:19 -04:00
Charlie Marsh f16e780e0a
Add an implicit concatenation flag to string and bytes constants (#6512)
## Summary

Per the discussion in
https://github.com/astral-sh/ruff/discussions/6183, this PR adds an
`implicit_concatenated` flag to the string and bytes constant variants.
It's not actually _used_ anywhere as of this PR, but it is covered by
the tests.

Specifically, we now use a struct for the string and bytes cases, along
with the `Expr::FString` node. That struct holds the value, plus the
flag:

```rust
#[derive(Clone, Debug, PartialEq, is_macro::Is)]
pub enum Constant {
    Str(StringConstant),
    Bytes(BytesConstant),
    ...
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StringConstant {
    /// The string value as resolved by the parser (i.e., without quotes, or escape sequences, or
    /// implicit concatenations).
    pub value: String,
    /// Whether the string contains multiple string tokens that were implicitly concatenated.
    pub implicit_concatenated: bool,
}

impl Deref for StringConstant {
    type Target = str;
    fn deref(&self) -> &Self::Target {
        self.value.as_str()
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BytesConstant {
    /// The bytes value as resolved by the parser (i.e., without quotes, or escape sequences, or
    /// implicit concatenations).
    pub value: Vec<u8>,
    /// Whether the string contains multiple string tokens that were implicitly concatenated.
    pub implicit_concatenated: bool,
}

impl Deref for BytesConstant {
    type Target = [u8];
    fn deref(&self) -> &Self::Target {
        self.value.as_slice()
    }
}
```

## Test Plan

`cargo test`
2023-08-14 13:46:54 +00:00
Micha Reiser fc0c9507d0
Override fmt_dangling_comments for frequent nodes (#6551) 2023-08-14 15:29:05 +02:00
Tom Kuson 680d171ae5
Tweak documentation for `FBT002` (#6556) 2023-08-14 09:22:48 -04:00
konsti 01eceaf0dc
Format docstrings (#6452)
**Summary** Implement docstring formatting

**Test Plan** Matches black's `docstring.py` fixture exactly, added some
new cases for what is hard to debug with black and with what black
doesn't cover.

similarity index:

main:
zulip: 0.99702
django: 0.99784
warehouse: 0.99585
build: 0.75623
transformers: 0.99469
cpython: 0.75989
typeshed: 0.74853

this branch:

zulip: 0.99702
django: 0.99784
warehouse: 0.99585
build: 0.75623
transformers: 0.99464
cpython: 0.75517
typeshed: 0.74853

The regression in transformers is actually an improvement in a file they
don't format with black (they run `black examples tests src utils
setup.py conftest.py`, the difference is in hubconf.py). cpython doesn't
use black.

Closes #6196
2023-08-14 12:28:58 +00:00
Micha Reiser 910dbbd9b6
Printer: Reserve buffer upfront (#6550) 2023-08-14 12:15:36 +00:00
Micha Reiser 9584f613b9
Remove `allow(pedantic)` from formatter (#6549) 2023-08-14 14:02:06 +02:00
Micha Reiser 24f42f0894
Printer: Remove unused state fields (#6548) 2023-08-14 11:08:00 +02:00
Micha Reiser 51ae47ad56
Remove lex and parsing from formatter benchmark (#6547) 2023-08-14 10:25:37 +02:00
Charlie Marsh 1a9536c4e2
Remove `SemanticModel#find_binding` (#6546)
## Summary

This method is almost never what you actually want, because it doesn't
respect Python's scoping semantics. For example, if you call this within
a class method, it will return class attributes, whereas Python actually
_skips_ symbols in classes unless the load occurs within the class
itself. I also want to move away from these kinds of dynamic lookups and
more towards `resolve_name`, which performs a lookup based on the stored
`BindingId` at the time of symbol resolution, and will make it much
easier for us to separate model building from linting in the near
future.

## Test Plan

`cargo test`
2023-08-14 00:09:05 -04:00
Charlie Marsh bf4c6473c8
Remove unnecessary `expr_name` function (#6544) 2023-08-13 23:51:36 -04:00
Charlie Marsh 768686148f
Add support for unions to our Python builtins type system (#6541)
## Summary

Fixes some TODOs introduced in
https://github.com/astral-sh/ruff/pull/6538. In short, given an
expression like `1 if x > 0 else "Hello, world!"`, we now return a union
type that says the expression can resolve to either an `int` or a `str`.
The system remains very limited, it only works for obvious primitive
types, and there's no attempt to do inference on any more complex
variables. (If any expression yields `Unknown` or `TypeError`, we
propagate that result throughout and abort on the client's end.)
2023-08-13 18:00:50 -04:00
Charlie Marsh 446ceed1ad
Support `IfExp` with dual string arms in `invalid-envvar-value` (#6538)
## Summary

Closes https://github.com/astral-sh/ruff/issues/6537. We need to improve
the `PythonType` algorithm, so this also documents some of its
limitations as TODOs.
2023-08-13 15:52:10 -04:00
Takuma Watanabe 8660e5057c
Fix minor document errors (#6533)
## Summary

Fix minor errors in the sample codes of some rules.

## Test Plan

N/A (Just fix document typos.)
2023-08-13 13:35:30 -04:00
Konrad Listwan-Ciesielski 808e09180e
Add docs for `DTZ005` and `DTZ006` (#6529)
Changes:
- Adds docs for `DTZ005`
- Adds docs for `DTZ006`

Related to: https://github.com/astral-sh/ruff/issues/2646
2023-08-12 21:29:32 -04:00
Presley Graham dbf003fde4
importer: skip whitespace between comments at start of file (#6523)
## Summary

When adding an import, such as when fixing `I002`, ruff doesn't skip
whitespace between comments, but isort does. See this issue for more
detail: https://github.com/astral-sh/ruff/issues/6504

This change would fix that by skipping whitespace between comments in
`Insertion.start_of_file()`.

## Test Plan

I added a new test, `comments_and_newlines`, to verify this behavior. I
also ran `cargo test` and no existing tests broke. That being said, this
is technically a breaking change, as it's possible that someone was
relying on the previous behavior.
2023-08-12 16:37:56 -04:00
Charlie Marsh 010293ddcc
Use a unified policy abstraction for the `flake8-tidy-imports` rules (#6527)
## Summary

Generalizes the abstractions for name matching introduced in
https://github.com/astral-sh/ruff/pull/6378 and applies them to the
existing `banned_api` rule, such that both rules have a uniform API and
implementation.

## Test Plan

`cargo test`
2023-08-12 16:32:09 -04:00
James Braza 4974964ad3
Clarifying `target-version` in `flake8-future-annotations` docs (#6520) 2023-08-12 19:01:03 +00:00
Charlie Marsh b49c80f8c8
Use top-level semantic detection for E402 (#6526)
## Summary

Noticed in https://github.com/astral-sh/ruff/pull/6378. Given `import h;
import i`, we don't consider `import i` to be a "top-level" import for
E402 purposes, which is wrong. Similarly, we _do_ consider `import k` to
be a "top-level" import in:

```python
if __name__ == "__main__":
    import j; \
import k
```

Using the semantic detection, rather than relying on newline position,
fixes both cases.

## Test Plan

`cargo test`
2023-08-12 18:52:44 +00:00
Presley Graham c03e2acadb
[`flake8-tidy-imports`] Add `TID253` (#6378)
## Summary

Add a new rule `TID253` (`banned-module-level-imports`), to ban a
user-specified list of imports from appearing at module level. This rule
doesn't exist in `flake8-tidy-imports`, so it's unique to Ruff. The
implementation is pretty similar to `TID251`.

Briefly discussed
[here](https://github.com/astral-sh/ruff/discussions/6370).

## Test Plan

Added a new test case, checking that inline imports are allowed and that
non-inline imports from the banned list are disallowed.
2023-08-12 18:45:34 +00:00
Harutaka Kawamura c6ad364d8b
Add `PT008` and `PT009` docs (#6479) 2023-08-11 23:44:48 -04:00
Zanie Blue 5b47350c25
Document default behavior of `W505` in setting (#6463)
Addresses https://github.com/astral-sh/ruff/discussions/6459
2023-08-11 16:41:31 -05:00
Charlie Marsh e91caea490
Add test case for walrus operators in return types (#6438)
## Summary

Closes https://github.com/astral-sh/ruff/issues/6437.

## Test Plan

`cargo test`
2023-08-11 18:28:48 +00:00
Charlie Marsh 53246b725e
Allow return type annotations to use their own parentheses (#6436)
## Summary

This PR modifies our logic for wrapping return type annotations.
Previously, we _always_ wrapped the annotation in parentheses if it
expanded; however, Black only exhibits this behavior when the function
parameters is empty (i.e., it doesn't and can't break). In other cases,
it uses the normal parenthesization rules, allowing nodes to bring their
own parentheses.

For example, given:

```python
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[
    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]:
    ...

def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(x) -> Set[
    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]:
    ...
```

Black will format as:

```python
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
    Set[
        "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    ]
):
    ...


def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(
    x,
) -> Set[
    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]:
    ...
```

Whereas, prior to this PR, Ruff would format as:

```python
def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> (
    Set[
        "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    ]
):
    ...


def xxxxxxxxxxxxxxxxxxxxxxxxxxxx(
    x,
) -> (
    Set[
        "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    ]
):
    ...
```

Closes https://github.com/astral-sh/ruff/issues/6431.

## Test Plan

Before:

- `zulip`: 0.99702
- `django`: 0.99784
- `warehouse`: 0.99585
- `build`: 0.75623
- `transformers`: 0.99470
- `cpython`: 0.75988
- `typeshed`: 0.74853

After:

- `zulip`: 0.99724
- `django`: 0.99791
- `warehouse`: 0.99586
- `build`: 0.75623
- `transformers`: 0.99474
- `cpython`: 0.75956
- `typeshed`: 0.74857
2023-08-11 18:19:21 +00:00
Charlie Marsh d616c9b870
Avoid omitting optional parentheses for argument-less parentheses (#6484)
## Summary

This PR fixes some misformattings around optional parentheses for
expressions.

I first noticed that we were misformatting this:

```python
return (
    unicodedata.normalize("NFKC", s1).casefold()
    == unicodedata.normalize("NFKC", s2).casefold()
)
```

The above is stable Black formatting, but we were doing:
```python
return unicodedata.normalize("NFKC", s1).casefold() == unicodedata.normalize(
    "NFKC", s2
).casefold()
```

Above, the "last" expression is a function call, so our
`can_omit_optional_parentheses` was returning `true`...

However, it turns out that Black treats function calls differently
depending on whether or not they have arguments -- presumedly because
they'll never split empty parentheses, and so they're functionally
non-useful. On further investigation, I believe this applies to all
parenthesized expressions. If Black can't split on the parentheses, it
doesn't leverage them when removing optional parentheses.

## Test Plan

Nice increase in similarity scores.

Before:

- `zulip`: 0.99702
- `django`: 0.99784
- `warehouse`: 0.99585
- `build`: 0.75623
- `transformers`: 0.99470
- `cpython`: 0.75989
- `typeshed`: 0.74853

After:

- `zulip`: 0.99705
- `django`: 0.99795
- `warehouse`: 0.99600
- `build`: 0.75623
- `transformers`: 0.99471
- `cpython`: 0.75989
- `typeshed`: 0.74853
2023-08-11 17:58:42 +00:00
Chris Pryer 7c4aa3948b
Fix typo in MeasureMode comment (#6508) 2023-08-11 17:46:59 +00:00
konsti 0c9ded9d84
Use a faster diffing library for the formatter ecosystem checks (#6497)
**Summary** Some files seems notoriously slow in the formatter (secons in debug mode). This time was however almost exclusively spent in the diff algorithm to collect the similarity index, so i replaced that. I kept `similar` for printing actual diff to avoid rewriting that too, with the disadvantage that we now have to diff libraries in format_dev.

I used this PR to remove the spinner from tracing-indicatif and changed `flamegraph --perfdata perf.data` to `flamegraph --perfdata perf.data --no-inline` as the former wouldn't finish for me on release builds with debug info.
2023-08-11 15:51:54 +02:00
Dhruv Manilawala c434bdd2bd
Add formatting for `MatchCase` (#6360)
## Summary

This PR adds formatting support for `MatchCase` node with subs for the
`Pattern`
nodes.

## Test Plan

Added test cases for case node handling with comments, newlines.

resolves: #6299
2023-08-11 19:20:25 +05:30
konsti 8b24238d19
Show a pretty markdown table in formatter ecosystem checks (#6496)
**Summary** The formatter ecosystem checks will now print a markdown table you can copy&paste into your PR description. 

![image](https://github.com/astral-sh/ruff/assets/6826232/80289ed9-9d2b-400e-a994-de63dca0b065)

copied markdown:

| project      | similarity index |
|--------------|------------------|
| build        | 0.75623          |
| cpython      | 0.75989          |
| django       | 0.99784          |
| transformers | 0.99470          |
| typeshed     | 0.74853          |
| warehouse    | 0.99585          |
| zulip        | 0.99702          |

raw markdown:
```markdown
| project      | similarity index |
|--------------|------------------|
| build        | 0.75623          |
| cpython      | 0.75989          |
| django       | 0.99784          |
| transformers | 0.99470          |
| typeshed     | 0.74853          |
| warehouse    | 0.99585          |
| zulip        | 0.99702          |
```
2023-08-11 15:37:21 +02:00
Charlie Marsh f2939c678b
Avoid breaking call chains unnecessarily (#6488)
## Summary

This PR attempts to fix the formatting of the following expression:

```python
max_message_id = (
    Message.objects.filter(recipient=recipient).order_by("id").reverse()[0].id
)
```

Specifically, Black preserves _that_ formatting, while we do:

```python
max_message_id = (
    Message.objects.filter(recipient=recipient)
    .order_by("id")
    .reverse()[0]
    .id
)
```

The fix here is to add a group around the entire call chain.

## Test Plan

Before:

- `zulip`: 0.99702
- `django`: 0.99784
- `warehouse`: 0.99585
- `build`: 0.75623
- `transformers`: 0.99470
- `cpython`: 0.75989
- `typeshed`: 0.74853

After:

- `zulip`: 0.99703
- `django`: 0.99791
- `warehouse`: 0.99586
- `build`: 0.75623
- `transformers`: 0.99470
- `cpython`: 0.75989
- `typeshed`: 0.74853
2023-08-11 13:33:15 +00:00
Victor Hugo Gomes b05574babd
Fix formatter instability with half-indented comment (#6460)
## Summary
The bug was happening in this
[loop](75f402eb82/crates/ruff_python_formatter/src/comments/placement.rs (L545)).

Basically, In the first iteration of the loop, the `comment_indentation`
is bigger than `child_indentation` (`comment_indentation` is 7 and
`child_indentation` is 4) making the `Ordering::Greater` branch execute.
Inside the `Ordering::Greater` branch, the `if` block gets executed,
resulting in the update of these variables.
```rust
parent_body = current_body;                    
current_body = Some(last_child_in_current_body);
last_child_in_current_body = nested_child;
```
In the second iteration of the loop, `comment_indentation` is smaller
than `child_indentation` (`comment_indentation` is 7 and
`child_indentation` is 8) making the `Ordering::Less` branch execute.
Inside the `Ordering::Less` branch, the `if` block gets executed, this
is where the bug was happening. At this point `parent_body` should be a
`StmtFunctionDef` but it was a `StmtClassDef`. Causing the comment to be
incorrectly formatted.

That happened for the following code:
```python
class A:
    def f():
        pass
       # strangely indented comment

print()
```

There is only one problem that I couldn't figure it out a solution, the
variable `current_body` in this
[line](75f402eb82/crates/ruff_python_formatter/src/comments/placement.rs (L542C5-L542C49))
now gives this warning _"value assigned to `current_body` is never read
maybe it is overwritten before being read?"_
Any tips on how to solve that?

Closes #5337

## Test Plan

Add new test case.

---------

Co-authored-by: konstin <konstin@mailbox.org>
2023-08-11 11:21:16 +00:00
konsti 0ef6af807b
Implement DerefMut for WithNodeLevel (#6443)
**Summary** Implement `DerefMut` for `WithNodeLevel` so it can be used
in the same way as `PyFormatter`. I want this for my WIP upstack branch
to enable `.fmt(f)` on `WithNodeLevel` context. We could extend this to
remove the other two method from `WithNodeLevel`.
2023-08-11 10:41:48 +00:00
David Szotten f091b46497
move comments from expressions in f-strings out (#6481) 2023-08-11 09:22:30 +02:00
Charlie Marsh 2cedb401bd
Force parentheses for named expressions in more contexts (#6494)
See:
https://github.com/astral-sh/ruff/pull/6436#issuecomment-1673583888.
2023-08-11 01:54:46 -04:00
Charlie Marsh 2e5c81b202
Ensure that B006 autofix respects docstrings (#6493)
## Summary

Some follow-ups to https://github.com/astral-sh/ruff/pull/6131 to ensure
that fixes are inserted _after_ function docstrings, and that fixes are
robust to a bunch of edge cases.

## Test Plan

`cargo test`
2023-08-11 01:03:56 -04:00
Charlie Marsh cc151c35a8
Respect dummy-variable-rgx for unused bound exceptions (#6492)
## Summary

This PR respects our unused variable regex when flagging bound
exceptions, so that you no longer get a violation for, e.g.:

```python
def f():
    try:
        pass
    except Exception as _:
        pass
```

This is an odd pattern, but I think it's surprising that the regex
_isn't_ respected here.

Closes https://github.com/astral-sh/ruff/issues/6391

## Test Plan

`cargo test`
2023-08-11 04:02:02 +00:00
Charlie Marsh 95dea5c868
Respect tab width in line-length heuristic (#6491)
## Summary

In https://github.com/astral-sh/ruff/pull/5811, I suggested that we add
a heuristic to the overlong-lines check such that if the line had fewer
bytes than the character limit, we return early -- the idea being that a
single byte per character was the "worst case". I overlooked that this
isn't true for tabs -- with tabs, the "worst case" scenario is that
every byte is a tab, which can have a width greater than 1.

Closes https://github.com/astral-sh/ruff/issues/6425.

## Test Plan

`cargo test` with a new fixture borrowed from the issue, plus manual
testing.
2023-08-10 22:28:25 -04:00
Victor Hugo Gomes eb68addf97
[`pylint`] Implement `bad-dunder-name` (`W3201`) (#6486)
## Summary

Checks for any misspelled dunder name method and for any method defined
with `__...__` that's not one of the pre-defined methods.

The pre-defined methods encompass all of Python's standard dunder
methods.

ref: #970

## Test Plan
Snapshots and manual runs of pylint.
2023-08-11 01:31:16 +00:00
Tom Kuson 9ff80a82b4
[`pylint`] Implement `subprocess-run-check` (`W1510`) (#6487)
## Summary

Implements [`subprocess-run-check`
(`W1510`)](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/subprocess-run-check.html)
as `subprocess-run-without-check` (`PLW1510`). Includes documentation.

Related to #970.

## Test Plan

`cargo test`
2023-08-10 20:54:53 -04:00
Charlie Marsh 84ae00c395
Allow `os._exit` accesses in `SLF001` (#6490)
Closes https://github.com/astral-sh/ruff/issues/6483.
2023-08-11 00:54:38 +00:00
Zanie Blue 1050c4e104
Extend `target-version` documentation (#6482)
Closes https://github.com/astral-sh/ruff/issues/6462
2023-08-10 12:11:37 -05:00
Charlie Marsh 6706ae4828
Respect scoping rules when identifying builtins (#6468)
## Summary

Our `is_builtin` check did a naive walk over the parent scopes; instead,
it needs to (e.g.) skip symbols in a class scope if being called outside
of the class scope itself.

Closes https://github.com/astral-sh/ruff/issues/6466.

## Test Plan

`cargo test`
2023-08-10 10:20:09 -04:00
magic-akari dc3275fe7f
Improve Ruff Formatter Interoperability (#6472) 2023-08-10 14:39:53 +02:00
qdegraaf 50dab9cea6
[`flake8-bugbear`] Add autofix for B006 (#6131)
## Summary

Reopening of https://github.com/astral-sh/ruff/pull/4880 

One open TODO as described in:
https://github.com/astral-sh/ruff/pull/4880#discussion_r1265110215

FYI @charliermarsh seeing as you commented you wanted to do final review
and merge. @konstin @dhruvmanila @MichaReiser as previous reviewers.

# Old Description
## Summary

Adds an autofix for B006 turning mutable argument defaults into None and
setting their original value back in the function body if still `None`
at runtime like so:
```python
def before(x=[]):
    pass
    
def after(x=None):
    if x is None:
        x = []
    pass
```

## Test Plan

Added an extra test case to existing fixture with more indentation.
Checked results for all old examples.

NOTE: Also adapted the jupyter notebook test as this checked for B006 as
well.

## Issue link

Closes: https://github.com/charliermarsh/ruff/issues/4693

---------

Co-authored-by: konstin <konstin@mailbox.org>
2023-08-10 11:06:40 +00:00
konsti 4811af0f0b
Formatter: Add test cases for comments after opening parentheses (#6420)
**Summary** I collected all examples of end-of-line comments after
opening parentheses that i could think of so we get a comprehensive view
at the state of their formatting (#6390).

This PR intentionally only adds tests cases without any changes in
formatting. We need to decide which exact formatting we want, ideally in
terms of these test files, and implement this in follow-up PRs.

~~One stability check is still deactivated pending
https://github.com/astral-sh/ruff/pull/6386.~~
2023-08-10 08:34:03 +00:00
konsti 39beeb61f7
Track formatting all comments
We currently don't format all comments as match statements are not yet implemented. We can work around this for the top level match statement by setting them manually formatted but the mocked-out top level match doesn't call into its children so they would still have unformatted comments
2023-08-10 09:19:27 +02:00
Micha Reiser e2f7862404
Preserve dangling f-string comments
<!--
Thank you for contributing to Ruff! To help us out with reviewing, please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR fixes the issue where the FString formatting dropped dangling comments between the string parts.

```python
result_f = (
    f'  File "{__file__}", line {lineno_f+1}, in f\n'
    '    f()\n'
    # XXX: The following line changes depending on whether the tests
    # are run through the interactive interpreter or with -m
    # It also varies depending on the platform (stack size)
    # Fortunately, we don't care about exactness here, so we use regex
    r'  \[Previous line repeated (\d+) more times\]' '\n'
    'RecursionError: maximum recursion depth exceeded\n'
)
```

The solution here isn't ideal because it re-introduces the `enclosing_parent` on `DecoratedComment` but it is the easiest fix that I could come up. 
I didn't spend more time finding another solution becaues I think we have to re-write most of the fstring formatting with the upcoming Python 3.12 support (because lexing the individual parts as we do now will no longer work).

closes #6440

<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

`cargo test`

The child PR testing that all comments are formatted should now pass
2023-08-10 09:11:25 +02:00
Micha Reiser ac5c8bb3b6
Add `AnyNodeRef.visit_preorder`
<!--
Thank you for contributing to Ruff! To help us out with reviewing, please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR adds the `AnyNodeRef.visit_preorder` method. I'll need this method to mark all comments of a suppressed node's children as formatted (in debug builds). 

I'm not super happy with this because it now requires a double-dispatch where the `walk_*` methods call into `node.visit_preorder` and the `visit_preorder` then calls back into the visitor. Meaning,
the new implementation now probably results in way more function calls. The other downside is that `AnyNodeRef` now contains code that is difficult to auto-generate. This could be mitigated by extracting the `visit_preorder` method into its own `VisitPreorder` trait. 

Anyway, this approach solves the need and avoids duplicating the visiting code once more. 

<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

`cargo test`

<!-- How was it tested? -->
2023-08-10 08:35:09 +02:00
Micha Reiser c1bc67686c
Use SimpleTokenizer in `max_lines` (#6451) 2023-08-10 08:13:14 +02:00
Charlie Marsh 7eea0e94a2
Add containers to E721 types (#6469)
Related to https://github.com/astral-sh/ruff/issues/6465.
2023-08-10 02:34:51 +00:00
Charlie Marsh 0252995973
Document `FormatSpec` fields (#6458) 2023-08-09 18:13:29 -04:00
Charlie Marsh 627f475b91
Avoid applying `PYI055` to runtime-evaluated annotations (#6457)
## Summary

The use of `|` as a union operator is not always safe, if a type
annotation is evaluated in a runtime context. For example, this code
errors at runtime:

```python
import httpretty
import requests_mock

item: type[requests_mock.Mocker | httpretty] = requests_mock.Mocker
```

However, it's fine in a `.pyi` file, with `__future__` annotations`, or
if the annotation is in a non-evaluated context, like:

```python
def func():
    item: type[requests_mock.Mocker | httpretty] = requests_mock.Mocker
```

This PR modifies the rule to avoid enforcing in those invalid,
runtime-evaluated contexts.

Closes https://github.com/astral-sh/ruff/issues/6455.
2023-08-09 16:46:41 -04:00
Charlie Marsh 395bb31247
Improve counting of message arguments when msg is provided as a keyword (#6456)
Closes https://github.com/astral-sh/ruff/issues/6454.
2023-08-09 20:39:10 +00:00
Zanie Blue 3ecd263b4d
Bump version to 0.0.284 (#6453)
## What's Changed

This release fixes a few bugs, notably the previous release announced a
breaking change where the default target
Python version changed from 3.10 to 3.8 but it was not applied. Thanks
to @rco-ableton for fixing this in
https://github.com/astral-sh/ruff/pull/6444

### Bug Fixes
* Do not trigger `S108` if path is inside `tempfile.*` call by
@dhruvmanila in https://github.com/astral-sh/ruff/pull/6416
* Do not allow on zero tab width by @tjkuson in
https://github.com/astral-sh/ruff/pull/6429
* Fix false-positive in submodule resolution by @charliermarsh in
https://github.com/astral-sh/ruff/pull/6435

## New Contributors
* @rco-ableton made their first contribution in
https://github.com/astral-sh/ruff/pull/6444

**Full Changelog**:
https://github.com/astral-sh/ruff/compare/v0.0.283...v0.0.284
2023-08-09 13:32:33 -05:00
Charlie Marsh 6acf07c5c4
Use latest Python version by default in tests (#6448)
## Summary

Use the same Python version by default for all tests (our
latest-supported version).

## Test Plan

`cargo test`

---------

Co-authored-by: Zanie <contact@zanie.dev>
2023-08-09 15:22:39 +00:00
Charlie Marsh 38b9fb8bbd
Set a default on `PythonVersion` (#6446)
## Summary

I think it makes sense for `PythonVersion::default()` to return our
minimum-supported non-EOL version.

## Test Plan

`cargo test`

---------

Co-authored-by: Zanie <contact@zanie.dev>
2023-08-09 15:19:27 +00:00
Dhruv Manilawala 6a64f2289b
Rename `Magic*` to `IpyEscape*` (#6395)
## Summary

This PR renames the `MagicCommand` token to `IpyEscapeCommand` token and
`MagicKind` to `IpyEscapeKind` type to better reflect the purpose of the
token and type. Similarly, it renames the AST nodes from `LineMagic` to
`IpyEscapeCommand` prefixed with `Stmt`/`Expr` wherever necessary.

It also makes renames from using `jupyter_magic` to
`ipython_escape_commands` in various function names.

The mode value is still `Mode::Jupyter` because the escape commands are
part of the IPython syntax but the lexing/parsing is done for a Jupyter
notebook.

### Motivation behind the rename:
* IPython codebase defines it as "EscapeCommand" / "Escape Sequences":
* Escape Sequences:
292e3a2345/IPython/core/inputtransformer2.py (L329-L333)
* Escape command:
292e3a2345/IPython/core/inputtransformer2.py (L410-L411)
* The word "magic" is used mainly for the actual magic commands i.e.,
the ones starting with `%`/`%%`
(https://ipython.readthedocs.io/en/stable/interactive/reference.html#magic-command-system).
So, this avoids any confusion between the Magic token (`%`, `%%`) and
the escape command itself.
## Test Plan

* `cargo test` to make sure all renames are done correctly.
* `grep` for `jupyter_escape`/`magic` to make sure all renames are done
correctly.
2023-08-09 13:28:18 +00:00
Charlie Marsh 3bf1c66cda
Group function definition parameters with return type annotations (#6410)
## Summary

This PR removes the group around function definition parameters, instead
grouping the parameters with the type parameters and return type
annotation.

This increases Zulip's similarity score from 0.99385 to 0.99699, so it's
a meaningful improvement. However, there's at least one stability error
that I'm working on, and I'm really just looking for high-level feedback
at this point, because I'm not happy with the solution.

Closes https://github.com/astral-sh/ruff/issues/6352.

## Test Plan

Before:

- `zulip`: 0.99396
- `django`: 0.99784
- `warehouse`: 0.99578
- `build`: 0.75436
- `transformers`: 0.99407
- `cpython`: 0.75987
- `typeshed`: 0.74432

After:

- `zulip`: 0.99702
- `django`: 0.99784
- `warehouse`: 0.99585
- `build`: 0.75623
- `transformers`: 0.99470
- `cpython`: 0.75988
- `typeshed`: 0.74853
2023-08-09 12:13:58 +00:00
rco-ableton eaada0345c
Set default version to py38 (#6444)
## Summary

In https://github.com/astral-sh/ruff/pull/6397, the documentation was
updated stating that the default target-version is now "py38", but the
actual default value wasn't updated and remained py310. This commit
updates the default value to match what the documentation says.
2023-08-09 12:08:47 +00:00
Micha Reiser a39dd76d95
Add `enter` and `leave_node` methods to Preoder visitor (#6422) 2023-08-09 09:09:00 +00:00
Dhruv Manilawala e257c5af32
Add support for help end IPython escape commands (#6358)
## Summary

This PR adds support for a stricter version of help end escape
commands[^1] in the parser. By stricter, I mean that the escape tokens
are only at the end of the command and there are no tokens at the start.
This makes it difficult to implement it in the lexer without having to
do a lot of look aheads or keeping track of previous tokens.

Now, as we're adding this in the parser, the lexer needs to recognize
and emit a new token for `?`. So, `Question` token is added which will
be recognized only in `Jupyter` mode.

The conditions applied are the same as the ones in the original
implementation in IPython codebase (which is a regex):
* There can only be either 1 or 2 question mark(s) at the end
* The node before the question mark can be a `Name`, `Attribute`,
`Subscript` (only with integer constants in slice position), or any
combination of the 3 nodes.

## Test Plan

Added test cases for various combination of the possible nodes in the
command value position and update the snapshots.

fixes: #6359
fixes: #5030 (This is the final piece)

[^1]: https://github.com/astral-sh/ruff/pull/6272#issue-1833094281
2023-08-09 10:28:52 +05:30
Dhruv Manilawala 887a47cad9
Avoid `S108` if path is inside `tempfile.*` call (#6416) 2023-08-09 10:22:31 +05:30
Charlie Marsh a2758513de
Fix false-positive in submodule resolution (#6435)
Closes https://github.com/astral-sh/ruff/issues/6433.
2023-08-09 02:36:39 +00:00