Compare commits

..

93 Commits

Author SHA1 Message Date
Dhruv Manilawala
c76e15a45d Check context parameters directly from function definition 2025-01-23 14:13:29 +05:30
Ankit Chaurasia
d0aff2bbff Add find_parameter 2025-01-23 12:19:31 +05:45
Ankit Chaurasia
65db31f0e1 highlights the parameter itself 2025-01-22 12:59:39 +05:45
Wei Lee
c2c37b8052 test: update test fixture 2025-01-22 10:06:15 +08:00
Ankit Chaurasia
51613d9107 Add lint error for removed context variables for get_current_context 2025-01-22 09:57:26 +08:00
Ankit Chaurasia
f20e70cd62 remove use of vectors 2025-01-22 09:57:25 +08:00
Ankit Chaurasia
4737824345 fix the logic for lint error message 2025-01-22 09:57:25 +08:00
Ankit Chaurasia
1961b76d03 Refactor functions to use ExprSubscript 2025-01-22 09:57:25 +08:00
Ankit Chaurasia
62a1e55705 refactor rename functions 2025-01-22 09:57:25 +08:00
Ankit Chaurasia
8a7ec4c0a3 Fix PR comments 2025-01-22 09:57:25 +08:00
Ankit Chaurasia
9b9540c3cd Check arguments and function decorated with @task 2025-01-22 09:57:25 +08:00
Ankit Chaurasia
ccafaf8e30 Add more checks for removed context variables
add lint rule to show error for removed context variables in airflow
2025-01-22 09:57:25 +08:00
Alex Waygood
fbb06fe0ac [red-knot] Small simplifications to Type::is_subtype_of and Type::is_disjoint_from (#15622)
## Summary

This PR generalizes some of the logic we have in `Type::is_subtype_of`
and `Type::is_disjoint_from` so that we fallback to the instance type of
the metaclass more often in `Type::ClassLiteral` and `Type::SubclassOf`
branches. This simplifies the code (we end up with one less branch in
`is_subtype_of`, and we can remove a helper method that's no longer
used), makes the code more robust (any fixes made to subtyping or
disjointness of instance types will automatically improve our
understanding of subtyping/disjointness for class-literal types and
`type[]` types) and more elegantly expresses the type-system invariants
encoded in these branches.

## Test Plan

No new tests added (it's a pure refactor, adding no new functionality).
All existing tests pass, however, including the property tests.
2025-01-22 00:31:55 +00:00
Zanie Blue
8a8240b8a6 Use new-style Windows runner tag (#15661)
I changed these org-wide to make it more obvious what runner it maps to;
did not update here as I did in uv
2025-01-21 17:44:17 -06:00
Douglas Creager
ef85c682bd Remove customizable reference enum names (#15647)
The AST generator creates a reference enum for each syntax group — an
enum where each variant contains a reference to the relevant syntax
node. Previously you could customize the name of the reference enum for
a group — primarily because there was an existing `ExpressionRef` type
that wouldn't have lined up with the auto-derived name `ExprRef`. This
follow-up PR is a simple search/replace to switch over to the
auto-derived name, so that we can remove this customization point.
2025-01-21 13:46:31 -05:00
Douglas Creager
fa546b20a6 Separate grouped and ungrouped nodes more clearly in AST generator (#15646)
This is a minor cleanup to the AST generation script to make a clearer
separation between nodes that do appear in a group enum, and those that
don't. There are some types and methods that we create for every syntax
node, and others that refer to the group that the syntax node belongs
to, and which therefore don't make sense for ungrouped nodes. This new
separation makes it clearer which category each definition is in, since
you're either inside of a `for group in ast.groups` loop, or a `for node
in ast.all_nodes` loop.
2025-01-21 13:37:18 -05:00
InSync
fce4adfd41 [flake8-simplify] Mark fixes as unsafe (SIM201, SIM202) (#15626) 2025-01-21 18:17:48 +01:00
David Peter
13a6b5600b [red-knot] mdtest runner: include stderr for crashing tests (#15644)
## Summary

Test executables usually write failure messages (including panics) to
stdout, but I just managed to make a mdtest crash with
```
thread 'mdtest__unary_not' has overflowed its stack
fatal runtime error: stack overflow
```
which is printed to stderr. This test simply appends stderr to stdout
(`stderr=subprocess.STDOUT` can not be used with `capture_output`)

## Test Plan

Make sure that the error message is now visible in the output of `uv -q
run crates/red_knot_python_semantic/mdtest.py`
2025-01-21 14:59:36 +00:00
Micha Reiser
067c6de465 Change EnvironmentOptions::venv-path to Option<SystemPathBuf> (#15631)
## Summary

The `Options` struct is intended to capture the user's configuration
options but
`EnvironmentOptions::venv_path` supports both a `SitePackages::Known`
and `SitePackages::Derived`.

Users should only be able to provide `SitePackages::Derived`—they
specify a path to a venv, and Red Knot derives the path to the
site-packages directory. We'll only use the `Known` variant once we
automatically discover the Python installation.

That's why this PR changes `EnvironmentOptions::venv_path` from
`Option<SitePackages>` to `Option<SystemPathBuf>`.

This requires making some changes to the file watcher test, and I
decided to use `extra_paths` over venv path
because our venv validation is annoyingly correct -- making mocking a
venv rather involved.

## Test Plan

`cargo test`
2025-01-21 14:10:41 +00:00
David Salvisberg
4366473d9b [flake8-type-checking] Fix some safe fixes being labeled unsafe (#15638)
## Summary

We were mistakenly using `CommentRanges::has_comments` to determine
whether our edits
were safe, which sometimes expands the checked range to the end of a
line. But in order to
determine safety we need to check exactly the range we're replacing.

This bug affected the rules `runtime-cast-value` (`TC006`) and
`quoted-type-alias` (`TC008`)
although it was very unlikely to be hit for `TC006` and for `TC008` we
never hit it because we
were checking the wrong expression.

## Test Plan

`cargo nextest run`
2025-01-21 15:08:46 +01:00
Chandra Kiran G
cff9c13c42 feat: Update RUF055 to do var == value (#15605)
This commit fixes RUF055 rule to format `re.fullmatch(pattern, var)` to
`var == pattern` instead of the current `pattern == var` behaviour. This
is more idiomatic and easy to understand.

## Summary

This changes the current formatting behaviour of `re.fullmatch(pattern,
var)` to format it to `var == pattern` instead of `pattern == var`.

## Test Plan

I used a code file locally to see the updated formatting behaviour.

Fixes https://github.com/astral-sh/ruff/issues/14733
2025-01-21 08:47:06 -05:00
David Peter
4656e3c90f [red-knot] Markdown test runner (#15632)
## Summary

As more and more tests move to Markdown, running the mdtest suite
becomes one of the most common tasks for developers working on Red Knot.
There are a few pain points when doing so, however:

- The `build.rs` script enforces recompilation (~five seconds) whenever
something changes in the `resource/mdtest` folder. This is strictly
necessary, because whenever files are added or removed, the test harness
needs to be updated. But this is very rarely the case! The most common
scenario is that a Markdown file has *changed*, and in this case, no
recompilation is necessary. It is currently not possible to distinguish
these two cases using `cargo::rerun-if-changed`. One can work around
this by running the test executable manually, but it requires finding
the path to the correct `mdtest-<random-hash>` executable.
- All Markdown tests are run by default. This is needed whenever Rust
code changes, but while working on the tests themselves, it is often
much more convenient to only run the tests for a single file. This can
be done by using a `mdtest__path_to_file` filter, but this needs to be
manually spelled out or copied from the test output.
- `cargo`s test output for a failing Markdown test is often
unnecessarily verbose. Unless there is an *actual* panic somewhere in
the code, mdtests usually fail with the explicit *"Some tests failed"*
panic in the mdtest suite. But in those cases, we are not interested in
the pointer to the source of this panic, but only in the mdtest suite
output.

This PR adds a Markdown test runner tool that attempts to make the
developer experience better.

Once it is started using
```bash
uv run -q crates/red_knot_python_semantic/mdtest.py
```
it will first recompile the tests once (if cargo requires it), find the
path to the `mdtest` executable, and then enter into a mode where it
watches for changes in the `red_knot_python_semantic` crate. Whenever …
* … a Markdown file changes, it will rerun the mdtest for this specific
  file automatically (no recompilation!).
* … a Markdown file is added, it will recompile the tests and then run
  the mdtest for the new file
* … Rust code is changed, it will recompile the tests and run all of
  them

The tool also trims down `cargo test` output and only shows the actual
mdtest errors.

The tool will certainly require a few more iterations before it becomes
mature, but I'm curious to hear if there is any interest for something
like this.

## Test Plan

- Tested the new runner under various scenarios.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-21 14:06:35 +01:00
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
renovate[bot]
2a2ac8a483 Update pre-commit dependencies (#15596)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-01-20 13:10:09 +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
renovate[bot]
36c90ebe86 Update Rust crate notify to v8 (#15435)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [notify](https://redirect.github.com/notify-rs/notify) |
workspace.dependencies | major | `7.0.0` -> `8.0.0` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Release Notes

<details>
<summary>notify-rs/notify (notify)</summary>

###
[`v8.0.0`](https://redirect.github.com/notify-rs/notify/blob/HEAD/CHANGELOG.md#notify-800-2025-01-10)

[Compare
Source](https://redirect.github.com/notify-rs/notify/compare/notify-7.0.0...notify-8.0.0)

-   CHANGE: update notify-types to version 2.0.0
-   CHANGE: raise MSRV to 1.77 **breaking**
- FEATURE: add config option to disable following symbolic links
[#&#8203;635]
- FIX: unaligned access to FILE_NOTIFY_INFORMATION [#&#8203;647]
**breaking**

[#&#8203;635]: https://redirect.github.com/notify-rs/notify/pull/635

[#&#8203;647]: https://redirect.github.com/notify-rs/notify/pull/647

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/astral-sh/ruff).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS45Mi4wIiwidXBkYXRlZEluVmVyIjoiMzkuOTIuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiaW50ZXJuYWwiXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 10:41:16 +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
Dhruv Manilawala
d97502d647 Include more labels in CHANGELOG sections (#15566)
## Summary

This PR updates Rooster config to include more labels, specifically:
* Include
[`diagnostics`](https://github.com/astral-sh/ruff/labels/diagnostics),
[`docstring`](https://github.com/astral-sh/ruff/labels/docstring),
[`fixes`](https://github.com/astral-sh/ruff/labels/fixes) and
[`isort`](https://github.com/astral-sh/ruff/labels/isort) for "Rule
changes" section
* Use
[`performance`](https://github.com/astral-sh/ruff/labels/performance)
for "Performance" section. We already have included "Performance"
section in various version, so let's make it official :)
* Ignore [`testing`](https://github.com/astral-sh/ruff/labels/testing)
label

The following is open:
* [`suppression`](https://github.com/astral-sh/ruff/labels/suppression)
2025-01-20 10:34:22 +05:30
renovate[bot]
15c6cb50a0 Update NPM Development dependencies (#15601)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@types/react](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react))
| [`19.0.6` ->
`19.0.7`](https://renovatebot.com/diffs/npm/@types%2freact/19.0.6/19.0.7)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/19.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/19.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/19.0.6/19.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/19.0.6/19.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@typescript-eslint/eslint-plugin](https://typescript-eslint.io/packages/eslint-plugin)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin))
| [`8.19.1` ->
`8.20.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/8.19.1/8.20.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2feslint-plugin/8.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2feslint-plugin/8.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2feslint-plugin/8.19.1/8.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2feslint-plugin/8.19.1/8.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@typescript-eslint/parser](https://typescript-eslint.io/packages/parser)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser))
| [`8.19.1` ->
`8.20.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.19.1/8.20.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/8.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fparser/8.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fparser/8.19.1/8.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/8.19.1/8.20.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-config-prettier](https://redirect.github.com/prettier/eslint-config-prettier)
| [`^9.0.0` ->
`^10.0.0`](https://renovatebot.com/diffs/npm/eslint-config-prettier/9.1.0/10.0.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-prettier/10.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-prettier/10.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-prettier/9.1.0/10.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-prettier/9.1.0/10.0.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-plugin-react](https://redirect.github.com/jsx-eslint/eslint-plugin-react)
| [`7.37.3` ->
`7.37.4`](https://renovatebot.com/diffs/npm/eslint-plugin-react/7.37.3/7.37.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-react/7.37.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-plugin-react/7.37.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-plugin-react/7.37.3/7.37.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-react/7.37.3/7.37.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[miniflare](https://redirect.github.com/cloudflare/workers-sdk/tree/main/packages/miniflare#readme)
([source](https://redirect.github.com/cloudflare/workers-sdk/tree/HEAD/packages/miniflare))
| [`3.20241230.1` ->
`3.20241230.2`](https://renovatebot.com/diffs/npm/miniflare/3.20241230.1/3.20241230.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/miniflare/3.20241230.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/miniflare/3.20241230.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/miniflare/3.20241230.1/3.20241230.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/miniflare/3.20241230.1/3.20241230.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [postcss](https://postcss.org/)
([source](https://redirect.github.com/postcss/postcss)) | [`8.4.49` ->
`8.5.1`](https://renovatebot.com/diffs/npm/postcss/8.4.49/8.5.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/postcss/8.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/postcss/8.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/postcss/8.4.49/8.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/postcss/8.4.49/8.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [wrangler](https://redirect.github.com/cloudflare/workers-sdk)
([source](https://redirect.github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler))
| [`3.101.0` ->
`3.103.2`](https://renovatebot.com/diffs/npm/wrangler/3.101.0/3.103.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/wrangler/3.103.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/wrangler/3.103.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/wrangler/3.101.0/3.103.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/wrangler/3.101.0/3.103.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Release Notes

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/eslint-plugin)</summary>

###
[`v8.20.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8200-2025-01-13)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.19.1...v8.20.0)

##### 🚀 Features

- **eslint-plugin:** \[consistent-type-assertions] add
arrayLiteralTypeAssertions options
([#&#8203;10565](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10565))
- **eslint-plugin:** \[no-deprecated] add allow options
([#&#8203;10585](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10585))
- **eslint-plugin:** \[no-misused-spread] add new rule
([#&#8203;10551](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10551))

##### 🩹 Fixes

- **eslint-plugin:** \[no-unnecessary-condition] don't flag optional
chaining for union types with an unconstrained type parameters
([#&#8203;10602](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10602))
- **eslint-plugin:** \[no-shadow] ignore ordering of type declarations
([#&#8203;10593](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10593))

##### ❤️ Thank You

-   Josh Goldberg 
-   Ronen Amiel
-   YeonJuan [@&#8203;yeonjuan](https://redirect.github.com/yeonjuan)

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

</details>

<details>
<summary>typescript-eslint/typescript-eslint
(@&#8203;typescript-eslint/parser)</summary>

###
[`v8.20.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8200-2025-01-13)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.19.1...v8.20.0)

This was a version bump only for parser to align it with other projects,
there were no code changes.

You can read about our [versioning
strategy](https://main--typescript-eslint.netlify.app/users/versioning)
and
[releases](https://main--typescript-eslint.netlify.app/users/releases)
on our website.

</details>

<details>
<summary>prettier/eslint-config-prettier
(eslint-config-prettier)</summary>

###
[`v10.0.1`](https://redirect.github.com/prettier/eslint-config-prettier/releases/tag/v10.0.1)

[Compare
Source](https://redirect.github.com/prettier/eslint-config-prettier/compare/v10.0.0...v10.0.1)

### eslint-config-prettier

#### 10.0.1

#### What's Changed

- chore: migrate to changeset for automatically releasing by
[@&#8203;JounQin](https://redirect.github.com/JounQin) in
[https://github.com/prettier/eslint-config-prettier/pull/278](https://redirect.github.com/prettier/eslint-config-prettier/pull/278)
- add support for `@stylistic/eslint-plugin` by
[@&#8203;abrahamguo](https://redirect.github.com/abrahamguo) in
[https://github.com/prettier/eslint-config-prettier/pull/272](https://redirect.github.com/prettier/eslint-config-prettier/pull/272)

#### New Contributors

- [@&#8203;JounQin](https://redirect.github.com/JounQin) made their
first contribution in
[https://github.com/prettier/eslint-config-prettier/pull/278](https://redirect.github.com/prettier/eslint-config-prettier/pull/278)
- [@&#8203;abrahamguo](https://redirect.github.com/abrahamguo) made
their first contribution in
[https://github.com/prettier/eslint-config-prettier/pull/272](https://redirect.github.com/prettier/eslint-config-prettier/pull/272)

**Full Changelog**:
https://github.com/prettier/eslint-config-prettier/compare/v9.1.0...v10.0.1

###
[`v10.0.0`](https://redirect.github.com/prettier/eslint-config-prettier/blob/HEAD/CHANGELOG.md#1000)

[Compare
Source](https://redirect.github.com/prettier/eslint-config-prettier/compare/v9.1.0...v10.0.0)

##### Major Changes

-
[#&#8203;272](https://redirect.github.com/prettier/eslint-config-prettier/pull/272)
[`5be64be`](5be64bef68)
Thanks [@&#8203;abrahamguo](https://redirect.github.com/abrahamguo)! -
add support for
[@&#8203;stylistic](https://redirect.github.com/stylistic) formatting
rules

</details>

<details>
<summary>jsx-eslint/eslint-plugin-react (eslint-plugin-react)</summary>

###
[`v7.37.4`](https://redirect.github.com/jsx-eslint/eslint-plugin-react/blob/HEAD/CHANGELOG.md#7374---20250112)

[Compare
Source](https://redirect.github.com/jsx-eslint/eslint-plugin-react/compare/v7.37.3...v7.37.4)

##### Fixed

- \[`no-unknown-property`]: support `onBeforeToggle`, `popoverTarget`,
`popoverTargetAction` attributes ([#&#8203;3865][]
[@&#8203;acusti](https://redirect.github.com/acusti))
- \[types] fix types of flat configs ([#&#8203;3874][]
[@&#8203;ljharb](https://redirect.github.com/ljharb))

[7.37.4]:
https://redirect.github.com/jsx-eslint/eslint-plugin-react/compare/v7.37.3...v7.37.4

[#&#8203;3874]:
https://redirect.github.com/jsx-eslint/eslint-plugin-react/pull/3874

[#&#8203;3865]:
https://redirect.github.com/jsx-eslint/eslint-plugin-react/pull/3865

</details>

<details>
<summary>cloudflare/workers-sdk (miniflare)</summary>

###
[`v3.20241230.2`](https://redirect.github.com/cloudflare/workers-sdk/blob/HEAD/packages/miniflare/CHANGELOG.md#3202412302)

[Compare
Source](https://redirect.github.com/cloudflare/workers-sdk/compare/miniflare@3.20241230.1...miniflare@3.20241230.2)

##### Patch Changes

-
[#&#8203;7738](https://redirect.github.com/cloudflare/workers-sdk/pull/7738)
[`8e9aa40`](8e9aa40a6c)
Thanks [@&#8203;penalosa](https://redirect.github.com/penalosa)! - Use
TEXT bindings for plain text values in Miniflare. This is an internal
detail that should have no user facing impact.

</details>

<details>
<summary>postcss/postcss (postcss)</summary>

###
[`v8.5.1`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#851)

[Compare
Source](https://redirect.github.com/postcss/postcss/compare/8.5.0...8.5.1)

- Fixed backwards compatibility for complex cases (by
[@&#8203;romainmenke](https://redirect.github.com/romainmenke)).

###
[`v8.5.0`](https://redirect.github.com/postcss/postcss/releases/tag/8.5.0):
8.5 “Duke Alloces”

[Compare
Source](https://redirect.github.com/postcss/postcss/compare/8.4.49...8.5.0)

<img
src="https://github.com/user-attachments/assets/6ef654a0-d675-4ba0-a670-e28ef27062f5"
align="right" width="200" height="200" alt="President Alloces seal">

PostCSS 8.5 brought API to work better with non-CSS sources like HTML,
Vue.js/Svelte sources or CSS-in-JS.

[@&#8203;romainmenke](https://redirect.github.com/romainmenke) during
[his work](https://redirect.github.com/postcss/postcss/issues/1995) on
[Stylelint](https://stylelint.io) added `Input#document` in additional
to `Input#css`.

```js
root.source.input.document //=> "<p>Hello</p>
                           //    <style>
                           //    p {
                           //      color: green;
                           //    }
                           //    </style>"
root.source.input.css      //=> "p {
                           //      color: green;
                           //    }"

```

#### Thanks to Sponsors

This release was possible thanks to our community.

If your company wants to support the sustainability of front-end
infrastructure or wants to give some love to PostCSS, you can join our
supporters by:

- [**Tidelift**](https://tidelift.com/) with a Spotify-like subscription
model supporting all projects from your lock file.
- Direct donations at [**GitHub
Sponsors**](https://redirect.github.com/sponsors/ai) or [**Open
Collective**](https://opencollective.com/postcss#section-contributors).

</details>

<details>
<summary>cloudflare/workers-sdk (wrangler)</summary>

###
[`v3.103.2`](https://redirect.github.com/cloudflare/workers-sdk/blob/HEAD/packages/wrangler/CHANGELOG.md#31032)

[Compare
Source](https://redirect.github.com/cloudflare/workers-sdk/compare/wrangler@3.103.1...wrangler@3.103.2)

##### Patch Changes

-
[#&#8203;7804](https://redirect.github.com/cloudflare/workers-sdk/pull/7804)
[`16a9460`](16a9460ea6)
Thanks [@&#8203;vicb](https://redirect.github.com/vicb)! -
fix(wrangler): use require.resolve to resolve unenv path

###
[`v3.103.1`](https://redirect.github.com/cloudflare/workers-sdk/blob/HEAD/packages/wrangler/CHANGELOG.md#31031)

[Compare
Source](https://redirect.github.com/cloudflare/workers-sdk/compare/wrangler@3.103.0...wrangler@3.103.1)

##### Patch Changes

-
[#&#8203;7798](https://redirect.github.com/cloudflare/workers-sdk/pull/7798)
[`a1ff045`](a1ff045cfc)
Thanks
[@&#8203;CarmenPopoviciu](https://redirect.github.com/CarmenPopoviciu)!
- Reverts
[#&#8203;7720](https://redirect.github.com/cloudflare/workers-sdk/issues/7720)
as it introduced breakage in some of the C3 templates (eg. Nuxt)

###
[`v3.103.0`](https://redirect.github.com/cloudflare/workers-sdk/blob/HEAD/packages/wrangler/CHANGELOG.md#31030)

[Compare
Source](https://redirect.github.com/cloudflare/workers-sdk/compare/wrangler@3.102.0...wrangler@3.103.0)

##### Minor Changes

-
[#&#8203;5086](https://redirect.github.com/cloudflare/workers-sdk/pull/5086)
[`8faf2c0`](8faf2c0741)
Thanks
[@&#8203;dario-piotrowicz](https://redirect.github.com/dario-piotrowicz)!
- add `--strict-vars` option to `wrangler types`

add a new `--strict-vars` option to `wrangler types` that developers can
(by setting the
flag to `false`) use to disable the default strict/literal types
generation for their variables

opting out of strict variables can be useful when developers change
often their `vars` values,
    even more so when multiple environments are involved

###
[`v3.102.0`](https://redirect.github.com/cloudflare/workers-sdk/blob/HEAD/packages/wrangler/CHANGELOG.md#31020)

[Compare
Source](https://redirect.github.com/cloudflare/workers-sdk/compare/wrangler@3.101.0...wrangler@3.102.0)

##### Minor Changes

-
[#&#8203;7592](https://redirect.github.com/cloudflare/workers-sdk/pull/7592)
[`f613276`](f6132761c8)
Thanks [@&#8203;garrettgu10](https://redirect.github.com/garrettgu10)! -
New filter validation logic supporting set and range queries in
Vectorize CLI

##### Patch Changes

-
[#&#8203;7750](https://redirect.github.com/cloudflare/workers-sdk/pull/7750)
[`df0e5be`](df0e5bef81)
Thanks [@&#8203;andyjessop](https://redirect.github.com/andyjessop)! -
bug: Removes the (local) tag on Vectorize bindings in the console output
of `wrangler dev`, and adds-in the same tag for Durable Objects (which
are emulated locally in `wrangler dev`).

-
[#&#8203;7732](https://redirect.github.com/cloudflare/workers-sdk/pull/7732)
[`d102b60`](d102b60238)
Thanks [@&#8203;Ankcorn](https://redirect.github.com/Ankcorn)! - fix
pages secret bulk copy

-
[#&#8203;7706](https://redirect.github.com/cloudflare/workers-sdk/pull/7706)
[`c63f1b0`](c63f1b0790)
Thanks [@&#8203;penalosa](https://redirect.github.com/penalosa)! -
Remove the server-based dev registry in favour of the more stable
file-based dev registry. There should be no user-facing impact.

- Updated dependencies
\[[`8e9aa40`](8e9aa40a6c)]:
    -   miniflare@3.20241230.2

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/astral-sh/ruff).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xMDcuMCIsInVwZGF0ZWRJblZlciI6IjM5LjEwNy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 10:25:36 +05:30
Dhruv Manilawala
613951d848 Ignore notebook with syntax error in ecosystem (#15604)
I'll open a PR in `openai/openai-cookbook` to fix these syntax errors
later but for now let's just ignore the notebook.

<img width="2560" alt="Screenshot 2025-01-20 at 10 17 43 AM"
src="https://github.com/user-attachments/assets/075127e4-956d-43f9-b175-b492600dbdee"
/>
2025-01-20 04:53:22 +00:00
renovate[bot]
070c160fd5 Update dependency tomli_w to v1.2.0 (#15600)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [tomli_w](https://redirect.github.com/hukkin/tomli-w)
([changelog](https://redirect.github.com/hukkin/tomli-w/blob/master/CHANGELOG.md))
| `==1.1.0` -> `==1.2.0` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/tomli-w/1.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/tomli-w/1.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/tomli-w/1.1.0/1.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/tomli-w/1.1.0/1.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

> [!WARNING]
> Some dependencies could not be looked up. Check the Dependency
Dashboard for more information.

---

### Release Notes

<details>
<summary>hukkin/tomli-w (tomli_w)</summary>

###
[`v1.2.0`](https://redirect.github.com/hukkin/tomli-w/blob/HEAD/CHANGELOG.md#120)

[Compare
Source](https://redirect.github.com/hukkin/tomli-w/compare/1.1.0...1.2.0)

-   Added
    -   Always preserve `decimal.Decimal` type in parse round trips
-   Improved
    -   Better `TypeError` message on invalid mapping keys
    -   Unify type representation in error messages
-   Performance
    -   Improve import time by removing `typing` import
    -   Improve import time by removing `string` import
    -   Improve import time by lazy importing `decimal`

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/astral-sh/ruff).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xMDcuMCIsInVwZGF0ZWRJblZlciI6IjM5LjEwNy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 10:18:43 +05:30
renovate[bot]
c0383daf58 Update Rust crate similar to v2.7.0 (#15602) 2025-01-19 22:46:45 -05:00
renovate[bot]
780335b50d Update Rust crate uuid to v1.12.0 (#15599) 2025-01-19 22:45:12 -05:00
renovate[bot]
07f2308557 Update cloudflare/wrangler-action action to v3.13.1 (#15594) 2025-01-19 22:31:47 -05:00
renovate[bot]
06d9f8ba00 Update Rust crate tracing-indicatif to v0.3.9 (#15593) 2025-01-19 22:31:38 -05:00
renovate[bot]
57a84a3354 Update dependency ruff to v0.9.2 (#15595) 2025-01-19 22:31:26 -05:00
renovate[bot]
b49dee0959 Update Rust crate bitflags to v2.8.0 (#15597) 2025-01-19 22:31:19 -05:00
renovate[bot]
68755ac1e3 Update Rust crate ordermap to v0.5.5 (#15591) 2025-01-19 22:31:02 -05:00
renovate[bot]
b9402688b1 Update Rust crate serde_json to v1.0.137 (#15592) 2025-01-19 22:30:54 -05:00
renovate[bot]
75eccfd2a2 Update Rust crate log to v0.4.25 (#15590) 2025-01-19 22:30:32 -05:00
renovate[bot]
3c043e7e70 Update Rust crate indexmap to v2.7.1 (#15589) 2025-01-19 22:30:24 -05: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
9730ff3a25 Generate documentation redirects for lowercase rule codes (#15564)
## Summary

Resolves #15016.

## Test Plan

Generate the docs with:

```console
uv run --with-requirements docs/requirements-insiders.txt scripts/generate_mkdocs.py
```

and, check whether the mapping was created in `mkdocs.generated.yml` and run the server using:

```console
uvx --with-requirements docs/requirements-insiders.txt -- mkdocs serve -f mkdocs.insiders.yml -o
```
2025-01-18 10:09:23 +05:30
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
Brent Westbrook
e2da33a45c [unconventional-import-alias] Fix infinite loop between ICN001 and I002 (ICN001) (#15480)
## Summary

This fixes the infinite loop reported in #14389 by raising an error to
the user about conflicting ICN001 (`unconventional-import-alias`) and
I002 (`missing-required-import`) configuration options.

## Test Plan

Added a CLI integration test reproducing the old behavior and then
confirming the fix.

Closes #14389

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-16 10:45:24 -05:00
Brent Westbrook
ca3b210f2e [pyflakes] Fix infinite loop with unused local import in __init__.py (F401) (#15517)
## Summary

This fixes the infinite loop reported in #12897, where an
`unused-import` that is undefined at the scope of `__all__` is "fixed"
by adding it to `__all__` repeatedly. These changes make it so that only
imports in the global scope will be suggested to add to `__all__` and
the unused local import is simply removed.

## Test Plan

Added a CLI integration test that sets up the same module structure as
the original report

Closes #12897

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-16 10:43:32 -05:00
InSync
6f0b66278f [red-knot] Migrate is_fully_static/is_single_valued/is_singleton unit tests to Markdown tests (#15533)
## Summary

Part of #15397.

## Test Plan

Markdown tests.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-16 07:40:41 -08:00
InSync
aed0bf1c11 [ruff] itertools.starmap(..., zip(...)) (RUF058) (#15483)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-01-16 15:18:12 +01:00
669 changed files with 16411 additions and 13929 deletions

4
.gitattributes vendored
View File

@@ -14,5 +14,7 @@ crates/ruff_python_parser/resources/invalid/re_lex_logical_token_mac_eol.py text
crates/ruff_python_parser/resources/inline linguist-generated=true
ruff.schema.json linguist-generated=true text=auto eol=lf
ruff.schema.json -diff linguist-generated=true text=auto eol=lf
crates/ruff_python_ast/src/generated.rs -diff linguist-generated=true text=auto eol=lf
crates/ruff_python_formatter/src/generated.rs -diff linguist-generated=true text=auto eol=lf
*.md.snap linguist-language=Markdown

View File

@@ -6,4 +6,5 @@ self-hosted-runner:
labels:
- depot-ubuntu-latest-8
- depot-ubuntu-22.04-16
- windows-latest-xlarge
- github-windows-2025-x86_64-8
- github-windows-2025-x86_64-16

View File

@@ -203,7 +203,7 @@ jobs:
cargo-test-windows:
name: "cargo test (windows)"
runs-on: windows-latest-xlarge
runs-on: github-windows-2025-x86_64-16
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
timeout-minutes: 20
@@ -386,6 +386,12 @@ jobs:
- name: "Install Rust toolchain"
run: rustup component add rustfmt
- uses: Swatinem/rust-cache@v2
# Run all code generation scripts, and verify that the current output is
# already checked into git.
- run: python crates/ruff_python_ast/generate.py
- run: python crates/ruff_python_formatter/generate.py
- run: test -z "$(git status --porcelain)"
# Verify that adding a plugin or rule produces clean code.
- run: ./scripts/add_rule.py --name DoTheThing --prefix F --code 999 --linter pyflakes
- run: cargo check
- run: cargo fmt --all --check

View File

@@ -49,7 +49,7 @@ jobs:
working-directory: playground
- name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@v3.13.0
uses: cloudflare/wrangler-action@v3.13.1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}

View File

@@ -55,9 +55,3 @@ jobs:
run: npm publish --provenance --access public crates/ruff_wasm/pkg
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Archive npm failure logs
uses: actions/upload-artifact@v4
if: failure()
with:
name: npm-logs
path: ~/.npm/_logs

View File

@@ -202,6 +202,20 @@ jobs:
name: artifacts-dist-manifest
path: dist-manifest.json
custom-publish-pypi:
needs:
- plan
- host
if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
uses: ./.github/workflows/publish-pypi.yml
with:
plan: ${{ needs.plan.outputs.val }}
secrets: inherit
# publish jobs get escalated permissions
permissions:
"id-token": "write"
"packages": "write"
custom-publish-wasm:
needs:
- plan
@@ -222,11 +236,12 @@ jobs:
needs:
- plan
- host
- custom-publish-pypi
- custom-publish-wasm
# use "always() && ..." to allow us to wait for all publish jobs while
# still allowing individual publish jobs to skip themselves (for prereleases).
# "host" however must run to completion, no skipping allowed!
if: ${{ always() && needs.host.result == 'success' && (needs.custom-publish-wasm.result == 'skipped' || needs.custom-publish-wasm.result == 'success') }}
if: ${{ always() && needs.host.result == 'success' && (needs.custom-publish-pypi.result == 'skipped' || needs.custom-publish-pypi.result == 'success') && (needs.custom-publish-wasm.result == 'skipped' || needs.custom-publish-wasm.result == 'success') }}
runs-on: "ubuntu-20.04"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -4,7 +4,7 @@ exclude: |
(?x)^(
.github/workflows/release.yml|
crates/red_knot_vendored/vendor/.*|
crates/red_knot_workspace/resources/.*|
crates/red_knot_project/resources/.*|
crates/ruff_linter/resources/.*|
crates/ruff_linter/src/rules/.*/snapshots/.*|
crates/ruff_notebook/resources/.*|
@@ -73,7 +73,7 @@ repos:
pass_filenames: false # This makes it a lot faster
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.1
rev: v0.9.2
hooks:
- id: ruff-format
- id: ruff
@@ -91,7 +91,7 @@ repos:
# zizmor detects security vulnerabilities in GitHub Actions workflows.
# Additional configuration for the tool is found in `.github/zizmor.yml`
- repo: https://github.com/woodruffw/zizmor-pre-commit
rev: v1.0.1
rev: v1.1.1
hooks:
- id: zizmor
@@ -103,7 +103,7 @@ repos:
# `actionlint` hook, for verifying correct syntax in GitHub Actions workflows.
# Some additional configuration for `actionlint` can be found in `.github/actionlint.yaml`.
- repo: https://github.com/rhysd/actionlint
rev: v1.7.6
rev: v1.7.7
hooks:
- id: actionlint
stages:

157
Cargo.lock generated
View File

@@ -212,9 +212,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.7.0"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "block-buffer"
@@ -477,7 +477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
dependencies = [
"lazy_static",
"windows-sys 0.48.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -1062,7 +1062,7 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
"ignore",
"walkdir",
]
@@ -1343,9 +1343,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.7.0"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
dependencies = [
"equivalent",
"hashbrown 0.15.2",
@@ -1374,11 +1374,11 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
[[package]]
name = "inotify"
version = "0.10.2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
"bitflags 1.3.2",
"bitflags 2.8.0",
"inotify-sys",
"libc",
]
@@ -1422,15 +1422,6 @@ dependencies = [
"serde_json",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "is-docker"
version = "0.2.0"
@@ -1610,7 +1601,7 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
"libc",
"redox_syscall 0.5.3",
]
@@ -1657,9 +1648,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.22"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
[[package]]
name = "lsp-server"
@@ -1781,7 +1772,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
"cfg-if",
"cfg_aliases",
"libc",
@@ -1805,11 +1796,11 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "notify"
version = "7.0.0"
version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009"
checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
"filetime",
"fsevent-sys",
"inotify",
@@ -1819,17 +1810,14 @@ dependencies = [
"mio",
"notify-types",
"walkdir",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
name = "notify-types"
version = "1.0.0"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7393c226621f817964ffb3dc5704f9509e107a8b024b489cc2c1b217378785df"
dependencies = [
"instant",
]
checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d"
[[package]]
name = "nu-ansi-term"
@@ -1895,9 +1883,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "ordermap"
version = "0.5.4"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f80a48eb68b6a7da9829b8b0429011708f775af80676a91063d023a66a656106"
checksum = "c55fdf45a2b1e929e3656d404395767e05c98b6ebd8157eb31e370077d545160"
dependencies = [
"indexmap",
]
@@ -2336,25 +2324,55 @@ dependencies = [
"crossbeam",
"ctrlc",
"filetime",
"insta",
"insta-cmd",
"rayon",
"red_knot_project",
"red_knot_python_semantic",
"red_knot_server",
"red_knot_workspace",
"regex",
"ruff_db",
"salsa",
"tempfile",
"toml",
"tracing",
"tracing-flame",
"tracing-subscriber",
"tracing-tree",
]
[[package]]
name = "red_knot_project"
version = "0.0.0"
dependencies = [
"anyhow",
"crossbeam",
"glob",
"insta",
"notify",
"pep440_rs",
"rayon",
"red_knot_python_semantic",
"red_knot_vendored",
"ruff_cache",
"ruff_db",
"ruff_macros",
"ruff_python_ast",
"ruff_text_size",
"rustc-hash 2.1.0",
"salsa",
"serde",
"thiserror 2.0.11",
"toml",
"tracing",
]
[[package]]
name = "red_knot_python_semantic"
version = "0.0.0"
dependencies = [
"anyhow",
"bitflags 2.7.0",
"bitflags 2.8.0",
"camino",
"compact_str",
"countme",
@@ -2401,7 +2419,7 @@ dependencies = [
"libc",
"lsp-server",
"lsp-types",
"red_knot_workspace",
"red_knot_project",
"ruff_db",
"ruff_notebook",
"ruff_python_ast",
@@ -2456,39 +2474,14 @@ dependencies = [
"console_log",
"js-sys",
"log",
"red_knot_project",
"red_knot_python_semantic",
"red_knot_workspace",
"ruff_db",
"ruff_notebook",
"wasm-bindgen",
"wasm-bindgen-test",
]
[[package]]
name = "red_knot_workspace"
version = "0.0.0"
dependencies = [
"anyhow",
"crossbeam",
"glob",
"insta",
"notify",
"pep440_rs",
"rayon",
"red_knot_python_semantic",
"red_knot_vendored",
"ruff_cache",
"ruff_db",
"ruff_python_ast",
"ruff_text_size",
"rustc-hash 2.1.0",
"salsa",
"serde",
"thiserror 2.0.11",
"toml",
"tracing",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
@@ -2504,7 +2497,7 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
]
[[package]]
@@ -2596,7 +2589,7 @@ dependencies = [
"argfile",
"assert_fs",
"bincode",
"bitflags 2.7.0",
"bitflags 2.8.0",
"cachedir",
"chrono",
"clap",
@@ -2668,8 +2661,8 @@ dependencies = [
"criterion",
"mimalloc",
"rayon",
"red_knot_project",
"red_knot_python_semantic",
"red_knot_workspace",
"ruff_db",
"ruff_linter",
"ruff_python_ast",
@@ -2828,7 +2821,7 @@ version = "0.9.2"
dependencies = [
"aho-corasick",
"anyhow",
"bitflags 2.7.0",
"bitflags 2.8.0",
"chrono",
"clap",
"colored 3.0.0",
@@ -2918,7 +2911,7 @@ name = "ruff_python_ast"
version = "0.0.0"
dependencies = [
"aho-corasick",
"bitflags 2.7.0",
"bitflags 2.8.0",
"compact_str",
"is-macro",
"itertools 0.14.0",
@@ -3000,7 +2993,7 @@ dependencies = [
name = "ruff_python_literal"
version = "0.0.0"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
"itertools 0.14.0",
"ruff_python_ast",
"unic-ucd-category",
@@ -3011,7 +3004,7 @@ name = "ruff_python_parser"
version = "0.0.0"
dependencies = [
"anyhow",
"bitflags 2.7.0",
"bitflags 2.8.0",
"bstr",
"compact_str",
"insta",
@@ -3043,7 +3036,7 @@ dependencies = [
name = "ruff_python_semantic"
version = "0.0.0"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
"is-macro",
"ruff_cache",
"ruff_index",
@@ -3062,7 +3055,7 @@ dependencies = [
name = "ruff_python_stdlib"
version = "0.0.0"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
"unicode-ident",
]
@@ -3229,7 +3222,7 @@ version = "0.38.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
dependencies = [
"bitflags 2.7.0",
"bitflags 2.8.0",
"errno",
"libc",
"linux-raw-sys",
@@ -3412,9 +3405,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.135"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b"
dependencies = [
"itoa",
"memchr",
@@ -3511,9 +3504,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "similar"
version = "2.6.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
[[package]]
name = "siphasher"
@@ -3933,9 +3926,9 @@ dependencies = [
[[package]]
name = "tracing-indicatif"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74ba258e9de86447f75edf6455fded8e5242704c6fccffe7bf8d7fb6daef1180"
checksum = "8201ca430e0cd893ef978226fd3516c06d9c494181c8bf4e5b32e30ed4b40aa1"
dependencies = [
"indicatif",
"tracing",
@@ -4176,9 +4169,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "uuid"
version = "1.11.1"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4"
checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4"
dependencies = [
"getrandom",
"rand",
@@ -4188,9 +4181,9 @@ dependencies = [
[[package]]
name = "uuid-macro-internal"
version = "1.11.1"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c91084647266237a48351d05d55dee65bba9e1b597f555fcf54680f820284a1c"
checksum = "144b419c512fdd5eaa4c2998813e32aaab2b257746ee038de93985a99635501d"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -41,7 +41,7 @@ ruff_workspace = { path = "crates/ruff_workspace" }
red_knot_python_semantic = { path = "crates/red_knot_python_semantic" }
red_knot_server = { path = "crates/red_knot_server" }
red_knot_test = { path = "crates/red_knot_test" }
red_knot_workspace = { path = "crates/red_knot_workspace", default-features = false }
red_knot_project = { path = "crates/red_knot_project", default-features = false }
aho-corasick = { version = "1.1.3" }
anstream = { version = "0.6.18" }
@@ -105,7 +105,7 @@ matchit = { version = "0.8.1" }
memchr = { version = "2.7.1" }
mimalloc = { version = "0.1.39" }
natord = { version = "1.0.9" }
notify = { version = "7.0.0" }
notify = { version = "8.0.0" }
ordermap = { version = "0.5.0" }
path-absolutize = { version = "3.1.1" }
path-slash = { version = "0.2.1" }
@@ -303,7 +303,7 @@ build-local-artifacts = false
# Local artifacts jobs to run in CI
local-artifacts-jobs = ["./build-binaries", "./build-docker"]
# Publish jobs to run in CI
publish-jobs = ["./publish-wasm"]
publish-jobs = ["./publish-pypi", "./publish-wasm"]
# Post-announce jobs to run in CI
post-announce-jobs = ["./notify-dependents", "./publish-docs", "./publish-playground"]
# Custom permissions for GitHub Jobs

View File

@@ -13,7 +13,7 @@ license.workspace = true
[dependencies]
red_knot_python_semantic = { workspace = true }
red_knot_workspace = { workspace = true, features = ["zstd"] }
red_knot_project = { workspace = true, features = ["zstd"] }
red_knot_server = { workspace = true }
ruff_db = { workspace = true, features = ["os", "cache"] }
@@ -32,9 +32,14 @@ tracing-flame = { workspace = true }
tracing-tree = { workspace = true }
[dev-dependencies]
filetime = { workspace = true }
tempfile = { workspace = true }
ruff_db = { workspace = true, features = ["testing"] }
insta = { workspace = true, features = ["filters"] }
insta-cmd = { workspace = true }
filetime = { workspace = true }
regex = { workspace = true }
tempfile = { workspace = true }
toml = { workspace = true }
[lints]
workspace = true

View File

@@ -6,13 +6,11 @@ use clap::Parser;
use colored::Colorize;
use crossbeam::channel as crossbeam_channel;
use python_version::PythonVersion;
use red_knot_python_semantic::SitePackages;
use red_knot_project::metadata::options::{EnvironmentOptions, Options};
use red_knot_project::watch;
use red_knot_project::watch::ProjectWatcher;
use red_knot_project::{ProjectDatabase, ProjectMetadata};
use red_knot_server::run_server;
use red_knot_workspace::db::ProjectDatabase;
use red_knot_workspace::project::settings::Configuration;
use red_knot_workspace::project::ProjectMetadata;
use red_knot_workspace::watch;
use red_knot_workspace::watch::ProjectWatcher;
use ruff_db::diagnostic::Diagnostic;
use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf};
use salsa::plumbing::ZalsaDatabase;
@@ -71,31 +69,28 @@ struct Args {
}
impl Args {
fn to_configuration(&self, cli_cwd: &SystemPath) -> Configuration {
let mut configuration = Configuration::default();
if let Some(python_version) = self.python_version {
configuration.python_version = Some(python_version.into());
fn to_options(&self, cli_cwd: &SystemPath) -> Options {
Options {
environment: Some(EnvironmentOptions {
python_version: self.python_version.map(Into::into),
venv_path: self
.venv_path
.as_ref()
.map(|venv_path| SystemPath::absolute(venv_path, cli_cwd)),
typeshed: self
.typeshed
.as_ref()
.map(|typeshed| SystemPath::absolute(typeshed, cli_cwd)),
extra_paths: self.extra_search_path.as_ref().map(|extra_search_paths| {
extra_search_paths
.iter()
.map(|path| SystemPath::absolute(path, cli_cwd))
.collect()
}),
..EnvironmentOptions::default()
}),
..Default::default()
}
if let Some(venv_path) = &self.venv_path {
configuration.search_paths.site_packages = Some(SitePackages::Derived {
venv_path: SystemPath::absolute(venv_path, cli_cwd),
});
}
if let Some(typeshed) = &self.typeshed {
configuration.search_paths.typeshed = Some(SystemPath::absolute(typeshed, cli_cwd));
}
if let Some(extra_search_paths) = &self.extra_search_path {
configuration.search_paths.extra_paths = extra_search_paths
.iter()
.map(|path| Some(SystemPath::absolute(path, cli_cwd)))
.collect();
}
configuration
}
}
@@ -164,18 +159,13 @@ fn run() -> anyhow::Result<ExitStatus> {
.unwrap_or_else(|| cli_base_path.clone());
let system = OsSystem::new(cwd.clone());
let cli_configuration = args.to_configuration(&cwd);
let workspace_metadata = ProjectMetadata::discover(
system.current_directory(),
&system,
Some(&cli_configuration),
)?;
let cli_options = args.to_options(&cwd);
let mut workspace_metadata = ProjectMetadata::discover(system.current_directory(), &system)?;
workspace_metadata.apply_cli_options(cli_options.clone());
// TODO: Use the `program_settings` to compute the key for the database's persistent
// cache and load the cache if it exists.
let mut db = ProjectDatabase::new(workspace_metadata, system)?;
let (main_loop, main_loop_cancellation_token) = MainLoop::new(cli_configuration);
let (main_loop, main_loop_cancellation_token) = MainLoop::new(cli_options);
// Listen to Ctrl+C and abort the watch mode.
let main_loop_cancellation_token = Mutex::new(Some(main_loop_cancellation_token));
@@ -228,11 +218,11 @@ struct MainLoop {
/// The file system watcher, if running in watch mode.
watcher: Option<ProjectWatcher>,
cli_configuration: Configuration,
cli_options: Options,
}
impl MainLoop {
fn new(cli_configuration: Configuration) -> (Self, MainLoopCancellationToken) {
fn new(cli_options: Options) -> (Self, MainLoopCancellationToken) {
let (sender, receiver) = crossbeam_channel::bounded(10);
(
@@ -240,7 +230,7 @@ impl MainLoop {
sender: sender.clone(),
receiver,
watcher: None,
cli_configuration,
cli_options,
},
MainLoopCancellationToken { sender },
)
@@ -324,7 +314,7 @@ impl MainLoop {
MainLoopMessage::ApplyChanges(changes) => {
revision += 1;
// Automatically cancels any pending queries and waits for them to complete.
db.apply_changes(changes, Some(&self.cli_configuration));
db.apply_changes(changes, Some(&self.cli_options));
if let Some(watcher) = self.watcher.as_mut() {
watcher.update(db);
}

View File

@@ -0,0 +1,60 @@
use anyhow::Context;
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
use std::process::Command;
use tempfile::TempDir;
/// Specifying an option on the CLI should take precedence over the same setting in the
/// project's configuration.
#[test]
fn test_config_override() -> anyhow::Result<()> {
let tempdir = TempDir::new()?;
std::fs::write(
tempdir.path().join("pyproject.toml"),
r#"
[tool.knot.environment]
python-version = "3.11"
"#,
)
.context("Failed to write settings")?;
std::fs::write(
tempdir.path().join("test.py"),
r#"
import sys
# Access `sys.last_exc` that was only added in Python 3.12
print(sys.last_exc)
"#,
)
.context("Failed to write test.py")?;
insta::with_settings!({filters => vec![(&*tempdir_filter(&tempdir), "<temp_dir>/")]}, {
assert_cmd_snapshot!(knot().arg("--project").arg(tempdir.path()), @r"
success: false
exit_code: 1
----- stdout -----
error[lint:unresolved-attribute] <temp_dir>/test.py:5:7 Type `<module 'sys'>` has no attribute `last_exc`
----- stderr -----
");
});
assert_cmd_snapshot!(knot().arg("--project").arg(tempdir.path()).arg("--python-version").arg("3.12"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
");
Ok(())
}
fn knot() -> Command {
Command::new(get_cargo_bin("red_knot"))
}
fn tempdir_filter(tempdir: &TempDir) -> String {
format!(r"{}\\?/?", regex::escape(tempdir.path().to_str().unwrap()))
}

View File

@@ -4,11 +4,11 @@ use std::io::Write;
use std::time::{Duration, Instant};
use anyhow::{anyhow, Context};
use red_knot_python_semantic::{resolve_module, ModuleName, Program, PythonVersion, SitePackages};
use red_knot_workspace::db::{Db, ProjectDatabase};
use red_knot_workspace::project::settings::{Configuration, SearchPathConfiguration};
use red_knot_workspace::project::ProjectMetadata;
use red_knot_workspace::watch::{directory_watcher, ChangeEvent, ProjectWatcher};
use red_knot_project::metadata::options::{EnvironmentOptions, Options};
use red_knot_project::metadata::pyproject::{PyProject, Tool};
use red_knot_project::watch::{directory_watcher, ChangeEvent, ProjectWatcher};
use red_knot_project::{Db, ProjectDatabase, ProjectMetadata};
use red_knot_python_semantic::{resolve_module, ModuleName, PythonPlatform, PythonVersion};
use ruff_db::files::{system_path_to_file, File, FileError};
use ruff_db::source::source_text;
use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf};
@@ -22,7 +22,6 @@ struct TestCase {
/// We need to hold on to it in the test case or the temp files get deleted.
_temp_dir: tempfile::TempDir,
root_dir: SystemPathBuf,
configuration: Configuration,
}
impl TestCase {
@@ -112,19 +111,44 @@ impl TestCase {
Ok(all_events)
}
fn take_watch_changes(&self) -> Vec<ChangeEvent> {
self.try_take_watch_changes(Duration::from_secs(10))
fn take_watch_changes<M: MatchEvent>(&self, matcher: M) -> Vec<ChangeEvent> {
self.try_take_watch_changes(matcher, Duration::from_secs(10))
.expect("Expected watch changes but observed none")
}
fn try_take_watch_changes(&self, timeout: Duration) -> Option<Vec<ChangeEvent>> {
let watcher = self.watcher.as_ref()?;
fn try_take_watch_changes<M: MatchEvent>(
&self,
mut matcher: M,
timeout: Duration,
) -> Result<Vec<ChangeEvent>, Vec<ChangeEvent>> {
let watcher = self
.watcher
.as_ref()
.expect("Cannot call `try_take_watch_changes` after `stop_watch`");
let mut all_events = self
.changes_receiver
.recv_timeout(timeout)
.unwrap_or_default();
watcher.flush();
let start = Instant::now();
let mut all_events = Vec::new();
loop {
let events = self
.changes_receiver
.recv_timeout(Duration::from_millis(100))
.unwrap_or_default();
if events
.iter()
.any(|event| matcher.match_event(event) || event.is_rescan())
{
all_events.extend(events);
break;
}
all_events.extend(events);
if start.elapsed() > timeout {
return Err(all_events);
}
}
while let Ok(event) = self
.changes_receiver
@@ -134,26 +158,28 @@ impl TestCase {
watcher.flush();
}
if all_events.is_empty() {
return None;
}
Some(all_events)
Ok(all_events)
}
fn apply_changes(&mut self, changes: Vec<ChangeEvent>) {
self.db.apply_changes(changes, Some(&self.configuration));
self.db.apply_changes(changes, None);
}
fn update_search_path_settings(
&mut self,
configuration: SearchPathConfiguration,
) -> anyhow::Result<()> {
let program = Program::get(self.db());
fn update_options(&mut self, options: Options) -> anyhow::Result<()> {
std::fs::write(
self.project_path("pyproject.toml").as_std_path(),
toml::to_string(&PyProject {
project: None,
tool: Some(Tool {
knot: Some(options),
}),
})
.context("Failed to serialize options")?,
)
.context("Failed to write configuration")?;
let new_settings = configuration.to_settings(self.db.project().root(&self.db));
self.configuration.search_paths = configuration;
program.update_search_paths(&mut self.db, &new_settings)?;
let changes = self.take_watch_changes(event_for_file("pyproject.toml"));
self.apply_changes(changes);
if let Some(watcher) = &mut self.watcher {
watcher.update(&self.db);
@@ -234,14 +260,13 @@ fn setup<F>(setup_files: F) -> anyhow::Result<TestCase>
where
F: SetupFiles,
{
setup_with_search_paths(setup_files, |_root, _project_path| {
SearchPathConfiguration::default()
})
setup_with_options(setup_files, |_root, _project_path| None)
}
fn setup_with_search_paths<F>(
// TODO: Replace with configuration?
fn setup_with_options<F>(
setup_files: F,
create_search_paths: impl FnOnce(&SystemPath, &SystemPath) -> SearchPathConfiguration,
create_options: impl FnOnce(&SystemPath, &SystemPath) -> Option<Options>,
) -> anyhow::Result<TestCase>
where
F: SetupFiles,
@@ -275,32 +300,33 @@ where
let system = OsSystem::new(&project_path);
let search_paths = create_search_paths(&root_path, &project_path);
if let Some(options) = create_options(&root_path, &project_path) {
std::fs::write(
project_path.join("pyproject.toml").as_std_path(),
toml::to_string(&PyProject {
project: None,
tool: Some(Tool {
knot: Some(options),
}),
})
.context("Failed to serialize options")?,
)
.context("Failed to write configuration")?;
}
for path in search_paths
let project = ProjectMetadata::discover(&project_path, &system)?;
let program_settings = project.to_program_settings(&system);
for path in program_settings
.search_paths
.extra_paths
.iter()
.flatten()
.chain(search_paths.typeshed.iter())
.chain(search_paths.site_packages.iter().flat_map(|site_packages| {
if let SitePackages::Known(path) = site_packages {
path.as_slice()
} else {
&[]
}
}))
.chain(program_settings.search_paths.typeshed.as_ref())
{
std::fs::create_dir_all(path.as_std_path())
.with_context(|| format!("Failed to create search path `{path}`"))?;
}
let configuration = Configuration {
python_version: Some(PythonVersion::PY312),
search_paths,
};
let project = ProjectMetadata::discover(&project_path, &system, Some(&configuration))?;
let db = ProjectDatabase::new(project, system)?;
let (sender, receiver) = crossbeam::channel::unbounded();
@@ -316,12 +342,12 @@ where
watcher: Some(watcher),
_temp_dir: temp_dir,
root_dir: root_path,
configuration,
};
// Sometimes the file watcher reports changes for events that happened before the watcher was started.
// Do a best effort at dropping these events.
test_case.try_take_watch_changes(Duration::from_millis(100));
let _ =
test_case.try_take_watch_changes(|_event: &ChangeEvent| true, Duration::from_millis(100));
Ok(test_case)
}
@@ -762,13 +788,15 @@ fn directory_deleted() -> anyhow::Result<()> {
#[test]
fn search_path() -> anyhow::Result<()> {
let mut case =
setup_with_search_paths([("bar.py", "import sub.a")], |root_path, _project_path| {
SearchPathConfiguration {
site_packages: Some(SitePackages::Known(vec![root_path.join("site_packages")])),
..SearchPathConfiguration::default()
}
})?;
let mut case = setup_with_options([("bar.py", "import sub.a")], |root_path, _project_path| {
Some(Options {
environment: Some(EnvironmentOptions {
extra_paths: Some(vec![root_path.join("site_packages")]),
..EnvironmentOptions::default()
}),
..Options::default()
})
})?;
let site_packages = case.root_path().join("site_packages");
@@ -802,9 +830,12 @@ fn add_search_path() -> anyhow::Result<()> {
assert!(resolve_module(case.db().upcast(), &ModuleName::new_static("a").unwrap()).is_none());
// Register site-packages as a search path.
case.update_search_path_settings(SearchPathConfiguration {
site_packages: Some(SitePackages::Known(vec![site_packages.clone()])),
..SearchPathConfiguration::default()
case.update_options(Options {
environment: Some(EnvironmentOptions {
extra_paths: Some(vec![site_packages.clone()]),
..EnvironmentOptions::default()
}),
..Options::default()
})
.expect("Search path settings to be valid");
@@ -821,19 +852,22 @@ fn add_search_path() -> anyhow::Result<()> {
#[test]
fn remove_search_path() -> anyhow::Result<()> {
let mut case =
setup_with_search_paths([("bar.py", "import sub.a")], |root_path, _project_path| {
SearchPathConfiguration {
site_packages: Some(SitePackages::Known(vec![root_path.join("site_packages")])),
..SearchPathConfiguration::default()
}
})?;
let mut case = setup_with_options([("bar.py", "import sub.a")], |root_path, _project_path| {
Some(Options {
environment: Some(EnvironmentOptions {
extra_paths: Some(vec![root_path.join("site_packages")]),
..EnvironmentOptions::default()
}),
..Options::default()
})
})?;
// Remove site packages from the search path settings.
let site_packages = case.root_path().join("site_packages");
case.update_search_path_settings(SearchPathConfiguration {
site_packages: None,
..SearchPathConfiguration::default()
case.update_options(Options {
environment: None,
..Options::default()
})
.expect("Search path settings to be valid");
@@ -846,9 +880,63 @@ fn remove_search_path() -> anyhow::Result<()> {
Ok(())
}
#[test]
fn change_python_version_and_platform() -> anyhow::Result<()> {
let mut case = setup_with_options(
// `sys.last_exc` is a Python 3.12 only feature
// `os.getegid()` is Unix only
[(
"bar.py",
r#"
import sys
import os
print(sys.last_exc, os.getegid())
"#,
)],
|_root_path, _project_path| {
Some(Options {
environment: Some(EnvironmentOptions {
python_version: Some(PythonVersion::PY311),
python_platform: Some(PythonPlatform::Identifier("win32".to_string())),
..EnvironmentOptions::default()
}),
..Options::default()
})
},
)?;
let diagnostics = case.db.check().context("Failed to check project.")?;
assert_eq!(diagnostics.len(), 2);
assert_eq!(
diagnostics[0].message(),
"Type `<module 'sys'>` has no attribute `last_exc`"
);
assert_eq!(
diagnostics[1].message(),
"Type `<module 'os'>` has no attribute `getegid`"
);
// Change the python version
case.update_options(Options {
environment: Some(EnvironmentOptions {
python_version: Some(PythonVersion::PY312),
python_platform: Some(PythonPlatform::Identifier("linux".to_string())),
..EnvironmentOptions::default()
}),
..Options::default()
})
.expect("Search path settings to be valid");
let diagnostics = case.db.check().context("Failed to check project.")?;
assert!(diagnostics.is_empty());
Ok(())
}
#[test]
fn changed_versions_file() -> anyhow::Result<()> {
let mut case = setup_with_search_paths(
let mut case = setup_with_options(
|root_path: &SystemPath, project_path: &SystemPath| {
std::fs::write(project_path.join("bar.py").as_std_path(), "import sub.a")?;
std::fs::create_dir_all(root_path.join("typeshed/stdlib").as_std_path())?;
@@ -860,9 +948,14 @@ fn changed_versions_file() -> anyhow::Result<()> {
Ok(())
},
|root_path, _project_path| SearchPathConfiguration {
typeshed: Some(root_path.join("typeshed")),
..SearchPathConfiguration::default()
|root_path, _project_path| {
Some(Options {
environment: Some(EnvironmentOptions {
typeshed: Some(root_path.join("typeshed")),
..EnvironmentOptions::default()
}),
..Options::default()
})
},
)?;
@@ -1127,7 +1220,7 @@ mod unix {
update_file(baz_original, "def baz(): print('Version 2')")
.context("Failed to update bar/baz.py")?;
let changes = case.take_watch_changes();
let changes = case.take_watch_changes(event_for_file("baz.py"));
case.apply_changes(changes);
@@ -1259,7 +1352,7 @@ mod unix {
/// ```
#[test]
fn symlinked_module_search_path() -> anyhow::Result<()> {
let mut case = setup_with_search_paths(
let mut case = setup_with_options(
|root: &SystemPath, project: &SystemPath| {
// Set up the symlink target.
let site_packages = root.join("site-packages");
@@ -1282,11 +1375,15 @@ mod unix {
Ok(())
},
|_root, project| SearchPathConfiguration {
site_packages: Some(SitePackages::Known(vec![
project.join(".venv/lib/python3.12/site-packages")
])),
..SearchPathConfiguration::default()
|_root, project| {
Some(Options {
environment: Some(EnvironmentOptions {
extra_paths: Some(vec![project.join(".venv/lib/python3.12/site-packages")]),
python_version: Some(PythonVersion::PY312),
..EnvironmentOptions::default()
}),
..Options::default()
})
},
)?;

View File

@@ -1,5 +1,5 @@
[package]
name = "red_knot_workspace"
name = "red_knot_project"
version = "0.0.0"
edition.workspace = true
rust-version.workspace = true
@@ -12,12 +12,12 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
red_knot_python_semantic = { workspace = true }
ruff_cache = { workspace = true }
ruff_db = { workspace = true, features = ["os", "cache", "serde"] }
ruff_macros = { workspace = true }
ruff_python_ast = { workspace = true, features = ["serde"] }
ruff_text_size = { workspace = true }
red_knot_python_semantic = { workspace = true, features = ["serde"] }
red_knot_vendored = { workspace = true }
anyhow = { workspace = true }
@@ -34,7 +34,6 @@ toml = { workspace = true }
tracing = { workspace = true }
[dev-dependencies]
red_knot_python_semantic = { workspace = true, features = ["serde"] }
ruff_db = { workspace = true, features = ["testing"] }
glob = { workspace = true }
insta = { workspace = true, features = ["redactions", "ron"] }

Some files were not shown because too many files have changed in this diff Show More