Commit Graph

1078 Commits

Author SHA1 Message Date
Micha Reiser d4e140d47f
perf: `RuleTable::any_enabled` (#10971) 2024-04-16 12:20:27 +00:00
Alex Waygood f779babc5f
Improve handling of builtin symbols in linter rules (#10919)
Add a new method to the semantic model to simplify and improve the correctness of a common pattern
2024-04-16 11:37:31 +01:00
Charlie Marsh effd5188c9
[`flake8-bandit`] Allow `urllib.request.urlopen` calls with static `Request` argument (#10964)
## Summary

Allows, e.g.:

```python
import urllib

urllib.request.urlopen(urllib.request.Request("https://example.com/"))
```

...in
[`suspicious-url-open-usage`](https://docs.astral.sh/ruff/rules/suspicious-url-open-usage/).

See:
https://github.com/astral-sh/ruff/issues/7918#issuecomment-2057661054
2024-04-16 02:30:23 +00:00
Steve C c2210359e7
[`pylint`] Implement `self-cls-assignment` (`W0642`) (#9267)
## Summary

This PR implements [`W0642`/`self-cls-assignment`](https://pylint.readthedocs.io/en/stable/user_guide/messages/warning/self-cls-assignment.html)

See: #970 

## Test Plan

Add test cases and verified the updated snapshots.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2024-04-15 09:06:01 +00:00
Hoël Bagard 670d66f54c
[`pycodestyle`] Do not trigger `E3` rules on defs following a function/method with a dummy body (#10704) 2024-04-15 10:23:49 +02:00
Dhruv Manilawala f9a828f493
Move `Q003` to AST checker (#10923)
## Summary

This PR moves the `Q003` rule to AST checker.

This is the final rule that used the docstring detection state machine
and thus this PR removes it as well.

resolves: #7595 
resolves: #7808 

## Test Plan

- [x] `cargo test`
- [x] Make sure there are no changes in the ecosystem
2024-04-14 23:44:12 +05:30
Steve C 812b0976a9
[`pylint`] Support inverted comparisons (`PLR1730`) (#10920)
## Summary

Adds more aggressive logic to PLR1730, `if-stmt-min-max`

Closes #10907 

## Test Plan

`cargo test`

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-04-13 22:57:20 +00:00
Hoël Bagard b356c4376c
Fix S310 `suspicious-url-open-usage` description (#10917)
## Summary

The "What it does" section of the docstring is missing a verb, this PR
adds it.
2024-04-13 12:52:04 +01:00
Sebastian Pipping 85ca5b7eed
Fix last example of flake8-bugbear rule `B023` "function uses loop variable" (#10913)
<!--
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

Hi! 👋 

Thanks for sharing ruff as software libre — it helps me keep Python code
quality up with pre-commit, both locally and CI 🙏

While studying the examples at
https://docs.astral.sh/ruff/rules/function-uses-loop-variable/#example I
noticed that the last of the examples had a bug: prior to this fix, `ì`
was passed to the lambda for `x` rather than for `i` — the two are
mixed-up. The reason it's easy to overlook is because addition is an
commutative operation and so `x + i` and `i + x` give the same result
(and least with integers), despite the mix-up. For proof, let me demo
the relevant part with before and after:

```python
In [1]: from functools import partial

In [2]: [partial(lambda x, i: (x, i), i)(123) for i in range(3)]
Out[2]: [(0, 123), (1, 123), (2, 123)]

In [3]: [partial(lambda x, i: (x, i), i=i)(123) for i in range(3)]
Out[3]: [(123, 0), (123, 1), (123, 2)]
```

Does that make sense?

## Test Plan

<!-- How was it tested? -->
Was manually tested using IPython.


CC @r4f @grandchild
2024-04-12 20:07:52 +00:00
Charlie Marsh c2421068bc
Limit commutative non-augmented-assignments to primitive data types (#10912)
## Summary

I think this is the best we can do without type inference. At least it
will still catch some common cases.

Closes #10911.
2024-04-12 15:02:29 -04:00
Charlie Marsh e9870fe468
Avoid `non-augmented-assignment` for reversed, non-commutative operators (#10909)
Closes https://github.com/astral-sh/ruff/issues/10900.
2024-04-12 10:04:57 -04:00
Charlie Marsh a013050c11
Respect `per-file-ignores` for `RUF100` on blanket `# noqa` (#10908)
## Summary

If `RUF100` was included in a per-file-ignore, we respected it on cases
like `# noqa: F401`, but not the blanket variant (`# noqa`).

Closes https://github.com/astral-sh/ruff/issues/10906.
2024-04-12 13:45:29 +00:00
Dhruv Manilawala 2e37cf6b3b
Bump version to v0.3.7 (#10895) 2024-04-12 03:39:45 +00:00
wolfgangshi a9e4393008
[`pylint`] Implement rule to prefer augmented assignment (`PLR6104`) (#9932)
## Summary

Implement new rule: Prefer augmented assignment (#8877). It checks for
the assignment statement with the form of `<expr> = <expr>
<binary-operator> …` with a unsafe fix to use augmented assignment
instead.

## Test Plan

1. Snapshot test is included in the PR.
2. Manually test with playground.
2024-04-11 23:08:42 -04:00
Charlie Marsh 312f43475f
[`pylint`] Recode `nan-comparison` rule to `W0177` (#10894)
## Summary

This was accidentally committed under `W0117`, but the actual Pylint
code is `W0177`:
https://pylint.readthedocs.io/en/latest/user_guide/checkers/features.html.

Closes https://github.com/astral-sh/ruff/issues/10791.
2024-04-11 22:49:20 -04:00
Martin Imre 03899dcba3
[`flake8-bugbear`] Implement `loop-iterator-mutation` (`B909`) (#9578)
## Summary
This PR adds the implementation for the current
[flake8-bugbear](https://github.com/PyCQA/flake8-bugbear)'s B038 rule.
The B038 rule checks for mutation of loop iterators in the body of a for
loop and alerts when found.

Rational: 
Editing the loop iterator can lead to undesired behavior and is probably
a bug in most cases.

Closes #9511.

Note there will be a second iteration of B038 implemented in
`flake8-bugbear` soon, and this PR currently only implements the weakest
form of the rule.
I'd be happy to also implement the further improvements to B038 here in
ruff 🙂
See https://github.com/PyCQA/flake8-bugbear/issues/454 for more
information on the planned improvements.

## Test Plan
Re-using the same test file that I've used for `flake8-bugbear`, which
is included in this PR (look for the `B038.py` file).


Note: this is my first time using `rust` (beside `rustlings`) - I'd be
very happy about thorough feedback on what I could've done better
🙂 - Bring it on 😀
2024-04-11 19:52:52 +00:00
Carl Meyer 25f5a8b201
Struct not tuple for compiled per-file ignores (#10864)
## Summary

Code cleanup for per-file ignores; use a struct instead of a tuple.

Named the structs for individual ignores and the list of ignores
`CompiledPerFileIgnore` and `CompiledPerFileIgnoreList`. Name choice is
because we already have a `PerFileIgnore` struct for a
pre-compiled-matchers form of the config. Name bikeshedding welcome.

## Test Plan

Refactor, should not change behavior; existing tests pass.

---------

Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2024-04-11 13:47:57 -06:00
Charlie Marsh e7d1d43f39
[`pylint`] Reverse min-max logic in `if-stmt-min-max` (#10890)
Closes https://github.com/astral-sh/ruff/issues/10889.
2024-04-11 14:16:13 -04:00
Dhruv Manilawala 4e8a84617c
Bump version to v0.3.6 (#10883)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-04-11 15:53:01 +00:00
Auguste Lalande ffea1bb0a3
[`refurb`] Implement `write-whole-file` (`FURB103`) (#10802)
## Summary

Implement `write-whole-file` (`FURB103`), part of #1348. This is largely
a copy and paste of `read-whole-file` #7682.

## Test Plan

Text fixture added.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2024-04-11 14:21:45 +05:30
Charlie Marsh 1eee6f16e4
[`flake8-pytest-style`] Fix single-tuple conversion in `pytest-parametrize-values-wrong-type` (#10862)
## Summary

This looks like a typo (without test coverage).

Closes https://github.com/astral-sh/ruff/issues/10861.
2024-04-10 14:20:09 -04:00
Auguste Lalande de46a36bbc
[`pygrep-hooks`] Improve `blanket-noqa` error message (`PGH004`) (#10851)
## Summary

Improve `blanket-noqa` error message in cases where codes are provided
but not detected due to formatting issues. Namely `# noqa X100` (missing
colon) or `noqa : X100` (space before colon). The behavior is similar to
`NQA002` and `NQA003` from `flake8-noqa` mentioned in #850. The idea to
merge the rules into `PGH004` was suggested by @MichaReiser
https://github.com/astral-sh/ruff/pull/10325#issuecomment-2025535444.

## Test Plan

Test cases added to fixture.
2024-04-10 04:30:25 +00:00
Charlie Marsh dbf8d0c82c
Show negated condition in `needless-bool` diagnostics (#10854)
## Summary

Closes https://github.com/astral-sh/ruff/issues/10843.
2024-04-10 04:29:43 +00:00
Carl Meyer 02e88fdbb1
Support negated patterns in [extend-]per-file-ignores (#10852)
Fixes #3172 

## Summary

Allow prefixing [extend-]per-file-ignores patterns with `!` to negate
the pattern; listed rules / prefixes will be ignored in all files that
don't match the pattern.

## Test Plan

Added tests for the feature.

Rendered docs and checked rendered output.
2024-04-09 21:53:41 -06:00
Carl Meyer e13e57e024
Localize cleanup for FunctionDef and ClassDef (#10837)
## Summary

Came across this code while digging into the semantic model with
@AlexWaygood, and found it confusing because of how it splits
`push_scope` from the paired `pop_scope` (took me a few minutes to even
figure out if/where we were popping the pushed scope). Since this
"cleanup" is already totally split by node type, there doesn't seem to
be any gain in having it as a separate "step" rather than just
incorporating it into the traversal clauses for those node types.

I left the equivalent cleanup step alone for the expression case,
because in that case it is actually generic across several different
node types, and due to the use of the common `visit_generators` utility
there isn't a clear way to keep the pushes and corresponding pops
localized.

Feel free to just reject this if I've missed a good reason for it to
stay this way!

## Test Plan

Tests and clippy.
2024-04-08 13:29:38 -06:00
Aleksei Latyshev 6050bab5db
[`refurb`] Support `itemgetter` in `reimplemented-operator` (`FURB118`) (#10526)
## Summary
Lint about function like expressions which are equivalent to
`operator.itemgetter`.
See:
https://github.com/astral-sh/ruff/issues/1348#issuecomment-1909421747

## Test Plan
cargo test
2024-04-07 02:31:59 +00:00
Alex Waygood 2a51dcfdf7
[`pyflakes`] Allow forward references in class bases in stub files (`F821`) (#10779)
## Summary

Fixes #3011.

Type checkers currently allow forward references in all contexts in stub
files, and stubs frequently make use of this capability (although it
doesn't actually seem to be specc'd anywhere --neither in PEP 484, nor
https://typing.readthedocs.io/en/latest/source/stubs.html#id6, nor the
CPython typing docs). Implementing it so that Ruff allows forward
references in _all contexts_ in stub files seems non-trivial, however
(or at least, I couldn't figure out how to do it easily), so this PR
does not do that. Perhaps it _should_; if we think this apporach isn't
principled enough, I'm happy to close it and postpone changing anything
here.

However, this does reduce the number of F821 errors Ruff emits on
typeshed down from 76 to 2, which would mean that we could enable the
rule at typeshed. The remaining 2 F821 errors can be trivially fixed at
typeshed by moving definitions around; forward references in class bases
were really the only remaining places where there was a real _use case_
for forward references in stub files that Ruff wasn't yet allowing.

## Test plan

`cargo test`. I also ran this PR branch on typeshed to check to see if
there were any new false positives caused by the changes here; there
were none.
2024-04-07 01:15:58 +01:00
Alex Waygood 86588695e3
[`flake8-slots`] Flag subclasses of call-based `typing.NamedTuple`s as well as subclasses of `collections.namedtuple()` (`SLOT002`) (#10808) 2024-04-07 00:16:06 +01:00
Alex Waygood 47e0cb8985
[`flake8-pyi`] Various improvements to PYI034 (#10807)
More accurately identify whether a class is a metaclass, a subclass of `collections.abc.Iterator`, or a subclass of `collections.abc.AsyncIterator`
2024-04-07 00:15:48 +01:00
Tibor Reiss 3194f90db1
[`pylint`] Implement `if-stmt-min-max` (`PLR1730`, `PLR1731`) (#10002)
Add rule [consider-using-min-builtin
(R1730)](https://pylint.readthedocs.io/en/latest/user_guide/messages/refactor/consider-using-min-builtin.html)
and [consider-using-max-builtin
(R1731)](https://pylint.readthedocs.io/en/latest/user_guide/messages/refactor/consider-using-max-builtin.html)

See https://github.com/astral-sh/ruff/issues/970 for rules

Test Plan: `cargo test`
2024-04-06 17:32:05 +00:00
Charlie Marsh ee4bff3475
Add comment test for `FURB110` (#10804) 2024-04-06 16:49:22 +00:00
Auguste Lalande 7fb012d0df
[`refurb`] Do not allow any keyword arguments for `read-whole-file` in `rb` mode (`FURB101`) (#10803)
## Summary

`Path.read_bytes()` does not support any keyword arguments, so `FURB101`
should not be triggered if the file is opened in `rb` mode with any
keyword arguments.

## Test Plan

Move erroneous test to "Non-error" section of fixture.
2024-04-06 12:41:39 -04:00
Steve C 44459f92ef
[`refurb`] Implement `if-expr-instead-of-or-operator` (`FURB110`) (#10687)
## Summary

Add
[`FURB110`](https://github.com/dosisod/refurb/blob/master/refurb/checks/logical/use_or.py)

See: #1348 

## Test Plan

`cargo test`
2024-04-06 16:39:40 +00:00
Alex Waygood 1dc93107dc
Improve internal documentation for the semantic model (#10788) 2024-04-06 16:28:32 +00:00
Charlie Marsh 7fb5f47efe
Respect `# noqa` directives on `__all__` openers (#10798)
## Summary

Historically, given:

```python
__all__ = [  # noqa: F822
    "Bernoulli",
    "Beta",
    "Binomial",
]
```

The F822 violations would be attached to the `__all__`, so this `# noqa`
would be enforced for _all_ definitions in the list. This changed in
https://github.com/astral-sh/ruff/pull/10525 for the better, in that we
now use the range of each string. But these `# noqa` directives stopped
working.

This PR sets the `__all__` as a parent range in the diagnostic, so that
these directives are respected once again.

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

## Test Plan

`cargo test`
2024-04-06 14:51:17 +00:00
Charlie Marsh 83db62bcda
Use within-scope shadowed bindings in `asyncio-dangling-task` (#10793)
## Summary

I think this is using the wrong shadowing, as seen by the change in the
test fixture.
2024-04-06 10:44:03 -04:00
Bohdan b45fd61ec5
[`pyupgrade`] Replace `str, Enum` with `StrEnum` (`UP042`) (#10713)
## Summary

Add new rule `pyupgrade - UP042` (I picked next available number).
Closes https://github.com/astral-sh/ruff/discussions/3867
Closes https://github.com/astral-sh/ruff/issues/9569

It should warn + provide a fix `class A(str, Enum)` -> `class
A(StrEnum)` for py311+.

## Test Plan

Added UP042.py test.

## Notes

I did not find a way to call `remove_argument` 2 times consecutively, so
the automatic fixing works only for classes that inherit exactly `str,
Enum` (regardless of the order).

I also plan to extend this rule to support IntEnum in next PR.
2024-04-06 01:56:28 +00:00
Auguste Lalande c2790f912b
[`pylint`] Implement `bad-staticmethod-argument` (`PLW0211`) (#10781)
## Summary

Implement `bad-staticmethod-argument` from pylint, part of #970.

## Test Plan

Text fixture added.
2024-04-05 21:33:39 +00:00
Micha Reiser 2e7a1a4cb1
D403: Require capitalizing single word sentence (#10776) 2024-04-05 08:42:00 +02:00
Jane Lewis d050d6da2e
`ruff server` now supports the `source.organizeImports` source action (#10652)
## Summary

This builds on top of the work in
https://github.com/astral-sh/ruff/pull/10597 to support `Ruff: Organize
imports` as an available source action.

To do this, we have to support `Clone`-ing for linter settings, since we
need to modify them in place to select import-related diagnostics
specifically (`I001` and `I002`).

## Test Plan


https://github.com/astral-sh/ruff/assets/19577865/04282d01-dfda-4ac5-aa8f-6a92d5f85bfd
2024-04-04 22:20:50 +00:00
Dhruv Manilawala d02b1069b5
Add semantic model flag when inside f-string replacement field (#10766)
## Summary

This PR adds a new semantic model flag to indicate that the checker is
inside an f-string replacement field. This will be used to ignore
certain checks if the target version doesn't support a specific feature
like PEP 701.

fixes: #10761 

## Test Plan

Add a test case from the raised issue.
2024-04-04 09:08:48 +05:30
Alex Waygood 6b4fa17097
Rework docs for pydocstyle rules (#10754) 2024-04-03 22:34:00 +01:00
Carl Meyer 5e2482824c
[flake8_comprehensions] add sum/min/max to unnecessary comprehension check (C419) (#10759)
Fixes #3259 

## Summary

Renames `UnnecessaryComprehensionAnyAll` to
`UnnecessaryComprehensionInCall` and extends the check to `sum`, `min`,
and `max`, in addition to `any` and `all`.

## Test Plan

Updated snapshot test.

Built docs locally and verified the docs for this rule still render
correctly.
2024-04-03 14:44:33 -06:00
Charlie Marsh e54b591ec7
Use section name range for all section-related docstring diagnostics (#10740)
## Summary

We may not have had access to this in the past, but in short, if the
diagnostic is related to a specific section of a docstring, it seems
better to highlight the section (via the header) than the _entire_
docstring.

This should be completely compatible with existing `# noqa` since it's
always inside of a multi-line string anyway, and in such cases the `#
noqa` is always placed at the end of the multiline string.

Closes https://github.com/astral-sh/ruff/issues/10736.
2024-04-02 22:10:04 -04:00
Carl Meyer 814b26f82e
[flake8_comprehensions] update docs for unnecessary-comprehension-any-all (C419) (#10744)
Ref #3259; see in particular
https://github.com/astral-sh/ruff/issues/3259#issuecomment-2033127339

## Summary

Improve the accuracy of the docs for this lint rule/fix.

## Test Plan

Generated the docs locally and visited the page for this rule:

![Screenshot 2024-04-02 at 4 56
40 PM](https://github.com/astral-sh/ruff/assets/61586/64f25cf6-edfe-4682-ac8e-7e21b834f5f2)

---------

Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-04-02 17:42:55 -06:00
Charlie Marsh dff8f93457
[`flake8-return`] Ignore assignments to annotated variables in `unnecessary-assign` (#10741)
## Summary

Closes https://github.com/astral-sh/ruff/issues/10732.
2024-04-02 16:18:05 -04:00
Aleksei Latyshev 859e3fc7fa
[`refurb`] Implement `int-on-sliced-str` (`FURB166`) (#10650)
## Summary
implement int_on_sliced_str (FURB166) lint
- #1348
- [original
lint](https://github.com/dosisod/refurb/blob/master/refurb/checks/builtin/use_int_base_zero.py)

## Test Plan
cargo test
2024-04-02 19:29:42 +00:00
Aleksei Latyshev 0de23760ff
[`pylint`] Don't recommend decorating staticmethods with `@singledispatch` (`PLE1519`, `PLE1520`) (#10637)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2024-04-02 16:47:31 +00:00
Charlie Marsh 159bad73d5
Accept non-aliased (but correct) import in unconventional-import-alias (#10729)
## Summary

Given:

```toml
[tool.ruff.lint.flake8-import-conventions.aliases]
"django.conf.settings" = "settings"
```

We should accept `from django.conf import settings`.

Closes https://github.com/astral-sh/ruff/issues/10599.
2024-04-01 23:47:20 -04:00
Charlie Marsh 7b48443624
Respect `Q00*` ignores in `flake8-quotes` rules (#10728)
## Summary

We lost the per-rule ignores when these were migrated to the AST, so if
_any_ `Q` rule is enabled, they're now all enabled.

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

## Test Plan

Ran:

```shell
ruff check . --isolated --select Q --ignore Q000
ruff check . --isolated --select Q --ignore Q001
ruff check . --isolated --select Q --ignore Q002
ruff check . --isolated --select Q --ignore Q000,Q001
ruff check . --isolated --select Q --ignore Q000,Q002
ruff check . --isolated --select Q --ignore Q001,Q002
```

...against:

```python
'''
bad docsting
'''
a = 'single'
b = '''
bad multi line
'''
```
2024-04-02 03:21:12 +00:00
Charlie Marsh d36f60999d
Ignore annotated lambdas in class scopes (#10720)
## Summary

An annotated lambda assignment within a class scope is often
intentional. For example, within a dataclass or Pydantic model, these
are treated as fields rather than methods (and so can be passed values
in constructors).

I originally wrote this to special-case dataclasses and Pydantic
models... But was left feeling like we'd see more false positives here
for little gain (an annotated lambda within a `class` is likely
intentional?). Open to opinions, though.

Closes https://github.com/astral-sh/ruff/issues/10718.
2024-04-01 15:44:45 -04:00
Charlie Marsh 67f0f615b2
Recursively resolve `TypeDicts` for N815 violations (#10719)
## Summary

Only works within a single file for now.

Closes https://github.com/astral-sh/ruff/issues/10671.
2024-04-01 17:40:55 +00:00
Charlie Marsh 200ebeebdc
Bump version to v0.3.5 (#10717) 2024-04-01 13:15:32 -04:00
renovate[bot] a0e1544848
chore(deps): update rust crate pep440_rs to 0.5.0 (#10703) 2024-04-01 16:02:18 +00:00
Steve C f6b6f0df67
[`ruff`] Fix panic in unused `# noqa` removal with multi-byte space (`RUF100`) (#10682)
## Summary

Currently, [this
line](716688d44e/crates/ruff_linter/src/fix/edits.rs (L101))
assumes that the `noqa` comment begins with an octothorpe followed by a
space. (`# `) With anyone's random code, this of course is not always
true.

When there's a multi-byte character after the leading octothorpe, such
as
[`\u0085`](https://www.fileformat.info/info/unicode/char/85/index.htm),
we try slicing from within the character, causing a panic.

To fix this, the logic has been changed to remove unused `noqa`
directives and keep any trailing comments, or removing the whole comment
if the comment is just the unused `noqa`

Fixes #10097.

## Test Plan

`cargo test`
2024-04-01 01:00:37 +00:00
hikaru-kajita 716688d44e
[`pylint`] Implement `modified-iterating-set` (`E4703`) (#10473)
## Summary

Implement `E4703` in the issue #970.
Relevant pylint docs is here:
https://pylint.readthedocs.io/en/stable/user_guide/messages/error/modified-iterating-set.html

## Test Plan

I've written it in the `modified_iterating_set.py`.
2024-03-31 14:37:49 +00:00
hikaru-kajita 9ad9cea952
[`refurb`] Implement `unnecessary-from-float` (`FURB164`) (#10647)
## Summary

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

Implement FURB164 in the issue #1348.
Relevant Refurb docs is here:
https://github.com/dosisod/refurb/blob/v2.0.0/docs/checks.md#furb164-no-from-float

I've changed the name from `no-from-float` to
`verbose-decimal-fraction-construction`.

## Test Plan

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

I've written it in the `FURB164.py`.

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-03-30 07:04:01 -04:00
Charlie Marsh 75e01420fa
Always place non-relative imports after relative imports (#10669)
## Summary

When `relative-imports-order = "closest-to-furthest"` is set, we should
_still_ put non-relative imports after relative imports. It's rare for
them to be in the same section, but _possible_ if you use
`known-local-folder`.

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

## Test Plan

New tests.

Also sorted this file:

```python
from ..models import ABC
from .models import Question
from .utils import create_question
from django_polls.apps.polls.models import Choice
```

With both:

- `isort view.py`
- `ruff check view.py --select I --fix`

And the following `pyproject.toml`:

```toml
[tool.ruff.lint.isort]
order-by-type = false
relative-imports-order = "closest-to-furthest"
known-local-folder = ["django_polls"]

[tool.isort]
profile = "black"
reverse_relative = true
known_local_folder = ["django_polls"]
```

I verified that Ruff and isort gave the same result, and that they
_still_ gave the same result when removing the relevant setting:

```toml
[tool.ruff.lint.isort]
order-by-type = false
known-local-folder = ["django_polls"]

[tool.isort]
profile = "black"
known_local_folder = ["django_polls"]
```
2024-03-29 22:13:54 -04:00
Charlie Marsh fc54f53662
Make `unnecessary-lambda` an always-unsafe fix (#10668)
## Summary

See the linked issue and comment for more.

Closes https://github.com/astral-sh/ruff/issues/10663.
2024-03-30 01:05:05 +00:00
Charlie Marsh 7c2e9f71ea
Change `quadratic-list-summation` docs to use `iadd` consistently (#10666)
Closes https://github.com/astral-sh/ruff/issues/10088.
2024-03-30 00:32:34 +00:00
Auguste Lalande 3c48913473
[`flake8-boolean-trap`] Add setting for user defined allowed boolean trap (#10531)
## Summary

Add a setting `extend-allowed-calls` to allow users to define their own
list of calls which allow boolean traps.

Resolves #10485.
Resolves #10356.

## Test Plan

Extended text fixture and added setting test.
2024-03-30 00:26:12 +00:00
Dhruv Manilawala 1bcdfe268d
Allow f-strings with `%z` for `DTZ007` (#10651)
## Summary

This PR fixes the bug for `DTZ007` rule where it didn't consider to
check for the presence of `%z` in f-strings. It also considers the
string parts of an implicitly concatenated f-strings for which I want to
find a better solution (#10308).

fixes: #10601 

## Test Plan

Add test cases and update the snapshots.
2024-03-29 09:57:13 +05:30
Mateusz Sokół a0263ab472
Add `row_stack` to NumPy 2.0 migration rule (#10646)
Hi! 

I left out one of the functions in the migration rule which became
deprecated/removed in NumPy 2.0
(https://github.com/numpy/numpy/issues/26032#issuecomment-1999870797).

cc @anntzer
2024-03-28 09:49:40 -04:00
Mix cce25ec116
Update warning message for rule S305 to address insecure block cipher mode use (#10602)
<!--
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 updates the warning message for rule S305 to accurately reflect
the security concern over using ECB mode in block ciphers, which is
considered insecure compared to other modes like CBC or CTR. The
previous message incorrectly mentioned AES as a [block cipher
mode](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation),
which has been corrected to avoid confusion.

Ref: 

c85576d903/bandit/blacklists/calls.py (L99-L102)


825fd7c990/crates/ruff_linter/src/rules/flake8_bandit/rules/suspicious_function_call.rs (L187-L216)

## Test Plan

No testing required as the change is limited to a minor change of
warning message update.
2024-03-27 21:00:49 -04:00
Peter A. Jonsson fc7fa59e5f
space_around_operator: use same before/after numbers (#10640)
## Summary

The example for tab-after-comma (E242):
```python
a = 4,\t5
```
Use instead:
```python
a = 4, 3
```
is confusing since both the whitespace and the numbers are changed.

Change so the examples use the same numbers before/after.

## Test Plan

Untested.
2024-03-27 19:31:19 -04:00
Alex Waygood abbefae6f1
`DTZ` rules: Clarify error messages and docs (#10621)
- Clearly state in the documentation that passing `tz=None` is just as bad as not passing a `tz=` argument, from the perspective of these rules.
- Clearly state in the error messages exactly what the user is doing wrong, if the user is passing `tz=None` rather than failing to pass a `tz=` argument at all.
- Make error messages more concise, and separate out the suggested remedy from the thing that the user is identified as doing wrong.

Co-authored-by: Christian Clauss <cclauss@me.com>
2024-03-27 19:42:13 +00:00
Aleksei Latyshev f9d0c6d9ae
[`refurb`] Implement `for-loop-set-mutations` (`FURB142`) (#10583)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2024-03-27 09:26:12 +01:00
hikaru-kajita a28776e3aa
[`flake8-comprehensions`] Handled special case for `C401` which also matches `C416` (#10596)
## Summary

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

Similar to #10419, there was a case where there is a collision of C401
and C416 (as discussed in #10101).
Fixed this by implementing short-circuit for the comprehension of the
form `{x for x in foo}`.

## Test Plan

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

Extended `C401.py` with the case where `set` is not builtin function,
and divided the case where the short-circuit should occur.
Removed the last testcase of `print(f"{ {set(a for a in 'abc')} }")`
test as this is invalid as a python code, but should I keep this?
2024-03-26 03:54:58 +00:00
Filipe Laíns 960e47423c
Put flake8-logging next to the other flake8 plugins in registry (#10587)
## Summary

This is just a nitpicky improvement, but I thought it'd be a good
opportunity to look at the ruff source.

> The rules list in the documentation is generated using the registry
order. Currently, flake8-logging is separated from the rest of the
flake8 plugins. This patch puts it next to them.

https://docs.astral.sh/ruff/rules/

If it makes sense, we could alternatively just sort the linters in
https://github.com/astral-sh/ruff/blob/main/crates/ruff_dev/src/generate_rules_table.rs.

Signed-off-by: Filipe Laíns <lains@riseup.net>
2024-03-25 20:23:31 +00:00
Dhruv Manilawala 4950ca4142
Ignore `Q000`, `Q001` when string is inside forward ref (#10585)
## Summary

This is not the holistic solution but just to fix that issue.

fixes: #10546 

## Test Plan

Add a regression test for it and check the snapshots.
2024-03-25 18:52:59 +00:00
hikaru-kajita f7aab5ac69
[`pylint`] Fixed false-positive on the rule `PLW1641` (`eq-without-hash`) (#10566)
## Summary

Fixed false-positive on the rule `PLW1641`, where the explicit
assignment on the `__hash__` method is not counted as an definition of
`__hash__`. (Discussed in #10557).

Also, added one new testcase.

## Test Plan

Checked on `cargo test` in `eq_without_hash.py`.

Before the change, for the assignment into `__hash__`, only `__hash__ =
None` was counted as an explicit definition of `__hash__` method.
Probably any assignment into `__hash__` property could be counted as an
explicit definition of hash, so I removed `value.is_none_literal_expr()`
check.
2024-03-25 14:40:01 +00:00
Hoël Bagard 9512bd66b5
[`pycodestyle`] Avoid blank line rules for the first logical line in cell (#10291)
## Summary

Closes #10228

The PR makes the blank lines rules keep track of the cell status when
running on a notebook, and makes the rules not trigger when the line is
the first of the cell.

## Test Plan

The example given in #10228 is added as a fixture, along with a few
tests from the main blank lines fixtures.
2024-03-25 11:19:30 +00:00
Dhruv Manilawala e9115b8d8a
Move `Q004` to AST based checker (#10548)
## Summary

Continuing with #7595, this PR moves the `Q004` rule to the AST checker.

## Test Plan

- [x] Existing test cases should pass
- [x] No ecosystem updates
2024-03-25 03:31:31 +00:00
Alexey Preobrazhenskiy d625f55c05
Nested namespace packages support (#10541)
## Summary
PEP 420 says [nested namespace
packages](https://peps.python.org/pep-0420/#nested-namespace-packages)
are allowed, i.e. marking a directory as a namespace package marks all
subdirectories in the subtree as namespace packages.

`is_package` is modified to use `Path::starts_with` and the order of
checks is reversed to do in-memory checks first before hitting the disk.

## Test Plan
Added unit tests. Previously all tests were run with `namespace_packages
== &[]`. Verified that one of the tests was failing before changing the
implementation.

## Future Improvements
The `is_package_with_cache` can probably be rewritten to avoid repeated
calls to `Path::starts_with`, by caching all directories up to the
`namespace_root`:
```ruff
let namespace_root = namespace_packages
    .iter()
    .filter(|namespace_package| path.starts_with(namespace_package))
    .min();
```
2024-03-24 22:53:32 -04:00
Charlie Marsh 9856c1446b
Document use of anonymous assignment in `useless-expression` (#10551)
Closes https://github.com/astral-sh/ruff/issues/10536.
2024-03-25 02:46:33 +00:00
hikaru-kajita 39fb6d9bfc
[`refurb`] Implement `verbose-decimal-constructor` (`FURB157`) (#10533)
## Summary

Implement FURB157 in the issue #1348.
Relevant Refurb docs is here:
https://github.com/dosisod/refurb/blob/master/docs/checks.md#furb157-simplify-decimal-ctor

## Test Plan

I've written it in the `FURB157.py`.
2024-03-24 22:28:58 -04:00
yt2b 22f237fec6
[`flake8-bugbear`] Avoid false positive for usage after `continue` (`B031`) (#10539)
## Summary

Closes #10337.

I've fixed the code to count usage of variable.
Usage count inside the block is reset when there is a following
statement.
- continue
- break
- return 

## Test Plan

Add test case.
2024-03-25 00:38:30 +00:00
Alex Waygood 021f0bdccb
Mark PYI025 fix as safe in more cases for stub files (#10547)
## Summary

The fix for PYI025 is currently marked as unsafe in non-global scopes
for both `.py` and `.pyi` files, on the grounds that all global-scope
symbols in Python are implicitly exported from the module, so changing
the name of something in the global scope could break other modules that
import the module we're fixing. Unlike in `.py` files, however, imported
symbols are never implicitly re-exported from stub files. Symbols are
only understood by static analysis tools as being re-exported from stubs
if they are marked as explicit re-exports, which take three forms:

```py
from foo import *  # all symbols from foo are re-exported from the stub

# the "redundant" alias marks it as an explicit re-export
# (note that the alias needs to be identical to the symbol's "actual" name
# in order for it to be a re-export)
from bar import barrr as barrr

# inclusion in __all__ also marks it as an explicit re-export,
# just like in `.py` files
from baz import bazzz
__all__ = ["bazzz"]
```

This is [specc'd in PEP
484](https://peps.python.org/pep-0484/#stub-files), and means that we
can mark the fix for PYI025 as safe in more cases for `.pyi` files.

## Test Plan

`cargo test`. An existing test case goes from being an unsafe fix to a
safe fix in a `.pyi` fixture. I also added a new fixture so we have
coverage of global-scope imports that are marked as re-exports using
"redundant" `from collections.abc import Set as Set` aliases.
2024-03-24 16:11:48 +00:00
Dhruv Manilawala c447454111
[`E402`] Allow cell magics before an import (#10545) 2024-03-24 16:20:00 +05:30
Dhruv Manilawala 895d9df02f
Move `Q001-3` to AST based checker (#10312)
## Summary

Continuing with https://github.com/astral-sh/ruff/issues/7595, this PR
moves the `Q001`, `Q002`, `Q003` rules to the AST based checker.

## Test Plan

Make sure all of the existing test cases pass and verify there are no
ecosystem changes.
2024-03-23 22:59:50 +05:30
Auguste Lalande 0c194f55e8
Fix `PT014` autofix for last item in list (#10532)
## Summary

This error was found browsing
https://github.com/qarmin/Automated-Fuzzer/actions/runs/8396966850.
Which failed when trying to autofix the PT014 violation in the following
code:
```python
@pytest.mark.parametrize('data, spec', [(1.0, 1.0), (1.0, 1.0)])
def test_numbers(data, spec):
    ...
```

Investigation revealed that the implementation was not properly tested,
when the duplicate value was also the last in the list. In particular
the following function, which is in charge of finding the comma
following an element to create the suggested fix,

0a99bd84ce/crates/ruff_linter/src/rules/flake8_pytest_style/rules/parametrize.rs (L647-L651)
would find the next comma even if it was outside the list itself leading
to a lot of code being deleted.

This PR fixes that.

## Test Plan

Added misbehaving code to the test fixture.
2024-03-23 09:26:42 -04:00
Alex Waygood 9feb9b0aa8
Correctly handle references in `__all__` definitions when renaming symbols in autofixes (#10527) 2024-03-22 20:06:35 +00:00
Charlie Marsh 61b7982422
Respect Unicode characters in import sorting (#10529)
## Summary

Ensures that we use the raw identifier as provided in the source code,
rather than the normalized Unicode identifier.

This _does_ mean that we treat these as two separate identifiers, and
_don't_ merge them, even though Python will treat them as the same
symbol:

```python
import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ
import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio
```

I think that's fine, this is super rare anyway and would likely be
confusing for users.

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

## Test Plan

`cargo test`
2024-03-22 15:16:49 -04:00
Ryan May 594b232e0f
Accept commas in default copyright pattern (#9498)
## Summary

Adds commas as an accepted separator between copyright years by default,
which is actually documented in one spot, but not currently accurate.
Fixes #9477.
2024-03-22 14:42:02 -04:00
Alex Waygood a06ffeb54e
Track ranges of names inside `__all__` definitions (#10525) 2024-03-22 18:38:40 +00:00
Alex Waygood b74dd420fc
Fix F821 false negatives when `from __future__ import annotations` is active (attempt 2) (#10524) 2024-03-22 18:11:16 +00:00
Charlie Marsh 5062572aca
Bump version to v0.3.4 (#10515) 2024-03-21 18:08:21 +00:00
Charlie Marsh dc6f6398e7
Rename `list-reassign-reversed` to `list-reverse-copy` (#10514)
After discussion with @MichaReiser.
2024-03-21 17:33:00 +00:00
Aleksei Latyshev 01fe268612
[`refurb`] Implement `list_assign_reversed` lint (FURB187) (#10212)
## Summary

Implement [use_reverse
(FURB187)](https://github.com/dosisod/refurb/blob/master/refurb/checks/readability/use_reverse.py)
lint.
Tests were copied from original
https://github.com/dosisod/refurb/blob/master/test/data/err_187.py.

## Test Plan

cargo test
2024-03-21 17:09:09 +00:00
Alex Waygood c62184d057
'Revert "F821: Fix false negatives in .py files when `from __future__ import annotations` is active (#10362)"' (#10513) 2024-03-21 16:41:05 +00:00
Charlie Marsh caa1450895
Don't treat annotations as redefinitions in `.pyi` files (#10512)
## Summary

In https://github.com/astral-sh/ruff/pull/10341, we fixed some false
positives in `.pyi` files, but introduced others. This PR effectively
reverts the change in #10341 and fixes it in a slightly different way.
Instead of changing the _bindings_ we generate in the semantic model in
`.pyi` files, we instead change how we _resolve_ them.

Closes https://github.com/astral-sh/ruff/issues/10509.
2024-03-21 12:22:50 -04:00
Charlie Marsh 60fd98eb2f
Update Rust to v1.77 (#10510) 2024-03-21 12:10:33 -04:00
Alex Waygood ac150b9314
Spruce up docs for flake8-pyi rules (part 2) (#10494)
- Improve clarity over the motivation for some rules
- Improve links to external references. In particular, reduce links to PEPs, as PEPs are generally historical documents rather than pieces of living documentation. Where possible, it's better to link to the official typing spec, the other docs at typing.readthedocs.io/en/latest, or the docs at docs.python.org/3/library/typing.html.
- Use more concise language in a few places
2024-03-21 11:54:43 +00:00
Auguste Lalande d9ac170eb4
Fix `E231` bug: Inconsistent catch compared to pycodestyle, such as when dict nested in list (#10469)
<!--
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

Fix `E231` bug: Inconsistent catch compared to pycodestyle, such as when
dict nested in list. Resolves #10113.

## Test Plan

Example from #10113 added to test fixture.
2024-03-21 09:13:37 +01:00
Charlie Marsh 9aded0284e
Add missing `Options` references to blank line docs (#10498)
See: https://github.com/astral-sh/ruff/issues/10427.
2024-03-21 00:49:36 +00:00
Auguste Lalande 685de912ff
[`pylint`] Implement `nan-comparison` (`PLW0117`) (#10401)
## Summary

Implement pylint's nan-comparison, part of #970.

## Test Plan

Text fixture was added.
2024-03-21 00:36:17 +00:00
Sergey Chudov 4045df4ad4
Avoid incorrect tuple transformation in single-element case (`C409`) (#10491)
# Summary
Fixed: incorrect rule transformation rule C409 with single element.

# Test Plan
Added examples from #10323 to test fixtures.
2024-03-21 00:09:28 +00:00
Auguste Lalande fd3d272026
Improve clarity of `PT006`'s error message (#10468)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-03-20 18:22:02 +00:00
Alex Waygood 7caf0d064a
Simplify formatting of strings by using flags from the AST nodes (#10489) 2024-03-20 16:16:54 +00:00
Vasco Schiavo fc792d1d2e
Fix error message for rule C400 (#10488)
Fix a typos in the error message of rule C400

With the latest version of Ruff (0.3.3) if I have a `scratch.py` script
like that:

```python
from typing import Dict, List, Tuple


def generate_samples(test_cases: Dict) -> List[Tuple]:
    return list(
        (input, expected)
        for input, expected in zip(test_cases["input_value"], test_cases["expected_value"])
    )
```

and I run ruff

```shell
>>> ruff check scratch.py --select C400
>>> scratch.py:5:12: C400 Unnecessary generator (rewrite using `list()`
```

This PR fixes the error message from _"(rewrite using `list()`"_ to
_"(rewrite using `list()`)"_, and it fixes also the doc.

Related question: why I have this error message? The rule is not correct
in this case. Should I open an issue for that?
2024-03-20 14:22:34 +01:00
Charlie Marsh f7740a8a20
Allow SPDX license headers to exceed the line length (#10481)
Closes https://github.com/astral-sh/ruff/issues/10465.
2024-03-19 15:57:03 -04:00
Dhruv Manilawala 42d4216fd7
Consider raw source code for `W605` (#10480)
## Summary

This PR fixes a panic in the linter for `W605`.

Consider the following f-string:
```python
f"{{}}ab"
```

The `FStringMiddle` token would contain `{}ab`. Notice that the escaped
braces have _reduced_ the string. This means we cannot use the text
value from the token to determine the location of the escape sequence
but need to extract it from the source code.

fixes: #10434 

## Test Plan

Add new test cases and update the snapshots.
2024-03-20 00:16:35 +05:30
Charlie Marsh bc9b4571eb
Avoid failures due to non-deterministic binding ordering (#10478)
## Summary

We're seeing failures in https://github.com/astral-sh/ruff/issues/10470
because `resolve_qualified_import_name` isn't guaranteed to return a
specific import if a symbol is accessible in two ways (e.g., you have
both `import logging` and `from logging import error` in scope, and you
want `logging.error`). This PR breaks up the failing tests such that the
imports aren't in the same scope.

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

## Test Plan

I added a `bindings.reverse()` to `resolve_qualified_import_name` to
ensure that the tests pass regardless of the binding order.
2024-03-19 18:01:33 +00:00
Micha Reiser 17d56ccab3
Remove unused dependencies (#10475)
## Summary
I used `cargo-shear` (see
[tweet](https://twitter.com/boshen_c/status/1770106165923586395)) to
remove some unused dependencies that `cargo udeps` wasn't reporting.

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

## Test Plan

`cargo test`
2024-03-19 17:33:47 +01:00
Charlie Marsh 938118b65c
Avoid code comment detection in PEP 723 script tags (#10464)
Closes https://github.com/astral-sh/ruff/issues/10455.
2024-03-18 17:48:51 -04:00
Sid 1a2f9f082d
[`flake8-pytest-style`] Add automatic fix for `pytest-parametrize-values-wrong-type` (`PT007`) (#10461)
## Summary

This adds automatic fixes for the `PT007` rule.

I am currently reviewing and adding Ruff rules to Home Assistant. One
rule is PT007, which has multiple hundred occurrences in the codebase,
but no automatic fix, and this is not fun to do manually, especially
because using Regexes are not really possible with this.

My knowledge of the Ruff codebase and Rust in general is not good and
this is my first PR here, so I hope it is not too bad.

One thing where I need help is: How can I have the transformed code to
be formatted automatically, instead of it being minimized as it does it
now?

## Test Plan

Using the existing fixtures and updated snapshots.
2024-03-18 20:28:49 +00:00
Alex Waygood ae0ff9b029
Spruce up docs for flake8-pyi rules (#10422) 2024-03-18 18:03:32 +00:00
Alex Waygood 162d2eb723
Track casing of r-string prefixes in the tokenizer and AST (#10314)
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-03-18 17:18:04 +00:00
Alex Waygood 92e6026446
Apply NFKC normalization to unicode identifiers in the lexer (#10412) 2024-03-18 11:56:56 +00:00
Robin Caloudis 2edd61709f
[`flake8-quotes`] Fix Autofix Error (`Q000, Q002`) (#10199)
## Summary
In issue https://github.com/astral-sh/ruff/issues/6785 it is reported
that a docstring in the form of `''"assert" ' SAM macro definitions '''`
is autocorrected to `"""assert" ' SAM macro definitions '''` (note the
triple quotes one only one side), which breaks the python program due
`undetermined string lateral`.

* `Q002`: Not only would docstrings in the form of `''"assert" ' SAM
macro definitions '''` (single quotes) be autofixed wrongly, but also
e.g. `""'assert' ' SAM macro definitions '''` (double quotes). The bug
is present for docstrings in all scopes (e.g. module docstrings, class
docstrings, function docstrings)

* `Q000`: The autofix error is not only present for `Q002` (docstrings),
but also for inline strings (`Q000`). Therefore `s = ''"assert" ' SAM
macro definitions '''` will also be wrongly autofixed.

Note that situation in which the first string is non-empty can be fixed,
e.g. `'123'"assert" ' SAM macro definitions '''` -> `"123""assert" ' SAM
macro definitions '''` is valid.

## What
* Change FixAvailability of `Q000` `Q002` to `Sometimes`
* Changed both rules such that docstrings/inline strings that cannot be
fixed are still reported as bad quotes via diagnostics, but no fix is
provided

## Test Plan
* For `Q000`: Add docstrings in different scopes that (partially) would
have been autofixed wrongly
* For `Q002`: Add inline strings that (partially) would have been
autofixed wrongly

Closes https://github.com/astral-sh/ruff/issues/6785
2024-03-18 01:31:25 +00:00
Auguste Lalande dc021dd4d2
Fix pylint upstream categories not showing in docs (#10441)
## Summary

The upstream category check here

fd26b29986/crates/ruff_linter/src/upstream_categories.rs (L54-L65)

was not working because the code is actually "E0001" not "PLE0001", I
changed it so it will detect the upstream category correctly.

I also sorted the upstream categories alphabetically, so that the
document generation will be deterministic.

## Test Plan

I compared the diff before and after the change.
2024-03-18 01:27:39 +00:00
hikaru-kajita fd26b29986
[`pylint`] Implement `nonlocal-and-global` (`E115`) (#10407)
## Summary

Implement `E115` in the issue #970.
Reference to pylint docs:
https://pylint.readthedocs.io/en/stable/user_guide/messages/error/nonlocal-and-global.html
Throws an error when a variable name is both declared as global and
nonlocal

## Test Plan

With `nonlocal_and_global.py`
2024-03-18 00:43:02 +00:00
Ottavio Hartman 6123a5b8bc
[`flake8-bugbear`] Allow tuples of exceptions (`B030`) (#10437)
Fixes #10426 

## Summary

Fix rule B030 giving a false positive with Tuple operations like `+`.

[Playground](https://play.ruff.rs/17b086bc-cc43-40a7-b5bf-76d7d5fce78a)
```python
try:
    ...
except (ValueError,TypeError) + (EOFError,ArithmeticError):
    ...
```

## Reviewer notes

This is a little more convoluted than I was expecting -- because we can
have valid nested Tuples with operations done on them, the flattening
logic has become a bit more complex.

Shall I guard this behind --preview?

## Test Plan

Unit tested.
2024-03-18 00:31:23 +00:00
Ottavio Hartman 526abebbae
[`flake8-simplify`] Detect implicit `else` cases in `needless-bool` (`SIM103`) (#10414)
Fixes #10402 

## Summary

For SIM103, detect and simplify the following case:

[playground
link](https://play.ruff.rs/d98570aa-b180-495b-8600-5c4c3fd02526)
```python
def main():
    if foo > 5:
        return True
    return False
```

## Test Plan

Unit tested only.
2024-03-18 00:15:28 +00:00
Auguste Lalande 229a50a2c8
[`pylint`] Implement `singledispatchmethod-function` (`PLE5120`) (#10428)
## Summary

Implement `singledispatchmethod-function` from pylint, part of #970.

This is essentially a copy paste of #8934 for `@singledispatchmethod`
decorator.

## Test Plan

Text fixture added.
2024-03-18 00:02:52 +00:00
Zanie Blue 608df9a1bc
Bump version to 0.3.3 (#10425)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-03-15 12:51:49 -05:00
Steve C 740c08b033
[`pylint`] - implement `redeclared-assigned-name` (`W0128`) (#9268)
## Summary

Implements
[`W0128`/`redeclared-assigned-name`](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/redeclared-assigned-name.html)

See: #970 

## Test Plan

`cargo test`
2024-03-15 09:43:55 -05:00
hikaru-kajita 7e652e8fcb
[`flake8_comprehensions`] Handled special case for `C400` which also matches `C416` (#10419)
## Summary

Short-circuit implementation mentioned in #10403.

I implemented this by extending C400:
- Made `UnnecessaryGeneratorList` have information of whether the the
short-circuiting occurred (to put diagnostic)
- Add additional check for whether in `unnecessary_generator_list`
function.

Please give me suggestions if you think this isn't the best way to
handle this :)

## Test Plan

Extended `C400.py` a little, and written the cases where:
- Code could be converted to one single conversion to `list` e.g.
`list(x for x in range(3))` -> `list(range(3))`
- Code couldn't be converted to one single conversion to `list` e.g.
`list(2 * x for x in range(3))` -> `[2 * x for x in range(3)]`
- `list` function is not built-in, and should not modify the code in any
way.
2024-03-15 14:34:18 +00:00
Tom Kuson 9675e1867a
Allow trailing ellipsis in `typing.TYPE_CHECKING` (#10413)
## Summary

Trailing ellipses in objects defined in `typing.TYPE_CHECKING` might be
meaningful (it might be declaring a stub). Thus, we should skip the
`unnecessary-placeholder` (`PIE970`) rule in such contexts.

Closes #10358.

## Test Plan

`cargo nextest run`
2024-03-15 03:55:57 +00:00
Charlie Marsh 10ace88e9a
Track conditional deletions in the semantic model (#10415)
## Summary

Given `del X`, we'll typically add a `BindingKind::Deletion` to `X` to
shadow the current binding. However, if the deletion is inside of a
conditional operation, we _won't_, as in:

```python
def f():
    global X

    if X > 0:
        del X
```

We will, however, track it as a reference to the binding. This PR adds
the expression context to those resolved references, so that we can
detect that the `X` in `global X` was "assigned to".

Closes https://github.com/astral-sh/ruff/issues/10397.
2024-03-14 20:45:46 -04:00
Guilherme Vasconcelos a8e50a7f40
[RUF008] Make it clearer that a mutable default in a dataclass is only valid if it is typed as a ClassVar (#10395)
## Summary

The previous documentation sounded as if typing a mutable default as a
`ClassVar` were optional. However, it is not, as not doing so causes a
`ValueError`. The snippet below was tested in Python's interactive
shell:

```
>>> from dataclasses import dataclass
>>> @dataclass
... class A:
...     mutable_default: list[int] = []
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/dataclasses.py", line 1230, in dataclass
    return wrap(cls)
           ^^^^^^^^^
  File "/usr/lib/python3.11/dataclasses.py", line 1220, in wrap
    return _process_class(cls, init, repr, eq, order, unsafe_hash,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/dataclasses.py", line 958, in _process_class
    cls_fields.append(_get_field(cls, name, type, kw_only))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/dataclasses.py", line 815, in _get_field
    raise ValueError(f'mutable default {type(f.default)} for field '
ValueError: mutable default <class 'list'> for field mutable_default is not allowed: use default_factory
>>>
```

This behavior is also documented in Python's docs, see
[here](https://docs.python.org/3/library/dataclasses.html#mutable-default-values):

> [...] the
[dataclass()](https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass)
decorator will raise a
[ValueError](https://docs.python.org/3/library/exceptions.html#ValueError)
if it detects an unhashable default parameter. The assumption is that if
a value is unhashable, it is mutable. This is a partial solution, but it
does protect against many common errors.

And
[here](https://docs.python.org/3/library/dataclasses.html#class-variables)
it is documented why it works if it is typed as a `ClassVar`:

> One of the few places where
[dataclass()](https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass)
actually inspects the type of a field is to determine if a field is a
class variable as defined in [PEP
526](https://peps.python.org/pep-0526/). It does this by checking if the
type of the field is typing.ClassVar. If a field is a ClassVar, it is
excluded from consideration as a field and is ignored by the dataclass
mechanisms. Such ClassVar pseudo-fields are not returned by the
module-level
[fields()](https://docs.python.org/3/library/dataclasses.html#dataclasses.fields)
function.

In this PR I have changed the documentation to make it a little bit
clearer that not using `ClassVar` makes the code invalid.
2024-03-14 23:18:03 +00:00
Hoël Bagard e944c16c46
[`pycodestyle`] Do not ignore lines before the first logical line in blank lines rules (#10382)
## Summary

Ignoring all lines until the first logical line does not match the
behavior from pycodestyle. This PR therefore removes the `if
state.is_not_first_logical_line` skipping the line check before the
first logical line, and applies it only to `E302`.

For example, in the snippet below a rule violation should be detected on
the second comment and on the import.

```python
# first comment




# second comment




import foo
```

Fixes #10374

## Test Plan

Add test cases, update the snapshots and verify the ecosystem check output
2024-03-14 14:05:24 +05:30
Dhruv Manilawala 5f40371ffc
Use `ExprFString` for `StringLike::FString` variant (#10311)
## Summary

This PR updates the `StringLike::FString` variant to use `ExprFString`
instead of `FStringLiteralElement`.

For context, the reason it used `FStringLiteralElement` is that the node
is actually the string part of an f-string ("foo" in `f"foo{x}"`). But,
this is inconsistent with other variants where the captured value is the
_entire_ string.

This is also problematic w.r.t. implicitly concatenated strings. Any
rules which work with `StringLike::FString` doesn't account for the
string part in an implicitly concatenated f-strings. For example, we
don't flag confusable character in the first part of `"𝐁ad" f"𝐁ad
string"`, but only the second part
(https://play.ruff.rs/16071c4c-a1dd-4920-b56f-e2ce2f69c843).

### Update `PYI053`

_This is included in this PR because otherwise it requires a temporary
workaround to be compatible with the old logic._

This PR also updates the `PYI053` (`string-or-bytes-too-long`) rule for
f-string to consider _all_ the visible characters in a f-string,
including the ones which are implicitly concatenated. This is consistent
with implicitly concatenated strings and bytes.

For example,

```python
def foo(
	# We count all the characters here
    arg1: str = '51 character ' 'stringgggggggggggggggggggggggggggggggg',
	# But not here because of the `{x}` replacement field which _breaks_ them up into two chunks
    arg2: str = f'51 character {x} stringgggggggggggggggggggggggggggggggggggggggggggg',
) -> None: ...
```

This PR fixes it to consider all _visible_ characters inside an f-string
which includes expressions as well.

fixes: #10310 
fixes: #10307 

## Test Plan

Add new test cases and update the snapshots.

## Review

To facilitate the review process, the change have been split into two
commits: one which has the code change while the other has the test
cases and updated snapshots.
2024-03-14 13:30:22 +05:30
boolean f7802ad5de
[`pylint`] Extend docs and test in `invalid-str-return-type` (`E307`) (#10400)
## Summary

Added some docs, and a little of test cases in
`invalid-str-return-type`, mentioned in
https://github.com/astral-sh/ruff/pull/10377#pullrequestreview-1934295027

## Test Plan

On `invalid_return_type_str.py`.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2024-03-14 04:38:30 +00:00
Charlie Marsh 324390607c
[`pylint`] Include builtin warnings in useless-exception-statement (`PLW0133`) (#10394)
## Summary

Closes https://github.com/astral-sh/ruff/issues/10392.
2024-03-13 15:26:11 -04:00
Zanie Blue 7b3ee2daff
Remove `F401` fix for `__init__` imports by default and allow opt-in to unsafe fix (#10365)
Re-implementation of https://github.com/astral-sh/ruff/pull/5845 but
instead of deprecating the option I toggle the default. Now users can
_opt-in_ via the setting which will give them an unsafe fix to remove
the import. Otherwise, we raise violations but do not offer a fix. The
setting is a bit of a misnomer in either case, maybe we'll want to
remove it still someday.

As discussed there, I think the safe fix should be to import it as an
alias. I'm not sure. We need support for offering multiple fixes for
ideal behavior though? I think we should remove the fix entirely and
consider it separately.

Closes https://github.com/astral-sh/ruff/issues/5697
Supersedes https://github.com/astral-sh/ruff/pull/5845

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-03-13 12:58:25 -05:00
Alex Waygood c2e15f38ee
Unify enums used for internal representation of quoting style (#10383) 2024-03-13 17:19:17 +00:00
Charlie Marsh d59433b12e
Avoid removing shadowed imports that point to different symbols (#10387)
This ensures that we don't have incorrect, automated fixes for shadowed
names that actually point to different imports.

See: https://github.com/astral-sh/ruff/issues/10384.
2024-03-13 15:44:28 +00:00
boolean c269c1a706
[`pylint`] Implement `invalid-bool-return-type` (`E304`) (#10377)
## Summary

Implement `E304` in the issue #970. Throws an error when the returning value
of `__bool__` method is not boolean.

Reference: https://pylint.readthedocs.io/en/stable/user_guide/messages/error/invalid-bool-returned.html

## Test Plan

Add test cases and run `cargo test`
2024-03-13 19:43:45 +05:30
Dhruv Manilawala 32d6f84e3d
Add methods to iter over f-string elements (#10309)
## Summary

This PR adds methods on `FString` to iterate over the two different kind
of elements it can have - literals and expressions. This is similar to
the methods we have on `ExprFString`.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-03-13 08:46:55 +00:00
Auguste Lalande 93d582d734
Avoid `TRIO115` if the argument is a variable (#10376)
## Summary

Fix "TRIO115 false positive with with sleep(var) where var starts as 0"
#9935 based on the discussion in the issue.

## Test Plan

Issue code added to fixture
2024-03-13 13:09:18 +05:30
Auguste Lalande 3ed707f245
Spellcheck & grammar (#10375)
## Summary

I used `codespell` and `gramma` to identify mispellings and grammar
errors throughout the codebase and fixed them. I tried not to make any
controversial changes, but feel free to revert as you see fit.
2024-03-13 02:34:23 +00:00
Charlie Marsh c56fb6e15a
Sort hash maps in `Settings` display (#10370)
## Summary

We had a report of a test failure on a specific architecture, and
looking into it, I think the test assumes that the hash keys are
iterated in a specific order. This PR thus adds a variant to our
settings display macro specifically for maps and sets. Like `CacheKey`,
it sorts the keys when printing.

Closes https://github.com/astral-sh/ruff/issues/10359.
2024-03-12 15:59:38 -04:00
Zanie Blue 87afe36c87
Add test case for `F401` in `__init__` files (#10364)
In preparation for https://github.com/astral-sh/ruff/pull/5845
2024-03-12 13:30:17 -05:00
Alex Waygood 704fefc7ab
F821: Fix false negatives in `.py` files when `from __future__ import annotations` is active (#10362) 2024-03-12 17:07:44 +00:00
Auguste Lalande b117f33075
[`pycodestyle`] Implement `blank-line-at-end-of-file` (`W391`) (#10243)
## Summary

Implements the [blank line at end of
file](https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes)
rule (W391) from pycodestyle. Renamed to TooManyNewlinesAtEndOfFile for
clarity.

## Test Plan

New fixtures have been added

Part of #2402
2024-03-11 22:07:59 -04:00
Auguste Lalande c746912b9e
[`pycodestyle`] Implement `redundant-backslash` (`E502`) (#10292)
## Summary

Implements the
[redundant-backslash](https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes)
rule (E502) from pycodestyle.

## Test Plan

New fixture has been added

Part of #2402
2024-03-11 21:15:06 -04:00
Mathieu Kniewallner fc7139d9a5
[`flake8-bandit`]: Implement `S610` rule (#10316)
Part of https://github.com/astral-sh/ruff/issues/1646.

## Summary

Implement `S610` rule from `flake8-bandit`. 

Upstream references:
- Implementation:
https://github.com/PyCQA/bandit/blob/1.7.8/bandit/plugins/django_sql_injection.py#L20-L97
- Test cases:
https://github.com/PyCQA/bandit/blob/1.7.8/examples/django_sql_injection_extra.py
- Test assertion:
https://github.com/PyCQA/bandit/blob/1.7.8/tests/functional/test_functional.py#L517-L524

The implementation in `bandit` targets additional arguments (`params`,
`order_by` and `select_params`) but doesn't seem to do anything with
them in the end, so I did not include them in the implementation.

Note that this rule could be prone to false positives, as ideally we
would want to check if `extra()` is tied to a [Django
queryset](https://docs.djangoproject.com/en/5.0/ref/models/querysets/),
but AFAIK Ruff is not able to resolve classes outside of the current
module.

## Test Plan

Snapshot tests
2024-03-11 20:22:02 -04:00
Charlie Marsh f8f56186b3
[`pylint`] Avoid false-positive slot non-assignment for `__dict__` (`PLE0237`) (#10348)
Closes https://github.com/astral-sh/ruff/issues/10306.
2024-03-11 18:48:56 -04:00
Charlie Marsh 02fc521369
Wrap expressions in parentheses when negating (#10346)
## Summary

When negating an expression like `a or b`, we need to wrap it in
parentheses, e.g., `not (a or b)` instead of `not a or b`, due to
operator precedence.

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

## Test Plan

`cargo test`
2024-03-11 18:20:55 -04:00
Alex Waygood 4b0666919b
F821, F822: fix false positive for `.pyi` files; add more test coverage for `.pyi` files (#10341)
This PR fixes the following false positive in a `.pyi` stub file:

```py
x: int
y = x  # F821 currently emitted here, but shouldn't be in a stub file
```

In a `.py` file, this is invalid regardless of whether `from __future__ import annotations` is enabled or not. In a `.pyi` stub file, however, it's always valid, as an annotation counts as a binding in a stub file even if no value is assigned to the variable.

I also added more test coverage for `.pyi` stub files in various edge cases where ruff's behaviour is currently correct, but where `.pyi` stub files do slightly different things to `.py` files.
2024-03-11 22:15:24 +00:00
Hoël Bagard 8d73866f70
[`pycodestyle`] Do not trigger `E225` and `E275` when the next token is a ')' (#10315)
## Summary

Fixes #10295.

`E225` (`Missing whitespace around operator`) and `E275` (`Missing
whitespace after keyword`) try to add a white space even when the next
character is a `)` (which is a syntax error in most cases, the
exceptions already being handled). This causes `E202` (`Whitespace
before close bracket`) to try to remove the added whitespace, resulting
in an infinite loop when `E225`/`E275` re-add it.
This PR adds an exception in `E225` and `E275` to not trigger in case
the next token is a `)`. It is a bit simplistic, but it solves the
example given in the issue without introducing a change in behavior
(according to the fixtures).

## Test Plan

`cargo test` and the `ruff-ecosystem` check were used to check that the
PR's changes do not have side-effects.
A new fixture was added to check that running the 3 rules on the example
given in the issue does not cause ruff to fail to converge.
2024-03-11 21:23:18 +00:00
Mathieu Kniewallner bc693ea13a
[`flake8-bandit`] Implement upstream updates for `S311`, `S324` and `S605` (#10313)
## Summary

Pick up updates made in latest
[releases](https://github.com/PyCQA/bandit/releases) of `bandit`:
- `S311`: https://github.com/PyCQA/bandit/pull/940 and
https://github.com/PyCQA/bandit/pull/1096
- `S324`: https://github.com/PyCQA/bandit/pull/1018
- `S605`: https://github.com/PyCQA/bandit/pull/1116

## Test Plan

Snapshot tests
2024-03-11 21:07:58 +00:00
Charlie Marsh a892fc755d
Bump version to v0.3.2 (#10304) 2024-03-09 00:24:22 +00:00
Gautier Moin a067d87ccc
Fix incorrect `Parameter` range for `*args` and `**kwargs` (#10283)
## Summary

Fix #10282 

This PR updates the Python grammar to include the `*` character in
`*args` `**kwargs` in the range of the `Parameter`
```
def f(*args, **kwargs): pass
#      ~~~~    ~~~~~~    <-- range before the PR
#     ^^^^^  ^^^^^^^^    <-- range after
```

The invalid syntax `def f(*, **kwargs): ...` is also now correctly
reported.

## Test Plan

Test cases were added to `function.rs`.
2024-03-08 18:57:49 -05:00
Alex Waygood 1d97f27335
Start tracking quoting style in the AST (#10298)
This PR modifies our AST so that nodes for string literals, bytes literals and f-strings all retain the following information:
- The quoting style used (double or single quotes)
- Whether the string is triple-quoted or not
- Whether the string is raw or not

This PR is a followup to #10256. Like with that PR, this PR does not, in itself, fix any bugs. However, it means that we will have the necessary information to preserve quoting style and rawness of strings in the `ExprGenerator` in a followup PR, which will allow us to provide a fix for https://github.com/astral-sh/ruff/issues/7799.

The information is recorded on the AST nodes using a bitflag field on each node, similarly to how we recorded the information on `Tok::String`, `Tok::FStringStart` and `Tok::FStringMiddle` tokens in #10298. Rather than reusing the bitflag I used for the tokens, however, I decided to create a custom bitflag for each AST node.

Using different bitflags for each node allows us to make invalid states unrepresentable: it is valid to set a `u` prefix on a string literal, but not on a bytes literal or an f-string. It also allows us to have better debug representations for each AST node modified in this PR.
2024-03-08 19:11:47 +00:00
Alex Waygood c504d7ab11
Track quoting style in the tokenizer (#10256) 2024-03-08 08:40:06 +00:00
Tom Kuson 72c9f7e4c9
Include actual conditions in E712 diagnostics (#10254)
## Summary

Changes the generic recommendation to replace

```python
if foo == True: ...
```

with `if cond:` to `if foo:`.

Still uses a generic message for compound comparisons as a specific
message starts to become confusing. For example,

```python
if foo == True != False: ...
```

produces two recommendations, one of which would recommend `if True:`,
which is confusing.

Resolves [recommendation in a previous
PR](https://github.com/astral-sh/ruff/pull/8613/files#r1514915070).

## Test Plan

`cargo nextest run`
2024-03-08 01:20:56 +00:00
Charlie Marsh 57be3fce90
Treat `typing.Annotated` subscripts as type definitions (#10285)
## Summary

I think this code has existed since the start of `typing.Annotated`
support (https://github.com/astral-sh/ruff/pull/333), and was then
overlooked over a series of refactors.

Closes https://github.com/astral-sh/ruff/issues/10279.
2024-03-07 19:51:54 -05:00
Samuel Cormier-Iijima 7b4a73d421
Fix E203 false positive for slices in format strings (#10280)
## Summary

The code later in this file that checks for slices relies on the stack
of brackets to determine the position. I'm not sure why format strings
were being excluded from this, but the tests still pass with these match
guards removed.

Closes #10278

## Test Plan

~Still needs a test.~ Test case added for this example.
2024-03-07 17:09:05 -05:00
Charlie Marsh 91af5a4b74
[`pyupgrade`] Allow fixes for f-string rule regardless of line length (`UP032`) (#10263)
## Summary

This is a follow-up to https://github.com/astral-sh/ruff/pull/10238 to
offer fixes for the f-string rule regardless of the line length of the
resulting fix. To quote Alex in the linked PR:

> Yes, from the user's perspective I'd rather have a fix that may lead
to line length issues than have to fix them myself :-) Cleaning up line
lengths is easier than changing from `"".format()` to `f""`

I agree with this position, which is that if we're going to offer a
diagnostic, we should really be offering the user the ability to fix it
-- otherwise, we're just inconveniencing them.
2024-03-07 08:59:29 -05:00
Charlie Marsh 461cdad53a
Avoid repeating function calls in f-string conversions (#10265)
## Summary

Given a format string like `"{x} {x}".format(x=foo())`, we should avoid
converting to an f-string, since doing so would require repeating the
function call (`f"{foo()} {foo()}"`), which could introduce side
effects.

Closes https://github.com/astral-sh/ruff/issues/10258.
2024-03-06 23:33:19 -05:00
Charlie Marsh ea79f616bc
Bump version to v0.3.1 (#10252) 2024-03-06 19:59:04 +00:00
Tom Kuson f999b1b617
Tweak `E712` docs (#8613)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-03-06 17:54:29 +00:00
Eero Vaher cbd927f346
Make rule PT012 example clearer (#10248) 2024-03-06 15:47:14 +00:00
Micha Reiser 6159a8e532
[`pyupgrade`] Generate diagnostic for all valid f-string conversions regardless of line-length (`UP032`) (#10238)
## Summary

Fixes https://github.com/astral-sh/ruff/issues/10235

This PR changes `UP032` to flag all `"".format` calls that can
technically be rewritten to an f-string, even if rewritting it to an
fstring, at least automatically, exceeds the line length (or increases
the amount by which it goes over the line length).

I looked at the Git history to understand whether the check prevents
some false positives (reported by an issue), but i haven't found a
compelling reason to limit the rule to only flag format calls that stay
in the line length limit:

* https://github.com/astral-sh/ruff/pull/7818 Changed the heuristic to
determine if the fix fits to address
https://github.com/astral-sh/ruff/discussions/7810
* https://github.com/astral-sh/ruff/pull/1905 first version of the rule 


I did take a look at pyupgrade and couldn't find a similar check, at
least not in the rule code (maybe it's checked somewhere else?)
https://github.com/asottile/pyupgrade/blob/main/pyupgrade/_plugins/fstrings.py


## Breaking Change?

This could be seen as a breaking change according to ruff's [versioning
policy](https://docs.astral.sh/ruff/versioning/):

> The behavior of a stable rule is changed
  
  * The scope of a stable rule is significantly increased
  * The intent of the rule changes
* Does not include bug fixes that follow the original intent of the rule

It does increase the scope of the rule, but it is in the original intent
of the rule (so it's not).

## Test Plan

See changed test output
2024-03-06 09:58:20 +01:00
Micha Reiser 8ea5b08700
refactor: Use `QualifiedName` for `Imported::call_path` (#10214)
## Summary

When you try to remove an internal representation leaking into another
type and end up rewriting a simple version of `smallvec`.

The goal of this PR is to replace the `Box<[&'a str]>` with
`Box<QualifiedName>` to avoid that the internal `QualifiedName`
representation leaks (and it gives us a nicer API too). However, doing
this when `QualifiedName` uses `SmallVec` internally gives us all sort
of funny lifetime errors. I was lost but @BurntSushi came to rescue me.
He figured out that `smallvec` has a variance problem which is already
tracked in https://github.com/servo/rust-smallvec/issues/146

To fix the variants problem, I could use the smallvec-2-alpha-4 or
implement our own smallvec. I went with implementing our own small vec
for this specific problem. It obviously isn't as sophisticated as
smallvec (only uses safe code), e.g. it doesn't perform any size
optimizations, but it does its job.

Other changes:

* Removed `Imported::qualified_name` (the version that returns a
`String`). This can be replaced by calling `ToString` on the qualified
name.
* Renamed `Imported::call_path` to `qualified_name` and changed its
return type to `&QualifiedName`.
* Renamed `QualifiedName::imported` to `user_defined` which is the more
common term when talking about builtins vs the rest/user defined
functions.


## Test plan

`cargo test`
2024-03-06 09:55:59 +01:00
Micha Reiser af6ea2f5e4
[`pycodestyle`]: Make blank lines in typing stub files optional (`E3*`) (#10098)
## Summary

Fixes https://github.com/astral-sh/ruff/issues/10039

The [recommendation for typing stub
files](https://typing.readthedocs.io/en/latest/source/stubs.html#blank-lines)
is to use **one** blank line to group related definitions and
otherwise omit blank lines. 

The newly added blank line rules (`E3*`) didn't account for typing stub
files and enforced two empty lines at the top level and one empty line
otherwise, making it impossible to group related definitions.

This PR implements the `E3*` rules to:

* Not enforce blank lines. The use of blank lines in typing definitions
is entirely up to the user.
* Allow at most one empty line, including between top level statements. 

## Test Plan

Added unit tests (It may look odd that many snapshots are empty but the
point is that the rule should no longer emit diagnostics)
2024-03-05 12:48:50 +01:00
Micha Reiser 46ab9dec18
[`pycodestyle`] Respect `isort` settings in blank line rules (`E3*`) (#10096)
## Summary

This PR changes the `E3*` rules to respect the `isort`
`lines-after-imports` and `lines-between-types` settings. Specifically,
the following rules required changing

* `TooManyBlannkLines` : Respects both settings.
* `BlankLinesTopLevel`: Respects `lines-after-imports`. Doesn't need to
respect `lines-between-types` because it only applies to classes and
functions


The downside of this approach is that `isort` and the blank line rules
emit a diagnostic when there are too many blank lines. The fixes aren't
identical, the blank line is less opinionated, but blank lines accepts
the fix of `isort`.

<details>
	<summary>Outdated approach</summary>
Fixes
https://github.com/astral-sh/ruff/issues/10077#issuecomment-1961266981

This PR changes the blank line rules to not enforce the number of blank
lines after imports (top-level) if isort is enabled and leave it to
isort to enforce the right number of lines (depends on the
`isort.lines-after-imports` and `isort.lines-between-types` settings).

The reason to give `isort` precedence over the blank line rules is that
they are configurable. Users that always want to blank lines after
imports can use `isort.lines-after-imports=2` to enforce that
(specifically for imports).

This PR does not fix the incompatibility with the formatter in pyi files
that only uses 0 to 1 blank lines. I'll address this separately.

</details>

## Review
The first commit is a small refactor that simplified implementing the
fix (and makes it easier to reason about what's mutable and what's not).


## Test Plan

I added a new test and verified that it fails with an error that the fix
never converges. I verified the snapshot output after implementing the
fix.

---------

Co-authored-by: Hoël Bagard <34478245+hoel-bagard@users.noreply.github.com>
2024-03-05 10:09:15 +00:00
ooo oo 72599dafb6
docs: fix a rustdoc typo in C409 rule (#10233) 2024-03-05 02:33:08 +00:00
Micha Reiser 184241f99a
Remove `Expr` postfix from `ExprNamed`, `ExprIf`, and `ExprGenerator` (#10229)
The expression types in our AST are called `ExprYield`, `ExprAwait`,
`ExprStringLiteral` etc, except `ExprNamedExpr`, `ExprIfExpr` and
`ExprGenratorExpr`. This seems to align with [Python AST's
naming](https://docs.python.org/3/library/ast.html) but feels
inconsistent and excessive.

This PR removes the `Expr` postfix from `ExprNamedExpr`, `ExprIfExpr`,
and `ExprGeneratorExpr`.
2024-03-04 12:55:01 +01:00
Alex Waygood 8b749e1d4d
Make `--config` and `--isolated` global flags (#10150) 2024-03-04 11:19:40 +00:00
Steve C 8dde81a905
[`pylint`] - add fix for unary expressions in `PLC2801` (#9587)
## Summary

Closes #9572

Don't go easy on this review!

## Test Plan

`cargo test`
2024-03-04 11:25:17 +01:00
Micha Reiser a6d892b1f4
Split `CallPath` into `QualifiedName` and `UnqualifiedName` (#10210)
## Summary

Charlie can probably explain this better than I but it turns out,
`CallPath` is used for two different things:

* To represent unqualified names like `version` where `version` can be a
local variable or imported (e.g. `from sys import version` where the
full qualified name is `sys.version`)
* To represent resolved, full qualified names

This PR splits `CallPath` into two types to make this destinction clear.

> Note: I haven't renamed all `call_path` variables to `qualified_name`
or `unqualified_name`. I can do that if that's welcomed but I first want
to get feedback on the approach and naming overall.

## Test Plan

`cargo test`
2024-03-04 09:06:51 +00:00
Micha Reiser 64f66cd8fe
Refine SemanticModel lifetime bounds (#10221)
## Summary

Corrects/refines some semantic model and related lifetime bounds.

## Test Plan

`cargo check`
2024-03-04 09:21:13 +01:00
Gautier Moin 4eac9baf43
[`pep8_naming`] Add fixes `N804` and `N805` (#10215)
## Summary

This PR fixes for `invalid-first-argument` rules.
The fixes rename the first argument of methods and class methods to the
valid one. References to this argument are also renamed.
Fixes are skipped when another argument is named as the valid first
argument.
The fix is marked as unsafe due

The functions for the `N804` and `N805` rules are now merged, as they
only differ by the name of the valid first argument.
The rules were moved from the AST iteration to the deferred scopes to be
in the function scope while creating the fix.

## Test Plan

`cargo test`
2024-03-04 02:22:54 +00:00
Charlie Marsh 737fcfd79e
Remove trailing space from `CapWords` message (#10220) 2024-03-04 01:54:53 +00:00
Charlie Marsh 84bf333031
Accept a PEP 440 version specifier for required-version (#10216)
## Summary

Allows `required-version` to be set with a version specifier, like
`>=0.3.1`.

If a single version is provided, falls back to assuming `==0.3.1`, for
backwards compatibility.

Closes https://github.com/astral-sh/ruff/issues/10192.
2024-03-03 18:43:49 -05:00
Micha Reiser db25a563f7
Remove unneeded lifetime bounds (#10213)
## Summary

This PR removes the unneeded lifetime `'b` from many of our `Visitor`
implementations.

The lifetime is unneeded because it is only constraint by `'a`, so we
can use `'a` directly.

## Test Plan

`cargo build`
2024-03-03 18:12:11 +00:00
Micha Reiser e725b6fdaf
CallPath newtype wrapper (#10201)
## Summary

This PR changes the `CallPath` type alias to a newtype wrapper. 

A newtype wrapper allows us to limit the API and to experiment with
alternative ways to implement matching on `CallPath`s.



## Test Plan

`cargo test`
2024-03-03 16:54:24 +01:00
Charlie Marsh ba7f6783e9
Avoid false-positives for parens-on-raise with futures.exception() (#10206)
## Summary

As a heuristic, we now ignore function calls that "look like" method
calls (e.g., `future.exception()`).

Closes https://github.com/astral-sh/ruff/issues/10205.
2024-03-03 00:28:51 +00:00
Charlie Marsh 7515196245
Respect external codes in file-level exemptions (#10203)
We shouldn't warn when an "external" code is used in a file-level
exemption.

Closes https://github.com/astral-sh/ruff/issues/10202.
2024-03-03 00:20:36 +00:00
Jeremy Hiatt c007b175ba
Check for use of `debugpy` and `ptvsd` debug modules (#10177) (#10194)
## Summary

This addresses https://github.com/astral-sh/ruff/issues/10177.

## Test Plan

I added additional lines to the existing test file for T100.
2024-03-01 23:02:44 -05:00
trag1c 0cd3b07efa
Removed unused variable in `TRY300`'s example (#10190)
<!--
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

Removes the unnecessary `exc` variable in `TRY300`'s docs example.

## Test Plan
```
python scripts/generate_mkdocs.py; mkdocs serve -f mkdocs.public.yml
```
2024-03-01 18:50:52 -05:00
Meheret c59d82a22e
CLI: Color entire line in Diffs (#10183) 2024-03-01 13:53:45 +01:00
Greenstar 8b5daaec7d
Fix broken documentation links affected by namespace changes in lint rules (#10182) 2024-03-01 12:35:29 +01:00
Hoël Bagard b82e87790e
Fix E301 not triggering on decorated methods. (#10117)
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-03-01 09:30:53 +00:00
Meheret 56d445add9
Colorize the output of ruff format --diff (#10110)
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-03-01 08:55:30 +00:00
Jane Lewis 8ecdf5369a
Fix RUF028 not allowing `# fmt: skip` on match cases (#10178)
## Summary

Fixes #10174 by allowing match cases to be enclosing nodes for
suppression comments. `else/elif` clauses are now also allowed to be
enclosing nodes.

## Test Plan
I've added the offending code from the original issue to the `RUF028`
snapshot test, and I've also expanded it to test the allowed `else/elif`
clause.
2024-03-01 00:36:23 -08:00
Michael Merickel c9931a548f
Implement isort's `default-section` setting (#10149)
## Summary

This fixes https://github.com/astral-sh/ruff/issues/7868.

Support isort's `default-section` feature which allows any imports that
match sections that are not in `section-order` to be mapped to a
specifically named section.


https://pycqa.github.io/isort/docs/configuration/options.html#default-section

This has a few implications:

- It is no longer required that all known sections are defined in
`section-order`.
- This is technically a bw-incompat change because currently if folks
define custom groups, and do not define a `section-order`, the code used
to add all known sections to `section-order` while emitting warnings.
**However, when this happened, users would be seeing warnings so I do
not think it should count as a bw-incompat change.**

## Test Plan

- Added a new test.
- Did not break any existing tests.

Finally, I ran the following config against Pyramid's complex codebase
that was previously using isort and this change worked there.

### pyramid's previous isort config


5f7e286b06/pyproject.toml (L22-L37)

```toml
[tool.isort]
profile = "black"
multi_line_output = 3
src_paths = ["src", "tests"]
skip_glob = ["docs/*"]
include_trailing_comma = true
force_grid_wrap = false
combine_as_imports = true
line_length = 79
force_sort_within_sections = true
no_lines_before = "THIRDPARTY"
sections = "FUTURE,THIRDPARTY,FIRSTPARTY,LOCALFOLDER"
default_section = "THIRDPARTY"
known_first_party = "pyramid"
```

### tested with ruff isort config

```toml
[tool.ruff.lint.isort]
case-sensitive = true
combine-as-imports = true
force-sort-within-sections = true
section-order = [
    "future",
    "third-party",
    "first-party",
    "local-folder",
]
default-section = "third-party"
known-first-party = [
    "pyramid",
]
```
2024-03-01 03:32:03 +00:00
Mikko Leppänen 8e0a70cfa3
[`pylint`] Implement `useless-exception-statement` (`W0133`) (#10176)
## Summary

This review contains a new rule for handling `useless exception
statements` (`PLW0133`). Is it based on the following pylint's rule:
[W0133](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/pointless-exception-statement.html)


Note: this rule does not cover the case if an error is a custom
exception class.

See: [Rule request](https://github.com/astral-sh/ruff/issues/10145)

## Test Plan

```bash
cargo test & manually
```
2024-02-29 21:37:16 -05:00
Shaygan Hooshyari cbafae022d
[`pylint`] Implement `singledispatch-method` (`E1519`) (#10140)
Implementing the rule 

https://pylint.readthedocs.io/en/stable/user_guide/messages/error/singledispatch-method.html#singledispatch-method-e1519

Implementation simply checks the function type and name of the
decorators.
2024-03-01 02:22:30 +00:00
Micha Reiser b53118ed00
Bump version to v0.3.0 (#10151)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-02-29 16:05:20 +01:00
Justin Sexton c73c497477
[`pydocstyle`] Trim whitespace when removing blank lines after section (`D413`) (#10162)
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-02-29 13:29:40 +00:00
Jane Lewis 0293908b71
Implement RUF028 to detect useless formatter suppression comments (#9899)
<!--
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?
-->
Fixes #6611

## Summary

This lint rule spots comments that are _intended_ to suppress or enable
the formatter, but will be ignored by the Ruff formatter.

We borrow some functions the formatter uses for determining comment
placement / putting them in context within an AST.

The analysis function uses an AST visitor to visit each comment and
attach it to the AST. It then uses that context to check:
1. Is this comment in an expression?
2. Does this comment have bad placement? (e.g. a `# fmt: skip` above a
function instead of at the end of a line)
3. Is this comment redundant?
4. Does this comment actually suppress any code?
5. Does this comment have ambiguous placement? (e.g. a `# fmt: off`
above an `else:` block)

If any of these are true, a violation is thrown. The reported reason
depends on the order of the above check-list: in other words, a `# fmt:
skip` comment on its own line within a list expression will be reported
as being in an expression, since that reason takes priority.

The lint suggests removing the comment as an unsafe fix, regardless of
the reason.

## Test Plan

A snapshot test has been created.
2024-02-28 19:21:06 +00:00
Philipp Thiel 36bc725eaa
[`flake8-bugbear`] Avoid adding default initializers to stubs (`B006`) (#10152)
## Summary

Adapts the fix for rule B006 to no longer modify the body of function
stubs, while retaining the change in method signature.

## Test Plan

The existing tests for B006 were adapted to reflect this change in
behavior.

## Relevant issue

https://github.com/astral-sh/ruff/issues/10083
2024-02-28 18:19:36 +00:00
Charlie Marsh a1905172a8
[`flake8-bandit`] Remove `suspicious-lxml-import` (`S410`) (#10154)
## Summary

The `lxml` library has been modified to address known vulnerabilities
and unsafe defaults. As such, the `defusedxml`
library is no longer necessary, `defusedxml` has deprecated its `lxml`
module.

Closes https://github.com/astral-sh/ruff/issues/10030.
2024-02-28 12:38:55 -05:00
Micha Reiser 1791e7d73b
Limit `isort.lines-after-imports` to 1 for stub files (#9971) 2024-02-28 17:36:51 +01:00
Robin Caloudis a1e8784207
[`ruff`] Expand rule for `list(iterable).pop(0)` idiom (`RUF015`) (#10148)
## Summary

Currently, rule `RUF015` is not able to detect the usage of
`list(iterable).pop(0)` falling under the category of an _unnecessary
iterable allocation for accessing the first element_. This PR wants to
change that. See the underlying issue for more details.

* Provide extension to detect `list(iterable).pop(0)`, but not
`list(iterable).pop(i)` where i > 1
* Update corresponding doc

## Test Plan

* `RUF015.py` and the corresponding snap file were extended such that
their correspond to the new behaviour

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

--- 

PS: I've only been working on this ticket as I haven't seen any activity
from issue assignee @rmad17, neither in this repo nor in a fork. I hope
I interpreted his inactivity correctly. Didn't mean to steal his chance.
Since I stumbled across the underlying problem myself, I wanted to offer
a solution as soon as possible.
2024-02-28 00:24:28 +00:00
Micha Reiser 15b87ea8be
E203: Don't warn about single whitespace before tuple , (#10094) 2024-02-26 18:22:35 +01:00
Micha Reiser 77c5561646
Add `parenthesized` flag to `ExprTuple` and `ExprGenerator` (#9614) 2024-02-26 15:35:20 +00:00
Robin Caloudis fc8738f52a
[`ruff`] Avoid f-string false positives in `gettext` calls (`RUF027`) (#10118)
## Summary

It is a convention to use the `_()` alias for `gettext()`. We want to
avoid
statement expressions and assignments related to aliases of the gettext
API.
See https://docs.python.org/3/library/gettext.html for details. When one
uses `_() to mark a string for translation, the tools look for these
markers
and replace the original string with its translated counterpart. If the
string contains variable placeholders or formatting, it can complicate
the
translation process, lead to errors or incorrect translations.

## Test Plan

* Test file `RUF027_1.py` was extended such that the test reproduces the
false-positive

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

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-02-25 18:17:56 -05:00
Micha Reiser a284c711bf
Refactor trailing comma rule into explicit check and state update code (#10100) 2024-02-23 17:56:05 +01:00
Charlie Marsh 946028e358
Respect runtime-required decorators for function signatures (#10091)
## Summary

The original implementation of this applied the runtime-required context
to definitions _within_ the function, but not the signature itself. (We
had test coverage; the snapshot was just correctly showing the wrong
outcome.)

Closes https://github.com/astral-sh/ruff/issues/10089.
2024-02-23 03:33:08 +00:00
Charlie Marsh 6fe15e7289
Allow © in copyright notices (#10065)
Closes https://github.com/astral-sh/ruff/issues/10061.
2024-02-22 12:44:22 -05:00
Seo Sanghyeon 7d9ce5049a
PLR0203: Delete entire statement, including semicolons (#10074)
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-02-22 16:03:00 +00:00
Arjun Munji 175c266de3
Omit repeated equality comparison for sys (#10054)
## Summary
Update PLR1714 to ignore `sys.platform` and `sys.version` checks. 
I'm not sure if these checks or if we need to add more. Please advise.

Fixes #10017

## Test Plan
Added a new test case and ran `cargo nextest run`
2024-02-20 19:03:32 +00:00
Charlie Marsh 4997c681f1
[`pycodestyle`] Allow `os.environ` modifications between imports (`E402`) (#10066)
## Summary

Allows, e.g.:

```python
import os

os.environ["WORLD_SIZE"] = "1"
os.putenv("CUDA_VISIBLE_DEVICES", "4")

import torch
```

For now, this is only allowed in preview.

Closes https://github.com/astral-sh/ruff/issues/10059
2024-02-20 13:24:27 -05:00
Seo Sanghyeon 7eafba2a4d
[`pyupgrade`] Detect literals with unary operators (`UP018`) (#10060)
Fix #10029.
2024-02-20 18:21:06 +00:00
Ottavio Hartman 0f70c99c42
feat(ERA001): detect single-line code for try:, except:, etc. (#10057)
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-02-20 18:40:18 +01:00
Ottavio Hartman 0d363ab239
fix(ERA001): detect commented out `case` statements, add more one-line support (#10055)
## Summary

Closes #10031 

- Detect commented out `case` statements. Playground repro:
https://play.ruff.rs/5a305aa9-6e5c-4fa4-999a-8fc427ab9a23
- Add more support for one-line commented out code.

## Test Plan

Unit tested and tested with
```sh
cargo run -p ruff -- check crates/ruff_linter/resources/test/fixtures/eradicate/ERA001.py --no-cache --preview --select ERA001
```

TODO:
- [x] `cargo insta test`
2024-02-19 22:56:42 -05:00
Daniël van Noord 68b8abf9c6
[`pylint`] Add PLE1141 `DictIterMissingItems` (#9845)
## Summary

References https://github.com/astral-sh/ruff/issues/970.

Implements
[`dict-iter-missing-items`](https://pylint.readthedocs.io/en/latest/user_guide/messages/error/dict-iter-missing-items.html).

Took the tests from "upstream"
[here](https://github.com/DanielNoord/pylint/blob/main/tests/functional/d/dict_iter_missing_items.py).

~I wasn't able to implement code for one false positive, but it is
pretty estoric: https://github.com/pylint-dev/pylint/issues/3283. I
would personally argue that adding this check as preview rule without
supporting this specific use case is fine. I did add a "test" for it.~
This was implemented.

## Test Plan

Followed the Contributing guide to create tests, hopefully I didn't miss
any.
Also ran CI on my own fork and seemed to be all okay 😄 

~Edit: the ecosystem check seems a bit all over the place? 😅~ All good.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-02-19 19:56:55 +05:30
Seo Sanghyeon 1c8851e5fb
Do multiline string test for W293 too (#10049) 2024-02-19 11:58:56 +00:00
Charlie Marsh e1928be36e
Allow boolean positionals in `__post_init__` (#10027)
Closes https://github.com/astral-sh/ruff/issues/10011.
2024-02-18 15:03:17 +00:00
Charlie Marsh 235cfb7976
Bump version to v0.2.2 (#10018) 2024-02-17 22:15:04 +00:00
Dhruv Manilawala 91ae81b565
Move `RUF001`, `RUF002` to AST checker (#9993)
## Summary

Part of #7595 

This PR moves the `RUF001` and `RUF002` rules to the AST checker. This
removes the use of docstring detection from these rules.

## Test Plan

As this is just a refactor, make sure existing test cases pass.
2024-02-17 17:01:31 +00:00
Adam Kuhn d46c5d8ac8
docs: Formatter compatibility warning for D207 and D300 (#10007)
- Update docs to mention formatter compatibility interactions for
under-indentation (D207) and triple-single-quotes (D300)
- Changes verified locally with mkdocs
- Closes: https://github.com/astral-sh/ruff/issues/9675
2024-02-17 07:37:38 -05:00
Jane Lewis 20217e9bbd
Fix panic on RUF027 (#9990)
## Summary

Fixes #9895 

The cause for this panic came from an offset error in the code. When
analyzing a hypothetical f-string, we attempt to re-parse it as an
f-string, and use the AST data to determine, among other things, whether
the format specifiers are correct. To determine the 'correctness' of a
format specifier, we actually have to re-parse the format specifier, and
this is where the issue lies. To get the source text for the specifier,
we were taking a slice from the original file source text... even though
the AST data for the specifier belongs to the standalone parsed f-string
expression, meaning that the ranges are going to be way off. In a file
with Unicode, this can cause panics if the slice is inside a char
boundary.

To fix this, we now slice from the temporary source we created earlier
to parse the literal as an f-string.

## Test Plan

The RUF027 snapshot test was amended to include a string with format
specifiers which we _should_ be calling out. This is to ensure we do
slice format specifiers from the source text correctly.
2024-02-16 20:04:39 +00:00
Adrien Ball c3bba54b6b
Fix SIM113 false positive with async for loops (#9996)
## Summary
Ignore `async for` loops when checking the SIM113 rule.

Closes #9995 

## Test Plan
A new test case was added to SIM113.py with an async for loop.
2024-02-15 22:40:01 -05:00
Charlie Marsh f40e012b4e
Use name directly in RUF006 (#9979) 2024-02-14 00:00:47 +00:00
Asger Hautop Drewsen 3e9d761b13
Expand `asyncio-dangling-task` (`RUF006`) to include `new_event_loop` (#9976)
## Summary

Fixes #9974

## Test Plan

I added some new test cases.
2024-02-13 18:28:06 +00:00
Micha Reiser 6380c90031
Run isort CRLF tests (#9970) 2024-02-13 09:25:22 +01:00
Charlie Marsh d96a0dbe57
Respect tuple assignments in typing analyzer (#9969)
## Summary

Just addressing some discrepancies between the analyzers like `is_dict`
and the logic that's matured in `find_binding_value`.
2024-02-13 05:02:52 +00:00
Dhruv Manilawala 180920fdd9
Make semantic model aware of docstring (#9960)
## Summary

This PR introduces a new semantic model flag `DOCSTRING` which suggests
that the model is currently in a module / class / function docstring.
This is the first step in eliminating the docstring detection state
machine which is prone to bugs as stated in #7595.

## Test Plan

~TODO: Is there a way to add a test case for this?~

I tested this using the following code snippet and adding a print
statement in the `string_like` analyzer to print if we're currently in a
docstring or not.

<details><summary>Test code snippet:</summary>
<p>

```python
"Docstring" ", still a docstring"
"Not a docstring"


def foo():
    "Docstring"
    "Not a docstring"
    if foo:
        "Not a docstring"
        pass


class Foo:
    "Docstring"
    "Not a docstring"

    foo: int
    "Unofficial variable docstring"

    def method():
        "Docstring"
        "Not a docstring"
        pass


def bar():
    "Not a docstring".strip()


def baz():
    _something_else = 1
    """Not a docstring"""
```

</p>
</details>
2024-02-13 04:26:08 +00:00
Aleksei Latyshev dd0ba16a79
[`refurb`] Implement `readlines_in_for` lint (FURB129) (#9880)
## Summary
Implement [implicit readlines
(FURB129)](https://github.com/dosisod/refurb/blob/master/refurb/checks/iterable/implicit_readlines.py)
lint.

## Notes
I need a help/an opinion about suggested implementations.

This implementation differs from the original one from `refurb` in the
following way. This implementation checks syntactically the call of the
method with the name `readlines()` inside `for` {loop|generator
expression}. The implementation from refurb also
[checks](https://github.com/dosisod/refurb/blob/master/refurb/checks/iterable/implicit_readlines.py#L43)
that callee is a variable with a type `io.TextIOWrapper` or
`io.BufferedReader`.

- I do not see a simple way to implement the same logic.
- The best I can have is something like
```rust
checker.semantic().binding(checker.semantic().resolve_name(attr_expr.value.as_name_expr()?)?).statement(checker.semantic())
```
and analyze cases. But this will be not about types, but about guessing
the type by assignment (or with) expression.
- Also this logic has several false negatives, when the callee is not a
variable, but the result of function call (e.g. `open(...)`).
- On the other side, maybe it is good to lint this on other things,
where this suggestion is not safe, and push the developers to change
their interfaces to be less surprising, comparing with the standard
library.
- Anyway while the current implementation has false-positives (I
mentioned some of them in the test) I marked the fixes to be unsafe.
2024-02-12 22:28:35 -05:00
Charlie Marsh 609d0a9a65
Remove symbol from type-matching API (#9968)
## Summary

These should be no-op refactors to remove some redundant data from the
type analysis APIs.
2024-02-12 20:57:19 -05:00
Auguste Lalande 8fba97f72f
`PLR2004`: Accept 0.0 and 1.0 as common magic values (#9964)
## Summary

Accept 0.0 and 1.0 as common magic values. This is in line with the
pylint behaviour, and I think makes sense conceptually.


## Test Plan

Test cases were added to
`crates/ruff_linter/resources/test/fixtures/pylint/magic_value_comparison.py`
2024-02-13 01:21:06 +00:00
Charlie Marsh 5bc0d9c324
Add a binding kind for comprehension targets (#9967)
## Summary

I was surprised to learn that we treat `x` in `[_ for x in y]` as an
"assignment" binding kind, rather than a dedicated comprehension
variable.
2024-02-12 20:09:39 -05:00
Hashem cf77eeb913
unused_imports/F401: Explain when imports are preserved (#9963)
The docs previously mentioned an irrelevant config option, but were
missing a link to the relevant `ignore-init-module-imports` config
option which _is_ actually used.

Additionally, this commit adds a link to the documentation to explain
the conventions around a module interface which includes using a
redundant import alias to preserve an unused import.

(noticed this while filing  #9962)
2024-02-12 19:07:20 -05:00
Dhruv Manilawala 3f4dd01e7a
Rename semantic model flag to `MODULE_DOCSTRING_BOUNDARY` (#9959)
## Summary

This PR renames the semantic model flag `MODULE_DOCSTRING` to
`MODULE_DOCSTRING_BOUNDARY`. The main reason is for readability and for
the new semantic model flag `DOCSTRING` which tracks that the model is
in a module / class / function docstring.

I got confused earlier with the name until I looked at the use case and
it seems that the `_BOUNDARY` prefix is more appropriate for the
use-case and is consistent with other flags.
2024-02-13 00:47:12 +05:30
Charlie Marsh ab2253db03
[`pylint`] Avoid suggesting set rewrites for non-hashable types (#9956)
## Summary

Ensures that `x in [y, z]` does not trigger in `x`, `y`, or `z` are
known _not_ to be hashable.

Closes https://github.com/astral-sh/ruff/issues/9928.
2024-02-12 13:05:54 -05:00
Charlie Marsh 0304623878
[`perflint`] Catch a wider range of mutations in `PERF101` (#9955)
## Summary

This PR ensures that if a list `x` is modified within a `for` loop, we
avoid flagging `list(x)` as unnecessary. Previously, we only detected
calls to exactly `.append`, and they couldn't be nested within other
statements.

Closes https://github.com/astral-sh/ruff/issues/9925.
2024-02-12 12:17:55 -05:00
Charlie Marsh e2785f3fb6
[`flake8-pyi`] Ignore 'unused' private type dicts in class scopes (#9952)
## Summary

If these are defined within class scopes, they're actually attributes of
the class, and can be accessed through the class itself.

(We preserve our existing behavior for `.pyi` files.)

Closes https://github.com/astral-sh/ruff/issues/9948.
2024-02-12 17:06:20 +00:00
Alex Waygood 8ec56277e9
Allow arbitrary configuration options to be overridden via the CLI (#9599)
Fixes #8368
Fixes https://github.com/astral-sh/ruff/issues/9186

## Summary

Arbitrary TOML strings can be provided via the command-line to override
configuration options in `pyproject.toml` or `ruff.toml`. As an example:
to run over typeshed and respect typeshed's `pyproject.toml`, but
override a specific isort setting and enable an additional pep8-naming
setting:

```
cargo run -- check ../typeshed --no-cache --config ../typeshed/pyproject.toml --config "lint.isort.combine-as-imports=false" --config "lint.extend-select=['N801']"
```

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Zanie Blue <contact@zanie.dev>
2024-02-09 21:56:37 +00:00
Alex Waygood d387d0ba82
RUF022, RUF023: Ensure closing parentheses for multiline sequences are always on their own line (#9793)
## Summary

Currently these rules apply the heuristic that if the original sequence
doesn't have a newline in between the final sequence item and the
closing parenthesis, the autofix won't add one for you. The feedback
from @ThiefMaster, however, was that this was producing slightly unusual
formatting -- things like this:

```py
__all__ = [
    "b", "c",
    "a", "d"]
```

were being autofixed to this:

```py
__all__ = [
    "a",
    "b",
    "c",
    "d"]
```

When, if it was _going_ to be exploded anyway, they'd prefer something
like this (with the closing parenthesis on its own line, and a trailing comma added):

```py
__all__ = [
    "a",
    "b",
    "c",
    "d",
]
```

I'm still pretty skeptical that we'll be able to please everybody here
with the formatting choices we make; _but_, on the other hand, this
_specific_ change is pretty easy to make.

## Test Plan

`cargo test`. I also ran the autofixes for RUF022 and RUF023 on CPython
to check how they looked; they looked fine to me.
2024-02-09 21:27:44 +00:00
Charlie Marsh 6f0e4ad332
Remove unnecessary string cloning from the parser (#9884)
Closes https://github.com/astral-sh/ruff/issues/9869.
2024-02-09 16:03:27 -05:00
trag1c 7ca515c0aa
Corrected PTH203–PTH205 rule descriptions (#9914)
## Summary
Closes #9898.

## Test Plan
```sh
python scripts/generate_mkdocs.py && mkdocs serve -f mkdocs.public.yml
```
2024-02-09 15:47:07 -05:00
Charlie Marsh 52ebfc9718
Respect duplicates when rewriting type aliases (#9905)
## Summary

If a generic appears multiple times on the right-hand side, we should
only include it once on the left-hand side when rewriting.

Closes https://github.com/astral-sh/ruff/issues/9904.
2024-02-09 14:02:41 +00:00
Hoël Bagard 12a91f4e90
Fix `E30X` panics on blank lines with trailing white spaces (#9907) 2024-02-09 14:00:26 +00:00
Mikko Leppänen b4f2882b72
[`pydocstyle-D405`] Allow using `parameters` as a sub-section header (#9894)
## Summary

This review contains a fix for
[D405](https://docs.astral.sh/ruff/rules/capitalize-section-name/)
(capitalize-section-name)
The problem is that Ruff considers the sub-section header as a normal
section if it has the same name as some section name. For instance, a
function/method has an argument named "parameters". This only applies if
you use Numpy style docstring.

See: [ISSUE](https://github.com/astral-sh/ruff/issues/9806)

The following will not raise D405 after the fix:
```python  
def some_function(parameters: list[str]):
    """A function with a parameters parameter

    Parameters
    ----------

    parameters:
        A list of string parameters
    """
    ...
```


## Test Plan

```bash
cargo test
```

---------

Co-authored-by: Mikko Leppänen <mikko.leppanen@vaisala.com>
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-02-08 21:54:32 -05:00
Charlie Marsh 49fe1b85f2
Reduce size of `Expr` from 80 to 64 bytes (#9900)
## Summary

This PR reduces the size of `Expr` from 80 to 64 bytes, by reducing the
sizes of...

- `ExprCall` from 72 to 56 bytes, by using boxed slices for `Arguments`.
- `ExprCompare` from 64 to 48 bytes, by using boxed slices for its
various vectors.

In testing, the parser gets a bit faster, and the linter benchmarks
improve quite a bit.
2024-02-09 02:53:13 +00:00
Micha Reiser bd8123c0d8
Fix clippy unused variable warning (#9902) 2024-02-08 22:13:31 +00:00
Micha Reiser 49c5e715f9
Filter out test rules in `RuleSelector` JSON schema (#9901) 2024-02-08 21:06:51 +00:00
Micha Reiser fe7d965334
Reduce `Result<Tok, LexicalError>` size by using `Box<str>` instead of `String` (#9885) 2024-02-08 20:36:22 +00:00
Hoël Bagard 9027169125
[`pycodestyle`] Add blank line(s) rules (`E301`, `E302`, `E303`, `E304`, `E305`, `E306`) (#9266)
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-02-08 18:35:08 +00:00
trag1c eb2784c495
Corrected Path symlink method name (PTH114) (#9896)
## Summary
Corrects mentions of `Path.is_link` to `Path.is_symlink` (the former
doesn't exist).

## Test Plan
```sh
python scripts/generate_mkdocs.py && mkdocs serve -f mkdocs.public.yml
```
2024-02-08 13:09:28 -05:00
Jane Lewis ad313b9089
RUF027 no longer has false negatives with string literals inside of method calls (#9865)
Fixes #9857.

## Summary

Statements like `logging.info("Today it is: {day}")` will no longer be
ignored by RUF027. As before, statements like `"Today it is:
{day}".format(day="Tuesday")` will continue to be ignored.

## Test Plan

The snapshot tests were expanded to include new cases. Additionally, the
snapshot tests have been split in two to separate positive cases from
negative cases.
2024-02-08 10:00:20 -05:00
Charlie Marsh f76a3e8502
Detect `mark_safe` usages in decorators (#9887)
## Summary

Django's `mark_safe` can also be used as a decorator, so we should
detect usages of `@mark_safe` for the purpose of the relevant Bandit
rule.

Closes https://github.com/astral-sh/ruff/issues/9780.
2024-02-07 23:10:46 -05:00
Tom Kuson ed07fa08bd
Fix list formatting in documention (#9886)
## Summary

Adds a blank line to render the list correctly.

## Test Plan

Ocular inspection
2024-02-07 20:01:21 -05:00
Charlie Marsh 45937426c7
Fix blank-line docstring rules for module-level docstrings (#9878)
## Summary

Given:

```python
"""Make a summary line.

Note:
----
  Per the code comment the next two lines are blank. "// The first blank line is the line containing the closing
      triple quotes, so we need at least two."

"""
```

It turns out we excluded the line ending in `"""`, because it's empty
(unlike for functions, where it consists of the indent). This PR changes
the `following_lines` iterator to always include the trailing newline,
which gives us correct and consistent handling between function and
module-level docstrings.

Closes https://github.com/astral-sh/ruff/issues/9877.
2024-02-07 16:48:28 -05:00
Charlie Marsh 533dcfb114
Add a note regarding ignore-without-code (#9879)
Closes https://github.com/astral-sh/ruff/issues/9863.
2024-02-07 21:20:18 +00:00
Jack McIvor aa38307415
Add more NPY002 violations (#9862) 2024-02-07 09:54:11 -05:00
Charlie Marsh e9ddd4819a
Make show-settings filters directory-agnostic (#9866)
Closes https://github.com/astral-sh/ruff/issues/9864.
2024-02-07 03:20:27 +00:00
Micha Reiser fdb5eefb33
Improve trailing comma rule performance (#9867) 2024-02-06 23:04:36 +00:00
Charlie Marsh daae28efc7
Respect `async with` in `timeout-without-await` (#9859)
Closes https://github.com/astral-sh/ruff/issues/9855.
2024-02-06 12:04:24 -05:00
Charlie Marsh c34908f5ad
Use `memchr` for tab-indentation detection (#9853)
## Summary

The benchmarks show a pretty consistent 1% speedup here for all-rules,
though not enough to trigger our threshold of course:

![Screenshot 2024-02-05 at 11 55
59 PM](https://github.com/astral-sh/ruff/assets/1309177/317dca3f-f25f-46f5-8ea8-894a1747d006)
2024-02-06 09:44:56 -05:00
Charlie Marsh a662c2447c
Ignore builtins when detecting missing f-strings (#9849)
## Summary

Reported on Discord: if the name maps to a builtin, it's not bound
locally, so is very unlikely to be intended as an f-string expression.
2024-02-05 23:49:56 -05:00
Seo Sanghyeon df7fb95cbc
Index multiline f-strings (#9837)
Fix #9777.
2024-02-05 21:25:33 -05:00
Eero Vaher cd5bcd815d
Mention a related setting in C408 description (#9839)
#2977 added the `allow-dict-calls-with-keyword-arguments` configuration
option for the `unnecessary-collection-call (C408)` rule, but it did not
update the rule description.
2024-02-06 03:57:53 +05:30
Charlie Marsh 0ccca4083a
Bump version to v0.2.1 (#9843) 2024-02-05 15:31:05 -05:00