Commit graph

5731 commits

Author SHA1 Message Date
Alex Waygood
187a358d7a
[red-knot] Heterogeneous tuple types with differently ordered (but equivalent) unions at the same index should be considered equivalent (#15637) 2025-01-21 12:51:20 +00:00
Calum Young
023c52d82b
Standardise ruff config (#15558) 2025-01-21 12:09:11 +01:00
InSync
c616650dfa
[ruff] Needless else clause (RUF047) (#15051)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-01-21 08:21:19 +00:00
InSync
4cfa355519
[ruff] Exempt NewType calls where the original type is immutable (RUF009) (#15588)
## Summary

Resolves #6447.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-01-20 20:14:47 +05:30
David Peter
134fefa945
[red-knot] Rename bindings_ty, declarations_ty (#15618)
## Summary

Rename two functions with outdated names (they used to return `Type`s):

* `bindings_ty` => `symbol_from_bindings` (returns `Symbol`)
* `declarations_ty` => `symbol_from_declarations` (returns a
`SymbolAndQualifiers` result)

I chose `symbol_from_*` instead of `*_symbol` as I found the previous
name quite confusing. Especially since `binding_ty` and `declaration_ty`
also exist (singular).

## Test Plan

—

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-20 15:23:33 +01:00
Micha Reiser
73798327c6
Flatten red_knot_project import paths (#15616) 2025-01-20 14:57:57 +01:00
wooly18
f82ef32e53
[red-knot] No cyclic-class-def diagnostics for subclasses of cyclic classes (#15561)
Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-01-20 13:35:29 +00:00
Micha Reiser
d70d959612
Rename red_knot_workspace to red_knot_project (#15615) 2025-01-20 14:02:36 +01:00
Micha Reiser
80345e72c4
show-settings: Properly filter out backslashes on windows (#15612)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

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

## Summary

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

## Test Plan

<!-- How was it tested? -->
2025-01-20 10:57:21 +01:00
Wei Lee
cbf9b66fc1
[airflow] Extend AIR303 with more symbols (#15611)
## Summary

Extend `AIR303` with the following rules

* `airflow.operators.datetime.*` → `airflow.providers.standard.time.operators.datetime.*`
* `airflow.operators.weekday.*` → `airflow.providers.standard.time.operators.weekday.*`
* `airflow.sensors.date_time.*` → `airflow.providers.standard.time.sensors.date_time.*`
* `airflow.sensors.time_sensor.*` → `airflow.providers.standard.time.sensors.time.*`
* `airflow.sensors.time_delta.*` → `airflow.providers.standard.time.sensors.time_delta.*`
* `airflow.sensors.weekday.*` → `airflow.providers.standard.time.sensors.weekday.*`
* `airflow.hooks.filesystem.*` → `airflow.providers.standard.hooks.filesystem.*`
* `airflow.hooks.package_index.*` → `airflow.providers.standard.hooks.package_index.*`
* `airflow.hooks.subprocess.*` → `airflow.providers.standard.hooks.subprocess.*`
* `airflow.triggers.external_task.*` → `airflow.providers.standard.triggers.external_task.*`
* `airflow.triggers.file.*` → `airflow.providers.standard.triggers.file.*`
* `airflow.triggers.temporal.*` → `airflow.providers.standard.triggers.temporal.*`
* `airflow.sensors.filesystem.FileSensor` → `airflow.providers.standard.sensors.filesystem.FileSensor`
* `airflow.operators.trigger_dagrun.TriggerDagRunOperator` → `airflow.providers.standard.operators.trigger_dagrun.TriggerDagRunOperator`
* `airflow.sensors.external_task.ExternalTaskMarker` → `airflow.providers.standard.sensors.external_task.ExternalTaskMarker`
* `airflow.sensors.external_task.ExternalTaskSensor` → `airflow.providers.standard.sensors.external_task.ExternalTaskSensor`

## Test Plan

a test fixture has been updated
2025-01-20 15:00:26 +05:30
Micha Reiser
248f0ec6b2
Isolate show_settings test from Ruff's `pyproject.toml (#15610)
## Summary

In preperation for https://github.com/astral-sh/ruff/pull/15558

Isolate the `show_settings` test instead of reading Ruff's
`pyproject.toml` for better test isolation.

## Test Plan

`cargo test`
2025-01-20 09:28:01 +00:00
Dhruv Manilawala
d8cabf62b1
Avoid large closure to make rustfmt work (#15609)
## Summary

I noticed this while reviewing
https://github.com/astral-sh/ruff/pull/15541 that the code inside the
large closure cannot be formatted by the Rust formatter. This PR
extracts the qualified name and inlines the match expression.

## Test Plan

`cargo clippy` and `cargo insta`
2025-01-20 09:15:48 +00:00
David Peter
912247635d
[red-knot] Move Ty enum to property tests (#15608)
## Summary

Move the `Ty` enum into the `property_tests` module, as it was only used
in a single place in `types.rs`.
2025-01-20 10:15:31 +01:00
InSync
5cd1f79864
[flake8-bandit] Report all references to suspicious functions (S3) (#15541)
## Summary

Resolves #15522.

## Test Plan

`cargo nextest run` and `cargo insta test`.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-01-20 09:02:53 +00:00
David Peter
4eb465ee95
[red-knot] Move type_alias_types test to Markdown (#15607)
## Summary

Move `type_alias_types` test to Markdown

## Test Plan

New MD test
2025-01-20 09:55:54 +01:00
David Peter
9725a2d476
[red-knot] More exhaustive disjointness tests (#15606)
## Summary

Mostly just brings the structure/format of the disjointness-tests closer
to what we have for `is_subtype_of` etc.
2025-01-20 09:47:51 +01:00
InSync
975d1457c5
[red-knot] Migrate is_disjoint_from unit tests to Markdown tests (#15580)
## Summary

Part of and resolves #15397, built on top of #15579.

## Test Plan

Markdown tests.
2025-01-20 08:42:22 +01:00
Charlie Marsh
98fccec2e7
Avoid removing too many imports in redefined-while-unused (#15585)
## Summary

Closes https://github.com/astral-sh/ruff/issues/15583.
2025-01-19 13:28:08 -05:00
InSync
444f799f5e
[red-knot] Two gradual equivalent fully static types are also equivalent (#15579) 2025-01-19 16:37:22 +00:00
Alex Waygood
2b24b3b316
[red-knot] Ensure differently ordered unions and intersections are considered equivalent (#15516) 2025-01-19 16:10:42 +00:00
Charlie Marsh
b8e5b95423
Avoid quadratic membership check in import fixes (#15576)
## Summary

This leads to an explosion in runtime for (admittedly absurd) cases with
tens of thousands of imports.
2025-01-18 23:01:26 +00:00
Charlie Marsh
6004c8c003
Apply redefinition fixes by source code order (#15575)
## Summary

Right now, these are being applied in random order, since if we have two
`RedefinitionWhileUnused`, it just takes the first-generated (whereas
the next comparator in the sort here orders by location)... Which means
we frequently have to re-run!
2025-01-18 17:44:10 -05:00
Charlie Marsh
1344c8a4e2
Group redefinition fixes by source statement (#15574)
## Summary

Like unused imports, we should create a single fix for all redefined
members in a single statement.

Closes https://github.com/astral-sh/ruff/issues/15182.
2025-01-18 17:31:58 -05:00
Dylan
8a50f3f361
[isort] Omit trailing whitespace in unsorted-imports (I001) (#15518)
## Summary
The fix range for sorting imports accounts for trailing whitespace, but
we should only show the trimmed range to the user when displaying the
diagnostic. So this PR changes the diagnostic range.

Closes #15504 

## Test Plan

Reviewed snapshot changes
2025-01-18 11:08:58 -06:00
InSync
001e5adec5
[flake8-simplify] Avoid double negations (SIM103) (#15562)
## Summary

Related to [this
comment](https://github.com/astral-sh/ruff/issues/6184#issuecomment-2578673788)
at #6184.

---------

Co-authored-by: Dylan <53534755+dylwil3@users.noreply.github.com>
2025-01-18 17:06:46 +00:00
Will Lachance
38adc7f702
TRY300: Add some extra notes on not catching exceptions you didn't expect (#15036)
## Summary

Added some extra notes on why you should have focused try...except
blocks to
[TRY300](https://docs.astral.sh/ruff/rules/try-consider-else/).

When fixing a violation of this rule, a co-worker of mine (very
understandably) asked why this was better. The current docs just say
putting the return in the else is "more explicit", but if you look at
the [linked reference in the python
documentation](https://docs.python.org/3/tutorial/errors.html) they are
more clear on why violations like this is bad:

> The use of the else clause is better than adding additional code to
the [try](https://docs.python.org/3/reference/compound_stmts.html#try)
clause because it avoids accidentally catching an exception that wasn’t
raised by the code being protected by the try … except statement.

This is my attempt at adding more context to the docs on this. Open to
suggestions for wording!

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-01-18 10:23:43 -06:00
Dylan
4caeeb8d98
[pylint] Include name of base class in message for redefined-slots-in-subclass (W0244) (#15559)
In the following situation:

```python
class Grandparent:
  __slots__ = "a"

class Parent(Grandparent): ...

class Child(Parent):
  __slots__ = "a"
```

the message for `W0244` now specifies that `a` is overwriting a slot
from `Grandparent`.

To implement this, we introduce a helper function `iter_super_classes`
which does a breadth-first traversal of the superclasses of a given
class (as long as they are defined in the same file, due to the usual
limitations of the semantic model).

Note: Python does not allow conflicting slots definitions under multiple
inheritance. Unless I'm misunderstanding something, I believe It follows
that the subposet of superclasses of a given class that redefine a given
slot is in fact totally ordered. There is therefore a unique _nearest_
superclass whose slot is being overwritten. So, you know, in case anyone
was super worried about that... you can just chill.

This is a followup to #9640 .
2025-01-18 09:50:27 -06:00
David Peter
fb15da5694
[red-knot] Add support for typing.ClassVar (#15550)
## Summary

Add support for `typing.ClassVar`, i.e. emit a diagnostic in this
scenario:
```py
from typing import ClassVar

class C:
    x: ClassVar[int] = 1

c = C()
c.x = 3  # error: "Cannot assign to pure class variable `x` from an instance of type `C`"
```

## Test Plan

- New tests for the `typing.ClassVar` qualifier
- Fixed one TODO in `attributes.md`
2025-01-18 13:51:35 +01:00
InSync
9d845ec8f5
[red-knot] Migrate is_gradual_equivalent_to unit tests to Markdown tests (#15563)
## Summary

Part of #15397 and #15516.

## Test Plan

Markdown tests.
2025-01-17 16:48:01 -08:00
Douglas Creager
98ef564170
Remove AstNode and AnyNode (#15479)
While looking into potential AST optimizations, I noticed the `AstNode`
trait and `AnyNode` type aren't used anywhere in Ruff or Red Knot. It
looks like they might be historical artifacts of previous ways of
consuming AST nodes?

- `AstNode::cast`, `AstNode::cast_ref`, and `AstNode::can_cast` are not
used anywhere.
- Since `cast_ref` isn't needed anymore, the `Ref` associated type isn't
either.

This is a pure refactoring, with no intended behavior changes.
2025-01-17 17:11:00 -05:00
Douglas Creager
8e3633f55a
Auto-generate AST boilerplate (#15544)
This PR replaces most of the hard-coded AST definitions with a
generation script, similar to what happens in `rust_python_formatter`.
I've replaced every "rote" definition that I could find, where the
content is entirely boilerplate and only depends on what syntax nodes
there are and which groups they belong to.

This is a pretty massive diff, but it's entirely a refactoring. It
should make absolutely no changes to the API or implementation. In
particular, this required adding some configuration knobs that let us
override default auto-generated names where they don't line up with
types that we created previously by hand.

## Test plan

There should be no changes outside of the `rust_python_ast` crate, which
verifies that there were no API changes as a result of the
auto-generation. Aggressive `cargo clippy` and `uvx pre-commit` runs
after each commit in the branch.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-17 14:23:02 -05:00
Alex Waygood
4351d85d24
[red-knot] Inline SubclassOfType::as_instance_type_of_metaclass() (#15556) 2025-01-17 19:01:36 +00:00
wooly18
1ba8e61875
[flake8-comprehensions] strip parentheses around generators in unnecessary-generator-set (C401) (#15553)
<!--
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

Fixes parentheses not being stripped in C401. Pretty much the same as
#11607 which fixed it for C400.

## Test Plan
`cargo nextest run`
2025-01-17 18:08:22 +01:00
Akira Noda
5cdac2533e
[pylint] Implement redefined-slots-in-subclass (W0244) (#9640)
## Summary

- Implementation of [redefined-slots-in-subclass /
W0244](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/redefined-slots-in-subclass.html).
- Related to #970

---------

Co-authored-by: Akira Noda <akira.noda@onecareer.com>
Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-01-17 09:54:15 -06:00
guillaumeLepape
4fdf8af747
[flake8-bugbear] Do not raise error if keyword argument is present and target-python version is less or equals than 3.9 (B903) (#15549) 2025-01-17 12:48:14 +01:00
Alex Waygood
4328df7226
[red-knot] type[T] is disjoint from type[S] if the metaclass of T is disjoint from the metaclass of S (#15547) 2025-01-17 10:41:36 +00:00
David Peter
6771b8ebd2
[red-knot] Pure instance variables declared in class body (#15515)
## Summary

This is a small, tentative step towards the bigger goal of understanding
instance attributes.

- Adds partial support for pure instance variables declared in the class
  body, i.e. this case:
  ```py
  class C:
      variable1: str = "a"
      variable2 = "b"

  reveal_type(C().variable1)  # str
  reveal_type(C().variable2)  # Unknown | Literal["b"]
  ```
- Adds `property` as a known class to query for `@property` decorators
- Splits up various `@Todo(instance attributes)` cases into
  sub-categories.

## Test Plan

Modified existing MD tests.
2025-01-17 10:48:20 +01:00
Micha Reiser
dbb2efdb87
Update snapshots of #15507 with new annotated snipetts rendering (#15546) 2025-01-17 09:39:15 +00:00
InSync
dbfdaaded1
[pylint] Do not report methods with only one EM101-compatible raise (PLR6301) (#15507) 2025-01-17 10:17:39 +01:00
Micha Reiser
1ecb7ce645
Fix unstable f-string formatting for expressions containing a trailing comma (#15545) 2025-01-17 10:08:09 +01:00
Micha Reiser
fdb9f4e404
Support knot.toml files in project discovery (#15505) 2025-01-17 09:01:58 +00:00
Micha Reiser
eb47a6634d
Add support for configuring knot in pyproject.toml files (#15493)
## Summary

This PR adds support for configuring Red Knot in the `tool.knot` section
of the project's
`pyproject.toml` section. Options specified on the CLI precede the
options in the configuration file.

This PR only supports the `environment` and the `src.root` options for
now.
Other options will be added as separate PRs.

There are also a few concerns that I intentionally ignored as part of
this PR:

* Handling of relative paths: We need to anchor paths relative to the
current working directory (CLI), or the project (`pyproject.toml` or
`knot.toml`)
* Tracking the source of a value. Diagnostics would benefit from knowing
from which configuration a value comes so that we can point the user to
the right configuration file (or CLI) if the configuration is invalid.
* Schema generation and there's a lot more; see
https://github.com/astral-sh/ruff/issues/15491

This PR changes the default for first party codes: Our existing default
was to only add the project root. Now, Red Knot adds the project root
and `src` (if such a directory exists).

Theoretically, we'd have to add a file watcher event that changes the
first-party search paths if a user later creates a `src` directory. I
think this is pretty uncommon, which is why I ignored the complexity for
now but I can be persuaded to handle it if it's considered important.

Part of https://github.com/astral-sh/ruff/issues/15491

## Test Plan

Existing tests, new file watching test demonstrating that changing the
python version and platform is correctly reflected.
2025-01-17 09:41:06 +01:00
Micha Reiser
9ed67ba33e
Fix bracket spacing for single-element tuples in f-string expressions (#15537) 2025-01-17 08:02:34 +00:00
InSync
556116ee76
[flake8-simplify] Do not emit diagnostics for expressions inside string type annotations (SIM222, SIM223) (#15405)
## Summary

Resolves #7127.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-01-17 12:18:35 +05:30
InSync
7ddf59be5f
[flake8-pytest-style] Do not emit diagnostics for empty for loops (PT012, PT031) (#15542)
## Summary

Resolves #9730.

## Test Plan

`cargo nextest run` and `cargo insta test`.

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2025-01-17 01:44:07 +00:00
InSync
fa239f76ea
[pyupgrade] Avoid syntax error when the iterable is an non-parenthesized tuple (UP028) (#15543)
## Summary

Resolves #15540.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-01-16 20:13:50 -05:00
Alex Waygood
3950b00ee4
[red-knot] Implement disjointness for Instance types where the underlying class is @final (#15539)
## Summary

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

For any two instance types `T` and `S`, we know they are disjoint if
either `T` is final and `T` is not a subclass of `S` or `S` is final and
`S` is not a subclass of `T`.

Correspondingly, for any two types `type[T]` and `S` where `S` is an
instance type, `type[T]` can be said to be disjoint from `S` if `S` is
disjoint from `U`, where `U` is the type that represents all instances
of `T`'s metaclass.

And a heterogeneous tuple type can be said to be disjoint from an
instance type if the instance type is disjoint from `tuple` (a type
representing all instances of the `tuple` class at runtime).

## Test Plan

- A new mdtest added. Most of our `is_disjoint_from()` tests are not
written as mdtests just yet, but it's pretty hard to test some of these
edge cases from a Rust unit test!
- Ran `QUICKCHECK_TESTS=1000000 cargo test --release -p
red_knot_python_semantic -- --ignored types::property_tests::stable`

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-01-16 23:48:52 +00:00
Auguste Lalande
e84c82424d
[pydoclint] Allow ignoring one line docstrings for DOC rules (#13302)
## Summary

Add a setting to allow ignoring one line docstrings for the pydoclint
rules.

Resolves #13086

Part of #12434

## Test Plan

Run tests with setting enabled.

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-01-16 16:05:10 -06:00
Aleksei Latyshev
177bf72598
[refurb] Implement for-loop-writes (FURB122) (#10630)
## Summary
Implement `for-loop-writes` (FURB122) lint
- https://github.com/astral-sh/ruff/issues/1348
- [original
lint](https://github.com/dosisod/refurb/blob/master/refurb/checks/builtin/writelines.py)

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-01-16 15:02:46 -06:00
InSync
2e6729d900
[red-knot] Migrate bool/str/repr unit tests to Markdown tests (#15534)
## Summary

Part of #15397.

## Test Plan

Markdown tests.
2025-01-16 11:21:56 -08:00