Commit Graph

332 Commits

Author SHA1 Message Date
Charlie Marsh 432b4da27b Recategorize `static-key-dict-comprehension` from `RUF011` to `B035` (#9428)
## Summary

This rule was added to flake8-bugbear. In general, we tend to prefer
redirecting to prominent plugins when our own rules are reimplemented
(since more projects have `B` activated than `RUF`).

## Test Plan

`cargo test`
2024-01-30 12:00:45 -06:00
Mikko Leppänen 79f0522eb7
[`flake8-async`] Take `pathlib.Path` into account when analyzing async functions (#9703)
## Summary

This review contains a fix for
[ASYNC101](https://docs.astral.sh/ruff/rules/open-sleep-or-subprocess-in-async-function/)
(open-sleep-or-subprocess-in-async-function)

The problem is that ruff does not take open calls from pathlib.Path into
account in async functions. Path.open() call is still a blocking call.
In addition, PTH123 suggests to use pathlib.Path instead of os.open. So
this might create an additional confusion.

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

## Test Plan

```bash
cargo test
```
2024-01-30 17:42:50 +00:00
Alex Waygood 0c8d140321
RUF022, RUF023: never add two trailing commas to the end of a sequence (#9698)
Fixes the issues highlighted in
https://github.com/astral-sh/ruff/issues/8402#issuecomment-1916203707
and
https://github.com/astral-sh/ruff/issues/8402#issuecomment-1916213693
2024-01-30 17:19:38 +00:00
Steve C f0e598ea84
[`flake8-return`] Fix indentation syntax error (`RET505`) (#9705)
## Summary

Fix for
https://github.com/astral-sh/ruff/issues/8402#issuecomment-1916223126

## Test Plan

`cargo test`
2024-01-30 16:46:04 +00:00
Bartosz Sławecki b6a96452fc
[`pylint`] Add `__mro_entries__` to known dunder methods (`PLW3201`) (#9706)
## Summary

This change adds
[`__mro_entries__`](https://docs.python.org/3/reference/datamodel.html#object.__mro_entries__)
to the list of known dunder methods.
2024-01-30 11:41:19 -05:00
Steve C 214563261d
[`flake8-simplify`] - Fix syntax error in autofix (`SIM114`) (#9704)
## Summary

A fix for
https://github.com/astral-sh/ruff/issues/8402#issuecomment-1916215124

Improves the code, as well. :)

## Test Plan

`cargo test`
2024-01-30 11:36:44 -05:00
Steve C dacda0f202
[`pylint`] Show verbatim constant in `magic-value-comparison` (`PLR2004`) (#9694)
## Summary

Tweaks PLR2004 to show the literal source text, rather than the constant
value.

I noticed this when I had a hexadecimal constant, and the linter turned
it into base-10.

Now, if you have `0x300`, it will show `0x300` instead of `768`.

Also, added backticks around the constant in the output message.

## Test Plan

`cargo test`
2024-01-30 00:22:09 -05:00
Charlie Marsh 11449acfd9
Avoid marking `InitVar` as a typing-only annotation (#9688)
## Summary

Given:

```python
from dataclasses import InitVar, dataclass

@dataclass
class C:
    i: int
    j: int = None
    database: InitVar[DatabaseType] = None

    def __post_init__(self, database):
        if self.j is None and database is not None:
            self.j = database.lookup('j')

c = C(10, database=my_database)
```

We should avoid marking `InitVar` as typing-only, since it _is_ required
by the dataclass at runtime.

Note that by default, we _already_ don't flag this, since the
`@dataclass` member is needed at runtime too -- so it's only a problem
with `strict` mode.

Closes https://github.com/astral-sh/ruff/issues/9666.
2024-01-29 16:27:20 -05:00
Charlie Marsh a6f7100b55
[`pycodestyle`] Allow `dtype` comparisons in `type-comparison` (#9676)
## Summary

Per https://github.com/astral-sh/ruff/issues/9570:

> `dtype` are a bit of a strange beast, but definitely best thought of
as instances, not classes, and they are meant to be comparable not just
to their own class, but also to the corresponding scalar types (e.g.,
`x.dtype == np.float32`) and strings (e.g., `x.dtype == ['i1,i4']`;
basically, `__eq__` always tries to do `dtype(other)`.

This PR thus allows comparisons to `dtype` in preview.

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

## Test Plan

`cargo test`
2024-01-29 12:39:01 -05:00
Mikko Leppänen ad2cfa3dba
[flake8-return] Consider exception suppress for unnecessary assignment (#9673)
## Summary

This review contains a fix for
[RET504](https://docs.astral.sh/ruff/rules/unnecessary-assign/)
(unnecessary-assign)

The problem is that Ruff suggests combining a return statement inside
contextlib.suppress. Even though it is an unsafe fix it might lead to an
invalid code that is not equivalent to the original one.

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

## Test Plan

```bash
cargo test
```
2024-01-29 12:29:05 -05:00
Mikko Leppänen b9139a31d5
[`flake8-pie`] Omit bound tuples passed to `.startswith` or `.endswith` (#9661)
## Summary

This review contains a fix for
[PIE810](https://docs.astral.sh/ruff/rules/multiple-starts-ends-with/)
(multiple-starts-ends-with)

The problem is that ruff suggests combining multiple startswith/endswith
calls into a single call even though there might be a call with tuple of
strs. This leads to calling startswith/endswith with tuple of tuple of
strs which is incorrect and violates startswith/endswith conctract and
results in runtime failure.

However the following will be valid and fixed correctly => 
```python
x = ("hello", "world")
y = "h"
z = "w"
msg = "hello world"

if msg.startswith(x) or msg.startswith(y) or msg.startswith(z) :
      sys.exit(1)
```
```
ruff --fix --select PIE810 --unsafe-fixes
```
=> 
```python
if msg.startswith(x) or msg.startswith((y,z)):
      sys.exit(1)
```

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

## Test Plan

```bash
cargo test
```
2024-01-28 19:29:04 +00:00
Charlie Marsh 7329bf459c
Avoid panic when fixing inlined else blocks (#9657)
Closes https://github.com/astral-sh/ruff/issues/9655.
2024-01-27 14:15:33 +00:00
Charlie Marsh 157d5bacfc
[`pydocstyle`] Re-implement `last-line-after-section` (`D413`) (#9654)
## Summary

This rule was just incorrect, it didn't match the examples in the docs.
(It's a very rarely-used rule since it's not included in any of the
conventions.)

Closes https://github.com/astral-sh/ruff/issues/9452.
2024-01-26 19:30:59 +00:00
Mikko Leppänen d496c164d3
[`ruff`] Guard against use of `default_factory` as a keyword argument (`RUF026`) (#9651)
## Summary

Add a rule for defaultdict(default_factory=callable). Instead suggest
using defaultdict(callable).

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

If a user tries to bind a "non-callable" to default_factory, the rule
ignores it. Another option would be to warn that it's probably not what
you want. Because Python allows the following:

```python 
from collections import defaultdict

defaultdict(default_factory=1)
```
this raises after you actually try to use it:

```python
dd = defaultdict(default_factory=1)
dd[1]
```
=> 
```bash
KeyError: 1
```

Instead using callable directly in the constructor it will raise (not
being a callable):

```python 
from collections import defaultdict

defaultdict(1)
```
=> 
```bash
TypeError: first argument must be callable or None
```




## Test Plan

```bash
cargo test
```
2024-01-26 19:10:05 +00:00
Charlie Marsh b61b0edeea
Add Pydantic's `BaseConfig` to default-copy list (#9650)
Closes https://github.com/astral-sh/ruff/issues/9647.
2024-01-26 14:54:48 +00:00
Steve C ffd13e65ae
[`flake8-return`] - Add fixes for (`RET505`, `RET506`, `RET507`, `RET508`) (#9595) 2024-01-25 08:28:32 +01:00
Steve C dba2cb79cb
[`pylint`] Implement `too-many-nested-blocks` (`PLR1702`) (#9172)
## Summary

Implement
[`PLR1702`/`too-many-nested-blocks`](https://pylint.readthedocs.io/en/latest/user_guide/messages/refactor/too-many-nested-blocks.html)

See: #970 

## Test Plan

`cargo test`
2024-01-24 19:30:01 +00:00
Mikko Leppänen 45628a5883
[`flake8-return`] Take `NoReturn` annotation into account when analyzing implicit returns (#9636)
## Summary

When we are analyzing the implicit return rule this change add an
additional check to verify if the call expression has been annotated
with NoReturn type from typing module.

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

## Test Plan

```bash
cargo test
```
2024-01-24 17:19:26 +00:00
Akira Noda 57313d9d63
[`pylint`] Implement `assigning-non-slot` (`E0237`) (#9623)
## Summary

Implement [assigning-non-slot /
E0237](https://pylint.readthedocs.io/en/latest/user_guide/messages/error/assigning-non-slot.html)

related #970

## Test Plan

`cargo test`
2024-01-24 02:50:22 +00:00
Mikko Leppänen eab1a6862b
[`ruff`] Detect unnecessary `dict` comprehensions for iterables (`RUF025`) (#9613)
## Summary

Checks for unnecessary `dict` comprehension when creating a new
dictionary from iterable. Suggest to replace with
`dict.fromkeys(iterable)`

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

## Test Plan

```bash
cargo test
```
2024-01-24 02:15:38 +00:00
Alex Waygood f5061dbb8e
Add a rule/autofix to sort `__slots__` and `__match_args__` (#9564)
## Summary

This PR introduces a new rule to sort `__slots__` and `__match_args__`
according to a [natural sort](https://en.wikipedia.org/wiki/Natural_sort_order), as was
requested in https://github.com/astral-sh/ruff/issues/1198#issuecomment-1881418365.

The implementation here generalises some of the machinery introduced in
3aae16f1bd
so that different kinds of sorts can be applied to lists of string
literals. (We use an "isort-style" sort for `__all__`, but that isn't
really appropriate for `__slots__` and `__match_args__`, where nearly
all items will be snake_case.) Several sections of code have been moved
from `sort_dunder_all.rs` to a new module, `sorting_helpers.rs`, which
`sort_dunder_all.rs` and `sort_dunder_slots.rs` both make use of.

`__match_args__` is very similar to `__all__`, in that it can only be a
tuple or a list. `__slots__` differs from the other two, however, in
that it can be any iterable of strings. If slots is a dictionary, the
values are used by the builtin `help()` function as per-attribute
docstrings that show up in the output of `help()`. (There's no
particular use-case for making `__slots__` a set, but it's perfectly
legal at runtime, so there's no reason for us not to handle it in this
rule.)

Note that we don't do an autofix for multiline `__slots__` if `__slots__` is a dictionary: that's out of scope. Everything else, we can nearly always fix, however.

## Test Plan

`cargo test` / `cargo insta review`.

I also ran this rule on CPython, and the diff looked pretty good

---

Co-authored-by: Micha Reiser <micha@reiser.io>
2024-01-22 12:21:55 +00:00
Steve C 9c8a4d927e
[`flake8-simplify`] Add fix for `if-with-same-arms` (`SIM114`) (#9591)
## Summary

 add fix for `if-with-same-arms` / `SIM114`

Also preserves comments!

## Test Plan

`cargo test`
2024-01-22 04:37:18 +00:00
Steve C e54ed28ba9
[`pylint`] Add fix for `collapsible-else-if` (`PLR5501`) (#9594)
## Summary

adds a fix for `collapsible-else-if` / `PLR5501`

## Test Plan

`cargo test`
2024-01-21 19:53:15 -05:00
Tom Kuson 1e4b421a00
[`ruff`] Implement `mutable-fromkeys-value` (`RUF024`) (#9597)
## Summary

Implement rule `mutable-fromkeys-value` (`RUF023`).

Autofixes

```python
dict.fromkeys(foo, [])
```

to

```python
{key: [] for key in foo}
```

The fix is marked as unsafe as it changes runtime behaviour. It also
uses `key` as the comprehension variable, which may not always be
desired.

Closes #4613.

## Test Plan

`cargo test`
2024-01-22 00:22:02 +00:00
Steve C 837984168a
[`pycodestyle`] Add fix for `multiple-imports-on-one-line` (`E401`) (#9518)
## Summary

Add autofix for `multiple_imports_on_one_line`, `E401`

## Test Plan

`cargo test`
2024-01-21 15:33:38 -05:00
Steve C 9e5f3f1b1b
[`pylint`] Add fix for `useless-else-on-loop` (`PLW0120`) (#9590)
## Summary

adds fix for `useless-else-on-loop` / `PLW0120`.

## Test Plan

`cargo test`
2024-01-21 11:17:58 -05:00
Steve C 49a445a23d
[`pylint`] Implement `potential-index-error` (`PLE0643`) (#9545)
## Summary

add `potential-index-error` rule (`PLE0643`)

See: #970 

## Test Plan

`cargo test`
2024-01-21 03:59:48 +00:00
Alex Waygood b3a6f0ce81
[flake8-pyi] Fix PYI049 false negatives on call-based TypedDicts (#9567)
## Summary

Fixes another of the bullet points from #8771

## Test Plan

`cargo test` / `cargo insta review`
2024-01-18 10:01:21 +00:00
Thomas M Kehrenberg 7be706641d
[`pylint`] Exclude `self` and `cls` when counting method arguments (#9563)
## Summary

This PR detects whether PLR0917 is being applied to a method or class
method, and if so, it ignores the first argument for the purposes of
counting the number of positional arguments.

## Test Plan

New tests have been added to the corresponding fixture.

Closes #9552.
2024-01-18 03:17:45 +00:00
Alex Waygood 848e473f69
[flake8-pyi] Fix PYI047 false negatives on PEP-695 type aliases (#9566)
## Summary

Fixes one of the issues listed in
https://github.com/astral-sh/ruff/issues/8771. Fairly straightforward!

## Test Plan

`cargo test` / `cargo insta review`
2024-01-17 22:14:18 -05:00
Charlie Marsh 8118d29419
Rename `ruff_cli` crate to `ruff` (#9557)
## Summary

Long ago, we had a single `ruff` crate. We started to break that up, and
at some point, we wanted to separate the CLI from the core library. So
we created `ruff_cli`, which created a `ruff` binary. Later, the `ruff`
crate was renamed to `ruff_linter` and further broken up into additional
crates.

(This is all from memory -- I didn't bother to look through the history
to ensure that this is 100% correct :))

Now that `ruff` no longer exists, this PR renames `ruff_cli` to `ruff`.
The primary benefit is that the binary target and the crate name are now
the same, which helps with downstream tooling like `cargo-dist`, and
also removes some complexity from the crate and `Cargo.toml` itself.

## Test Plan

- Ran `rm -rf target/release`.
- Ran `cargo build --release`.
- Verified that `./target/release/ruff` was created.
2024-01-16 17:47:01 -05:00
Tom Kuson f426c0fdaf
[`pylint`] (Re-)Implement `import-private-name` (`C2701`) (#9553)
## Summary

#5920 with a fix for the erroneous slice in `module_name`. Fixes #9547.

## Test Plan

Added `import bbb.ccc._ddd as eee` to the test fixture to ensure it no
longer panics.

`cargo test`
2024-01-16 14:03:11 -05:00
Alex Waygood 3aae16f1bd
Add rule and autofix to sort the contents of `__all__` (#9474)
## Summary

This implements the rule proposed in #1198 (though it doesn't close the
issue, as there are some open questions about configuration that might
merit some further discussion).

## Test Plan

`cargo test` / `cargo insta review`. I also ran this PR branch on the CPython
codebase with `--fix --select=RUF022 --preview `, and the results looked
pretty good to me.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Andrew Gallant <andrew@astral.sh>
2024-01-16 14:42:47 +00:00
Micha Reiser f9191b07c5
Revert "[`pylint`] Implement `import-private-name` (`C2701`)" (#9547) 2024-01-16 08:33:21 +00:00
Tom Kuson 2b605527bd
[`pylint`] Implement `import-private-name` (`C2701`) (#5920)
## Summary

Implements [`import-private-name`
(`C2701`)](https://pylint.pycqa.org/en/latest/user_guide/messages/convention/import-private-name.html)
as `import-private-name` (`PLC2701`). Includes documentation.

Related to #970.

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

### PEP 420 namespace package limitation

`checker.module_path` doesn't seem to support automatic detection of
namespace packages (PEP 420). This leads to 'false' positives (Pylint
allows both).

Currently, for this to work like Pylint, users would have to [manually
input known namespace
packages](https://beta.ruff.rs/docs/settings/#namespace-packages).

## Test Plan

`cargo test`
2024-01-16 05:17:42 +00:00
Charlie Marsh f9331c7683
Recursively visit deferred AST nodes (#9541)
## Summary

This PR is a more holistic fix for
https://github.com/astral-sh/ruff/issues/9534 and
https://github.com/astral-sh/ruff/issues/9159.

When we visit the AST, we track nodes that we need to visit _later_
(deferred nodes). For example, when visiting a function, we defer the
function body, since we don't want to visit the body until we've visited
the rest of the statements in the containing scope.

However, deferred nodes can themselves contain deferred nodes... For
example, a function body can contain a lambda (which contains a deferred
body). And then there are rarer cases, like a lambda inside of a type
annotation.

The aforementioned issues were fixed by reordering the deferral visits
to catch common cases. But even with those fixes, we still fail on cases
like:

```python
from __future__ import annotations

import re
from typing import cast

cast(lambda: re.match, 1)
```

Since we don't expect lambdas to appear inside of type definitions.

This PR modifies the `Checker` to keep visiting until all the deferred
stacks are empty. We _already_ do this for any one kind of deferred
node; now, we do it for _all_ of them at a level above.
2024-01-15 20:34:38 -05:00
Charlie Marsh da275b8572
Visit deferred lambdas before type definitions (#9540)
## Summary

This is effectively the same problem as
https://github.com/astral-sh/ruff/pull/9175. And this just papers over
it again, though I'm gonna try a more holistic fix in a follow-up PR.
The _real_ fix here is that we need to continue to visit deferred items
until they're exhausted since, e.g., we still get this case wrong
(flagging `re` as unused):

```python
import re

cast(lambda: re.match, 1)
```

Closes https://github.com/astral-sh/ruff/issues/9534.
2024-01-15 20:08:40 -05:00
yataka 0753968ef3
add the "__prepare__" method to the list of recognized dunder method (#9529)
## Summary
Closes #9508 .
Add `__prepare__` method to dunder method list in
`is_known_dunder_method`.

## Test Plan
1. add "__prepare__" method to `Apple` class in
crates/ruff_linter/resources/test/fixtures/pylint/bad_dunder_method_name.py.
2. run `cargo test`
2024-01-15 14:37:19 +00:00
Steve C 6183b8e98b
[`refurb`] Implement `regex-flag-alias` with fix (`FURB167`) (#9516)
## Summary

add
[`FURB167`/`use-long-regex-flag`](https://github.com/dosisod/refurb/blob/master/refurb/checks/regex/use_long_flag.py)
with autofix

See: #1348 

## Test Plan

`cargo test`

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-01-14 23:40:17 +00:00
Steve C 0c0d3db1b5
[`flake8-bugbear`] Add fix for `duplicate-value` (`B033`) (#9510)
## Summary

Adds autofix for
[B033](https://docs.astral.sh/ruff/rules/duplicate-value/)

## Test Plan

`cargo test`
2024-01-14 23:20:16 +00:00
Charlie Marsh 953d48b7f4
[`flake8-simplify`] Avoid some more `enumerate-for-loop` false positives (`SIM113`) (#9515)
Avoids, e.g., [this false
positive](a4fad5dda1/zerver/data_import/slack.py (L634))
from the ecosystem check.
2024-01-14 13:02:13 -05:00
Chammika Mannakkara 0003c730e0
[`flake8-simplify`] Implement `enumerate-for-loop` (`SIM113`) (#7777)
Implements SIM113 from #998

Added tests
Limitations 
   - No fix yet
   - Only flag cases where index variable immediately precede `for` loop

@charliermarsh please review and let me know any improvements

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-01-14 11:00:59 -05:00
Charlie Marsh 957a1f35c4
Ignore unnecessary dunder calls within dunder definitions (#9496)
Closes https://github.com/astral-sh/ruff/issues/9486.
2024-01-12 14:48:42 -05:00
Charlie Marsh 009430e034
[`ruff`] Avoid treating named expressions as static keys (`RUF011`) (#9494)
Closes https://github.com/astral-sh/ruff/issues/9487.
2024-01-12 14:33:45 -05:00
Charlie Marsh fee64b52ba
Limit inplace diagnostics to methods that accept inplace (#9495)
## Summary

This should reduce false positives like
https://github.com/astral-sh/ruff/issues/9491, by ignoring methods that
are clearly not on a DataFrame.

Closes https://github.com/astral-sh/ruff/issues/9491.
2024-01-12 14:12:54 -05:00
Charlie Marsh a31a314b2b
Account for possibly-empty f-string values in truthiness logic (#9484)
Closes https://github.com/astral-sh/ruff/issues/9479.
2024-01-11 21:16:19 -05:00
Charlie Marsh f9dd7bb190
Remove `unreachable-code` feature (#9463)
## Summary

We haven't found time to flip this on, so feels like it's best to remove
it for now -- can always restore from source when we get back to it.
2024-01-11 20:24:57 -05:00
trag1c eb4ed2471b
[`flake8-simplify`] Implement `SIM911` (#9460)
## Summary

Closes #9319, implements the [`SIM911` rule from
`flake8-simplify`](https://github.com/MartinThoma/flake8-simplify/pull/183).


#### Note
I wasn't sure whether or not to include
```rs
if checker.settings.preview.is_disabled() {
    return;
}
```
at the beginning of the function with violation logic if the rule's
already declared as part of `RuleGroup::Preview`.
I've seen both variants, so I'd appreciate some feedback on that :)
2024-01-11 14:42:43 -05:00
Charlie Marsh 25bafd2d66
Restrict `builtin-attribute-shadowing` to actual shadowed references (#9462)
## Summary

This PR attempts to improve `builtin-attribute-shadowing` (`A003`), a
rule which has been repeatedly criticized, but _does_ have value (just
not in the current form).

Historically, this rule would flag cases like:

```python
class Class:
    id: int
```

This led to an increasing number of exceptions and special-cases to the
rule over time to try and improve it's specificity (e.g., ignore
`TypedDict`, ignore `@override`).

The crux of the issue is that given the above, referencing `id` will
never resolve to `Class.id`, so the shadowing is actually fine. There's
one exception, however:

```python
class Class:
    id: int

    def do_thing() -> id:
        pass
```

Here, `id` actually resolves to the `id` attribute on the class, not the
`id` builtin.

So this PR completely reworks the rule around this _much_ more targeted
case, which will almost always be a mistake: when you reference a class
member from within the class, and that member shadows a builtin.

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

Closes https://github.com/astral-sh/ruff/issues/7806.
2024-01-11 12:59:40 -05:00
Alex Waygood 6be73322da
[RUF021]: Add an autofix (#9449)
## Summary

This adds an autofix for the newly added RUF021 (see #9440).
2024-01-09 17:55:33 +00:00