Compare commits

...

1676 Commits

Author SHA1 Message Date
Brent Westbrook
47a5543109 chore: stabilize RUF059 2025-06-05 12:33:28 -04:00
Andrew Gallant
55100209c7 [ty] IDE: add support for object.<CURSOR> completions (#18468)
This PR adds logic for detecting `Name Dot [Name]` token patterns,
finding the corresponding `ExprAttribute`, getting the type of the
object and returning the members available on that object.

Here's a video demonstrating this working:

https://github.com/user-attachments/assets/42ce78e8-5930-4211-a18a-fa2a0434d0eb

Ref astral-sh/ty#86
2025-06-05 11:15:19 -04:00
chiri
c0bb83b882 [perflint] fix missing parentheses for lambda and ternary conditions (PERF401, PERF403) (#18412)
Closes #18405
2025-06-05 09:57:08 -05:00
Brent Westbrook
74a4e9af3d Combine lint and syntax error handling (#18471)
## Summary

This is a spin-off from
https://github.com/astral-sh/ruff/pull/18447#discussion_r2125844669 to
avoid using `Message::noqa_code` to differentiate between lints and
syntax errors. I went through all of the calls on `main` and on the
branch from #18447, and the instance in `ruff_server` noted in the
linked comment was actually the primary place where this was being done.
Other calls to `noqa_code` are typically some variation of
`message.noqa_code().map_or(String::new, format!(...))`, with the major
exception of the gitlab output format:


a120610b5b/crates/ruff_linter/src/message/gitlab.rs (L93-L105)

which obviously assumes that `None` means syntax error. A simple fix
here would be to use `message.name()` for `check_name` instead of the
noqa code, but I'm not sure how breaking that would be. This could just
be:

```rust
 let description = message.body();
 let description = description.strip_prefix("SyntaxError: ").unwrap_or(description).to_string();
 let check_name = message.name();
```

In that case. This sounds reasonable based on the [Code Quality report
format](https://docs.gitlab.com/ci/testing/code_quality/#code-quality-report-format)
docs:

> | Name | Type | Description|
> |-----|-----|----|
> |`check_name` | String | A unique name representing the check, or
rule, associated with this violation. |

## Test Plan

Existing tests
2025-06-05 12:50:02 +00:00
Alex Waygood
8485dbb324 [ty] Fix --python argument for Windows, and improve error messages for bad --python arguments (#18457)
## Summary

Fixes https://github.com/astral-sh/ty/issues/556.

On Windows, system installations have different layouts to virtual
environments. In Windows virtual environments, the Python executable is
found at `<sys.prefix>/Scripts/python.exe`. But in Windows system
installations, the Python executable is found at
`<sys.prefix>/python.exe`. That means that Windows users were able to
point to Python executables inside virtual environments with the
`--python` flag, but they weren't able to point to Python executables
inside system installations.

This PR fixes that issue. It also makes a couple of other changes:
- Nearly all `sys.prefix` resolution is moved inside `site_packages.rs`.
That was the original design of the `site-packages` resolution logic,
but features implemented since the initial implementation have added
some resolution and validation to `resolver.rs` inside the module
resolver. That means that we've ended up with a somewhat confusing code
structure and a situation where several checks are unnecessarily
duplicated between the two modules.
- I noticed that we had quite bad error messages if you e.g. pointed to
a path that didn't exist on disk with `--python` (we just gave a
somewhat impenetrable message saying that we "failed to canonicalize"
the path). I improved the error messages here and added CLI tests for
`--python` and the `environment.python` configuration setting.

## Test Plan

- Existing tests pass
- Added new CLI tests
- I manually checked that virtual-environment discovery still works if
no configuration is given
- Micha did some manual testing to check that pointing `--python` to a
system-installation executable now works on Windows
2025-06-05 08:19:15 +01:00
Shunsuke Shibayama
0858896bc4 [ty] type narrowing by attribute/subscript assignments (#18041)
## Summary

This PR partially solves https://github.com/astral-sh/ty/issues/164
(derived from #17643).

Currently, the definitions we manage are limited to those for simple
name (symbol) targets, but we expand this to track definitions for
attribute and subscript targets as well.

This was originally planned as part of the work in #17643, but the
changes are significant, so I made it a separate PR.
After merging this PR, I will reflect this changes in #17643.

There is still some incomplete work remaining, but the basic features
have been implemented, so I am publishing it as a draft PR.
Here is the TODO list (there may be more to come):
* [x] Complete rewrite and refactoring of documentation (removing
`Symbol` and replacing it with `Place`)
* [x] More thorough testing
* [x] Consolidation of duplicated code (maybe we can consolidate the
handling related to name, attribute, and subscript)

This PR replaces the current `Symbol` API with the `Place` API, which is
a concept that includes attributes and subscripts (the term is borrowed
from Rust).

## Test Plan

`mdtest/narrow/assignment.md` is added.

---------

Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-06-04 17:24:27 -07:00
Alex Waygood
ce8b744f17 [ty] Only calculate information for unresolved-reference subdiagnostic if we know we'll emit the diagnostic (#18465)
## Summary

This optimizes some of the logic added in
https://github.com/astral-sh/ruff/pull/18444. In general, we only
calculate information for subdiagnostics if we know we'll actually emit
the diagnostic. The check to see whether we'll emit the diagnostic is
work we'll definitely have to do whereas the the work to gather
information for a subdiagnostic isn't work we necessarily have to do if
the diagnostic isn't going to be emitted at all.

This PR makes us lazier about gathering the information we need for the
subdiagnostic, and moves all the subdiagnostic logic into one function
rather than having some `unresolved-reference` subdiagnostic logic in
`infer.rs` and some in `diagnostic.rs`.

## Test Plan

`cargo test -p ty_python_semantic`
2025-06-04 20:41:00 +01:00
Alex Waygood
5a8cdab771 [ty] Only consider a type T a subtype of a protocol P if all of P's members are fully bound on T (#18466)
## Summary

Fixes https://github.com/astral-sh/ty/issues/578

## Test Plan

mdtests
2025-06-04 19:39:14 +00:00
Alex Waygood
3a8191529c [ty] Exclude members starting with _abc_ from a protocol interface (#18467)
## Summary

As well as excluding a hardcoded set of special attributes, CPython at
runtime also excludes any attributes or declarations starting with
`_abc_` from the set of members that make up a protocol interface. I
missed this in my initial implementation.

This is a bit of a CPython implementation detail, but I do think it's
important that we try to model the runtime as best we can here. The
closer we are to the runtime behaviour, the closer we come to sound
behaviour when narrowing types from `isinstance()` checks against
runtime-checkable protocols (for example)

## Test Plan

Extended an existing mdtest
2025-06-04 20:34:09 +01:00
lipefree
e658778ced [ty] Add subdiagnostic suggestion to unresolved-reference diagnostic when variable exists on self (#18444)
## Summary

Closes https://github.com/astral-sh/ty/issues/502.

In the following example:
```py
class Foo:
    x: int

    def method(self):
        y = x
```
The user may intended to use `y = self.x` in `method`. 

This is now added as a subdiagnostic in the following form : 

`info: An attribute with the same name as 'x' is defined, consider using
'self.x'`

## Test Plan

Added mdtest with snapshot diagnostics.
2025-06-04 08:13:50 -07:00
David Peter
f1883d71a4 [ty] IDE: only provide declarations and bindings as completions (#18456)
## Summary

Previously, all symbols where provided as possible completions. In an
example like the following, both `foo` and `f` were suggested as
completions, because `f` itself is a symbol.
```py
foo = 1

f<CURSOR>
```
Similarly, in the following example, `hidden_symbol` was suggested, even
though it is not statically visible:
```py
if 1 + 2 != 3:
    hidden_symbol = 1

hidden_<CURSOR>
```

With the change suggested here, we only use statically visible
declarations and bindings as a source for completions.


## Test Plan

- Updated snapshot tests
- New test for statically hidden definitions
- Added test for star import
2025-06-04 16:11:05 +02:00
David Peter
11db567b0b [ty] ty_ide: Hotfix for expression_scope_id panics (#18455)
## Summary

Implement a hotfix for the playground/LSP crashes related to missing
`expression_scope_id`s.

relates to: https://github.com/astral-sh/ty/issues/572

## Test Plan

* Regression tests from https://github.com/astral-sh/ruff/pull/18441
* Ran the playground locally to check if panics occur / completions
still work.

---------

Co-authored-by: Andrew Gallant <andrew@astral.sh>
2025-06-04 10:39:16 +02:00
David Peter
9f8c3de462 [ty] Improve docs for Class{Literal,Type}::instance_member (#18454)
## Summary

Mostly just refer to `Type::instance_member` which has much more
details.
2025-06-04 09:55:45 +02:00
David Peter
293d4ac388 [ty] Add meta-type tests for legavy TypeVars (#18453)
## Summary

Follow up to the comment by @dcreager
[here](https://github.com/astral-sh/ruff/pull/18439#discussion_r2123802784).
2025-06-04 07:44:44 +00:00
Carl Meyer
9e8a7e9353 update to salsa that doesn't panic silently on cycles (#18450) 2025-06-04 07:40:16 +02:00
Dhruv Manilawala
453e5f5934 [ty] Add tests for empty list/tuple unpacking (#18451)
## Summary

This PR is to address this comment:
https://github.com/astral-sh/ruff/pull/18438#issuecomment-2935344415

## Test Plan

Run mdtest
2025-06-04 02:40:26 +00:00
Dhruv Manilawala
7ea773daf2 [ty] Argument type expansion for overload call evaluation (#18382)
## Summary

Part of astral-sh/ty#104, closes: astral-sh/ty#468

This PR implements the argument type expansion which is step 3 of the
overload call evaluation algorithm.

Specifically, this step needs to be taken if type checking resolves to
no matching overload and there are argument types that can be expanded.

## Test Plan

Add new test cases.

## Ecosystem analysis

This PR removes 174 `no-matching-overload` false positives -- I looked
at a lot of them and they all are false positives.

One thing that I'm not able to understand is that in
2b7e3adf27/sphinx/ext/autodoc/preserve_defaults.py (L179)
the inferred type of `value` is `str | None` by ty and Pyright, which is
correct, but it's only ty that raises `invalid-argument-type` error
while Pyright doesn't. The constructor method of `DefaultValue` has
declared type of `str` which is invalid.

There are few cases of false positives resulting due to the fact that ty
doesn't implement narrowing on attribute expressions.
2025-06-04 02:12:00 +00:00
Alex Waygood
0079cc6817 [ty] Minor cleanup for site-packages discovery logic (#18446) 2025-06-03 18:49:14 +00:00
Matthew Mckee
e8ea40012a [ty] Add generic inference for dataclasses (#18443)
## Summary

An issue seen here https://github.com/astral-sh/ty/issues/500

The `__init__` method of dataclasses had no inherited generic context,
so we could not infer the type of an instance from a constructor call
with generics

## Test Plan

Add tests to classes.md` in generics folder
2025-06-03 09:59:43 -07:00
Abhijeet Prasad Bodas
71d8a5da2a [ty] dataclasses: Allow using dataclasses.dataclass as a function. (#18440)
## Summary

Part of https://github.com/astral-sh/ty/issues/111

Using `dataclass` as a function, instead of as a decorator did not work
as expected prior to this.
Fix that by modifying the dataclass overload's return type.

## Test Plan

New mdtests, fixing the existing TODO.
2025-06-03 09:50:29 -07:00
Douglas Creager
2c3b3d3230 [ty] Create separate FunctionLiteral and FunctionType types (#18360)
This updates our representation of functions to more closely match our
representation of classes.

The new `OverloadLiteral` and `FunctionLiteral` classes represent a
function definition in the AST. If a function is generic, this is
unspecialized. `FunctionType` has been updated to represent a function
type, which is specialized if the function is generic. (These names are
chosen to match `ClassLiteral` and `ClassType` on the class side.)

This PR does not add a separate `Type` variant for `FunctionLiteral`.
Maybe we should? Possibly as a follow-on PR?

Part of https://github.com/astral-sh/ty/issues/462

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-06-03 10:59:31 -04:00
Dhruv Manilawala
8d98c601d8 [ty] Infer list[T] when unpacking non-tuple type (#18438)
## Summary

Follow-up from #18401, I was looking at whether that would fix the issue
at https://github.com/astral-sh/ty/issues/247#issuecomment-2917656676
and it didn't, which made me realize that the PR only inferred `list[T]`
when the value type was tuple but it could be other types as well.

This PR fixes the actual issue by inferring `list[T]` for the non-tuple
type case.

## Test Plan

Add test cases for starred expression involved with non-tuple type. I
also added a few test cases for list type and list literal.

I also verified that the example in the linked issue comment works:
```py
def _(line: str):
    a, b, *c = line.split(maxsplit=2)
    c.pop()
```
2025-06-03 19:17:47 +05:30
David Peter
0986edf427 [ty] Meta-type of type variables should be type[..] (#18439)
## Summary

Came across this while debugging some ecosystem changes in
https://github.com/astral-sh/ruff/pull/18347. I think the meta-type of a
typevar-annotated variable should be equal to `type`, not `<class
'object'>`.

## Test Plan

New Markdown tests.
2025-06-03 15:22:00 +02:00
chiri
03f1f8e218 [pyupgrade] Make fix unsafe if it deletes comments (UP050) (#18390)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary
/closes #18387
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan
update snapshots
<!-- How was it tested? -->
2025-06-03 09:10:15 -04:00
chiri
628bb2cd1d [pyupgrade] Make fix unsafe if it deletes comments (UP004) (#18393)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary
https://github.com/astral-sh/ruff/issues/18387#issuecomment-2923039331
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan
update snapshots
<!-- How was it tested? -->
2025-06-03 09:09:33 -04:00
lipefree
f23d2c9b9e [ty] Support using legacy typing aliases for generic classes in type annotations (#18404)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-06-03 12:09:51 +01:00
Micha Reiser
67d94d9ec8 Use ty's completions in playground (#18425) 2025-06-03 10:11:39 +02:00
otakutyrant
d1cb8e2142 Update editor setup docs about Neovim and Vim (#18324)
## Summary

I struggled to make ruff_organize_imports work and then I found out I
missed the key note about conform.nvim before because it was put in the
Vim section wrongly! So I refined them both.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-06-03 07:40:22 +00:00
renovate[bot]
57202c1c77 Update NPM Development dependencies (#18423) 2025-06-03 08:06:56 +02:00
Dhruv Manilawala
2289187b74 Infer list[T] for starred target in unpacking (#18401)
## Summary

Closes: astral-sh/ty#191

## Test Plan

Update existing tests.
2025-06-03 07:25:07 +05:30
Robsdedude
14c42a8ddf [refurb] Mark FURB180 fix unsafe when class has bases (#18149)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

Mark `FURB180`'s fix as unsafe if the class already has base classes.
This is because the base classes might validate the other base classes
(like `typing.Protocol` does) or otherwise alter runtime behavior if
more base classes are added.

## Test Plan

The existing snapshot test covers this case already.

## References

Partially addresses https://github.com/astral-sh/ruff/issues/13307 (left
out way to permit certain exceptions)

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-06-03 00:51:09 +00:00
Denys Kyslytsyn
e677863787 [fastapi] Avoid false positive for class dependencies (FAST003) (#18271)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

Closes #17226.

This PR updates the `FAST003` rule to correctly handle [FastAPI class
dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/classes-as-dependencies/).
Specifically, if a path parameter is declared in either:

- a `pydantic.BaseModel` used as a dependency, or  
- the `__init__` method of a class used as a dependency,  

then `FAST003` will no longer incorrectly report it as unused.

FastAPI allows a shortcut when using annotated class dependencies -
`Depends` can be called without arguments, e.g.:

```python
class MyParams(BaseModel):
    my_id: int

@router.get("/{my_id}")
def get_id(params: Annotated[MyParams, Depends()]): ...
```
This PR ensures that such usage is properly supported by the linter.

Note: Support for dataclasses is not included in this PR. Let me know if
you’d like it to be added.

## Test Plan

Added relevant test cases to the `FAST003.py` fixture.
2025-06-02 14:34:50 -04:00
lipefree
f379eb6e62 [ty] Treat lambda functions as instances of types.FunctionType (#18431) 2025-06-02 16:46:26 +01:00
Alex Waygood
47698883ae [ty] Fix false positives for legacy ParamSpecs inside Callable type expressions (#18426) 2025-06-02 14:10:00 +01:00
Alex Waygood
e2d96df501 [ty] Improve diagnostics if the user attempts to import a stdlib module that does not exist on their configured Python version (#18403) 2025-06-02 10:52:26 +00:00
renovate[bot]
384e80ec80 Update taiki-e/install-action action to v2.52.4 (#18420)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 09:03:32 +02:00
renovate[bot]
b9f3b0e0a6 Update docker/build-push-action action to v6.18.0 (#18422)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 09:03:09 +02:00
Micha Reiser
1e6d76c878 [ty] Fix server hang after shutdown request (#18414) 2025-06-02 06:57:51 +00:00
renovate[bot]
844c8626c3 Update Rust crate libcst to v1.8.0 (#18424) 2025-06-02 07:40:18 +02:00
renovate[bot]
1c8d9d707e Update Rust crate clap to v4.5.39 (#18419) 2025-06-02 07:39:27 +02:00
renovate[bot]
4856377478 Update cargo-bins/cargo-binstall action to v1.12.6 (#18416) 2025-06-02 07:38:57 +02:00
renovate[bot]
643c845a47 Update dependency mdformat-mkdocs to v4.3.0 (#18421) 2025-06-02 07:38:36 +02:00
renovate[bot]
9e952cf0e0 Update pre-commit dependencies (#18418) 2025-06-02 07:38:10 +02:00
renovate[bot]
c4015edf48 Update dependency ruff to v0.11.12 (#18417) 2025-06-02 07:37:56 +02:00
Matthew Mckee
97b824db3e [ty] Ensure Literal types are considered assignable to anything their Instance supertypes are assignable to (#18351) 2025-06-01 16:39:56 +01:00
Micha Reiser
220ab88779 [ty] Promote projects to good that now no longer hang (#18370) 2025-06-01 17:25:46 +02:00
github-actions[bot]
7a63ac145a Sync vendored typeshed stubs (#18407)
Co-authored-by: typeshedbot <>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-06-01 15:21:18 +01:00
Micha Reiser
54f597658c [ty] Fix multithreading related hangs and panics (#18238) 2025-06-01 11:07:55 +02:00
Ibraheem Ahmed
aa1fad61e0 Support relative --ty-path in ty-benchmark (#18385)
## Summary

This currently doesn't work because the benchmark changes the working
directory. Also updates the process name to make it easier to compare
two local ty binaries.
2025-05-30 18:19:20 -04:00
Alex Waygood
b390b3cb8e [ty] Update docs for Python version inference (#18397) 2025-05-30 22:45:28 +01:00
Zanie Blue
88866f0048 [ty] Infer the Python version from the environment if feasible (#18057)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-05-30 21:22:51 +00:00
Dylan
9bbf4987e8 Implement template strings (#17851)
This PR implements template strings (t-strings) in the parser and
formatter for Ruff.

Minimal changes necessary to compile were made in other parts of the code (e.g. ty, the linter, etc.). These will be covered properly in follow-up PRs.
2025-05-30 15:00:56 -05:00
Carl Meyer
ad024f9a09 [ty] support callability of bound/constrained typevars (#18389)
## Summary

Allow a typevar to be callable if it is bound to a callable type, or
constrained to callable types.

I spent some time digging into why this support didn't fall out
naturally, and ultimately the reason is that we look up `__call__` on
the meta type (since its a dunder), and our implementation of
`Type::to_meta_type` for `Type::Callable` does not return a type with
`__call__`.

A more general solution here would be to have `Type::to_meta_type` for
`Type::Callable` synthesize a protocol with `__call__` and return an
intersection with that protocol (since for a type to be callable, we
know its meta-type must have `__call__`). That solution could in
principle also replace the special-case handling of `Type::Callable`
itself, here in `Type::bindings`. But that more general approach would
also be slower, and our protocol support isn't quite ready for that yet,
and handling this directly in `Type::bindings` is really not bad.

Fixes https://github.com/astral-sh/ty/issues/480

## Test Plan

Added mdtests.
2025-05-30 12:01:51 -07:00
Andrew Gallant
fc549bda94 [ty] Minor tweaks to "list all members" docs and tests (#18388)
Ref https://github.com/astral-sh/ruff/pull/18251#pullrequestreview-2881810681
2025-05-30 13:36:57 -04:00
Alex Waygood
77c8ddf101 [ty] Fix broken property tests for disjointness (#18384) 2025-05-30 16:49:20 +01:00
David Peter
e730f27f80 [ty] List available members for a given type (#18251)
This PR adds initial support for listing all attributes of
an object. It is exposed through a new `all_members`
routine in `ty_extensions`, which is in turn used to test
the functionality.

The purpose of listing all members is for code
completion. That is, given a `object.<CURSOR>`, we
would like to list all available attributes on
`object`.
2025-05-30 11:24:20 -04:00
Wei Lee
d65bd69963 [airflow] Add unsafe fix for module moved cases (AIR312) (#18363)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

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

Follow up on https://github.com/astral-sh/ruff/pull/18093 and apply it
to AIR312

## Test Plan

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

The existing test fixtures have been updated
2025-05-30 09:36:20 -04:00
Brent Westbrook
c713e76e4d Add a SourceFile to OldDiagnostic (#18356)
Summary
--

This is the last main difference between the `OldDiagnostic` and
`Message`
types, so attaching a `SourceFile` to `OldDiagnostic` should make
combining the
two types almost trivial.

Initially I updated the remaining rules without access to a `Checker` to
take a
`&SourceFile` directly, but after Micha's suggestion in
https://github.com/astral-sh/ruff/pull/18356#discussion_r2113281552, I
updated all of these calls to take a
`LintContext` instead. This new type is a thin wrapper around a
`RefCell<Vec<OldDiagnostic>>`
and a `SourceFile` and now has the `report_diagnostic` method returning
a `DiagnosticGuard` instead of `Checker`.
This allows the same `Drop`-based implementation to be used in cases
without a `Checker` and also avoids a lot of intermediate allocations of
`Vec<OldDiagnostic>`s.

`Checker` now also contains a `LintContext`, which it defers to for its
`report_diagnostic` methods, which I preserved for convenience.

Test Plan
--

Existing tests
2025-05-30 13:34:38 +00:00
Micha Reiser
8005ebb405 Update salsa past generational id change (#18362) 2025-05-30 15:31:33 +02:00
Wei Lee
0c29e258c6 [airflow] Add unsafe fix for module moved cases (AIR311) (#18366)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

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

Follow up on https://github.com/astral-sh/ruff/pull/18093 and apply it
to AIR311

---

Rules fixed
* `airflow.models.datasets.expand_alias_to_datasets` →
`airflow.models.asset.expand_alias_to_assets`
* `airflow.models.baseoperatorlink.BaseOperatorLink` →
`airflow.sdk.BaseOperatorLink`


## Test Plan

<!-- How was it tested? -->
The existing test fixtures have been updated
2025-05-30 09:27:14 -04:00
Wei Lee
b5b6b657cc [airflow] Add unsafe fix for module moved cases (AIR301) (#18367)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

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

Follow up on https://github.com/astral-sh/ruff/pull/18093 and apply it
to AIR301

## Test Plan

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

The existing test fixtures have been updated
2025-05-30 08:46:39 -04:00
Alex Waygood
ad2f667ee4 [ty] Improve tests for site-packages discovery (#18374)
## Summary

- Convert tests demonstrating our resilience to malformed/absent
`version` fields in `pyvenf.cfg` files to mdtests. Also make them more
expansive.
- Convert the regression test I added in
https://github.com/astral-sh/ruff/pull/18157 to an mdtest
- Add comments next to unit tests that cannot be converted to mdtests
(but where it's not obvious why they can't) so I don't have to do this
exercise again 😄
- In `site_packages.rs`, factor out the logic for figuring out where we
expect the system-installation `site-packages` to be. Currently we have
the same logic twice.

## Test Plan

`cargo test -p ty_python_semantic`
2025-05-30 07:32:21 +01:00
Carl Meyer
363f061f09 [ty] _typeshed.Self is not a special form (#18377)
## Summary

This change was based on a mis-reading of a comment in typeshed, and a
wrong assumption about what was causing a test failure in a prior PR.
Reverting it doesn't cause any tests to fail.

## Test Plan

Existing tests.
2025-05-29 17:11:13 -07:00
InSync
9b0dfc505f [ty] Callable types are disjoint from non-callable @final nominal instance types (#18368)
## Summary

Resolves [#513](https://github.com/astral-sh/ty/issues/513).

Callable types are now considered to be disjoint from nominal instance
types where:

* The class is `@final`, and
* Its `__call__` either does not exist or is not assignable to `(...) ->
Unknown`.

## Test Plan

Markdown tests.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-29 23:27:27 +00:00
lipefree
695de4f27f [ty] Add diagnosis for function with no return statement but with return type annotation (#18359)
## Summary

Partially implement https://github.com/astral-sh/ty/issues/538, 
```py
from pathlib import Path

def setup_test_project(registry_name: str, registry_url: str, project_dir: str) -> Path:
    pyproject_file = Path(project_dir) / "pyproject.toml"
    pyproject_file.write_text("...", encoding="utf-8")
```
As no return statement is defined in the function `setup_test_project`
with annotated return type `Path`, we provide the following diagnosis :

- error[invalid-return-type]: Function **always** implicitly returns
`None`, which is not assignable to return type `Path`

with a subdiagnostic : 
- note: Consider changing your return annotation to `-> None` or adding a `return` statement
 
## Test Plan

mdtests with snapshots to capture the subdiagnostic. I have to mention
that existing snapshots were modified since they now fall in this
category.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-29 23:17:18 +00:00
Wei Lee
3445d1322d [airflow] Add unsafe fix module moved cases (AIR302) (#18093)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

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

Add utility functions `generate_import_edit` and
`generate_remove_and_runtime_import_edit` to generate the fix needed for
the airflow rules.

1. `generate_import_edit` is for the cases where the member name has
changed. (e.g., `airflow.datasts.Dataset` to `airflow.sdk.Asset`) It's
just extracted from the original logic
2. `generate_remove_and_runtime_import_edit` is for cases where the
member name has not changed. (e.g.,
`airflow.operators.pig_operator.PigOperator` to
`airflow.providers.apache.pig.hooks.pig.PigCliHook`) This is newly
introduced. As it introduced runtime import, I mark it as an unsafe fix.
Under the hook, it tried to find the original import statement, remove
it, and add a new import fix

---

* rules fix
* `airflow.sensors.external_task_sensor.ExternalTaskSensorLink` →
`airflow.providers.standard.sensors.external_task.ExternalDagLink`

## Test Plan

<!-- How was it tested? -->
The existing test fixtures have been updated
2025-05-29 16:30:40 -04:00
Brent Westbrook
2c3f091e0e Rename ruff_linter::Diagnostic to OldDiagnostic (#18355)
Summary
--

It's a bit late in the refactoring process, but I think there are still
a couple of PRs left before getting rid of this type entirely, so I
thought it would still be worth doing.

This PR is just a quick rename with no other changes.

Test Plan
--

Existing tests
2025-05-29 15:04:31 -04:00
Marcus Näslund
9d3cad95bc [refurb] Add coverage of set and frozenset calls (FURB171) (#18035)
## Summary

Adds coverage of using set(...) in addition to `{...} in
SingleItemMembershipTest.

Fixes #15792
(and replaces the old PR #15793)

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

## Test Plan

Updated unit test and snapshot.

Steps to reproduce are in the issue linked above.

<!-- How was it tested? -->
2025-05-29 14:59:49 -04:00
Alex Waygood
7df79cfb70 Add offset method to ruff_python_trivia::Cursor (#18371) 2025-05-29 16:08:15 +01:00
Andrew Gallant
33ed502edb ty_ide: improve completions by using scopes
Previously, completions were based on just returning every identifier
parsed in the current Python file. In this commit, we change it to
identify an expression under the cursor and then return all symbols
available to the scope containing that expression.

This is still returning too much, and also, in some cases, not enough.
Namely, it doesn't really take the specific context into account other
than scope. But this does improve on the status quo. For example:

    def foo(): ...
    def bar():
        def fast(): ...
    def foofoo(): ...

    f<CURSOR>

When asking for completions here, the LSP will no longer include `fast`
as a possible completion in this context.

Ref https://github.com/astral-sh/ty/issues/86
2025-05-29 10:31:30 -04:00
Andrew Gallant
a827b16ebd ruff_python_parser: add Tokens::before method
This is analogous to the existing `Tokens::after` method. Its
implementation is almost identical.

We plan to use this for looking at the tokens immediately before the
cursor when fetching completions.
2025-05-29 10:31:30 -04:00
Alex Waygood
47a2ec002e [ty] Split Type::KnownInstance into two type variants (#18350) 2025-05-29 14:47:55 +01:00
Brent Westbrook
aee3af0f7a Bump 0.11.12 (#18369) 2025-05-29 09:17:12 -04:00
Victor Hugo Gomes
04dc48e17c [refurb] Fix FURB129 autofix generating invalid syntax (#18235)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

Fixes #18231

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

## Test Plan

Snapshot tests
<!-- How was it tested? -->
2025-05-28 17:01:03 -04:00
vjurczenia
27743efa1b [pylint] Implement missing-maxsplit-arg (PLC0207) (#17454)
## Summary

Implements  `use-maxsplit-arg` (`PLC0207`)

https://pylint.readthedocs.io/en/latest/user_guide/messages/convention/use-maxsplit-arg.html
> Emitted when accessing only the first or last element of str.split().
The first and last element can be accessed by using str.split(sep,
maxsplit=1)[0] or str.rsplit(sep, maxsplit=1)[-1] instead.

This is part of https://github.com/astral-sh/ruff/issues/970

## Test Plan

`cargo test`

Additionally compared Ruff output to Pylint:
```
pylint --disable=all --enable=use-maxsplit-arg crates/ruff_linter/resources/test/fixtures/pylint/missing_maxsplit_arg.py

cargo run -p ruff -- check crates/ruff_linter/resources/test/fixtures/pylint/missing_maxsplit_arg.py --no-cache --select PLC0207
```

---------

Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-05-28 20:46:30 +00:00
Matthew Mckee
c60b4d7f30 [ty] Add subtyping between Callable types and class literals with __init__ (#17638)
## Summary

Allow classes with `__init__` to be subtypes of `Callable`

Fixes https://github.com/astral-sh/ty/issues/358

## Test Plan

Update is_subtype_of.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-28 13:43:07 -07:00
Hans
16621fa19d [flake8-bugbear ] Add fix safety section (B006) (#17652)
## Summary

This PR add the `fix safety` section for rule `B006` in
`mutable_argument_default.rs` for #15584

When applying this rule for fixes, certain changes may alter the
original logical behavior. For example:

before:
```python
def cache(x, storage=[]):
    storage.append(x)
    return storage

print(cache(1))  # [1]
print(cache(2))  # [1, 2]
```

after:
```python
def cache(x, storage=[]):
    storage.append(x)
    return storage

print(cache(1))  # [1]
print(cache(2))  # [2]
```
2025-05-28 16:27:13 -04:00
Victor Hugo Gomes
e23d4ea027 [flake8-bugbear] Ignore __debug__ attribute in B010 (#18357)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

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

## Test Plan

<!-- How was it tested? -->
Snapshot tests
2025-05-28 16:24:52 -04:00
Douglas Creager
452f992fbc [ty] Simplify signature types, use them in CallableType (#18344)
There were many fields in `Signature` and friends that really had more
to do with how a signature was being _used_ — how it was looked up,
details about an individual call site, etc. Those fields more properly
belong in `Bindings` and friends.

This is a pure refactoring, and should not affect any tests or ecosystem
projects.

I started on this journey in support of
https://github.com/astral-sh/ty/issues/462. It seemed worth pulling out
as a separate PR.

One major concrete benefit of this refactoring is that we can now use
`CallableSignature` directly in `CallableType`. (We can't use
`CallableSignature` directly in that `Type` variant because signatures
are not currently interned.)
2025-05-28 13:11:45 -04:00
Alex Waygood
a5ebb3f3a2 [ty] Support ephemeral uv virtual environments (#18335) 2025-05-28 14:54:59 +00:00
Brent Westbrook
9925910a29 Add a ViolationMetadata::rule method (#18234)
Summary
--

This PR adds a macro-generated method to retrieve the `Rule` associated
with a given `Violation` struct, which makes it substantially cheaper
than parsing from the rule name. The rule is then converted to a
`NoqaCode` for storage on the `Message` (and eventually on the new
diagnostic type). The `ViolationMetadata::rule_name` method was now
unused, so the `rule` method replaces it.

Several types had to be moved from the `ruff_diagnostics` crate to the
`ruff_linter` crate to make this work, namely the `Violation` traits and
the old `Diagnostic` type, which had a constructor generic over a
`Violation`.

It's actually a fairly small PR, minus the hundreds of import changes.
The main changes are in these files:

-
[crates/ruff_linter/src/message/mod.rs](https://github.com/astral-sh/ruff/pull/18234/files#diff-139754ea310d75f28307008d21c771a190038bd106efe3b9267cc2d6c0fa0921)
-
[crates/ruff_diagnostics/src/lib.rs](https://github.com/astral-sh/ruff/pull/18234/files#diff-8e8ea5c586935bf21ea439f24253fcfd5955d2cb130f5377c2fa7bfee3ea3a81)
-
[crates/ruff_linter/src/diagnostic.rs](https://github.com/astral-sh/ruff/pull/18234/files#diff-1d0c9aad90d8f9446079c5be5f284150d97797158715bd9729e6f1f70246297a)
-
[crates/ruff_linter/src/lib.rs](https://github.com/astral-sh/ruff/pull/18234/files#diff-eb93ef7e78a612f5fa9145412c75cf6b1a5cefba1c2233e4a11a880a1ce1fbcc)

Test Plan
--

Existing tests
2025-05-28 09:27:09 -04:00
Brent Westbrook
a3ee6bb3b5 Return DiagnosticGuard from Checker::report_diagnostic (#18232)
Summary
--

This PR adds a `DiagnosticGuard` type to ruff that is adapted from the
`DiagnosticGuard` and `LintDiagnosticGuard` types from ty. This guard is
returned by `Checker::report_diagnostic` and derefs to a
`ruff_diagnostics::Diagnostic` (`OldDiagnostic`), allowing methods like
`OldDiagnostic::set_fix` to be called on the result. On `Drop` the
`DiagnosticGuard` pushes its contained `OldDiagnostic` to the `Checker`.

The main motivation for this is to make a following PR adding a
`SourceFile` to each diagnostic easier. For every rule where a `Checker`
is available, this will now only require modifying
`Checker::report_diagnostic` rather than all the rules.

In the few cases where we need to create a diagnostic before we know if
we actually want to emit it, there is a `DiagnosticGuard::defuse`
method, which consumes the guard without emitting the diagnostic. I was
able to restructure about half of the rules that naively called this to
avoid calling it, but a handful of rules still need it.

One of the fairly common patterns where `defuse` was needed initially
was something like

```rust
let diagnostic = Diagnostic::new(DiagnosticKind, range);

if !checker.enabled(diagnostic.rule()) {
    return;
}
```

So I also added a `Checker::checked_report_diagnostic` method that
handles this check internally. That helped to avoid some additional
`defuse` calls. The name is a bit repetitive, so I'm definitely open to
suggestions there. I included a warning against using it in the docs
since, as we've seen, the conversion from a diagnostic to a rule is
actually pretty expensive.

Test Plan
--

Existing tests
2025-05-28 07:41:31 -04:00
Viktor Merkurev
b60ba75d09 [flake8_use_pathlib]: Replace os.symlink with Path.symlink_to (PTH211) (#18337)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-28 12:39:05 +02:00
Micha Reiser
66ba1d8775 [ty] Support cancellation and retry in the server (#18273) 2025-05-28 10:59:29 +02:00
David Peter
bbcd7e0196 [ty] Synthetic function-like callables (#18242)
## Summary

We create `Callable` types for synthesized functions like the `__init__`
method of a dataclass. These generated functions are real functions
though, with descriptor-like behavior. That is, they can bind `self`
when accessed on an instance. This was modeled incorrectly so far.

## Test Plan

Updated tests
2025-05-28 10:00:56 +02:00
Dhruv Manilawala
48c425c15b [ty] Support publishing diagnostics in the server (#18309)
## Summary

This PR adds support for [publishing
diagnostics](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_publishDiagnostics)
from the ty language server.

It only adds support for it for text documents and not notebook
documents because the server doesn't have full notebook support yet.

Closes: astral-sh/ty#79

## Test Plan

Testing this out in Helix and Zed since those are the two editors that I
know of that doesn't support pull diagnostics:

### Helix


https://github.com/user-attachments/assets/e193f804-0b32-4f7e-8b83-6f9307e3d2d4



### Zed



https://github.com/user-attachments/assets/93ec7169-ce2b-4521-b009-a82d8afb9eaa
2025-05-28 13:15:11 +05:30
Max Mynter
6d210dd0c7 Add Autofix for ISC003 (#18256)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-28 09:30:51 +02:00
chiri
9ce83c215d [pyupgrade]: new rule UP050 (useless-class-metaclass-type) (#18334)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-28 09:22:44 +02:00
हिमांशु
602dd5c039 [pycodestyle] Make E712 suggestion not assume a context (#18328) 2025-05-28 09:06:39 +02:00
Carl Meyer
3eada01153 put similar dunder-call tests next to each other (#18343)
Follow-up from post-land review on
https://github.com/astral-sh/ruff/pull/18260
2025-05-27 12:16:41 -07:00
Alex Waygood
3e811fc369 [ty] Derive PartialOrd, Ord for KnownInstanceType (#18340) 2025-05-27 19:37:01 +01:00
Alex Waygood
743764d384 [ty] Simplify Type::try_bool() (#18342)
## Summary

I don't think we're ever going to add any `KnownInstanceType` variants
that evaluate to `False` in a boolean context; the
`KnownInstanceType::bool()` method just seems like unnecessary
complexity.

## Test Plan

`cargo test -p ty_python_semantic`
2025-05-27 19:32:17 +01:00
Alex Waygood
e03e05d2b3 [ty] Simplify Type::normalized slightly (#18339) 2025-05-27 18:08:59 +00:00
Alex Waygood
9ec4a178a4 [ty] Move arviz off the list of selected primer projects (#18336) 2025-05-27 17:51:19 +01:00
justin
8d5655a7ba [ty] Add --config-file CLI arg (#18083) 2025-05-27 08:00:38 +02:00
Alex Waygood
6453ac9ea1 [ty] Tell the user why we inferred a certain Python version when reporting version-specific syntax errors (#18295) 2025-05-26 20:44:43 +00:00
Alex Waygood
0a11baf29c [ty] Implement implicit inheritance from Generic[] for PEP-695 generic classes (#18283) 2025-05-26 20:40:16 +01:00
lipefree
1d20cf9570 [ty] Add hint if async context manager is used in non-async with statement (#18299)
# Summary

Adds a subdiagnostic hint in the following scenario where a
synchronous `with` is used with an async context manager:
```py
class Manager:
    async def __aenter__(self): ...
    async def __aexit__(self, *args): ...

# error: [invalid-context-manager] "Object of type `Manager` cannot be used with `with` because it does not implement `__enter__` and `__exit__`"
# note: Objects of type `Manager` *can* be used as async context managers
# note: Consider using `async with` here
with Manager():
    ...
```

closes https://github.com/astral-sh/ty/issues/508

## Test Plan

New MD snapshot tests

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-05-26 21:34:47 +02:00
Micha Reiser
62ef96f51e [ty] Move respect-ignore-files under src section (#18322) 2025-05-26 18:45:48 +01:00
David Peter
4e68dd96a6 [ty] Infer types for ty_extensions.Intersection[A, B] tuple expressions (#18321)
## Summary

fixes astral-sh/ty#366

## Test Plan

* Added panic corpus regression tests
* I also wrote a hover regression test (see below), but decided not to
include it. The corpus tests are much more "effective" at finding these
types of errors, since they exhaustively check all expressions for
types.

<details>

```rs
#[test]
fn hover_regression_test_366() {
    let test = cursor_test(
        r#"
    from ty_extensions import Intersection

    class A: ...
    class B: ...

    def _(x: Intersection[A,<CURSOR> B]):
        pass
    "#,
    );

    assert_snapshot!(test.hover(), @r"
    A & B
    ---------------------------------------------
    ```text
    A & B
    ```
    ---------------------------------------------
    info[hover]: Hovered content is
     --> main.py:7:31
      |
    5 |         class B: ...
    6 |
    7 |         def _(x: Intersection[A, B]):
      |                               ^^-^
      |                               | |
      |                               | Cursor offset
      |                               source
    8 |             pass
      |
    ");
}
```

</details>
2025-05-26 17:08:52 +02:00
Maddy Guthridge
b25b642371 Improve readability of rule status icons in documentation (#18297)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-26 14:35:20 +00:00
Micha Reiser
175402aa75 [ty] Remove unnecessary lifetimes for Task (#18261) 2025-05-26 12:44:43 +00:00
Micha Reiser
d8216fa328 [ty] Gracefully handle salsa cancellations and panics in background request handlers (#18254) 2025-05-26 13:37:49 +01:00
David Peter
d51f6940fe [ty] Playground: Better default settings (#18316)
## Summary

The playground default settings set the `division-by-zero` rule severity
to `error`. This slightly confusing because `division-by-zero` is now
disabled by default. I am assuming that we have a `rules` section in
there to make it easier for users to customize those settings (in
addition to what the JSON schema gives us).

Here, I'm proposing a different default rule-set (`"undefined-reveal":
"ignore"`) that I would personally find more helpful for the playground,
since we're using it so frequently for MREs that often involve some
`reveal_type` calls.
2025-05-26 14:14:23 +02:00
Micha Reiser
66b082ff71 [ty] Abort process if worker thread panics (#18211) 2025-05-26 13:09:06 +01:00
Micha Reiser
5d93d619f3 Use git-commit as ty playground version instead of 0.0.0 (#18314) 2025-05-26 11:55:11 +00:00
David Peter
e1b662bf5d [ty] Always pass NO_INSTANCE_FALLBACK in try_call_dunder_with_policy (#18315)
## Summary

The previous `try_call_dunder_with_policy` API was a bit of a footgun
since you needed to pass `NO_INSTANCE_FALLBACK` in *addition* to other
policies that you wanted for the member lookup. Implicit calls to dunder
methods never access instance members though, so we can do this
implicitly in `try_call_dunder_with_policy`.

No functional changes.
2025-05-26 13:20:27 +02:00
Felix Scherz
f885cb8a2f [ty] use __getattribute__ to lookup unknown members on a type (#18280)
## Summary

`Type::member_lookup_with_policy` now falls back to calling
`__getattribute__` when a member cannot be found as a second fallback
after `__getattr__`.


closes https://github.com/astral-sh/ty/issues/441

## Test Plan

Added markdown tests.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: David Peter <mail@david-peter.de>
2025-05-26 12:59:45 +02:00
David Peter
4ef2c223c9 [ty] Respect MRO_NO_OBJECT_FALLBACK policy when looking up symbols on type instances (#18312)
## Summary

This should address a problem that came up while working on
https://github.com/astral-sh/ruff/pull/18280. When looking up an
attribute (typically a dunder method) with the `MRO_NO_OBJECT_FALLBACK`
policy, the attribute is first looked up on the meta type. If the meta
type happens to be `type`, we go through the following branch in
`find_name_in_mro_with_policy`:


97ff015c88/crates/ty_python_semantic/src/types.rs (L2565-L2573)

The problem is that we now look up the attribute on `object` *directly*
(instead of just having `object` in the MRO). In this case,
`MRO_NO_OBJECT_FALLBACK` has no effect in `class_member_from_mro`:


c3feb8ce27/crates/ty_python_semantic/src/types/class.rs (L1081-L1082)

So instead, we need to explicitly respect the `MRO_NO_OBJECT_FALLBACK`
policy here by returning `Symbol::Unbound`.

## Test Plan

Added new Markdown tests that explain the ecosystem changes that we
observe.
2025-05-26 12:03:29 +02:00
Vasanth
d078ecff37 [flake8_async] Refactor argument name resolution for async sleep func… (#18262)
Co-authored-by: Vasanth-96 <ramavath.naik@itilite.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-26 09:53:03 +00:00
David Peter
7eca6f96e3 [ty] Fix attribute writes to unions/intersections including modules (#18313)
## Summary

Fix a bug that involved writes to attributes on union/intersection types
that included modules as elements.

This is a prerequisite to avoid some ecosystem false positives in
https://github.com/astral-sh/ruff/pull/18312

## Test Plan

Added regression test
2025-05-26 11:41:03 +02:00
David Sherret
fbaf826a9d Only enable js feature of uuid crate for wasm crates (#18152) 2025-05-26 10:33:51 +01:00
Wei Lee
d8a5b9de17 [airflow] Revise fix title AIR3 (#18215) 2025-05-26 10:31:48 +01:00
otakutyrant
c3feb8ce27 Update editor integrations link in README (#17977)
Co-authored-by: Oscar Gustafsson <oscar.gustafsson@gmail.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-26 09:50:09 +01:00
Jo
97ff015c88 [ty] Add tests to src.root if it exists and is not a package (#18286) 2025-05-26 09:08:57 +01:00
renovate[bot]
1f7134f727 Update rui314/setup-mold digest to 67424c1 (#18300) 2025-05-26 07:43:52 +02:00
renovate[bot]
6a0b93170e Update pre-commit dependencies (#18302) 2025-05-26 07:43:31 +02:00
renovate[bot]
cc59ff8aad Update dependency ruff to v0.11.11 (#18301) 2025-05-26 07:41:54 +02:00
renovate[bot]
2b90e7fcd7 Update NPM Development dependencies (#18305) 2025-05-26 07:41:37 +02:00
renovate[bot]
a43f5b2129 Update taiki-e/install-action action to v2.52.1 (#18307) 2025-05-26 07:41:18 +02:00
renovate[bot]
f3fb7429ca Update astral-sh/setup-uv action to v6.1.0 (#18304) 2025-05-26 07:40:51 +02:00
renovate[bot]
83498b95fb Update Rust crate uuid to v1.17.0 (#18306) 2025-05-26 07:40:01 +02:00
renovate[bot]
03d7be3747 Update Rust crate jiff to v0.2.14 (#18303) 2025-05-26 07:38:37 +02:00
Dhruv Manilawala
d95b029862 [ty] Move diagnostics API for the server (#18308)
## Summary

This PR moves the diagnostics API for the language server out from the
request handler module to the diagnostics API module.

This is in preparation to add support for publishing diagnostics.
2025-05-26 04:16:38 +00:00
Charlie Marsh
14c3755445 Fix YTT201 for '!=' comparisons (#18293)
## Summary

Closes #18292.
2025-05-25 13:16:19 -04:00
Jo
83a036960b [ty] Add long help for --config argument (#18285) 2025-05-25 13:09:02 +02:00
chiri
be76fadb05 [pyupgrade] make fix unsafe if it deletes comments (UP010, unnecessary-future-import) (#18291) 2025-05-25 12:44:21 +02:00
Alex Waygood
e293411679 [ty] get_protocol_members returns a frozenset, not a tuple (#18284) 2025-05-23 23:20:34 +00:00
lipefree
53d19f8368 [ty] Resolving Python path using CONDA_PREFIX variable to support Conda and Pixi (#18267) 2025-05-23 20:00:42 +02:00
InSync
a1399656c9 [ty] Fix binary intersection comparison inference logic (#18266)
## Summary

Resolves https://github.com/astral-sh/ty/issues/485.

`infer_binary_intersection_type_comparison()` now checks for all
positive members before concluding that an operation is unsupported for
a given intersection type.

## Test Plan

Markdown tests.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-05-23 12:55:17 +02:00
David Peter
6392dccd24 [ty] Add warning that docs are autogenerated (#18270)
## Summary

This is a practice I followed on previous projects. Should hopefully
further help developers who want to update the documentation.

The big downside is that it's annoying to see this *as a user of the
documentation* if you don't open the Markdown file in the browser. But
I'd argue that those files don't really follow the original Markdown
spirit anyway with all the inline HTML.
2025-05-23 09:58:16 +00:00
David Peter
93ac0934dd [ty] Type compendium (#18263)
## Summary

This is something I wrote a few months ago, and continued to update from
time to time. It was mostly written for my own education. I found a few
bugs while writing it at the time (there are still one or two TODOs in
the test assertions that are probably bugs). Our other tests are fairly
comprehensive, but they are usually structured around a certain
functionality or operation (subtyping, assignability, narrowing). The
idea here was to focus on individual *types and their properties*.

closes #197 (added `JustFloat` and `JustComplex` to `ty_extensions`).
2025-05-23 11:41:31 +02:00
David Peter
aae4482c55 [ty] Replace remaining knot.toml reference (#18269)
## Summary

Fix remaining `knot.toml` reference and replace it with `ty.toml`. This
change was probably still in flight while we renamed things.

## Test Plan

Added a second assertion which ensures that the config file has any
effect.
2025-05-23 10:44:46 +02:00
Alex Waygood
d02c9ada5d [ty] Do not carry the generic context of Protocol or Generic in the ClassBase enum (#17989)
## Summary

It doesn't seem to be necessary for our generics implementation to carry
the `GenericContext` in the `ClassBase` variants. Removing it simplifies
the code, fixes many TODOs about `Generic` or `Protocol` appearing
multiple times in MROs when each should only appear at most once, and
allows us to more accurately detect runtime errors that occur due to
`Generic` or `Protocol` appearing multiple times in a class's bases.

In order to remove the `GenericContext` from the `ClassBase` variant, it
turns out to be necessary to emulate
`typing._GenericAlias.__mro_entries__`, or we end up with a large number
of false-positive `inconsistent-mro` errors. This PR therefore also does
that.

Lastly, this PR fixes the inferred MROs of PEP-695 generic classes,
which implicitly inherit from `Generic` even if they have no explicit
bases.

## Test Plan

mdtests
2025-05-22 21:37:03 -04:00
Dylan
6c0a59ea78 Fix insider docs requirement syntax (#18265)
Attempting to fix the `mkdocs` workflow (maybe `uv` is more forgiving
than `pip` for the syntax in `requirements.txt`?)
2025-05-22 16:21:51 -05:00
Carl Meyer
0b181bc2ad Fix instance vs callable subtyping/assignability (#18260)
## Summary

Fix some issues with subtying/assignability for instances vs callables.
We need to look up dunders on the class, not the instance, and we should
limit our logic here to delegating to the type of `__call__`, so it
doesn't get out of sync with the calls we allow.

Also, we were just entirely missing assignability handling for
`__call__` implemented as anything other than a normal bound method
(though we had it for subtyping.)

A first step towards considering what else we want to change in
https://github.com/astral-sh/ty/issues/491

## Test Plan

mdtests

---------

Co-authored-by: med <medioqrity@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-05-22 19:47:05 +00:00
Dylan
0397682f1f Bump 0.11.11 (#18259) 2025-05-22 13:09:44 -05:00
InSync
bcefa459f4 [ty] Rename call-possibly-unbound-method to possibly-unbound-implicit-call (#18017) 2025-05-22 15:25:51 +00:00
Brandt Bucher
91b7a570c2 [ty] Implement Python's floor division semantics for Literal ints (#18249)
Division works differently in Python than in Rust. If the result is
negative and there is a remainder, the division rounds down (instead of
towards zero). The remainder needs to be adjusted to compensate so that
`(lhs // rhs) * rhs + (lhs % rhs) == lhs`.

Fixes astral-sh/ty#481.
2025-05-22 10:42:29 -04:00
Micha Reiser
98da200d45 [ty] Fix server panic when calling system_mut (#18252) 2025-05-22 16:10:07 +02:00
Sumana Harihareswara
029085fa72 [ty] Clarify ty check output default in documentation. (#18246)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-22 15:24:58 +02:00
Denys Kyslytsyn
6df10c638e [pylint] Fix docs example that produced different output (PLW0603) (#18216) 2025-05-22 07:55:37 +02:00
Max Mynter
bdf488462a Preserve tuple parentheses in case patterns (#18147) 2025-05-22 07:52:21 +02:00
justin
01eeb2f0d6 [ty] Support frozen dataclasses (#17974)
## Summary
https://github.com/astral-sh/ty/issues/111

This PR adds support for `frozen` dataclasses. It will emit a diagnostic
with a similar message to mypy

Note: This does not include emitting a diagnostic if `__setattr__` or
`__delattr__` are defined on the object as per the
[spec](https://docs.python.org/3/library/dataclasses.html#module-contents)

## Test Plan
mdtest

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-22 00:20:34 -04:00
Alex Waygood
cb04343b3b [ty] Split invalid-base error code into two error codes (#18245) 2025-05-21 18:02:39 -04:00
Alex Waygood
02394b8049 [ty] Improve invalid-type-form diagnostic where a module-literal type is used in a type expression and the module has a member which would be valid in a type expression (#18244) 2025-05-21 15:38:56 -04:00
Alex Waygood
41463396cf [ty] Add a subdiagnostic if invalid-return-type is emitted on a method with an empty body on a non-protocol subclass of a protocol class (#18243) 2025-05-21 17:38:07 +00:00
David Peter
da4be789ef [ty] Ignore ClassVar declarations when resolving instance members (#18241)
## Summary

Make sure that the following definitions all lead to the same outcome
(bug originally noticed by @AlexWaygood)

```py
from typing import ClassVar

class Descriptor:
    def __get__(self, instance, owner) -> int:
        return 42

class C:
    a: ClassVar[Descriptor]
    b: Descriptor = Descriptor()
    c: ClassVar[Descriptor] = Descriptor()

reveal_type(C().a)  # revealed: int  (previously: int | Descriptor)
reveal_type(C().b)  # revealed: int
reveal_type(C().c)  # revealed: int
```

## Test Plan

New Markdown tests
2025-05-21 19:23:35 +02:00
Max Mynter
02fd48132c [ty] Don't warn yield not in function when yield is in function (#18008) 2025-05-21 18:16:25 +02:00
Alex Waygood
d37592175f [ty] Tell the user why we inferred the Python version we inferred (#18082) 2025-05-21 11:06:27 -04:00
Micha Reiser
cb9e66927e Run mypy primer on Cargo.lock changes (#18239) 2025-05-21 13:21:38 +02:00
Micha Reiser
76ab77fe01 [ty] Support import <namespace> and from <namespace> import module (#18137) 2025-05-21 07:28:33 +00:00
Carl Meyer
7b253100f8 switch the playground repo button to ty repo (#18228)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-21 06:35:13 +00:00
Carl Meyer
d098118e37 [ty] disable division-by-zero by default (#18220)
## Summary

I think `division-by-zero` is a low-value diagnostic in general; most
real division-by-zero errors (especially those that are less obvious to
the human eye) will occur on values typed as `int`, in which case we
don't issue the diagnostic anyway. Mypy and pyright do not emit this
diagnostic.

Currently the diagnostic is prone to false positives because a) we do
not silence it in unreachable code, and b) we do not implement narrowing
of literals from inequality checks. We will probably fix (a) regardless,
but (b) is low priority apart from division-by-zero.

I think we have many more important things to do and should not allow
false positives on a low-value diagnostic to be a distraction. Not
opposed to re-enabling this diagnostic in future when we can prioritize
reducing its false positives.

References https://github.com/astral-sh/ty/issues/443

## Test Plan

Existing tests.
2025-05-20 14:47:56 -04:00
Ramil Aleskerov
7917269d9a [ty] Add support for PyPy virtual environments (#18203)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-05-20 14:46:50 -04:00
Alex Waygood
e8d4f6d891 [ty] Ensure that a function-literal type is always equivalent to itself (#18227) 2025-05-20 14:11:03 -04:00
Alex Waygood
60b486abce [ty] Deeply normalize many types (#18222) 2025-05-20 11:41:26 -04:00
Dhruv Manilawala
32403dfb28 [ty] Avoid panicking when there are multiple workspaces (#18151)
## Summary

This PR updates the language server to avoid panicking when there are
multiple workspace folders passed during initialization. The server
currently picks up the first workspace folder and provides a warning and
a log message.

## Test Plan

<img width="1724" alt="Screenshot 2025-05-17 at 11 43 09"
src="https://github.com/user-attachments/assets/1a7ddbc3-198d-4191-a28f-9b69321e8f99"
/>
2025-05-20 20:53:23 +05:30
InSync
76ab3425d3 [ty] Integer indexing into bytes returns int (#18218)
## Summary

Resolves [#461](https://github.com/astral-sh/ty/issues/461).

ty was hardcoded to infer `BytesLiteral` types for integer indexing into
`BytesLiteral`. It will now infer `IntLiteral` types instead.

## Test Plan

Markdown tests.
2025-05-20 16:44:12 +02:00
हिमांशु
90ca0a4c13 add full option name in formatter warning (#18217) 2025-05-20 16:26:47 +02:00
Brent Westbrook
15dbfad265 Remove Checker::report_diagnostics (#18206)
Summary
--

I thought that emitting multiple diagnostics at once would be difficult
to port to a diagnostic construction model closer to ty's
`InferContext::report_lint`, so as a first step toward that, this PR
removes `Checker::report_diagnostics`.

In many cases I was able to do some related refactoring to avoid
allocating a `Vec<Diagnostic>` at all, often by adding a `Checker` field
to a `Visitor` or by passing a `Checker` instead of a `&mut
Vec<Diagnostic>`.

In other cases, I had to fall back on something like

```rust
for diagnostic in diagnostics {
    checker.report_diagnostic(diagnostic);
}
```

which I guess is a bit worse than the `extend` call in
`report_diagnostics`, but hopefully it won't make too much of a
difference.

I'm still not quite sure what to do with the remaining loop cases. The
two main use cases for collecting a sequence of diagnostics before
emitting any of them are:

1. Applying a single `Fix` to a group of diagnostics
2. Avoiding an earlier diagnostic if something goes wrong later

I was hoping we could get away with just a `DiagnosticGuard` that
reported a `Diagnostic` on drop, but I guess we will still need a
`DiagnosticGuardBuilder` that can be collected in these cases and
produce a `DiagnosticGuard` once we know we actually want the
diagnostics.

Test Plan
--

Existing tests
2025-05-20 10:00:06 -04:00
Vasco Schiavo
4f8a005f8f [flake8-simplify] enable fix in preview mode (SIM117) (#18208)
The PR add the `fix safety` section for rule `SIM117` (#15584 ), and
enable a fix in preview mode.
2025-05-20 08:34:50 -05:00
Micha Reiser
3b56c7ca3d Update salsa (#18212) 2025-05-20 09:19:34 +02:00
Micha Reiser
f9ca6eb63e Fix rendering of admonition in docs (#18163) 2025-05-20 08:22:06 +02:00
Adam Aaronson
8729cb208f [ty] Raise invalid-exception-caught even when exception is not captured (#18202)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-19 18:13:34 -04:00
Emily B. Zhang
a2c87c2bc1 [ty] Add note to unresolved-import hinting to users to configure their Python environment (#18207)
Closes https://github.com/astral-sh/ty/issues/453.

## Summary

Add an additional info diagnostic to `unresolved-import` check to hint
to users that they should make sure their Python environment is properly
configured for ty, linking them to the corresponding doc. This
diagnostic is only shown when an import is not relative, e.g., `import
maturin` not `import .maturin`.

## Test Plan

Updated snapshots with new info message and reran tests.
2025-05-19 17:24:25 -04:00
Vasco Schiavo
b302d89da3 [flake8-simplify] add fix safety section (SIM110) (#18114)
The PR add the `fix safety` section for rule `SIM110` (#15584 )

### Unsafe Fix Example

```python
def predicate(item):
    global called
    called += 1
    if called == 1:
    # after first call we change the method
        def new_predicate(_): return False
        globals()['predicate'] = new_predicate
    return True

def foo():
    for item in range(10):
        if predicate(item):
            return True
    return False

def foo_gen():
    return any(predicate(item) for item in range(10))

called = 0
print(foo())      # true – returns immediately on first call

called = 0
print(foo_gen())  # false – second call uses new `predicate`
```

### Note

I notice that
[here](46be305ad2/crates/ruff_linter/src/rules/flake8_simplify/rules/reimplemented_builtin.rs (L60))
we have two rules, `SIM110` & `SIM111`. The second one seems not anymore
active. Should I delete `SIM111`?
2025-05-19 16:38:08 -04:00
Douglas Creager
ce43dbab58 [ty] Promote literals when inferring class specializations from constructors (#18102)
This implements the stopgap approach described in
https://github.com/astral-sh/ty/issues/336#issuecomment-2880532213 for
handling literal types in generic class specializations.

With this approach, we will promote any literal to its instance type,
but _only_ when inferring a generic class specialization from a
constructor call:

```py
class C[T]:
    def __init__(self, x: T) -> None: ...

reveal_type(C("string"))  # revealed: C[str]
```

If you specialize the class explicitly, we still use whatever type you
provide, even if it's a literal:

```py
from typing import Literal

reveal_type(C[Literal[5]](5))  # revealed: C[Literal[5]]
```

And this doesn't apply at all to generic functions:

```py
def f[T](x: T) -> T:
    return x

reveal_type(f(5))  # revealed: Literal[5]
```

---

As part of making this happen, we also generalize the `TypeMapping`
machinery. This provides a way to apply a function to type, returning a
new type. Complicating matters is that for function literals, we have to
apply the mapping lazily, since the function's signature is not created
until (and if) someone calls its `signature` method. That means we have
to stash away the mappings that we want to apply to the signatures
parameter/return annotations once we do create it. This requires some
minor `Cow` shenanigans to continue working for partial specializations.
2025-05-19 15:42:54 -04:00
Felix Scherz
fb589730ef [ty]: Consider a class with a dynamic element in its MRO assignable to any subtype of type (#18205) 2025-05-19 19:30:30 +00:00
Douglas Creager
4fad15805b [ty] Use first matching constructor overload when inferring specializations (#18204)
This is a follow-on to #18155. For the example raised in
https://github.com/astral-sh/ty/issues/370:

```py
import tempfile

with tempfile.TemporaryDirectory() as tmp: ...
```

the new logic would notice that both overloads of `TemporaryDirectory`
match, and combine their specializations, resulting in an inferred type
of `str | bytes`.

This PR updates the logic to match our other handling of other calls,
where we only keep the _first_ matching overload. The result for this
example then becomes `str`, matching the runtime behavior. (We still do
not implement the full [overload resolution
algorithm](https://typing.python.org/en/latest/spec/overload.html#overload-call-evaluation)
from the spec.)
2025-05-19 15:12:28 -04:00
David Peter
0ede831a3f [ty] Add hint that PEP 604 union syntax is only available in 3.10+ (#18192)
## Summary

Add a new diagnostic hint if you try to use PEP 604 `X | Y` union syntax
in a non-type-expression before 3.10.

closes https://github.com/astral-sh/ty/issues/437

## Test Plan

New snapshot test
2025-05-19 19:47:31 +02:00
Brent Westbrook
d6009eb942 Unify Message variants (#18051)
## Summary

This PR unifies the ruff `Message` enum variants for syntax errors and
rule violations into a single `Message` struct consisting of a shared
`db::Diagnostic` and some additional, optional fields used for some rule
violations.

This version of `Message` is nearly a drop-in replacement for
`ruff_diagnostics::Diagnostic`, which is the next step I have in mind
for the refactor.

I think this is also a useful checkpoint because we could possibly add
some of these optional fields to the new `Diagnostic` type. I think
we've previously discussed wanting support for `Fix`es, but the other
fields seem less relevant, so we may just need to preserve the `Message`
wrapper for a bit longer.

## Test plan

Existing tests

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-19 13:34:04 -04:00
Wei Lee
236633cd42 [airflow] Update AIR301 and AIR311 with the latest Airflow implementations (#17985)
<!--
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? -->



* Remove the following rules
    * name
* `airflow.auth.managers.base_auth_manager.is_authorized_dataset` →
`airflow.api_fastapi.auth.managers.base_auth_manager.is_authorized_asset`
*
`airflow.providers.fab.auth_manager.fab_auth_manager.is_authorized_dataset`
→
`airflow.providers.fab.auth_manager.fab_auth_manager.is_authorized_asset`
* Update the following rules
    * name
* `airflow.models.baseoperatorlink.BaseOperatorLink` →
`airflow.sdk.BaseOperatorLink`
* `airflow.api_connexion.security.requires_access` → "Use
`airflow.api_fastapi.core_api.security.requires_access_*` instead`"
* `airflow.api_connexion.security.requires_access_dataset`→
`airflow.api_fastapi.core_api.security.requires_access_asset`
* `airflow.notifications.basenotifier.BaseNotifier` →
`airflow.sdk.bases.notifier.BaseNotifier`
        * `airflow.www.auth.has_access`  → None
        * `airflow.www.auth.has_access_dataset` → None
        * `airflow.www.utils.get_sensitive_variables_fields`→ None
        * `airflow.www.utils.should_hide_value_for_key`→ None
    * class attribute
        * `airflow..sensors.weekday.DayOfWeekSensor`
            * `use_task_execution_day` removed
*
`airflow.providers.amazon.aws.auth_manager.aws_auth_manager.AwsAuthManager`
            * `is_authorized_dataset`
* Add the following rules
    * class attribute
* `airflow.auth.managers.base_auth_manager.BaseAuthManager` |
`airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager`
     * name
* `airflow.auth.managers.base_auth_manager.BaseAuthManager` →
`airflow.api_fastapi.auth.managers.base_auth_manager.BaseAuthManager` *
`is_authorized_dataset` → `is_authorized_asset`
* refactor
    * simplify unnecessary match with if else
    * rename Replacement::Name as Replacement::AttrName

## Test Plan

<!-- How was it tested? -->
The test fixtures have been revised and updated.
2025-05-19 13:28:04 -04:00
Wei Lee
99cb89f90f [airflow] Move rules from AIR312 to AIR302 (#17940)
<!--
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? -->

In the later development of Airflow 3.0, backward compatibility was not
added for some cases. Thus, the following rules are moved back to AIR302

* airflow.hooks.subprocess.SubprocessResult →
airflow.providers.standard.hooks.subprocess.SubprocessResult
* airflow.hooks.subprocess.working_directory →
airflow.providers.standard.hooks.subprocess.working_directory
* airflow.operators.datetime.target_times_as_dates →
airflow.providers.standard.operators.datetime.target_times_as_dates
* airflow.operators.trigger_dagrun.TriggerDagRunLink →
airflow.providers.standard.operators.trigger_dagrun.TriggerDagRunLink
* airflow.sensors.external_task.ExternalTaskSensorLink →
airflow.providers.standard.sensors.external_task.ExternalDagLink (**This
one contains a minor change**)
* airflow.sensors.time_delta.WaitSensor →
airflow.providers.standard.sensors.time_delta.WaitSensor

## Test Plan

<!-- How was it tested? -->
2025-05-19 13:20:21 -04:00
Micha Reiser
ac5df56aa3 [ty] Small LSP cleanups (#18201) 2025-05-19 17:08:59 +00:00
Micha Reiser
6985de4c40 [ty] Show related information in diagnostic (#17359) 2025-05-19 18:52:12 +02:00
Micha Reiser
55a410a885 Default src.root to ['.', '<project_name>'] if the directory exists (#18141) 2025-05-19 18:11:27 +02:00
Douglas Creager
97058e8093 [ty] Infer function call typevars in both directions (#18155)
This primarily comes up with annotated `self` parameters in
constructors:

```py
class C[T]:
    def __init__(self: C[int]): ...
```

Here, we want infer a specialization of `{T = int}` for a call that hits
this overload.

Normally when inferring a specialization of a function call, typevars
appear in the parameter annotations, and not in the argument types. In
this case, this is reversed: we need to verify that the `self` argument
(`C[T]`, as we have not yet completed specialization inference) is
assignable to the parameter type `C[int]`.

To do this, we simply look for a typevar/type in both directions when
performing inference, and apply the inferred specialization to argument
types as well as parameter types before verifying assignability.

As a wrinkle, this exposed that we were not checking
subtyping/assignability for function literals correctly. Our function
literal representation includes an optional specialization that should
be applied to the signature. Before, function literals were considered
subtypes of (assignable to) each other only if they were identical Salsa
objects. Two function literals with different specializations should
still be considered subtypes of (assignable to) each other if those
specializations result in the same function signature (typically because
the function doesn't use the typevars in the specialization).

Closes https://github.com/astral-sh/ty/issues/370
Closes https://github.com/astral-sh/ty/issues/100
Closes https://github.com/astral-sh/ty/issues/258

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-19 11:45:40 -04:00
Douglas Creager
569c94b71b Add rustfmt.toml file (#18197)
My editor runs `rustfmt` on save to format Rust code, not `cargo fmt`.

With our recent bump to the Rust 2024 edition, the formatting that
`rustfmt`/`cargo fmt` applies changed. Unfortunately, `rustfmt` and
`cargo fmt` have different behaviors for determining which edition to
use when formatting: `cargo fmt` looks for the Rust edition in
`Cargo.toml`, whereas `rustfmt` looks for it in `rustfmt.toml`. As a
result, whenever I save, I have to remember to manually run `cargo fmt`
before committing/pushing.

There is an open issue asking for `rustfmt` to also look at `Cargo.toml`
when it's present (https://github.com/rust-lang/rust.vim/issues/368),
but it seems like they "closed" that issue just by bumping the default
edition (six years ago, from 2015 to 2018).

In the meantime, this PR adds a `rustfmt.toml` file with our current
Rust edition so that both invocation have the same behavior. I don't
love that this duplicates information in `Cargo.toml`, but I've added a
reminder comment there to hopefully ensure that we bump the edition in
both places three years from now.
2025-05-19 11:40:58 -04:00
Micha Reiser
59d80aff9f [ty] Update mypy primer (#18196) 2025-05-19 17:35:48 +02:00
David Peter
b913f568c4 [ty] Mark generated files as such in .gitattributes (#18195)
## Summary

See comment here:
https://github.com/astral-sh/ruff/pull/18156#discussion_r2095850586
2025-05-19 16:50:48 +02:00
David Peter
4c889d5251 [ty] Support typing.TypeAliasType (#18156)
## Summary

Support direct uses of `typing.TypeAliasType`, as in:

```py
from typing import TypeAliasType

IntOrStr = TypeAliasType("IntOrStr", int | str)

def f(x: IntOrStr) -> None:
    reveal_type(x)  # revealed: int | str
```

closes https://github.com/astral-sh/ty/issues/392

## Ecosystem

The new false positive here:
```diff
+ error[invalid-type-form] altair/utils/core.py:49:53: The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`
```
comes from the fact that we infer the second argument as a type
expression now. We silence false positives for PEP695 `ParamSpec`s, but
not for `P = ParamSpec("P")` inside `Callable[P, ...]`.

## Test Plan

New Markdown tests
2025-05-19 16:36:49 +02:00
Micha Reiser
220137ca7b Cargo update (#18191) 2025-05-19 09:14:11 +02:00
renovate[bot]
34337fb8ba Update NPM Development dependencies (#18187)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:57:45 +02:00
renovate[bot]
38c332fe23 Update Rust crate bincode to v2 (#18188)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-19 08:57:09 +02:00
renovate[bot]
9f743d1b9f Update astral-sh/setup-uv action to v6 (#18184)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:46:40 +02:00
renovate[bot]
405544cc8f Update dependency react-resizable-panels to v3 (#18185)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 06:29:31 +00:00
renovate[bot]
ab96adbcd1 Update dependency ruff to v0.11.10 (#18171)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:29:03 +02:00
renovate[bot]
a761b8cfa2 Update pre-commit dependencies (#18172)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-19 08:28:43 +02:00
renovate[bot]
8c020cc2e9 Update docker/build-push-action action to v6.17.0 (#18174)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:28:31 +02:00
renovate[bot]
c67aa0cce2 Update uraimo/run-on-arch-action action to v3 (#18190)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:28:22 +02:00
renovate[bot]
b00e390f3a Update docker/metadata-action action to v5.7.0 (#18175)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:28:09 +02:00
renovate[bot]
1f9df0c8f0 Update docker/setup-buildx-action action to v3.10.0 (#18176)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:27:55 +02:00
renovate[bot]
9dd9227bca Update taiki-e/install-action action to v2.51.2 (#18183)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:27:44 +02:00
renovate[bot]
181a380ee0 Update extractions/setup-just action to v3 (#18186)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:26:34 +02:00
renovate[bot]
12f5e99389 Update Rust crate jod-thread to v1 (#18189)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:25:46 +02:00
renovate[bot]
d9cd6399e6 Update Rust crate insta to v1.43.1 (#18180)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 06:24:40 +00:00
renovate[bot]
c40a801002 Update dependency pyodide to v0.27.6 (#18170)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:23:21 +02:00
renovate[bot]
04168cf1ce Update react monorepo to v19.1.0 (#18178)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:13:33 +02:00
renovate[bot]
6d0703ae78 Update taiki-e/install-action digest to 941e8a4 (#18168)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:10:30 +02:00
renovate[bot]
f7691a79a0 Update peter-evans/find-comment action to v3.1.0 (#18177)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:10:14 +02:00
renovate[bot]
6e7340c68b Update cargo-bins/cargo-binstall action to v1.12.5 (#18169)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:09:54 +02:00
renovate[bot]
5095248b7e Update Rust crate bitflags to v2.9.1 (#18173)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:09:42 +02:00
renovate[bot]
b1e6c6edce Update Rust crate criterion to 0.6.0 (#18179)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:09:18 +02:00
renovate[bot]
8ee92c6c77 Update Rust crate tempfile to v3.20.0 (#18182)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:07:22 +02:00
renovate[bot]
d6709abd94 Update Rust crate quickcheck_macros to v1.1.0 (#18181)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 08:06:32 +02:00
Dragon
660375d429 T201/T203 Improve print/pprint docs (#18130)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-18 18:40:42 +02:00
Alex Waygood
dd04ca7f58 [ty] Add regression test for fixed pyvenv.cfg parsing bug (#18157) 2025-05-17 21:10:15 +00:00
Chandra Kiran G
b86960f18c [ty] Add rule link to server diagnostics (#18128)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-17 17:27:59 +00:00
Carl Meyer
2abcd86c57 Revert "[ty] Better control flow for boolean expressions that are inside if (#18010)" (#18150)
This reverts commit 9910ec700c.

## Summary

This change introduced a serious performance regression. Revert it while
we investigate.

Fixes https://github.com/astral-sh/ty/issues/431

## Test Plan

Timing on the snippet in https://github.com/astral-sh/ty/issues/431
again shows times similar to before the regression.
2025-05-17 08:27:32 -04:00
Matthew Mckee
c6e55f673c Remove pyvenv.cfg validation check for lines with multiple = (#18144) 2025-05-17 08:42:39 +02:00
Micha Reiser
3d55a16c91 [ty] Migrate the namespace package module resolver tests to mdtests (#18133)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-05-16 19:56:33 +02:00
Micha Reiser
e21972a79b Fix test scripts CI job (#18140) 2025-05-16 17:49:27 +00:00
Alex Waygood
0adbb3d600 [ty] Fix assignability checks for invariant generics parameterized by gradual types (#18138) 2025-05-16 13:37:07 -04:00
Alex Waygood
28fb802467 [ty] Merge SemanticIndexBuilder impl blocks (#18135)
## Summary

just a minor nit followup to
https://github.com/astral-sh/ruff/pull/18010 -- put all the
non-`Visitor` methods of `SemanticIndexBuilder` in the same impl block
rather than having multiple impl blocks

## Test Plan

`cargo build`
2025-05-16 11:05:02 -04:00
Brent Westbrook
a1d007c37c Use insta settings instead of cfg (#18134)
Summary
--

I noticed these `cfg` directives while working on diagnostics. I think
it makes more sense to apply an `insta` filter in the test instead. I
copied this filter from a CLI test for the same rule.

Test Plan
--

Existing tests, especially Windows CI on this PR
2025-05-16 10:55:33 -04:00
Micha Reiser
1ba56b4bc6 [ty] Fix relative imports in stub packages (#18132) 2025-05-16 15:30:10 +02:00
David Peter
e677cabd69 [ty] Reduce size of the many-tuple-assignments benchmark (#18131)
## Summary

The previous version took several minute to complete on codspeed.
2025-05-16 15:28:23 +02:00
TomerBin
9910ec700c [ty] Better control flow for boolean expressions that are inside if (#18010)
## Summary
With this PR we now detect that x is always defined in `use`:
```py
if flag and (x := number):
    use(x)
```

When outside if, it's still detected as possibly not defined
```py
flag and (x := number)
# error: [possibly-unresolved-reference]
use(x)
```
In order to achieve that, I had to find a way to get access to the
flow-snapshots of the boolean expression when analyzing the flow of the
if statement. I did it by special casing the visitor of boolean
expression to return flow control information, exporting two snapshots -
`maybe_short_circuit` and `no_short_circuit`. When indexing
boolean expression itself we must assume all possible flows, but when
it's inside if statement, we can be smarter than that.

## Test Plan
Fixed existing and added new mdtests.
I went through some of mypy primer results and they look fine

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-16 11:59:21 +00:00
Micha Reiser
9ae698fe30 Switch to Rust 2024 edition (#18129) 2025-05-16 13:25:28 +02:00
David Peter
e67b35743a [ty] NamedTuple 'fallback' attributes (#18127)
## Summary

Add various attributes to `NamedTuple` classes/instances that are
available at runtime.

closes https://github.com/astral-sh/ty/issues/417

## Test Plan

New Markdown tests
2025-05-16 12:56:43 +02:00
David Peter
8644c9da43 [ty] Regression test for relative import in stubs package (#18123)
## Summary

Regression test for https://github.com/astral-sh/ty/issues/408
2025-05-16 12:49:35 +02:00
Micha Reiser
196e4befba Update MSRV to 1.85 and toolchain to 1.87 (#18126) 2025-05-16 09:19:55 +02:00
David Peter
6e39250015 [ty] Allow unions including Any/Unknown as bases (#18094)
## Summary

Alternative fix for https://github.com/astral-sh/ty/issues/312

## Test Plan

New Markdown test
2025-05-16 06:57:26 +02:00
Matthew Mckee
7dc4fefb47 Remove ty property tests (#18124) 2025-05-15 20:57:00 -04:00
Vasco Schiavo
e5435eb106 [flake8-simplify] add fix safety section (SIM210) (#18100)
The PR add the `fix safety` section for rule `SIM210` (#15584 )

It is a little cheating, as the Fix safety section is copy/pasted by
#18086 as the problem is the same.

### Unsafe Fix Example

```python
class Foo():
    def __eq__(self, other):
        return 0

def foo():
    return True if Foo() == 0 else False

def foo_fix():
    return Foo() == 0

print(foo()) # False
print(foo_fix()) # 0
```
2025-05-15 16:26:10 -04:00
Victor Hugo Gomes
f53c580c53 [pylint] Fix PLW1514 not recognizing the encoding positional argument of codecs.open (#18109)
<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

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

## Test Plan

Snapshot tests
<!-- How was it tested? -->
2025-05-15 16:17:07 -04:00
Wei Lee
2ceba6ae67 [airflow] Add autofixes for AIR302 and AIR312 (#17942)
<!--
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? -->

`ProviderReplacement::Name` was designed back when we only wanted to do
linting. Now we also want to fix the user code. It would be easier for
us to replace them with better AutoImport struct.

## Test Plan

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

The test fixture has been updated as some cases can now be fixed
2025-05-15 16:03:02 -04:00
Felix Scherz
d3a7cb3fe4 [ty] support accessing __builtins__ global (#18118)
## Summary

The PR adds an explicit check for `"__builtins__"` during name lookup,
similar to how `"__file__"` is implemented. The inferred type is
`Any`.

closes https://github.com/astral-sh/ty/issues/393

## Test Plan

Added a markdown test for `__builtins__`.

---------

Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-05-15 22:01:38 +02:00
Andrew Gallant
69393b2e6e [ty] Improve invalid method calls for unmatched overloads (#18122)
This makes an easy tweak to allow our diagnostics for unmatched
overloads to apply to method calls. Previously, they only worked for
function calls.

There is at least one other case worth addressing too, namely, class
literals. e.g., `type()`. We had a diagnostic snapshot test case to
track it.

Closes astral-sh/ty#274
2025-05-15 11:39:14 -04:00
David Peter
c066bf0127 [ty] type[…] is always assignable to type (#18121)
## Summary

Model that `type[C]` is always assignable to `type`, even if `C` is not
fully static.

closes https://github.com/astral-sh/ty/issues/312

## Test Plan

* New Markdown tests
* Property tests
2025-05-15 17:13:47 +02:00
Max Mynter
a5ee1a3bb1 Bump py-fuzzer Dependencies (#18113) 2025-05-15 10:47:37 -04:00
Brent Westbrook
e2c5b83fe1 Inline DiagnosticKind into other diagnostic types (#18074)
## Summary

This PR deletes the `DiagnosticKind` type by inlining its three fields
(`name`, `body`, and `suggestion`) into three other diagnostic types:
`Diagnostic`, `DiagnosticMessage`, and `CacheMessage`.

Instead of deferring to an internal `DiagnosticKind`, both `Diagnostic`
and `DiagnosticMessage` now have their own macro-generated `AsRule`
implementations.

This should make both https://github.com/astral-sh/ruff/pull/18051 and
another follow-up PR changing the type of `name` on `CacheMessage`
easier since its type will be able to change separately from
`Diagnostic` and `DiagnosticMessage`.

## Test Plan

Existing tests
2025-05-15 10:27:21 -04:00
Brent Westbrook
b35bf8ae07 Bump 0.11.10 (#18120) 2025-05-15 09:54:08 -04:00
David Peter
279dac1c0e [ty] Make dataclass instances adhere to DataclassInstance (#18115)
## Summary

Make dataclass instances adhere to the `DataclassInstance` protocol.

fixes astral-sh/ty#400

## Test Plan

New Markdown tests
2025-05-15 14:27:23 +02:00
Micha Reiser
57617031de [ty] Enable optimizations for salsa in debug profile (#18117) 2025-05-15 12:31:46 +02:00
Micha Reiser
28b5a868d3 [ty] Enable 'ansi' feature to fix compile error (#18116) 2025-05-15 11:43:15 +02:00
Micha Reiser
b6b7caa023 [ty] Change layout of extra verbose output and respect --color for verbose output (#18089) 2025-05-15 09:57:59 +02:00
InSync
46be305ad2 [ty] Include synthesized arguments in displayed counts for too-many-positional-arguments (#18098)
## Summary

Resolves [#290](https://github.com/astral-sh/ty/issues/290).

All arguments, synthesized or not, are now accounted for in
`too-many-positional-arguments`'s error message.

For example, consider this example:

```python
class C:
	def foo(self): ...

C().foo(1)  # !!!
```

Previously, ty would say:

> Too many positional arguments to bound method foo: expected 0, got 1

After this change, it will say:

> Too many positional arguments to bound method foo: expected 1, got 2

This is what Python itself does too:

```text
Traceback (most recent call last):
  File "<python-input-0>", line 3, in <module>
    C().foo()
    ~~~~~~~^^
TypeError: C.foo() takes 0 positional arguments but 1 was given
```

## Test Plan

Markdown tests.
2025-05-14 22:51:23 -04:00
Alex Waygood
c3a4992ae9 [ty] Fix normalization of unions containing instances parameterized with unions (#18112) 2025-05-14 22:48:33 -04:00
Alex Waygood
9aa6330bb1 [ty] Fix redundant-cast false positives when casting to Unknown (#18111) 2025-05-14 22:38:53 -04:00
github-actions[bot]
b600ff106a Sync vendored typeshed stubs (#18110)
Close and reopen this PR to trigger CI

---------

Co-authored-by: typeshedbot <>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-14 22:14:52 -04:00
Vasco Schiavo
466021d5e1 [flake8-simplify] add fix safety section (SIM112) (#18099)
The PR add the `fix safety` section for rule `SIM112` (#15584 ).
2025-05-14 17:16:20 -04:00
Simon Sawert
33e14c5963 Update Neovim setup docs (#18108)
## Summary

Nvim 0.11+ uses the builtin `vim.lsp.enable` and `vim.lsp.config` to
enable and configure LSP clients. This adds the new non legacy way of
configuring Nvim with `nvim-lspconfig` according to the upstream
documentation.

Update documentation for Nvim LSP configuration according to
`nvim-lspconfig` and Nvim 0.11+

## Test Plan

Tested locally on macOS with Nvim 0.11.1 and `nvim-lspconfig`
master/[ac1dfbe](ac1dfbe3b6).
2025-05-14 20:54:24 +00:00
David Peter
6800a9f6f3 [ty] Add type-expression syntax link to invalid-type-expression (#18104)
## Summary

Add a link to [this
page](https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions)
when emitting `invalid-type-expression` diagnostics.
2025-05-14 18:56:44 +00:00
Vasco Schiavo
68559fc17d [flake8-simplify] add fix safety section (SIM103) (#18086)
The PR add the `fix safety` section for rule `SIM103` (#15584 )

### Unsafe Fix Example

```python
class Foo:
    def __eq__(self, other):
        return 1
    
def foo():
    if Foo() == 1:
        return True
    return False

def foo_fix():
    return Foo() == 1
    
print(foo()) # True
print(foo_fix()) # 1
```

### Note

I updated the code snippet example, because I thought it was cool to
have a correct example, i.e., that I can paste inside the playground and
it works :-)
2025-05-14 14:24:15 -04:00
David Peter
2a217e80ca [ty] mypy_primer: fix static-frame setup (#18103)
## Summary

Pull in https://github.com/hauntsaninja/mypy_primer/pull/169
2025-05-14 20:23:53 +02:00
Dan Parizher
030a16cb5f [flake8-simplify] Correct behavior for str.split/rsplit with maxsplit=0 (SIM905) (#18075)
Fixes #18069

<!--
Thank you for contributing to Ruff/ty! 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? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR addresses a bug in the `flake8-simplify` rule `SIM905`
(split-static-string) where `str.split(maxsplit=0)` and
`str.rsplit(maxsplit=0)` produced incorrect results for empty strings or
strings starting/ending with whitespace. The fix ensures that the
linting rule's suggested replacements now align with Python's native
behavior for these specific `maxsplit=0` scenarios.

## Test Plan

1. Added new test cases to the existing
`crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM905.py`
fixture to cover the scenarios described in issue #18069.
2.  Ran `cargo test -p ruff_linter`.
3. Verified and accepted the updated snapshots for `SIM905.py` using
`cargo insta review`. The new snapshots confirm the corrected behavior
for `maxsplit=0`.
2025-05-14 14:20:18 -04:00
Alex Waygood
0590b38214 [ty] Fix more generics-related TODOs (#18062) 2025-05-14 12:26:52 -04:00
Usul-Dev
8104b1e83b [ty] fix missing '>' in HTML anchor tags in CLI reference (#18096)
Co-authored-by: Usul <Usul-Dev@users.noreply.github.com>
2025-05-14 15:50:35 +00:00
Dhruv Manilawala
cf70c7863c Remove symlinks from the fuzz directory (#18095)
## Summary

This PR does the following:
1. Remove the symlinks from the `fuzz/` directory
2. Update `init-fuzzer.sh` script to create those symlinks
3. Update `fuzz/.gitignore` to ignore those corpus directories

## Test Plan

Initialize the fuzzer:

```sh
./fuzz/init-fuzzer.sh
```

And, run a fuzz target:

```sh
cargo +nightly fuzz run ruff_parse_simple -- -timeout=1 -only_ascii=1
```
2025-05-14 21:05:52 +05:30
Andrew Gallant
faf54c0181 ty_python_semantic: improve failed overloaded function call
The diagnostic now includes a pointer to the implementation definition
along with each possible overload.

This doesn't include information about *why* each overload failed. But
given the emphasis on concise output (since there can be *many*
unmatched overloads), it's not totally clear how to include that
additional information.

Fixes #274
2025-05-14 11:13:41 -04:00
Andrew Gallant
451c5db7a3 ty_python_semantic: move some routines to FunctionType
These are, after all, specific to function types. The methods on `Type`
are more like conveniences that return something when the type *happens*
to be a function. But defining them on `FunctionType` itself makes it
easy to call them when you have a `FunctionType` instead of a `Type`.
2025-05-14 11:13:41 -04:00
Andrew Gallant
bd5b7f415f ty_python_semantic: rejigger handling of overload error conditions
I found the previous code somewhat harder to read. Namely, a `for`
loop was being used to encode "execute zero or one times, but not
more." Which is sometimes okay, but it seemed clearer to me to use
more explicit case analysis here.

This should have no behavioral changes.
2025-05-14 11:13:41 -04:00
Andrew Gallant
0230cbac2c ty_python_semantic: update "no matching overload" diagnostic test
It looks like support for `@overload` has been added since this test was
created, so we remove the TODO and add a snippet (from #274).
2025-05-14 11:13:41 -04:00
Wei Lee
2e94d37275 [airflow] Get rid of Replacement::Name and replace them with Replacement::AutoImport for enabling auto fixing (AIR301, AIR311) (#17941)
<!--
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? -->

Similiar to https://github.com/astral-sh/ruff/pull/17941.

`Replacement::Name` was designed for linting only. Now, we also want to
fix the user code. It would be easier to replace it with a better
AutoImport struct whenever possible.

On the other hand, `AIR301` and `AIR311` contain attribute changes that
can still use a struct like `Replacement::Name`. To reduce the
confusion, I also updated it as `Replacement::AttrName`

Some of the original `Replacement::Name` has been replaced as
`Replacement::Message` as they're not directly mapping and the message
has now been moved to `help`


## Test Plan

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

The test fixtures have been updated
2025-05-14 11:10:15 -04:00
Vasco Schiavo
1e4377c9c6 [ruff] add fix safety section (RUF007) (#17755)
The PR add the `fix safety` section for rule `RUF007` (#15584 )

It seems that the fix was always marked as unsafe #14401

## Unsafety example

This first example is a little extreme. In fact, the class `Foo`
overrides the `__getitem__` method but in a very special, way. The
difference lies in the fact that `zip(letters, letters[1:])` call the
slice `letters[1:]` which is behaving weird in this case, while
`itertools.pairwise(letters)` call just `__getitem__(0), __getitem__(1),
...` and so on.

Note that the diagnostic is emitted: [playground](https://play.ruff.rs)

I don't know if we want to mention this problem, as there is a subtile
bug in the python implementation of `Foo` which make the rule unsafe.

```python
from dataclasses import dataclass
import itertools

@dataclass
class Foo:
    letters: str
    
    def __getitem__(self, index):
        return self.letters[index] + "_foo"


letters = Foo("ABCD")
zip_ = zip(letters, letters[1:])
for a, b in zip_:
    print(a, b) # A_foo B, B_foo C, C_foo D, D_foo _
    
pair = itertools.pairwise(letters)
for a, b in pair:
    print(a, b) # A_foo B_foo, B_foo C_foo, C_foo D_foo
```

This other example is much probable.
here, `itertools.pairwise` was shadowed by a costume function
[(playground)](https://play.ruff.rs)

```python
from dataclasses import dataclass
from itertools import pairwise

def pairwise(a):
    return []
    
letters = "ABCD"
zip_ = zip(letters, letters[1:])
print([(a, b) for a, b in zip_]) # [('A', 'B'), ('B', 'C'), ('C', 'D')]

pair = pairwise(letters)
print(pair) # []
```
2025-05-14 11:07:11 -04:00
Dimitri Papadopoulos Orfanos
1b4f7de840 [pyupgrade] Add resource.error as deprecated alias of OSError (UP024) (#17933)
## Summary

Partially addresses #17935.


[`resource.error`](https://docs.python.org/3/library/resource.html#resource.error)
is a deprecated alias of
[`OSError`](https://docs.python.org/3/library/exceptions.html#OSError).
> _Changed in version 3.3:_ Following [**PEP
3151**](https://peps.python.org/pep-3151/), this class was made an alias
of
[`OSError`](https://docs.python.org/3/library/exceptions.html#OSError).

Add it to the list of `OSError` aliases found by [os-error-alias
(UP024)](https://docs.astral.sh/ruff/rules/os-error-alias/#os-error-alias-up024).

## Test Plan

Sorry, I usually don't program in Rust. Could you at least point me to
the test I would need to modify?
2025-05-14 10:37:25 -04:00
Victor Hugo Gomes
9b52ae8991 [flake8-pytest-style] Don't recommend usefixtures for parametrize values in PT019 (#17650)
<!--
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 #17599.

## Test Plan

Snapshot tests.

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-05-14 10:31:42 -04:00
David Peter
97d7b46936 [ty] Do not look up __init__ on instances (#18092)
## Summary

Dunder methods are never looked up on instances. We do this implicitly
in `try_call_dunder`, but the corresponding flag was missing in the
instance-construction code where we use `member_lookup_with_policy`
directly.

fixes https://github.com/astral-sh/ty/issues/322

## Test Plan

Added regression test.
2025-05-14 15:33:42 +02:00
Luke
1eab59e681 Remove double whitespace (#18090) 2025-05-14 11:20:19 +02:00
Micha Reiser
e7f97a3e4b [ty] Reduce log level of 'symbol .. (via star import) not found' log message (#18087) 2025-05-14 09:20:23 +02:00
Chandra Kiran G
d17557f0ae [ty] Fix Inconsistent casing in diagnostic (#18084) 2025-05-14 08:26:48 +02:00
Dhruv Manilawala
8cbd433a31 [ty] Add cycle handling for unpacking targets (#18078)
## Summary

This PR adds cycle handling for `infer_unpack_types` based on the
analysis in astral-sh/ty#364.

Fixes: astral-sh/ty#364

## Test Plan

Add a cycle handling test for unpacking in `cycle.md`
2025-05-13 21:27:48 +00:00
Alex Waygood
65e48cb439 [ty] Check assignments to implicit global symbols are assignable to the types declared on types.ModuleType (#18077) 2025-05-13 16:37:20 -04:00
David Peter
301d9985d8 [ty] Add benchmark for union of tuples (#18076)
## Summary

Add a micro-benchmark for the code pattern observed in
https://github.com/astral-sh/ty/issues/362.

This currently takes around 1 second on my machine.

## Test Plan

```bash
cargo bench -p ruff_benchmark -- 'ty_micro\[many_tuple' --sample-size 10
```
2025-05-13 22:14:30 +02:00
Micha Reiser
cfbb914100 Use https://ty.dev/rules when linking to the rules table (#18072) 2025-05-13 19:21:06 +02:00
Douglas Creager
fe653de3dd [ty] Infer parameter specializations of explicitly implemented generic protocols (#18054)
Follows on from (and depends on)
https://github.com/astral-sh/ruff/pull/18021.

This updates our function specialization inference to infer type
mappings from parameters that are generic protocols.

For now, this only works when the argument _explicitly_ implements the
protocol by listing it as a base class. (We end up using exactly the
same logic as for generic classes in #18021.) For this to work with
classes that _implicitly_ implement the protocol, we will have to check
the types of the protocol members (which we are not currently doing), so
that we can infer the specialization of the protocol that the class
implements.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-05-13 13:13:00 -04:00
InSync
a9f7521944 [ty] Shorten snapshot names (#18039)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-13 18:43:19 +02:00
Carl Meyer
f8890b70c3 [ty] __file__ is always a string inside a Python module (#18071)
## Summary

Understand that `__file__` is always set and a `str` when looked up as
an implicit global from a Python file we are type checking.

## Test Plan

mdtests
2025-05-13 08:20:43 -07:00
David Peter
142c1bc760 [ty] Recognize submodules in self-referential imports (#18005)
## Summary

Fix the lookup of `submodule`s in cases where the `parent` module has a
self-referential import like `from parent import submodule`. This allows
us to infer proper types for many symbols where we previously inferred
`Never`. This leads to many new false (and true) positives across the
ecosystem because the fact that we previously inferred `Never` shadowed
a lot of problems. For example, we inferred `Never` for `os.path`, which
is why we now see a lot of new diagnostics related to `os.path.abspath`
and similar.

```py
import os

reveal_type(os.path)  # previously: Never, now: <module 'os.path'>
```

closes https://github.com/astral-sh/ty/issues/261
closes https://github.com/astral-sh/ty/issues/307

## Ecosystem analysis

```
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┓
┃ Diagnostic ID                 ┃ Severity ┃ Removed ┃ Added ┃ Net Change ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━┩
│ call-non-callable             │ error    │       1 │     5 │         +4 │
│ call-possibly-unbound-method  │ warning  │       6 │    26 │        +20 │
│ invalid-argument-type         │ error    │      26 │    94 │        +68 │
│ invalid-assignment            │ error    │      18 │    46 │        +28 │
│ invalid-context-manager       │ error    │       9 │     4 │         -5 │
│ invalid-raise                 │ error    │       1 │     1 │          0 │
│ invalid-return-type           │ error    │       3 │    20 │        +17 │
│ invalid-super-argument        │ error    │       4 │     0 │         -4 │
│ invalid-type-form             │ error    │     573 │     0 │       -573 │
│ missing-argument              │ error    │       2 │    10 │         +8 │
│ no-matching-overload          │ error    │       0 │   715 │       +715 │
│ non-subscriptable             │ error    │       0 │    35 │        +35 │
│ not-iterable                  │ error    │       6 │     7 │         +1 │
│ possibly-unbound-attribute    │ warning  │      14 │    31 │        +17 │
│ possibly-unbound-import       │ warning  │      13 │     0 │        -13 │
│ possibly-unresolved-reference │ warning  │       0 │     8 │         +8 │
│ redundant-cast                │ warning  │       1 │     0 │         -1 │
│ too-many-positional-arguments │ error    │       2 │     0 │         -2 │
│ unknown-argument              │ error    │       2 │     0 │         -2 │
│ unresolved-attribute          │ error    │     583 │   304 │       -279 │
│ unresolved-import             │ error    │       0 │    96 │        +96 │
│ unsupported-operator          │ error    │       0 │    17 │        +17 │
│ unused-ignore-comment         │ warning  │      29 │     2 │        -27 │
├───────────────────────────────┼──────────┼─────────┼───────┼────────────┤
│ TOTAL                         │          │    1293 │  1421 │       +128 │
└───────────────────────────────┴──────────┴─────────┴───────┴────────────┘

Analysis complete. Found 23 unique diagnostic IDs.
Total diagnostics removed: 1293
Total diagnostics added: 1421
Net change: +128
```

* We see a lot of new errors (`no-matching-overload`) related to
`os.path.dirname` and other `os.path` operations because we infer `str |
None` for `__file__`, but many projects use something like
`os.path.dirname(__file__)`.
* We also see many new `unresolved-attribute` errors related to the fact
that we now infer proper module types for some imports (e.g. `import
kornia.augmentation as K`), but we don't allow implicit imports (e.g.
accessing `K.auto.operations` without also importing `K.auto`). See
https://github.com/astral-sh/ty/issues/133.
* Many false positive `invalid-type-form` are removed because we now
infer the correct type for some type expression instead of `Never`,
which is not valid in a type annotation/expression context.

## Test Plan

Added new Markdown tests
2025-05-13 16:59:11 +02:00
Alex Waygood
c0f22928bd [ty] Add a note to the diagnostic if a new builtin is used on an old Python version (#18068)
## Summary

If the user tries to use a new builtin on an old Python version, tell
them what Python version the builtin was added on, what our inferred
Python version is for their project, and what configuration settings
they can tweak to fix the error.

## Test Plan

Snapshots and screenshots:


![image](https://github.com/user-attachments/assets/767d570e-7af1-4e1f-98cf-50e4311db511)
2025-05-13 10:08:04 -04:00
Alex Waygood
5bf5f3682a [ty] Add tests for else branches of hasattr() narrowing (#18067)
## Summary

This addresses @sharkdp's post-merge review in
https://github.com/astral-sh/ruff/pull/18053#discussion_r2086190617

## Test Plan

`cargo test -p ty_python_semantic`
2025-05-13 09:57:53 -04:00
Alex Waygood
5913997c72 [ty] Improve diagnostics for assert_type and assert_never (#18050) 2025-05-13 13:00:20 +00:00
Carl Meyer
00f672a83b [ty] contribution guide (#18061)
First take on a contributing guide for `ty`. Lots of it is copied from
the existing Ruff contribution guide.

I've put this in Ruff repo, since I think a contributing guide belongs
where the code is. I also updated the Ruff contributing guide to link to
the `ty` one.

Once this is merged, we can also add a link from the `CONTRIBUTING.md`
in ty repo (which focuses on making contributions to things that are
actually in the ty repo), to this guide.

I also updated the pull request template to mention that it might be a
ty PR, and mention the `[ty]` PR title prefix.

Feel free to update/modify/merge this PR before I'm awake tomorrow.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
Co-authored-by: David Peter <mail@david-peter.de>
2025-05-13 10:55:01 +02:00
Abhijeet Prasad Bodas
68b0386007 [ty] Implement DataClassInstance protocol for dataclasses. (#18018)
Fixes: https://github.com/astral-sh/ty/issues/92

## Summary

We currently get a `invalid-argument-type` error when using
`dataclass.fields` on a dataclass, because we do not synthesize the
`__dataclass_fields__` member.

This PR fixes this diagnostic.

Note that we do not yet model the `Field` type correctly. After that is
done, we can assign a more precise `tuple[Field, ...]` type to this new
member.

## Test Plan
New mdtest.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-05-13 10:31:26 +02:00
ZGY
0ae07cdd1f [ruff_python_ast] Fix redundant visitation of test expressions in elif clause statements (#18064) 2025-05-13 07:10:23 +00:00
Douglas Creager
0fb94c052e [ty] Infer parameter specializations of generic aliases (#18021)
This updates our function specialization inference to infer type
mappings from parameters that are generic aliases, e.g.:

```py
def f[T](x: list[T]) -> T: ...

reveal_type(f(["a", "b"]))  # revealed: str
```

Though note that we're still inferring the type of list literals as
`list[Unknown]`, so for now we actually need something like the
following in our tests:

```py
def _(x: list[str]):
    reveal_type(f(x))  # revealed: str
```
2025-05-12 22:12:44 -04:00
Alex Waygood
55df9271ba [ty] Understand homogeneous tuple annotations (#17998) 2025-05-12 22:02:25 -04:00
Douglas Creager
f301931159 [ty] Induct into instances and subclasses when finding and applying generics (#18052)
We were not inducting into instance types and subclass-of types when
looking for legacy typevars, nor when apply specializations.

This addresses
https://github.com/astral-sh/ruff/pull/17832#discussion_r2081502056

```py
from __future__ import annotations
from typing import TypeVar, Any, reveal_type

S = TypeVar("S")

class Foo[T]:
    def method(self, other: Foo[S]) -> Foo[T | S]: ...  # type: ignore[invalid-return-type]

def f(x: Foo[Any], y: Foo[Any]):
    reveal_type(x.method(y))  # revealed: `Foo[Any | S]`, but should be `Foo[Any]`
```

We were not detecting that `S` made `method` generic, since we were not
finding it when searching the function signature for legacy typevars.
2025-05-12 21:53:11 -04:00
Alex Waygood
7e9b0df18a [ty] Allow classes to inherit from type[Any] or type[Unknown] (#18060) 2025-05-12 20:30:21 -04:00
Alex Waygood
41fa082414 [ty] Allow a class to inherit from an intersection if the intersection contains a dynamic type and the intersection is not disjoint from type (#18055) 2025-05-12 23:07:11 +00:00
Alex Waygood
c7b6108cb8 [ty] Narrowing for hasattr() (#18053) 2025-05-12 18:58:14 -04:00
Zanie Blue
a97e72fb5e Update reference documentation for --python-version (#18056)
Adding more detail here
2025-05-12 22:31:04 +00:00
Victor Hugo Gomes
0d6fafd0f9 [flake8-bugbear] Ignore B028 if skip_file_prefixes is present (#18047)
## Summary

Fixes #18011
2025-05-12 17:06:51 -05:00
Wei Lee
2eb2d5359b [airflow] Apply try-catch guard to all AIR3 rules (AIR3) (#17887)
<!--
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? -->

If a try-catch block guards the names, we don't raise warnings. During
this change, I discovered that some of the replacement types were
missed. Thus, I extend the fix to types other than AutoImport as well

## Test Plan

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

Test fixtures are added and updated.
2025-05-12 17:13:41 -04:00
Yunchi Pang
f549dfe39d [pylint] add fix safety section (PLW3301) (#17878)
parent: #15584 
issue: #16163

---------

Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-05-12 20:51:05 +00:00
Zanie Blue
6b64630635 Update --python to accept paths to executables in virtual environments (#17954)
## Summary

Updates the `--python` flag to accept Python executables in virtual
environments. Notably, we do not query the executable and it _must_ be
in a canonical location in a virtual environment. This is pretty naive,
but solves for the trivial case of `ty check --python .venv/bin/python3`
which will be a common mistake (and `ty check --python $(which python)`)

I explored this while trying to understand Python discovery in ty in
service of https://github.com/astral-sh/ty/issues/272, I'm not attached
to it, but figure it's worth sharing.

As an alternative, we can add more variants to the
`SearchPathValidationError` and just improve the _error_ message, i.e.,
by hinting that this looks like a virtual environment and suggesting the
concrete alternative path they should provide. We'll probably want to do
that for some other cases anyway (e.g., `3.13` as described in the
linked issue)

This functionality is also briefly mentioned in
https://github.com/astral-sh/ty/issues/193

Closes https://github.com/astral-sh/ty/issues/318

## Test Plan

e.g.,

```
uv run ty check --python .venv/bin/python3
```

needs test coverage still
2025-05-12 15:39:04 -05:00
Yunchi Pang
d545b5bfd2 [pylint] add fix safety section (PLE4703) (#17824)
This PR adds a fix safety section in comment for rule PLE4703.

parent: #15584 
impl was introduced at #970 (couldn't find newer PRs sorry!)
2025-05-12 16:27:54 -04:00
Marcus Näslund
b2d9f59937 [ruff] Implement a recursive check for RUF060 (#17976)
<!--
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? -->
The existing implementation of RUF060 (InEmptyCollection) is not
recursive, meaning that although set([]) results in an empty collection,
the existing code fails it because set is taking an argument.

The updated implementation allows set and frozenset to take empty
collection as positional argument (which results in empty
set/frozenset).

## Test Plan

Added test cases for recursive cases + updated snapshot (see RUF060.py).

---------

Co-authored-by: Marcus Näslund <marcus.naslund@kognity.com>
2025-05-12 16:17:13 -04:00
Victor Hugo Gomes
d7ef01401c [flake8-use-pathlib] PTH* suppress diagnostic for all os.* functions that have the dir_fd parameter (#17968)
<!--
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? -->

Fixes #17776.

This PR also handles all other `PTH*` rules that don't support file
descriptors.

## Test Plan

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

Update existing tests.
2025-05-12 16:11:56 -04:00
Victor Hugo Gomes
c9031ce59f [refurb] Mark autofix as safe only for number literals in FURB116 (#17692)
<!--
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
We can only guarantee the safety of the autofix for number literals, all
other cases may change the runtime behaviour of the program or introduce
a syntax error. For the cases reported in the issue that would result in
a syntax error, I disabled the autofix.

Follow-up of #17661. 

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

## Test Plan

Snapshot tests.
<!-- How was it tested? -->
2025-05-12 16:08:12 -04:00
Victor Hugo Gomes
138ab91def [flake8-simplify] Fix SIM905 autofix for rsplit creating a reversed list literal (#18045)
## Summary

Fixes #18042
2025-05-12 14:53:08 -05:00
Ibraheem Ahmed
550b8be552 Avoid initializing progress bars early (#18049)
## Summary

Resolves https://github.com/astral-sh/ty/issues/324.
2025-05-12 15:07:55 -04:00
Douglas Creager
bdccb37b4a [ty] Apply function specialization to all overloads (#18020)
Function literals have an optional specialization, which is applied to
the parameter/return type annotations lazily when the function's
signature is requested. We were previously only applying this
specialization to the final overload of an overloaded function.

This manifested most visibly for `list.__add__`, which has an overloaded
definition in the typeshed:


b398b83631/crates/ty_vendored/vendor/typeshed/stdlib/builtins.pyi (L1069-L1072)

Closes https://github.com/astral-sh/ty/issues/314
2025-05-12 13:48:54 -04:00
Charlie Marsh
3ccc0edfe4 Add comma to panic message (#18048)
## Summary

Consistent with other variants of this, separate the conditional clause.
2025-05-12 11:52:55 -04:00
Victor Hugo Gomes
6b3ff6f5b8 [flake8-pie] Mark autofix for PIE804 as unsafe if the dictionary contains comments (#18046)
## Summary

Fixes #18036
2025-05-12 10:16:59 -05:00
Shunsuke Shibayama
6f8f7506b4 [ty] fix infinite recursion bug in is_disjoint_from (#18043)
## Summary

I found this bug while working on #18041. The following code leads to
infinite recursion.

```python
from ty_extensions import is_disjoint_from, static_assert, TypeOf

class C:
    @property
    def prop(self) -> int:
        return 1

static_assert(not is_disjoint_from(int, TypeOf[C.prop]))
```

The cause is a trivial missing binding in `is_disjoint_from`. This PR
fixes the bug and adds a test case (this is a simple fix and may not
require a new test case?).

## Test Plan

A new test case is added to
`mdtest/type_properties/is_disjoint_from.md`.
2025-05-12 09:44:00 -04:00
Micha Reiser
797eb70904 disable jemalloc on android (#18033) 2025-05-12 14:41:00 +02:00
Micha Reiser
be6ec613db [ty] Fix incorrect type of src.root in documentation (#18040) 2025-05-12 12:28:14 +00:00
Micha Reiser
fcd858e0c8 [ty] Refine message for why a rule is enabled (#18038) 2025-05-12 13:31:42 +02:00
Micha Reiser
d944a1397e [ty] Remove brackets around option names (#18037) 2025-05-12 11:16:03 +00:00
renovate[bot]
d3f3d92df3 Update pre-commit dependencies (#18025)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:31:23 +02:00
renovate[bot]
38c00dfad5 Update docker/build-push-action action to v6.16.0 (#18030)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:26:41 +02:00
renovate[bot]
d6280c5aea Update docker/login-action action to v3.4.0 (#18031)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:26:22 +02:00
renovate[bot]
a34240a3f0 Update taiki-e/install-action digest to 83254c5 (#18022)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:26:03 +02:00
renovate[bot]
b86c7bbf7c Update cargo-bins/cargo-binstall action to v1.12.4 (#18023)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:25:28 +02:00
renovate[bot]
d7c54ba8c4 Update Rust crate ctrlc to v3.4.7 (#18027)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:25:08 +02:00
renovate[bot]
c38d6e8045 Update Rust crate clap to v4.5.38 (#18026)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:24:40 +02:00
renovate[bot]
2bfd7b1816 Update Rust crate jiff to v0.2.13 (#18029)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:24:16 +02:00
renovate[bot]
c1cfb43bf0 Update Rust crate getrandom to v0.3.3 (#18028)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 08:23:49 +02:00
renovate[bot]
99555b775c Update dependency ruff to v0.11.9 (#18024)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-11 22:03:55 -04:00
Yunchi Pang
b398b83631 [pylint] add fix safety section (PLW1514) (#17932)
parent #15584 
fix was made unsafe at #8928
2025-05-11 12:25:07 -05:00
Rogdham
bc7b30364d python_stdlib: update for 3.14 (#18014)
## Summary

Added version 3.14 to the script generating the `known_stdlib.rs` file.

Rebuilt the known stdlibs with latest version (2025.5.10) of [stdlibs
Python lib](https://pypi.org/project/stdlibs/) (which added support for
3.14.0b1).

_Note: Python 3.14 is now in [feature
freeze](https://peps.python.org/pep-0745/) so the modules in stdlib
should be stable._

_See also: #15506_

## Test Plan

The following command has been run. Using for tests the `compression`
module which been introduced with Python 3.14.
```sh
ruff check --no-cache --select I001 --target-version py314 --fix
```

With ruff 0.11.9:
```python
import base64
import datetime

import compression

print(base64, compression, datetime)
```

With this PR:
```python
import base64
import compression
import datetime   

print(base64, compression, datetime)
```
2025-05-11 11:25:54 -05:00
Vasco Schiavo
5792ed15da [ruff] add fix safety section (RUF033) (#17760)
This PR adds the fix safety section for rule `RUF033`
(https://github.com/astral-sh/ruff/issues/15584 ).
2025-05-11 11:15:15 -05:00
Yunchi Pang
8845a13efb [pylint] add fix safety section (PLC0414) (#17802)
This PR adds a fix safety section in comment for rule `PLC0414`.

parent: #15584 
discussion: #6294
2025-05-11 11:01:26 -05:00
Alex Waygood
669855d2b5 [ty] Remove unused variants from various Known* enums (#18015)
## Summary

`KnownClass::Range`, `KnownInstanceType::Any` and `ClassBase::any()` are
no longer used or useful: all our tests pass with them removed.
`KnownModule::Abc` _is_ now used outside of tests, however, so I removed
the `#[allow(dead_code)]` branch above that variant.

## Test Plan

`cargo test -p ty_python_semantic`
2025-05-11 11:18:55 +01:00
Alex Waygood
ff7ebecf89 [ty] Remove generic types from the daily property test run (for now) (#18004) 2025-05-11 09:27:27 +00:00
Zanie Blue
7e8ba2b68e [ty] Remove vestigial pyvenv.cfg creation in mdtest (#18006)
Following #17991, removes some of
https://github.com/astral-sh/ruff/pull/17222 which is no longer strictly
necessary. I don't actually think it's that ugly to have around? no
strong feelings on retaining it or not.
2025-05-10 20:52:49 +00:00
Zanie Blue
0bb8cbdf07 [ty] Do not allow invalid virtual environments from discovered .venv or VIRTUAL_ENV (#18003)
Follow-up to https://github.com/astral-sh/ruff/pull/17991 ensuring we do
not allow detection of system environments when the origin is
`VIRTUAL_ENV` or a discovered `.venv` directory — i.e., those always
require a `pyvenv.cfg` file.
2025-05-10 20:36:12 +00:00
Zanie Blue
2923c55698 [ty] Add test coverage for PythonEnvironment::System variants (#17996)
Adds test coverage for https://github.com/astral-sh/ruff/pull/17991,
which includes some minor refactoring of the virtual environment test
infrastructure.

I tried to minimize stylistic changes, but there are still a few because
I was a little confused by the setup. I could see this evolving more in
the future, as I don't think the existing model can capture all the test
coverage I'm looking for.
2025-05-10 20:28:15 +00:00
Zanie Blue
316e406ca4 [ty] Add basic support for non-virtual Python environments (#17991)
This adds basic support for non-virtual Python environments by accepting
a directory without a `pyvenv.cfg` which allows existing, subsequent
site-packages discovery logic to succeed. We can do better here in the
long-term, by adding more eager validation (for error messages) and
parsing the Python version from the discovered site-packages directory
(which isn't relevant yet, because we don't use the discovered Python
version from virtual environments as the default `--python-version` yet
either).

Related

- https://github.com/astral-sh/ty/issues/265
- https://github.com/astral-sh/ty/issues/193

You can review this commit by commit if it makes you happy.

I tested this manually; I think refactoring the test setup is going to
be a bit more invasive so I'll stack it on top (see
https://github.com/astral-sh/ruff/pull/17996).

```
❯ uv run ty check --python /Users/zb/.local/share/uv/python/cpython-3.10.17-macos-aarch64-none/ -vv example
2025-05-09 12:06:33.685911 DEBUG Version: 0.0.0-alpha.7 (f9c4c8999 2025-05-08)
2025-05-09 12:06:33.685987 DEBUG Architecture: aarch64, OS: macos, case-sensitive: case-insensitive
2025-05-09 12:06:33.686002 DEBUG Searching for a project in '/Users/zb/workspace/ty'
2025-05-09 12:06:33.686123 DEBUG Resolving requires-python constraint: `>=3.8`
2025-05-09 12:06:33.686129 DEBUG Resolved requires-python constraint to: 3.8
2025-05-09 12:06:33.686142 DEBUG Project without `tool.ty` section: '/Users/zb/workspace/ty'
2025-05-09 12:06:33.686147 DEBUG Searching for a user-level configuration at `/Users/zb/.config/ty/ty.toml`
2025-05-09 12:06:33.686156 INFO Defaulting to python-platform `darwin`
2025-05-09 12:06:33.68636 INFO Python version: Python 3.8, platform: darwin
2025-05-09 12:06:33.686375 DEBUG Adding first-party search path '/Users/zb/workspace/ty'
2025-05-09 12:06:33.68638 DEBUG Using vendored stdlib
2025-05-09 12:06:33.686634 DEBUG Discovering site-packages paths from sys-prefix `/Users/zb/.local/share/uv/python/cpython-3.10.17-macos-aarch64-none` (`--python` argument')
2025-05-09 12:06:33.686667 DEBUG Attempting to parse virtual environment metadata at '/Users/zb/.local/share/uv/python/cpython-3.10.17-macos-aarch64-none/pyvenv.cfg'
2025-05-09 12:06:33.686671 DEBUG Searching for site-packages directory in `sys.prefix` path `/Users/zb/.local/share/uv/python/cpython-3.10.17-macos-aarch64-none`
2025-05-09 12:06:33.686702 DEBUG Resolved site-packages directories for this environment are: ["/Users/zb/.local/share/uv/python/cpython-3.10.17-macos-aarch64-none/lib/python3.10/site-packages"]
2025-05-09 12:06:33.686706 DEBUG Adding site-packages search path '/Users/zb/.local/share/uv/python/cpython-3.10.17-macos-aarch64-none/lib/python3.10/site-packages'
...

❯ uv run ty check --python /tmp -vv example
2025-05-09 15:36:10.819416 DEBUG Version: 0.0.0-alpha.7 (f9c4c8999 2025-05-08)
2025-05-09 15:36:10.819708 DEBUG Architecture: aarch64, OS: macos, case-sensitive: case-insensitive
2025-05-09 15:36:10.820118 DEBUG Searching for a project in '/Users/zb/workspace/ty'
2025-05-09 15:36:10.821652 DEBUG Resolving requires-python constraint: `>=3.8`
2025-05-09 15:36:10.821667 DEBUG Resolved requires-python constraint to: 3.8
2025-05-09 15:36:10.8217 DEBUG Project without `tool.ty` section: '/Users/zb/workspace/ty'
2025-05-09 15:36:10.821888 DEBUG Searching for a user-level configuration at `/Users/zb/.config/ty/ty.toml`
2025-05-09 15:36:10.822072 INFO Defaulting to python-platform `darwin`
2025-05-09 15:36:10.822439 INFO Python version: Python 3.8, platform: darwin
2025-05-09 15:36:10.822773 DEBUG Adding first-party search path '/Users/zb/workspace/ty'
2025-05-09 15:36:10.822929 DEBUG Using vendored stdlib
2025-05-09 15:36:10.829872 DEBUG Discovering site-packages paths from sys-prefix `/tmp` (`--python` argument')
2025-05-09 15:36:10.829911 DEBUG Attempting to parse virtual environment metadata at '/private/tmp/pyvenv.cfg'
2025-05-09 15:36:10.829917 DEBUG Searching for site-packages directory in `sys.prefix` path `/private/tmp`
ty failed
  Cause: Invalid search path settings
  Cause: Failed to discover the site-packages directory: Failed to search the `lib` directory of the Python installation at `sys.prefix` path `/private/tmp` for `site-packages`
```
2025-05-10 20:17:47 +00:00
Micha Reiser
5ecd560c6f Link to the rules.md in the ty repository (#17979) 2025-05-10 11:40:40 +01:00
Max Mynter
b765dc48e9 Skip S608 for expressionless f-strings (#17999) 2025-05-10 11:37:58 +01:00
David Peter
cd1d906ffa [ty] Silence false positives for PEP-695 ParamSpec annotations (#18001)
## Summary

Suppress false positives for uses of PEP-695 `ParamSpec` in `Callable`
annotations:
```py
from typing_extensions import Callable

def f[**P](c: Callable[P, int]):
    pass
```

addresses a comment here:
https://github.com/astral-sh/ty/issues/157#issuecomment-2859284721

## Test Plan

Adapted Markdown tests
2025-05-10 11:59:25 +02:00
Abhijeet Prasad Bodas
235b74a310 [ty] Add more tests for NamedTuples (#17975)
## Summary

Add more tests and TODOs for `NamedTuple` support, based on the typing
spec: https://typing.python.org/en/latest/spec/namedtuples.html

## Test Plan

This PR adds new tests.
2025-05-10 10:46:08 +02:00
Brent Westbrook
40fd52dde0 Exclude broken symlinks from meson-python ecosystem check (#17993)
Summary
--

This should resolve the formatter ecosystem errors we've been seeing
lately. https://github.com/mesonbuild/meson-python/pull/728 added the
links, which I think are intentionally broken for testing purposes.

Test Plan
--

Ecosystem check on this PR
2025-05-09 16:59:00 -04:00
Carl Meyer
fd1eb3d801 add test for typing_extensions.Self (#17995)
Using `typing_extensions.Self` already worked, but we were lacking a
test for it.
2025-05-09 20:29:13 +00:00
omahs
882a1a702e Fix typos (#17988)
Fix typos

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-05-09 14:57:14 -04:00
Max Mynter
b4a1ebdfe3 [semantic-syntax-tests] IrrefutableCasePattern, SingleStarredAssignment, WriteToDebug, InvalidExpression (#17748)
Re: #17526 

## Summary

Add integration test for semantic syntax for `IrrefutableCasePattern`,
`SingleStarredAssignment`, `WriteToDebug`, and `InvalidExpression`.

## Notes
- Following @ntBre's suggestion, I will keep the test coming in batches
like this over the next few days in separate PRs to keep the review load
per PR manageable while also not spamming too many.

- I did not add a test for `del __debug__` which is one of the examples
in `crates/ruff_python_parser/src/semantic_errors.rs:1051`.
For python version `<= 3.8` there is no error and for `>=3.9` the error
is not `WriteToDebug` but `SyntaxError: cannot delete __debug__ on
Python 3.9 (syntax was removed in 3.9)`.

- The `blacken-docs` bypass is necessary because otherwise the test does
not pass pre-commit checks; but we want to check for this faulty syntax.

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

## Test Plan
This is a test.
2025-05-09 14:54:05 -04:00
Brent Westbrook
7a48477c67 [ty] Add a warning about pre-release status to the CLI (#17983)
Summary
--

This was suggested on Discord, I hope this is roughly what we had in
mind. I took the message from the ty README, but I'm more than happy to
update it. Otherwise I just tried to mimic the appearance of the `ruff
analyze graph` warning (although I'm realizing now the whole text is
bold for ruff).

Test Plan
--

New warnings in the CLI tests. I thought this might be undesirable but
it looks like uv did the same thing
(https://github.com/astral-sh/uv/pull/6166).


![image](https://github.com/user-attachments/assets/e5e56a49-02ab-4c5f-9c38-716e4008d6e6)
2025-05-09 13:42:36 -04:00
Andrew Gallant
346e82b572 ty_python_semantic: add union type context to function call type errors
This context gets added only when calling a function through a union
type.
2025-05-09 13:40:51 -04:00
Andrew Gallant
5ea3a52c8a ty_python_semantic: report all union diagnostic
This makes one very simple change: we report all call binding
errors from each union variant.

This does result in duplicate-seeming diagnostics. For example,
when two union variants are invalid for the same reason.
2025-05-09 13:40:51 -04:00
Andrew Gallant
90272ad85a ty_python_semantic: add snapshot tests for existing union function type diagnostics
This is just capturing the status quo so that we can better see the
changes. I took these tests from the (now defunct) PR #17959.
2025-05-09 13:40:51 -04:00
Ibraheem Ahmed
e9da1750a1 Add progress bar for ty check (#17965)
## Summary

Adds a simple progress bar for the `ty check` CLI command. The style is
taken from uv, and like uv the bar is always shown - for smaller
projects it is fast enough that it isn't noticeable. We could
alternatively hide it completely based on some heuristic for the number
of files, or only show it after some amount of time.

I also disabled it when `--watch` is passed, cancelling inflight checks
was leading to zombie progress bars. I think we can fix this by using
[`MultiProgress`](https://docs.rs/indicatif/latest/indicatif/struct.MultiProgress.html)
and managing all the bars globally, but I left that out for now.

Resolves https://github.com/astral-sh/ty/issues/98.
2025-05-09 13:32:27 -04:00
Wei Lee
25e13debc0 [airflow] extend AIR311 rules (#17913)
<!--
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? -->

* `airflow.models.Connection` → `airflow.sdk.Connection`
* `airflow.models.Variable` → `airflow.sdk.Variable`

## Test Plan

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

The test fixtures has been updated (see the first commit for easier
review)
2025-05-09 13:08:37 -04:00
InSync
249a852a6e [ty] Document nearly all lints (#17981) 2025-05-09 18:06:56 +01:00
Andrew Gallant
861ef2504e ty: add more snapshot updates 2025-05-09 12:42:14 -04:00
Andrew Gallant
b71ef8a26e ruff_db: completely rip lint: prefix out
This does a deeper removal of the `lint:` prefix by removing the
`DiagnosticId::as_str` method and replacing it with `as_concise_str`. We
remove the associated error type and simplify the `Display` impl for
`DiagnosticId` as well.

This turned out to catch a `lint:` that was still in the diagnostic
output: the part that says why a lint is enabled.
2025-05-09 12:42:14 -04:00
Andrew Gallant
50c780fc8b ty: switch to use annotate-snippets ID functionality
We just set the ID on the `Message` and it just does what we want in
this case. I think I didn't do this originally because I was trying to
preserve the existing rendering? I'm not sure. I might have just missed
this method.
2025-05-09 12:42:14 -04:00
Andrew Gallant
244ea27d5f ruff_db: a small tweak to remove empty message case
In a subsequent commit, we're going to start using `annotate-snippets`'s
functionality for diagnostic IDs in the rendering. As part of doing
that, I wanted to remove this special casing of an empty message. I did
that independently to see what, if anything, would change. (The changes
look fine to me. They'll be tweaked again in the next commit along with
a bunch of others.)
2025-05-09 12:42:14 -04:00
Andrew Gallant
2c4cbb6e29 ty: get rid of lint: prefix in ID for diagnostic rendering
In #289, we seem to have consensus that this prefix isn't really pulling
its weight.

Ref #289
2025-05-09 12:42:14 -04:00
Alex Waygood
d1bb10a66b [ty] Understand classes that inherit from subscripted Protocol[] as generic (#17832) 2025-05-09 17:39:15 +01:00
Dylan
2370297cde Bump 0.11.9 (#17986) 2025-05-09 10:43:27 -05:00
Alex Waygood
a137cb18d4 [ty] Display "All checks passed!" message in green (#17982) 2025-05-09 14:29:43 +01:00
Alex Waygood
03a4d56624 [ty] Change range of revealed-type diagnostic to be the range of the argument passed in, not the whole call (#17980) 2025-05-09 14:15:39 +01:00
David Peter
642eac452d [ty] Recursive protocols (#17929)
## Summary

Use a self-reference "marker" ~~and fixpoint iteration~~ to solve the
stack overflow problems with recursive protocols. This is not pretty and
somewhat tedious, but seems to work fine. Much better than all my
fixpoint-iteration attempts anyway.

closes https://github.com/astral-sh/ty/issues/93

## Test Plan

New Markdown tests.
2025-05-09 14:54:02 +02:00
Micha Reiser
c1b875799b [ty] CLI reference (#17978) 2025-05-09 14:23:24 +02:00
Micha Reiser
6cd8a49638 [ty] Update salsa (#17964) 2025-05-09 11:54:07 +02:00
Micha Reiser
12ce445ff7 [ty] Document configuration schema (#17950) 2025-05-09 10:47:45 +02:00
justin
f46ed8d410 [ty] Add --config CLI arg (#17697) 2025-05-09 08:38:37 +02:00
Carl Meyer
6c177e2bbe [ty] primer updates (#17903)
## Summary

Update ecosystem project lists in light of
https://github.com/astral-sh/ruff/pull/17758

## Test Plan

CI on this PR.
2025-05-08 20:43:31 -07:00
Carl Meyer
3d2485eb1b [ty] fix more ecosystem/fuzzer panics with fixpoint (#17758)
## Summary

Add cycle handling for `try_metaclass` and `pep695_generic_context`
queries, as well as adjusting the cycle handling for `try_mro` to ensure
that it short-circuits on cycles and won't grow MROs indefinitely.

This reduces the number of failing fuzzer seeds from 68 to 17. The
latter count includes fuzzer seeds 120, 160, and 335, all of which
previously panicked but now either hang or are very slow; I've
temporarily skipped those seeds in the fuzzer until I can dig into that
slowness further.

This also allows us to move some more ecosystem projects from `bad.txt`
to `good.txt`, which I've done in
https://github.com/astral-sh/ruff/pull/17903

## Test Plan

Added mdtests.
2025-05-08 20:36:20 -07:00
Douglas Creager
f78367979e [ty] Remove SliceLiteral type variant (#17958)
@AlexWaygood pointed out that the `SliceLiteral` type variant was
originally created to handle slices before we had generics.
https://github.com/astral-sh/ruff/pull/17927#discussion_r2078115787

Now that we _do_ have generics, we can use a specialization of the
`slice` builtin type for slice literals.

This depends on https://github.com/astral-sh/ruff/pull/17956, since we
need to make sure that all typevar defaults are fully substituted when
specializing `slice`.
2025-05-08 20:16:41 -04:00
Douglas Creager
b705664d49 [ty] Handle typevars that have other typevars as a default (#17956)
It's possible for a typevar to list another typevar as its default
value:

```py
class C[T, U = T]: ...
```

When specializing this class, if a type isn't provided for `U`, we would
previously use the default as-is, leaving an unspecialized `T` typevar
in the specialization. Instead, we want to use what `T` is mapped to as
the type of `U`.

```py
reveal_type(C())  # revealed: C[Unknown, Unknown]
reveal_type(C[int]())  # revealed: C[int, int]
reveal_type(C[int, str]())  # revealed: C[int, str]
```

This is especially important for the `slice` built-in type.
2025-05-08 19:01:27 -04:00
Alex Waygood
f51f1f7153 [ty] Support extending __all__ from an imported module even when the module is not an ExprName node (#17947) 2025-05-08 23:54:19 +01:00
Alex Waygood
9b694ada82 [ty] Report duplicate Protocol or Generic base classes with [duplicate-base], not [inconsistent-mro] (#17971) 2025-05-08 23:41:22 +01:00
Alex Waygood
4d81a41107 [ty] Respect the gradual guarantee when reporting errors in resolving MROs (#17962) 2025-05-08 22:57:39 +01:00
Brent Westbrook
981bd70d39 Convert Message::SyntaxError to use Diagnostic internally (#17784)
## Summary

This PR is a first step toward integration of the new `Diagnostic` type
into ruff. There are two main changes:
- A new `UnifiedFile` enum wrapping `File` for red-knot and a
`SourceFile` for ruff
- ruff's `Message::SyntaxError` variant is now a `Diagnostic` instead of
a `SyntaxErrorMessage`

The second of these changes was mostly just a proof of concept for the
first, and it went pretty smoothly. Converting `DiagnosticMessage`s will
be most of the work in replacing `Message` entirely.

## Test Plan

Existing tests, which show no changes.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-08 12:45:51 -04:00
Alex Waygood
0763331f7f [ty] Support extending __all__ with a literal tuple or set as well as a literal list (#17948) 2025-05-08 17:37:25 +01:00
Alex Waygood
da8540862d [ty] Make unused-ignore-comment disabled by default for now (#17955) 2025-05-08 17:21:34 +01:00
Micha Reiser
6a5533c44c [ty] Change default severity for unbound-reference to error (#17936) 2025-05-08 17:54:46 +02:00
Micha Reiser
d608eae126 [ty] Ignore possibly-unresolved-reference by default (#17934) 2025-05-08 17:44:56 +02:00
Micha Reiser
067a8ac574 [ty] Default to latest supported python version (#17938) 2025-05-08 16:58:35 +02:00
Micha Reiser
5eb215e8e5 [ty] Generate and add rules table (#17953) 2025-05-08 16:55:39 +02:00
Zanie Blue
91aa853b9c Update the schemastore script to match changes in ty (#17952)
See https://github.com/astral-sh/ty/pull/273
2025-05-08 09:31:52 -05:00
Brent Westbrook
57bf7dfbd9 [ty] Implement global handling and load-before-global-declaration syntax error (#17637)
Summary
--

This PR resolves both the typing-related and syntax error TODOs added in
#17563 by tracking a set of `global` bindings for each scope. As
discussed below, we avoid the additional AST traversal from ruff by
collecting `Name`s from `global` statements while building the semantic
index and emit a syntax error if the `Name` is already bound in the
current scope at the point of the `global` statement. This has the
downside of separating the error from the `SemanticSyntaxChecker`, but I
plan to explore using this approach in the `SemanticSyntaxChecker`
itself as a follow-up. It seems like this may be a better approach for
ruff as well.

Test Plan
--

Updated all of the related mdtests to remove the TODOs (and add quotes I
forgot on the messages).

There is one remaining TODO, but it requires `nonlocal` support, which
isn't even incorporated into the `SemanticSyntaxChecker` yet.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-08 10:30:04 -04:00
Alex Waygood
67cd94ed64 [ty] Add missing bitwise-operator branches for boolean and integer arithmetic (#17949) 2025-05-08 14:10:35 +01:00
Wei Lee
aac862822f [airflow] Fix SQLTableCheckOperator typo (AIR302) (#17946) 2025-05-08 14:34:55 +02:00
Micha Reiser
3755ac9fac Update ty metadata (#17943) 2025-05-08 13:24:31 +02:00
David Peter
4f890b2867 [ty] Update salsa (#17937)
## Summary

* Update salsa to pull in https://github.com/salsa-rs/salsa/pull/850.
* Some refactoring of salsa event callbacks in various `Db`'s due to
https://github.com/salsa-rs/salsa/pull/849

closes https://github.com/astral-sh/ty/issues/108

## Test Plan

Ran `cargo run --bin ty -- -vvv` on a test file to make sure that salsa
Events are still logged.
2025-05-08 12:02:53 +02:00
Shaygan Hooshyari
d566636ca5 Support typing.Self in methods (#17689)
## Summary

Fixes: astral-sh/ty#159 

This PR adds support for using `Self` in methods.
When the type of an annotation is `TypingSelf` it is converted to a type
var based on:
https://typing.python.org/en/latest/spec/generics.html#self

I just skipped Protocols because it had more problems and the tests was
not useful.
Also I need to create a follow up PR that implicitly assumes `self`
argument has type `Self`.

In order to infer the type in the `in_type_expression` method I needed
to have scope id and semantic index available. I used the idea from
[this PR](https://github.com/astral-sh/ruff/pull/17589/files) to pass
additional context to this method.
Also I think in all places that `in_type_expression` is called we need
to have this context because `Self` can be there so I didn't split the
method into one version with context and one without.

## Test Plan

Added new tests from spec.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-07 15:58:00 -07:00
Alex Waygood
51cef5a72b [ty] Recognise functions containing yield from expressions as being generator functions (#17930) 2025-05-07 23:29:44 +01:00
Douglas Creager
2cf5cba7ff [ty] Check base classes when determining subtyping etc for generic aliases (#17927)
#17897 added variance handling for legacy typevars — but they were only
being considered when checking generic aliases of the same class:

```py
class A: ...
class B(A): ...

class C[T]: ...

static_assert(is_subtype_of(C[B], C[A]))
```

and not for generic subclasses:

```py
class D[U](C[U]): ...

static_assert(is_subtype_of(D[B], C[A]))
```

Now we check those too!

Closes https://github.com/astral-sh/ty/issues/101
2025-05-07 15:21:11 -04:00
yunchi
ce0800fccf [pylint] add fix safety section (PLC2801) (#17825)
parent: #15584 
fix was introduced at: #9587 
reasoning: #9572
2025-05-07 14:34:34 -04:00
Micha Reiser
d03a7069ad Add instructions on how to upgrade to a newer Rust version (#17928) 2025-05-07 20:11:58 +02:00
Abhijeet Prasad Bodas
f5096f2050 [parser] Flag single unparenthesized generator expr with trailing comma in arguments. (#17893)
Fixes #17867

## Summary

The CPython parser does not allow generator expressions which are the
sole arguments in an argument list to have a trailing comma.
With this change, we start flagging such instances.

## Test Plan

Added new inline tests.
2025-05-07 14:11:35 -04:00
Alex Waygood
895b6161a6 [ty] Ensure that T is disjoint from ~T even when T is a TypeVar (#17922)
Same as https://github.com/astral-sh/ruff/pull/17910 but for
disjointness
2025-05-07 10:59:16 -07:00
Alex Waygood
74fe7982ba [ty] Sort collected diagnostics before snapshotting them in mdtest (#17926) 2025-05-07 18:23:22 +01:00
Micha Reiser
51386b3c7a [ty] Add basic file watching to server (#17912) 2025-05-07 19:03:30 +02:00
Charlie Marsh
51e2effd2d Make completions an opt-in LSP feature (#17921)
## Summary

We now expect the client to send initialization options to opt-in to
experimental (but LSP-standardized) features, like completion support.
Specifically, the client should set `"experimental.completions.enable":
true`.

Closes https://github.com/astral-sh/ty/issues/74.
2025-05-07 16:39:35 +00:00
Dhruv Manilawala
82d31a6014 Add link to ty issue tracker (#17924)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-07 16:33:27 +00:00
Dhruv Manilawala
78054824c0 [ty] Add support for __all__ (#17856)
## Summary

This PR adds support for the `__all__` module variable.

Reference spec:
https://typing.python.org/en/latest/spec/distributing.html#library-interface-public-and-private-symbols

This PR adds a new `dunder_all_names` query that returns a set of
`Name`s defined in the `__all__` variable of the given `File`. The query
works by implementing the `StatementVisitor` and collects all the names
by recognizing the supported idioms as mentioned in the spec. Any idiom
that's not recognized are ignored.

The current implementation is minimum to what's required for us to
remove all the false positives that this is causing. Refer to the
"Follow-ups" section below to see what we can do next. I'll a open
separate issue to keep track of them.

Closes: astral-sh/ty#106 
Closes: astral-sh/ty#199

### Follow-ups

* Diagnostics:
* Add warning diagnostics for unrecognized `__all__` idioms, `__all__`
containing non-string element
* Add an error diagnostic for elements that are present in `__all__` but
not defined in the module. This could lead to runtime error
* Maybe we should return `<type>` instead of `Unknown | <type>` for
`module.__all__`. For example:
https://playknot.ruff.rs/2a6fe5d7-4e16-45b1-8ec3-d79f2d4ca894
* Mark a symbol that's mentioned in `__all__` as used otherwise it could
raise (possibly in the future) "unused-name" diagnostic

Supporting diagnostics will require that we update the return type of
the query to be something other than `Option<FxHashSet<Name>>`,
something that behaves like a result and provides a way to check whether
a name exists in `__all__`, loop over elements in `__all__`, loop over
the invalid elements, etc.

## Ecosystem analysis

The following are the maximum amount of diagnostics **removed** in the
ecosystem:

* "Type <module '...'> has no attribute ..."
    * `collections.abc` - 14
    * `numpy` - 35534
    * `numpy.ma` - 296
    * `numpy.char` - 37
    * `numpy.testing` - 175
    * `hashlib` - 311
    * `scipy.fft` - 2
    * `scipy.stats` - 38
* "Module '...' has no member ..."
    * `collections.abc` - 85
    * `numpy` - 508
    * `numpy.testing` - 741
    * `hashlib` - 36
    * `scipy.stats` - 68
    * `scipy.interpolate` - 7
    * `scipy.signal` - 5

The following modules have dynamic `__all__` definition, so `ty` assumes
that `__all__` doesn't exists in that module:
* `scipy.stats`
(95a5d6ea8b/scipy/stats/__init__.py (L665))
* `scipy.interpolate`
(95a5d6ea8b/scipy/interpolate/__init__.py (L221))
* `scipy.signal` (indirectly via
95a5d6ea8b/scipy/signal/_signal_api.py (L30))
* `numpy.testing`
(de784cd6ee/numpy/testing/__init__.py (L16-L18))

~There's this one category of **false positives** that have been added:~
Fixed the false positives by also ignoring `__all__` from a module that
uses unrecognized idioms.

<details><summary>Details about the false postivie:</summary>
<p>

The `scipy.stats` module has dynamic `__all__` and it imports a bunch of
symbols via star imports. Some of those modules have a mix of valid and
invalid `__all__` idioms. For example, in
95a5d6ea8b/scipy/stats/distributions.py (L18-L24),
2 out of 4 `__all__` idioms are invalid but currently `ty` recognizes
two of them and says that the module has a `__all__` with 5 values. This
leads to around **2055** newly added false positives of the form:
```
Type <module 'scipy.stats'> has no attribute ...
```

I think the fix here is to completely ignore `__all__`, not only if
there are invalid elements in it, but also if there are unrecognized
idioms used in the module.

</p>
</details> 

## Test Plan

Add a bunch of test cases using the new `ty_extensions.dunder_all_names`
function to extract a module's `__all__` names.

Update various test cases to remove false positives around `*` imports
and re-export convention.

Add new test cases for named import behavior as `*` imports covers all
of it already (thanks Alex!).
2025-05-07 21:42:42 +05:30
Alex Waygood
c6f4929cdc [ty] fix assigning a typevar to a union with itself (#17910)
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-07 15:50:22 +00:00
Alex Waygood
2ec0d7e072 [ty] Improve UX for [duplicate-base] diagnostics (#17914) 2025-05-07 15:27:37 +00:00
Charlie Marsh
ad658f4d68 Clean up some Ruff references in the ty server (#17920)
## Summary

Anything user-facing, etc.
2025-05-07 10:55:16 -04:00
Abhijeet Prasad Bodas
3dedd70a92 [ty] Detect overloads decorated with @dataclass_transform (#17835)
## Summary

Fixes #17541

Before this change, in the case of overloaded functions,
`@dataclass_transform` was detected only when applied to the
implementation, not the overloads.
However, the spec also allows this decorator to be applied to any of the
overloads as well.
With this PR, we start handling `@dataclass_transform`s applied to
overloads.

## Test Plan

Fixed existing TODOs in the test suite.
2025-05-07 15:51:13 +02:00
David Peter
fab862c8cd [ty] Ecosystem checks: activate running on 'manticore' (#17916)
## Summary

This is sort of an anticlimactic resolution to #17863, but now that we
understand what the root cause for the stack overflows was, I think it's
fine to enable running on this project. See the linked ticket for the
full analysis.

closes #17863

## Test Plan

Ran lots of times locally and never observed a crash at worker thread
stack sizes > 8 MiB.
2025-05-07 06:27:36 -07:00
Douglas Creager
0d9b6a0975 [ty] Handle explicit variance in legacy typevars (#17897)
We now track the variance of each typevar, and obey the `covariant` and
`contravariant` parameters to the legacy `TypeVar` constructor. We still
don't yet infer variance for PEP-695 typevars or for the
`infer_variance` legacy constructor parameter.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-07 08:44:51 -04:00
Micha Reiser
c5e299e796 Update salsa (#17895) 2025-05-07 09:51:15 +02:00
Victor Hugo Gomes
c504001b32 [pyupgrade] Add spaces between tokens as necessary to avoid syntax errors in UP018 autofix (#17648)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-07 09:34:08 +02:00
David Peter
04457f99b6 [ty] Protocols: Fixpoint iteration for fully-static check (#17880)
## Summary

A recursive protocol like the following would previously lead to stack
overflows when attempting to create the union type for the `P | None`
member, because `UnionBuilder` checks if element types are fully static,
and the fully-static check on `P` would in turn list all members and
check whether all of them were fully static, leading to a cycle.

```py
from __future__ import annotations

from typing import Protocol

class P(Protocol):
    parent: P | None
```

Here, we make the fully-static check on protocols a salsa query and add
fixpoint iteration, starting with `true` as the initial value (assume
that the recursive protocol is fully-static). If the recursive protocol
has any non-fully-static members, we still return `false` when
re-executing the query (see newly added tests).

closes #17861

## Test Plan

Added regression test
2025-05-07 08:55:21 +02:00
InSync
a33d0d4bf4 [ty] Support generate-shell-completion (#17879)
## Summary

Resolves #15502.

`ty generate-shell-completion` now works in a similar manner to `ruff
generate-shell-completion`.

## Test Plan

Manually:

<details>

```shell
$ cargo run --package ty generate-shell-completion nushell
module completions {

  # An extremely fast Python type checker.
  export extern ty [
    --help(-h)                # Print help
    --version(-V)             # Print version
  ]
  
  # ...

}

export use completions *
```
</details>
2025-05-06 18:04:57 -07:00
Charlie Marsh
443f62e98d Remove condensed display type enum (#17902)
## Summary

See: https://github.com/astral-sh/ruff/pull/17889#discussion_r2076556002
2025-05-06 18:04:03 -07:00
Charlie Marsh
a2e9a7732a Update class literal display to use <class 'Foo'> style (#17889)
## Summary

Closes https://github.com/astral-sh/ruff/issues/17238.
2025-05-06 20:11:25 -04:00
Micha Reiser
b2de749c32 Add a note to diagnostics why the rule is enabled (#17854) 2025-05-06 20:29:03 +02:00
Douglas Creager
9085f18353 [ty] Propagate specializations to ancestor base classes (#17892)
@AlexWaygood discovered that even though we've been propagating
specializations to _parent_ base classes correctly, we haven't been
passing them on to _grandparent_ base classes:
https://github.com/astral-sh/ruff/pull/17832#issuecomment-2854360969

```py
class Bar[T]:
    x: T

class Baz[T](Bar[T]): ...
class Spam[T](Baz[T]): ...

reveal_type(Spam[int]().x) # revealed: `T`, but should be `int`
```

This PR updates the MRO machinery to apply the current specialization
when starting to iterate the MRO of each base class.
2025-05-06 14:25:21 -04:00
Dylan
8152ba7cb7 [ty] Add minimal docs for a few lints (#17874)
Just the bare minimum to remove a few TODOs - omitted examples, and only
did 9 but I will check back tomorrow and try to knock out a few more!
2025-05-06 10:36:47 -07:00
Aria Desires
3d01d3be3e update the repository for ty (#17891)
This metadata is used by cargo-dist for artifact URLs (in curl-sh
expressions)
2025-05-06 12:03:38 -04:00
Brent Westbrook
4510a236d3 Default to latest supported Python version for version-related syntax errors (#17529)
## Summary

This PR partially addresses #16418 via the following:

- `LinterSettings::unresolved_python_version` is now a `TargetVersion`,
which is a thin wrapper around an `Option<PythonVersion>`
- `Checker::target_version` now calls `TargetVersion::linter_version`
internally, which in turn uses `unwrap_or_default` to preserve the
current default behavior
- Calls to the parser now call `TargetVersion::parser_version`, which
calls `unwrap_or_else(PythonVersion::latest)`
- The `Checker`'s implementation of
`SemanticSyntaxContext::python_version` also uses
`TargetVersion::parser_version` to use `PythonVersion::latest` for
semantic errors

In short, all lint rule behavior should be unchanged, but we default to
the latest Python version for the new syntax errors, which should
minimize confusing version-related syntax errors for users without a
version configured.

## Test Plan

Existing tests, which showed no changes (except for printing default
settings).
2025-05-06 10:19:13 -04:00
Marcus Näslund
76b6d53d8b Add new rule InEmptyCollection (#16480)
## Summary

Introducing a new rule based on discussions in #15732 and #15729 that
checks for unnecessary in with empty collections.

I called it in_empty_collection and gave the rule number RUF060.

Rule is in preview group.
2025-05-06 13:52:07 +00:00
Zanie Blue
f82b72882b Display ty version for ty --version and ty -V (#17888)
e.g.,

```
❯ uv run -q -- ty -V
ty 0.0.0-alpha.4 (08881edba 2025-05-05)
❯ uv run -q -- ty --version
ty 0.0.0-alpha.4 (08881edba 2025-05-05)
```

Previously, this just displayed `ty 0.0.0` because it didn't use our
custom version implementation. We no longer have a short version —
matching the interface in uv. We could add a variant for it, if it seems
important to people. However, I think we found it more confusing than
not over there and didn't get any complaints about the change.

Closes https://github.com/astral-sh/ty/issues/54
2025-05-06 08:06:41 -05:00
Zanie Blue
d07eefc408 Parse dist-workspace.toml for version (#17868)
Extends https://github.com/astral-sh/ruff/pull/17866, using
`dist-workspace.toml` as a source of truth for versions to enable
version retrieval in distributions that are not Git repositories (i.e.,
Python source distributions and source tarballs consumed by Linux
distros).

I retain the Git tag lookup from
https://github.com/astral-sh/ruff/pull/17866 as a fallback — it seems
harmless, but we could drop it to simplify things here.

I confirmed this works from the repository as well as Python source and
binary distributions:

```
❯ uv run --refresh-package ty --reinstall-package ty -q --  ty version
ty 0.0.1-alpha.1+5 (2eadc9e61 2025-05-05)
❯ uv build
...
❯ uvx --from ty@dist/ty-0.0.0a1.tar.gz --no-cache -q -- ty version
ty 0.0.1-alpha.1
❯ uvx --from ty@dist/ty-0.0.0a1-py3-none-macosx_11_0_arm64.whl -q -- ty version
ty 0.0.1-alpha.1
```

Requires https://github.com/astral-sh/ty/pull/36

cc @Gankra and @MichaReiser for review.
2025-05-06 12:18:17 +00:00
Zanie Blue
f7237e3b69 Update ty version to use parent Git repository information (#17866)
Currently, `ty version` pulls its information from the Ruff repository —
but we want this to pull from the repository in the directory _above_
when Ruff is a submodule.

I tested this in the `ty` repository after tagging an arbitrary commit:

```
❯ uv run --refresh-package ty --reinstall-package ty ty version
      Built ty @ file:///Users/zb/workspace/ty
Uninstalled 1 package in 2ms
Installed 1 package in 1ms
ty 0.0.0+3 (34253b1d4 2025-05-05)
```

We also use the last Git tag as the source of truth for the version,
instead of the crate version. However, we'll need a way to set the
version for releases still, as the tag is published _after_ the build.
We can either tag early (without pushing the tag to the remote), or add
another environment variable. (**Note, this approach is changed in a
follow-up. See https://github.com/astral-sh/ruff/pull/17868**)

From this repository, the version will be `unknown`:

```
❯ cargo run -q --bin ty -- version
ty unknown
```

We could add special handling like... `ty unknown (ruff@...)` but I see
that as a secondary goal.

Closes https://github.com/astral-sh/ty/issues/5

The reviewer situation in this repository is unhinged, cc @Gankra and
@MichaReiser for review.
2025-05-06 07:14:30 -05:00
Alex Waygood
2f9992b6ef [ty] Fix duplicate diagnostics for unresolved module when an import from statement imports multiple members (#17886) 2025-05-06 12:37:10 +01:00
Alex Waygood
457ec4dddd Generalize special-casing for enums constructed with the functional syntax (#17885) 2025-05-06 11:02:55 +01:00
Micha Reiser
aa0614509b Update salsa to pull in fixpoint fixes (#17847) 2025-05-06 11:27:51 +02:00
Micha Reiser
9000eb3bfd Update favicon and URL for playground (#17860) 2025-05-06 10:51:45 +02:00
Micha Reiser
7f50b503cf Allowlist play.ty.dev (#17857) 2025-05-06 10:16:17 +02:00
Micha Reiser
24d3fc27fb Fixup wording of fatal error warning (#17881) 2025-05-06 09:44:23 +02:00
Micha Reiser
6f821ac846 Show a warning at the end of the diagnostic list if there are any fatal warnings (#17855) 2025-05-06 07:14:21 +00:00
Charlie Marsh
d410d12bc5 Update code of conduct email address (#17875)
## Summary

For consistency with the `pyproject.toml`, etc.
2025-05-05 21:34:45 -04:00
Alex Waygood
89424cce5f [ty] Do not emit errors if enums or NamedTuples constructed using functional syntax are used in type expressions (#17873)
## Summary

This fixes some false positives that showed up in the primer diff for
https://github.com/astral-sh/ruff/pull/17832

## Test Plan

new mdtests added that fail with false-positive diagnostics on `main`
2025-05-06 00:37:24 +01:00
Shunsuke Shibayama
fd76d70a31 [red-knot] fix narrowing in nested scopes (#17630)
## Summary

This PR fixes #17595.

## Test Plan

New test cases are added to `mdtest/narrow/conditionals/nested.md`.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-05 16:28:42 -07:00
yunchi
a4c8e43c5f [pylint] Add fix safety section (PLR1722) (#17826)
parent: #15584 
fix introduced at: #816
2025-05-05 19:13:04 -04:00
Douglas Creager
ada4c4cb1f [ty] Don't require default typevars when specializing (#17872)
If a typevar is declared as having a default, we shouldn't require a
type to be specified for that typevar when explicitly specializing a
generic class:

```py
class WithDefault[T, U = int]: ...

reveal_type(WithDefault[str]())  # revealed: WithDefault[str, int]
```

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-05-05 18:29:30 -04:00
Alex Waygood
bb6c7cad07 [ty] Fix false-positive [invalid-return-type] diagnostics on generator functions (#17871) 2025-05-05 21:44:59 +00:00
Douglas Creager
47e3aa40b3 [ty] Specialize bound methods and nominal instances (#17865)
Fixes
https://github.com/astral-sh/ruff/pull/17832#issuecomment-2851224968. We
had a comment that we did not need to apply specializations to generic
aliases, or to the bound `self` of a bound method, because they were
already specialized. But they might be specialized with a type variable,
which _does_ need to be specialized, in the case of a "multi-step"
specialization, such as:

```py
class LinkedList[T]: ...

class C[U]:
    def method(self) -> LinkedList[U]:
        return LinkedList[U]()
```

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-05-05 17:17:36 -04:00
David Peter
9a6633da0b [ty] ecosystem: activate running on 'sympy' (#17870)
## Summary

Following #17869, we can now run `ty` on `sympy`.
2025-05-05 21:50:13 +02:00
David Peter
de78da5ee6 [ty] Increase worker-thread stack size (#17869)
## Summary

closes #17472 

This is obviously just a band-aid solution to this problem (in that you
can always make your [pathological
inputs](28994edd82/sympy/polys/numberfields/resolvent_lookup.py)
bigger and it will still crash), but I think this is not an unreasonable
change — even if we add more sophisticated solutions later. I tried
using `stacker` as suggested by @MichaReiser, and it works. But it's
unclear where exactly would be the right place to put it, and even for
the `sympy` problem, we would need to add it both in the semantic index
builder AST traversal and in type inference. Increasing the default
stack size for worker threads, as proposed here, doesn't solve the
underlying problem (that there is a hard limit), but it is more
universal in the sense that it is not specific to large binary-operator
expression chains.

To determine a reasonable stack size, I created files that look like

*right associative*:
```py
from typing import reveal_type
total = (1 + (1 + (1 + (1 + (… + 1)))))
reveal_type(total)
```

*left associative*
```py
from typing import reveal_type
total = 1 + 1 + 1 + 1 + … + 1
reveal_type(total)
```

with a variable amount of operands (`N`). I then chose the stack size
large enough to still be able to handle cases that existing type
checkers can not:

```
right

  N = 20: mypy takes ~ 1min
  N = 350: pyright crashes with a stack overflow (mypy fails with "too many nested parentheses")
  N = 800: ty(main) infers Literal[800] instantly
  N = 1000: ty(main) crashes with "thread '<unknown>' has overflowed its stack"

  N = 7000: ty(this branch) infers Literal[7000] instantly
  N = 8000+: ty(this branch) crashes


left

  N = 300: pyright emits "Maximum parse depth exceeded; break expression into smaller sub-expressions"
           total is inferred as Unknown
  N = 5500: mypy crashes with "INTERNAL ERROR"
  N = 2500: ty(main) infers Literal[2500] instantly
  N = 3000: ty(main) crashes with "thread '<unknown>' has overflowed its stack"

  N = 22000: ty(this branch) infers Literal[22000] instantly
  N = 23000+: ty(this branch) crashes
```

## Test Plan

New regression test.
2025-05-05 21:31:55 +02:00
Carl Meyer
20d64b9c85 [ty] add passing projects to primer (#17834)
Add projects to primer that now pass, with
https://github.com/astral-sh/ruff/pull/17833
2025-05-05 12:21:06 -07:00
Carl Meyer
4850c187ea [ty] add cycle handling for FunctionType::signature query (#17833)
This fixes cycle panics in several ecosystem projects (moved to
`good.txt` in a following PR
https://github.com/astral-sh/ruff/pull/17834 because our mypy-primer job
doesn't handle it well if we move projects to `good.txt` in the same PR
that fixes `ty` to handle them), as well as in the minimal case in the
added mdtest. It also fixes a number of panicking fuzzer seeds. It
doesn't appear to cause any regression in any ecosystem project or any
fuzzer seed.
2025-05-05 12:12:38 -07:00
Vasco Schiavo
3f32446e16 [ruff] add fix safety section (RUF013) (#17759)
The PR add the fix safety section for rule `RUF013`
(https://github.com/astral-sh/ruff/issues/15584 )
The fix was introduced here #4831

The rule as a lot of False Negative (as it is explained in the docs of
the rule).

The main reason because the fix is unsafe is that it could change code
generation tools behaviour, as in the example here:

```python
def generate_api_docs(func):
    hints = get_type_hints(func)
    for param, hint in hints.items():
        if is_optional_type(hint):
            print(f"Parameter '{param}' is optional")
        else:
            print(f"Parameter '{param}' is required")

# Before fix
def create_user(name: str, roles: list[str] = None):
    pass

# After fix
def create_user(name: str, roles: Optional[list[str]] = None):
    pass

# Generated docs would change from "roles is required" to "roles is optional"
```
2025-05-05 13:47:56 -05:00
Aria Desires
784daae497 migrate to dist-workspace.toml, use new workspace.packages config (#17864) 2025-05-05 14:07:46 -04:00
Max Mynter
178c882740 [semantic-syntax-tests] Add test fixtures for AwaitOutsideAsyncFunction (#17785)
<!--
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?
-->
Re: #17526 
## Summary
Add test fixtures for `AwaitOutsideAsync` and
`AsyncComprehensionOutsideAsyncFunction` errors.

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

## Test Plan
This is a test. 

<!-- How was it tested? -->
2025-05-05 14:02:06 -04:00
Max Mynter
101e1a5ddd [semantic-syntax-tests] for for InvalidStarExpression, DuplicateMatchKey, and DuplicateMatchClassAttribute (#17754)
Re: #17526 

## Summary
Add integration tests for Python Semantic Syntax for
`InvalidStarExpression`, `DuplicateMatchKey`, and
`DuplicateMatchClassAttribute`.

## Note
- Red knot integration tests for `DuplicateMatchKey` exist already in
line 89-101.
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan
This is a test.
<!-- How was it tested? -->
2025-05-05 17:30:16 +00:00
Dylan
965a4dd731 [isort] Check full module path against project root(s) when categorizing first-party (#16565)
When attempting to determine whether `import foo.bar.baz` is a known
first-party import relative to [user-provided source
paths](https://docs.astral.sh/ruff/settings/#src), when `preview` is
enabled we now check that `SRC/foo/bar/baz` is a directory or
`SRC/foo/bar/baz.py` or `SRC/foo/bar/baz.pyi` exist.

Previously, we just checked the analogous thing for `SRC/foo`, but this
can be misleading in situations with disjoint namespace packages that
share a common base name (e.g. we may be working inside the namespace
package `foo.buzz` and importing `foo.bar` from elsewhere).

Supersedes #12987 
Closes #12984
2025-05-05 11:40:01 -05:00
Victor Hugo Gomes
5e2c818417 [flake8-bandit] Mark tuples of string literals as trusted input in S603 (#17801)
<!--
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 #17798
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

Snapshot tests
<!-- How was it tested? -->
2025-05-05 10:50:44 -04:00
David Peter
90c12f4177 [ty] ecosystem: Activate running on 'materialize' (#17862) 2025-05-05 16:34:23 +02:00
Wei Lee
6e9fb9af38 [airflow] Skip attribute check in try catch block (AIR301) (#17790)
<!--
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? -->

Skip attribute check in try catch block (`AIR301`)

## Test Plan

<!-- How was it tested? -->
update
`crates/ruff_linter/resources/test/fixtures/airflow/AIR301_names_try.py`
2025-05-05 10:01:05 -04:00
Wei Lee
a507c1b8b3 [airflow] Remove airflow.utils.dag_parsing_context.get_parsing_context (AIR301) (#17852)
<!--
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? -->
Remove `airflow.utils.dag_parsing_context.get_parsing_context` from
AIR301 as it has been moved to AIR311

## Test Plan

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

the test fixture was updated in the previous PR
2025-05-05 09:31:57 -04:00
David Peter
5a91badb8b [ty] Move 'scipy' to list of 'good' projects (#17850)
## Summary

Adds `scipy` as a new project to `good.txt` as a follow-up to #17849.
2025-05-05 13:52:57 +02:00
David Peter
1945bfdb84 [ty] Fix standalone expression type retrieval in presence of cycles (#17849)
## Summary

When entering an `infer_expression_types` cycle from
`TypeInferenceBuilder::infer_standalone_expression`, we might get back a
`TypeInference::cycle_fallback(…)` that doesn't actually contain any new
types, but instead it contains a `cycle_fallback_type` which is set to
`Some(Type::Never)`. When calling `self.extend(…)`, we therefore don't
really pull in a type for the expression we're interested in. This
caused us to panic if we tried to call `self.expression_type(…)` after
`self.extend(…)`.

The proposed fix here is to retrieve that type from the nested
`TypeInferenceBuilder` directly, which will correctly fall back to
`cycle_fallback_type`.

## Details

I minimized the second example from #17792 a bit further and used this
example for debugging:

```py
from __future__ import annotations

class C: ...

def f(arg: C):
    pass

x, _ = f(1)

assert x
```

This is self-referential because when we check the assignment statement
`x, _ = f(1)`, we need to look up the signature of `f`. Since evaluation
of annotations is deferred, we look up the public type of `C` for the
`arg` parameter. The public use of `C` is visibility-constraint by "`x`"
via the `assert` statement. While evaluating this constraint, we need to
look up the type of `x`, which in turn leads us back to the `x, _ =
f(1)` definition.

The reason why this only showed up in the relatively peculiar case with
unpack assignments is the code here:


78b4c3ccf1/crates/ty_python_semantic/src/types/infer.rs (L2709-L2718)

For a non-unpack assignment like `x = f(1)`, we would not try to infer
the right-hand side eagerly. Instead, we would enter a
`infer_definition_types` cycle that handles the situation correctly. For
unpack assignments, however, we try to infer the type of `value`
(`f(1)`) and therefore enter the cycle via `standalone_expression_type
=> infer_expression_type`.

closes #17792 

## Test Plan

* New regression test
* Made sure that we can now run successfully on scipy => see #17850
2025-05-05 13:52:08 +02:00
Dylan
a95c73d5d0 Implement deferred annotations for Python 3.14 (#17658)
This PR updates the semantic model for Python 3.14 by essentially
equating "run using Python 3.14" with "uses `from __future__ import
annotations`".

While this is not technically correct under the hood, it appears to be
correct for the purposes of our semantic model. That is: from the point
of view of deciding when to parse, bind, etc. annotations, these two
contexts behave the same. More generally these contexts behave the same
unless you are performing some kind of introspection like the following:


Without future import:
```pycon
>>> from annotationlib import get_annotations,Format
>>> def foo()->Bar:...
...
>>> get_annotations(foo,format=Format.FORWARDREF)
{'return': ForwardRef('Bar')}
>>> get_annotations(foo,format=Format.STRING)
{'return': 'Bar'}
>>> get_annotations(foo,format=Format.VALUE)
Traceback (most recent call last):
[...]
NameError: name 'Bar' is not defined
>>> get_annotations(foo)
Traceback (most recent call last):
[...]
NameError: name 'Bar' is not defined
```

With future import:
```
>>> from __future__ import annotations
>>> from annotationlib import get_annotations,Format
>>> def foo()->Bar:...
...
>>> get_annotations(foo,format=Format.FORWARDREF)
{'return': 'Bar'}
>>> get_annotations(foo,format=Format.STRING)
{'return': 'Bar'}
>>> get_annotations(foo,format=Format.VALUE)
{'return': 'Bar'}
>>> get_annotations(foo)
{'return': 'Bar'}
```

(Note: the result of the last call to `get_annotations` in these
examples relies on the fact that, as of this writing, the default value
for `format` is `Format.VALUE`).

If one day we support lint rules targeting code that introspects using
the new `annotationlib`, then it is possible we will need to revisit our
approximation.

Closes #15100
2025-05-05 06:40:36 -05:00
David Peter
78b4c3ccf1 [ty] Minor typo in environment variable name (#17848) 2025-05-05 10:25:48 +00:00
renovate[bot]
2485afe640 Update pre-commit dependencies (#17840)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-05 07:36:09 +00:00
renovate[bot]
b8ed729f59 Update taiki-e/install-action digest to 86c23ee (#17838)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 07:43:54 +02:00
renovate[bot]
108c470348 Update actions/download-artifact action to v4.3.0 (#17845)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 07:43:33 +02:00
renovate[bot]
87c64c9eab Update actions/setup-python action to v5.6.0 (#17846)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 07:43:01 +02:00
renovate[bot]
a10606dda2 Update Rust crate jiff to v0.2.12 (#17843) 2025-05-05 07:34:09 +02:00
renovate[bot]
d1c6dd9ac1 Update Rust crate toml to v0.8.22 (#17844) 2025-05-05 07:32:50 +02:00
renovate[bot]
073b993ab0 Update Rust crate assert_fs to v1.1.3 (#17841) 2025-05-05 07:31:02 +02:00
renovate[bot]
6a36cd6f02 Update Rust crate hashbrown to v0.15.3 (#17842) 2025-05-05 07:30:46 +02:00
renovate[bot]
3b15af6d4f Update dependency ruff to v0.11.8 (#17839) 2025-05-05 07:29:36 +02:00
Micha Reiser
e95130ad80 Introduce TY_MAX_PARALLELISM environment variable (#17830) 2025-05-04 16:27:15 +02:00
Micha Reiser
68e32c103f Ignore PRs labeled with ty for Ruff changelog (#17831) 2025-05-04 14:42:10 +01:00
Brent Westbrook
fe4051b2e6 Fix missing combine call for lint.typing-extensions setting (#17823)
## Summary

Fixes #17821.

## Test Plan

New CLI test. This might be overkill for such a simple fix, but it made
me feel better to add a test.
2025-05-03 18:19:19 -04:00
Micha Reiser
fa628018b2 Use #[expect(lint)] over #[allow(lint)] where possible (#17822) 2025-05-03 21:20:31 +02:00
Eric Botti
8535af8516 [red-knot] Add support for the LSP diagnostic tag (#17657)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-03 20:35:03 +02:00
Micha Reiser
b51c4f82ea Rename Red Knot (#17820) 2025-05-03 19:49:15 +02:00
Alex Waygood
e6a798b962 [red-knot] Recurse into the types of protocol members when normalizing a protocol's interface (#17808)
## Summary

Currently red-knot does not understand `Foo` and `Bar` here as being
equivalent:

```py
from typing import Protocol

class A: ...
class B: ...
class C: ...

class Foo(Protocol):
    x: A | B | C

class Bar(Protocol):
    x: B | A | C
```

Nor does it understand `A | B | Foo` as being equivalent to `Bar | B |
A`. This PR fixes that.

## Test Plan

new mdtest assertions added that fail on `main`
2025-05-03 16:43:37 +01:00
Alex Waygood
52b0470870 [red-knot] Synthesize a __call__ attribute for Callable types (#17809)
## Summary

Currently this assertion fails on `main`, because we do not synthesize a
`__call__` attribute for Callable types:

```py
from typing import Protocol, Callable
from knot_extensions import static_assert, is_assignable_to

class Foo(Protocol):
    def __call__(self, x: int, /) -> str: ...

static_assert(is_assignable_to(Callable[[int], str], Foo))
```

This PR fixes that.

See previous discussion about this in
https://github.com/astral-sh/ruff/pull/16493#discussion_r1985098508 and
https://github.com/astral-sh/ruff/pull/17682#issuecomment-2839527750

## Test Plan

Existing mdtests updated; a couple of new ones added.
2025-05-03 16:43:18 +01:00
Brent Westbrook
c4a08782cc Add regression test for parent noqa (#17783)
Summary
--

Adds a regression test for #2253 after I tried to delete the fix from
#2464.
2025-05-03 11:38:31 -04:00
Alex Waygood
91481a8be7 [red-knot] Minor simplifications to types/display.rs (#17813) 2025-05-03 15:29:05 +01:00
Victor Hugo Gomes
097af060c9 [refurb] Fix false positive for float and complex numbers in FURB116 (#17661) 2025-05-03 15:59:46 +02:00
Alex Waygood
b7d0b3f9e5 [red-knot] Add tests asserting that subclasses of Any are assignable to arbitrary protocol types (#17810) 2025-05-03 12:41:55 +00:00
Alex Waygood
084352f72c [red-knot] Distinguish fully static protocols from non-fully-static protocols (#17795) 2025-05-03 11:12:23 +01:00
Carl Meyer
78d4356301 [red-knot] add tracing of salsa events in mdtests (#17803) 2025-05-03 09:00:11 +02:00
Douglas Creager
96697c98f3 [red-knot] Legacy generic classes (#17721)
This adds support for legacy generic classes, which use a
`typing.Generic` base class, or which inherit from another generic class
that has been specialized with legacy typevars.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-02 20:34:20 -04:00
Micha Reiser
f7cae4ffb5 [red-knot] Don't panic when primary-span is missing while panicking (#17799) 2025-05-02 21:19:03 +01:00
Douglas Creager
675a5af89a [red-knot] Use Vec in CallArguments; reuse self when we can (#17793)
Quick follow-on to #17788. If there is no bound `self` parameter, we can
reuse the existing `CallArgument{,Type}s`, and we can use a straight
`Vec` instead of a `VecDeque`.
2025-05-02 12:00:02 -04:00
David Peter
ea3f4ac059 [red-knot] Refactor: no mutability in call APIs (#17788)
## Summary

Remove mutability in parameter types for a few functions such as
`with_self` and `try_call`. I tried the `Rc`-approach with cheap cloning
[suggest
here](https://github.com/astral-sh/ruff/pull/17733#discussion_r2068722860)
first, but it turns out we need a whole stack of prepended arguments
(there can be [both `self` *and*
`cls`](3cf44e401a/crates/red_knot_python_semantic/resources/mdtest/call/constructor.md (L113))),
and we would need the same construct not just for `CallArguments` but
also for `CallArgumentTypes`. At that point we're cloning `VecDeque`s
anyway, so the overhead of cloning the whole `VecDeque` with all
arguments didn't seem to justify the additional code complexity.

## Benchmarks

Benchmarks on tomllib, black, jinja, isort seem neutral.
2025-05-02 13:53:19 +02:00
David Peter
6d2c10cca2 [red-knot] Fix panic for tuple[x[y]] string annotation (#17787)
## Summary

closes #17775

## Test Plan

Added corpus regression test
2025-05-02 12:11:47 +02:00
David Peter
3cf44e401a [red-knot] Implicit instance attributes in generic methods (#17769)
## Summary

Add the ability to detect instance attribute assignments in class
methods that are generic.

This does not address the code duplication mentioned in #16928. I can
open a ticket for this after this has been merged.

closes #16928

## Test Plan

Added regression test.
2025-05-02 08:20:37 +00:00
Micha Reiser
17050e2ec5 doc: Add link to check-typed-exception from S110 and S112 (#17786) 2025-05-02 09:25:58 +02:00
Micha Reiser
a6dc04f96e Fix module name in ASYNC110, 115, and 116 fixes (#17774) 2025-05-01 23:37:09 +02:00
David Peter
e515899141 [red-knot] More informative hover-types for assignments (#17762)
## Summary

closes https://github.com/astral-sh/ruff/issues/17122

## Test Plan

* New hover tests
* Opened the playground locally and saw that new hover-types are shown
as expected.
2025-05-01 20:33:51 +02:00
Abhijeet Prasad Bodas
0c80c56afc [syntax-errors] Use consistent message for bad starred expression usage. (#17772) 2025-05-01 20:18:35 +02:00
Andrew Gallant
b7ce694162 red_knot_server: add auto-completion MVP
This PR does the wiring necessary to respond to completion requests from
LSP clients.

As far as the actual completion results go, they are nearly about the
dumbest and simplest thing we can do: we simply return a de-duplicated
list of all identifiers from the current module.
2025-05-01 12:08:10 -04:00
Brent Westbrook
163d526407 Allow passing a virtual environment to ruff analyze graph (#17743)
Summary
--

Fixes #16598 by adding the `--python` flag to `ruff analyze graph`,
which adds a `PythonPath` to the `SearchPathSettings` for module
resolution. For the [albatross-virtual-workspace] example from the uv
repo, this updates the output from the initial issue:

```shell
> ruff analyze graph packages/albatross
{
  "packages/albatross/check_installed_albatross.py": [
    "packages/albatross/src/albatross/__init__.py"
  ],
  "packages/albatross/src/albatross/__init__.py": []
}
```

To include both the the workspace `bird_feeder` import _and_ the
third-party `tqdm` import in the output:

```shell
> myruff analyze graph packages/albatross --python .venv
{
  "packages/albatross/check_installed_albatross.py": [
    "packages/albatross/src/albatross/__init__.py"
  ],
  "packages/albatross/src/albatross/__init__.py": [
    ".venv/lib/python3.12/site-packages/tqdm/__init__.py",
    "packages/bird-feeder/src/bird_feeder/__init__.py"
  ]
}
```

Note the hash in the uv link! I was temporarily very confused why my
local tests were showing an `iniconfig` import instead of `tqdm` until I
realized that the example has been updated on the uv main branch, which
I had locally.

Test Plan
--

A new integration test with a stripped down venv based on the
`albatross` example.

[albatross-virtual-workspace]:
aa629c4a54/scripts/workspaces/albatross-virtual-workspace
2025-05-01 11:29:52 -04:00
Brent Westbrook
75effb8ed7 Bump 0.11.8 (#17766) 2025-05-01 10:19:58 -04:00
Victor Hugo Gomes
3353d07938 [flake8-use-pathlib] Fix PTH104false positive when rename is passed a file descriptor (#17712)
## Summary
Contains the same changes to the semantic type inference as
https://github.com/astral-sh/ruff/pull/17705.

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

## Test Plan

<!-- How was it tested? -->
Snapshot tests.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-05-01 10:01:17 -04:00
Alex Waygood
41f3f21629 Improve messages outputted by py-fuzzer (#17764) 2025-05-01 12:32:45 +00:00
Hans
76ec64d535 [red-knot] Allow subclasses of Any to be assignable to Callable types (#17717)
## Summary

Fixes #17701.

## Test plan

New Markdown test.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-05-01 10:18:12 +02:00
Micha Reiser
b7e69ecbfc [red-knot] Increase durability of read-only File fields (#17757) 2025-05-01 09:25:48 +02:00
Micha Reiser
9c57862262 [red-knot] Cache source type during semanic index building (#17756)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-05-01 08:51:53 +02:00
Victor Hugo Gomes
67ef370733 [flake8-use-pathlib] Fix PTH116 false positive when stat is passed a file descriptor (#17709)
Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-05-01 08:16:28 +02:00
github-actions[bot]
e17e1e860b Sync vendored typeshed stubs (#17753)
Co-authored-by: typeshedbot <>
2025-05-01 07:57:03 +02:00
David Peter
03d8679adf [red-knot] Preliminary NamedTuple support (#17738)
## Summary

Adds preliminary support for `NamedTuple`s, including:
* No false positives when constructing a `NamedTuple` object
* Correct signature for the synthesized `__new__` method, i.e. proper
checking of constructor calls
* A patched MRO (`NamedTuple` => `tuple`), mainly to make type inference
of named attributes possible, but also to better reflect the runtime
MRO.

All of this works:
```py
from typing import NamedTuple

class Person(NamedTuple):
    id: int
    name: str
    age: int | None = None

alice = Person(1, "Alice", 42)
alice = Person(id=1, name="Alice", age=42)

reveal_type(alice.id)  # revealed: int
reveal_type(alice.name)  # revealed: str
reveal_type(alice.age)  # revealed: int | None

# error: [missing-argument]
Person(3)

# error: [too-many-positional-arguments]
Person(3, "Eve", 99, "extra")

# error: [invalid-argument-type]
Person(id="3", name="Eve")
```

Not included:
* type inference for index-based access.
* support for the functional `MyTuple = NamedTuple("MyTuple", […])`
syntax

## Test Plan

New Markdown tests

## Ecosystem analysis

```
                          Diagnostic Analysis Report                           
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┓
┃ Diagnostic ID                     ┃ Severity ┃ Removed ┃ Added ┃ Net Change ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━┩
│ lint:call-non-callable            │ error    │       0 │     3 │         +3 │
│ lint:call-possibly-unbound-method │ warning  │       0 │     4 │         +4 │
│ lint:invalid-argument-type        │ error    │       0 │    72 │        +72 │
│ lint:invalid-context-manager      │ error    │       0 │     2 │         +2 │
│ lint:invalid-return-type          │ error    │       0 │     2 │         +2 │
│ lint:missing-argument             │ error    │       0 │    46 │        +46 │
│ lint:no-matching-overload         │ error    │   19121 │     0 │     -19121 │
│ lint:not-iterable                 │ error    │       0 │     6 │         +6 │
│ lint:possibly-unbound-attribute   │ warning  │      13 │    32 │        +19 │
│ lint:redundant-cast               │ warning  │       0 │     1 │         +1 │
│ lint:unresolved-attribute         │ error    │       0 │    10 │        +10 │
│ lint:unsupported-operator         │ error    │       3 │     9 │         +6 │
│ lint:unused-ignore-comment        │ warning  │      15 │     4 │        -11 │
├───────────────────────────────────┼──────────┼─────────┼───────┼────────────┤
│ TOTAL                             │          │   19152 │   191 │     -18961 │
└───────────────────────────────────┴──────────┴─────────┴───────┴────────────┘

Analysis complete. Found 13 unique diagnostic IDs.
Total diagnostics removed: 19152
Total diagnostics added: 191
Net change: -18961
```

I uploaded the ecosystem full diff (ignoring the 19k
`no-matching-overload` diagnostics)
[here](https://shark.fish/diff-namedtuple.html).

* There are some new `missing-argument` false positives which come from
the fact that named tuples are often created using unpacking as in
`MyNamedTuple(*fields)`, which we do not understand yet.
* There are some new `unresolved-attribute` false positives, because
methods like `_replace` are not available.
* Lots of the `invalid-argument-type` diagnostics look like true
positives

---------

Co-authored-by: Douglas Creager <dcreager@dcreager.net>
2025-04-30 22:52:04 +02:00
Victor Hugo Gomes
d33a503686 [red-knot] Add tests for classes that have incompatible __new__ and __init__ methods (#17747)
Closes #17737
2025-04-30 20:40:16 +00:00
renovate[bot]
650cbdd296 Update dependency vite to v6.2.7 (#17746) 2025-04-30 22:12:03 +02:00
Dhruv Manilawala
d2a238dfad [red-knot] Update call binding to return all matching overloads (#17618)
## Summary

This PR updates the existing overload matching methods to return an
iterator of all the matched overloads instead.

This would be useful once the overload call evaluation algorithm is
implemented which should provide an accurate picture of all the matched
overloads. The return type would then be picked from either the only
matched overload or the first overload from the ones that are matched.

In an earlier version of this PR, it tried to check if using an
intersection of return types from the matched overload would help reduce
the false positives but that's not enough. [This
comment](https://github.com/astral-sh/ruff/pull/17618#issuecomment-2842891696)
keep the ecosystem analysis for that change for prosperity.

> [!NOTE]
>
> The best way to review this PR is by hiding the whitespace changes
because there are two instances where a large match expression is
indented to be inside a loop over matching overlods
>
> <img width="1207" alt="Screenshot 2025-04-28 at 15 12 16"
src="https://github.com/user-attachments/assets/e06cbfa4-04fa-435f-84ef-4e5c3c5626d1"
/>

## Test Plan

Make sure existing test cases are unaffected and no ecosystem changes.
2025-05-01 01:33:21 +05:30
Wei Lee
6e765b4527 [airflow] apply Replacement::AutoImport to AIR312 (#17570)
## Summary

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

This is not yet fixing anything as the names are not changed, but it
lays down the foundation for fixing.

## Test Plan

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

the existing test fixture should already cover this change
2025-04-30 15:53:10 -04:00
Vasco Schiavo
c5e41c278c [ruff] Add fix safety section (RUF028) (#17722)
The PR add the fix safety section for rule `RUF028`
(https://github.com/astral-sh/ruff/issues/15584 )

See also
[here](https://github.com/astral-sh/ruff/issues/15584#issuecomment-2820424485)
for the reason behind the _unsafe_ of the fix.
2025-04-30 15:06:25 -04:00
Abhijeet Prasad Bodas
0eeb02c0c1 [syntax-errors] Detect single starred expression assignment x = *y (#17624)
## Summary

Part of #17412

Starred expressions cannot be used as values in assignment expressions.
Add a new semantic syntax error to catch such instances.
Note that we already have
`ParseErrorType::InvalidStarredExpressionUsage` to catch some starred
expression errors during parsing, but that does not cover top level
assignment expressions.

## Test Plan

- Added new inline tests for the new rule
- Found some examples marked as "valid" in existing tests (`_ = *data`),
which are not really valid (per this new rule) and updated them
- There was an existing inline test - `assign_stmt_invalid_value_expr`
which had instances of `*` expression which would be deemed invalid by
this new rule. Converted these to tuples, so that they do not trigger
this new rule.
2025-04-30 15:04:00 -04:00
Alex Waygood
f31b1c695c py-fuzzer: fix minimization logic when --only-new-bugs is passed (#17739) 2025-04-30 18:48:31 +01:00
Brendan Cooley
5679bf00bc Fix example syntax for pydocstyle ignore_var_parameters option (#17740)
Co-authored-by: Brendan Cooley <brendanc@ladodgers.com>
2025-04-30 18:19:41 +02:00
Micha Reiser
a7c358ab5c [red-knot] Update salsa to prevent panic in custom panic-handler (#17742) 2025-04-30 18:19:07 +02:00
Alex Waygood
b6de01b9a5 [red-knot] Ban direct instantiation of generic protocols as well as non-generic ones (#17741) 2025-04-30 16:01:28 +00:00
David Peter
18bac94226 [red-knot] Lookup of __new__ (#17733)
## Summary

Model the lookup of `__new__` without going through
`Type::try_call_dunder`. The `__new__` method is only looked up on the
constructed type itself, not on the meta-type.

This now removes ~930 false positives across the ecosystem (vs 255 for
https://github.com/astral-sh/ruff/pull/17662). It introduces 30 new
false positives related to the construction of enums via something like
`Color = enum.Enum("Color", ["RED", "GREEN"])`. This is expected,
because we don't handle custom metaclass `__call__` methods. The fact
that we previously didn't emit diagnostics there was a coincidence (we
incorrectly called `EnumMeta.__new__`, and since we don't fully
understand its signature, that happened to work with `str`, `list`
arguments).

closes #17462

## Test Plan

Regression test
2025-04-30 17:27:09 +02:00
Dhruv Manilawala
7568eeb7a5 [red-knot] Check decorator consistency on overloads (#17684)
## Summary

Part of #15383.

As per the spec
(https://typing.python.org/en/latest/spec/overload.html#invalid-overload-definitions):

For `@staticmethod` and `@classmethod`:

> If one overload signature is decorated with `@staticmethod` or
`@classmethod`, all overload signatures must be similarly decorated. The
implementation, if present, must also have a consistent decorator. Type
checkers should report an error if these conditions are not met.

For `@final` and `@override`:

> If a `@final` or `@override` decorator is supplied for a function with
overloads, the decorator should be applied only to the overload
implementation if it is present. If an overload implementation isn’t
present (for example, in a stub file), the `@final` or `@override`
decorator should be applied only to the first overload. Type checkers
should enforce these rules and generate an error when they are violated.
If a `@final` or `@override` decorator follows these rules, a type
checker should treat the decorator as if it is present on all overloads.

## Test Plan

Update existing tests; add snapshots.
2025-04-30 20:34:21 +05:30
Hans
0e85cbdd91 [flake8-use-pathlib] Avoid suggesting Path.iterdir() for os.listdir with file descriptor (PTH208) (#17715)
## Summary

Fixes: #17695

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-04-30 20:08:57 +05:30
Dhruv Manilawala
7825975972 [red-knot] Check overloads without an implementation (#17681)
## Summary

As mentioned in the spec
(https://typing.python.org/en/latest/spec/overload.html#invalid-overload-definitions),
part of #15383:

> The `@overload`-decorated definitions must be followed by an overload
implementation, which does not include an `@overload` decorator. Type
checkers should report an error or warning if an implementation is
missing. Overload definitions within stub files, protocols, and on
abstract methods within abstract base classes are exempt from this
check.

## Test Plan

Remove TODOs from the test; create one diagnostic snapshot.
2025-04-30 19:54:21 +05:30
Max Mynter
f584b66824 Expand Semantic Syntax Coverage (#17725)
Re: #17526 

## Summary
Adds tests to red knot and `linter.rs` for the semantic syntax. 

Specifically add tests for `ReboundComprehensionVariable`,
`DuplicateTypeParameter`, and `MultipleCaseAssignment`.

Refactor the `test_async_comprehension_in_sync_comprehension` →
`test_semantic_error` to be more general for all semantic syntax test
cases.

## Test Plan
This is a test.

## Question
I'm happy to contribute more tests the coming days. 

Should that happen here or should we merge this PR such that the
refactor `test_async_comprehension_in_sync_comprehension` →
`test_semantic_error` is available on main and others can chime in, too?
2025-04-30 10:14:08 -04:00
Dhruv Manilawala
ad1a8da4d1 [red-knot] Check for invalid overload usages (#17609)
## Summary

Part of #15383, this PR adds the core infrastructure to check for
invalid overloads and adds a diagnostic to raise if there are < 2
overloads for a given definition.

### Design notes

The requirements to check the overloads are:
* Requires `FunctionType` which has the `to_overloaded` method
* The `FunctionType` **should** be for the function that is either the
implementation or the last overload if the implementation doesn't exists
* Avoid checking any `FunctionType` that are part of an overload chain
* Consider visibility constraints

This required a couple of iteration to make sure all of the above
requirements are fulfilled.

#### 1. Use a set to deduplicate

The logic would first collect all the `FunctionType` that are part of
the overload chain except for the implementation or the last overload if
the implementation doesn't exists. Then, when iterating over all the
function declarations within the scope, we'd avoid checking these
functions. But, this approach would fail to consider visibility
constraints as certain overloads _can_ be behind a version check. Those
aren't part of the overload chain but those aren't a separate overload
chain either.

<details><summary>Implementation:</summary>
<p>

```rs
fn check_overloaded_functions(&mut self) {
    let function_definitions = || {
        self.types
            .declarations
            .iter()
            .filter_map(|(definition, ty)| {
                // Filter out function literals that result from anything other than a function
                // definition e.g., imports.
                if let DefinitionKind::Function(function) = definition.kind(self.db()) {
                    ty.inner_type()
                        .into_function_literal()
                        .map(|ty| (ty, definition.symbol(self.db()), function.node()))
                } else {
                    None
                }
            })
    };

    // A set of all the functions that are part of an overloaded function definition except for
    // the implementation function and the last overload in case the implementation doesn't
    // exists. This allows us to collect all the function definitions that needs to be skipped
    // when checking for invalid overload usages.
    let mut overloads: HashSet<FunctionType<'db>> = HashSet::default();

    for (function, _) in function_definitions() {
        let Some(overloaded) = function.to_overloaded(self.db()) else {
            continue;
        };
        if overloaded.implementation.is_some() {
            overloads.extend(overloaded.overloads.iter().copied());
        } else if let Some((_, previous_overloads)) = overloaded.overloads.split_last() {
            overloads.extend(previous_overloads.iter().copied());
        }
    }

    for (function, function_node) in function_definitions() {
        let Some(overloaded) = function.to_overloaded(self.db()) else {
            continue;
        };
        if overloads.contains(&function) {
            continue;
        }

        // At this point, the `function` variable is either the implementation function or the
        // last overloaded function if the implementation doesn't exists.

        if overloaded.overloads.len() < 2 {
            if let Some(builder) = self
                .context
                .report_lint(&INVALID_OVERLOAD, &function_node.name)
            {
                let mut diagnostic = builder.into_diagnostic(format_args!(
                    "Function `{}` requires at least two overloads",
                    &function_node.name
                ));
                if let Some(first_overload) = overloaded.overloads.first() {
                    diagnostic.annotate(
                        self.context
                            .secondary(first_overload.focus_range(self.db()))
                            .message(format_args!("Only one overload defined here")),
                    );
                }
            }
        }
    }
 }
```

</p>
</details> 

#### 2. Define a `predecessor` query

The `predecessor` query would return the previous `FunctionType` for the
given `FunctionType` i.e., the current logic would be extracted to be a
query instead. This could then be used to make sure that we're checking
the entire overload chain once. The way this would've been implemented
is to have a `to_overloaded` implementation which would take the root of
the overload chain instead of the leaf. But, this would require updates
to the use-def map to somehow be able to return the _following_
functions for a given definition.

#### 3. Create a successor link

This is what Pyrefly uses, we'd create a forward link between two
functions that are involved in an overload chain. This means that for a
given function, we can get the successor function. This could be used to
find the _leaf_ of the overload chain which can then be used with the
`to_overloaded` method to get the entire overload chain. But, this would
also require updating the use-def map to be able to "see" the
_following_ function.

### Implementation 

This leads us to the final implementation that this PR implements which
is to consider the overloaded functions using:
* Collect all the **function symbols** that are defined **and** called
within the same file. This could potentially be an overloaded function
* Use the public bindings to get the leaf of the overload chain and use
that to get the entire overload chain via `to_overloaded` and perform
the check

This has a limitation that in case a function redefines an overload,
then that overload will not be checked. For example:

```py
from typing import overload

@overload
def f() -> None: ...
@overload
def f(x: int) -> int: ...

# The above overload will not be checked as the below function with the same name
# shadows it

def f(*args: int) -> int: ...
```

## Test Plan

Update existing mdtest and add snapshot diagnostics.
2025-04-30 19:37:42 +05:30
Micha Reiser
0861ecfa55 [red-knot] Use 'full' salsa backtrace output that includes durability and revisions (#17735) 2025-04-30 11:04:06 +00:00
Alex Waygood
d1f359afbb [red-knot] Initial support for protocol types (#17682) 2025-04-30 11:03:10 +00:00
Alex Waygood
b84b58760e [red-knot] Computing a type ordering for two non-normalized types is meaningless (#17734) 2025-04-30 11:58:55 +01:00
Micha Reiser
d94be0e780 [red-knot] Include salsa backtrace in check and mdtest panic messages (#17732)
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-04-30 10:26:40 +02:00
Alex Waygood
8a6787b39e [red-knot] Fix control flow for assert statements (#17702)
## Summary

@sharkdp and I realised in our 1:1 this morning that our control flow
for `assert` statements isn't quite accurate at the moment. Namely, for
something like this:

```py
def _(x: int | None):
    assert x is None, reveal_type(x)
```

we currently reveal `None` for `x` here, but this is incorrect. In
actual fact, the `msg` expression of an `assert` statement (the
expression after the comma) will only be evaluated if the test (`x is
None`) evaluates to `False`. As such, we should be adding a constraint
of `~None` to `x` in the `msg` expression, which should simplify the
inferred type of `x` to `int` in that context (`(int | None) & ~None` ->
`int`).

## Test Plan

Mdtests added.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-04-30 09:57:49 +02:00
David Peter
4a621c2c12 [red-knot] Fix recording of negative visibility constraints (#17731)
## Summary

We were previously recording wrong reachability constraints for negative
branches. Instead of `[cond] AND (NOT [True])` below, we were recording
`[cond] AND (NOT ([cond] AND [True]))`, i.e. we were negating not just
the last predicate, but the `AND`-ed reachability constraint from last
clause. With this fix, we now record the correct constraints for the
example from #17723:

```py
def _(cond: bool):
    if cond:
        # reachability: [cond]
        if True:
            # reachability: [cond] AND [True]
            pass
        else:
            # reachability: [cond] AND (NOT [True])
            x
```

closes #17723 

## Test Plan

* Regression test.
* Verified the ecosystem changes
2025-04-30 09:32:13 +02:00
Micha Reiser
2bb99df394 [red-knot] Update salsa (#17730) 2025-04-30 08:58:31 +02:00
Dhruv Manilawala
f11d9cb509 [red-knot] Support overloads for callable equivalence (#17698)
## Summary

Part of #15383, this PR adds `is_equivalent_to` support for overloaded
callables.

This is mainly done by delegating it to the subtyping check in that two
types A and B are considered equivalent if A is a subtype of B and B is
a subtype of A.

## Test Plan

Add test cases for overloaded callables in `is_equivalent_to.md`
2025-04-30 02:53:59 +05:30
Alex Waygood
549ab74bd6 [red-knot] Run py-fuzzer in CI to check for new panics (#17719) 2025-04-29 21:19:29 +00:00
Alex Waygood
81fc7d7d3a Upload red-knot binaries in CI on completion of linux tests (#17720) 2025-04-29 22:15:26 +01:00
Victor Hugo Gomes
8c68d30c3a [flake8-use-pathlib] Fix PTH123 false positive when open is passed a file descriptor from a function call (#17705)
## Summary
Includes minor changes to the semantic type inference to help detect the
return type of function call.

Fixes #17691

## Test Plan

Snapshot tests
2025-04-29 16:51:38 -04:00
Alex Waygood
93d6a3567b [red-knot] mdtest.py: Watch for changes in red_knot_vendored and red_knot_test as well as in red_knot_python_semantic (#17718) 2025-04-29 18:27:49 +00:00
Micha Reiser
1d788981cd [red-knot] Capture backtrace in "check-failed" diagnostic (#17641)
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-04-29 16:58:58 +00:00
Hans
7d46579808 [docs] fix duplicated 'are' in comment for PTH123 rule (#17714) 2025-04-29 17:58:39 +02:00
Alex Waygood
c9a6b1a9d0 [red-knot] Make Type::signatures() exhaustive (#17706) 2025-04-29 15:14:08 +01:00
Hans
9b9d16c3ba [red-knot] colorize concise output diagnostics (#17232) (#17479)
Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Andrew Gallant <andrew@astral.sh>
2025-04-29 16:07:16 +02:00
David Peter
79f8473e51 [red-knot] Assignability of class literals to Callables (#17704)
## Summary

Subtyping was already modeled, but assignability also needs an explicit
branch. Removes 921 ecosystem false positives.

## Test Plan

New Markdown tests.
2025-04-29 15:04:22 +02:00
Douglas Creager
ca4fdf452d Create TypeVarInstance type for legacy typevars (#16538)
We are currently representing type variables using a `KnownInstance`
variant, which wraps a `TypeVarInstance` that contains the information
about the typevar (name, bounds, constraints, default type). We were
previously only constructing that type for PEP 695 typevars. This PR
constructs that type for legacy typevars as well.

It also detects functions that are generic because they use legacy
typevars in their parameter list. With the existing logic for inferring
specializations of function calls (#17301), that means that we are
correctly detecting that the definition of `reveal_type` in the typeshed
is generic, and inferring the correct specialization of `_T` for each
call site.

This does not yet handle legacy generic classes; that will come in a
follow-on PR.
2025-04-29 09:03:06 -04:00
Dylan
3c460a7b9a Make syntax error for unparenthesized except tuples version specific to before 3.14 (#17660)
What it says on the tin 😄
2025-04-29 07:55:30 -05:00
Alex Waygood
31e6576971 [red-knot] micro-optimise ClassLiteral::is_protocol (#17703) 2025-04-29 12:35:53 +00:00
Micha Reiser
c953e7d143 [red-knot] Improve log message for default python platform (#17700) 2025-04-29 08:26:41 +00:00
Vasco Schiavo
5096824793 [ruff] add fix safety section (RUF017) (#17480)
The PR add the `fix safety` section for rule `RUF017` (#15584 )
2025-04-28 22:07:22 +00:00
Dylan
ae7691b026 Add Python 3.14 to configuration options (#17647)
A small PR that just updates the various settings/configurations to
allow Python 3.14. At the moment selecting that target version will
have no impact compared to Python 3.13 - except that a warning
is emitted if the user does so with `preview` disabled.
2025-04-28 16:29:00 -05:00
Wei Lee
504fa20057 [airflow] Apply auto fixes to cases where the names have changed in Airflow 3 (AIR302) (#17553)
## Summary

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

Apply auto fixes to cases where the names have changed in Airflow 3 in
AIR302 and split the huge test cases into different test cases based on
proivder

## Test Plan

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

the test cases has been split into multiple for easier checking
2025-04-28 16:35:17 -04:00
David Peter
f0868ac0c9 [red-knot] Revert blanket clippy::too_many_arguments allow (#17688)
## Summary

Now that https://github.com/salsa-rs/salsa/issues/808 has been fixed, we
can revert this global change in `Cargo.toml`.
2025-04-28 21:21:53 +02:00
Brent Westbrook
01a31c08f5 Add config option to disable typing_extensions imports (#17611)
Summary
--

This PR resolves https://github.com/astral-sh/ruff/issues/9761 by adding
a linter configuration option to disable
`typing_extensions` imports. As mentioned [here], it would be ideal if
we could
detect whether or not `typing_extensions` is available as a dependency
automatically, but this seems like a much easier fix in the meantime.

The default for the new option, `typing-extensions`, is `true`,
preserving the current behavior. Setting it to `false` will bail out of
the new
`Checker::typing_importer` method, which has been refactored from the 
`Checker::import_from_typing` method in
https://github.com/astral-sh/ruff/pull/17340),
with `None`, which is then handled specially by each rule that calls it.

I considered some alternatives to a config option, such as checking if
`typing_extensions` has been imported or checking for a `TYPE_CHECKING`
block we could use, but I think defaulting to allowing
`typing_extensions` imports and allowing the user to disable this with
an option is both simple to implement and pretty intuitive.

[here]:
https://github.com/astral-sh/ruff/issues/9761#issuecomment-2790492853

Test Plan
--

New linter tests exercising several combinations of Python versions and
the new config option for PYI019. I also added tests for the other
affected rules, but only in the case where the new config option is
enabled. The rules' existing tests also cover the default case.
2025-04-28 14:57:36 -04:00
Andrew Gallant
405878a128 ruff_db: render file paths in diagnostics as relative paths if possible
This is done in what appears to be the same way as Ruff: we get the CWD,
strip the prefix from the path if possible, and use that. If stripping
the prefix fails, then we print the full path as-is.

Fixes #17233
2025-04-28 14:32:34 -04:00
Alex Waygood
80103a179d Bump mypy_primer pin (#17685) 2025-04-28 16:13:07 +00:00
Andrew Gallant
9a8f3cf247 red_knot_python_semantic: improve not-iterable diagnostic
This cleans up one particular TODO by splitting the "because" part of
the `not-iterable` diagnostic out into an info sub-diagnostic.
2025-04-28 11:03:41 -04:00
David Peter
07718f4788 [red-knot] Allow all callables to be assignable to @Todo-signatures (#17680)
## Summary

Removes ~850 diagnostics related to assignability of callable types,
where the callable-being-assigned-to has a "Todo signature", which
should probably accept any left hand side callable/signature.
2025-04-28 16:40:35 +02:00
Dylan
1e8881f9af [refurb] Mark fix as safe for readlines-in-for (FURB129) (#17644)
This PR promotes the fix applicability of [readlines-in-for
(FURB129)](https://docs.astral.sh/ruff/rules/readlines-in-for/#readlines-in-for-furb129)
to always safe.

In the original PR (https://github.com/astral-sh/ruff/pull/9880), the
author marked the rule as unsafe because Ruff's type inference couldn't
quite guarantee that we had an `IOBase` object in hand. Some false
positives were recorded in the test fixture. However, before the PR was
merged, Charlie added the necessary type inference and the false
positives went away.

According to the [Python
documentation](https://docs.python.org/3/library/io.html#io.IOBase), I
believe this fix is safe for any proper implementation of `IOBase`:

>[IOBase](https://docs.python.org/3/library/io.html#io.IOBase) (and its
subclasses) supports the iterator protocol, meaning that an
[IOBase](https://docs.python.org/3/library/io.html#io.IOBase) object can
be iterated over yielding the lines in a stream. Lines are defined
slightly differently depending on whether the stream is a binary stream
(yielding bytes), or a text stream (yielding character strings). See
[readline()](https://docs.python.org/3/library/io.html#io.IOBase.readline)
below.

and then in the [documentation for
`readlines`](https://docs.python.org/3/library/io.html#io.IOBase.readlines):

>Read and return a list of lines from the stream. hint can be specified
to control the number of lines read: no more lines will be read if the
total size (in bytes/characters) of all lines so far exceeds hint. [...]
>Note that it’s already possible to iterate on file objects using for
line in file: ... without calling file.readlines().

I believe that a careful reading of our [versioning
policy](https://docs.astral.sh/ruff/versioning/#version-changes)
requires that this change be deferred to a minor release - but please
correct me if I'm wrong!
2025-04-28 09:39:55 -05:00
Dylan
152a0b6585 Collect preview lint behaviors in separate module (#17646)
This PR collects all behavior gated under preview into a new module
`ruff_linter::preview` that exposes functions like
`is_my_new_feature_enabled` - just as is done in the formatter crate.
2025-04-28 09:12:24 -05:00
Alex Waygood
1ad5015e19 Upgrade Salsa to a more recent commit (#17678) 2025-04-28 13:32:19 +01:00
David Peter
92f95ff494 [red-knot] TypedDict: No errors for introspection dunder attributes (#17677)
## Summary

Do not emit errors when accessing introspection dunder attributes such
as `__required_keys__` on `TypedDict`s.
2025-04-28 13:28:43 +02:00
Victor Hugo Gomes
ceb2bf1168 [flake8-pyi] Ensure Literal[None,] | Literal[None,] is not autofixed to None | None (PYI061) (#17659)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-28 12:23:29 +01:00
David Peter
f521358033 [red-knot] No errors for definitions of TypedDicts (#17674)
## Summary

Do not emit errors when defining `TypedDict`s:

```py
from typing_extensions import TypedDict

# No error here
class Person(TypedDict):
    name: str
    age: int | None

# No error for this alternative syntax
Message = TypedDict("Message", {"id": int, "content": str})
```

## Ecosystem analysis

* Removes ~ 450 false positives for `TypedDict` definitions.
* Changes a few diagnostic messages.
* Adds a few (< 10) false positives, for example:
  ```diff
+ error[lint:unresolved-attribute]
/tmp/mypy_primer/projects/hydra-zen/src/hydra_zen/structured_configs/_utils.py:262:5:
Type `Literal[DataclassOptions]` has no attribute `__required_keys__`
+ error[lint:unresolved-attribute]
/tmp/mypy_primer/projects/hydra-zen/src/hydra_zen/structured_configs/_utils.py:262:42:
Type `Literal[DataclassOptions]` has no attribute `__optional_keys__`
  ```
* New true positive

4f8263cd7f/corporate/lib/remote_billing_util.py (L155-L157)
  ```diff
+ error[lint:invalid-assignment]
/tmp/mypy_primer/projects/zulip/corporate/lib/remote_billing_util.py:155:5:
Object of type `RemoteBillingIdentityDict | LegacyServerIdentityDict |
None` is not assignable to `LegacyServerIdentityDict | None`
  ```

## Test Plan

New Markdown tests
2025-04-28 13:13:28 +02:00
renovate[bot]
74081032d9 Update actions/download-artifact digest to d3f86a1 (#17664)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-28 10:51:59 +00:00
Micha Reiser
dbc137c951 [red-knot] Use 101 exit code when there's at least one diagnostic with severity 'fatal' (#17640) 2025-04-28 10:03:14 +02:00
Victor Hugo Gomes
826b2c9ff3 [pycodestyle] Fix duplicated diagnostic in E712 (#17651) 2025-04-28 08:31:16 +01:00
jie211
a3e55cfd8f [airflow] fix typos AIR312 (#17673) 2025-04-28 08:31:41 +02:00
justin
d2246278e6 [red-knot] Don't ignore hidden files by default (#17655) 2025-04-28 08:21:11 +02:00
renovate[bot]
6bd1863bf0 Update pre-commit hook astral-sh/ruff-pre-commit to v0.11.7 (#17670)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:16:10 +02:00
renovate[bot]
97dc58fc77 Update docker/build-push-action digest to 14487ce (#17665)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:15:54 +02:00
renovate[bot]
53a9448fb5 Update taiki-e/install-action digest to ab3728c (#17666)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:15:01 +02:00
renovate[bot]
516291b693 Update dependency react-resizable-panels to v2.1.9 (#17667)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:10:24 +02:00
renovate[bot]
b09f00a4ef Update dependency ruff to v0.11.7 (#17668)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:09:50 +02:00
renovate[bot]
03065c245c Update dependency smol-toml to v1.3.4 (#17669)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:09:33 +02:00
renovate[bot]
b45598389d Update Rust crate jiff to v0.2.10 (#17671)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:09:10 +02:00
renovate[bot]
4729ff2bc8 Update Rust crate syn to v2.0.101 (#17672)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:08:41 +02:00
Micha Reiser
1bdb22c139 [red-knot] Fix offset handling in playground for 2-code-point UTF16 characters (#17520) 2025-04-27 11:44:55 +01:00
Micha Reiser
1c65e0ad25 Split SourceLocation into LineColumn and SourceLocation (#17587) 2025-04-27 11:27:33 +01:00
justin
4443f6653c [red-knot] Add --respect-ignore-files flag (#17645)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-27 10:55:41 +01:00
Vasco Schiavo
b0d475f353 [ruff] add fix safety section (RUF027) (#17485)
The PR add the `fix safety` section for rule `RUF027` (#15584 ).

Actually, I have an example of a false positive. Should I include it in
the` fix safety` section?

---------

Co-authored-by: Dylan <dylwil3@gmail.com>
2025-04-26 16:43:53 -05:00
Vasco Schiavo
b578a828ef [ruff] add fix safety section (RUF005) (#17484)
The PR add the `fix safety` section for rule `RUF005` (#15584 ).

---------

Co-authored-by: Dylan <dylwil3@gmail.com>
2025-04-26 16:43:02 -05:00
Vasco Schiavo
64ba39a385 [flynt] add fix safety section (FLY002) (#17496)
The PR add the fix safety section for rule `FLY002` (#15584 )

The motivation for the content of the fix safety section is given by the
following example

```python
foo = 1
bar = [2, 3]

try:
    result_join = " ".join((foo, bar))
    print(f"Join result: {result_join}")
except TypeError as e:
    print(f"Join error: {e}")
```

which print `Join error: sequence item 0: expected str instance, int
found`

But after the fix is applied, we have

```python
foo = 1
bar = [2, 3]

try:
    result_join = f"{foo} {bar}"
    print(f"Join result: {result_join}")
except TypeError as e:
    print(f"Join error: {e}")
```

which print `Join result: 1 [2, 3]`

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-04-26 16:00:01 +00:00
Hans
a4e225ee8a [flake8-async] Add fix safety section (ASYNC116) (#17497)
## Summary

This PR add the `fix safety` section for rule `ASYNC116` in
`long_sleep_not_forever.rs` for #15584

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-04-26 10:40:51 -05:00
Vasco Schiavo
45d0634b01 [pydocstyle] add fix safety section (D200) (#17502)
The PR add the fix safety section for rule `D200` (#15584 )
2025-04-26 08:59:05 -05:00
Vasco Schiavo
4bcf1778fa [ruff] add fix safety section (RUF057) (#17483)
The PR add the `fix safety` section for rule `RUF057` (#15584 )
2025-04-26 06:58:52 -05:00
Micha Reiser
6044f04137 Revert "[red-knot] Add --respect-ignore-files flag (#17569)" (#17642) 2025-04-26 10:30:50 +00:00
justin
2e95475f57 [red-knot] Add --respect-ignore-files flag (#17569)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-26 10:02:03 +00:00
Micha Reiser
cfa1505068 [red-knot] Fix CLI hang when a dependent query panics (#17631) 2025-04-26 06:28:45 +00:00
Dhruv Manilawala
0251679f87 [red-knot] Add new property tests for subtyping with "bottom" callable (#17635)
## Summary

I remember we discussed about adding this as a property tests so here I
am.

## Test Plan

```console
❯ QUICKCHECK_TESTS=10000000 cargo test --locked --release --package red_knot_python_semantic -- --ignored types::property_tests::stable::bottom_callable_is_subtype_of_all_fully_static_callable
    Finished `release` profile [optimized] target(s) in 0.10s
     Running unittests src/lib.rs (target/release/deps/red_knot_python_semantic-e41596ca2dbd0e98)
running 1 test
test types::property_tests::stable::bottom_callable_is_subtype_of_all_fully_static_callable ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 233 filtered out; finished in 30.91s
```
2025-04-26 03:58:13 +05:30
Douglas Creager
6ab32a7746 [red-knot] Create generic context for generic classes lazily (#17617)
As discussed today, this is needed to handle legacy generic classes
without having to infer the types of the class's explicit bases eagerly
at class construction time. Pulling this out into a separate PR so
there's a smaller diff to review.

This also makes our representation of generic classes and functions more
consistent — before, we had separate Rust types and enum variants for
generic/non-generic classes, but a single type for generic functions.
Now we each a single (respective) type for each.

There were very few places we were differentiation between generic and
non-generic _class literals_, and these are handled now by calling the
(salsa cached) `generic_context` _accessor function_.

Note that _`ClassType`_ is still an enum with distinct variants for
non-generic classes and specialized generic classes.
2025-04-25 14:10:03 -04:00
Andrew Gallant
bc0a5aa409 ruff_db: add tests for annotations with no ranges
... and fix the case where an annotation with a `Span` but no
`TextRange` or message gets completely dropped.
2025-04-25 13:25:20 -04:00
Wei Lee
aba21a5d47 [airflow] Extend AIR301 rule (#17598)
## Summary

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

Add "airflow.operators.python.get_current_context" →
"airflow.sdk.get_current_context" rule

## Test Plan

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

the test fixture has been updated accordingly
2025-04-25 12:49:32 -04:00
Wei Lee
b6281a8805 [airflow] update existing AIR302 rules with better suggestions (#17542)
## Summary

Even though the original suggestion works, they've been removed in later
version and is no longer the best practices.

e.g., many sql realted operators have been removed and are now suggested
to use SQLExecuteQueryOperator instead

## Test Plan

The existing test fixtures have been updated
2025-04-25 12:44:28 -04:00
Andrew Gallant
049280a3bc red_knot_project: sort diagnostics from checking files
Previously, we could iterate over files in an unspecified order (via
`HashSet` iteration) and we could accumulate diagnostics from files in
an unspecified order (via parallelism).

Here, we change the status quo so that diagnostics collected from files
are sorted after checking is complete. For now, we sort by severity
(with higher severity diagnostics appearing first) and then by
diagnostic ID to give a stable ordering.

I'm not sure if this is the best ordering.
2025-04-25 12:38:31 -04:00
Carl Meyer
fa88989ef0 [red-knot] fix detecting a metaclass on a not-explicitly-specialized generic base (#17621)
## Summary

After https://github.com/astral-sh/ruff/pull/17620 (which this PR is
based on), I was looking at other call sites of `Type::into_class_type`,
and I began to feel that _all_ of them were currently buggy due to
silently skipping unspecialized generic class literal types (though in
some cases the bug hadn't shown up yet because we don't understand
legacy generic classes from typeshed), and in every case they would be
better off if an unspecialized generic class literal were implicitly
specialized with the default specialization (which is the usual Python
typing semantics for an unspecialized reference to a generic class),
instead of silently skipped.

So I changed the method to implicitly apply the default specialization,
and added a test that previously failed for detecting metaclasses on an
unspecialized generic base.

I also renamed the method to `to_class_type`, because I feel we have a
strong naming convention where `Type::into_foo` is always a trivial
`const fn` that simply returns `Some()` if the type is of variant `Foo`
and `None` otherwise. Even the existing method (with it handling both
`GenericAlias` and `ClassLiteral`, and distinguishing kinds of
`ClassLiteral`) was stretching this convention, and the new version
definitely breaks that envelope.

## Test Plan

Added a test that failed before this PR.
2025-04-25 06:55:54 -07:00
Carl Meyer
4c3f389598 [red-knot] fix inheritance-cycle detection for generic classes (#17620)
## Summary

The `ClassLiteralType::inheritance_cycle` method is intended to detect
inheritance cycles that would result in cyclic MROs, emit a diagnostic,
and skip actually trying to create the cyclic MRO, falling back to an
"error" MRO instead with just `Unknown` and `object`.

This method didn't work properly for generic classes. It used
`fully_static_explicit_bases`, which filter-maps `explicit_bases` over
`Type::into_class_type`, which returns `None` for an unspecialized
generic class literal. So in a case like `class C[T](C): ...`, because
the explicit base is an unspecialized generic, we just skipped it, and
failed to detect the class as cyclically defined.

Instead, iterate directly over all `explicit_bases`, and explicitly
handle both the specialized (`GenericAlias`) and unspecialized
(`ClassLiteral`) cases, so that we check all bases and correctly detect
cyclic inheritance.

## Test Plan

Added mdtests.
2025-04-25 06:55:00 -07:00
Brent Westbrook
6d3b1d13d6 [pylint] Detect global declarations in module scope (PLE0118) (#17411)
Summary
--

While going through the syntax errors in [this comment], I was surprised
to see the error `name 'x' is assigned to before global declaration`,
which corresponds to [load-before-global-declaration (PLE0118)] and has
also been reimplemented as a syntax error (#17135). However, it looks
like neither of the implementations consider `global` declarations in
the top-level module scope, which is a syntax error in CPython:

```python
# try.py
x = None
global x
```

```shell
> python -m compileall -f try.py
Compiling 'try.py'...
***   File "try.py", line 2
    global x
    ^^^^^^^^
SyntaxError: name 'x' is assigned to before global declaration
```

I'm not sure this is the best or most elegant solution, but it was a
quick fix that passed all of our tests.

Test Plan
--

New PLE0118 test case.

[this comment]:
https://github.com/astral-sh/ruff/issues/7633#issuecomment-1740424031
[load-before-global-declaration (PLE0118)]:
https://docs.astral.sh/ruff/rules/load-before-global-declaration/#load-before-global-declaration-ple0118
2025-04-25 08:37:16 -04:00
Max Mynter
3f84e75e20 Add Semantic Error Test for LateFutureImport (#17612)
Adresses a question in #17526.

## Summary
Adds a syntax error test for `__future__` import not at top of file. 

## Question: 
Is this a redundant with
8d2c79276d/crates/ruff_linter/resources/test/fixtures/pyflakes/F404_0.py (L1-L8)
and
8d2c79276d/crates/ruff_linter/resources/test/fixtures/pyflakes/F404_1.py (L1-L5)

which test pyflake `F404`?
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan
This is a test
<!-- How was it tested? -->
2025-04-25 08:32:57 -04:00
Carl Meyer
afc18ff1a1 [red-knot] change TypeVarInstance to be interned, not tracked (#17616)
## Summary

Tracked structs have some issues with fixpoint iteration in Salsa, and
there's not actually any need for this to be tracked, it should be
interned like most of our type structs.

The removed comment was probably never correct (in that we could have
disambiguated sufficiently), and is definitely not relevant now that
`TypeVarInstance` also holds its `Definition`.

## Test Plan

Existing tests.
2025-04-24 14:52:25 -07:00
Dhruv Manilawala
f1a539dac6 [red-knot] Special case @final, @override (#17608)
## Summary

This PR adds special-casing for `@final` and `@override` decorator for a
similar reason as https://github.com/astral-sh/ruff/pull/17591 to
support the invalid overload check.

Both `final` and `override` are identity functions which can be removed
once `TypeVar` support is added.
2025-04-25 03:15:23 +05:30
Carl Meyer
ef0343189c [red-knot] add TODO comment in specialization code (#17615)
## Summary

As promised, this just adds a TODO comment to document something we
discussed today that should probably be improved at some point, but
isn't a priority right now (since it's an issue that in practice would
only affect generic classes with both `__init__` and `__new__` methods,
where some typevar is bound to `Unknown` in one and to some other type
in another.)
2025-04-24 14:41:19 -07:00
Vasco Schiavo
4eecc40110 [semantic-syntax-errors] test for LoadBeforeGlobalDeclaration - ruff linter (#17592)
Hey @ntBre 

just one easy case to see if I understood the issue #17526 

Let me know if is this what you had in mind.
2025-04-24 16:14:33 -04:00
Abhijeet Prasad Bodas
cf59cee928 [syntax-errors] nonlocal declaration at module level (#17559)
## Summary

Part of #17412

Add a new compile-time syntax error for detecting `nonlocal`
declarations at a module level.

## Test Plan

- Added new inline tests for the syntax error
- Updated existing tests for `nonlocal` statement parsing to be inside a
function scope

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-04-24 16:11:46 -04:00
Wei Lee
538393d1f3 [airflow] Apply auto fix to cases where name has been changed in Airflow 3 (AIR311) (#17571)
## Summary

Apply auto fix to cases where the name has been changed in Airflow 3
(`AIR311`)

## Test Plan

The test features has been updated
2025-04-24 15:48:54 -04:00
Brent Westbrook
92ecfc908b [syntax-errors] Make async-comprehension-in-sync-comprehension more specific (#17460)
## Summary

While adding semantic error support to red-knot, I noticed duplicate
diagnostics for code like this:

```py
# error: [invalid-syntax] "cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.9 (syntax was added in 3.11)"
# error: [invalid-syntax] "`asynchronous comprehension` outside of an asynchronous function"
 [reveal_type(x) async for x in AsyncIterable()]
```

Beyond the duplication, the first error message doesn't make much sense
because this syntax is _not_ allowed on Python 3.11 either.

To fix this, this PR renames the
`async-comprehension-outside-async-function` semantic syntax error to
`async-comprehension-in-sync-comprehension` and fixes the rule to avoid
applying outside of sync comprehensions at all.

## Test Plan

New linter test demonstrating the false positive. The mdtests from my red-knot 
PR also reflect this change.
2025-04-24 15:45:54 -04:00
Dylan
f7b48510b5 Bump 0.11.7 (#17613) 2025-04-24 13:06:38 -05:00
Dhruv Manilawala
9937064761 [red-knot] Use iterative approach to collect overloads (#17607)
## Summary

This PR updates the `to_overloaded` method to use an iterative approach
instead of a recursive one.

Refer to
https://github.com/astral-sh/ruff/pull/17585#discussion_r2056804587 for
context.

The main benefit here is that it avoids calling the `to_overloaded`
function in a recursive manner which is a salsa query. So, this is a bit
hand wavy but we should also see less memory used because the cache will
only contain a single entry which should be the entire overload chain.
Previously, the recursive approach would mean that each of the function
involved in an overload chain would have a cache entry. This reduce in
memory shouldn't be too much and I haven't looked at the actual data for
it.

## Test Plan

Existing test cases should pass.
2025-04-24 22:23:50 +05:30
Andrew Gallant
8d2c79276d red_knot_python_semantic: avoid Rust's screaming snake case convention in mdtest 2025-04-24 11:43:01 -04:00
Andrew Gallant
0f47810768 red_knot_python_semantic: improve diagnostics for unsupported boolean conversions
This mostly only improves things for incorrect arguments and for an
incorrect return type. It doesn't do much to improve the case where
`__bool__` isn't callable and leaves the union/other cases untouched
completely.

I picked this one because, at first glance, this _looked_ like a lower
hanging fruit. The conceptual improvement here is pretty
straight-forward: add annotations for relevant data. But it took me a
bit to figure out how to connect all of the pieces.
2025-04-24 11:43:01 -04:00
Andrew Gallant
eb1d2518c1 red_knot_python_semantic: add "return type span" helper method
This is very similar to querying for the span of a parameter
in a function definition, but instead we look for the span of
a return type.
2025-04-24 11:43:01 -04:00
Andrew Gallant
a45a0a92bd red_knot_python_semantic: move parameter span helper method
I wanted to use this method in other places, so I moved it
to what appears to be a God-type. I also made it slightly
more versatile: callers can ask for the entire parameter list
by omitting a specific parameter index.
2025-04-24 11:43:01 -04:00
Andrew Gallant
43bd043755 ruff_db: add a From impl for FileRange to Span
These types are almost equivalent. The only difference
is that a `Span`'s range is optional.
2025-04-24 11:43:01 -04:00
Andrew Gallant
9a54ee3a1c red_knot_python_semantic: add snapshot tests for unsupported boolean conversions
This just captures the status quo before we try to improve them.
2025-04-24 11:43:01 -04:00
Carl Meyer
25c3be51d2 [red-knot] simplify != narrowing (#17610)
## Summary

Follow-up from review comment in
https://github.com/astral-sh/ruff/pull/17567#discussion_r2058649527

## Test Plan

Existing tests.
2025-04-24 15:11:45 +00:00
Matthew Mckee
e71f3ed2c5 [red-knot] Update == and != narrowing (#17567)
## Summary

Historically we have avoided narrowing on `==` tests because in many
cases it's unsound, since subclasses of a type could compare equal to
who-knows-what. But there are a lot of types (literals and unions of
them, as well as some known instances like `None` -- single-valued
types) whose `__eq__` behavior we know, and which we can safely narrow
away based on equality comparisons.

This PR implements equality narrowing in the cases where it is sound.
The most elegant way to do this (and the way that is most in-line with
our approach up until now) would be to introduce new Type variants
`NeverEqualTo[...]` and `AlwaysEqualTo[...]`, and then implement all
type relations for those variants, narrow by intersection, and let union
and intersection simplification sort it all out. This is analogous to
our existing handling for `AlwaysFalse` and `AlwaysTrue`.

But I'm reluctant to add new `Type` variants for this, mostly because
they could end up un-simplified in some types and make types even more
complex. So let's try this approach, where we handle more of the
narrowing logic as a special case.

## Test Plan

Updated and added tests.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
Co-authored-by: Carl Meyer <carl@oddbird.net>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-24 07:56:39 -07:00
Carl Meyer
ac6219ec38 [red-knot] fix collapsing literal and its negation to object (#17605)
## Summary

Another follow-up to the unions-of-large-literals optimization. Restore
the behavior that e.g. `Literal[""] | ~Literal[""]` collapses to
`object`.

## Test Plan

Added mdtests.
2025-04-24 13:55:05 +00:00
Alex Waygood
e93fa7062c [red-knot] Add more tests for protocols (#17603) 2025-04-24 13:11:31 +01:00
Alex Waygood
21fd28d713 [red-knot] Ban direct instantiations of Protocol classes (#17597) 2025-04-24 09:31:35 +00:00
Max Mynter
a01f25107a [pyupgrade] Preserve parenthesis when fixing native literals containing newlines (UP018) (#17220) 2025-04-24 08:48:02 +02:00
camper42
48a85c4ed4 [airflow] fix typos (AIR302, AIR312) (#17574) 2025-04-24 08:06:32 +02:00
Dhruv Manilawala
1796ca97d5 [red-knot] Special case @abstractmethod for function type (#17591)
## Summary

This is required because otherwise the inferred type is not going to be
`Type::FunctionLiteral` but a todo type because we don't recognize
`TypeVar` yet:

```py
_FuncT = TypeVar("_FuncT", bound=Callable[..., Any])

def abstractmethod(funcobj: _FuncT) -> _FuncT: ...
```

This is mainly required to raise diagnostic when only some (and not all)
`@overload`-ed functions are decorated with `@abstractmethod`.
2025-04-24 03:54:52 +05:30
Alex Waygood
e897f37911 [red-knot] Emit diagnostics for isinstance() and issubclass() calls where a non-runtime-checkable protocol is the second argument (#17561) 2025-04-23 21:40:23 +00:00
Alex Waygood
00e73dc331 [red-knot] Infer the members of a protocol class (#17556) 2025-04-23 21:36:12 +00:00
Dhruv Manilawala
7b6222700b [red-knot] Add FunctionType::to_overloaded (#17585)
## Summary

This PR adds a new method `FunctionType::to_overloaded` which converts a
`FunctionType` into an `OverloadedFunction` which contains all the
`@overload`-ed `FunctionType` and the implementation `FunctionType` if
it exists.

There's a big caveat here (it's the way overloads work) which is that
this method can only "see" all the overloads that comes _before_ itself.
Consider the following example:

```py
from typing import overload

@overload
def foo() -> None: ...
@overload
def foo(x: int) -> int: ...
def foo(x: int | None) -> int | None:
	return x
```

Here, when the `to_overloaded` method is invoked on the
1. first `foo` definition, it would only contain a single overload which
is itself and no implementation.
2. second `foo` definition, it would contain both overloads and still no
implementation
3. third `foo` definition, it would contain both overloads and the
implementation which is itself

### Usages

This method will be used in the logic for checking invalid overload
usages. It can also be used for #17541.

## Test Plan

Make sure that existing tests pass.
2025-04-24 02:57:05 +05:30
Brent Westbrook
bfc1650198 [red-knot] Add mdtests for global statement (#17563)
## Summary

This is a first step toward `global` support in red-knot (#15385). I
went through all the matches for `global` in the `mypy/test-data`
directory, but I didn't find anything too interesting that wasn't
already covered by @carljm's suggestions on Discord. I still pulled in a
couple of cases for a little extra variety. I also included a section
from the
[PLE0118](https://docs.astral.sh/ruff/rules/load-before-global-declaration/)
tests in ruff that will become syntax errors once #17463 is merged and
we handle `global` statements.

I don't think I figured out how to use `@Todo` properly, so please let
me know if I need to fix that. I hope this is a good start to the test
suite otherwise.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-23 17:18:42 -04:00
Brent Westbrook
d5410ef9fe [syntax-errors] Make duplicate parameter names a semantic error (#17131)
Status
--

This is a pretty minor change, but it was breaking a red-knot mdtest
until #17463 landed. Now this should close #11934 as the last syntax
error being tracked there!

Summary
--

Moves `Parser::validate_parameters` to
`SemanticSyntaxChecker::duplicate_parameter_name`.

Test Plan
--

Existing tests, with `## Errors` replaced with `## Semantic Syntax
Errors`.
2025-04-23 15:45:51 -04:00
Douglas Creager
9db63fc58c [red-knot] Handle generic constructors of generic classes (#17552)
We now handle generic constructor methods on generic classes correctly:

```py
class C[T]:
    def __init__[S](self, t: T, s: S): ...

x = C(1, "str")
```

Here, constructing `C` requires us to infer a specialization for the
generic contexts of `C` and `__init__` at the same time.

At first I thought I would need to track the full stack of nested
generic contexts here (since the `[S]` context is nested within the
`[T]` context). But I think this is the only way that we might need to
specialize more than one generic context at once — in all other cases, a
containing generic context must be specialized before we get to a nested
one, and so we can just special-case this.

While we're here, we also construct the generic context for a generic
function lazily, when its signature is accessed, instead of eagerly when
inferring the function body.
2025-04-23 15:06:18 -04:00
David Peter
61e73481fe [red-knot] Assignability of class instances to Callable (#17590)
## Summary

Model assignability of class instances with a `__call__` method to
`Callable` types. This should solve some false positives related to
`functools.partial` (yes, 1098 fewer diagnostics!).

Reference:
https://github.com/astral-sh/ruff/issues/17343#issuecomment-2824618483

## Test Plan

New Markdown tests.
2025-04-23 20:34:13 +02:00
David Peter
e170fe493d [red-knot] Trust all symbols in stub files (#17588)
## Summary

*Generally* trust undeclared symbols in stubs, not just at the module
level.

Follow-up on the discussion
[here](https://github.com/astral-sh/ruff/pull/17577#discussion_r2055945909).

## Test Plan

New Markdown test.
2025-04-23 20:07:29 +02:00
David Peter
e91e2f49db [red-knot] Trust module-level undeclared symbols in stubs (#17577)
## Summary

Many symbols in typeshed are defined without being declared. For
example:
```pyi
# builtins:
IOError = OSError

# types
LambdaType = FunctionType
NotImplementedType = _NotImplementedType

# typing
Text = str

# random
uniform = _inst.uniform

# optparse
make_option = Option

# all over the place:
_T = TypeVar("_T")
```

Here, we introduce a change that skips widening the public type of these
symbols (by unioning with `Unknown`).

fixes #17032

## Ecosystem analysis

This is difficult to analyze in detail, but I went over most changes and
it looks very favorable to me overall. The diff on the overall numbers
is:
```
errors: 1287 -> 859 (reduction by 428)
warnings: 45 -> 59 (increase by 14)
```

### Removed false positives

`invalid-base` examples:

```diff
- error[lint:invalid-base] /tmp/mypy_primer/projects/pip/src/pip/_vendor/rich/console.py:548:27: Invalid class base with type `Unknown | Literal[_local]` (all bases must be a class, `Any`, `Unknown` or `Todo`)
- error[lint:invalid-base] /tmp/mypy_primer/projects/tornado/tornado/iostream.py:84:25: Invalid class base with type `Unknown | Literal[OSError]` (all bases must be a class, `Any`, `Unknown` or `Todo`)
- error[lint:invalid-base] /tmp/mypy_primer/projects/mitmproxy/test/conftest.py:35:40: Invalid class base with type `Unknown | Literal[_UnixDefaultEventLoopPolicy]` (all bases must be a class, `Any`, `Unknown` or `Todo`)
```

`invalid-exception-caught` examples:

```diff
- error[lint:invalid-exception-caught] /tmp/mypy_primer/projects/cloud-init/cloudinit/cmd/status.py:334:16: Cannot catch object of type `Literal[ProcessExecutionError]` in an exception handler (must be a `BaseException` subclass or a tuple of `BaseException` subclasses)
- error[lint:invalid-exception-caught] /tmp/mypy_primer/projects/jinja/src/jinja2/loaders.py:537:16: Cannot catch object of type `Literal[TemplateNotFound]` in an exception handler (must be a `BaseException` subclass or a tuple of `BaseException` subclasses)
```

`unresolved-reference` examples


7a0265d36e/cloudinit/handlers/jinja_template.py (L120-L123)
(we now understand the `isinstance` narrowing)

```diff
- error[lint:unresolved-attribute] /tmp/mypy_primer/projects/cloud-init/cloudinit/handlers/jinja_template.py:123:16: Type `Exception` has no attribute `errno`
```

`unknown-argument` examples


https://github.com/hauntsaninja/boostedblob/blob/master/boostedblob/request.py#L53

```diff
- error[lint:unknown-argument] /tmp/mypy_primer/projects/boostedblob/boostedblob/request.py:53:17: Argument `connect` does not match any known parameter of bound method `__init__`
```

`unknown-argument`

There are a lot of `__init__`-related changes because we now understand
[`@attr.s`](3d42a6978a/src/attr/__init__.pyi (L387))
as a `@dataclass_transform` annotated symbol. For example:

```diff
- error[lint:unknown-argument] /tmp/mypy_primer/projects/attrs/tests/test_hooks.py:72:18: Argument `x` does not match any known parameter of bound method `__init__`
```

### New false positives

This can happen if a symbol that previously was inferred as `X |
Unknown` was assigned-to, but we don't yet understand the assignability
to `X`:


https://github.com/strawberry-graphql/strawberry/blob/main/strawberry/exceptions/handler.py#L90

```diff
+ error[lint:invalid-assignment] /tmp/mypy_primer/projects/strawberry/strawberry/exceptions/handler.py:90:9: Object of type `def strawberry_threading_exception_handler(args: tuple[type[BaseException], BaseException | None, TracebackType | None, Thread | None]) -> None` is not assignable to attribute `excepthook` of type `(_ExceptHookArgs, /) -> Any`
```

### New true positives


6bbb5519fe/tests/tracer/test_span.py (L714)

```diff
+ error[lint:invalid-argument-type] /tmp/mypy_primer/projects/dd-trace-py/tests/tracer/test_span.py:714:33: Argument to this function is incorrect: Expected `str`, found `Literal[b"\xf0\x9f\xa4\x94"]`
```

### Changed diagnostics

A lot of changed diagnostics because we now show `@Todo(Support for
`typing.TypeVar` instances in type expressions)` instead of `Unknown`
for all kinds of symbols that used a `_T = TypeVar("_T")` as a type. One
prominent example is the `list.__getitem__` method:

`builtins.pyi`:
```pyi
_T = TypeVar("_T")  # previously `TypeVar | Unknown`, now just `TypeVar`

# …

class list(MutableSequence[_T]):
    # …
    @overload
    def __getitem__(self, i: SupportsIndex, /) -> _T: ...
    # …
```

which causes this change in diagnostics:
```py
xs = [1, 2]
reveal_type(xs[0])  # previously `Unknown`, now `@Todo(Support for `typing.TypeVar` instances in type expressions)`
```

## Test Plan

Updated Markdown tests
2025-04-23 19:31:14 +02:00
Wei Lee
b537552927 [airflow] Apply auto fixes to cases where the names have changed in Airflow 3 (AIR301) (#17355)
## Summary

Apply auto fixes to cases where the names have changed in Airflow 3

## Test Plan

Add `AIR301_names_fix.py` and `AIR301_provider_names_fix.py` test fixtures
2025-04-23 12:43:41 -04:00
Navdeep K
5a719f2d60 [pycodestyle] Auto-fix redundant boolean comparison (E712) (#17090)
This pull request fixes https://github.com/astral-sh/ruff/issues/17014

changes this
```python
from __future__ import annotations

flag1 = True
flag2 = True

if flag1 == True or flag2 == True:
    pass

if flag1 == False and flag2 == False:
    pass

flag3 = True
if flag1 == flag3 and (flag2 == False or flag3 == True):  # Should become: if flag1==flag3 and (not flag2 or flag3)
    pass

if flag1 == True and (flag2 == False or not flag3 == True):  # Should become: if flag1 and (not flag2 or not flag3)
    pass

if flag1 != True and (flag2 != False or not flag3 == True):  # Should become: if not flag1 and (flag2 or not flag3)
    pass


flag = True
while flag == True:  # Should become: while flag
    flag = False

flag = True
x = 5
if flag == True and x > 0:  # Should become: if flag and x > 0
    print("ok")

flag = True
result = "yes" if flag == True else "no"  # Should become: result = "yes" if flag else "no"

x = flag == True < 5

x = (flag == True) == False < 5
```

to this 
```python
from __future__ import annotations

flag1 = True
flag2 = True

if flag1 or flag2:
    pass

if not flag1 and not flag2:
    pass

flag3 = True
if flag1 == flag3 and (not flag2 or flag3):  # Should become: if flag1 == flag3 and (not flag2 or flag3)
    pass

if flag1 and (not flag2 or not flag3):  # Should become: if flag1 and (not flag2 or not flag3)
    pass

if not flag1 and (flag2 or not flag3):  # Should become: if not flag1 and (flag2 or not flag3)
    pass


flag = True
while flag:  # Should become: while flag
    flag = False

flag = True
x = 5
if flag and x > 0:  # Should become: if flag and x > 0
    print("ok")

flag = True
result = "yes" if flag else "no"  # Should become: result = "yes" if flag else "no"

x = flag is True < 5

x = (flag) is False < 5
```

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-04-23 11:49:20 -04:00
Brent Westbrook
e7f38fe74b [red-knot] Detect semantic syntax errors (#17463)
Summary
--

This PR extends semantic syntax error detection to red-knot. The main
changes here are:

1. Adding `SemanticSyntaxChecker` and `Vec<SemanticSyntaxError>` fields
to the `SemanticIndexBuilder`
2. Calling `SemanticSyntaxChecker::visit_stmt` and `visit_expr` in the
`SemanticIndexBuilder`'s `visit_stmt` and `visit_expr` methods
3. Implementing `SemanticSyntaxContext` for `SemanticIndexBuilder`
4. Adding new mdtests to test the context implementation and show
diagnostics

(3) is definitely the trickiest and required (I think) a minor addition
to the `SemanticIndexBuilder`. I tried to look around for existing code
performing the necessary checks, but I definitely could have missed
something or misused the existing code even when I found it.

There's still one TODO around `global` statement handling. I don't think
there's an existing way to look this up, but I'm happy to work on that
here or in a separate PR. This currently only affects detection of one
error (`LoadBeforeGlobalDeclaration` or
[PLE0118](https://docs.astral.sh/ruff/rules/load-before-global-declaration/)
in ruff), so it's not too big of a problem even if we leave the TODO.

Test Plan
--

New mdtests, as well as new errors for existing mdtests

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-23 09:52:58 -04:00
Micha Reiser
624f5c6c22 Fix stale diagnostics in Ruff playground (#17583) 2025-04-23 15:47:54 +02:00
Micha Reiser
8abf93f5fb [red-knot] Early return from project.is_file_open for vendored files (#17580) 2025-04-23 15:32:41 +02:00
Micha Reiser
5407249467 [red-knot] Make BoundMethodType a salsa interned (#17581) 2025-04-23 15:11:20 +02:00
Alex Waygood
0a1f9d090e [red-knot] Emit a diagnostic if a non-protocol is passed to get_protocol_members (#17551) 2025-04-23 10:13:20 +00:00
Alex Waygood
f9c7908bb7 [red-knot] Add more tests for protocol members (#17550) 2025-04-23 11:03:52 +01:00
David Peter
99fa850e53 [red-knot] Assignability for subclasses of Any and Unknown (#17557)
## Summary

Allow (instances of) subclasses of `Any` and `Unknown` to be assignable
to (instances of) other classes, unless they are final. This allows us
to get rid of ~1000 false positives, mostly when mock-objects like
`unittest.mock.MagicMock` are assigned to various targets.

## Test Plan

Adapted and new Markdown tests.
2025-04-23 11:37:30 +02:00
David Peter
a241321735 [red-knot] mypy_primer: add strawberry, print compilation errors to stderr (#17578)
## Summary

mypy_primer changes included here:
ebaa9fd27b..4c22d192a4

- Add strawberry as a `good.txt` project (was previously included in our
fork)
- Print Red Knot compilation errors to stderr (thanks @MichaReiser)
2025-04-23 10:57:11 +02:00
David Peter
b1b8ca3bcd [red-knot] GenericAlias instances as a base class (#17575)
## Summary

We currently emit a diagnostic for code like the following:
```py
from typing import Any

# error: Invalid class base with type `GenericAlias` (all bases must be a class, `Any`, `Unknown` or `Todo`)
class C(tuple[Any, ...]): ...
```

The changeset here silences this diagnostic by recognizing instances of
`GenericAlias` in `ClassBase::try_from_type`, and inferring a `@Todo`
type for them. This is a change in preparation for #17557, because `C`
previously had `Unknown` in its MRO …
```py
reveal_type(C.__mro__)  # tuple[Literal[C], Unknown, Literal[object]]
```
… which would cause us to think that `C` is assignable to everything.

The changeset also removes some false positive `invalid-base`
diagnostics across the ecosystem.

## Test Plan

Updated Markdown tests.
2025-04-23 10:39:10 +02:00
Shaygan Hooshyari
3fae176345 Remove redundant type_to_visitor_function entries (#17564) 2025-04-23 09:27:00 +02:00
David Salvisberg
f36262d970 Fixes how the checker visits typing.cast/typing.NewType arguments (#17538) 2025-04-23 09:26:00 +02:00
Matthew Mckee
e45f23b0ec [red-knot] Class literal __new__ function callable subtyping (#17533)
## Summary

From
https://typing.python.org/en/latest/spec/constructors.html#converting-a-constructor-to-callable

this covers step 2 and partially step 3 (always respecting the
`__new__`)

## Test Plan

Update is_subtype_of.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-22 22:40:33 -07:00
Matthew Mckee
aa46047649 [red-knot] Surround intersections with () in potentially ambiguous contexts (#17568)
## Summary

Add parentheses to multi-element intersections, when displayed in a
context that's otherwise potentially ambiguous.

## Test Plan

Update mdtest files

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-23 04:18:20 +00:00
Brent Westbrook
f9da115fdc [minor] Delete outdated TODO comment (#17565)
Summary
--

Delete a TODO I left that was handled in the last minor release
(#16125).

Test Plan
--

N/a
2025-04-22 20:23:08 +00:00
Carl Meyer
3872d57463 [red-knot] add regression test for fixed cycle panic (#17535)
Add a regression test for the cycle documented in
https://github.com/astral-sh/ruff/issues/14767, which no longer panics
(or even causes a cycle at all.)

Fixes https://github.com/astral-sh/ruff/issues/14767
2025-04-22 09:20:53 -07:00
Carl Meyer
27ada26ddb [red-knot] fix unions of literals, again (#17534)
## Summary

#17451 was incomplete. `AlwaysFalsy` and `AlwaysTruthy` are not the only
two types that are super-types of some literals (of a given kind) and
not others. That set also includes intersections containing
`AlwaysTruthy` or `AlwaysFalsy`, and intersections containing literal
types of the same kind. Cover these cases as well.

Fixes #17478.

## Test Plan

Added mdtests.

`QUICKCHECK_TESTS=1000000 cargo test -p red_knot_python_semantic --
--ignored types::property_tests::stable` failed on both
`all_fully_static_type_pairs_are_subtypes_of_their_union` and
`all_type_pairs_are_assignable_to_their_union` prior to this PR, passes
after it.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-22 16:12:52 +00:00
Andrew Gallant
810478f68b red_knot_python_semantic: remove last vestige of old diagnostics! 2025-04-22 12:08:03 -04:00
Andrew Gallant
17f799424a red_knot_python_semantic: migrate types to new diagnostics 2025-04-22 12:08:03 -04:00
Andrew Gallant
c12640fea8 red_knot_python_semantic: migrate types/diagnostic to new diagnostics 2025-04-22 12:08:03 -04:00
Andrew Gallant
3796b13ea2 red_knot_python_semantic: migrate types/call/bind to new diagnostics 2025-04-22 12:08:03 -04:00
Andrew Gallant
ad5a659f29 red_knot_python_semantic: migrate types/string_annotation to new diagnostics 2025-04-22 12:08:03 -04:00
Andrew Gallant
27a377f077 red_knot_python_semantic: migrate types/infer to new diagnostic model
I gave up trying to do this one lint at a time and just (mostly)
mechanically translated this entire file in one go.

Generally the messages stay the same (with most moving from an
annotation message to the diagnostic's main message). I added a couple
of `info` sub-diagnostics where it seemed to be the obvious intent.
2025-04-22 12:08:03 -04:00
Andrew Gallant
b8b624d890 red_knot_python_semantic: migrate INVALID_ASSIGNMENT for inference
This finishes the migration for the `INVALID_ASSIGNMENT` lint.

Notice how I'm steadily losing steam in terms of actually improving the
diagnostics. This change is more mechanical, because taking the time to
revamp every diagnostic is a ton of effort. Probably future migrations
will be similar unless there are easy pickings.
2025-04-22 12:08:03 -04:00
Andrew Gallant
6dc2d29966 red_knot_python_semantic: migrate INVALID_ASSIGNMENT for shadowing
We mostly keep things the same here, but the message has been moved from
the annotation to the diagnostic's top-line message. I think this is
perhaps a little worse, but some bigger improvements could be made here.
Indeed, we could perhaps even add a "fix" here.
2025-04-22 12:08:03 -04:00
Andrew Gallant
890ba725d9 red_knot_python_semantic: migrate INVALID_ASSIGNMENT for unpacking
This moves all INVALID_ASSIGNMENT lints related to unpacking over to the new
diagnostic model.

While we're here, we improve the diagnostic a bit by adding a secondary
annotation covering where the value is. We also split apart the original
singular message into one message for the diagnostic and the "expected
versus got" into annotation messages.
2025-04-22 12:08:03 -04:00
Andrew Gallant
298f43f34e red_knot_python_semantic: add invalid assignment diagnostic snapshot
This tests the diagnostic rendering of a case that wasn't previously
covered by snapshots: when unpacking fails because there are too few
values, but where the left hand side can tolerate "N or more." In the
code, this is a distinct diagnostic, so we capture it here.

(Sorry about the diff here, but it made sense to rename the other
sections and that changes the name of the snapshot file.)
2025-04-22 12:08:03 -04:00
Andrew Gallant
3b300559ab red_knot_python_semantic: remove #[must_use] on diagnostic guard constructor
I believe this was an artifact of an older iteration of the diagnostic
reporting API. But this is strictly not necessary now, and indeed, might
even be annoying. It is okay, but perhaps looks a little odd, to do
`builder.into_diagnostic("...")` if you don't want to add anything else
to the diagnostic.
2025-04-22 12:08:03 -04:00
Andrew Gallant
14f71ceb83 red_knot_python_semantic: add helper method for creating a secondary annotation
I suspect this will be used pretty frequently (I wanted it
immediately). And more practically, this avoids needing to
import `Annotation` to create it.
2025-04-22 12:08:03 -04:00
David Peter
4775719abf [red-knot] mypy_primer: larger depot runner (#17547)
## Summary

A switch from 16 to 32 cores reduces the `mypy_primer` CI time from
3.5-4 min to 2.5-3 min. There's also a 64-core runner, but the 4 min ->
3 min change when doubling the cores once does suggest that it doesn't
parallelize *this* well.
2025-04-22 17:36:13 +02:00
Alex Waygood
6bdffc3cbf [red-knot] Consider two instance types disjoint if the underlying classes have disjoint metaclasses (#17545) 2025-04-22 15:14:10 +01:00
Aria Desires
775815ef22 Update cargo-dist and apply config improvements (#17453) 2025-04-22 10:05:15 -04:00
Carl Meyer
0299a52fb1 [red-knot] Add list of failing/slow ecosystem projects (#17474)
## Summary

I ran red-knot on every project in mypy-primer. I moved every project
where red-knot ran to completion (fast enough, and mypy-primer could
handle its output) into `good.txt`, so it will run in our CI.

The remaining projects I left listed in `bad.txt`, with a comment
summarizing the failure mode (a few don't fail, they are just slow -- on
a debug build, at least -- or output too many diagnostics for
mypy-primer to handle.)

We will now run CI on 109 projects; 34 are left in `bad.txt`.

## Test Plan

CI on this PR!

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-04-22 14:15:36 +02:00
David Peter
83d5ad8983 [red-knot] mypy_primer: extend ecosystem checks (#17544)
## Summary

Takes the `good.txt` changes from #17474, and removes the following
projects:
- arrow (not part of mypy_primer upstream)
- freqtrade, hydpy, ibis, pandera, xarray (saw panics locally, all
related to try_metaclass cycles)

Increases the mypy_primer CI run time to ~4 min.

## Test Plan

Three successful CI runs.
2025-04-22 13:39:42 +02:00
Alex Waygood
ae6fde152c [red-knot] Move InstanceType to its own submodule (#17525) 2025-04-22 11:34:46 +00:00
David Peter
d2b20f7367 [red-knot] mypy_primer: capture backtraces (#17543)
## Summary

`mypy_primer` is not deterministic (we pin `mypy_primer` itself, but
projects change over time and we just pull in the latest version). We've
also seen occasional panics being caught in `mypy_primer` runs, so this
is trying to make these CI failures more helpful.
2025-04-22 12:05:57 +02:00
David Peter
38a3b056e3 [red-knot] mypy_primer: Use upstream repo (#17500)
## Summary

Switch to the official version of
[`mypy_primer`](https://github.com/hauntsaninja/mypy_primer), now that
Red Knot support has been upstreamed (see
https://github.com/hauntsaninja/mypy_primer/pull/138,
https://github.com/hauntsaninja/mypy_primer/pull/135,
https://github.com/hauntsaninja/mypy_primer/pull/151,
https://github.com/hauntsaninja/mypy_primer/pull/155).

## Test Plan

Locally and in CI
2025-04-22 11:55:16 +02:00
David Peter
37a0836bd2 [red-knot] typing.dataclass_transform (#17445)
## Summary

* Add initial support for `typing.dataclass_transform`
* Support decorating a function decorator with `@dataclass_transform(…)`
(used by `attrs`, `strawberry`)
* Support decorating a metaclass with `@dataclass_transform(…)` (used by
`pydantic`, but doesn't work yet, because we don't seem to model
`__new__` calls correctly?)
* *No* support yet for decorating base classes with
`@dataclass_transform(…)`. I haven't figured out how this even supposed
to work. And haven't seen it being used.
* Add `strawberry` as an ecosystem project, as it makes heavy use of
`@dataclass_transform`

## Test Plan

New Markdown tests
2025-04-22 10:33:02 +02:00
renovate[bot]
f83295fe51 Update dependency react-resizable-panels to v2.1.8 (#17513)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 09:30:07 +02:00
renovate[bot]
c4581788b2 Update dependency smol-toml to v1.3.3 (#17505)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 09:19:55 +02:00
renovate[bot]
2894aaa943 Update dependency uuid to v11.1.0 (#17517)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 09:18:54 +02:00
renovate[bot]
ed4866a00b Update actions/setup-node action to v4.4.0 (#17514)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 09:18:13 +02:00
Matthew Mckee
9b5fe51b32 [red-knot] Fix variable name (#17532) 2025-04-21 17:20:04 -07:00
Matthew Mckee
53ffe7143f [red-knot] Add basic subtyping between class literal and callable (#17469)
## Summary

This covers step 1 from
https://typing.python.org/en/latest/spec/constructors.html#converting-a-constructor-to-callable

Part of #17343

## Test Plan

Update is_subtype_of.md and is_assignable_to.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-21 22:29:36 +00:00
Hans
21561000b1 [pyupgrade] Add fix safety section to docs (UP030) (#17443)
## Summary

add fix safety section to format_literals, for #15584
2025-04-21 14:14:58 -04:00
w0nder1ng
9c0772d8f0 [perflint] Allow list function calls to be replaced with a comprehension (PERF401) (#17519)
This is an implementation of the discussion from #16719. 

This change will allow list function calls to be replaced with
comprehensions:

```python
result = list()
for i in range(3):
    result.append(i + 1)
# becomes
result = [i + 1 for i in range(3)]
```

I added a new test to `PERF401.py` to verify that this fix will now work
for `list()`.
2025-04-21 13:29:24 -04:00
renovate[bot]
a4531bf865 Update pre-commit dependencies (#17506)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-04-21 17:09:54 +01:00
Alex Waygood
be54b840e9 [red-knot] Simplify visibility constraint handling for *-import definitions (#17486) 2025-04-21 15:33:35 +00:00
Alex Waygood
45b5dedee2 [red-knot] Detect (some) invalid protocols (#17488) 2025-04-21 16:24:19 +01:00
Alex Waygood
9ff4772a2c [red-knot] Correctly identify protocol classes (#17487) 2025-04-21 16:17:06 +01:00
renovate[bot]
c077b109ce Update dependency ruff to v0.11.6 (#17516) 2025-04-21 09:49:22 +01:00
renovate[bot]
8a2dd01db4 Update Rust crate shellexpand to v3.1.1 (#17512) 2025-04-21 01:59:02 +00:00
renovate[bot]
f888e51a34 Update Rust crate proc-macro2 to v1.0.95 (#17510) 2025-04-20 21:57:44 -04:00
renovate[bot]
d11e959ad5 Update Rust crate rand to v0.9.1 (#17511) 2025-04-21 01:57:27 +00:00
renovate[bot]
a56eef444a Update Rust crate libc to v0.2.172 (#17509) 2025-04-20 21:51:51 -04:00
renovate[bot]
14ff67fd46 Update Rust crate jiff to v0.2.9 (#17508) 2025-04-20 21:51:31 -04:00
renovate[bot]
ada7d4da0d Update Rust crate clap to v4.5.37 (#17507) 2025-04-20 21:51:27 -04:00
renovate[bot]
4cafb44ba7 Update astral-sh/setup-uv action to v5.4.2 (#17504)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [astral-sh/setup-uv](https://redirect.github.com/astral-sh/setup-uv) |
action | patch | `v5.4.1` -> `v5.4.2` |

---

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

---

### Release Notes

<details>
<summary>astral-sh/setup-uv (astral-sh/setup-uv)</summary>

###
[`v5.4.2`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.4.2):
🌈 Make sure uv installed by setup-uv is first in PATH

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.4.1...v5.4.2)

##### Changes

This release fixes an issue on self-hosted runners.
If you manually installed uv with version 0.5.0 or later this version
would overwrite the uv version installed by this action.
We now make sure the version installed by this action is the first found
in PATH

##### 🐛 Bug fixes

- Make sure uv installed by setup-uv is first in PATH
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;373](https://redirect.github.com/astral-sh/setup-uv/issues/373))

##### 🧰 Maintenance

- chore: update known checksums for 0.6.14
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;366](https://redirect.github.com/astral-sh/setup-uv/issues/366))
- chore: update known checksums for 0.6.13
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;365](https://redirect.github.com/astral-sh/setup-uv/issues/365))
- chore: update known checksums for 0.6.12
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;362](https://redirect.github.com/astral-sh/setup-uv/issues/362))
- chore: update known checksums for 0.6.11
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;357](https://redirect.github.com/astral-sh/setup-uv/issues/357))

##### 📚 Documentation

- Fix pep440 identifier instead of specifier
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;358](https://redirect.github.com/astral-sh/setup-uv/issues/358))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNDguNCIsInVwZGF0ZWRJblZlciI6IjM5LjI0OC40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-20 21:50:39 -04:00
renovate[bot]
1445836872 Update taiki-e/install-action digest to 09dc018 (#17503) 2025-04-20 21:50:26 -04:00
Shunsuke Shibayama
da6b68cb58 [red-knot] infer attribute assignments bound in comprehensions (#17396)
## Summary

This PR is a follow-up to #16852.

Instance variables bound in comprehensions are recorded, allowing type
inference to work correctly.

This required adding support for unpacking in comprehension which
resolves https://github.com/astral-sh/ruff/issues/15369.

## Test Plan

One TODO in `mdtest/attributes.md` is now resolved, and some new test
cases are added.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-04-19 06:42:48 +05:30
Carl Meyer
2a478ce1b2 [red-knot] simplify gradually-equivalent types out of unions and intersections (#17467)
## Summary

If two types are gradually-equivalent, that means they share the same
set of possible materializations. There's no need to keep two such types
in the same union or intersection; we should simplify them.

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

The one downside here is that now we will simplify e.g. `Unknown |
Todo(...)` to just `Unknown`, if `Unknown` was added to the union first.
This is correct from a type perspective (they are equivalent types), but
it can mean we lose visibility into part of the cause for the type
inferring as unknown. I think this is OK, but if we think it's important
to avoid this, I can add a special case to try to preserve `Todo` over
`Unknown`, if we see them both in the same union or intersection.

## Test Plan

Added and updated mdtests.
2025-04-18 15:08:57 -07:00
Carl Meyer
8fe2dd5e03 [red-knot] pull primer projects to run from file (#17473)
## Summary

The long line of projects in `mypy_primer.yaml` is hard to work with
when adding projects or checking whether they are currently run. Use a
one-per-line text file instead.

## Test Plan

Ecosystem check on this PR.
2025-04-18 21:20:18 +00:00
Alex Waygood
454ad15aee [red-knot] Fix MRO inference for protocol classes; allow inheritance from subscripted Generic[]; forbid subclassing unsubscripted Generic (#17452) 2025-04-18 19:55:53 +00:00
Hans
fd3fc34a9e [pyflakes] Add fix safety section to docs (F601, F602) (#17440)
## Summary

add fix safety section to repeated_keys_docs, for #15584

---------

Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-04-18 18:27:40 +00:00
Hans
c550b4d565 [pyupgrade] Add fix safety section to docs (UP008, UP022) (#17441)
## Summary

add fix safety section to replace_stdout_stderr and
super_call_with_parameters, for #15584
I checked the behavior and found that these two files could only
potentially delete the appended comments, so I submitted them as a PR.
2025-04-18 13:48:13 -04:00
Vasco Schiavo
f8061e8b99 [refurb] Mark the FURB161 fix unsafe except for integers and booleans (#17240)
The PR fixes #16457 .

Specifically, `FURB161` is marked safe, but the rule generates safe
fixes only in specific cases. Therefore, we attempt to mark the fix as
unsafe when we are not in one of these cases.

For instances, the fix is marked as aunsafe just in case of strings (as
pointed out in the issue). Let me know if I should change something.

---------

Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-04-18 13:46:01 -04:00
Carl Meyer
27a315b740 [red-knot] add fixpoint iteration for Type::member_lookup_with_policy (#17464)
## Summary

Member lookup can be cyclic, with type inference of implicit members. A
sample case is shown in the added mdtest.

There's no clear way to handle such cases other than to fixpoint-iterate
the cycle.

Fixes #17457.

## Test Plan

Added test.
2025-04-18 10:20:03 -07:00
w0nder1ng
08221454f6 [perflint] Implement fix for manual-dict-comprehension (PERF403) (#16719)
## Summary

This change adds an auto-fix for manual dict comprehensions. It also
copies many of the improvements from #13919 (and associated PRs fixing
issues with it), and moves some of the utility functions from
`manual_list_comprehension.rs` into a separate `helpers.rs` to be used
in both.

## Test Plan

I added a preview test case to showcase the new fix and added a test
case in `PERF403.py` to make sure lines with semicolons function. I
didn't yet make similar tests to the ones I added earlier to
`PERF401.py`, but the logic is the same, so it might be good to add
those to make sure they work.
2025-04-18 13:10:40 -04:00
Vasco Schiavo
5fec1039ed [pylint] Make fix unsafe if it deletes comments (PLR1730) (#17459)
The PR addresses issue #17311

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-04-18 12:49:01 -04:00
Douglas Creager
787bcd1c6a [red-knot] Handle explicit class specialization in type expressions (#17434)
You can now use subscript expressions in a type expression to explicitly
specialize generic classes, just like you could already do in value
expressions.

This still does not implement bidirectional checking, so a type
annotation on an assignment does not influence how we infer a
specialization for a (not explicitly specialized) constructor call. You
might get an `invalid-assignment` error if (a) we cannot infer a class
specialization from the constructor call (in which case you end up e.g.
trying to assign `C[Unknown]` to `C[int]`) or if (b) we can infer a
specialization, but it doesn't match the annotation.

Closes https://github.com/astral-sh/ruff/issues/17432
2025-04-18 11:49:22 -04:00
Matthew Mckee
5853eb28dd [red-knot] allow assignment expression in call compare narrowing (#17461)
## Summary

There was some narrowing constraints not covered from the previous PR

```py
def _(x: object):
    if (type(y := x)) is bool:
        reveal_type(y)  # revealed: bool
```

Also, refactored a bit

## Test Plan

Update type_api.md
2025-04-18 08:46:15 -07:00
Carl Meyer
84d064a14c [red-knot] fix building unions with literals and AlwaysTruthy/AlwaysFalsy (#17451)
In #17403 I added a comment asserting that all same-kind literal types
share all the same super-types. This is true, with two notable
exceptions: the types `AlwaysTruthy` and `AlwaysFalsy`. These two types
are super-types of some literal types within a given kind and not
others: `Literal[0]`, `Literal[""]`, and `Literal[b""]` inhabit
`AlwaysFalsy`, while other literals inhabit `AlwaysTruthy`.

This PR updates the literal-unions optimization to handle these types
correctly.

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

Verified locally that `QUICKCHECK_TESTS=100000 cargo test -p
red_knot_python_semantic -- --ignored types::property_tests::stable` now
passes again.
2025-04-18 08:20:03 -07:00
Carl Meyer
e4e405d2a1 [red-knot] Type narrowing for assertions (take 2) (#17345)
## Summary

Fixes #17147.

This was landed in #17149 and then reverted in #17335 because it caused
cycle panics in checking pybind11. #17456 fixed the cause of that panic.

## Test Plan

Add new narrow/assert.md test file

Co-authored-by: Matthew Mckee <matthewmckee04@yahoo.co.uk>
2025-04-18 08:11:07 -07:00
Carl Meyer
1918c61623 [red-knot] class bases are not affected by __future__.annotations (#17456)
## Summary

We were over-conflating the conditions for deferred name resolution.
`from __future__ import annotations` defers annotations, but not class
bases. In stub files, class bases are also deferred. Modeling this
correctly also reduces likelihood of cycles in Python files using `from
__future__ import annotations` (since deferred resolution is inherently
cycle-prone). The same cycles are still possible in `.pyi` files, but
much less likely, since typically there isn't anything in a `pyi` file
that would cause an early return from a scope, or otherwise cause
visibility constraints to persist to end of scope. Usually there is only
code at module global scope and class scope, which can't have `return`
statements, and `raise` or `assert` statements in a stub file would be
very strange. (Technically according to the spec we'd be within our
rights to just forbid a whole bunch of syntax outright in a stub file,
but I kinda like minimizing unnecessary differences between the handling
of Python files and stub files.)

## Test Plan

Added mdtests.
2025-04-18 06:46:21 -07:00
Dhruv Manilawala
44ad201262 [red-knot] Add support for overloaded functions (#17366)
## Summary

Part of #15383, this PR adds support for overloaded callables.

Typing spec: https://typing.python.org/en/latest/spec/overload.html

Specifically, it does the following:
1. Update the `FunctionType::signature` method to return signatures from
a possibly overloaded callable using a new `FunctionSignature` enum
2. Update `CallableType` to accommodate overloaded callable by updating
the inner type to `Box<[Signature]>`
3. Update the relation methods on `CallableType` with logic specific to
overloads
4. Update the display of callable type to display a list of signatures
enclosed by parenthesis
5. Update `CallableTypeOf` special form to recognize overloaded callable
6. Update subtyping, assignability and fully static check to account for
callables (equivalence is planned to be done as a follow-up)

For (2), it is required to be done in this PR because otherwise I'd need
to add some workaround for `into_callable_type` and I though it would be
best to include it in here.

For (2), another possible design would be convert `CallableType` in an
enum with two variants `CallableType::Single` and
`CallableType::Overload` but I decided to go with `Box<[Signature]>` for
now to (a) mirror it to be equivalent to `overload` field on
`CallableSignature` and (b) to avoid any refactor in this PR. This could
be done in a follow-up to better split the two kind of callables.

### Design

There were two main candidates on how to represent the overloaded
definition:
1. To include it in the existing infrastructure which is what this PR is
doing by recognizing all the signatures within the
`FunctionType::signature` method
2. To create a new `Overload` type variant

<details><summary>For context, this is what I had in mind with the new
type variant:</summary>
<p>

```rs
pub enum Type {
	FunctionLiteral(FunctionType),
    Overload(OverloadType),
    BoundMethod(BoundMethodType),
    ...
}

pub struct OverloadType {
	// FunctionLiteral or BoundMethod
    overloads: Box<[Type]>,
	// FunctionLiteral or BoundMethod
    implementation: Option<Type>
}

pub struct BoundMethodType {
    kind: BoundMethodKind,
    self_instance: Type,
}

pub enum BoundMethodKind {
    Function(FunctionType),
    Overload(OverloadType),
}
```

</p>
</details> 

The main reasons to choose (1) are the simplicity in the implementation,
reusing the existing infrastructure, avoiding any complications that the
new type variant has specifically around the different variants between
function and methods which would require the overload type to use `Type`
instead.

### Implementation

The core logic is how to collect all the overloaded functions. The way
this is done in this PR is by recording a **use** on the `Identifier`
node that represents the function name in the use-def map. This is then
used to fetch the previous symbol using the same name. This way the
signatures are going to be propagated from top to bottom (from first
overload to the final overload or the implementation) with each function
/ method. For example:

```py
from typing import overload

@overload
def foo(x: int) -> int: ...
@overload
def foo(x: str) -> str: ...
def foo(x: int | str) -> int | str:
	return x
```

Here, each definition of `foo` knows about all the signatures that comes
before itself. So, the first overload would only see itself, the second
would see the first and itself and so on until the implementation or the
final overload.

This approach required some updates specifically recognizing
`Identifier` node to record the function use because it doesn't use
`ExprName`.

## Test Plan

Update existing test cases which were limited by the overload support
and add test cases for the following cases:
* Valid overloads as functions, methods, generics, version specific
* Invalid overloads as stated in
https://typing.python.org/en/latest/spec/overload.html#invalid-overload-definitions
(implementation will be done in a follow-up)
* Various relation: fully static, subtyping, and assignability (others
in a follow-up)

## Ecosystem changes

_WIP_

After going through the ecosystem changes (there are a lot!), here's
what I've found:

We need assignability check between a callable type and a class literal
because a lot of builtins are defined as classes in typeshed whose
constructor method is overloaded e.g., `map`, `sorted`, `list.sort`,
`max`, `min` with the `key` parameter, `collections.abc.defaultdict`,
etc. (https://github.com/astral-sh/ruff/issues/17343). This makes up
most of the ecosystem diff **roughly 70 diagnostics**. For example:

```py
from collections import defaultdict

# red-knot: No overload of bound method `__init__` matches arguments [lint:no-matching-overload]
defaultdict(int)
# red-knot: No overload of bound method `__init__` matches arguments [lint:no-matching-overload]
defaultdict(list)

class Foo:
    def __init__(self, x: int):
        self.x = x

# red-knot: No overload of function `__new__` matches arguments [lint:no-matching-overload]
map(Foo, ["a", "b", "c"])
```

Duplicate diagnostics in unpacking
(https://github.com/astral-sh/ruff/issues/16514) has **~16
diagnostics**.

Support for the `callable` builtin which requires `TypeIs` support. This
is **5 diagnostics**. For example:
```py
from typing import Any

def _(x: Any | None) -> None:
    if callable(x):
        # red-knot: `Any | None`
        # Pyright: `(...) -> object`
        # mypy: `Any`
        # pyrefly: `(...) -> object`
        reveal_type(x)
```

Narrowing on `assert` which has **11 diagnostics**. This is being worked
on in https://github.com/astral-sh/ruff/pull/17345. For example:
```py
import re

match = re.search("", "")
assert match
match.group()  # error: [possibly-unbound-attribute]
```

Others:
* `Self`: 2
* Type aliases: 6
* Generics: 3
* Protocols: 13
* Unpacking in comprehension: 1
(https://github.com/astral-sh/ruff/pull/17396)

## Performance

Refer to
https://github.com/astral-sh/ruff/pull/17366#issuecomment-2814053046.
2025-04-18 09:57:40 +05:30
Hans
c7372d218d [pyupgrade] Add fix safety section to docs (UP036) (#17444)
## Summary

add fix safety section to outdated_version_block, for #15584
2025-04-17 22:45:53 -04:00
Eric Mark Martin
de8f4e62e2 [red-knot] more type-narrowing in match statements (#17302)
## Summary

Add more narrowing analysis for match statements:
* add narrowing constraints from guard expressions
* add negated constraints from previous predicates and guards to
subsequent cases

This PR doesn't address that guards can mutate your subject, and so
theoretically invalidate some of these narrowing constraints that you've
previously accumulated. Some prior art on this issue [here][mutable
guards].

[mutable guards]:
https://www.irif.fr/~scherer/research/mutable-patterns/mutable-patterns-mlworkshop2024-abstract.pdf

## Test Plan

Add some new tests, and update some existing ones


---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-17 18:18:34 -07:00
Matthew Mckee
edfa03a692 [red-knot] Add some narrowing for assignment expressions (#17448)
<!--
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 #14866
Fixes #17437

## Test Plan

Update mdtests in `narrow/`
2025-04-17 17:28:06 -07:00
Alex Waygood
9965cee998 [red-knot] Understand typing.Protocol and typing_extensions.Protocol as equivalent (#17446) 2025-04-17 21:54:22 +01:00
Nuri Jung
58807b2980 Server: Use min instead of max to limit the number of threads (#17421)
## Summary

Prevent overcommit by using max 4 threads as intended.

Unintuitively, `.max()` returns the maximum value of `self` and the
argument (not limiting to the argument). To limit the value to 4, one
needs to use `.min()`.

https://doc.rust-lang.org/std/cmp/trait.Ord.html#method.max
2025-04-18 01:32:12 +05:30
Brent Westbrook
9c47b6dbb0 [red-knot] Detect version-related syntax errors (#16379)
## Summary
This PR extends version-related syntax error detection to red-knot. The
main changes here are:

1. Passing `ParseOptions` specifying a `PythonVersion` to parser calls
2. Adding a `python_version` method to the `Db` trait to make this
possible
3. Converting `UnsupportedSyntaxError`s to `Diagnostic`s
4. Updating existing mdtests  to avoid unrelated syntax errors

My initial draft of (1) and (2) in #16090 instead tried passing a
`PythonVersion` down to every parser call, but @MichaReiser suggested
the `Db` approach instead
[here](https://github.com/astral-sh/ruff/pull/16090#discussion_r1969198407),
and I think it turned out much nicer.

All of the new `python_version` methods look like this:

```rust
fn python_version(&self) -> ruff_python_ast::PythonVersion {
    Program::get(self).python_version(self)
}
```

with the exception of the `TestDb` in `ruff_db`, which hard-codes
`PythonVersion::latest()`.

## Test Plan

Existing mdtests, plus a new mdtest to see at least one of the new
diagnostics.
2025-04-17 14:00:30 -04:00
Hans
d2ebfd6ed7 [pyflakes] Add fix safety section (F841) (#17410)
add fix safety section to docs for #15584, I'm new to ruff and not sure
if the content of this PR is correct, but I hope it can be helpful.

---------

Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-04-17 09:58:26 -04:00
Alex Waygood
c36f3f5304 [red-knot] Add KnownFunction variants for is_protocol, get_protocol_members and runtime_checkable (#17450) 2025-04-17 14:49:52 +01:00
Brent Westbrook
fcd50a0496 Bump 0.11.6 (#17449) 2025-04-17 09:20:29 -04:00
Shaygan Hooshyari
3ada36b766 Auto generate visit_source_order (#17180)
## Summary

part of: #15655 

I tried generating the source order function using code generation. I
tried a simple approach, but it is not enough to generate all of them
this way.

There is one good thing, that most of the implementations are fine with
this. We only have a few that are not. So one benefit of this PR could
be it eliminates a lot of the code, hence changing the AST structure
will only leave a few places to be fixed.

The `source_order` field determines if a node requires a source order
implementation. If it’s empty it means source order does not visit
anything.

Initially I didn’t want to repeat the field names. But I found two
things:
- `ExprIf` statement unlike other statements does not have the fields
defined in source order. This and also some fields do not need to be
included in the visit. So we just need a way to determine order, and
determine presence.
- Relying on the fields sounds more complicated to me. Maybe another
solution is to add a new attribute `order` to each field? I'm open to
suggestions.
But anyway, except for the `ExprIf` we don't need to write the field
names in order. Just knowing what fields must be visited are enough.

Some nodes had a more complex visitor:

`ExprCompare` required zipping two fields.

`ExprBoolOp` required a match over the fields.

`FstringValue` required a match, I created a new walk_ function that
does the match. and used it in code generation. I don’t think this
provides real value. Because I mostly moved the code from one file to
another. I was tried it as an option. I prefer to leave it in the code
as before.

Some visitors visit a slice of items. Others visit a single element. I
put a check on this in code generation to see if the field requires a
for loop or not. I think better approach is to have a consistent style.
So we can by default loop over any field that is a sequence.

For field types `StringLiteralValue` and `BytesLiteralValue` the types
are not a sequence in toml definition. But they implement `iter` so they
are iterated over. So the code generation does not properly identify
this. So in the code I'm checking for their types.

## Test Plan

All the tests should pass without any changes.
I checked the generated code to make sure it's the same as old code. I'm
not sure if there's a test for the source order visitor.
2025-04-17 08:59:57 -04:00
Alex Waygood
bd89838212 [red-knot] Initial tests for protocols (#17436) 2025-04-17 11:36:41 +00:00
David Peter
b32407b6f3 [red-knot] Dataclasses: synthesize __init__ with proper signature (#17428)
## Summary

This changeset allows us to generate the signature of synthesized
`__init__` functions in dataclasses by analyzing the fields on the class
(and its superclasses). There are certain things that I have not yet
attempted to model in this PR, like `kw_only`,
[`dataclasses.KW_ONLY`](https://docs.python.org/3/library/dataclasses.html#dataclasses.KW_ONLY)
or functionality around
[`dataclasses.field`](https://docs.python.org/3/library/dataclasses.html#dataclasses.field).

ticket: https://github.com/astral-sh/ruff/issues/16651

## Ecosystem analysis

These two seem to depend on missing features in generics (see [relevant
code
here](9898ccbb78/tests/core/test_generics.py (L54))):

> ```diff
> + error[lint:unknown-argument]
/tmp/mypy_primer/projects/dacite/tests/core/test_generics.py:54:24:
Argument `x` does not match any known parameter
> + error[lint:unknown-argument]
/tmp/mypy_primer/projects/dacite/tests/core/test_generics.py:54:38:
Argument `y` does not match any known parameter
> ```



These two are true positives. See [relevant code
here](9898ccbb78/tests/core/test_config.py (L154-L161)).

> ```diff
> + error[lint:invalid-argument-type]
/tmp/mypy_primer/projects/dacite/tests/core/test_config.py:161:24:
Argument to this function is incorrect: Expected `int`, found
`Literal["test"]`
> + error[lint:invalid-argument-type]
/tmp/mypy_primer/projects/dacite/tests/core/test_config.py:172:24:
Argument to this function is incorrect: Expected `int | float`, found
`Literal["test"]`
> ```


This one depends on `**` unpacking of dictionaries, which we don't
support yet:

> ```diff
> + error[lint:missing-argument]
/tmp/mypy_primer/projects/mypy_primer/mypy_primer/globals.py:218:11: No
arguments provided for required parameters `new`, `old`, `repo`,
`type_checker`, `mypyc_compile_level`, `custom_typeshed_repo`,
`new_typeshed`, `old_typeshed`, `new_prepend_path`, `old_prepend_path`,
`additional_flags`, `project_selector`, `known_dependency_selector`,
`local_project`, `expected_success`, `project_date`, `shard_index`,
`num_shards`, `output`, `old_success`, `coverage`, `bisect`,
`bisect_output`, `validate_expected_success`,
`measure_project_runtimes`, `concurrency`, `base_dir`, `debug`, `clear`
> ```



## Test Plan

New Markdown tests.
2025-04-17 09:30:59 +02:00
David Peter
b4de245a5a [red-knot] Dataclasses: support order=True (#17406)
## Summary

Support dataclasses with `order=True`:

```py
@dataclass(order=True)
class WithOrder:
    x: int

WithOrder(1) < WithOrder(2)  # no error
```

Also adds some additional tests to `dataclasses.md`.

ticket: #16651

## Test Plan

New Markdown tests
2025-04-17 08:58:46 +02:00
Douglas Creager
914095d08f [red-knot] Super-basic generic inference at call sites (#17301)
This PR adds **_very_** basic inference of generic typevars at call
sites. It does not bring in a full unification algorithm, and there are
a few TODOs in the test suite that are not discharged by this. But it
handles a good number of useful cases! And the PR does not add anything
that would go away with a more sophisticated constraint solver.

In short, we just look for typevars in the formal parameters, and assume
that the inferred type of the corresponding argument is what that
typevar should map to. If a typevar appears more than once, we union
together the corresponding argument types.

Cases we are not yet handling:

- We are not widening literals.
- We are not recursing into parameters that are themselves generic
aliases.
- We are not being very clever with parameters that are union types.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-16 15:07:36 -04:00
Dhruv Manilawala
5350288d07 [red-knot] Check assignability of bound methods to callables (#17430)
## Summary

This is similar to https://github.com/astral-sh/ruff/pull/17095, it adds
assignability check for bound methods to callables.

## Test Plan

Add test cases to for assignability; specifically it uses gradual types
because otherwise it would just delegate to `is_subtype_of`.
2025-04-17 00:21:59 +05:30
cake-monotone
649610cc98 [red-knot] Support super (#17174)
## Summary

closes #16615 

This PR includes:

- Introduces a new type: `Type::BoundSuper`
- Implements member lookup for `Type::BoundSuper`, resolving attributes
by traversing the MRO starting from the specified class
- Adds support for inferring appropriate arguments (`pivot_class` and
`owner`) for `super()` when it is used without arguments

When `super(..)` appears in code, it can be inferred into one of the
following:

- `Type::Unknown`: when a runtime error would occur (e.g. calling
`super()` out of method scope, or when parameter validation inside
`super` fails)
- `KnownClass::Super::to_instance()`: when the result is an *unbound
super object* or when a dynamic type is used as parameters (MRO
traversing is meaningless)
- `Type::BoundSuper`: the common case, representing a properly
constructed `super` instance that is ready for MRO traversal and
attribute resolution

### Terminology

Python defines the terms *bound super object* and *unbound super
object*.

An **unbound super object** is created when `super` is called with only
one argument (e.g.
`super(A)`). This object may later be bound via the `super.__get__`
method. However, this form is rarely used in practice.

A **bound super object** is created either by calling
`super(pivot_class, owner)` or by using the implicit form `super()`,
where both arguments are inferred from the context. This is the most
common usage.

### Follow-ups

- Add diagnostics for `super()` calls that would result in runtime
errors (marked as TODO)
- Add property tests for `Type::BoundSuper`

## Test Plan

- Added `mdtest/class/super.md`

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-16 18:41:55 +00:00
Wei Lee
1a79722ee0 [airflow] Extend AIR311 rules (#17422)
<!--
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? -->

* Extend the following AIR311 rules
* `airflow.io.path.ObjectStoragePath` → `airflow.sdk.ObjectStoragePath`
    * `airflow.io.storage.attach` → `airflow.sdk.io.attach`
    * `airflow.models.dag.DAG` → `airflow.sdk.DAG`
    * `airflow.models.DAG` → `airflow.sdk.DAG`
    * `airflow.decorators.dag` → `airflow.sdk.dag`
    * `airflow.decorators.task` → `airflow.sdk.task`
    * `airflow.decorators.task_group` → `airflow.sdk.task_group`
    * `airflow.decorators.setup` → `airflow.sdk.setup`
    * `airflow.decorators.teardown` → `airflow.sdk.teardown`

## Test Plan

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

The test case has been added to the button of the existing test
fixtures, confirmed to be correct and later reorgnaized
2025-04-16 12:40:15 -04:00
Carl Meyer
b67590bfde [red-knot] simplify union size limit handling (#17429) 2025-04-16 09:22:16 -07:00
Wei Lee
e6a2de3ac6 [airflow] Extract AIR311 from AIR301 rules (AIR301, AIR311) (#17310)
<!--
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? -->

As discussed in
https://github.com/astral-sh/ruff/issues/14626#issuecomment-2766146129,
we're to separate suggested changes from required changes.

The following symbols have been moved to AIR311 from AIR301. They still
work in Airflow 3.0, but they're suggested to be changed as they're
expected to be removed in a future version.

* arguments
    * `airflow..DAG | dag`
        * `sla_miss_callback`
    * operators
        * `sla`
* name
* `airflow.Dataset] | [airflow.datasets.Dataset` → `airflow.sdk.Asset`
    * `airflow.datasets, rest @ ..`
        * `DatasetAlias` → `airflow.sdk.AssetAlias`
        * `DatasetAll` → `airflow.sdk.AssetAll`
        * `DatasetAny` → `airflow.sdk.AssetAny`
* `expand_alias_to_datasets` → `airflow.sdk.expand_alias_to_assets`
        * `metadata.Metadata` → `airflow.sdk.Metadata`
    <!--airflow.models.baseoperator-->
    * `airflow.models.baseoperator.chain` → `airflow.sdk.chain`
* `airflow.models.baseoperator.chain_linear` →
`airflow.sdk.chain_linear`
* `airflow.models.baseoperator.cross_downstream` →
`airflow.sdk.cross_downstream`
* `airflow.models.baseoperatorlink.BaseOperatorLink` →
`airflow.sdk.definitions.baseoperatorlink.BaseOperatorLink`
    * `airflow.timetables, rest @ ..`
* `datasets.DatasetOrTimeSchedule` → *
`airflow.timetables.assets.AssetOrTimeSchedule`
    * `airflow.utils, rest @ ..`
        <!--airflow.utils.dag_parsing_context-->
* `dag_parsing_context.get_parsing_context` →
`airflow.sdk.get_parsing_context`

## Test Plan

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

The test fixture has been updated acccordingly
2025-04-16 11:06:57 -04:00
Carl Meyer
c7b5067ef8 [red-knot] set a size limit on unions of literals (#17419)
## Summary

Until we optimize our full union/intersection representation to
efficiently handle large numbers of same-kind literal types "as a
block", set a fairly low limit on the size of unions of literals.

We will want to increase this limit once we've made the broader
efficiency improvement (tracked in
https://github.com/astral-sh/ruff/issues/17420).

## Test Plan

`cargo bench --bench red_knot`
2025-04-16 14:23:11 +00:00
Carl Meyer
5a115e750d [red-knot] make large-union benchmark slow again (#17418)
## Summary

Now that we've made the large-unions benchmark fast, let's make it slow
again!

This adds a following operation (checking `len`) on the large union,
which is slow, even though building the large union is now fast. (This
is also observed in a real-world code sample.) It's slow because for
every element of the union, we fetch its `__len__` method and check it
for compatibility with `Sized`.

We can make this fast by extending the grouped-types approach, as
discussed in https://github.com/astral-sh/ruff/pull/17403, so that we
can do this `__len__` operation (which is identical for every literal
string) just once for all literal strings, instead of once per literal
string type in the union.

Until we do that, we can make this acceptably fast again for now by
setting a lowish limit on union size, which we can increase in the
future when we make it fast. This is what I'll do in the next PR.

## Test Plan

`cargo bench --bench red_knot`
2025-04-16 14:05:42 +00:00
Carl Meyer
a1f361949e [red-knot] optimize building large unions of literals (#17403)
## Summary

Special-case literal types in `UnionBuilder` to speed up building large
unions of literals.

This optimization is extremely effective at speeding up building even a
very large union (it improves the large-unions benchmark by 41x!). The
problem we can run into is that it is easy to then run into another
operation on the very large union (for instance, narrowing may add it to
an intersection, which then distributes it over the intersection) which
is still slow.

I think it is possible to avoid this by extending this optimized
"grouped" representation throughout not just `UnionBuilder`, but all of
our union and intersection representations. I have some work in this
direction, but rather than spending more time on it right now, I'd
rather just land this much, along with a limit on the size of these
unions (to avoid building really big unions quickly and then hitting
issues where they are used.)

## Test Plan

Existing tests and benchmarks.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-16 13:55:37 +00:00
Matthew Mckee
13ea4e5d0e [red-knot] Fix comments in type_api.md (#17425) 2025-04-16 11:19:48 +00:00
Matthew Mckee
a2a7b1e268 [red-knot] Do not assume that x != 0 if x inhabits ~Literal[0] (#17370)
## Summary

Fixes incorrect negated type eq and ne assertions in
infer_binary_intersection_type_comparison

fixes #17360

## Test Plan

Remove and update some now incorrect tests
2025-04-15 22:27:27 -07:00
Carl Meyer
1dedcb9e0d [red-knot] make large-union benchmark more challenging (#17416) 2025-04-15 18:04:57 -07:00
Douglas Creager
807a8a7a29 [red-knot] Acknowledge that T & anything is assignable to T (#17413)
This reworks the assignability/subtyping relations a bit to handle
typevars better:

1. For the most part, types are not assignable to typevars, since
there's no guarantee what type the typevar will be specialized to.

2. An intersection is an exception, if it contains the typevar itself as
one of the positive elements. This should fall out from the other
clauses automatically, since a typevar is assignable to itself, and an
intersection is assignable to something if any positive element is
assignable to that something.

3. Constrained typevars are an exception, since they must be specialized
to _exactly_ one of the constraints, not to a _subtype_ of a constraint.
If a type is assignable to every constraint, then the type is also
assignable to the constrained typevar.

We already had a special case for (3), but the ordering of it relative
to the intersection clauses meant we weren't catching (2) correctly. To
fix this, we keep the special case for (3), but fall through to the
other match arms for non-constrained typevars and if the special case
isn't true for a constrained typevar.

Closes https://github.com/astral-sh/ruff/issues/17364
2025-04-15 16:34:07 -04:00
renovate[bot]
78dabc332d Update Rust crate clap to v4.5.36 (#17381)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-04-15 16:27:36 +00:00
Dhruv Manilawala
bfc17fecaa Raise syntax error when \ is at end of file (#17409)
## Summary

This PR fixes a bug in the lexer specifically around line continuation
character at end of file.

The reason this was occurring is because the lexer wouldn't check for
EOL _after_ consuming the escaped newline but only if the EOL was right
after the line continuation character.

fixes: #17398 

## Test Plan

Add tests for the scenarios where this should occur mainly (a) when the
state is `AfterNewline` and (b) when the state is `Other`.
2025-04-15 21:26:12 +05:30
cake-monotone
942cb9e3ad [red-knot] Add regression tests for narrowing constraints cycles (#17408)
## Summary

closes #17215 

This PR adds regression tests for the following cycled queries:
- all_narrowing_constraints_for_expression
- all_negative_narrowing_constraints_for_expression

The following test files are included:
-
`red_knot_project/resources/test/corpus/cycle_narrowing_constraints.py`
-
`red_knot_project/resources/test/corpus/cycle_negative_narrowing_constraints.py`

These test names don't follow the existing naming convention based on
Cinder.
However, I’ve chosen these names to clearly reflect the regression
cases.
Let me know if you’d prefer to align more closely with the existing
Cinder-based style.

## Test Plan

```sh
git checkout 1a6a10b30
cargo test --package red_knot_project  -- corpus
```
2025-04-15 07:27:54 -07:00
Alex Waygood
312a487ea7 [red-knot] Add some knowledge of __all__ to *-import machinery (#17373) 2025-04-15 12:56:40 +01:00
renovate[bot]
cf8dc60292 Update taiki-e/install-action digest to be7c31b (#17379)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 12:55:31 +01:00
renovate[bot]
ea5d5c4e29 Update Rust crate mimalloc to v0.1.46 (#17382)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 12:55:15 +01:00
renovate[bot]
c99d5522eb Update PyO3/maturin-action action to v1.49.1 (#17384)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 12:54:53 +01:00
renovate[bot]
e57c83e369 Update Rust crate anyhow to v1.0.98 (#17380)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 12:52:03 +01:00
Andrew Gallant
1d49e71ddd dependencies: switch from chrono to jiff
We weren't really using `chrono` for anything other than getting the
current time and formatting it for logs.

Unfortunately, this doesn't quite get us to a point where `chrono`
can be removed. From what I can tell, we're still bringing it via
[`tracing-subscriber`](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/)
and
[`quick-junit`](https://docs.rs/quick-junit/latest/quick_junit/).
`tracing-subscriber` does have an
[issue open about Jiff](https://github.com/tokio-rs/tracing/discussions/3128),
but there's no movement on it.

Normally I'd suggest holding off on this since it doesn't get us all of
the way there and it would be better to avoid bringing in two datetime
libraries, but we are, it appears, already there. In particular,
`env_logger` brings in Jiff. So this PR doesn't really make anything
worse, but it does bring us closer to an all-Jiff world.
2025-04-15 07:47:55 -04:00
renovate[bot]
f05b2d3673 Update Rust crate bstr to v1.12.0 (#17385)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [bstr](https://redirect.github.com/BurntSushi/bstr) |
workspace.dependencies | minor | `1.11.3` -> `1.12.0` |

---

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

---

### Release Notes

<details>
<summary>BurntSushi/bstr (bstr)</summary>

###
[`v1.12.0`](https://redirect.github.com/BurntSushi/bstr/compare/1.11.3...1.12.0)

[Compare
Source](https://redirect.github.com/BurntSushi/bstr/compare/1.11.3...1.12.0)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMzguMCIsInVwZGF0ZWRJblZlciI6IjM5LjIzOC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 07:46:27 -04:00
Alex Waygood
79b921179c [red-knot] Further optimize *-import visibility constraints (#17375) 2025-04-15 12:32:22 +01:00
David Peter
1f85e0d0a0 [red-knot] Minor 'member_lookup_with_policy' fix (#17407)
## Summary

Couldn't really think of a regression test, but it's probably better to
fix this if we ever add new member-lookup-policies.
2025-04-15 13:28:51 +02:00
David Peter
03adae80dc [red-knot] Initial support for dataclasses (#17353)
## Summary

Add very early support for dataclasses. This is mostly to make sure that
we do not emit false positives on dataclass construction, but it also
lies some foundations for future extensions.

This seems like a good initial step to merge to me, as it basically
removes all false positives on dataclass constructor calls. This allows
us to use the ecosystem checks for making sure we don't introduce new
false positives as we continue to work on dataclasses.

## Ecosystem analysis

I re-ran the mypy_primer evaluation of [the `__init__`
PR](https://github.com/astral-sh/ruff/pull/16512) locally with our
current mypy_primer version and project selection. It introduced 1597
new diagnostics. Filtering those by searching for `__init__` and
rejecting those that contain `invalid-argument-type` (those could not
possibly be solved by this PR) leaves 1281 diagnostics. The current
version of this PR removes 1171 diagnostics, which leaves 110
unaccounted for. I extracted the lint + file path for all of these
diagnostics and generated a diff (of diffs), to see which
`__init__`-diagnostics remain. I looked at a subset of these: There are
a lot of `SomeClass(*args)` calls where we don't understand the
unpacking yet (this is not even related to `__init__`). Some others are
related to `NamedTuple`, which we also don't support yet. And then there
are some errors related to `@attrs.define`-decorated classes, which
would probably require support for `dataclass_transform`, which I made
no attempt to include in this PR.

## Test Plan

New Markdown tests.
2025-04-15 10:39:21 +02:00
github-actions[bot]
4894f52bae Sync vendored typeshed stubs (#17402)
Close and reopen this PR to trigger CI

---------

Co-authored-by: typeshedbot <>
Co-authored-by: David Peter <mail@david-peter.de>
2025-04-15 09:16:42 +02:00
Mike Perlov
3b24fe5c07 [red-knot] improve function/bound method type display (#17294)
## Summary

* Partial #17238
* Flyby from discord discussion - `todo_type!` now statically checks for
no parens in the message to avoid issues between debug & release build
tests

## Test Plan

many mdtests are changing
2025-04-14 15:56:18 -07:00
Dhruv Manilawala
b5d529e976 [red-knot] Move relation methods from CallableType to Signature (#17365)
## Summary

This PR moves all the relation methods from `CallableType` to
`Signature`.

The main reason for this is that `Signature` is going to be the common
denominator between normal and overloaded callables and the core logic
to check a certain relationship is going to just require the information
that would exists on `Signature`. For example, to check whether an
overloaded callable is a subtype of a normal callable, we need to check
whether _every_ overloaded signature is a subtype of the normal
callable's signature. This "every" logic would become part of the
`CallableType` and the core logic of checking the subtyping would exists
on `Signature`.
2025-04-15 03:32:25 +05:30
Brent Westbrook
014bb526f4 [syntax-errors] await outside async functions (#17363)
Summary
--

This PR implements detecting the use of `await` expressions outside of
async functions. This is a reimplementation of
[await-outside-async
(PLE1142)](https://docs.astral.sh/ruff/rules/await-outside-async/) as a
semantic syntax error.

Despite the rule name, PLE1142 also applies to `async for` and `async
with`, so these are covered here too.

Test Plan
--

Existing PLE1142 tests.

I also deleted more code from the `SemanticSyntaxCheckerVisitor` to
avoid changes in other parser tests.
2025-04-14 13:01:48 -04:00
Carl Meyer
e2a38e4c00 [red-knot] optimize is_subtype_of for literals (#17394)
## Summary

Allows us to establish that two literals do not have a subtype
relationship with each other, without having to fallback to a typeshed
Instance type, which is comparatively slow.

Improves the performance of the many-string-literals union benchmark by
5x.

## Test Plan

`cargo test -p red_knot_python_semantic` and `cargo bench --bench
red_knot`.
2025-04-14 09:42:44 -07:00
Carl Meyer
9bee9429de [red-knot] add a large-union-of-string-literals benchmark (#17393)
## Summary

Add a benchmark for a large-union case that currently has exponential
blow-up in execution time.

## Test Plan

`cargo bench --bench red_knot`
2025-04-14 09:40:46 -07:00
renovate[bot]
17e5b61c54 Update pre-commit dependencies (#17383) 2025-04-14 17:14:38 +01:00
David Peter
701aecb2a6 [red-knot] mypy_primer: Fail job on panic or internal errors (#17389)
## Summary

Let the mypy_primer job fail if Red Knot panics or exits with code 2
(indicating an internal error).

Corresponding mypy_primer commit:
90808f4656

In addition, we may also want to make a successful mypy_primer run
required for merging?

## Test Plan

Made sure that mypy_primer exits with code 70 locally on panics, which
should result in a pipeline failure, since we only allow code 0 and 1 in
the pipeline here:
a4d7c6669b/.github/workflows/mypy_primer.yaml (L73)
2025-04-14 11:50:17 +00:00
David Peter
850360a0b4 [red-knot] Document limitations of diagnostics-silencing in unreachable code (#17387)
## Summary

Document the limitations of our current approach to silencing only a
subset of diagnostics in unreachable sections.
2025-04-14 12:55:14 +02:00
Shunsuke Shibayama
dfd8eaeb32 [red-knot] detect unreachable attribute assignments (#16852)
## Summary

This PR closes #15967.

Attribute assignments that are statically known to be unreachable are
excluded from consideration for implicit instance attribute type
inference. If none of the assignments are found to be reachable, an
`unresolved-attribute` error is reported.

## Test Plan

[A test
case](https://github.com/astral-sh/ruff/blob/main/crates/red_knot_python_semantic/resources/mdtest/attributes.md#attributes-defined-in-statically-known-to-be-false-branches)
marked as TODO now work as intended, and new test cases have been added.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-04-14 09:23:20 +02:00
Dhruv Manilawala
3aa3ee8b89 [red-knot] Use concise message for the server (#17367)
## Summary

This is mainly a follow-up from
https://github.com/astral-sh/ruff/pull/17357 to use the
`concise_message` method for the red-knot server which I noticed
recently while testing the overload implementation.
2025-04-12 04:49:28 +00:00
David Peter
f0c3abd198 [red-knot] Minor followup on str.startswith (#17362)
## Summary

Minor follow-up to https://github.com/astral-sh/ruff/pull/17351, thank
you @AlexWaygood.
2025-04-11 18:40:08 +00:00
Dhruv Manilawala
e5026c0877 Use concise message to show diagnostics in playground (#17357)
## Summary

This PR fixes the playground to use the new `concise_diagnostic` method.

## Test plan

**Before:**

<img width="1728" alt="Screenshot 2025-04-11 at 11 37 34 AM"
src="https://github.com/user-attachments/assets/cbfcbc52-2e70-4277-9363-ba197711390e"
/>

**After:**

<img width="1728" alt="Screenshot 2025-04-11 at 11 38 03 AM"
src="https://github.com/user-attachments/assets/356ec63c-50d9-49a8-8df4-84000b46fb6d"
/>
2025-04-11 22:44:24 +05:30
Brent Westbrook
da32a83c9f [syntax-errors] return outside function (#17300)
Summary
--

This PR reimplements [return-outside-function
(F706)](https://docs.astral.sh/ruff/rules/return-outside-function/) as a
semantic syntax error.

These changes are very similar to those in
https://github.com/astral-sh/ruff/pull/17298.

Test Plan
--

New linter tests, plus existing F706 tests.
2025-04-11 17:05:54 +00:00
Charlie Marsh
4bfdf54d1a Allow types.ruff.rs for red-knot playground (#17358) 2025-04-11 12:56:03 -04:00
Andrew Gallant
7d11ef1564 red_knot_python_semantic: make TextRange required for reporting a lint diagnostic
This commit shuffles the reporting API around a little bit such that a
range is required, up front, when reporting a lint diagnostic. This in
turn enables us to make suppression checking eager.

In order to avoid callers needing to provide the range twice, we create
a primary annotation *without* a message inside the `Diagnostic`
encapsulated by the guard. We do this instead of requiring the message
up front because we're concerned about API complexity and the effort
involved in creating the message.

In order to provide a means of attaching a message to the primary
annotation, we expose a convenience API on `LintDiagnosticGuard` for
setting the message. This isn't generally possible for a `Diagnostic`,
but since a `LintDiagnosticGuard` knows how the `Diagnostic` was
constructed, we can offer this API correctly.

It strikes me that it might be easy to forget to attach a primary
annotation message, btu I think this the "least" bad failure mode. And
in particular, it should be somewhat obvious that it's missing once one
adds a snapshot test for how the diagnostic renders.

Otherwise, this API gives us the ability to eagerly check whether a
diagnostic should be reported with nearly minimal information. It also
shouldn't have any footguns since it guarantees that the primary
annotation is tied to the file in the typing context. And it keeps
things pretty simple: callers only need to provide what is actually
strictly necessary to make a diagnostic.
2025-04-11 12:36:36 -04:00
Andrew Gallant
b79d43a852 ruff_db: add primary annotation message mutators on Diagnostic
This will enable us to provide an API on `LintDiagnosticGuard` for
setting the primary annotation message. It will require an `unwrap()`,
but due to how `LintDiagnosticGuard` will build a `Diagnostic`, this
`unwrap()` will be guaranteed to succeed. (And it won't bubble out to
every user of `LintDiagnosticGuard`.)
2025-04-11 12:36:36 -04:00
Andrew Gallant
a4d3c4bf8b red_knot_python_semantic: make the guards implement DerefMut
This is the payoff from removing a bit of indirection. The types still
exist, but now callers don't need to do builder -> reporter ->
diagnostic. They can just conceptually think of it as builder ->
diagnostic.
2025-04-11 12:36:36 -04:00
Andrew Gallant
f3cc287a40 red_knot_python_semantic: tweak naming
We're going to make the guards deref to `Diagnostic` in order to remove
a layer of indirection in the reporter API. (Well, technically the layer
is not removed since the types still exist, but in actual _usage_ the
layer will be removed. We'll see how it shakes out in the next commit.)
2025-04-11 12:36:36 -04:00
Andrew Gallant
bd5b8a9ec6 ruff_db: tweak APIs accepting a diagnostic message
This expands the set of types accepted for diagnostic messages. Instead
of only `std::fmt::Display` impls, we now *also* accept a concrete
`DiagnosticMessage`.

This will be useful to avoid unnecessary copies of every single
diagnostic message created via `InferContext::report_lint`. (I'll call
out how this helps in a subsequent commit.)
2025-04-11 12:36:36 -04:00
renovate[bot]
0caf09f5c3 Update dependency vite to v6.2.6 (#17354)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 15:56:10 +00:00
David Peter
47956db567 [red-knot] Specialize str.startswith for string literals (#17351)
## Summary

Infer precise Boolean literal types for `str.startswith` calls where the
instance and the prefix are both string literals. This allows us to
understand `sys.platform.startswith(…)` branches.

## Test Plan

New Markdown tests
2025-04-11 16:26:45 +02:00
Brent Westbrook
ffef71d106 [syntax-errors] yield, yield from, and await outside functions (#17298)
Summary
--

This PR reimplements [yield-outside-function
(F704)](https://docs.astral.sh/ruff/rules/yield-outside-function/) as a
semantic syntax error. Despite the name, this rule covers `yield from`
and `await` in addition to `yield`.

Test Plan
--

New linter tests, along with the existing F704 test.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-04-11 10:16:23 -04:00
Micha Reiser
7e571791c0 [red-knot] Refresh diagnostics when changing related files (#17350) 2025-04-11 15:50:28 +02:00
Brent Westbrook
8e11c53310 Add Checker::import_from_typing (#17340)
Summary
--

This PR replaces uses of version-dependent imports from `typing` or
`typing_extensions` with a centralized `Checker::import_from_typing`
method.

The idea here is to make the fix for #9761 (whatever it ends up being)
applicable to all of the rules performing similar checks.

Test Plan
--

Existing tests for the affected rules.
2025-04-11 13:37:55 +00:00
Max Mynter
1aad180aae Don't add chaperone space after escaped quote in triple quote (#17216)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-11 10:21:47 +02:00
David Peter
1a3b73720c [red-knot] Silence errors in unreachable type annotations / class bases (#17342)
## Summary

For silencing `invalid-type-form` diagnostics in unreachable code, we
use the same approach that we use before and check the reachability that
we already record.

For silencing `invalid-bases`, we simply check if the type of the base
is `Never`. If so, we silence the diagnostic with the argument that the
class construction would never happen.

## Test Plan

Updated Markdown tests.
2025-04-10 22:47:47 +02:00
David Peter
8b2727cf67 [red-knot] Silence unresolved-import in unreachable code (#17336)
## Summary

Similar to what we did for `unresolved-reference` and
`unresolved-attribute`, we now also silence `unresolved-import`
diagnostics if the corresponding `import` statement is unreachable.

This addresses the (already closed) issue #17049.

## Test Plan

Adapted Markdown tests.
2025-04-10 21:13:28 +02:00
Andrew Gallant
410aa4b8fd red_knot_python_semantic: move TODO comment
It fits with reporting lint diagnostics much better than reporting
general diagnostics.
2025-04-10 13:21:00 -04:00
Andrew Gallant
bd58135b0d red_knot_python_semantic: rename lint() and report()
... to `report_lint()` and `report_diagnostic()`. And rename the old
`report_lint()` to `report_lint_old()`.
2025-04-10 13:21:00 -04:00
Andrew Gallant
81045758d3 ruff_db: use Annotation::get_message in more places
I added this accessor because tests want it, but we can also use it in
other places internally. It's a little nicer because it does the
`as_deref()` for you.
2025-04-10 13:21:00 -04:00
Andrew Gallant
0b2a5b5cd3 red_knot_python_semantic: tweak docs on building reporter builders 2025-04-10 13:21:00 -04:00
Andrew Gallant
7d958a9ee5 red_knot_python_semantic: remove the "old" secondary message type
This finally completes the deletion of all old diagnostic types.

We do this by migrating the second (and last) use of secondary
diagnostic messages: to highlight the return type of a function
definition when its return value is inconsistent with the type.

Like the last diagnostic, we do actually change the message here a bit.
We don't need a sub-diagnostic here, and we can instead just add a
secondary annotation to highlight the return type.
2025-04-10 13:21:00 -04:00
Andrew Gallant
7e2eb591bc red_knot_python_semantic: replace one use of "old" secondary diagnostic messages
This is the first use of the new `lint()` reporter.

I somewhat skipped a step here and also modified the actual diagnostic
message itself. The snapshots should tell the story.

We couldn't do this before because we had no way of differentiating
between "message for the diagnostic as a whole" and "message for a
specific code annotation." Now we can, so we can write more precise
messages based on the assumption that users are also seeing the code
snippet.

The downside here is that the actual message text can become quite vague
in the absence of the code snippet. This occurs, for example, with
concise diagnostic formatting. It's unclear if we should do anything
about it. I don't really see a way to make it better that doesn't
involve creating diagnostics with messages for each mode, which I think
would be a major PITA.

The upside is that this code gets a bit simpler, and we very
specifically avoid doing extra work if this specific lint is disabled.
2025-04-10 13:21:00 -04:00
Andrew Gallant
ba408f4231 red_knot_python_semantic: update revealed type snapshots
This required a bit of surgery in the diagnostic matching and more
faffing about using a "concise" message from a diagnostic instead of
only printing the "primary" message.
2025-04-10 13:21:00 -04:00
Andrew Gallant
28b64064f5 ruff_db: tweak how the revealed type diagnostic is rendered
In the new diagnostic data model, we really should have a main
diagnostic message *and* a primary span (with an optional message
attached to it) for every diagnostic.

In this commit, I try to make this true for the "revealed type"
diagnostic. Instead of the annotation saying both "revealed type is"
and also the revealed type itself, the annotation is now just the
revealed type and the main diagnostic message is "Revealed type."

I expect this may be controversial. I'm open to doing something
different. I tried to avoid redundancy, but maybe this is a special case
where we want the redundancy. I'm honestly not sure. I do *like* how it
looks with this commit, but I'm not working with Red Knot's type
checking daily, so my opinion doesn't count for much.

This did also require some tweaking to concise diagnostic formatting in
order to preserve the essential information.

This commit doesn't update every relevant snapshot. Just a few. I split
the rest out into the next commit.
2025-04-10 13:21:00 -04:00
Andrew Gallant
75b15ea2d0 red_knot: add explicit test for concise reveal_type diagnostic
This test reflects the status quo before we change things.
2025-04-10 13:21:00 -04:00
Andrew Gallant
e7e86b8584 red_knot_python_semantic: remove InferContext::report_diagnostic
... and replace it with use of `report()`.

Interestingly, this is the only instance of `report_diagnostic` used
directly, and thus anticipated to be the only instance of using
`report()`. If this ends up being a true single use method, we could
make it less generic and tailored specifically to "reveal type."

Two other things to note:

I left the "primary message" as empty. This avoids changing snapshots.
I address this in a subsequent commit.

The creation of a diagnostic here is a bit verbose/annoying. Certainly
more so than it was. This is somewhat expected since our diagnostic
model is more expressive and because we don't have a proc macro. I
avoided creating helpers for this case since there's only one use of
`report()`. But I expect to create helpers for the `lint()` case.
2025-04-10 13:21:00 -04:00
Andrew Gallant
f84bc07d56 red_knot_python_semantic: add "reporter" API
This is a surgical change that adds new `report()` and `lint()`
APIs to `InferContext`. These are intended to replace the existing
`report_*` APIs.

The comments should explain what these reporters are meant to do. For
the most part, this is "just" shuffling some code around. The actual
logic for determining whether a lint *should* be reported or not remains
unchanged and we don't make any changes to how a `Diagnostic` is
actually constructed (yet).

I initially tried to just use `LintReporter` and `DiagnosticReporter`
without the builder types, since I perceive the builder types to be an
annoying additional layer. But I found it also exceedingly annoying to
have to construct and provide the diagnostic message before you even
know if you are going to build the diagnostic. I also felt like this
could result in potentially unnecessary and costly querying in some
cases, although this is somewhat hand wavy. So I overall felt like the
builder route was the way to go. If the builders end up being super
annoying, we can probably add convenience APIs for common patterns to
paper over them.
2025-04-10 13:21:00 -04:00
Dylan
7186d5e9ad Bump 0.11.5 (#17337) 2025-04-10 11:57:44 -05:00
David Peter
5b6e94981d [red-knot] Silence unresolved-attribute in unreachable code (#17305)
## Summary

Basically just repeat the same thing that we did for
`unresolved-reference`, but now for attribute expressions.

We now also handle the case where the unresolved attribute (or the
unresolved reference) diagnostic originates from a stringified type
annotation.

And I made the evaluation of reachability constraints lazy (will only be
evaluated right before we are about to emit a diagnostic).

## Test Plan

New Markdown tests for stringified annotations.
2025-04-10 17:15:47 +02:00
Carl Meyer
ec74f2d522 Revert "[red-knot] Type narrowing for assertions (#17149)" (#17335)
I merged #17149 without checking the ecosystem results, and it still
caused a cycle panic in pybind11. Reverting for now until I fix that, so
we don't lose the ecosystem signal on other PRs.
2025-04-10 11:06:25 -04:00
Matthew Mckee
907b6ed7b5 [red-knot] Type narrowing for assertions (#17149)
## Summary

Fixes #17147 

## Test Plan

Add new narrow/assert.md test file

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-10 10:15:52 -04:00
Carl Meyer
fd9882a1f4 [red-knot] avoid unnecessary evaluation of visibility constraint on definitely-unbound symbol (#17326)
This causes spurious query cycles.

This PR also includes an update to Salsa, which gives us db events on
cycle iteration, so we can write tests asserting the absence of a cycle.
2025-04-10 13:59:38 +00:00
Aria Desires
66a33bfd32 update cargo-dist (#17325)
Putting this up to confirm that it does what it should:

* undirty the release.yml by including action-commits in the config
* add persist-credentials=false hardening
2025-04-10 09:43:13 -04:00
Micha Reiser
5b1d8350ff [red-knot] Fix double hovers/inlays in playground (#17334) 2025-04-10 12:40:41 +00:00
David Peter
4d50ee6f52 [red-knot] Track reachability of scopes (#17332)
## Summary

Track the reachability of nested scopes within their parent scopes. We
use this as an additional requirement for emitting
`unresolved-reference` diagnostics (and in the future,
`unresolved-attribute` and `unresolved-import`). This means that we only
emit `unresolved-reference` for a given use of a symbol if the use
itself is reachable (within its own scope), *and if the scope itself is
reachable*. For example, no diagnostic should be emitted for the use of
`x` here:

```py
if False:
    x = 1

    def f():
        print(x)  # this use of `x` is reachable inside the `f` scope,
                  # but the whole `f` scope is not reachable.
```

There are probably more fine-grained ways of solving this problem, but
they require a more sophisticated understanding of nested scopes (see
#15777, in particular
https://github.com/astral-sh/ruff/issues/15777#issuecomment-2788950267).
But it doesn't seem completely unreasonable to silence *this specific
kind of error* in unreachable scopes.

## Test Plan

Observed changes in reachability tests and ecosystem.
2025-04-10 11:56:40 +00:00
Aaron Gokaslan
06ffeb2e09 Add pre-commit hook to check for merge conflicts (#17279) 2025-04-10 11:22:54 +01:00
Matthew Mckee
10e44124e6 [red-knot] Add inlay type hints (#17214)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-10 09:21:40 +00:00
Micha Reiser
9f6913c488 [red-knot] Update salsa (#17320)
## Summary

Update Salsa to pull in https://github.com/salsa-rs/salsa/pull/788 which
fixes the, by now, famous *access to field whilst the value is being
initialized*.

This PR also re-enables all tests that previously triggered the panic.

## Test Plan

`cargo test`
2025-04-09 16:22:02 -04:00
David Peter
5fef4d4572 Use python.typing.org for typing documentation links (#17323)
## Summary

There is a new official URL for the typing documentation:
https://typing.python.org/

Change all https://typing.readthedocs.io/ links to use the new sub
domain, which is slightly shorter and looks more official.

## Test Plan

Tested to see if each and every new URL is accessible. I noticed that
some links go to https://typing.python.org/en/latest/source/stubs.html
which seems to be outdated, but that is a separate issue. The same page
shows up for the old URL.
2025-04-09 20:38:20 +02:00
Brent Westbrook
144484d46c Refactor semantic syntax error scope handling (#17314)
## Summary

Based on the discussion in
https://github.com/astral-sh/ruff/pull/17298#discussion_r2033975460, we
decided to move the scope handling out of the `SemanticSyntaxChecker`
and into the `SemanticSyntaxContext` trait. This PR implements that
refactor by:

- Reverting all of the `Checkpoint` and `in_async_context` code in the
`SemanticSyntaxChecker`
- Adding four new methods to the `SemanticSyntaxContext` trait
- `in_async_context`: matches `SemanticModel::in_async_context` and only
detects the nearest enclosing function
- `in_sync_comprehension`: uses the new `is_async` tracking on
`Generator` scopes to detect any enclosing sync comprehension
  - `in_module_scope`: reports whether we're at the top-level scope
  - `in_notebook`: reports whether we're in a Jupyter notebook
- In-lining the `TestContext` directly into the
`SemanticSyntaxCheckerVisitor`
- This allows modifying the context as the visitor traverses the AST,
which wasn't possible before

One potential question here is "why not add a single method returning a
`Scope` or `Scopes` to the context?" The main reason is that the `Scope`
type is defined in the `ruff_python_semantic` crate, which is not
currently a dependency of the parser. It also doesn't appear to be used
in red-knot. So it seemed best to use these more granular methods
instead of trying to access `Scope` in `ruff_python_parser` (and
red-knot).

## Test Plan

Existing parser and linter tests.
2025-04-09 14:23:29 -04:00
Wei Lee
c87e3ccb2f [airflow] Add missing AIR302 attribute check (#17115)
<!--
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? -->

attribute check was missing in the previous implementation

e.g.

```python
from airflow.api.auth.backend import basic_auth

basic_auth.auth_current_user
```

This PR adds this kind of check.

## Test Plan

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

The test case has been added to the button of the existing test
fixtures, confirmed to be correct and later reorgnaized
2025-04-09 13:58:41 -04:00
Alex Waygood
781b653511 [red-knot] Fix false positives on types.UnionType instances in type expressions (#17297) 2025-04-09 18:33:16 +01:00
Micha Reiser
484a8ed36d [red-knot] Update salsa (part 1) (#17321) 2025-04-09 19:15:43 +02:00
Brent Westbrook
2fbc4d577e [syntax-errors] Document behavior of global declarations in try nodes before 3.13 (#17285)
Summary
--

This PR extends the documentation of the `LoadBeforeGlobalDeclaration`
check to specify the behavior on versions of Python before 3.13. Namely,
on Python 3.12, the `else` clause of a `try` statement is visited before
the `except` handlers:

```pycon
Python 3.12.9 (main, Feb 12 2025, 14:50:50) [Clang 19.1.6 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 10
>>> def g():
...     try:
...         1 / 0
...     except:
...         a = 1
...     else:
...         global a
...
>>> def f():
...     try:
...         pass
...     except:
...         global a
...     else:
...         print(a)
...
  File "<stdin>", line 5
SyntaxError: name 'a' is used prior to global declaration

```

The order is swapped on 3.13 (see
[CPython#111123](https://github.com/python/cpython/issues/111123)):

```pycon
Python 3.13.2 (main, Feb  5 2025, 08:05:21) [GCC 14.2.1 20250128] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 10
... def g():
...     try:
...         1 / 0
...     except:
...         a = 1
...     else:
...         global a
...
  File "<python-input-0>", line 8
    global a
    ^^^^^^^^
SyntaxError: name 'a' is assigned to before global declaration
>>> def f():
...     try:
...         pass
...     except:
...         global a
...     else:
...         print(a)
...
>>>
```

The current implementation of PLE0118 is correct for 3.13 but not 3.12:
[playground](https://play.ruff.rs/d7467ea6-f546-4a76-828f-8e6b800694c9)
(it flags the first case regardless of Python version).

We decided to maintain this incorrect diagnostic for Python versions
before 3.13 because the pre-3.13 behavior is very unintuitive and
confirmed to be a bug, although the bug fix was not backported to
earlier versions. This can lead to false positives and false negatives
for pre-3.13 code, but we also expect that to be very rare, as
demonstrated by the ecosystem check (before the version-dependent check
was reverted here).

Test Plan
--

N/a
2025-04-09 12:54:21 -04:00
Alex Waygood
73399029b2 [red-knot] Optimise visibility constraints for *-import definitions (#17317) 2025-04-09 16:53:26 +00:00
Douglas Creager
ff376fc262 [red-knot] Allow explicit specialization of generic classes (#17023)
This PR lets you explicitly specialize a generic class using a subscript
expression. It introduces three new Rust types for representing classes:

- `NonGenericClass`
- `GenericClass` (not specialized)
- `GenericAlias` (specialized)

and two enum wrappers:

- `ClassType` (a non-generic class or generic alias, represents a class
_type_ at runtime)
- `ClassLiteralType` (a non-generic class or generic class, represents a
class body in the AST)

We also add internal support for specializing callables, in particular
function literals. (That is, the internal `Type` representation now
attaches an optional specialization to a function literal.) This is used
in this PR for the methods of a generic class, but should also give us
most of what we need for specializing generic _functions_ (which this PR
does not yet tackle).

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-09 11:18:46 -04:00
Wei Lee
7c81408c54 [airflow] Refactor AIR301 logic and fix typos (AIR301) (#17293)
<!--
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? -->

* Simplify match conditions in AIR301
* Fix
* `airflow.datasets.manager.DatasetManager` →
`airflow.assets.manager.AssetManager`
* `airflow.www.auth.has_access_dataset` →
`airflow.www.auth.has_access_dataset`

## Test Plan

<!-- How was it tested? -->
The test fixture has been updated accordingly
2025-04-09 10:46:17 -04:00
Wei Lee
7207c86971 [airflow] Extract AIR312 from AIR302 rules (AIR302, AIR312) (#17152)
<!--
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? -->

As discussed in
https://github.com/astral-sh/ruff/issues/14626#issuecomment-2766146129,
we're to separate suggested changes from required changes.

The following symbols has been moved to AIR312 from AIR302. They still
work in Airflow 3.0, but they're suggested to be changed as they're
expected to be removed in future version

```python
from airflow.hooks.filesystem import FSHook
from airflow.hooks.package_index import PackageIndexHook
from airflow.hooks.subprocess import (SubprocessHook, SubprocessResult, working_directory)
from airflow.operators.bash import BashOperator
from airflow.operators.datetime import BranchDateTimeOperator, target_times_as_dates
from airflow.operators.trigger_dagrun import TriggerDagRunLink, TriggerDagRunOperator
from airflow.operators.empty import EmptyOperator
from airflow.operators.latest_only import LatestOnlyOperator
from airflow.operators.python import (BranchPythonOperator, PythonOperator, PythonVirtualenvOperator, ShortCircuitOperator)
from airflow.operators.weekday import BranchDayOfWeekOperator
from airflow.sensors.date_time import DateTimeSensor, DateTimeSensorAsync
from airflow.sensors.external_task import ExternalTaskMarker, ExternalTaskSensor, ExternalTaskSensorLink
from airflow.sensors.filesystem import FileSensor
from airflow.sensors.time_sensor import TimeSensor, TimeSensorAsync
from airflow.sensors.time_delta import TimeDeltaSensor, TimeDeltaSensorAsync, WaitSensor
from airflow.sensors.weekday import DayOfWeekSensor
from airflow.triggers.external_task import DagStateTrigger, WorkflowTrigger
from airflow.triggers.file import FileTrigger
from airflow.triggers.temporal import DateTimeTrigger, TimeDeltaTrigger
```

## Test Plan

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

The test fixture has been updated acccordingly

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-04-09 10:43:07 -04:00
Alex Waygood
6ec4c6a97e [red-knot] Improve handling of visibility constraints in external modules when resolving * imports (#17286) 2025-04-09 14:36:52 +00:00
Alex Waygood
f1ba596f22 [red-knot] Add more tests for * imports (#17315) 2025-04-09 15:10:30 +01:00
Micha Reiser
8249a72412 [red-knot] Default python-platform to current platform (#17183)
## Summary

As discussed in https://github.com/astral-sh/ruff/issues/16983 and
"mitigate" said issue for the alpha.

This PR changes the default for `PythonPlatform` to be the current
platform rather than `all`.

I'm not sure if we should be as sophisticated as supporting `ios` and
`android` as defaults but it was easy...

## Test Plan

Updated Markdown tests.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-04-09 12:05:18 +02:00
David Peter
00e00b9ad6 [red-knot] Add new 'unreachable code' test case (#17306)
## Summary

This is a new test case that I don't know how to handle yet. It leads to
many false positives in `rich/tests/test_win32_console.py`, which does
something like:

```py
if sys.platform == "win32":
    from windows_only_module import some_symbol

    some_other_symbol = 1

    def some_test_case():
        use(some_symbol)  # Red Knot: unresolved-reference
        use(some_other_symbol)  # Red Knot: unresolved-reference
```

Also adds a test for using unreachable symbols in type annotations or as
class bases.
2025-04-09 11:45:42 +02:00
David Peter
9a5a86769b [red-knot] mypy_primer: Run on async-utils (#17303)
closes #17299
2025-04-09 09:43:22 +02:00
David Peter
2cee86d807 [red-knot] Add custom __setattr__ support (#16748)
## Summary

Add support for classes with a custom `__setattr__` method.

## Test Plan

New Markdown tests, ecosystem checks.
2025-04-09 08:04:11 +02:00
Mike Perlov
fab7d820bd [red-knot] Add __init__ arguments check when doing try_call on a class literal (#16512)
## Summary

* Addresses #16511 for simple cases where only `__init__` method is
bound on class or doesn't exist at all.
* fixes a bug with argument counting in bound method diagnostics

Caveats:
* No handling of `__new__` or modified `__call__` on metaclass.
* This leads to a couple of false positive errors in tests

## Test Plan

- A couple new cases in mdtests
- cargo nextest run -p red_knot_python_semantic --no-fail-fast

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-04-08 17:26:20 -04:00
Denys Kyslytsyn
ed14dbb1a2 [flake8-pie] Avoid false positive for multiple assignment with auto() (PIE796) (#17274)
This fix closes #16868 

I noticed the issue is assigned, but the assignee appears to be actively
working on another pull request. I hope that’s okay!

<!--
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? -->

As of Python 3.11.1, `enum.auto()` can be used in multiple assignments.
This pattern should not trigger non-unique-enums check.
Reference: [Python docs on
enum.auto()](https://docs.python.org/3/library/enum.html#enum.auto)

This fix updates the check logic to skip enum variant statements where
the right-hand side is a tuple containing a call to `enum.auto()`.

## Test Plan

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

The added test case uses the example from the original issue. It
previously triggered a false positive, but now passes successfully.
2025-04-08 15:53:27 -04:00
Brent Westbrook
058439d5d3 [syntax-errors] Async comprehension in sync comprehension (#17177)
Summary
--

Detect async comprehensions nested in sync comprehensions in async
functions before Python 3.11, when this was [changed].

The actual logic of this rule is very straightforward, but properly
tracking the async scopes took a bit of work. An alternative to the
current approach is to offload the `in_async_context` check into the
`SemanticSyntaxContext` trait, but that actually required much more
extensive changes to the `TestContext` and also to ruff's semantic
model, as you can see in the changes up to
31554b473507034735bd410760fde6341d54a050. This version has the benefit
of mostly centralizing the state tracking in `SemanticSyntaxChecker`,
although there was some subtlety around deferred function body traversal
that made the changes to `Checker` more intrusive too (hence the new
linter test).

The `Checkpoint` struct/system is obviously overkill for now since it's
only tracking a single `bool`, but I thought it might be more useful
later.

[changed]: https://github.com/python/cpython/issues/77527

Test Plan
--

New inline tests and a new linter integration test.
2025-04-08 12:50:52 -04:00
Wei Lee
dc02732d4d [airflow] Expand module path check to individual symbols (AIR302) (#17278)
## Summary

### Improvement
Expand the following moved module into individual symbols.

* airflow.triggers.temporal
* airflow.triggers.file
* airflow.triggers.external_task
* airflow.hooks.subprocess
* airflow.hooks.package_index
* airflow.hooks.filesystem
* airflow.sensors.weekday
* airflow.sensors.time_delta
* airflow.sensors.time_sensor
* airflow.sensors.date_time
* airflow.operators.weekday
* airflow.operators.datetime
* airflow.operators.bash 

This removes `Replacement::ImportPathMoved`.

## Fix
During the expansion, the following paths were also fixed

* airflow.sensors.s3_key_sensor.S3KeySensor →
airflow.providers.amazon.aws.sensors.S3KeySensor
* airflow.operators.sql.SQLThresholdCheckOperator →
airflow.providers.common.sql.operators.sql.SQLThresholdCheckOperator
* airflow.hooks.druid_hook.DruidDbApiHook →
airflow.providers.apache.druid.hooks.druid.DruidDbApiHook
* airflow.hooks.druid_hook.DruidHook →
airflow.providers.apache.druid.hooks.druid.DruidHook
* airflow.kubernetes.pod_generator.extend_object_field →
airflow.providers.cncf.kubernetes.pod_generator.extend_object_field
* airflow.kubernetes.pod_launcher.PodLauncher →
airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodLauncher
* airflow.kubernetes.pod_launcher.PodStatus →
airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodStatus
* airflow.kubernetes.pod_generator.PodDefaults →
airflow.providers.cncf.kubernetes.pod_generator.PodDefaults
* airflow.kubernetes.pod_launcher_deprecated.PodDefaults →
airflow.providers.cncf.kubernetes.pod_launcher_deprecated.PodDefaults

### Refactor
As many symbols are moved into the same module,
`SourceModuleMovedToProvider` is introduced for grouping similar logic

## Test Plan
2025-04-08 09:03:27 -04:00
Brent Westbrook
0891689d2f [syntax-errors] Check annotations in annotated assignments (#17283)
Summary
--

This PR extends the checks in #17101 and #17282 to annotated assignments
after Python 3.13.

Currently stacked on #17282 to include `await`.

Test Plan
--

New inline tests. These are simpler than the other cases because there's
no place to put generics.
2025-04-08 08:56:25 -04:00
Brent Westbrook
127a45622f [syntax-errors] Extend annotation checks to await (#17282)
Summary
--

This PR extends the changes in #17101 to include `await` in the same
positions.

I also renamed the `valid_annotation_function` test to include `_py313`
and explicitly passed a Python version to contrast it with the `_py314`
version.

Test Plan
--

New test cases added to existing files.
2025-04-08 08:55:43 -04:00
David Peter
b662c3ff7e [red-knot] Add support for assert_never (#17287)
## Summary

We already have partial "support" for `assert_never`, because it is
annotated as
```pyi
def assert_never(arg: Never, /) -> Never: ...
```
in typeshed. So we already emit a `invalid-argument-type` diagnostic if
the argument type to `assert_never` is not assignable to `Never`.

That is not enough, however. Gradual types like `Any`, `Unknown`,
`@Todo(…)` or `Any & int` can be assignable to `Never`. Which means that
we didn't issue any diagnostic in those cases.

Also, it seems like `assert_never` deserves a dedicated diagnostic
message, not just a generic "invalid argument type" error.

## Test Plan

New Markdown tests.
2025-04-08 09:31:49 +02:00
Denys Kyslytsyn
97dd6d120c [flake8-pytest-style] Avoid false positive for legacy form of pytest.raises (PT011) (#17231)
This fix closes #17026 

## Summary

The check for the `PytestRaisesTooBroad` rule is now skipped if there is
a second positional argument present, which means `pytest.raises` is
used as a function.

## Test Plan

Tested on the example from the issue, which now passes the check.
```Python3
pytest.raises(Exception, func, *func_args, **func_kwargs).match("error message")
```

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-08 09:24:47 +02:00
InSync
34e06f2d17 [red-knot] Do not show types for literal expressions on hover (#17290)
## Summary

Resolves #17289.

After this change, Red Knot will no longer show types on hover for
`None`, `...`, `True`, `False`, numbers, strings (but not f-strings),
and bytes literals.

## Test Plan

Unit tests.
2025-04-08 09:05:51 +02:00
David Peter
a388c73752 [red-knot] Fix dead-code clippy warning (#17291)
## Summary

Failed run on main:
https://github.com/astral-sh/ruff/actions/runs/14326812317
2025-04-08 08:56:59 +02:00
David Peter
60f2e67454 [red-knot] Reachability analysis (#17199)
## Summary

This implements a new approach to silencing `unresolved-reference`
diagnostics by keeping track of the reachability of each use of a
symbol. The changes merged in
https://github.com/astral-sh/ruff/pull/17169 are still needed for the
"Use of variable in nested function" test case, but that could also be
solved in another way eventually (see
https://github.com/astral-sh/ruff/issues/15777). We can use the same
technique to silence `unresolved-import` and `unresolved-attribute`
false-positives, but I think this could be merged in isolation.

## Test Plan

New Markdown tests, ecosystem tests
2025-04-08 08:37:20 +02:00
Micha Reiser
cb7f56fb20 [red-knot] Don't use latency-sensitive for handlers (#17227)
## Summary

The priority latency-sensitive is reserved for actions that need to run
immediately because they would otherwise block the user's action. An
example of this is a format request. VS code blocks the editor until the
save action is complete. That's why formatting a document is very
sensitive to delays and it's important that we always have a worker
thread available to run a format request *immediately*. Another example
are code completions, where it's important that they appear immediately
when the user types.

On the other hand, showing diagnostics, hover, or inlay hints has high
priority but users are used that the editor takes a few ms to compute
the overlay.
Computing this information can also be expensive (e.g. find all
references), blocking the worker for quiet some time (a few 100ms).
That's why it's important
that those requests don't clog the sensitive worker threads.
2025-04-08 08:33:30 +02:00
David Peter
761749cb50 [playground] New default program (#17277)
## Summary

This PR proposes to change the default example program in the
playground. I realize that this is somewhat underwhelming, but I found
it rather difficult to come up with something that circumvented missing
support for overloads/generics/self-type, while still looking like
(easy!) code that someone might actually write, and demonstrating some
Red Knot features. One thing that I wanted to capture was the experience
of adding type constraints to an untyped program. And I wanted something
that could be executed in the Playground once all errors are fixed.

Happy for any suggestions on what we could do instead. I had a lot of
different ideas, but always ran into one or another limitation. So I
guess we can also iterate on this as we add more features to Red Knot.

Try it here:
https://playknot.ruff.rs/8e3a96af-f35d-4488-840a-2abee6c0512d
```py
from typing import Literal

type Style = Literal["italic", "bold", "underline"]

# Add parameter annotations `line: str, word: str, style: Style` and a return
# type annotation `-> str` to see if you can find the mistakes in this program.

def with_style(line, word, style):
    if style == "italic":
        return line.replace(word, f"*{word}*")
    elif style == "bold":
        return line.replace(word, f"__{word}__")

    position = line.find(word)
    output = line + "\n"
    output += " " * position
    output += "-" * len(word)


print(with_style("Red Knot is a fast type checker for Python.", "fast", "underlined"))
```

closes https://github.com/astral-sh/ruff/issues/17267
2025-04-07 21:52:07 +02:00
David Peter
3657f798c9 [red-knot] Add --python-platform CLI option (#17284)
## Summary

Add a new `--python-platform` command-line option, in analogy to
`--python-version`.

## Test Plan

Added new integration test.
2025-04-07 21:04:44 +02:00
Matthew Mckee
4a4a376f02 [red-knot] Allow ellipsis default params in stub functions (#17243)
## Summary

Fixes #17234

## Test Plan

Add tests to functions/paremeters.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-07 17:34:59 +00:00
Micha Reiser
5e0f563ee4 [red-knot] Fix stale syntax errors in playground (#17280)
## Summary

React requires that `key`s are unique but the constructed key for
diagnostics wasn't guaranteed when two diagnostics had the same name and
location.

This PR fixes this by using a disambiguator map to disambiguate the key.

Fixes #17276

## Test Plan



https://github.com/user-attachments/assets/f3f9d10a-ecc4-4ffe-8676-3633a12e07ce
2025-04-07 18:39:21 +02:00
renovate[bot]
27ecf350d8 Update Rust crate clap to v4.5.35 (#17273)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.34` -> `4.5.35` |

---

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

---

### Release Notes

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

###
[`v4.5.35`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4535---2025-04-01)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.34...v4.5.35)

##### Fixes

- *(help)* Align positionals and flags when put in the same
`help_heading`
-   *(help)* Don't leave space for shorts if there are none

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-07 14:25:05 +00:00
Max Mynter
f1d4ba32cc Fix RUF100 to detect unused file-level noqa directives with specific codes (#17042) (#17061)
Closes #17042

## Summary
This PR fixes the issue outlined in #17042 where RUF100 (unused-noqa)
fails to detect unused file-level noqa directives (`# ruff: noqa` or `#
ruff: noqa: {code}`).

The issue stems from two underlying causes:

1. For blanket file-level directives (`# ruff: noqa`), there's a
circular dependency: the directive exempts all rules including RUF100
itself, which prevents checking for usage. This isn't changed by this
PR. I would argue it is intendend behavior - a blanket `# ruff: noqa`
directive should exempt all rules including RUF100 itself.

2. For code-specific file-level directives (e.g. `# ruff: noqa: F841`),
the handling was missing in the `check_noqa` function. This is added in
this PR.

## Notes
- For file-level directives, the `matches` array is pre-populated with
the specified codes during parsing, unlike line-level directives which
only populate their `matches` array when actually suppressing
diagnostics. This difference requires the somewhat clunky handling of
both cases. I would appreciate guidance on a cleaner design :)

- A more fundamental solution would be to change how file-level
directives initialize the `matches` array in
`FileNoqaDirectives::extract()`, but that requires more substantial
changes as it breaks existing functionality. I suspect discussions in
#16483 are relevant for this.

## Test Plan
- Local verification
- Added a test case and fixture
2025-04-07 09:21:52 -05:00
Micha Reiser
83a97235ae [ci] Fix pattern for code changes (#17275)
## Summary

`**/*` only matches files in a subdirectory whereas `**` matches any
file at an arbitrary depth

> A trailing "/**" matches everything inside. For example, "abc/**"
matches all files inside directory "abc", relative to the location of
the .gitignore file, with infinite depth.

> A leading "**" followed by a slash means match in all directories. For
example, "**/foo" matches file or directory "foo" anywhere, the same as
pattern "foo". "**/foo/bar" matches file or directory "bar" anywhere
that is directly under directory "foo".
2025-04-07 16:05:05 +02:00
Wei Lee
1e9e423362 [airflow] Update oudated AIR301, AIR302 rules (#17123)
## Summary

Some of the migration rules has been changed during Airflow 3
development. The following are new AIR302 rules. Corresponding AIR301
has also been removed.

* airflow.sensors.external_task_sensor.ExternalTaskMarker →
airflow.providers.standard.sensors.external_task.ExternalTaskMarker
* airflow.sensors.external_task_sensor.ExternalTaskSensor →
airflow.providers.standard.sensors.external_task.ExternalTaskSensor
* airflow.sensors.external_task_sensor.ExternalTaskSensorLink →
airflow.providers.standard.sensors.external_task.ExternalTaskSensorLink
* airflow.sensors.time_delta_sensor.TimeDeltaSensor →
airflow.providers.standard.sensors.time_delta.TimeDeltaSensor
* airflow.operators.dagrun_operator.TriggerDagRunLink →
airflow.providers.standard.operators.trigger_dagrun.TriggerDagRunLink
* airflow.operators.dagrun_operator.TriggerDagRunOperator →
airflow.providers.standard.operators.trigger_dagrun.TriggerDagRunOperator
* airflow.operators.python_operator.BranchPythonOperator →
airflow.providers.standard.operators.python.BranchPythonOperator
* airflow.operators.python_operator.PythonOperator →
airflow.providers.standard.operators.python.PythonOperator
* airflow.operators.python_operator.PythonVirtualenvOperator →
airflow.providers.standard.operators.python.PythonVirtualenvOperator
* airflow.operators.python_operator.ShortCircuitOperator →
airflow.providers.standard.operators.python.ShortCircuitOperator
* airflow.operators.latest_only_operator.LatestOnlyOperator →
airflow.providers.standard.operators.latest_only.LatestOnlyOperator
* airflow.sensors.date_time_sensor.DateTimeSensor →
airflow.providers.standard.sensors.DateTimeSensor
* airflow.operators.email_operator.EmailOperator →
airflow.providers.smtp.operators.smtp.EmailOperator
* airflow.operators.email.EmailOperator →
airflow.providers.smtp.operators.smtp.EmailOperator
* airflow.operators.bash.BashOperator →
airflow.providers.standard.operators.bash.BashOperator
* airflow.operators.EmptyOperator →
airflow.providers.standard.operators.empty.EmptyOperator

closes: https://github.com/astral-sh/ruff/issues/17103

## Test Plan

The test fixture has been updated and checked after each change and
later reorganized in the latest commit
2025-04-07 09:45:56 -04:00
Bruno Alla
708b84fb87 [docs] fix formatting of "See Style Guide" link (#17272)
<!--
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

Minor formatting tweak in the docs. Looks like the link is meant to be
italic (others "See XXXX" are), but the opening underscore isn't closed
so it's displayed in the rendered version:
https://docs.astral.sh/ruff/formatter/#philosophy


![image](https://github.com/user-attachments/assets/e5984a90-3ea6-4afc-a561-2c681519c78d)


## Test Plan

<!-- How was it tested? -->
2025-04-07 12:43:26 +00:00
Micha Reiser
6cc2d02dfa [red-knot] Support stub packages (#17204)
## Summary

This PR adds support for stub packages, except for partial stub packages
(a stub package is always considered non-partial).

I read the specification at
[typing.python.org/en/latest/spec/distributing.html#stub-only-packages](https://typing.python.org/en/latest/spec/distributing.html#stub-only-packages)
but I found it lacking some details, especially on how to handle
namespace packages or when the regular and stub packages disagree on
whether they're namespace packages. I tried to document my decisions in
the mdtests where the specification isn't clear and compared the
behavior to Pyright.

Mypy seems to only support stub packages in the venv folder. At least,
it never picked up my stub packages otherwise. I decided not to spend
too much time fighting mypyp, which is why I focused the comparison
around Pyright

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

## Test plan

Added mdtests
2025-04-07 14:40:50 +02:00
Andrew Gallant
c12c76e9c8 ruff_annotate_snippets: address unused code warnings
Fixes #17230
2025-04-07 08:24:08 -04:00
Alex Waygood
81cf860dc8 [red-knot] Add a couple more tests for * imports (#17270)
## Summary

Some more edge cases that I thought of while working on integrating
knowledge of statically known branches into the `*`-import machinery

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-04-07 11:12:28 +00:00
Micha Reiser
3150812ac4 [red-knot] Add 'Format document' to playground (#17217)
## Summary
This is more "because we can" than something we need. 

But since we're already building an "almost IDE" 

## Test Plan



https://github.com/user-attachments/assets/3a4bdad1-ba32-455a-9909-cfeb8caa1b28
2025-04-07 09:26:03 +02:00
renovate[bot]
12d7fad4ef Update actions/setup-node action to v4.3.0 (#17259)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | minor | `v4` -> `v4.3.0` |

---

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

---

### Release Notes

<details>
<summary>actions/setup-node (actions/setup-node)</summary>

###
[`v4.3.0`](https://redirect.github.com/actions/setup-node/compare/v4.2.0...v4.3.0)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v4.2.0...v4.3.0)

###
[`v4.2.0`](https://redirect.github.com/actions/setup-node/releases/tag/v4.2.0)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v4.1.0...v4.2.0)

#### What's Changed

- Enhance workflows and upgrade publish-actions from 0.2.2 to 0.3.0 by
[@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y) in
[https://github.com/actions/setup-node/pull/1174](https://redirect.github.com/actions/setup-node/pull/1174)
- Add recommended permissions section to readme by
[@&#8203;benwells](https://redirect.github.com/benwells) in
[https://github.com/actions/setup-node/pull/1193](https://redirect.github.com/actions/setup-node/pull/1193)
- Configure Dependabot settings by
[@&#8203;HarithaVattikuti](https://redirect.github.com/HarithaVattikuti)
in
[https://github.com/actions/setup-node/pull/1192](https://redirect.github.com/actions/setup-node/pull/1192)
- Upgrade `@actions/cache` to `^4.0.0` by
[@&#8203;priyagupta108](https://redirect.github.com/priyagupta108) in
[https://github.com/actions/setup-node/pull/1191](https://redirect.github.com/actions/setup-node/pull/1191)
- Upgrade pnpm/action-setup from 2 to 4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-node/pull/1194](https://redirect.github.com/actions/setup-node/pull/1194)
- Upgrade actions/publish-immutable-action from 0.0.3 to 0.0.4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-node/pull/1195](https://redirect.github.com/actions/setup-node/pull/1195)
- Upgrade semver from 7.6.0 to 7.6.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-node/pull/1196](https://redirect.github.com/actions/setup-node/pull/1196)
- Upgrade [@&#8203;types/jest](https://redirect.github.com/types/jest)
from 29.5.12 to 29.5.14 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-node/pull/1201](https://redirect.github.com/actions/setup-node/pull/1201)
- Upgrade undici from 5.28.4 to 5.28.5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-node/pull/1205](https://redirect.github.com/actions/setup-node/pull/1205)

#### New Contributors

- [@&#8203;benwells](https://redirect.github.com/benwells) made their
first contribution in
[https://github.com/actions/setup-node/pull/1193](https://redirect.github.com/actions/setup-node/pull/1193)

**Full Changelog**:
https://github.com/actions/setup-node/compare/v4...v4.2.0

###
[`v4.1.0`](https://redirect.github.com/actions/setup-node/releases/tag/v4.1.0)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v4.0.4...v4.1.0)

#### What's Changed

- Resolve High Security Alerts by upgrading Dependencies by
[@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y) in
[https://github.com/actions/setup-node/pull/1132](https://redirect.github.com/actions/setup-node/pull/1132)
- Upgrade IA Publish by
[@&#8203;Jcambass](https://redirect.github.com/Jcambass) in
[https://github.com/actions/setup-node/pull/1134](https://redirect.github.com/actions/setup-node/pull/1134)
- Revise `isGhes` logic by
[@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/setup-node/pull/1148](https://redirect.github.com/actions/setup-node/pull/1148)
- Add architecture to cache key by
[@&#8203;pengx17](https://redirect.github.com/pengx17) in
[https://github.com/actions/setup-node/pull/843](https://redirect.github.com/actions/setup-node/pull/843)
This addresses issues with caching by adding the architecture (arch) to
the cache key, ensuring that cache keys are accurate to prevent
conflicts.
Note: This change may break previous cache keys as they will no longer
be compatible with the new format.

#### New Contributors

- [@&#8203;jww3](https://redirect.github.com/jww3) made their first
contribution in
[https://github.com/actions/setup-node/pull/1148](https://redirect.github.com/actions/setup-node/pull/1148)
- [@&#8203;pengx17](https://redirect.github.com/pengx17) made their
first contribution in
[https://github.com/actions/setup-node/pull/843](https://redirect.github.com/actions/setup-node/pull/843)

**Full Changelog**:
https://github.com/actions/setup-node/compare/v4...v4.1.0

###
[`v4.0.4`](https://redirect.github.com/actions/setup-node/releases/tag/v4.0.4)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v4.0.3...v4.0.4)

#### What's Changed

- Add workflow file for publishing releases to immutable action package
by [@&#8203;Jcambass](https://redirect.github.com/Jcambass) in
[https://github.com/actions/setup-node/pull/1125](https://redirect.github.com/actions/setup-node/pull/1125)
- Enhance Windows ARM64 Setup and Update micromatch Dependency by
[@&#8203;priyagupta108](https://redirect.github.com/priyagupta108) in
[https://github.com/actions/setup-node/pull/1126](https://redirect.github.com/actions/setup-node/pull/1126)

##### Documentation changes:

- Documentation update in the README file by
[@&#8203;suyashgaonkar](https://redirect.github.com/suyashgaonkar) in
[https://github.com/actions/setup-node/pull/1106](https://redirect.github.com/actions/setup-node/pull/1106)
- Correct invalid 'lts' version string reference by
[@&#8203;fulldecent](https://redirect.github.com/fulldecent) in
[https://github.com/actions/setup-node/pull/1124](https://redirect.github.com/actions/setup-node/pull/1124)

#### New Contributors

- [@&#8203;suyashgaonkar](https://redirect.github.com/suyashgaonkar)
made their first contribution in
[https://github.com/actions/setup-node/pull/1106](https://redirect.github.com/actions/setup-node/pull/1106)
- [@&#8203;priyagupta108](https://redirect.github.com/priyagupta108)
made their first contribution in
[https://github.com/actions/setup-node/pull/1126](https://redirect.github.com/actions/setup-node/pull/1126)
- [@&#8203;Jcambass](https://redirect.github.com/Jcambass) made their
first contribution in
[https://github.com/actions/setup-node/pull/1125](https://redirect.github.com/actions/setup-node/pull/1125)
- [@&#8203;fulldecent](https://redirect.github.com/fulldecent) made
their first contribution in
[https://github.com/actions/setup-node/pull/1124](https://redirect.github.com/actions/setup-node/pull/1124)

**Full Changelog**:
https://github.com/actions/setup-node/compare/v4...v4.0.4

###
[`v4.0.3`](https://redirect.github.com/actions/setup-node/releases/tag/v4.0.3)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v4.0.2...v4.0.3)

##### What's Changed

##### Bug fixes:

- Fix macos latest check failures by
[@&#8203;HarithaVattikuti](https://redirect.github.com/HarithaVattikuti)
in
[https://github.com/actions/setup-node/pull/1041](https://redirect.github.com/actions/setup-node/pull/1041)

##### Documentation changes:

- Documentation update to update default Node version to 20 by
[@&#8203;bengreeley](https://redirect.github.com/bengreeley) in
[https://github.com/actions/setup-node/pull/949](https://redirect.github.com/actions/setup-node/pull/949)

##### Dependency  updates:

- Bump undici from 5.26.5 to 5.28.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-node/pull/965](https://redirect.github.com/actions/setup-node/pull/965)
- Bump braces from 3.0.2 to 3.0.3 and other dependency updates by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-node/pull/1087](https://redirect.github.com/actions/setup-node/pull/1087)

##### New Contributors

- [@&#8203;bengreeley](https://redirect.github.com/bengreeley) made
their first contribution in
[https://github.com/actions/setup-node/pull/949](https://redirect.github.com/actions/setup-node/pull/949)
-
[@&#8203;HarithaVattikuti](https://redirect.github.com/HarithaVattikuti)
made their first contribution in
[https://github.com/actions/setup-node/pull/1041](https://redirect.github.com/actions/setup-node/pull/1041)

**Full Changelog**:
https://github.com/actions/setup-node/compare/v4...v4.0.3

###
[`v4.0.2`](https://redirect.github.com/actions/setup-node/releases/tag/v4.0.2)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v4.0.1...v4.0.2)

##### What's Changed

- Add support for `volta.extends` by
[@&#8203;ThisIsManta](https://redirect.github.com/ThisIsManta) in
[https://github.com/actions/setup-node/pull/921](https://redirect.github.com/actions/setup-node/pull/921)
- Add support for arm64 Windows by
[@&#8203;dmitry-shibanov](https://redirect.github.com/dmitry-shibanov)
in
[https://github.com/actions/setup-node/pull/927](https://redirect.github.com/actions/setup-node/pull/927)

##### New Contributors

- [@&#8203;ThisIsManta](https://redirect.github.com/ThisIsManta) made
their first contribution in
[https://github.com/actions/setup-node/pull/921](https://redirect.github.com/actions/setup-node/pull/921)

**Full Changelog**:
https://github.com/actions/setup-node/compare/v4.0.1...v4.0.2

###
[`v4.0.1`](https://redirect.github.com/actions/setup-node/releases/tag/v4.0.1)

[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v4...v4.0.1)

##### What's Changed

- Ignore engines in Yarn 1 e2e-cache tests by
[@&#8203;trivikr](https://redirect.github.com/trivikr) in
[https://github.com/actions/setup-node/pull/882](https://redirect.github.com/actions/setup-node/pull/882)
- Update setup-node references in the README.md file to setup-node@v4 by
[@&#8203;jwetzell](https://redirect.github.com/jwetzell) in
[https://github.com/actions/setup-node/pull/884](https://redirect.github.com/actions/setup-node/pull/884)
- Update reusable workflows to use Node.js v20 by
[@&#8203;MaksimZhukov](https://redirect.github.com/MaksimZhukov) in
[https://github.com/actions/setup-node/pull/889](https://redirect.github.com/actions/setup-node/pull/889)
- Add fix for cache to resolve slow post action step by
[@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y) in
[https://github.com/actions/setup-node/pull/917](https://redirect.github.com/actions/setup-node/pull/917)
- Fix README.md by
[@&#8203;takayamaki](https://redirect.github.com/takayamaki) in
[https://github.com/actions/setup-node/pull/898](https://redirect.github.com/actions/setup-node/pull/898)
- Add `package.json` to `node-version-file` list of examples. by
[@&#8203;TWiStErRob](https://redirect.github.com/TWiStErRob) in
[https://github.com/actions/setup-node/pull/879](https://redirect.github.com/actions/setup-node/pull/879)
- Fix node-version-file interprets entire package.json as a version by
[@&#8203;NullVoxPopuli](https://redirect.github.com/NullVoxPopuli) in
[https://github.com/actions/setup-node/pull/865](https://redirect.github.com/actions/setup-node/pull/865)

##### New Contributors

- [@&#8203;trivikr](https://redirect.github.com/trivikr) made their
first contribution in
[https://github.com/actions/setup-node/pull/882](https://redirect.github.com/actions/setup-node/pull/882)
- [@&#8203;jwetzell](https://redirect.github.com/jwetzell) made their
first contribution in
[https://github.com/actions/setup-node/pull/884](https://redirect.github.com/actions/setup-node/pull/884)
- [@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y)
made their first contribution in
[https://github.com/actions/setup-node/pull/917](https://redirect.github.com/actions/setup-node/pull/917)
- [@&#8203;takayamaki](https://redirect.github.com/takayamaki) made
their first contribution in
[https://github.com/actions/setup-node/pull/898](https://redirect.github.com/actions/setup-node/pull/898)
- [@&#8203;TWiStErRob](https://redirect.github.com/TWiStErRob) made
their first contribution in
[https://github.com/actions/setup-node/pull/879](https://redirect.github.com/actions/setup-node/pull/879)
- [@&#8203;NullVoxPopuli](https://redirect.github.com/NullVoxPopuli)
made their first contribution in
[https://github.com/actions/setup-node/pull/865](https://redirect.github.com/actions/setup-node/pull/865)

**Full Changelog**:
https://github.com/actions/setup-node/compare/v4...v4.0.1

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 08:54:32 +02:00
renovate[bot]
41fec5171f Update actions/upload-artifact action to v4.6.2 (#17261)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/upload-artifact](https://redirect.github.com/actions/upload-artifact)
| action | minor | `v4` -> `v4.6.2` |

---

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

---

### Release Notes

<details>
<summary>actions/upload-artifact (actions/upload-artifact)</summary>

###
[`v4.6.2`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.6.2)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.6.1...v4.6.2)

#### What's Changed

- Update to use artifact 2.3.2 package & prepare for new upload-artifact
release by [@&#8203;salmanmkc](https://redirect.github.com/salmanmkc) in
[https://github.com/actions/upload-artifact/pull/685](https://redirect.github.com/actions/upload-artifact/pull/685)

#### New Contributors

- [@&#8203;salmanmkc](https://redirect.github.com/salmanmkc) made their
first contribution in
[https://github.com/actions/upload-artifact/pull/685](https://redirect.github.com/actions/upload-artifact/pull/685)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4...v4.6.2

###
[`v4.6.1`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.6.1)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.6.0...v4.6.1)

#### What's Changed

- Update to use artifact 2.2.2 package by
[@&#8203;yacaovsnc](https://redirect.github.com/yacaovsnc) in
[https://github.com/actions/upload-artifact/pull/673](https://redirect.github.com/actions/upload-artifact/pull/673)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4...v4.6.1

###
[`v4.6.0`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.6.0)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.5.0...v4.6.0)

##### What's Changed

- Expose env vars to control concurrency and timeout by
[@&#8203;yacaovsnc](https://redirect.github.com/yacaovsnc) in
[https://github.com/actions/upload-artifact/pull/662](https://redirect.github.com/actions/upload-artifact/pull/662)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4...v4.6.0

###
[`v4.5.0`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.5.0)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.4.3...v4.5.0)

##### What's Changed

- fix: deprecated `Node.js` version in action by
[@&#8203;hamirmahal](https://redirect.github.com/hamirmahal) in
[https://github.com/actions/upload-artifact/pull/578](https://redirect.github.com/actions/upload-artifact/pull/578)
- Add new `artifact-digest` output by
[@&#8203;bdehamer](https://redirect.github.com/bdehamer) in
[https://github.com/actions/upload-artifact/pull/656](https://redirect.github.com/actions/upload-artifact/pull/656)

##### New Contributors

- [@&#8203;hamirmahal](https://redirect.github.com/hamirmahal) made
their first contribution in
[https://github.com/actions/upload-artifact/pull/578](https://redirect.github.com/actions/upload-artifact/pull/578)
- [@&#8203;bdehamer](https://redirect.github.com/bdehamer) made their
first contribution in
[https://github.com/actions/upload-artifact/pull/656](https://redirect.github.com/actions/upload-artifact/pull/656)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.4.3...v4.5.0

###
[`v4.4.3`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.4.3)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.4.2...v4.4.3)

#### What's Changed

- Undo indirect dependency updates from
[#&#8203;627](https://redirect.github.com/actions/upload-artifact/issues/627)
by [@&#8203;joshmgross](https://redirect.github.com/joshmgross) in
[https://github.com/actions/upload-artifact/pull/632](https://redirect.github.com/actions/upload-artifact/pull/632)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.4.2...v4.4.3

###
[`v4.4.2`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.4.2)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.4.1...v4.4.2)

#### What's Changed

- Bump `@actions/artifact` to 2.1.11 by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/627](https://redirect.github.com/actions/upload-artifact/pull/627)
    -   Includes fix for relative symlinks not resolving properly

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.4.1...v4.4.2

###
[`v4.4.1`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.4.1)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.4.0...v4.4.1)

#### What's Changed

- Add a section about hidden files by
[@&#8203;joshmgross](https://redirect.github.com/joshmgross) in
[https://github.com/actions/upload-artifact/pull/607](https://redirect.github.com/actions/upload-artifact/pull/607)
- Add workflow file for publishing releases to immutable action package
by [@&#8203;Jcambass](https://redirect.github.com/Jcambass) in
[https://github.com/actions/upload-artifact/pull/621](https://redirect.github.com/actions/upload-artifact/pull/621)
- Update
[@&#8203;actions/artifact](https://redirect.github.com/actions/artifact)
to latest version, includes symlink and timeout fixes by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/625](https://redirect.github.com/actions/upload-artifact/pull/625)

#### New Contributors

- [@&#8203;Jcambass](https://redirect.github.com/Jcambass) made their
first contribution in
[https://github.com/actions/upload-artifact/pull/621](https://redirect.github.com/actions/upload-artifact/pull/621)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.4.0...v4.4.1

###
[`v4.4.0`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.4.0)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.3.6...v4.4.0)

#### Notice: Breaking Changes ⚠️

We will no longer include hidden files and folders by default in the
`upload-artifact` action of this version. This reduces the risk that
credentials are accidentally uploaded into artifacts. Customers who need
to continue to upload these files can use a new option,
`include-hidden-files`, to continue to do so.

See ["Notice of upcoming deprecations and breaking changes in GitHub
Actions
runners"](https://github.blog/changelog/2024-08-19-notice-of-upcoming-deprecations-and-breaking-changes-in-github-actions-runners/)
changelog and [this
issue](https://redirect.github.com/actions/upload-artifact/issues/602)
for more details.

#### What's Changed

- Exclude hidden files by default by
[@&#8203;joshmgross](https://redirect.github.com/joshmgross) in
[https://github.com/actions/upload-artifact/pull/598](https://redirect.github.com/actions/upload-artifact/pull/598)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.3.6...v4.4.0

###
[`v4.3.6`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.3.6)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.3.5...v4.3.6)

#### What's Changed

- Revert to
[@&#8203;actions/artifact](https://redirect.github.com/actions/artifact)
2.1.8 by [@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/594](https://redirect.github.com/actions/upload-artifact/pull/594)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4...v4.3.6

###
[`v4.3.5`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.3.5)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.3.4...v4.3.5)

#### What's Changed

- Bump
[@&#8203;actions/artifact](https://redirect.github.com/actions/artifact)
to v2.1.9 by [@&#8203;robherley](https://redirect.github.com/robherley)
in
[https://github.com/actions/upload-artifact/pull/588](https://redirect.github.com/actions/upload-artifact/pull/588)
- Fixed artifact upload chunk timeout logic
[#&#8203;1774](https://redirect.github.com/actions/toolkit/pull/1774)
- Use lazy stream to prevent issues with open file limits
[#&#8203;1771](https://redirect.github.com/actions/toolkit/pull/1771)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.3.4...v4.3.5

###
[`v4.3.4`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.3.4)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.3.3...v4.3.4)

#### What's Changed

- Update
[@&#8203;actions/artifact](https://redirect.github.com/actions/artifact)
version, bump dependencies by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/584](https://redirect.github.com/actions/upload-artifact/pull/584)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.3.3...v4.3.4

###
[`v4.3.3`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.3.3)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.3.2...v4.3.3)

#### What's Changed

- updating `@actions/artifact` dependency to v2.1.6 by
[@&#8203;eggyhead](https://redirect.github.com/eggyhead) in
[https://github.com/actions/upload-artifact/pull/565](https://redirect.github.com/actions/upload-artifact/pull/565)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.3.2...v4.3.3

###
[`v4.3.2`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.3.2)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.3.1...v4.3.2)

#### What's Changed

- Update release-new-action-version.yml by
[@&#8203;konradpabjan](https://redirect.github.com/konradpabjan) in
[https://github.com/actions/upload-artifact/pull/516](https://redirect.github.com/actions/upload-artifact/pull/516)
- Minor fix to the migration readme by
[@&#8203;andrewakim](https://redirect.github.com/andrewakim) in
[https://github.com/actions/upload-artifact/pull/523](https://redirect.github.com/actions/upload-artifact/pull/523)
- Update readme with v3/v2/v1 deprecation notice by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/561](https://redirect.github.com/actions/upload-artifact/pull/561)
- updating `@actions/artifact` dependency to v2.1.5 and `@actions/core`
to v1.0.1 by [@&#8203;eggyhead](https://redirect.github.com/eggyhead) in
[https://github.com/actions/upload-artifact/pull/562](https://redirect.github.com/actions/upload-artifact/pull/562)

#### New Contributors

- [@&#8203;andrewakim](https://redirect.github.com/andrewakim) made
their first contribution in
[https://github.com/actions/upload-artifact/pull/523](https://redirect.github.com/actions/upload-artifact/pull/523)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4.3.1...v4.3.2

###
[`v4.3.1`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.3.1)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.3.0...v4.3.1)

- Bump
[@&#8203;actions/artifacts](https://redirect.github.com/actions/artifacts)
to latest version to include [updated GHES host
check](https://redirect.github.com/actions/toolkit/pull/1648)

###
[`v4.3.0`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.3.0)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.2.0...v4.3.0)

#### What's Changed

- Reorganize upload code in prep for merge logic & add more tests by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/504](https://redirect.github.com/actions/upload-artifact/pull/504)
- Add sub-action to merge artifacts by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/505](https://redirect.github.com/actions/upload-artifact/pull/505)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4...v4.3.0

###
[`v4.2.0`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.2.0)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4.1.0...v4.2.0)

#### What's Changed

- Ability to overwrite an Artifact by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/501](https://redirect.github.com/actions/upload-artifact/pull/501)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4...v4.2.0

###
[`v4.1.0`](https://redirect.github.com/actions/upload-artifact/releases/tag/v4.1.0)

[Compare
Source](https://redirect.github.com/actions/upload-artifact/compare/v4...v4.1.0)

#### What's Changed

- Add migrations docs by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/482](https://redirect.github.com/actions/upload-artifact/pull/482)
- Update README.md by
[@&#8203;samuelwine](https://redirect.github.com/samuelwine) in
[https://github.com/actions/upload-artifact/pull/492](https://redirect.github.com/actions/upload-artifact/pull/492)
- Support artifact-url output by
[@&#8203;konradpabjan](https://redirect.github.com/konradpabjan) in
[https://github.com/actions/upload-artifact/pull/496](https://redirect.github.com/actions/upload-artifact/pull/496)
- Update readme to reflect new 500 artifact per job limit by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/upload-artifact/pull/497](https://redirect.github.com/actions/upload-artifact/pull/497)

#### New Contributors

- [@&#8203;samuelwine](https://redirect.github.com/samuelwine) made
their first contribution in
[https://github.com/actions/upload-artifact/pull/492](https://redirect.github.com/actions/upload-artifact/pull/492)

**Full Changelog**:
https://github.com/actions/upload-artifact/compare/v4...v4.1.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 08:49:44 +02:00
renovate[bot]
db69dfba45 Update actions/download-artifact action to v4.2.1 (#17258)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/download-artifact](https://redirect.github.com/actions/download-artifact)
| action | minor | `v4` -> `v4.2.1` |

---

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

---

### Release Notes

<details>
<summary>actions/download-artifact (actions/download-artifact)</summary>

###
[`v4.2.1`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.2.1)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.2.0...v4.2.1)

#### What's Changed

- Add unit tests by
[@&#8203;GhadimiR](https://redirect.github.com/GhadimiR) in
[https://github.com/actions/download-artifact/pull/392](https://redirect.github.com/actions/download-artifact/pull/392)
- Fix bug introduced in 4.2.0 by
[@&#8203;GhadimiR](https://redirect.github.com/GhadimiR) in
[https://github.com/actions/download-artifact/pull/391](https://redirect.github.com/actions/download-artifact/pull/391)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4.2.0...v4.2.1

###
[`v4.2.0`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.2.0)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.9...v4.2.0)

#### What's Changed

- Update README.md by
[@&#8203;lkfortuna](https://redirect.github.com/lkfortuna) in
[https://github.com/actions/download-artifact/pull/384](https://redirect.github.com/actions/download-artifact/pull/384)
- Bump artifact version, do digest check by
[@&#8203;GhadimiR](https://redirect.github.com/GhadimiR) in
[https://github.com/actions/download-artifact/pull/383](https://redirect.github.com/actions/download-artifact/pull/383)

#### New Contributors

- [@&#8203;lkfortuna](https://redirect.github.com/lkfortuna) made their
first contribution in
[https://github.com/actions/download-artifact/pull/384](https://redirect.github.com/actions/download-artifact/pull/384)
- [@&#8203;GhadimiR](https://redirect.github.com/GhadimiR) made their
first contribution in
[https://github.com/actions/download-artifact/pull/383](https://redirect.github.com/actions/download-artifact/pull/383)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4.1.9...v4.2.0

###
[`v4.1.9`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.9)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.8...v4.1.9)

#### What's Changed

- Add workflow file for publishing releases to immutable action package
by [@&#8203;Jcambass](https://redirect.github.com/Jcambass) in
[https://github.com/actions/download-artifact/pull/354](https://redirect.github.com/actions/download-artifact/pull/354)
- docs: small migration fix by
[@&#8203;froblesmartin](https://redirect.github.com/froblesmartin) in
[https://github.com/actions/download-artifact/pull/370](https://redirect.github.com/actions/download-artifact/pull/370)
- Update MIGRATION.md by
[@&#8203;andyfeller](https://redirect.github.com/andyfeller) in
[https://github.com/actions/download-artifact/pull/372](https://redirect.github.com/actions/download-artifact/pull/372)
- Update artifact package to 2.2.2 by
[@&#8203;yacaovsnc](https://redirect.github.com/yacaovsnc) in
[https://github.com/actions/download-artifact/pull/380](https://redirect.github.com/actions/download-artifact/pull/380)

#### New Contributors

- [@&#8203;Jcambass](https://redirect.github.com/Jcambass) made their
first contribution in
[https://github.com/actions/download-artifact/pull/354](https://redirect.github.com/actions/download-artifact/pull/354)
- [@&#8203;froblesmartin](https://redirect.github.com/froblesmartin)
made their first contribution in
[https://github.com/actions/download-artifact/pull/370](https://redirect.github.com/actions/download-artifact/pull/370)
- [@&#8203;andyfeller](https://redirect.github.com/andyfeller) made
their first contribution in
[https://github.com/actions/download-artifact/pull/372](https://redirect.github.com/actions/download-artifact/pull/372)
- [@&#8203;yacaovsnc](https://redirect.github.com/yacaovsnc) made their
first contribution in
[https://github.com/actions/download-artifact/pull/380](https://redirect.github.com/actions/download-artifact/pull/380)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4...v4.1.9

###
[`v4.1.8`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.8)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.7...v4.1.8)

#### What's Changed

- Update
[@&#8203;actions/artifact](https://redirect.github.com/actions/artifact)
version, bump dependencies by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/download-artifact/pull/341](https://redirect.github.com/actions/download-artifact/pull/341)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4...v4.1.8

###
[`v4.1.7`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.7)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.6...v4.1.7)

#### What's Changed

- Update
[@&#8203;actions/artifact](https://redirect.github.com/actions/artifact)
dependency by
[@&#8203;bethanyj28](https://redirect.github.com/bethanyj28) in
[https://github.com/actions/download-artifact/pull/325](https://redirect.github.com/actions/download-artifact/pull/325)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4.1.6...v4.1.7

###
[`v4.1.6`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.6)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.5...v4.1.6)

#### What's Changed

- updating `@actions/artifact` dependency to v2.1.6 by
[@&#8203;eggyhead](https://redirect.github.com/eggyhead) in
[https://github.com/actions/download-artifact/pull/324](https://redirect.github.com/actions/download-artifact/pull/324)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4.1.5...v4.1.6

###
[`v4.1.5`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.5)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.4...v4.1.5)

#### What's Changed

- Update readme with v3/v2/v1 deprecation notice by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/download-artifact/pull/322](https://redirect.github.com/actions/download-artifact/pull/322)
- Update dependencies `@actions/core` to v1.10.1 and `@actions/artifact`
to v2.1.5

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4.1.4...v4.1.5

###
[`v4.1.4`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.4)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.3...v4.1.4)

#### What's Changed

- Update
[@&#8203;actions/artifact](https://redirect.github.com/actions/artifact)
by [@&#8203;bethanyj28](https://redirect.github.com/bethanyj28) in
[https://github.com/actions/download-artifact/pull/307](https://redirect.github.com/actions/download-artifact/pull/307)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4...v4.1.4

###
[`v4.1.3`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.3)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.2...v4.1.3)

#### What's Changed

- Update release-new-action-version.yml by
[@&#8203;konradpabjan](https://redirect.github.com/konradpabjan) in
[https://github.com/actions/download-artifact/pull/292](https://redirect.github.com/actions/download-artifact/pull/292)
- Update toolkit dependency with updated unzip logic by
[@&#8203;bethanyj28](https://redirect.github.com/bethanyj28) in
[https://github.com/actions/download-artifact/pull/299](https://redirect.github.com/actions/download-artifact/pull/299)
- Update
[@&#8203;actions/artifact](https://redirect.github.com/actions/artifact)
by [@&#8203;bethanyj28](https://redirect.github.com/bethanyj28) in
[https://github.com/actions/download-artifact/pull/303](https://redirect.github.com/actions/download-artifact/pull/303)

#### New Contributors

- [@&#8203;bethanyj28](https://redirect.github.com/bethanyj28) made
their first contribution in
[https://github.com/actions/download-artifact/pull/299](https://redirect.github.com/actions/download-artifact/pull/299)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4...v4.1.3

###
[`v4.1.2`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.2)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.1...v4.1.2)

- Bump
[@&#8203;actions/artifacts](https://redirect.github.com/actions/artifacts)
to latest version to include [updated GHES host
check](https://redirect.github.com/actions/toolkit/pull/1648)

###
[`v4.1.1`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.1)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4.1.0...v4.1.1)

- Fix transient request timeouts
[https://github.com/actions/download-artifact/issues/249](https://redirect.github.com/actions/download-artifact/issues/249)
-   Bump `@actions/artifacts` to latest version

###
[`v4.1.0`](https://redirect.github.com/actions/download-artifact/releases/tag/v4.1.0)

[Compare
Source](https://redirect.github.com/actions/download-artifact/compare/v4...v4.1.0)

#### What's Changed

- Some cleanup by
[@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/download-artifact/pull/247](https://redirect.github.com/actions/download-artifact/pull/247)
- Fix default for run-id by
[@&#8203;stchr](https://redirect.github.com/stchr) in
[https://github.com/actions/download-artifact/pull/252](https://redirect.github.com/actions/download-artifact/pull/252)
- Support pattern matching to filter artifacts & merge to same directory
by [@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/download-artifact/pull/259](https://redirect.github.com/actions/download-artifact/pull/259)

#### New Contributors

- [@&#8203;stchr](https://redirect.github.com/stchr) made their first
contribution in
[https://github.com/actions/download-artifact/pull/252](https://redirect.github.com/actions/download-artifact/pull/252)

**Full Changelog**:
https://github.com/actions/download-artifact/compare/v4...v4.1.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 06:49:17 +00:00
renovate[bot]
50eb3f539e Update actions/setup-python action to v5.5.0 (#17260)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/setup-python](https://redirect.github.com/actions/setup-python)
| action | minor | `v5` -> `v5.5.0` |

---

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

---

### Release Notes

<details>
<summary>actions/setup-python (actions/setup-python)</summary>

###
[`v5.5.0`](https://redirect.github.com/actions/setup-python/releases/tag/v5.5.0)

[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v5.4.0...v5.5.0)

##### What's Changed

##### Enhancements:

- Support free threaded Python versions like '3.13t' by
[@&#8203;colesbury](https://redirect.github.com/colesbury) in
[https://github.com/actions/setup-python/pull/973](https://redirect.github.com/actions/setup-python/pull/973)
- Enhance Workflows: Include ubuntu-arm runners, Add e2e Testing for
free threaded and Upgrade
[@&#8203;action/cache](https://redirect.github.com/action/cache) from
4.0.0 to 4.0.3 by
[@&#8203;priya-kinthali](https://redirect.github.com/priya-kinthali) in
[https://github.com/actions/setup-python/pull/1056](https://redirect.github.com/actions/setup-python/pull/1056)
- Add support for .tool-versions file in setup-python by
[@&#8203;mahabaleshwars](https://redirect.github.com/mahabaleshwars) in
[https://github.com/actions/setup-python/pull/1043](https://redirect.github.com/actions/setup-python/pull/1043)

##### Bug fixes:

- Fix architecture for pypy on Linux ARM64 by
[@&#8203;mayeut](https://redirect.github.com/mayeut) in
[https://github.com/actions/setup-python/pull/1011](https://redirect.github.com/actions/setup-python/pull/1011)
This update maps arm64 to aarch64 for Linux ARM64 PyPy installations.

##### Dependency updates:

- Upgrade [@&#8203;vercel/ncc](https://redirect.github.com/vercel/ncc)
from 0.38.1 to 0.38.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-python/pull/1016](https://redirect.github.com/actions/setup-python/pull/1016)
- Upgrade
[@&#8203;actions/glob](https://redirect.github.com/actions/glob) from
0.4.0 to 0.5.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-python/pull/1015](https://redirect.github.com/actions/setup-python/pull/1015)

##### New Contributors

- [@&#8203;colesbury](https://redirect.github.com/colesbury) made their
first contribution in
[https://github.com/actions/setup-python/pull/973](https://redirect.github.com/actions/setup-python/pull/973)
- [@&#8203;mahabaleshwars](https://redirect.github.com/mahabaleshwars)
made their first contribution in
[https://github.com/actions/setup-python/pull/1043](https://redirect.github.com/actions/setup-python/pull/1043)

**Full Changelog**:
https://github.com/actions/setup-python/compare/v5...v5.5.0

###
[`v5.4.0`](https://redirect.github.com/actions/setup-python/releases/tag/v5.4.0)

[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v5.3.0...v5.4.0)

#### What's Changed

##### Enhancements:

- Update cache error message by
[@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y) in
[https://github.com/actions/setup-python/pull/968](https://redirect.github.com/actions/setup-python/pull/968)
- Enhance Workflows: Add Ubuntu-24, Remove Python 3.8 by
[@&#8203;priya-kinthali](https://redirect.github.com/priya-kinthali) in
[https://github.com/actions/setup-python/pull/985](https://redirect.github.com/actions/setup-python/pull/985)
- Configure Dependabot settings by
[@&#8203;HarithaVattikuti](https://redirect.github.com/HarithaVattikuti)
in
[https://github.com/actions/setup-python/pull/1008](https://redirect.github.com/actions/setup-python/pull/1008)

##### Documentation changes:

- Readme update - recommended permissions by
[@&#8203;benwells](https://redirect.github.com/benwells) in
[https://github.com/actions/setup-python/pull/1009](https://redirect.github.com/actions/setup-python/pull/1009)
- Improve Advanced Usage examples by
[@&#8203;lrq3000](https://redirect.github.com/lrq3000) in
[https://github.com/actions/setup-python/pull/645](https://redirect.github.com/actions/setup-python/pull/645)

##### Dependency updates:

- Upgrade `undici` from 5.28.4 to 5.28.5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-python/pull/1012](https://redirect.github.com/actions/setup-python/pull/1012)
- Upgrade `urllib3` from 1.25.9 to 1.26.19 in /**tests**/data by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-python/pull/895](https://redirect.github.com/actions/setup-python/pull/895)
- Upgrade `actions/publish-immutable-action` from 0.0.3 to 0.0.4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-python/pull/1014](https://redirect.github.com/actions/setup-python/pull/1014)
- Upgrade `@actions/http-client` from 2.2.1 to 2.2.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-python/pull/1020](https://redirect.github.com/actions/setup-python/pull/1020)
- Upgrade `requests` from 2.24.0 to 2.32.2 in /**tests**/data by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-python/pull/1019](https://redirect.github.com/actions/setup-python/pull/1019)
- Upgrade `@actions/cache` to `^4.0.0` by
[@&#8203;priyagupta108](https://redirect.github.com/priyagupta108) in
[https://github.com/actions/setup-python/pull/1007](https://redirect.github.com/actions/setup-python/pull/1007)

#### New Contributors

- [@&#8203;benwells](https://redirect.github.com/benwells) made their
first contribution in
[https://github.com/actions/setup-python/pull/1009](https://redirect.github.com/actions/setup-python/pull/1009)
-
[@&#8203;HarithaVattikuti](https://redirect.github.com/HarithaVattikuti)
made their first contribution in
[https://github.com/actions/setup-python/pull/1008](https://redirect.github.com/actions/setup-python/pull/1008)
- [@&#8203;lrq3000](https://redirect.github.com/lrq3000) made their
first contribution in
[https://github.com/actions/setup-python/pull/645](https://redirect.github.com/actions/setup-python/pull/645)

**Full Changelog**:
https://github.com/actions/setup-python/compare/v5...v5.4.0

###
[`v5.3.0`](https://redirect.github.com/actions/setup-python/releases/tag/v5.3.0)

[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v5.2.0...v5.3.0)

##### What's Changed

- Add workflow file for publishing releases to immutable action package
by [@&#8203;Jcambass](https://redirect.github.com/Jcambass) in
[https://github.com/actions/setup-python/pull/941](https://redirect.github.com/actions/setup-python/pull/941)
- Upgrade IA publish by
[@&#8203;Jcambass](https://redirect.github.com/Jcambass) in
[https://github.com/actions/setup-python/pull/943](https://redirect.github.com/actions/setup-python/pull/943)

##### Bug Fixes:

- Normalise Line Endings to Ensure Cross-Platform Consistency by
[@&#8203;priya-kinthali](https://redirect.github.com/priya-kinthali) in
[https://github.com/actions/setup-python/pull/938](https://redirect.github.com/actions/setup-python/pull/938)
- Revise `isGhes` logic by
[@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/setup-python/pull/963](https://redirect.github.com/actions/setup-python/pull/963)
- Bump pillow from 7.2 to 10.2.0 by
[@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y) in
[https://github.com/actions/setup-python/pull/956](https://redirect.github.com/actions/setup-python/pull/956)

##### Enhancements:

- Enhance workflows and documentation updates by
[@&#8203;priya-kinthali](https://redirect.github.com/priya-kinthali) in
[https://github.com/actions/setup-python/pull/965](https://redirect.github.com/actions/setup-python/pull/965)
- Bump default versions to latest by
[@&#8203;jeffwidman](https://redirect.github.com/jeffwidman) in
[https://github.com/actions/setup-python/pull/905](https://redirect.github.com/actions/setup-python/pull/905)

##### New Contributors

- [@&#8203;Jcambass](https://redirect.github.com/Jcambass) made their
first contribution in
[https://github.com/actions/setup-python/pull/941](https://redirect.github.com/actions/setup-python/pull/941)
- [@&#8203;jww3](https://redirect.github.com/jww3) made their first
contribution in
[https://github.com/actions/setup-python/pull/963](https://redirect.github.com/actions/setup-python/pull/963)

**Full Changelog**:
https://github.com/actions/setup-python/compare/v5...v5.3.0

###
[`v5.2.0`](https://redirect.github.com/actions/setup-python/releases/tag/v5.2.0)

[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v5.1.1...v5.2.0)

#### What's Changed

##### Bug fixes:

- Add `.zip` extension to Windows package downloads for `Expand-Archive`
Compatibility by
[@&#8203;priyagupta108](https://redirect.github.com/priyagupta108) in
[https://github.com/actions/setup-python/pull/916](https://redirect.github.com/actions/setup-python/pull/916)
This addresses compatibility issues on Windows self-hosted runners by
ensuring that the filenames for Python and PyPy package downloads
explicitly include the .zip extension, allowing the Expand-Archive
command to function correctly.
- Add arch to cache key by
[@&#8203;Zxilly](https://redirect.github.com/Zxilly) in
[https://github.com/actions/setup-python/pull/896](https://redirect.github.com/actions/setup-python/pull/896)
This addresses issues with caching by adding the architecture (arch) to
the cache key, ensuring that cache keys are accurate to prevent
conflicts.
Note: This change may break previous cache keys as they will no longer
be compatible with the new format.

##### Documentation changes:

- Fix display of emojis in contributors doc by
[@&#8203;sciencewhiz](https://redirect.github.com/sciencewhiz) in
[https://github.com/actions/setup-python/pull/899](https://redirect.github.com/actions/setup-python/pull/899)
- Documentation update for caching poetry dependencies by
[@&#8203;gowridurgad](https://redirect.github.com/gowridurgad) in
[https://github.com/actions/setup-python/pull/908](https://redirect.github.com/actions/setup-python/pull/908)

##### Dependency updates:

- Bump [@&#8203;iarna/toml](https://redirect.github.com/iarna/toml)
version from 2.2.5 to 3.0.0 by
[@&#8203;priya-kinthali](https://redirect.github.com/priya-kinthali) in
[https://github.com/actions/setup-python/pull/912](https://redirect.github.com/actions/setup-python/pull/912)
- Bump pyinstaller from 3.6 to 5.13.1 by
[@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y) in
[https://github.com/actions/setup-python/pull/923](https://redirect.github.com/actions/setup-python/pull/923)

#### New Contributors

- [@&#8203;sciencewhiz](https://redirect.github.com/sciencewhiz) made
their first contribution in
[https://github.com/actions/setup-python/pull/899](https://redirect.github.com/actions/setup-python/pull/899)
- [@&#8203;priyagupta108](https://redirect.github.com/priyagupta108)
made their first contribution in
[https://github.com/actions/setup-python/pull/916](https://redirect.github.com/actions/setup-python/pull/916)
- [@&#8203;Zxilly](https://redirect.github.com/Zxilly) made their first
contribution in
[https://github.com/actions/setup-python/pull/896](https://redirect.github.com/actions/setup-python/pull/896)
- [@&#8203;aparnajyothi-y](https://redirect.github.com/aparnajyothi-y)
made their first contribution in
[https://github.com/actions/setup-python/pull/923](https://redirect.github.com/actions/setup-python/pull/923)

**Full Changelog**:
https://github.com/actions/setup-python/compare/v5...v5.2.0

###
[`v5.1.1`](https://redirect.github.com/actions/setup-python/releases/tag/v5.1.1)

[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v5.1.0...v5.1.1)

#### What's Changed

##### Bug fixes:

- fix(ci): update all failing workflows by
[@&#8203;mayeut](https://redirect.github.com/mayeut) in
[https://github.com/actions/setup-python/pull/863](https://redirect.github.com/actions/setup-python/pull/863)
This update ensures compatibility and optimal performance of workflows
on the latest macOS version.

##### Documentation changes:

- Documentation update for cache by
[@&#8203;gowridurgad](https://redirect.github.com/gowridurgad) in
[https://github.com/actions/setup-python/pull/873](https://redirect.github.com/actions/setup-python/pull/873)

##### Dependency updates:

- Bump braces from 3.0.2 to 3.0.3 and undici from 5.28.3 to 5.28.4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/setup-python/pull/893](https://redirect.github.com/actions/setup-python/pull/893)

#### New Contributors

- [@&#8203;gowridurgad](https://redirect.github.com/gowridurgad) made
their first contribution in
[https://github.com/actions/setup-python/pull/873](https://redirect.github.com/actions/setup-python/pull/873)

**Full Changelog**:
https://github.com/actions/setup-python/compare/v5...v5.1.1

###
[`v5.1.0`](https://redirect.github.com/actions/setup-python/releases/tag/v5.1.0)

[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v5.0.0...v5.1.0)

#### What's Changed

- Leveraging the raw API to retrieve the version-manifest, as it does
not impose a rate limit and hence facilitates unrestricted consumption
without the need for a token for Github Enterprise Servers by
[@&#8203;Shegox](https://redirect.github.com/Shegox) in
[https://github.com/actions/setup-python/pull/766](https://redirect.github.com/actions/setup-python/pull/766).
- Dependency updates by
[@&#8203;dependabot](https://redirect.github.com/dependabot) and
[@&#8203;HarithaVattikuti](https://redirect.github.com/HarithaVattikuti)
in
[https://github.com/actions/setup-python/pull/817](https://redirect.github.com/actions/setup-python/pull/817)
- Documentation changes for version in README by
[@&#8203;basnijholt](https://redirect.github.com/basnijholt) in
[https://github.com/actions/setup-python/pull/776](https://redirect.github.com/actions/setup-python/pull/776)
- Documentation changes for link in README by
[@&#8203;ukd1](https://redirect.github.com/ukd1) in
[https://github.com/actions/setup-python/pull/793](https://redirect.github.com/actions/setup-python/pull/793)
- Documentation changes for link in Advanced Usage by
[@&#8203;Jamim](https://redirect.github.com/Jamim) in
[https://github.com/actions/setup-python/pull/782](https://redirect.github.com/actions/setup-python/pull/782)
- Documentation changes for avoiding rate limit issues on GHES by
[@&#8203;priya-kinthali](https://redirect.github.com/priya-kinthali) in
[https://github.com/actions/setup-python/pull/835](https://redirect.github.com/actions/setup-python/pull/835)

#### New Contributors

- [@&#8203;basnijholt](https://redirect.github.com/basnijholt) made
their first contribution in
[https://github.com/actions/setup-python/pull/776](https://redirect.github.com/actions/setup-python/pull/776)
- [@&#8203;ukd1](https://redirect.github.com/ukd1) made their first
contribution in
[https://github.com/actions/setup-python/pull/793](https://redirect.github.com/actions/setup-python/pull/793)
- [@&#8203;Jamim](https://redirect.github.com/Jamim) made their first
contribution in
[https://github.com/actions/setup-python/pull/782](https://redirect.github.com/actions/setup-python/pull/782)
- [@&#8203;Shegox](https://redirect.github.com/Shegox) made their first
contribution in
[https://github.com/actions/setup-python/pull/766](https://redirect.github.com/actions/setup-python/pull/766)
- [@&#8203;priya-kinthali](https://redirect.github.com/priya-kinthali)
made their first contribution in
[https://github.com/actions/setup-python/pull/835](https://redirect.github.com/actions/setup-python/pull/835)

**Full Changelog**:
https://github.com/actions/setup-python/compare/v5.0.0...v5.1.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 08:48:03 +02:00
renovate[bot]
ec30f18d02 Update actions/cache action to v4.2.3 (#17256)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/cache](https://redirect.github.com/actions/cache) | action |
minor | `v4` -> `v4.2.3` |

---

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

---

### Release Notes

<details>
<summary>actions/cache (actions/cache)</summary>

###
[`v4.2.3`](https://redirect.github.com/actions/cache/releases/tag/v4.2.3)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.2.2...v4.2.3)

##### What's Changed

- Update to use
[@&#8203;actions/cache](https://redirect.github.com/actions/cache) 4.0.3
package & prepare for new release by
[@&#8203;salmanmkc](https://redirect.github.com/salmanmkc) in
[https://github.com/actions/cache/pull/1577](https://redirect.github.com/actions/cache/pull/1577)
(SAS tokens for cache entries are now masked in debug logs)

##### New Contributors

- [@&#8203;salmanmkc](https://redirect.github.com/salmanmkc) made their
first contribution in
[https://github.com/actions/cache/pull/1577](https://redirect.github.com/actions/cache/pull/1577)

**Full Changelog**:
https://github.com/actions/cache/compare/v4.2.2...v4.2.3

###
[`v4.2.2`](https://redirect.github.com/actions/cache/releases/tag/v4.2.2)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.2.1...v4.2.2)

##### What's Changed

> \[!IMPORTANT]
> As a reminder, there were important backend changes to release v4.2.0,
see [those release
notes](https://redirect.github.com/actions/cache/releases/tag/v4.2.0)
and [the
announcement](https://redirect.github.com/actions/cache/discussions/1510)
for more details.

- Bump
[@&#8203;actions/cache](https://redirect.github.com/actions/cache) to
v4.0.2 by [@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/cache/pull/1560](https://redirect.github.com/actions/cache/pull/1560)

**Full Changelog**:
https://github.com/actions/cache/compare/v4.2.1...v4.2.2

###
[`v4.2.1`](https://redirect.github.com/actions/cache/releases/tag/v4.2.1)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.2.0...v4.2.1)

##### What's Changed

> \[!IMPORTANT]
> As a reminder, there were important backend changes to release v4.2.0,
see [those release
notes](https://redirect.github.com/actions/cache/releases/tag/v4.2.0)
and [the
announcement](https://redirect.github.com/actions/cache/discussions/1510)
for more details.

- docs: GitHub is spelled incorrectly in caching-strategies.md by
[@&#8203;janco-absa](https://redirect.github.com/janco-absa) in
[https://github.com/actions/cache/pull/1526](https://redirect.github.com/actions/cache/pull/1526)
- docs: Make the "always save prime numbers" example more clear by
[@&#8203;Tobbe](https://redirect.github.com/Tobbe) in
[https://github.com/actions/cache/pull/1525](https://redirect.github.com/actions/cache/pull/1525)
- Update force deletion docs due a recent deprecation by
[@&#8203;sebbalex](https://redirect.github.com/sebbalex) in
[https://github.com/actions/cache/pull/1500](https://redirect.github.com/actions/cache/pull/1500)
- Bump
[@&#8203;actions/cache](https://redirect.github.com/actions/cache) to
v4.0.1 by [@&#8203;robherley](https://redirect.github.com/robherley) in
[https://github.com/actions/cache/pull/1554](https://redirect.github.com/actions/cache/pull/1554)

##### New Contributors

- [@&#8203;janco-absa](https://redirect.github.com/janco-absa) made
their first contribution in
[https://github.com/actions/cache/pull/1526](https://redirect.github.com/actions/cache/pull/1526)
- [@&#8203;Tobbe](https://redirect.github.com/Tobbe) made their first
contribution in
[https://github.com/actions/cache/pull/1525](https://redirect.github.com/actions/cache/pull/1525)
- [@&#8203;sebbalex](https://redirect.github.com/sebbalex) made their
first contribution in
[https://github.com/actions/cache/pull/1500](https://redirect.github.com/actions/cache/pull/1500)

**Full Changelog**:
https://github.com/actions/cache/compare/v4.2.0...v4.2.1

###
[`v4.2.0`](https://redirect.github.com/actions/cache/releases/tag/v4.2.0)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.1.2...v4.2.0)

##### ⚠️ Important Changes

The cache backend service has been rewritten from the ground up for
improved performance and reliability.
[actions/cache](https://redirect.github.com/actions/cache) now
integrates with the new cache service (v2) APIs.

The new service will gradually roll out as of **February 1st, 2025**.
The legacy service will also be sunset on the same date. Changes in
these release are **fully backward compatible**.

**We are deprecating some versions of this action**. We recommend
upgrading to version `v4` or `v3` as soon as possible before **February
1st, 2025.** (Upgrade instructions below).

If you are using pinned SHAs, please use the SHAs of versions `v4.2.0`
or `v3.4.0`

If you do not upgrade, all workflow runs using any of the deprecated
[actions/cache](https://redirect.github.com/actions/cache) will fail.

Upgrading to the recommended versions will not break your workflows.

Read more about the change & access the migration guide: [reference to
the
announcement](https://redirect.github.com/actions/cache/discussions/1510).

##### Minor changes

Minor and patch version updates for these dependencies:

- [@&#8203;actions/core](https://redirect.github.com/actions/core):
`1.11.1`
- [@&#8203;actions/io](https://redirect.github.com/actions/io): `1.1.3`
- [@&#8203;vercel/ncc](https://redirect.github.com/vercel/ncc): `0.38.3`

**Full Changelog**:
https://github.com/actions/cache/compare/v4.1.2...v4.2.0

###
[`v4.1.2`](https://redirect.github.com/actions/cache/releases/tag/v4.1.2)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.1.1...v4.1.2)

##### What's Changed

- Add Bun example by
[@&#8203;idleberg](https://redirect.github.com/idleberg) in
[https://github.com/actions/cache/pull/1456](https://redirect.github.com/actions/cache/pull/1456)
- Revise `isGhes` logic by
[@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/cache/pull/1474](https://redirect.github.com/actions/cache/pull/1474)
- Bump braces from 3.0.2 to 3.0.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/cache/pull/1475](https://redirect.github.com/actions/cache/pull/1475)
- Add dependabot.yml to enable automatic dependency upgrades by
[@&#8203;Link-](https://redirect.github.com/Link-) in
[https://github.com/actions/cache/pull/1476](https://redirect.github.com/actions/cache/pull/1476)
- Bump actions/checkout from 3 to 4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/cache/pull/1478](https://redirect.github.com/actions/cache/pull/1478)
- Bump actions/stale from 3 to 9 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/cache/pull/1479](https://redirect.github.com/actions/cache/pull/1479)
- Bump github/codeql-action from 2 to 3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/cache/pull/1483](https://redirect.github.com/actions/cache/pull/1483)
- Bump actions/setup-node from 3 to 4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/cache/pull/1481](https://redirect.github.com/actions/cache/pull/1481)
- Prepare `4.1.2` release by
[@&#8203;Link-](https://redirect.github.com/Link-) in
[https://github.com/actions/cache/pull/1477](https://redirect.github.com/actions/cache/pull/1477)

##### New Contributors

- [@&#8203;idleberg](https://redirect.github.com/idleberg) made their
first contribution in
[https://github.com/actions/cache/pull/1456](https://redirect.github.com/actions/cache/pull/1456)
- [@&#8203;jww3](https://redirect.github.com/jww3) made their first
contribution in
[https://github.com/actions/cache/pull/1474](https://redirect.github.com/actions/cache/pull/1474)
- [@&#8203;Link-](https://redirect.github.com/Link-) made their first
contribution in
[https://github.com/actions/cache/pull/1476](https://redirect.github.com/actions/cache/pull/1476)

**Full Changelog**:
https://github.com/actions/cache/compare/v4.1.1...v4.1.2

###
[`v4.1.1`](https://redirect.github.com/actions/cache/releases/tag/v4.1.1)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.1.0...v4.1.1)

##### What's Changed

- Restore original behavior of `cache-hit` output by
[@&#8203;joshmgross](https://redirect.github.com/joshmgross) in
[https://github.com/actions/cache/pull/1467](https://redirect.github.com/actions/cache/pull/1467)

**Full Changelog**:
https://github.com/actions/cache/compare/v4.1.0...v4.1.1

###
[`v4.1.0`](https://redirect.github.com/actions/cache/releases/tag/v4.1.0)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.0.2...v4.1.0)

##### What's Changed

- Fix cache-hit output when cache missed by
[@&#8203;fchimpan](https://redirect.github.com/fchimpan) in
[https://github.com/actions/cache/pull/1404](https://redirect.github.com/actions/cache/pull/1404)
- Deprecate `save-always` input by
[@&#8203;joshmgross](https://redirect.github.com/joshmgross) in
[https://github.com/actions/cache/pull/1452](https://redirect.github.com/actions/cache/pull/1452)

##### New Contributors

- [@&#8203;ottlinger](https://redirect.github.com/ottlinger) made their
first contribution in
[https://github.com/actions/cache/pull/1437](https://redirect.github.com/actions/cache/pull/1437)
- [@&#8203;Olegt0rr](https://redirect.github.com/Olegt0rr) made their
first contribution in
[https://github.com/actions/cache/pull/1377](https://redirect.github.com/actions/cache/pull/1377)
- [@&#8203;fchimpan](https://redirect.github.com/fchimpan) made their
first contribution in
[https://github.com/actions/cache/pull/1404](https://redirect.github.com/actions/cache/pull/1404)
- [@&#8203;x612skm](https://redirect.github.com/x612skm) made their
first contribution in
[https://github.com/actions/cache/pull/1434](https://redirect.github.com/actions/cache/pull/1434)
- [@&#8203;todgru](https://redirect.github.com/todgru) made their first
contribution in
[https://github.com/actions/cache/pull/1311](https://redirect.github.com/actions/cache/pull/1311)
- [@&#8203;Jcambass](https://redirect.github.com/Jcambass) made their
first contribution in
[https://github.com/actions/cache/pull/1463](https://redirect.github.com/actions/cache/pull/1463)
- [@&#8203;mackey0225](https://redirect.github.com/mackey0225) made
their first contribution in
[https://github.com/actions/cache/pull/1462](https://redirect.github.com/actions/cache/pull/1462)
- [@&#8203;quatquatt](https://redirect.github.com/quatquatt) made their
first contribution in
[https://github.com/actions/cache/pull/1445](https://redirect.github.com/actions/cache/pull/1445)

**Full Changelog**:
https://github.com/actions/cache/compare/v4.0.2...v4.1.0

###
[`v4.0.2`](https://redirect.github.com/actions/cache/releases/tag/v4.0.2)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.0.1...v4.0.2)

#### What's Changed

- Fix `fail-on-cache-miss` not working by
[@&#8203;cdce8p](https://redirect.github.com/cdce8p) in
[https://github.com/actions/cache/pull/1327](https://redirect.github.com/actions/cache/pull/1327)

**Full Changelog**:
https://github.com/actions/cache/compare/v4.0.1...v4.0.2

###
[`v4.0.1`](https://redirect.github.com/actions/cache/releases/tag/v4.0.1)

[Compare
Source](https://redirect.github.com/actions/cache/compare/v4.0.0...v4.0.1)

#### What's Changed

- Update README.md by
[@&#8203;yacaovsnc](https://redirect.github.com/yacaovsnc) in
[https://github.com/actions/cache/pull/1304](https://redirect.github.com/actions/cache/pull/1304)
- Update examples by
[@&#8203;yacaovsnc](https://redirect.github.com/yacaovsnc) in
[https://github.com/actions/cache/pull/1305](https://redirect.github.com/actions/cache/pull/1305)
- Update actions/cache publish flow by
[@&#8203;bethanyj28](https://redirect.github.com/bethanyj28) in
[https://github.com/actions/cache/pull/1340](https://redirect.github.com/actions/cache/pull/1340)
- Update
[@&#8203;actions/cache](https://redirect.github.com/actions/cache) by
[@&#8203;bethanyj28](https://redirect.github.com/bethanyj28) in
[https://github.com/actions/cache/pull/1341](https://redirect.github.com/actions/cache/pull/1341)

#### New Contributors

- [@&#8203;yacaovsnc](https://redirect.github.com/yacaovsnc) made their
first contribution in
[https://github.com/actions/cache/pull/1304](https://redirect.github.com/actions/cache/pull/1304)

**Full Changelog**: https://github.com/actions/cache/compare/v4...v4.0.1

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 08:47:35 +02:00
renovate[bot]
1120def16a Update Swatinem/rust-cache action to v2.7.8 (#17255)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [Swatinem/rust-cache](https://redirect.github.com/Swatinem/rust-cache)
| action | minor | `v2` -> `v2.7.8` |

---

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

---

### Release Notes

<details>
<summary>Swatinem/rust-cache (Swatinem/rust-cache)</summary>

###
[`v2.7.8`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.7.8)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.7.7...v2.7.8)

##### What's Changed

- Include CPU arch in the cache key for arm64 Linux runners by
[@&#8203;rhysd](https://redirect.github.com/rhysd) in
[https://github.com/Swatinem/rust-cache/pull/228](https://redirect.github.com/Swatinem/rust-cache/pull/228)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.7.7...v2.7.8

###
[`v2.7.7`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.7.7)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.7.6...v2.7.7)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.7.6...v2.7.7

###
[`v2.7.6`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.7.6)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.7.5...v2.7.6)

##### What's Changed

- Updated artifact upload action to v4 by
[@&#8203;guylamar2006](https://redirect.github.com/guylamar2006) in
[https://github.com/Swatinem/rust-cache/pull/212](https://redirect.github.com/Swatinem/rust-cache/pull/212)
- Adds an option to do lookup-only of the cache by
[@&#8203;danlec](https://redirect.github.com/danlec) in
[https://github.com/Swatinem/rust-cache/pull/217](https://redirect.github.com/Swatinem/rust-cache/pull/217)
- add runner OS in cache key by
[@&#8203;rnbguy](https://redirect.github.com/rnbguy) in
[https://github.com/Swatinem/rust-cache/pull/220](https://redirect.github.com/Swatinem/rust-cache/pull/220)
- Allow opting out of caching $CARGO_HOME/bin. by
[@&#8203;benjyw](https://redirect.github.com/benjyw) in
[https://github.com/Swatinem/rust-cache/pull/216](https://redirect.github.com/Swatinem/rust-cache/pull/216)

##### New Contributors

- [@&#8203;guylamar2006](https://redirect.github.com/guylamar2006) made
their first contribution in
[https://github.com/Swatinem/rust-cache/pull/212](https://redirect.github.com/Swatinem/rust-cache/pull/212)
- [@&#8203;danlec](https://redirect.github.com/danlec) made their first
contribution in
[https://github.com/Swatinem/rust-cache/pull/217](https://redirect.github.com/Swatinem/rust-cache/pull/217)
- [@&#8203;rnbguy](https://redirect.github.com/rnbguy) made their first
contribution in
[https://github.com/Swatinem/rust-cache/pull/220](https://redirect.github.com/Swatinem/rust-cache/pull/220)
- [@&#8203;benjyw](https://redirect.github.com/benjyw) made their first
contribution in
[https://github.com/Swatinem/rust-cache/pull/216](https://redirect.github.com/Swatinem/rust-cache/pull/216)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.7.5...v2.7.6

###
[`v2.7.5`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.7.5)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.7.3...v2.7.5)

##### What's Changed

- Upgrade checkout action from version 3 to 4 by
[@&#8203;carsten-wenderdel](https://redirect.github.com/carsten-wenderdel)
in
[https://github.com/Swatinem/rust-cache/pull/190](https://redirect.github.com/Swatinem/rust-cache/pull/190)
- fix: usage of `deprecated` version of `node` by
[@&#8203;hamirmahal](https://redirect.github.com/hamirmahal) in
[https://github.com/Swatinem/rust-cache/pull/197](https://redirect.github.com/Swatinem/rust-cache/pull/197)
- Only run macOsWorkaround() on macOS by
[@&#8203;heksesang](https://redirect.github.com/heksesang) in
[https://github.com/Swatinem/rust-cache/pull/206](https://redirect.github.com/Swatinem/rust-cache/pull/206)
- Support Cargo.lock format cargo-lock v4 by
[@&#8203;NobodyXu](https://redirect.github.com/NobodyXu) in
[https://github.com/Swatinem/rust-cache/pull/211](https://redirect.github.com/Swatinem/rust-cache/pull/211)

##### New Contributors

-
[@&#8203;carsten-wenderdel](https://redirect.github.com/carsten-wenderdel)
made their first contribution in
[https://github.com/Swatinem/rust-cache/pull/190](https://redirect.github.com/Swatinem/rust-cache/pull/190)
- [@&#8203;hamirmahal](https://redirect.github.com/hamirmahal) made
their first contribution in
[https://github.com/Swatinem/rust-cache/pull/197](https://redirect.github.com/Swatinem/rust-cache/pull/197)
- [@&#8203;heksesang](https://redirect.github.com/heksesang) made their
first contribution in
[https://github.com/Swatinem/rust-cache/pull/206](https://redirect.github.com/Swatinem/rust-cache/pull/206)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.7.3...v2.7.5

###
[`v2.7.3`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.7.3)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.7.2...v2.7.3)

- Work around upstream problem that causes cache saving to hang for
minutes.

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.7.2...v2.7.3

###
[`v2.7.2`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.7.2)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.7.1...v2.7.2)

##### What's Changed

- Update action runtime to `node20` by
[@&#8203;rhysd](https://redirect.github.com/rhysd) in
[https://github.com/Swatinem/rust-cache/pull/175](https://redirect.github.com/Swatinem/rust-cache/pull/175)
- Only key by `Cargo.toml` and `Cargo.lock` files of workspace members
by [@&#8203;max-heller](https://redirect.github.com/max-heller) in
[https://github.com/Swatinem/rust-cache/pull/180](https://redirect.github.com/Swatinem/rust-cache/pull/180)

##### New Contributors

- [@&#8203;rhysd](https://redirect.github.com/rhysd) made their first
contribution in
[https://github.com/Swatinem/rust-cache/pull/175](https://redirect.github.com/Swatinem/rust-cache/pull/175)
- [@&#8203;max-heller](https://redirect.github.com/max-heller) made
their first contribution in
[https://github.com/Swatinem/rust-cache/pull/180](https://redirect.github.com/Swatinem/rust-cache/pull/180)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.7.1...v2.7.2

###
[`v2.7.1`](https://redirect.github.com/Swatinem/rust-cache/compare/v2.7.0...v2.7.1)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.7.0...v2.7.1)

###
[`v2.7.0`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.7.0)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.6.2...v2.7.0)

##### What's Changed

- Fix save-if documentation in readme by
[@&#8203;rukai](https://redirect.github.com/rukai) in
[https://github.com/Swatinem/rust-cache/pull/166](https://redirect.github.com/Swatinem/rust-cache/pull/166)
- Support for `trybuild` and similar macro testing tools by
[@&#8203;neysofu](https://redirect.github.com/neysofu) in
[https://github.com/Swatinem/rust-cache/pull/168](https://redirect.github.com/Swatinem/rust-cache/pull/168)

##### New Contributors

- [@&#8203;rukai](https://redirect.github.com/rukai) made their first
contribution in
[https://github.com/Swatinem/rust-cache/pull/166](https://redirect.github.com/Swatinem/rust-cache/pull/166)
- [@&#8203;neysofu](https://redirect.github.com/neysofu) made their
first contribution in
[https://github.com/Swatinem/rust-cache/pull/168](https://redirect.github.com/Swatinem/rust-cache/pull/168)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.6.2...v2.7.0

###
[`v2.6.2`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.6.2)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.6.1...v2.6.2)

##### What's Changed

- dep: Use `smol-toml` instead of `toml` by
[@&#8203;NobodyXu](https://redirect.github.com/NobodyXu) in
[https://github.com/Swatinem/rust-cache/pull/164](https://redirect.github.com/Swatinem/rust-cache/pull/164)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2...v2.6.2

###
[`v2.6.1`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.6.1)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.6.0...v2.6.1)

-   Fix hash contributions of `Cargo.lock`/`Cargo.toml` files.

###
[`v2.6.0`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.6.0)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.5.1...v2.6.0)

##### What's Changed

- Add "buildjet" as a second `cache-provider` backend
[@&#8203;joroshiba](https://redirect.github.com/joroshiba) in
[https://github.com/Swatinem/rust-cache/pull/154](https://redirect.github.com/Swatinem/rust-cache/pull/154)
-   Clean up sparse registry index.
-   Do not clean up src of `-sys` crates.
-   Remove `.cargo/credentials.toml` before saving.

##### New Contributors

- [@&#8203;joroshiba](https://redirect.github.com/joroshiba) made their
first contribution in
[https://github.com/Swatinem/rust-cache/pull/154](https://redirect.github.com/Swatinem/rust-cache/pull/154)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.5.1...v2.6.0

###
[`v2.5.1`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.5.1)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.5.0...v2.5.1)

-   Fix hash contribution of `Cargo.lock`.

###
[`v2.5.0`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.5.0)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.4.0...v2.5.0)

##### What's Changed

- feat: Rm workspace crates version before caching by
[@&#8203;NobodyXu](https://redirect.github.com/NobodyXu) in
[https://github.com/Swatinem/rust-cache/pull/147](https://redirect.github.com/Swatinem/rust-cache/pull/147)
- feat: Add hash of `.cargo/config.toml` to key by
[@&#8203;NobodyXu](https://redirect.github.com/NobodyXu) in
[https://github.com/Swatinem/rust-cache/pull/149](https://redirect.github.com/Swatinem/rust-cache/pull/149)

##### New Contributors

- [@&#8203;NobodyXu](https://redirect.github.com/NobodyXu) made their
first contribution in
[https://github.com/Swatinem/rust-cache/pull/147](https://redirect.github.com/Swatinem/rust-cache/pull/147)

**Full Changelog**:
https://github.com/Swatinem/rust-cache/compare/v2.4.0...v2.5.0

###
[`v2.4.0`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.4.0)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.3.0...v2.4.0)

-   Fix cache key stability.
- Use 8 character hash components to reduce the key length, making it
more readable.

###
[`v2.3.0`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.3.0)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.2.1...v2.3.0)

- Add `cache-all-crates` option, which enables caching of crates
installed by workflows.
- Add installed packages to cache key, so changes to workflows that
install rust tools are detected and cached properly.
-   Fix cache restore failures due to upstream bug.
-   Fix `EISDIR` error due to globed directories.
- Update runtime `@actions/cache`, `@actions/io` and dev `typescript`
dependencies.
- Update `npm run prepare` so it creates distribution files with the
right line endings.

###
[`v2.2.1`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.2.1)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.2.0...v2.2.1)

- Update `@actions/cache` dependency to fix usage of `zstd` compression.

###
[`v2.2.0`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.2.0)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.1.0...v2.2.0)

- Add new `save-if` option to always restore, but only conditionally
save the cache.

###
[`v2.1.0`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.1.0)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.0.2...v2.1.0)

- Only hash `Cargo.{lock,toml}` files in the configured workspace
directories.

###
[`v2.0.2`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.0.2)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2.0.1...v2.0.2)

-   Avoid calling cargo metadata on pre-cleanup.
-   Added `prefix-key`, `cache-directories` and `cache-targets` options.

###
[`v2.0.1`](https://redirect.github.com/Swatinem/rust-cache/releases/tag/v2.0.1)

[Compare
Source](https://redirect.github.com/Swatinem/rust-cache/compare/v2...v2.0.1)

- Primarily just updating dependencies to fix GitHub deprecation
notices.

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 08:46:35 +02:00
renovate[bot]
796e7510c4 Update actions/checkout action to v4.2.2 (#17257)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | minor | `v4` -> `v4.2.2` |

---

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

---

### Release Notes

<details>
<summary>actions/checkout (actions/checkout)</summary>

###
[`v4.2.2`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v422)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.2.1...v4.2.2)

- `url-helper.ts` now leverages well-known environment variables by
[@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/checkout/pull/1941](https://redirect.github.com/actions/checkout/pull/1941)
- Expand unit test coverage for `isGhes` by
[@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/checkout/pull/1946](https://redirect.github.com/actions/checkout/pull/1946)

###
[`v4.2.1`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v421)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.2.0...v4.2.1)

- Check out other refs/\* by commit if provided, fall back to ref by
[@&#8203;orhantoy](https://redirect.github.com/orhantoy) in
[https://github.com/actions/checkout/pull/1924](https://redirect.github.com/actions/checkout/pull/1924)

###
[`v4.2.0`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v420)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.1.7...v4.2.0)

- Add Ref and Commit outputs by
[@&#8203;lucacome](https://redirect.github.com/lucacome) in
[https://github.com/actions/checkout/pull/1180](https://redirect.github.com/actions/checkout/pull/1180)
- Dependency updates by
[@&#8203;dependabot-](https://redirect.github.com/dependabot-)
[https://github.com/actions/checkout/pull/1777](https://redirect.github.com/actions/checkout/pull/1777),
[https://github.com/actions/checkout/pull/1872](https://redirect.github.com/actions/checkout/pull/1872)

###
[`v4.1.7`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v417)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.1.6...v4.1.7)

- Bump the minor-npm-dependencies group across 1 directory with 4
updates by [@&#8203;dependabot](https://redirect.github.com/dependabot)
in
[https://github.com/actions/checkout/pull/1739](https://redirect.github.com/actions/checkout/pull/1739)
- Bump actions/checkout from 3 to 4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/checkout/pull/1697](https://redirect.github.com/actions/checkout/pull/1697)
- Check out other refs/\* by commit by
[@&#8203;orhantoy](https://redirect.github.com/orhantoy) in
[https://github.com/actions/checkout/pull/1774](https://redirect.github.com/actions/checkout/pull/1774)
- Pin actions/checkout's own workflows to a known, good, stable version.
by [@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/checkout/pull/1776](https://redirect.github.com/actions/checkout/pull/1776)

###
[`v4.1.6`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v416)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.1.5...v4.1.6)

- Check platform to set archive extension appropriately by
[@&#8203;cory-miller](https://redirect.github.com/cory-miller) in
[https://github.com/actions/checkout/pull/1732](https://redirect.github.com/actions/checkout/pull/1732)

###
[`v4.1.5`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v415)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.1.4...v4.1.5)

- Update NPM dependencies by
[@&#8203;cory-miller](https://redirect.github.com/cory-miller) in
[https://github.com/actions/checkout/pull/1703](https://redirect.github.com/actions/checkout/pull/1703)
- Bump github/codeql-action from 2 to 3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/checkout/pull/1694](https://redirect.github.com/actions/checkout/pull/1694)
- Bump actions/setup-node from 1 to 4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/checkout/pull/1696](https://redirect.github.com/actions/checkout/pull/1696)
- Bump actions/upload-artifact from 2 to 4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/checkout/pull/1695](https://redirect.github.com/actions/checkout/pull/1695)
- README: Suggest `user.email` to be
`41898282+github-actions[bot]@&#8203;users.noreply.github.com` by
[@&#8203;cory-miller](https://redirect.github.com/cory-miller) in
[https://github.com/actions/checkout/pull/1707](https://redirect.github.com/actions/checkout/pull/1707)

###
[`v4.1.4`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v414)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.1.3...v4.1.4)

- Disable `extensions.worktreeConfig` when disabling `sparse-checkout`
by [@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/checkout/pull/1692](https://redirect.github.com/actions/checkout/pull/1692)
- Add dependabot config by
[@&#8203;cory-miller](https://redirect.github.com/cory-miller) in
[https://github.com/actions/checkout/pull/1688](https://redirect.github.com/actions/checkout/pull/1688)
- Bump the minor-actions-dependencies group with 2 updates by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/checkout/pull/1693](https://redirect.github.com/actions/checkout/pull/1693)
- Bump word-wrap from 1.2.3 to 1.2.5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/actions/checkout/pull/1643](https://redirect.github.com/actions/checkout/pull/1643)

###
[`v4.1.3`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v413)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.1.2...v4.1.3)

- Check git version before attempting to disable `sparse-checkout` by
[@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/checkout/pull/1656](https://redirect.github.com/actions/checkout/pull/1656)
- Add SSH user parameter by
[@&#8203;cory-miller](https://redirect.github.com/cory-miller) in
[https://github.com/actions/checkout/pull/1685](https://redirect.github.com/actions/checkout/pull/1685)
- Update `actions/checkout` version in `update-main-version.yml` by
[@&#8203;jww3](https://redirect.github.com/jww3) in
[https://github.com/actions/checkout/pull/1650](https://redirect.github.com/actions/checkout/pull/1650)

###
[`v4.1.2`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v412)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.1.1...v4.1.2)

- Fix: Disable sparse checkout whenever `sparse-checkout` option is not
present [@&#8203;dscho](https://redirect.github.com/dscho) in
[https://github.com/actions/checkout/pull/1598](https://redirect.github.com/actions/checkout/pull/1598)

###
[`v4.1.1`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v411)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.1.0...v4.1.1)

- Correct link to GitHub Docs by
[@&#8203;peterbe](https://redirect.github.com/peterbe) in
[https://github.com/actions/checkout/pull/1511](https://redirect.github.com/actions/checkout/pull/1511)
- Link to release page from what's new section by
[@&#8203;cory-miller](https://redirect.github.com/cory-miller) in
[https://github.com/actions/checkout/pull/1514](https://redirect.github.com/actions/checkout/pull/1514)

###
[`v4.1.0`](https://redirect.github.com/actions/checkout/blob/HEAD/CHANGELOG.md#v410)

[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4.0.0...v4.1.0)

- [Add support for partial checkout
filters](https://redirect.github.com/actions/checkout/pull/1396)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 08:45:47 +02:00
renovate[bot]
1f254ab17e Update astral-sh/setup-uv action to v5.4.1 (#17262)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [astral-sh/setup-uv](https://redirect.github.com/astral-sh/setup-uv) |
action | minor | `v5` -> `v5.4.1` |

---

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

---

### Release Notes

<details>
<summary>astral-sh/setup-uv (astral-sh/setup-uv)</summary>

###
[`v5.4.1`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.4.1):
🌈 Add support for pep440 version specifiers

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.4.0...v5.4.1)

##### Changes

With this release you can also use [pep440 version
specifiers](https://peps.python.org/pep-0440/#version-specifiers) as
`required-version` in files`uv.toml`, `pyroject.toml` and in the
`version` input:

```yaml
- name: Install a pep440-specifier-satisfying version of uv
  uses: astral-sh/setup-uv@v5
  with:
    version: ">=0.4.25,<0.5"
```

##### 🐛 Bug fixes

- Add support for pep440 version identifiers
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;353](https://redirect.github.com/astral-sh/setup-uv/issues/353))

##### 🧰 Maintenance

- chore: update known checksums for 0.6.10
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;345](https://redirect.github.com/astral-sh/setup-uv/issues/345))

##### 📚 Documentation

- Add pep440 to docs header
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;355](https://redirect.github.com/astral-sh/setup-uv/issues/355))
- Fix glob syntax link
[@&#8203;flying-sheep](https://redirect.github.com/flying-sheep)
([#&#8203;349](https://redirect.github.com/astral-sh/setup-uv/issues/349))
- Add link to supported glob patterns
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;348](https://redirect.github.com/astral-sh/setup-uv/issues/348))

###
[`v5.4.0`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.4.0):
🌈 uv and uvx path as outputs

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.3.1...v5.4.0)

#### Changes

The absolute paths to the uv and uvx binaries can now be accessed via
the outputs `uv-path` and `uvx-path`.

`setup-uv` now also issues a warning if the working directory is empty.
This makes users aware of the common mistake to run `setup-uv` before
`actions/checkout`. You can remove the warning by setting
`ignore-empty-workdir: true`

#### 🚀 Enhancements

- Add uv-path and uvx-path output
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;341](https://redirect.github.com/astral-sh/setup-uv/issues/341))
- Warn when the workdir is empty
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;322](https://redirect.github.com/astral-sh/setup-uv/issues/322))

#### 🧰 Maintenance

- chore: update known checksums for 0.6.9
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;339](https://redirect.github.com/astral-sh/setup-uv/issues/339))
- Merge workflows and add all-tests-passed
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;331](https://redirect.github.com/astral-sh/setup-uv/issues/331))
- chore: update known checksums for 0.6.8
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;332](https://redirect.github.com/astral-sh/setup-uv/issues/332))
- chore: update known checksums for 0.6.7
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;330](https://redirect.github.com/astral-sh/setup-uv/issues/330))
- Set required workflow permissions
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;329](https://redirect.github.com/astral-sh/setup-uv/issues/329))
- Add workflow_dispatch triggers to every workflow
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;326](https://redirect.github.com/astral-sh/setup-uv/issues/326))
- Bump dependencies
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;324](https://redirect.github.com/astral-sh/setup-uv/issues/324))
- Inline action-update-semver
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;323](https://redirect.github.com/astral-sh/setup-uv/issues/323))
- chore: update known checksums for 0.6.6
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;318](https://redirect.github.com/astral-sh/setup-uv/issues/318))
- chore: update known checksums for 0.6.5
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;313](https://redirect.github.com/astral-sh/setup-uv/issues/313))

#### 📚 Documentation

- Fix wrong warning message in FAQ
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;337](https://redirect.github.com/astral-sh/setup-uv/issues/337))
- Warn when the workdir is empty
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;322](https://redirect.github.com/astral-sh/setup-uv/issues/322))
- Remove apk add python3 for musl test
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;319](https://redirect.github.com/astral-sh/setup-uv/issues/319))

#### ⬆️ Dependency updates

- Bump
[@&#8203;actions/cache](https://redirect.github.com/actions/cache) from
4.0.2 to 4.0.3
@&#8203;[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
([#&#8203;334](https://redirect.github.com/astral-sh/setup-uv/issues/334))

###
[`v5.3.1`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.3.1):
🌈 - Fix issues with GHES and HTTP proxies

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.3.0...v5.3.1)

##### Changes

This release fixes some issues when this action was used behind a HTTP
proxy or with GHES.
If you have been seeing `ENOTFOUND` or timeout errors, this release
should fix that.

A huge thank you to everyone who helped investigating this and testing
the fixes:

-   [@&#8203;siryessuhr](https://redirect.github.com/siryessuhr)
-   [@&#8203;my1e5](https://redirect.github.com/my1e5)
-   [@&#8203;dennis-m-e](https://redirect.github.com/dennis-m-e)
-   [@&#8203;PaarthShah](https://redirect.github.com/PaarthShah)

##### 🐛 Bug fixes

- Always fall back to anonymous download
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;304](https://redirect.github.com/astral-sh/setup-uv/issues/304))

##### 🧰 Maintenance

- chore: update known checksums for 0.6.3
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;300](https://redirect.github.com/astral-sh/setup-uv/issues/300))

##### 📚 Documentation

- 📚 Document automatically enabled cache on GitHub-hosted runners
[@&#8203;jerr0328](https://redirect.github.com/jerr0328)
([#&#8203;302](https://redirect.github.com/astral-sh/setup-uv/issues/302))

##### ⬆️ Dependency updates

- bump dependencies
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;308](https://redirect.github.com/astral-sh/setup-uv/issues/308))
- Bump peter-evans/create-pull-request from 7.0.6 to 7.0.7
@&#8203;[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
([#&#8203;299](https://redirect.github.com/astral-sh/setup-uv/issues/299))

###
[`v5.3.0`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.3.0):
🌈 Support MUSL, s390x and powerpc

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.2.2...v5.3.0)

In this release we add support for MUSL based systems.
This is helpful if you are running your workflow inside a docker image
based on [alpine](https://hub.docker.com/\_/alpine).

> \[!TIP]
> Please be aware that you have to make sure a python interpreter is
already present (`apk add python3`), see also
https://docs.astral.sh/uv/concepts/python-versions/#cpython-distributions
and
[https://github.com/astral-sh/uv/issues/6890](https://redirect.github.com/astral-sh/uv/issues/6890)

[@&#8203;Zxilly](https://redirect.github.com/Zxilly) also added support
for running this action on self-hosted runners using s390x and powerpc
architectures. Thank you!

This release also includes more debug logs which makes tracking down
issues easier in the future.

##### 🐛 Bug fixes

- Add more debug logs
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;297](https://redirect.github.com/astral-sh/setup-uv/issues/297))

##### 🚀 Enhancements

- Support OS using musl
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;284](https://redirect.github.com/astral-sh/setup-uv/issues/284))
- feat: support s390x and powerpc
[@&#8203;Zxilly](https://redirect.github.com/Zxilly)
([#&#8203;289](https://redirect.github.com/astral-sh/setup-uv/issues/289))

##### 🧰 Maintenance

- chore: update known checksums for 0.6.2
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;295](https://redirect.github.com/astral-sh/setup-uv/issues/295))
- chore: update known checksums for 0.6.1
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;293](https://redirect.github.com/astral-sh/setup-uv/issues/293))
- chore: update known checksums for 0.6.0
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;288](https://redirect.github.com/astral-sh/setup-uv/issues/288))
- chore: update known checksums for 0.5.31
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;277](https://redirect.github.com/astral-sh/setup-uv/issues/277))
- Run update-known-checksums every night
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;273](https://redirect.github.com/astral-sh/setup-uv/issues/273))
- chore: update known checksums for 0.5.29
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;272](https://redirect.github.com/astral-sh/setup-uv/issues/272))
- chore: update known checksums for 0.5.28
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;270](https://redirect.github.com/astral-sh/setup-uv/issues/270))
- chore: update known checksums for 0.5.27
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;267](https://redirect.github.com/astral-sh/setup-uv/issues/267))
- chore: update known checksums for 0.5.26
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;263](https://redirect.github.com/astral-sh/setup-uv/issues/263))

##### 📚 Documentation

- Add FAQ on resolution strategy and cache not found warnings
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;296](https://redirect.github.com/astral-sh/setup-uv/issues/296))

###
[`v5.2.2`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.2.2):
🌈 Full support for GHES

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.2.1...v5.2.2)

##### Changes

This release fixes some issues that prevented use with GitHub Enterprise
Server instances.

##### 🐛 Bug fixes

- Do not expect GITHUB_TOKEN to be set or valid
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;262](https://redirect.github.com/astral-sh/setup-uv/issues/262))
- Fallback if toml file parsing failed
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;246](https://redirect.github.com/astral-sh/setup-uv/issues/246))

##### 🧰 Maintenance

- chore: update known checksums for 0.5.25
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;259](https://redirect.github.com/astral-sh/setup-uv/issues/259))
- chore: update known checksums for 0.5.24
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;256](https://redirect.github.com/astral-sh/setup-uv/issues/256))
- chore: update known checksums for 0.5.23
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;252](https://redirect.github.com/astral-sh/setup-uv/issues/252))
- chore: update known checksums for 0.5.22
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;250](https://redirect.github.com/astral-sh/setup-uv/issues/250))
- chore: update known checksums for 0.5.21
@&#8203;[github-actions\[bot\]](https://redirect.github.com/apps/github-actions)
([#&#8203;247](https://redirect.github.com/astral-sh/setup-uv/issues/247))

##### 📚 Documentation

- Fix TOC [@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;257](https://redirect.github.com/astral-sh/setup-uv/issues/257))

##### ⬆️ Dependency updates

- Bump [@&#8203;types/node](https://redirect.github.com/types/node) from
22.10.10 to 22.12.0
@&#8203;[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
([#&#8203;258](https://redirect.github.com/astral-sh/setup-uv/issues/258))
- Bump release-drafter/release-drafter from 6.0.0 to 6.1.0
@&#8203;[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
([#&#8203;249](https://redirect.github.com/astral-sh/setup-uv/issues/249))
- Bump [@&#8203;types/node](https://redirect.github.com/types/node) from
22.10.9 to 22.10.10
@&#8203;[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
([#&#8203;254](https://redirect.github.com/astral-sh/setup-uv/issues/254))
- Bump [@&#8203;types/node](https://redirect.github.com/types/node) from
22.10.7 to 22.10.9
@&#8203;[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
([#&#8203;253](https://redirect.github.com/astral-sh/setup-uv/issues/253))
- Bump
[@&#8203;actions/tool-cache](https://redirect.github.com/actions/tool-cache)
from 2.0.1 to 2.0.2
@&#8203;[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
([#&#8203;244](https://redirect.github.com/astral-sh/setup-uv/issues/244))
- Bump [@&#8203;types/node](https://redirect.github.com/types/node) from
22.10.6 to 22.10.7
@&#8203;[dependabot\[bot\]](https://redirect.github.com/apps/dependabot)
([#&#8203;243](https://redirect.github.com/astral-sh/setup-uv/issues/243))

###
[`v5.2.1`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.2.1):
🌈 Support toml spec 1.0.0

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.2.0...v5.2.1)

v5.2.0 introduced TOML parsing using
[@&#8203;iarna/toml](https://www.npmjs.com/package/@&#8203;iarna/toml)
because we already found out in `astral-sh/ruff-action` that
[toml](https://www.npmjs.com/package/toml) has missing features.

As it turns out
[@&#8203;iarna/toml](https://www.npmjs.com/package/@&#8203;iarna/toml)
also is not fully TOML spec (1.0.0) compliant.

We now use [smol-toml](https://www.npmjs.com/package/smol-toml)

##### 🐛 Bug fixes

- Support toml spec 1.0.0
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;245](https://redirect.github.com/astral-sh/setup-uv/issues/245))

###
[`v5.2.0`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.2.0):
🌈 Detect required-version from config file

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.1.0...v5.2.0)

This release adds support to derive the version of uv to be installed
from `pyproject.toml` and `uv.toml` files.
If no `version` input is defined the default is now to look for a
[required-version](https://docs.astral.sh/uv/reference/settings/#required-version)
in `uv.toml` and then `pyproject.toml` in the repository root. If it
cannot find any it falls back to `latest`.

If your files are at a different place you can use the new inputs
`uv-file` or `pyproject-file`.

##### 🐛 Bug fixes

- Add venv/bin as absolute path to PATH
[@&#8203;op](https://redirect.github.com/op)
([#&#8203;241](https://redirect.github.com/astral-sh/setup-uv/issues/241))
- fix: make sure VIRTUAL_ENV is an absolute path
[@&#8203;samypr100](https://redirect.github.com/samypr100)
([#&#8203;224](https://redirect.github.com/astral-sh/setup-uv/issues/224))

##### 🚀 Enhancements

- Detect required-version from config file
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;233](https://redirect.github.com/astral-sh/setup-uv/issues/233))

##### 🧰 Maintenance

- chore: update known checksums for 0.5.20
[@&#8203;github-actions](https://redirect.github.com/github-actions)
([#&#8203;238](https://redirect.github.com/astral-sh/setup-uv/issues/238))
- chore: update known checksums for 0.5.19
[@&#8203;github-actions](https://redirect.github.com/github-actions)
([#&#8203;237](https://redirect.github.com/astral-sh/setup-uv/issues/237))
- chore: update known checksums for 0.5.18
[@&#8203;github-actions](https://redirect.github.com/github-actions)
([#&#8203;232](https://redirect.github.com/astral-sh/setup-uv/issues/232))
- chore: update known checksums for 0.5.17
[@&#8203;github-actions](https://redirect.github.com/github-actions)
([#&#8203;231](https://redirect.github.com/astral-sh/setup-uv/issues/231))
- chore: update known checksums for 0.5.16
[@&#8203;github-actions](https://redirect.github.com/github-actions)
([#&#8203;228](https://redirect.github.com/astral-sh/setup-uv/issues/228))
- chore: update known checksums for 0.5.15
[@&#8203;github-actions](https://redirect.github.com/github-actions)
([#&#8203;225](https://redirect.github.com/astral-sh/setup-uv/issues/225))
- chore: update known checksums for 0.5.14
[@&#8203;github-actions](https://redirect.github.com/github-actions)
([#&#8203;222](https://redirect.github.com/astral-sh/setup-uv/issues/222))
- chore: update known checksums for 0.5.12
[@&#8203;github-actions](https://redirect.github.com/github-actions)
([#&#8203;214](https://redirect.github.com/astral-sh/setup-uv/issues/214))

##### 📚 Documentation

- docs: bump `astral-sh/setup-uv` to `v5`
[@&#8203;njzjz](https://redirect.github.com/njzjz)
([#&#8203;205](https://redirect.github.com/astral-sh/setup-uv/issues/205))

##### ⬆️ Dependency updates

- Bump [@&#8203;octokit/rest](https://redirect.github.com/octokit/rest)
from 21.0.2 to 21.1.0
[@&#8203;dependabot](https://redirect.github.com/dependabot)
([#&#8203;229](https://redirect.github.com/astral-sh/setup-uv/issues/229))
- Bump typescript from 5.7.2 to 5.7.3
[@&#8203;dependabot](https://redirect.github.com/dependabot)
([#&#8203;230](https://redirect.github.com/astral-sh/setup-uv/issues/230))
- Bump [@&#8203;types/node](https://redirect.github.com/types/node) from
22.10.5 to 22.10.6
[@&#8203;dependabot](https://redirect.github.com/dependabot)
([#&#8203;236](https://redirect.github.com/astral-sh/setup-uv/issues/236))
- Bump [@&#8203;types/node](https://redirect.github.com/types/node) from
22.10.3 to 22.10.5
[@&#8203;dependabot](https://redirect.github.com/dependabot)
([#&#8203;223](https://redirect.github.com/astral-sh/setup-uv/issues/223))
- Bump [@&#8203;types/node](https://redirect.github.com/types/node) from
22.10.2 to 22.10.3
[@&#8203;dependabot](https://redirect.github.com/dependabot)
([#&#8203;220](https://redirect.github.com/astral-sh/setup-uv/issues/220))
- Bump peter-evans/create-pull-request from 7.0.5 to 7.0.6
[@&#8203;dependabot](https://redirect.github.com/dependabot)
([#&#8203;218](https://redirect.github.com/astral-sh/setup-uv/issues/218))

###
[`v5.1.0`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.1.0):
🌈 Fewer cache invalidations

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5.0.1...v5.1.0)

##### Changes

This release includes less frequently invalidated caches and a fix for
setting the correct `VIRTUAL_ENV`

##### 🐛 Bug fixes

- Set VIRTUAL_ENV to .venv instead of .venv/bin
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;210](https://redirect.github.com/astral-sh/setup-uv/issues/210))

##### 🚀 Enhancements

- Remove uv version from cache key
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;206](https://redirect.github.com/astral-sh/setup-uv/issues/206))

##### 📚 Documentation

- Align use of `actions/setup-python` with uv docu
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;207](https://redirect.github.com/astral-sh/setup-uv/issues/207))

###
[`v5.0.1`](https://redirect.github.com/astral-sh/setup-uv/releases/tag/v5.0.1):
🌈 The christmas elves overlooked something

[Compare
Source](https://redirect.github.com/astral-sh/setup-uv/compare/v5...v5.0.1)

##### Changes

With so many breaking changes so close to the end of the year we missed
something.

Thank you [@&#8203;ryanhiebert](https://redirect.github.com/ryanhiebert)
for quickly reporting that our new defaults fail the workflow if neither
a `uv.lock` nor a `requirements*.txt` can be found. This is now a
warning instead.

##### 🐛 Bug fixes

- Fix wrong cacheDependencyPathHash
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;201](https://redirect.github.com/astral-sh/setup-uv/issues/201))
- Warn instead of fail for no-dependency-glob
[@&#8203;eifinger](https://redirect.github.com/eifinger)
([#&#8203;200](https://redirect.github.com/astral-sh/setup-uv/issues/200))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 08:44:19 +02:00
Micha Reiser
10003bd4e5 Revert "Update Rust crate clap to v4.5.35" (#17265)
Reverts astral-sh/ruff#17245

This broke main. Let's revert and then land this upgrade properly
2025-04-07 08:33:44 +02:00
renovate[bot]
85f8116b2f Update Rust crate smallvec to v1.15.0 (#17254) 2025-04-07 02:06:59 +00:00
renovate[bot]
bc8c6a4810 Update taiki-e/install-action digest to d4635f2 (#17244) 2025-04-06 22:02:47 -04:00
renovate[bot]
22f9f1dd29 Update PyO3/maturin-action action to v1.48.1 (#17252) 2025-04-06 22:02:27 -04:00
renovate[bot]
6f11470298 Update pre-commit dependencies (#17251) 2025-04-06 22:02:07 -04:00
renovate[bot]
a038c2e662 Update dependency pyodide to v0.27.5 (#17250) 2025-04-06 22:01:57 -04:00
renovate[bot]
7dc6583f9f Update Rust crate ordermap to v0.5.7 (#17249) 2025-04-06 22:01:49 -04:00
renovate[bot]
8c51fdfeff Update Rust crate mimalloc to v0.1.45 (#17248) 2025-04-06 22:01:40 -04:00
renovate[bot]
861a9c5d6c Update Rust crate env_logger to v0.11.8 (#17247) 2025-04-06 22:01:32 -04:00
renovate[bot]
396a7162d6 Update Rust crate ctrlc to v3.4.6 (#17246) 2025-04-06 22:01:24 -04:00
renovate[bot]
040f80ab68 Update Rust crate clap to v4.5.35 (#17245) 2025-04-06 22:01:18 -04:00
Micha Reiser
67f8c30b53 [red-knot] Remove global dead_code from red-knot-server (#17229)
## Summary

Use more local `expect(dead_code)` suppressions instead of a global
`allow(dead_code)` in `lib.rs`.

Remove some methods that are either easy to add later, are less likely
to be needed for red knot, or it's unclear if we'd add it the same way
as in ruff.
2025-04-06 22:09:24 +01:00
Micha Reiser
e01d228a71 [playground] Provide fallback monospace-font (#17242)
<img width="1679" alt="Screenshot 2025-04-06 at 22 51 43"
src="https://github.com/user-attachments/assets/ccd9dd1a-67cd-4bc3-a22a-f3c530b8670d"
/>
2025-04-06 21:57:20 +01:00
Micha Reiser
51bdb87fd8 [red-knot] Fix loading color in dark mode (#17237)
## Summary

The loading indicator on dark mode isn't "visible" because it's black on
black. Use white as text color instead.
2025-04-06 18:30:21 +01:00
Alex Waygood
ac5d220d75 [red-knot] Fix python setting in mdtests, and rewrite a site-packages test as an mdtest (#17222)
## Summary

This PR does the following things:
- Fixes the `python` configuration setting for mdtest (added in
https://github.com/astral-sh/ruff/pull/17221) so that it expects a path
pointing to a venv's `sys.prefix` variable rather than the a path
pointing to the venv's `site-packages` subdirectory. This brings the
`python` setting in mdtest in sync with our CLI `--python` flag.
- Tweaks mdtest so that it automatically creates a valid `pyvenv.cfg`
file for you if you don't specify one. This makes it much more ergonomic
to write an mdtest with a custom `python` setting: red-knot will reject
a `python` setting that points to a directory that doesn't have a
`pyvenv.cfg` file in it
- Tweaks mdtest so that it doesn't check a custom `pyvenv.cfg` as Python
source code if you _do_ add a custom `pyvenv.cfg` file for your mock
virtual environment in an mdtest. (You get a lot of diagnostics about
Python syntax errors in the `pyvenv.cfg` file, otherwise!)
- Rewrites the test added in
https://github.com/astral-sh/ruff/pull/17178 as an mdtest, and deletes
the original test that was added in that PR

## Test Plan

I verified that the new mdtest fails if I revert the changes to
`resolver.rs` that were added in
https://github.com/astral-sh/ruff/pull/17178
2025-04-06 18:24:32 +01:00
Matthew Mckee
73a9974d8a Fix CallableTypeOf display signature (#17235) 2025-04-06 18:12:52 +01:00
Micha Reiser
3dd6d0a422 [playground] Add Reset button (#17236)
## Summary

Add a *Reset* button to both Ruff's and Red Knot's playground that
resets the playground to its initial state.

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

## Test Plan



https://github.com/user-attachments/assets/753cca19-155a-44b1-89ba-76744487a55d


https://github.com/user-attachments/assets/7d19f04c-70f4-4d9e-b745-0486cb1d4993
2025-04-06 17:09:56 +00:00
Micha Reiser
4571c5f56f [red-knot] Simplify playground editor state (#17223)
## Summary
Reduce the number of `useRef`s in `Editor`
2025-04-05 19:49:08 +02:00
Micha Reiser
1c652e6b98 [red-knot] Allow setting python in mdtests (#17221)
## Summary

This PR extends the mdtest options to allow setting the
`environment.python` option.

## Test Plan

I let @AlexWaygood write a test and he'll tell me if it works 😆
2025-04-05 16:43:31 +02:00
renovate[bot]
172af7b4b0 Update dependency vite to v6.2.5 (#17211)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [vite](https://vite.dev)
([source](https://redirect.github.com/vitejs/vite/tree/HEAD/packages/vite))
| [`6.2.4` ->
`6.2.5`](https://renovatebot.com/diffs/npm/vite/6.2.4/6.2.5) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vite/6.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite/6.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite/6.2.4/6.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/6.2.4/6.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

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

### GitHub Vulnerability Alerts

####
[CVE-2025-31486](https://redirect.github.com/vitejs/vite/security/advisories/GHSA-xcj6-pq6g-qj4x)

### Summary

The contents of arbitrary files can be returned to the browser.

### Impact

Only apps explicitly exposing the Vite dev server to the network (using
--host or [server.host config
option](https://vitejs.dev/config/server-options.html#server-host)) are
affected..

### Details

#### `.svg`

Requests ending with `.svg` are loaded at this line.

037f801075/packages/vite/src/node/plugins/asset.ts (L285-L290)
By adding `?.svg` with `?.wasm?init` or with `sec-fetch-dest: script`
header, the restriction was able to bypass.

This bypass is only possible if the file is smaller than
[`build.assetsInlineLimit`](https://vite.dev/config/build-options.html#build-assetsinlinelimit)
(default: 4kB) and when using Vite 6.0+.

#### relative paths

The check was applied before the id normalization. This allowed requests
to bypass with relative paths (e.g. `../../`).

### PoC

```bash
npm create vite@latest
cd vite-project/
npm install
npm run dev
```

send request to read `etc/passwd`

```bash
curl 'http://127.0.0.1:5173/etc/passwd?.svg?.wasm?init'
```

```bash
curl 'http://127.0.0.1:5173/@&#8203;fs/x/x/x/vite-project/?/../../../../../etc/passwd?import&?raw'
```

---

### Release Notes

<details>
<summary>vitejs/vite (vite)</summary>

###
[`v6.2.5`](https://redirect.github.com/vitejs/vite/releases/tag/v6.2.5)

[Compare
Source](https://redirect.github.com/vitejs/vite/compare/v6.2.4...v6.2.5)

Please refer to
[CHANGELOG.md](https://redirect.github.com/vitejs/vite/blob/v6.2.5/packages/vite/CHANGELOG.md)
for details.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMjcuMyIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCIsInNlY3VyaXR5Il19-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-05 08:28:01 +01:00
cake-monotone
7e6d3838bd [red-knot] Add cycle handling to narrow constraints queries (#17209)
## Summary

This PR fixes the cycle issue that was causing problems in the `support
super` PR.

### Affected queries
- `all_narrowing_constraints_for_expression`
- `all_negative_narrowing_constraints_for_expression`


--

Additionally, `bidict` and `werkzeug` have been added to the
project-selection list in `mypy_primer`.
This PR also addresses the panics that occurred while analyzing those
packages:

- `bidict`: panic triggered by
`all_narrowing_constraints_for_expression`
- `werkzeug`: panic triggered by
`all_negative_narrowing_constraints_for_expression`

I think the mypy-primer results for this PR can serve as sufficient test
:)
2025-04-04 22:26:20 -07:00
David Peter
1a6a10b30f [red-knot] Empty tuple is always-falsy (#17213)
## Summary

Fix assignability of `tuple[()]` to `AlwaysFalsy`.

closes #17202 

## Test Plan

Ran the property tests for a while
2025-04-04 22:00:28 +02:00
Brent Westbrook
b3243b5e2a Run fuzzer with --preview (#17210)
Summary
--

Updates `fuzz.py` to run with `--preview`, which should allow it to
catch semantic syntax errors.

Test Plan
--

@AlexWaygood and I temporarily made any named expression a semantic
syntax error and checked that this led to fuzzing errors. We also tested
that reverting the `--preview` addition did not show any errors.

We also ran the fuzzer on 500 seeds on `main` but didn't find any
issues, (un)fortunately.
2025-04-04 15:13:59 -04:00
Brent Westbrook
95d6ed40cc Bump 0.11.4 (#17212) 2025-04-04 14:09:10 -04:00
Brent Westbrook
acc5662e8b [syntax-errors] Allow yield in base classes and annotations (#17206)
Summary
--

This PR fixes the issue pointed out by @JelleZijlstra in
https://github.com/astral-sh/ruff/pull/17101#issuecomment-2777480204.
Namely, I conflated two very different errors from CPython:

```pycon
>>> def m[T](x: (yield from 1)): ...
  File "<python-input-310>", line 1
    def m[T](x: (yield from 1)): ...
                 ^^^^^^^^^^^^
SyntaxError: yield expression cannot be used within the definition of a generic
>>> def m(x: (yield from 1)): ...
  File "<python-input-311>", line 1
    def m(x: (yield from 1)): ...
              ^^^^^^^^^^^^
SyntaxError: 'yield from' outside function
>>> def outer():
...     def m(x: (yield from 1)): ...
...
>>>
```

I thought the second error was the same as the first, but `yield` (and
`yield from`) is actually valid in this position when inside a function
scope. The same is true for base classes, as pointed out in the original
comment.

We don't currently raise an error for `yield` outside of a function, but
that should be handled separately.

On the upside, this had the benefit of removing the
`InvalidExpressionPosition::BaseClass` variant and the
`allow_named_expr` field from the visitor because they were both no
longer used.

Test Plan
--

Updated inline tests.
2025-04-04 13:48:28 -04:00
David Salvisberg
33a56f198b Don't skip visiting non-tuple slice in typing.Annotated subscripts (#17201)
Fixes: #17196

## Summary

Skipping these nodes for malformed type expressions would lead to
incorrect semantic state, which can in turn mean we emit false positives
for rules like `unused-variable`(`F841`)

## Test Plan

`cargo nextest run`
2025-04-04 18:47:40 +05:30
David Peter
5cee346744 [red-knot] mypy_primer: do not specify Python version (#17200)
## Summary

* Pull in latest changes from upstream (which includes an update to a
`pyproject.toml` layout and a `uv.lock` file, which should make CI more
deterministic)
* Do not specify `--python-version 3.13` in Red Knot runs


https://github.com/astral-sh/mypy_primer/compare/add-red-knot-support-v2...astral-sh:mypy_primer:add-red-knot-support-v3

## Test Plan

Tested locally
2025-04-04 13:55:40 +02:00
Micha Reiser
ffa824e037 [red-knot] Add Type.definition method (#17153)
## Summary

This is a follow up to the goto type definition PR. Specifically, that
we want to avoid exposing too many semantic model internals publicly.

I want to get some feedback on the approach taken. I think it goes into
the right direction but I'm not super happy with it.
The basic idea is that we add a `Type::definition` method which does the
"goto type definition". The parts that I think make it awkward:

* We can't directly return `Definition` because we don't create a
`Definition` for modules (but we could?). Although I think it makes
sense to possibly have a more public wrapper type anyway?
* It doesn't handle unions and intersections. Mainly because not all
elements in an intersection may have a definition and we only want to
show a navigation target for intersections if there's only a single
positive element (besides maybe `Unknown`).


An alternative design or an addition to this design is to introduce a
`SemanticAnalysis(Db)` struct that has methods like
`type_definition(&self, type)` which explicitly exposes the methods we
want. I don't feel comfortable design this API yet because it's unclear
how fine granular it has to be (and if it is very fine granular,
directly using `Type` might be better after all)


## Test Plan

`cargo test`
2025-04-04 10:56:20 +02:00
Max Mynter
98b95c9c38 Implement Invalid rule provided as rule RUF102 with --fix (#17138)
<!--
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?
-->

Closes #17084

## Summary
This PR adds a new rule (RUF102) to detect and fix invalid rule codes in
`noqa` comments.
Invalid rule codes in `noqa` directives serve no purpose and may
indicate outdated code suppressions.

This extends the previous behaviour originating from
`crates/ruff_linter/src/noqa.rs` which would only emit a warnigs.
With this rule a `--fix` is available.

The rule:
1. Analyzes all `noqa` directives to identify invalid rule codes
2. Provides autofix functionality to:
   - Remove the entire comment if all codes are invalid
   - Remove only the invalid codes when mixed with valid codes
3. Preserves original comment formatting and whitespace where possible

Example cases:
- `# noqa: XYZ111` → Remove entire comment (keep empty line)
- `# noqa: XYZ222, XYZ333` → Remove entire comment (keep empty line)
-  `# noqa: F401, INVALID123` → Keep only valid codes (`# noqa: F401`)

## Test Plan
- Added tests in
`crates/ruff_linter/resources/test/fixtures/ruff/RUF102.py` covering
different example cases.

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

## Notes 
- This does not handle cases where parsing fails. E.g. `# noqa:
NON_EXISTENT, ANOTHER_INVALID` causes a `LexicalError` and the
diagnostic is not propagated and we cannot handle the diagnostic. I am
also unsure what proper `fix` handling would be and making the user
aware we don't understand the codes is probably the best bet.
- The rule is added to the Preview rule group as it's a new addition

## Questions
- Should we remove the warnings, now that we have a rule?
- Is the current fix behavior appropriate for all cases, particularly
the handling of whitespace and line deletions?
- I'm new to the codebase; let me know if there are rule utilities which
could have used but didn't.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-04 08:05:59 +00:00
Micha Reiser
a4ba10ff0a [red-knot] Add basic on-hover to playground and LSP (#17057)
## Summary

Implement a very basic hover in the playground and LSP.

It's basic, because it only shows the type on-hover. Most other LSPs
also show:

* The signature of the symbol beneath the cursor. E.g. `class
Test(a:int, b:int)` (we want something like
54f7da25f9/packages/pyright-internal/src/analyzer/typeEvaluator.ts (L21929-L22129))
* The symbols' documentation
* Do more fancy markdown rendering

I decided to defer these features for now because it requires new
semantic APIs (similar to *goto definition*), and investing in fancy
rendering only makes sense once we have the relevant data.

Closes [#16826](https://github.com/astral-sh/ruff/issues/16826)

## Test Plan



https://github.com/user-attachments/assets/044aeee4-58ad-4d4e-9e26-ac2a712026be


https://github.com/user-attachments/assets/4a1f4004-2982-4cf2-9dfd-cb8b84ff2ecb
2025-04-04 08:13:43 +02:00
Carl Meyer
bf0306887a [red-knot] don't remove negations when simplifying constrained typevars (#17189)
For two non-disjoint types `P` and `Q`, the simplification of `(P | Q) &
~Q` is not `P`, but `P & ~Q`. In other words, the non-empty set `P & Q`
is also excluded from the type.

The same applies for a constrained typevar `[T: (P, Q)]`: `T & ~Q`
should simplify to `P & ~Q`, not just `P`.

Implementing this is actually purely a matter of removing code from the
constrained typevar simplification logic; we just need to not bother
removing the negations. If the negations are actually redundant (because
the constraint types are disjoint), normal intersection simplification
will already eliminate them (as shown in the added test.)
2025-04-03 16:30:57 -07:00
Brent Westbrook
4f924bb975 [minor] Fix extra semicolon for clippy (#17188) 2025-04-03 18:17:00 -04:00
Brent Westbrook
c2b2e42ad3 [syntax-errors] Invalid syntax in annotations (#17101)
Summary
--

This PR detects the use of invalid syntax in annotation scopes,
including
`yield` and `yield from` expressions and named expressions. I combined a
few
different types of CPython errors here, but I think the resulting error
messages
still make sense and are even preferable to what CPython gives. For
example, we
report `yield expression cannot be used in a type annotation` for both
of these:

```pycon
>>> def f[T](x: (yield 1)): ...
  File "<python-input-26>", line 1
    def f[T](x: (yield 1)): ...
                 ^^^^^^^
SyntaxError: yield expression cannot be used within the definition of a generic
>>> def foo() -> (yield x): ...
  File "<python-input-28>", line 1
    def foo() -> (yield x): ...
                  ^^^^^^^
SyntaxError: 'yield' outside function
```

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

Test Plan
--

New inline tests, along with some updates to existing tests.
2025-04-03 17:56:55 -04:00
Brent Westbrook
24b1b1d52c [syntax-errors] Duplicate attributes in match class pattern (#17186)
Summary
--

Detects duplicate attributes in a `match` class pattern:

```python
match x:
    case Class(x=1, x=2): ...
```

which are more analogous to the similar check for mapping patterns than
to the
multiple assignments rule.

I also realized that both this and the mapping check would only work on
top-level patterns, despite the possibility that they can be nested
inside other
patterns:

```python
match x:
    case [{"x": 1, "x": 2}]: ...  # false negative in the old version
```

and moved these checks into the recursive pattern visitor instead.

I also tidied up some of the names like the `multiple_case_assignment`
function
and the `MultipleCaseAssignmentVisitor`, which are now doing more than
checking
for multiple assignments.

Test Plan
--

New inline tests for both classes and mappings.
2025-04-03 17:55:37 -04:00
Brent Westbrook
6a07dd227d [syntax-errors] Fix multiple assignment for class keyword argument (#17184)
Summary
--

Fixes #17181. The cases being tested with multiple *keys* being equal
are actually a slightly different error, more like the error for
`MatchMapping` than like the other multiple assignment errors:

```pycon
>>> match x:
...     case Class(x=x, x=x): ...
...
  File "<python-input-249>", line 2
    case Class(x=x, x=x): ...
                      ^
SyntaxError: attribute name repeated in class pattern: x
>>> match x:
...     case {"x": 1, "x": 2}: ...
...
  File "<python-input-251>", line 2
    case {"x": 1, "x": 2}: ...
         ^^^^^^^^^^^^^^^^
SyntaxError: mapping pattern checks duplicate key ('x')
>>> match x:
...     case [x, x]: ...
...
  File "<python-input-252>", line 2
    case [x, x]: ...
             ^
SyntaxError: multiple assignments to name 'x' in pattern
```

This PR just stops the false positive reported in the issue, but I will
quickly follow it up with a new rule (or possibly combined with the
mapping rule) catching the repeated attributes separately.

Test Plan
--

New inline `test_ok` and updating the `test_err` cases to have duplicate
values instead of keys.
2025-04-03 17:32:39 -04:00
Aria Desires
8aa5686e63 use astral-sh/cargo-dist instead (#17187) 2025-04-03 17:25:12 -04:00
Micha Reiser
e7684d3493 Enable overindented docs lint (#17182)
## Summary

It turns out that `a.` isn't a list format supported by rustdoc. I
changed the documentation to use `1.`, `2.` instead.

## Test Plan

`cargo clippy`
2025-04-03 20:27:11 +01:00
Douglas Creager
64e7e1aa64 [red-knot] Add Type::TypeVar variant (#17102)
This adds a new `Type` variant for holding an instance of a typevar
inside of a generic function or class. We don't handle specializing the
typevars yet, but this should implement most of the typing rules for
inside the generic function/class, where we don't know yet which
specific type the typevar will be specialized to.

This PR does _not_ yet handle the constraint that multiple occurrences
of the typevar must be specialized to the _same_ time. (There is an
existing test case for this in `generics/functions.md` which is still
marked as TODO.)

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-03 14:36:29 -04:00
Carl Meyer
45c43735e0 [red-knot] update to latest Salsa with fixpoint caching fix (#17179)
With this PR, we no longer "hang" (not actually a hang, just an
explosion in execution time) when checking pylint.
2025-04-03 09:05:09 -07:00
Micha Reiser
8a4158c5f8 Upgrade to Rust 1.86 and bump MSRV to 1.84 (#17171)
<!--
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

I decided to disable the new
[`needless_continue`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_continue)
rule because I often found the explicit `continue` more readable over an
empty block or having to invert the condition of an other branch.


## Test Plan

`cargo test`

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-03 15:59:44 +00:00
David Peter
fedd982fd5 [red-knot] Avoid unresolved-reference in unreachable code (#17169)
## Summary

This PR changes the inferred type for symbols in unreachable sections of
code to `Never` (instead of reporting them as unbound), in order to
silence false positive diagnostics. See the lengthy comment in the code
for further details.

## Test Plan

- Updated Markdown tests.
- Manually verified a couple of ecosystem diagnostic changes.
2025-04-03 16:52:11 +02:00
Alex Waygood
a1eb834a5f Fix relative import resolution in site-packages packages when the site-packages search path is a subdirectory of the first-party search path (#17178)
## Summary

If a package in `site-packages` had this directory structure:

```py
# bar/__init__.py
from .a import A

# bar/a.py
class A: ...
```

then we would fail to resolve the `from .a import A` import _if_ (as is
usually the case!) the `site-packages` search path was located inside a
`.venv` directory that was a subdirectory of the project's first-party
search path. The reason for this is a bug in `file_to_module` in the
module resolver. In this loop, we would identify that
`/project_root/.venv/lib/python3.13/site-packages/foo/__init__.py` can
be turned into a path relative to the first-party search path
(`/project_root`):


6e2b8f9696/crates/red_knot_python_semantic/src/module_resolver/resolver.rs (L101-L110)

but we'd then try to turn the relative path
(.venv/lib/python3.13/site-packages/foo/__init__.py`) into a module
path, realise that it wasn't a valid module path... and therefore
immediately `break` out of the loop before trying any other search paths
(such as the `site-packages` search path).

This bug was originally reported on Discord by @MatthewMckee4.

## Test Plan

I added a unit test for `file_to_module` in `resolver.rs`, and an
integration test that shows we can now resolve the import correctly in
`infer.rs`.
2025-04-03 15:48:05 +01:00
Carl Meyer
c1f93a702c [DO NOT LAND] bump Salsa version (#17176)
Update to latest Salsa main branch, so as to get a baseline for
measuring the perf effect of https://github.com/salsa-rs/salsa/pull/786
on red-knot in isolation from other recent changes in Salsa main branch.
2025-04-03 14:31:41 +00:00
Brent Westbrook
6e2b8f9696 [syntax-errors] Detect duplicate keys in match mapping patterns (#17129)
Summary
--

Detects duplicate literals in `match` mapping keys.

This PR also adds a `source` method to `SemanticSyntaxContext` to
display the duplicated key in the error message by slicing out its
range.

Test Plan
--

New inline tests.
2025-04-03 10:22:37 -04:00
Alex Waygood
ca0cce3f9c [red-knot] Fix more [redundant-cast] false positives (#17170)
Fixes #17164. Simply checking whether one type is gradually equivalent
to another is too simplistic here: `Any` is gradually equivalent to
`Todo`, but we should permit users to cast from `Todo` or `Unknown` to
`Any` without complaining about it. This changes our logic so that we
only complain about redundant casts if:
- the two types are exactly equal (when normalized) OR they are
equivalent (we'll still complain about `Any -> Any` casts, and about
`Any | str | int` -> `str | int | Any` casts, since their normalized
forms are exactly equal, even though the type is not fully static -- and
therefore does not participate in equivalence relations)
- AND the casted type does not contain `Todo`
2025-04-03 15:00:00 +01:00
David Peter
3f00010a7a [red-knot] Three-argument type-calls take 'str' as the first argument (#17168)
## Summary

Similar to #17163, a minor fix in the signature of `type(…)`.

## Test Plan

New MD tests
2025-04-03 15:45:08 +02:00
Dylan
d401a5440e Control flow: return and raise (#17121)
We add support for `return` and `raise` statements in the control flow
graph: we simply add an edge to the terminal block, push the statements
to the current block, and proceed.

This implementation will have to be modified somewhat once we add
support for `try` statements - then we will need to check whether to
_defer_ the jump. But for now this will do!

Also in this PR: We fix the `unreachable` diagnostic range so that it
lumps together consecutive unreachable blocks.
2025-04-03 08:30:29 -05:00
Brent Westbrook
755ece0c36 Bump 0.11.3 (#17173) 2025-04-03 09:05:40 -04:00
Alex Waygood
62f8d855d2 [red-knot] Improve Debug implementation for semantic_index::SymbolTable (#17172)
## Summary

`dbg!`ing a `SymbolTable` is currently very noisy due to the
`symbols_by_name` field, which doesn't tell you very much at all. The
noisiness makes debugging difficult. This PR removes the
`symbols_by_name` field from the `Debug` implementation.

## Test Plan

`dbg!` output before of the `builtins.pyi` global-scope symbol table:

<details>

```
[crates/red_knot_python_semantic/src/symbol.rs:633:5] symbol_table(db, scope) = SymbolTable {
    symbols: [
        Symbol {
            name: Name("_ast"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_sitebuiltins"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_typeshed"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("sys"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("types"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dict_items"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dict_keys"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dict_values"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("AnyStr_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConvertibleToFloat"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConvertibleToInt"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FileDescriptorOrPath"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenBinaryMode"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenBinaryModeReading"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenBinaryModeUpdating"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenBinaryModeWriting"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OpenTextMode"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ReadableBuffer"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsAdd"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsAiter"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsAnext"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsDivMod"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsFlush"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsIter"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsKeysAndGetItem"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsLenAndGetItem"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsNext"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsRAdd"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsRDivMod"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsRichComparison"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsRichComparisonT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsWrite"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Awaitable"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Callable"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Iterable"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Iterator"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("MutableSet"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Reversible"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("AbstractSet"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Sized"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BufferedRandom"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BufferedReader"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BufferedWriter"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FileIO"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TextIOWrapper"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("CellType"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("CodeType"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TracebackType"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("IO"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Any"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BinaryIO"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ClassVar"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Generic"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Mapping"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("MutableMapping"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("MutableSequence"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Protocol"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Sequence"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsAbs"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsBytes"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsComplex"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsFloat"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SupportsIndex"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeVar"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("final"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("overload"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("type_check_only"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Concatenate"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Literal"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("LiteralString"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ParamSpec"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Self"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeAlias"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeGuard"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeIs"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeVarTuple"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("deprecated"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("GenericAlias"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_T"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("int"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_I"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T_contra"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_R_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_KT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_VT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_S"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T1"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T2"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T3"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T4"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_T5"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_SupportsNextT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_SupportsAnextT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_AwaitableT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_AwaitableT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_P"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_StartT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_StopT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_StepT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("object"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("staticmethod"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("classmethod"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("type"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("super"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_PositiveInteger"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_NegativeInteger"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_LiteralInteger"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("float"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("complex"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_FormatMapMapping"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_TranslateTable"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("str"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("bytes"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("bytearray"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_IntegerFormats"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("memoryview"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("bool"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("slice"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("tuple"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("function"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("list"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dict"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("set"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("frozenset"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("enumerate"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("range"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("property"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_NotImplementedType"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("NotImplemented"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("abs"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("all"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("any"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ascii"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("bin"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("breakpoint"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("callable"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("chr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_PathLike"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("aiter"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsSynchronousAnext"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("anext"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("compile"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("copyright"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("credits"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("delattr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("dir"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("divmod"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("eval"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("exec"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("exit"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("filter"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("format"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("getattr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("globals"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("hasattr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("hash"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("help"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("hex"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("id"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("input"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_GetItemIterable"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("iter"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_ClassInfo"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("isinstance"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("issubclass"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("len"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("license"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("locals"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("map"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("max"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("min"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("next"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("oct"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_Opener"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("open"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ord"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsWriteAndFlush"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("print"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_E_contra"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_M_contra"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_SupportsPow2"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsPow3NoneOnly"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsPow3"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsSomeKindOfPow"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("pow"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("quit"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("reversed"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("repr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsRound1"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsRound2"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("round"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("setattr"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("sorted"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_AddableT1"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_AddableT2"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_SupportsSumWithNoDefaultGiven"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_SupportsSumNoDefaultT"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("sum"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("vars"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("zip"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("__import__"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("__build_class__"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("EllipsisType"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ellipsis"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Ellipsis"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BaseException"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("GeneratorExit"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("KeyboardInterrupt"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SystemExit"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Exception"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("StopIteration"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OSError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("EnvironmentError"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("IOError"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("WindowsError"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("ArithmeticError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("AssertionError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("AttributeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BufferError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("EOFError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ImportError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("LookupError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("MemoryError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("NameError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ReferenceError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("RuntimeError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("StopAsyncIteration"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SyntaxError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SystemError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TypeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ValueError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FloatingPointError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("OverflowError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ZeroDivisionError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ModuleNotFoundError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("IndexError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("KeyError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnboundLocalError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BlockingIOError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ChildProcessError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConnectionError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BrokenPipeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConnectionAbortedError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConnectionRefusedError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ConnectionResetError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FileExistsError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FileNotFoundError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("InterruptedError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("IsADirectoryError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("NotADirectoryError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("PermissionError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ProcessLookupError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TimeoutError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("NotImplementedError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("RecursionError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("IndentationError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("TabError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeError"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeDecodeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeEncodeError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeTranslateError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("Warning"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UserWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("DeprecationWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("SyntaxWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("RuntimeWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("FutureWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("PendingDeprecationWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ImportWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("UnicodeWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("BytesWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ResourceWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("EncodingWarning"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("_BaseExceptionT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_BaseExceptionT"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_ExceptionT_co"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND,
            ),
        },
        Symbol {
            name: Name("_ExceptionT"),
            flags: SymbolFlags(
                IS_BOUND,
            ),
        },
        Symbol {
            name: Name("BaseExceptionGroup"),
            flags: SymbolFlags(
                IS_USED | IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("ExceptionGroup"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
        Symbol {
            name: Name("PythonFinalizationError"),
            flags: SymbolFlags(
                IS_BOUND | IS_DECLARED,
            ),
        },
    ],
    symbols_by_name: {
        ScopedSymbolId(
            235,
        ): (),
        ScopedSymbolId(
            267,
        ): (),
        ScopedSymbolId(
            86,
        ): (),
        ScopedSymbolId(
            22,
        ): (),
        ScopedSymbolId(
            182,
        ): (),
        ScopedSymbolId(
            213,
        ): (),
        ScopedSymbolId(
            252,
        ): (),
        ScopedSymbolId(
            177,
        ): (),
        ScopedSymbolId(
            173,
        ): (),
        ScopedSymbolId(
            108,
        ): (),
        ScopedSymbolId(
            122,
        ): (),
        ScopedSymbolId(
            118,
        ): (),
        ScopedSymbolId(
            197,
        ): (),
        ScopedSymbolId(
            69,
        ): (),
        ScopedSymbolId(
            134,
        ): (),
        ScopedSymbolId(
            52,
        ): (),
        ScopedSymbolId(
            248,
        ): (),
        ScopedSymbolId(
            168,
        ): (),
        ScopedSymbolId(
            2,
        ): (),
        ScopedSymbolId(
            129,
        ): (),
        ScopedSymbolId(
            5,
        ): (),
        ScopedSymbolId(
            18,
        ): (),
        ScopedSymbolId(
            150,
        ): (),
        ScopedSymbolId(
            9,
        ): (),
        ScopedSymbolId(
            16,
        ): (),
        ScopedSymbolId(
            205,
        ): (),
        ScopedSymbolId(
            246,
        ): (),
        ScopedSymbolId(
            68,
        ): (),
        ScopedSymbolId(
            93,
        ): (),
        ScopedSymbolId(
            189,
        ): (),
        ScopedSymbolId(
            161,
        ): (),
        ScopedSymbolId(
            64,
        ): (),
        ScopedSymbolId(
            124,
        ): (),
        ScopedSymbolId(
            229,
        ): (),
        ScopedSymbolId(
            94,
        ): (),
        ScopedSymbolId(
            202,
        ): (),
        ScopedSymbolId(
            67,
        ): (),
        ScopedSymbolId(
            120,
        ): (),
        ScopedSymbolId(
            219,
        ): (),
        ScopedSymbolId(
            12,
        ): (),
        ScopedSymbolId(
            20,
        ): (),
        ScopedSymbolId(
            79,
        ): (),
        ScopedSymbolId(
            11,
        ): (),
        ScopedSymbolId(
            157,
        ): (),
        ScopedSymbolId(
            216,
        ): (),
        ScopedSymbolId(
            231,
        ): (),
        ScopedSymbolId(
            239,
        ): (),
        ScopedSymbolId(
            140,
        ): (),
        ScopedSymbolId(
            36,
        ): (),
        ScopedSymbolId(
            13,
        ): (),
        ScopedSymbolId(
            184,
        ): (),
        ScopedSymbolId(
            204,
        ): (),
        ScopedSymbolId(
            70,
        ): (),
        ScopedSymbolId(
            259,
        ): (),
        ScopedSymbolId(
            96,
        ): (),
        ScopedSymbolId(
            111,
        ): (),
        ScopedSymbolId(
            72,
        ): (),
        ScopedSymbolId(
            247,
        ): (),
        ScopedSymbolId(
            101,
        ): (),
        ScopedSymbolId(
            242,
        ): (),
        ScopedSymbolId(
            261,
        ): (),
        ScopedSymbolId(
            263,
        ): (),
        ScopedSymbolId(
            214,
        ): (),
        ScopedSymbolId(
            62,
        ): (),
        ScopedSymbolId(
            166,
        ): (),
        ScopedSymbolId(
            244,
        ): (),
        ScopedSymbolId(
            257,
        ): (),
        ScopedSymbolId(
            133,
        ): (),
        ScopedSymbolId(
            112,
        ): (),
        ScopedSymbolId(
            87,
        ): (),
        ScopedSymbolId(
            90,
        ): (),
        ScopedSymbolId(
            117,
        ): (),
        ScopedSymbolId(
            158,
        ): (),
        ScopedSymbolId(
            162,
        ): (),
        ScopedSymbolId(
            230,
        ): (),
        ScopedSymbolId(
            154,
        ): (),
        ScopedSymbolId(
            255,
        ): (),
        ScopedSymbolId(
            35,
        ): (),
        ScopedSymbolId(
            39,
        ): (),
        ScopedSymbolId(
            138,
        ): (),
        ScopedSymbolId(
            190,
        ): (),
        ScopedSymbolId(
            21,
        ): (),
        ScopedSymbolId(
            66,
        ): (),
        ScopedSymbolId(
            181,
        ): (),
        ScopedSymbolId(
            7,
        ): (),
        ScopedSymbolId(
            236,
        ): (),
        ScopedSymbolId(
            251,
        ): (),
        ScopedSymbolId(
            152,
        ): (),
        ScopedSymbolId(
            227,
        ): (),
        ScopedSymbolId(
            78,
        ): (),
        ScopedSymbolId(
            55,
        ): (),
        ScopedSymbolId(
            61,
        ): (),
        ScopedSymbolId(
            253,
        ): (),
        ScopedSymbolId(
            47,
        ): (),
        ScopedSymbolId(
            65,
        ): (),
        ScopedSymbolId(
            153,
        ): (),
        ScopedSymbolId(
            104,
        ): (),
        ScopedSymbolId(
            74,
        ): (),
        ScopedSymbolId(
            107,
        ): (),
        ScopedSymbolId(
            149,
        ): (),
        ScopedSymbolId(
            98,
        ): (),
        ScopedSymbolId(
            155,
        ): (),
        ScopedSymbolId(
            169,
        ): (),
        ScopedSymbolId(
            180,
        ): (),
        ScopedSymbolId(
            237,
        ): (),
        ScopedSymbolId(
            146,
        ): (),
        ScopedSymbolId(
            15,
        ): (),
        ScopedSymbolId(
            243,
        ): (),
        ScopedSymbolId(
            17,
        ): (),
        ScopedSymbolId(
            136,
        ): (),
        ScopedSymbolId(
            80,
        ): (),
        ScopedSymbolId(
            44,
        ): (),
        ScopedSymbolId(
            228,
        ): (),
        ScopedSymbolId(
            60,
        ): (),
        ScopedSymbolId(
            245,
        ): (),
        ScopedSymbolId(
            193,
        ): (),
        ScopedSymbolId(
            264,
        ): (),
        ScopedSymbolId(
            268,
        ): (),
        ScopedSymbolId(
            58,
        ): (),
        ScopedSymbolId(
            258,
        ): (),
        ScopedSymbolId(
            279,
        ): (),
        ScopedSymbolId(
            113,
        ): (),
        ScopedSymbolId(
            135,
        ): (),
        ScopedSymbolId(
            240,
        ): (),
        ScopedSymbolId(
            85,
        ): (),
        ScopedSymbolId(
            186,
        ): (),
        ScopedSymbolId(
            100,
        ): (),
        ScopedSymbolId(
            187,
        ): (),
        ScopedSymbolId(
            106,
        ): (),
        ScopedSymbolId(
            73,
        ): (),
        ScopedSymbolId(
            223,
        ): (),
        ScopedSymbolId(
            49,
        ): (),
        ScopedSymbolId(
            83,
        ): (),
        ScopedSymbolId(
            77,
        ): (),
        ScopedSymbolId(
            43,
        ): (),
        ScopedSymbolId(
            274,
        ): (),
        ScopedSymbolId(
            46,
        ): (),
        ScopedSymbolId(
            151,
        ): (),
        ScopedSymbolId(
            217,
        ): (),
        ScopedSymbolId(
            178,
        ): (),
        ScopedSymbolId(
            278,
        ): (),
        ScopedSymbolId(
            132,
        ): (),
        ScopedSymbolId(
            6,
        ): (),
        ScopedSymbolId(
            174,
        ): (),
        ScopedSymbolId(
            99,
        ): (),
        ScopedSymbolId(
            196,
        ): (),
        ScopedSymbolId(
            109,
        ): (),
        ScopedSymbolId(
            128,
        ): (),
        ScopedSymbolId(
            123,
        ): (),
        ScopedSymbolId(
            102,
        ): (),
        ScopedSymbolId(
            116,
        ): (),
        ScopedSymbolId(
            172,
        ): (),
        ScopedSymbolId(
            32,
        ): (),
        ScopedSymbolId(
            105,
        ): (),
        ScopedSymbolId(
            241,
        ): (),
        ScopedSymbolId(
            95,
        ): (),
        ScopedSymbolId(
            206,
        ): (),
        ScopedSymbolId(
            209,
        ): (),
        ScopedSymbolId(
            198,
        ): (),
        ScopedSymbolId(
            81,
        ): (),
        ScopedSymbolId(
            170,
        ): (),
        ScopedSymbolId(
            171,
        ): (),
        ScopedSymbolId(
            8,
        ): (),
        ScopedSymbolId(
            276,
        ): (),
        ScopedSymbolId(
            1,
        ): (),
        ScopedSymbolId(
            212,
        ): (),
        ScopedSymbolId(
            222,
        ): (),
        ScopedSymbolId(
            33,
        ): (),
        ScopedSymbolId(
            144,
        ): (),
        ScopedSymbolId(
            194,
        ): (),
        ScopedSymbolId(
            125,
        ): (),
        ScopedSymbolId(
            89,
        ): (),
        ScopedSymbolId(
            38,
        ): (),
        ScopedSymbolId(
            51,
        ): (),
        ScopedSymbolId(
            19,
        ): (),
        ScopedSymbolId(
            163,
        ): (),
        ScopedSymbolId(
            0,
        ): (),
        ScopedSymbolId(
            211,
        ): (),
        ScopedSymbolId(
            3,
        ): (),
        ScopedSymbolId(
            226,
        ): (),
        ScopedSymbolId(
            121,
        ): (),
        ScopedSymbolId(
            148,
        ): (),
        ScopedSymbolId(
            232,
        ): (),
        ScopedSymbolId(
            262,
        ): (),
        ScopedSymbolId(
            260,
        ): (),
        ScopedSymbolId(
            91,
        ): (),
        ScopedSymbolId(
            270,
        ): (),
        ScopedSymbolId(
            269,
        ): (),
        ScopedSymbolId(
            225,
        ): (),
        ScopedSymbolId(
            191,
        ): (),
        ScopedSymbolId(
            115,
        ): (),
        ScopedSymbolId(
            28,
        ): (),
        ScopedSymbolId(
            220,
        ): (),
        ScopedSymbolId(
            164,
        ): (),
        ScopedSymbolId(
            250,
        ): (),
        ScopedSymbolId(
            137,
        ): (),
        ScopedSymbolId(
            141,
        ): (),
        ScopedSymbolId(
            24,
        ): (),
        ScopedSymbolId(
            54,
        ): (),
        ScopedSymbolId(
            45,
        ): (),
        ScopedSymbolId(
            188,
        ): (),
        ScopedSymbolId(
            75,
        ): (),
        ScopedSymbolId(
            40,
        ): (),
        ScopedSymbolId(
            234,
        ): (),
        ScopedSymbolId(
            30,
        ): (),
        ScopedSymbolId(
            41,
        ): (),
        ScopedSymbolId(
            127,
        ): (),
        ScopedSymbolId(
            185,
        ): (),
        ScopedSymbolId(
            145,
        ): (),
        ScopedSymbolId(
            23,
        ): (),
        ScopedSymbolId(
            238,
        ): (),
        ScopedSymbolId(
            143,
        ): (),
        ScopedSymbolId(
            167,
        ): (),
        ScopedSymbolId(
            110,
        ): (),
        ScopedSymbolId(
            25,
        ): (),
        ScopedSymbolId(
            31,
        ): (),
        ScopedSymbolId(
            57,
        ): (),
        ScopedSymbolId(
            195,
        ): (),
        ScopedSymbolId(
            221,
        ): (),
        ScopedSymbolId(
            218,
        ): (),
        ScopedSymbolId(
            37,
        ): (),
        ScopedSymbolId(
            71,
        ): (),
        ScopedSymbolId(
            50,
        ): (),
        ScopedSymbolId(
            176,
        ): (),
        ScopedSymbolId(
            179,
        ): (),
        ScopedSymbolId(
            200,
        ): (),
        ScopedSymbolId(
            266,
        ): (),
        ScopedSymbolId(
            277,
        ): (),
        ScopedSymbolId(
            119,
        ): (),
        ScopedSymbolId(
            84,
        ): (),
        ScopedSymbolId(
            114,
        ): (),
        ScopedSymbolId(
            165,
        ): (),
        ScopedSymbolId(
            271,
        ): (),
        ScopedSymbolId(
            280,
        ): (),
        ScopedSymbolId(
            256,
        ): (),
        ScopedSymbolId(
            249,
        ): (),
        ScopedSymbolId(
            88,
        ): (),
        ScopedSymbolId(
            27,
        ): (),
        ScopedSymbolId(
            139,
        ): (),
        ScopedSymbolId(
            265,
        ): (),
        ScopedSymbolId(
            4,
        ): (),
        ScopedSymbolId(
            53,
        ): (),
        ScopedSymbolId(
            29,
        ): (),
        ScopedSymbolId(
            130,
        ): (),
        ScopedSymbolId(
            42,
        ): (),
        ScopedSymbolId(
            76,
        ): (),
        ScopedSymbolId(
            147,
        ): (),
        ScopedSymbolId(
            156,
        ): (),
        ScopedSymbolId(
            208,
        ): (),
        ScopedSymbolId(
            273,
        ): (),
        ScopedSymbolId(
            183,
        ): (),
        ScopedSymbolId(
            224,
        ): (),
        ScopedSymbolId(
            97,
        ): (),
        ScopedSymbolId(
            233,
        ): (),
        ScopedSymbolId(
            82,
        ): (),
        ScopedSymbolId(
            142,
        ): (),
        ScopedSymbolId(
            254,
        ): (),
        ScopedSymbolId(
            131,
        ): (),
        ScopedSymbolId(
            63,
        ): (),
        ScopedSymbolId(
            48,
        ): (),
        ScopedSymbolId(
            215,
        ): (),
        ScopedSymbolId(
            103,
        ): (),
        ScopedSymbolId(
            14,
        ): (),
        ScopedSymbolId(
            92,
        ): (),
        ScopedSymbolId(
            207,
        ): (),
        ScopedSymbolId(
            275,
        ): (),
        ScopedSymbolId(
            160,
        ): (),
        ScopedSymbolId(
            26,
        ): (),
        ScopedSymbolId(
            56,
        ): (),
        ScopedSymbolId(
            34,
        ): (),
        ScopedSymbolId(
            272,
        ): (),
        ScopedSymbolId(
            59,
        ): (),
        ScopedSymbolId(
            126,
        ): (),
        ScopedSymbolId(
            159,
        ): (),
        ScopedSymbolId(
            199,
        ): (),
        ScopedSymbolId(
            175,
        ): (),
        ScopedSymbolId(
            192,
        ): (),
        ScopedSymbolId(
            201,
        ): (),
        ScopedSymbolId(
            203,
        ): (),
        ScopedSymbolId(
            210,
        ): (),
        ScopedSymbolId(
            10,
        ): (),
    },
}
```

</details>


I checked that with this PR, the second field is gone from the debug
output (I'd paste it in, but it goes over the GitHub comment length
maximum).
2025-04-03 13:37:29 +01:00
David Peter
130339f3d8 [red-knot] Fix str(…) calls (#17163)
## Summary

The existing signature for `str` calls had various problems, one of
which I noticed while looking at some ecosystem projects (`scrapy`,
added as a project to mypy_primer in this PR).

## Test Plan

- New tests for `str(…)` calls.
- Observed reduction of false positives in ecosystem checks
2025-04-03 13:26:32 +02:00
Eric Mark Martin
e50fc049ab [red-knot] visibility_constraint analysis for match cases (#17077)
## Summary

Add visibility constraint analysis for pattern predicate kinds
`Singleton`, `Or`, and `Class`.

## Test Plan

update conditional/match.md
2025-04-03 11:15:33 +00:00
Micha Reiser
66355a6185 [red-knot] Fix playground crashes when diagnostics are stale (#17165)
## Summary

Fixes a crash in the playground where it crashed with an "index out of
bounds" error in the `Diagnostic::to_range` call
after deleting content at the end of the file. 

The root cause was that the playground uses `useDeferred` to avoid too
frequent `checkFile` calls (to get a smoother UX).
However, this has the problem that the rendered `diagnostics` can be
stable (from before the last change).
Rendering the diagnostics can then fail because the `toRange` call
queries the latest content and not the content
from when the diagnostics were created.

The fix is "easy" in the sense that we now eagerly perform the `toRange`
calls. This way, it doesn't matter
when the diagnostics are stale for a few ms. 

This problem can only be observed on examples where Red Knot is "slow"
(takes more than ~16ms to check) because
only then does `useDeferred` "debounce" the `check` calls.
2025-04-03 10:18:36 +02:00
Dhruv Manilawala
177afabe18 [red-knot] Callable types are disjoint from literals (#17160)
## Summary

A callable type is disjoint from other literal types. For example,
`Type::StringLiteral` must be an instance of exactly `str`, not a
subclass of `str`, and `str` is not callable. The same applies to other
literal types.

This should hopefully fix #17144, I couldn't produce any failures after
running property tests multiple times.

## Test Plan

Add test cases for disjointness check between callable and other literal
types.

Run property tests multiple times.
2025-04-03 03:38:13 +05:30
Alex Waygood
28c68934a4 [red-knot] Fix inference for pow between two literal integers (#17161)
## Summary

Python `**` works differently to Rust `**`!

## Test Plan

Added an mdtest for various edge cases, and checked in the Python REPL
that we infer the correct type in all the new cases tested.
2025-04-02 21:25:57 +00:00
Alex Waygood
195bb433db [red-knot] Add GitHub PR annotations when mdtests fail in CI (#17150)
## Summary

This PR adds a CI job that causes GitHub to add annotations to a PR diff
when mdtest assertions fail. For example:

<details>
<summary>Screenshot</summary>


![image](https://github.com/user-attachments/assets/bb2a649b-46ab-429d-a576-b36545940eaf)

</details>

## Motivation

Debugging mdtest failures locally is currently a really nice experience:
- Errors are displayed with pretty colours, which makes them much more
readable
- If you run the test from inside an IDE, you can CTRL-click on a path
and jump directly to the line that had the failing assertion
- If you use
[`mdtest.py`](https://github.com/astral-sh/ruff/blob/main/crates/red_knot_python_semantic/mdtest.py),
you don't even need to recompile anything after changing an assertion in
an mdtest, amd the test results instantly live-update with each change
to the MarkDown file

Debugging mdtest failures in CI is much more unpleasant, however.
Sometimes an error message is just

> [static-assert-error] Argument evaluates to `False`

...which doesn't tell you very much unless you navigate to the line in
question that has the failing mdtest assertion. The line in question
might not even be touched by the PR, and even if it is, it can be hard
to find the line if the PR touches many files. Unlike locally, you can't
click on the error and jump straight to the line that contains the
failing assertion. You also don't get colourised output in CI
(https://github.com/astral-sh/ruff/issues/13939).

GitHub PR annotations should make it really easy to debug why mdtests
are failing on PRs, making PR review much easier.

## Test Plan

I opened a PR to my fork
[here](https://github.com/AlexWaygood/ruff/pull/11/files) with some
bogus changes to an mdtest to show what it looks like when there are
failures in CI and this job has been added. Scroll down to
`crates/red_knot_python_semantic/resources/mdtest/type_properties/is_equivalent_to.md`
on the "files changed" tab for that PR to see the annotations.
2025-04-02 21:51:52 +01:00
Alex Waygood
c2bb5d5250 [red-knot] Fix equivalence of differently ordered unions that contain Callable types (#17145)
## Summary

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

Equivalent callable types were not understood as equivalent when they
appeared nested inside unions and intersections. This PR fixes that by
ensuring that `Callable` elements nested inside unions, intersections
and tuples have their representations normalized before one union type
is compared with another for equivalence, or before one intersection
type is compared with another for equivalence.

The normalizations applied to a `Callable` type are:
- the type of the default value is stripped from all parameters (only
whether the parameter _has_ a default value is relevant to whether one
`Callable` type is equivalent to another)
- The names of the parameters are stripped from positional-only
parameters, variadic parameters and keyword-variadic parameters
- Unions and intersections that are present (top-level or nested) inside
parameter annotations or return annotations are normalized.

Adding a `CallableType::normalized()` method also allows us to simplify
the implementation of `CallableType::is_equivalent_to()`.

### Should these normalizations be done eagerly as part of a
`CallableType` constructor?

I considered this. It's something that we could still consider doing in
the future; this PR doesn't rule it out as a possibility. However, I
didn't pursue it for now, for several reasons:
1. Our current `Display` implementation doesn't handle well the
possibility that a parameter might not have a name or an annotated type.
Callable types with parameters like this would be displayed as follows:
   ```py
   (, ,) -> None: ...
   ```

That's fixable! It could easily become something like `(Unknown,
Unknown) -> None: ...`. But it also illustrates that we probably want to
retain the parameter names when displaying the signature of a `lambda`
function if you're hovering over a reference to the lambda in an IDE.
Currently we don't have a `LambdaType` struct for representing `lambda`
functions; if we wanted to eagerly normalize signatures when creating
`CallableType`s, we'd probably have to add a `LambdaType` struct so that
we would retain the full signature of a `lambda` function, rather than
representing it as an eagerly simplified `CallableType`.
2. In order to ensure that it's impossible to create `CallableType`s
without the parameters being normalized, I'd either have to create an
alternative `SimplifiedSignature` struct (which would duplicate a lot of
code), or move `CallableType` to a new module so that the only way of
constructing a `CallableType` instance would be via a constructor method
that performs the normalizations eagerly on the callable's signature.
Again, this isn't a dealbreaker, and I think it's still an option, but
it would be a lot of churn, and it didn't seem necessary for now. Doing
it this way, at least to start with, felt like it would create a diff
that's easier to review and felt like it would create fewer merge
conflicts for others.

## Test Plan

- Added a regression mdtest for
https://github.com/astral-sh/ruff/issues/17058
- Ran `QUICKCHECK_TESTS=1000000 cargo test --release -p
red_knot_python_semantic -- --ignored types::property_tests::stable`
2025-04-02 17:43:34 +00:00
David Peter
cb7dae1e96 [red-knot] Add initial set of tests for unreachable code (#17159)
## Summary

Add an initial set of tests that will eventually document our behavior
around unreachable code. In the last section of this suite, I argue why
we should never type check unreachable sections and never emit any
diagnostics in these sections.
2025-04-02 19:39:44 +02:00
Wei Lee
8833484b10 [airflow] Move AIR302 to AIR301 and AIR303 to AIR302 (#17151)
## Summary

Following up the discussion in
https://github.com/astral-sh/ruff/issues/14626#issuecomment-2766548545,
we're to reorganize airflow rules. Before this discussion happens, we
combine required changes and suggested changes in to one single error
code.

This PR first rename the original error code to the new error code as we
discussed. We will gradually extract suggested changes out of AIR301 and
AIR302 to AIR311 and AIR312 in the following PRs

## Test Plan

Except for file, error code rename, the test case should work as it used
to be.
2025-04-02 23:01:31 +05:30
Andrew Gallant
adeba3dca7 ruff_db: simplify lifetimes on DiagnosticDisplay
I initially split the lifetime out into three distinct lifetimes on
near-instinct because I moved the struct into the public API. But
because they are all shared borrows, and because there are no other APIs
on `DisplayDiagnostic` to access individual fields (and probably never
will be), it's probably fine to just specify one lifetime. Because of
subtyping, the one lifetime will be the shorter of the three.

There's also the point that `ruff_db` isn't _really_ a public API, since
it isn't a library that others depend on. So my instinct is probably a
bit off there.
2025-04-02 12:47:02 -04:00
David Peter
af988bf866 [red-knot] Detect division-by-zero in unions and intersections (#17157)
## Summary

With this PR, we emit a diagnostic for this case where
previously didn't:
```py
from typing import Literal

def f(m: int, n: Literal[-1, 0, 1]):
    # error: [division-by-zero] "Cannot divide object of type `int` by zero"
    return m / n
```

## Test Plan

New Markdown test
2025-04-02 18:21:27 +02:00
Wei Lee
f989c2c3af [airflow] Add autofix infrastructure to AIR302 name checks (#16965)
## Summary

Add autofix infrastructure to `AIR302` name checks and use this logic to 
fix`"airflow", "api_connexion", "security", "requires_access_dataset"`, `"airflow", "Dataset"` and `"airflow",
"datasets", "Dataset"`

## Test Plan

The existing test fixture reflects the update
2025-04-02 15:27:51 +00:00
trag1c
c2512b4c50 [flake8-bandit] Mark str and list[str] literals as trusted input (S603) (#17136)
## Summary

Closes #17112. Allows passing in string and list-of-strings literals
into `subprocess.run` (and related) calls without marking them as
untrusted input:
```py
import subprocess

subprocess.run("true")

# "instant" named expressions are also allowed
subprocess.run(c := "ls")
```

## Test Plan

Added test cases covering new behavior, passed with `cargo nextest run`.
2025-04-02 11:22:37 -04:00
Wei Lee
6bc2b04c49 [airflow] Add autofix for AIR302 attribute checks (#16977)
## Summary

Add autofix logic to AIR302 check_method

## Test Plan

test fixtures have been updated accordingly
2025-04-02 15:18:24 +00:00
Wei Lee
fc2a0950eb [airflow] Extend AIR302 with additional symbols (#17085)
## Summary

* ``airflow.auth.managers.base_auth_manager.is_authorized_dataset`` has
been moved to
``airflow.api_fastapi.auth.managers.base_auth_manager.is_authorized_asset``
in Airflow 3.0
* ``airflow.auth.managers.models.resource_details.DatasetDetails`` has
been moved to
``airflow.api_fastapi.auth.managers.models.resource_details.AssetDetails``
in Airflow 3.0
* Dag arguments `default_view` and `orientation` has been removed in
Airflow 3.0
* `airflow.models.baseoperatorlink.BaseOperatorLink` has been moved to
`airflow.sdk.definitions.baseoperatorlink.BaseOperatorLink` in Airflow
3.0
* ``airflow.notifications.basenotifier.BaseNotifier`` has been moved to
``airflow.sdk.BaseNotifier`` in Airflow 3.0
* ``airflow.utils.log.secrets_masker`` has been moved to
``airflow.sdk.execution_time.secrets_masker`` in Airflow 3.0
* ``airflow...DAG.allow_future_exec_dates`` has been removed in Airflow
3.0
* `airflow.utils.db.create_session` has een removed in Airflow 3.0
* `airflow.sensors.base_sensor_operator.BaseSensorOperator` has been
moved to `airflow.sdk.bases.sensor.BaseSensorOperator` removed Airflow
3.0
* `airflow.utils.file.TemporaryDirectory` has been removed in Airflow
3.0 and can be replaced by `tempfile.TemporaryDirectory`
* `airflow.utils.file.mkdirs` has been removed in Airflow 3.0 and can be
replaced by `pathlib.Path({path}).mkdir`

## Test Plan

Test fixture has been added for these changes
2025-04-02 20:38:52 +05:30
Wei Lee
33bd08f49b [airflow] Move AIR301 to AIR002 (#16978)
## Summary

Unlike other AIR3XX rules, this best practice can be applied to Airflow
1 and Airflow 2 as well. Thus, we think it might make sense for use to
move it to AIR002 so that the first number of the error align to Airflow
version as possible to reduce confusion

## Test Plan

the test fixture has been updated
2025-04-02 20:37:35 +05:30
Wei Lee
5d57788328 [airflow] Add autofix for AIR302 method checks (#16976)
## Summary

Add autofix logic to `AIR302` method checks

## Test Plan

Test fixtures have been updated accordingly
2025-04-02 20:35:49 +05:30
Andrew Gallant
718b0cadf4 ruff_db: switch diagnostic rendering over to std::fmt::Display
It was already using this approach internally, so this is "just" a
matter of rejiggering the public API of `Diagnostic`.

We were previously writing directly to a `std::io::Write` since it was
thought that this worked better with the linear typing fakery. Namely,
it increased confidence that the diagnostic rendering was actually
written somewhere useful, instead of just being converted to a string
that could potentially get lost.

For reasons discussed in #17130, the linear type fakery was removed.
And so there is less of a reason to require a `std::io::Write`
implementation for diagnostic rendering. Indeed, this would sometimes
result in `unwrap()` calls when one wants to convert to a `String`.
2025-04-02 11:01:16 -04:00
Micha Reiser
24498e383d [red-knot] Add 'Goto type definition' to the playground (#17055)
## Summary

This PR adds Goto type definition to the playground, using the same
infrastructure as the LSP.


The main *challenge* with implementing this feature was that the editor
can now participate in which tab is open.

## Known limitations

The same as for the LSP. Most notably, navigating to types defined in
typeshed isn't supported.

## Test Plan


https://github.com/user-attachments/assets/22dad7c8-7ac7-463f-b066-5d5b2c45d1fe
2025-04-02 16:35:31 +02:00
Andrew Gallant
28c7e724e3 red_knot_ide: update snapshots
This just adds an extra blank line. I think these tests were written
against the new renderer before it was used by Red Knot's `main`
function. Once I did that, I saw that it was missing a blank line, and
so I added it to match the status quo. But that means these snapshots
have become stale. So this commit updates them.
2025-04-02 10:10:01 -04:00
Andrew Gallant
185bcfef1a red_knot_python_semantic: remove comment about TypeCheckDiagnostic
I put this in its own commit in case all of the information removed here
was controversial. But it *looks* stale to me. At the very least,
`TypeCheckDiagnostic` no longer exists, so that would need to be fixed.
And it doesn't really make sense to me (at this point) to make
`Diagnostic` a Salsa struct, particularly since we are keen on using it
in Ruff (at some point).
2025-04-02 10:10:01 -04:00
Andrew Gallant
c30e80a3f4 ruff_db: delete most of the old diagnostic code
We do keep around `OldSecondaryDiagnosticMessage`, since that's part of
the Red Knot `InferContext` API. But it's a rather simple type, and
we'll be able to delete it entirely once `InferContext` exposes the new
`Diagnostic` type directly.

Since we aren't consuming `OldSecondaryDiagnosticMessage` any more, we
can now accept a slice instead of a vec. (Thanks Clippy.)
2025-04-02 10:10:01 -04:00
Andrew Gallant
4e169e5f6c red_knot: use Diagnostic inside of red knot
This replaces things like `TypeCheckDiagnostic` with the new Diagnostic`
type.

This is a "surgical" replacement where we retain the existing API of
of diagnostic reporting such that _most_ of Red Knot doesn't need to be
changed to support this update. But it will enable us to start using the
new diagnostic renderer and to delete the old renderer. It also paves
the path for exposing the new `Diagnostic` data model to the broader Red
Knot codebase.
2025-04-02 10:10:01 -04:00
Andrew Gallant
883b8e3870 ruff_db: port concise diagnostic rendering to new renderer
Previously, this was only available in the old renderer.
To avoid regressions, we just copy it to the new renderer.
We don't bother with DRY because the old renderer will be
deleted very soon.
2025-04-02 10:10:01 -04:00
Andrew Gallant
2ca2f73ba8 ruff_db: tweak line terminators emitted by diagnostic rendering
This change just brings diagnostic rendering into parity
with the status quo.
2025-04-02 10:10:01 -04:00
Andrew Gallant
90f0766210 ruff_db: make Diagnostic::print use a non-mutable borrow
Now that we don't need to update the `printed` flag, this can just be an
immutable borrow.

(Arguably this should have been an immutable borrow even initially, but
I didn't want to introduce interior mutability without a more compelling
justification.)
2025-04-02 10:10:01 -04:00
Andrew Gallant
a9527edbbe ruff_db: switch Diagnostic to use Arc, drop linear type fakery
The switch to `Arc` was done because Salsa sometimes requires cloning a
`Diagnostic` (or something that contains a `Diagnostic`). And so it
probably makes sense to make this cheap.

Since `Diagnostic` exposes a mutable API, we adopt "clone on write"
semantics. Although, it's more like, "clone on write when the `Arc` has
more than one reference." In the common case of creating a `Diagnostic`
and then immediately mutating it, no additional copies should be made
over the status quo.

We also drop the linear type fakery. Its interaction with Salsa is
somewhat awkward, and it has been suggested that there will be points
where diagnostics will be dropped unceremoniously without an opportunity
to tag them as having been ignored. Moreover, this machinery was added
out of "good sense" and isn't actually motivated by real world problems
with accidentally ignoring diagnostics. So that makes it easier, I
think, to just kick this out entirely instead of trying to find a way to
make it work.
2025-04-02 10:10:01 -04:00
Andrew Gallant
57be814acb ruff_db: add method to create sub-diagnostics from old secondary messages
This is temporary to scaffold the refactor.

The main idea is that we want to take the `InferContext` API,
*as it is*, and migrate that to the new diagnostic data model
*internally*. Then we can rip out the old stuff and iterate
on the API.
2025-04-02 10:10:01 -04:00
Andrew Gallant
a8a18e7171 red_knot_python_semantic: remove WithDiagnostic trait
I did this mostly because it wasn't buying us much, and I'm
trying to simplify the public API of the types I'd like to
refactor in order to make the refactor simpler.

If we really want something like this, we can re-add it
later.
2025-04-02 10:10:01 -04:00
Andrew Gallant
a953373892 red_knot_python_semantic: remove Deref impl on TypeCheckDiagnostics
I removed this to see how much code was depending internally on the
`&[Arc<TypeCheckDiagnostic>]` representation. Thankfully, it was just
one place. So I just removed the `Deref` impl in favor of adding an
explicit `iter` method.

In general, I think using `Deref` for things like this is _somewhat_ of
an abuse. The tip-off is if there are `&self` or `&mut self` methods on
the type, then it's probably not a good candidate for `Deref`.
2025-04-02 10:10:01 -04:00
Brent Westbrook
d382065f8a [syntax-errors] Reimplement PLE0118 (#17135)
Summary
--

This PR reimplements
[load-before-global-declaration
(PLE0118)](https://docs.astral.sh/ruff/rules/load-before-global-declaration/)
as a semantic syntax error.

I added a `global` method to the `SemanticSyntaxContext` trait to make
this very easy, at least in ruff. Does red-knot have something similar?

If this approach will also work in red-knot, I think some of the other
PLE rules are also compile-time errors in CPython, PLE0117 in
particular. 0115 and 0116 also mention `SyntaxError`s in their docs, but
I haven't confirmed them in the REPL yet.

Test Plan
--

Existing linter tests for PLE0118. I think this actually can't be tested
very easily in an inline test because the `TestContext` doesn't have a
real way to track globals.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-02 13:03:44 +00:00
Brent Westbrook
d45593288f [syntax-errors] Starred expressions in return, yield, and for (#17134)
Summary
--

Fixes https://github.com/astral-sh/ruff/issues/16520 by flagging single,
starred expressions in `return`, `yield`, and
`for` statements.

I thought `yield from` would also be included here, but that error is
emitted by
the CPython parser:

```pycon
>>> ast.parse("def f(): yield from *x")
Traceback (most recent call last):
  File "<python-input-214>", line 1, in <module>
    ast.parse("def f(): yield from *x")
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/ast.py", line 54, in parse
    return compile(source, filename, mode, flags,
                   _feature_version=feature_version, optimize=optimize)
  File "<unknown>", line 1
    def f(): yield from *x
                        ^
SyntaxError: invalid syntax
```

And we also already catch it in our parser.

Test Plan
--

New inline tests and updates to existing tests.
2025-04-02 08:38:25 -04:00
Micha Reiser
2ae39edccf [red-knot] Goto type definition (#16901)
## Summary

Implement basic *Goto type definition* support for Red Knot's LSP.

This PR also builds the foundation for other LSP operations. E.g., Goto
definition, hover, etc., should be able to reuse some, if not most,
logic introduced in this PR.

The basic steps of resolving the type definitions are:

1. Find the closest token for the cursor offset. This is a bit more
subtle than I first anticipated because the cursor could be positioned
right between the callee and the `(` in `call(test)`, in which case we
want to resolve the type for `call`.
2. Find the node with the minimal range that fully encloses the token
found in 1. I somewhat suspect that 1 and 2 could be done at the same
time but it complicated things because we also need to compute the spine
(ancestor chain) for the node and there's no guarantee that the found
nodes have the same ancestors
3. Reduce the node found in 2. to a node that is a valid goto target.
This may require traversing upwards to e.g. find the closest expression.
4. Resolve the type for the goto target
5. Resolve the location for the type, return it to the LSP

## Design decisions

The current implementation navigates to the inferred type. I think this
is what we want because it means that it correctly accounts for
narrowing (in which case we want to go to the narrowed type because
that's the value's type at the given position). However, it does have
the downside that Goto type definition doesn't work whenever we infer `T
& Unknown` because intersection types aren't supported. I'm not sure
what to do about this specific case, other than maybe ignoring `Unkown`
in Goto type definition if the type is an intersection?

## Known limitations

* Types defined in the vendored typeshed aren't supported because the
client can't open files from the red knot binary (we can either
implement our own file protocol and handler OR extract the typeshed
files and point there). See
https://github.com/astral-sh/ruff/issues/17041
* Red Knot only exposes an API to get types for expressions and
definitions. However, there are many other nodes with identifiers that
can have a type (e.g. go to type of a globals statement, match patterns,
...). We can add support for those in separate PRs (after we figure out
how to query the types from the semantic model). See
https://github.com/astral-sh/ruff/issues/17113
* We should have a higher-level API for the LSP that doesn't directly
call semantic queries. I intentionally decided not to design that API
just yet.


## Test plan


https://github.com/user-attachments/assets/fa077297-a42d-4ec8-b71f-90c0802b4edb

Goto type definition on a union

<img width="1215" alt="Screenshot 2025-04-01 at 13 02 55"
src="https://github.com/user-attachments/assets/689cabcc-4a86-4a18-b14a-c56f56868085"
/>



Note: I recorded this using a custom typeshed path so that navigating to
builtins works.
2025-04-02 12:12:48 +00:00
cake-monotone
7e97910704 [red-knot] Fix _NotImplementedType check for Python >=3.10 (#17143)
<!--
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

from https://github.com/astral-sh/ruff/pull/17034#discussion_r2024222525

This is a simple PR to fix the invalid behavior of `NotImplemented` on
Python >=3.10.


## Test Plan

I think it would be better if we could run mdtest across multiple Python
versions in GitHub Actions.

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

---------

Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-04-02 10:02:59 +00:00
David Peter
ae2cf91a36 [red-knot] Decorators and properties (#17017)
## Summary

Add support for decorators on function as well as support
for properties by adding special handling for `@property` and `@<name of
property>.setter`/`.getter` decorators.

closes https://github.com/astral-sh/ruff/issues/16987

## Ecosystem results

- ✔️ A lot of false positives are fixed by our new
understanding of properties
- 🔴 A bunch of new false positives (typically
`possibly-unbound-attribute` or `invalid-argument-type`) occur because
we currently do not perform type narrowing on attributes. And with the
new understanding of properties, this becomes even more relevant. In
many cases, the narrowing occurs through an assertion, so this is also
something that we need to implement to get rid of these false positives.
- 🔴 A few new false positives occur because we do not
understand generics, and therefore some calls to custom setters fail.
- 🔴 Similarly, some false positives occur because we do not
understand protocols yet.
- ✔️ Seems like a true positive to me. [The
setter](e624d8edfa/src/packaging/specifiers.py (L752-L754))
only accepts `bools`, but `None` is assigned in [this
line](e624d8edfa/tests/test_specifiers.py (L688)).
  ```
+ error[lint:invalid-assignment]
/tmp/mypy_primer/projects/packaging/tests/test_specifiers.py:688:9:
Invalid assignment to data descriptor attribute `prereleases` on type
`SpecifierSet` with custom `__set__` method
  ```
- ✔️ This is arguable also a true positive. The setter
[here](0c6c75644f/rich/table.py (L359-L363))
returns `Table`, but typeshed wants [setters to return
`None`](bf8d2a9912/stdlib/builtins.pyi (L1298)).
  ```
+ error[lint:invalid-argument-type]
/tmp/mypy_primer/projects/rich/rich/table.py:359:5: Object of type
`Literal[padding]` cannot be assigned to parameter 2 (`fset`) of bound
method `setter`; expected type `(Any, Any, /) -> None`
  ```  

## Follow ups

- Fix the `@no_type_check` regression
- Implement class decorators

## Test Plan

New Markdown test suites for decorators and properties.
2025-04-02 09:27:46 +02:00
Mohammad Amin Ghasemi
e1b5b0de71 [flake8-import-conventions] Add import numpy.typing as npt to default flake8-import-conventions.aliases (#17133)
## Summary
Adds import `numpy.typing as npt` to `default in
flake8-import-conventions.aliases`
Resolves #17028

## Test Plan
Manually ran local ruff on the altered fixture and also ran `cargo test`
2025-04-02 09:25:46 +02:00
Dhruv Manilawala
f63024843c [red-knot] Move tuple containing Never tests (#17137)
Refer
https://github.com/astral-sh/ruff/pull/17094#discussion_r2023682840
2025-04-02 02:46:18 +00:00
Matthew Mckee
eb3e176309 [red-knot] Add callable subtyping for callable instances and bound methods (#17105)
## Summary

Trying to improve #17005
Partially fixes #16953

## Test Plan

Update is_subtype_of.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-04-01 23:40:44 +00:00
Dhruv Manilawala
d38f6fcc55 [red-knot] Add property tests for callable types (#17006)
## Summary

Part of #15382, this PR adds property tests for callable types.

Specifically, this PR updates the property tests to generate an
arbitrary signature for a general callable type which includes:
* Arbitrary combination of parameter kinds in the correct order
* Arbitrary number of parameters
* Arbitrary optional types for annotation and return type
* Arbitrary parameter names (no duplicate names), optional for
positional-only parameters

## Test Plan

```
QUICKCHECK_TESTS=100000 cargo test -p red_knot_python_semantic -- --ignored types::property_tests::stable
```

Also, the commands in CI:


d72b4100a3/.github/workflows/daily_property_tests.yaml (L47-L52)
2025-04-02 01:07:42 +05:30
Dhruv Manilawala
6be0a5057d [red-knot] Disjointness for callable types (#17094)
## Summary

Part of #15382, this PR adds support for disjointness between two
callable types. They are never disjoint because there exists a callable
type that's a subtype of all other callable types:
```py
(*args: object, **kwargs: object) -> Never
```

The `Never` is a subtype of every fully static type thus a callable type
that has the return type of `Never` means that it is a subtype of every
return type.

## Test Plan

Add test cases related to mixed parameter kinds, gradual form (`...`)
and `Never` type.
2025-04-01 19:00:27 +00:00
Alex Waygood
d6dcc377f7 [red-knot] Flatten Type::Callable into four Type variants (#17126)
## Summary

Currently our `Type::Callable` wraps a four-variant `CallableType` enum.
But as time has gone on, I think we've found that the four variants in
`CallableType` are really more different to each other than they are
similar to each other:
- `GeneralCallableType` is a structural type describing all callable
types with a certain signature, but the other three types are "literal
types", more similar to the `FunctionLiteral` variant
- `GeneralCallableType` is not a singleton or a single-valued type, but
the other three are all single-valued types
(`WrapperDescriptorDunderGet` is even a singleton type)
- `GeneralCallableType` has (or should have) ambiguous truthiness, but
all possible inhabitants of the other three types are always truthy.
- As a structural type, `GeneralCallableType` can contain inner unions
and intersections that must be sorted in some contexts in our internal
model, but this is not true for the other three variants.

This PR flattens `Type::Callable` into four distinct `Type::` variants.
In the process, it fixes a number of latent bugs that were concealed by
the current architecture but are laid bare by the refactor. Unit tests
for these bugs are included in the PR.
2025-04-01 19:30:06 +01:00
Alex Waygood
a43b683d08 mdtest.py: do a full mdtest run immediately when the script is executed (#17128)
## Summary

Currently if I run `uv run crates/red_knot_python_semantic/mdtest.py`
from the Ruff repo root, I get this output:

```
~/dev/ruff (main) % uv run crates/red_knot_python_semantic/mdtest.py
Ready to watch for changes...
```

...And I then have to make some spurious whitespace changes or something
to a test file in order to get the script to actually run mdtest. This
PR changes mdtest.py so that it does an initial run of all mdtests when
you invoke the script, and _then_ starts watching for changes in test
files/Rust code.
2025-04-01 19:27:55 +01:00
Dhruv Manilawala
d29d4956de [red-knot] Fix callable subtyping for standard parameters (#17125)
## Summary

This PR fixes a bug in callable subtyping to consider both the
positional and keyword form of the standard parameter in the supertype
when matching against variadic, keyword-only and keyword-variadic
parameter in the subtype.

This is done by collecting the unmatched standard parameters and then
checking them against the keyword-only / keyword-variadic parameters
after the positional loop.

## Test Plan

Add test cases.
2025-04-01 23:37:35 +05:30
Alex Waygood
c74ba00219 [red-knot] Fix more redundant-cast false positives (#17119)
## Summary

There are quite a few places we infer `Todo` types currently, and some
of them are nested somewhat deeply in type expressions. These can cause
spurious issues for the new `redundant-cast` diagnostics. We fixed all
the false positives we saw in the mypy_primer report before merging
https://github.com/astral-sh/ruff/pull/17100, but I think there are
still lots of places where we'd emit false positives due to this check
-- we currently don't run on that many projects at all in our
mypy_primer check:


d0c8eaa092/.github/workflows/mypy_primer.yaml (L71)

This PR fixes some more false positives from this diagnostic by making
the `Type::contains_todo()` method more expansive.

## Test Plan

I added a regression test which causes us to emit a spurious diagnostic
on `main`, but does not with this PR.
2025-04-01 19:03:42 +01:00
github-actions[bot]
a15404a5c1 Sync vendored typeshed stubs (#17106)
Close and reopen this PR to trigger CI

Co-authored-by: typeshedbot <>
2025-04-01 17:44:27 +01:00
Carl Meyer
3f63c08728 [red-knot] support Any as a class in typeshed (#17107)
## Summary

In https://github.com/python/typeshed/pull/13520 the typeshed definition
of `typing.Any` was changed from `Any = object()` to `class Any: ...`.
Our automated typeshed updater pulled down this change in
https://github.com/astral-sh/ruff/pull/17106, with the consequence that
we no longer understand `Any`, which is... not good.

This PR gives us the ability to understand `Any` defined as a class
instead of `object()`. It doesn't remove our ability to understand the
old form. Perhaps at some point we'll want to remove it, but for now we
may as well support both old and new typeshed?

This also directly patches typeshed to use the new form of `Any`; this
is purely to work around our tests that no known class is inferred as
`Unknown`, which otherwise fail with the old typeshed and the changes in
this PR. (All other tests pass.) This patch to typeshed will shortly be
subsumed by https://github.com/astral-sh/ruff/pull/17106 anyway.

## Test Plan

Without the typeshed change in this PR, all tests pass except for the
two `known_class_doesnt_fallback_to_unknown_unexpectedly_*` tests (so we
still support the old form of defining `Any`). With the typeshed change
in this PR, all tests pass, so we now support the new form in a way that
is indistinguishable to our test suite from the old form. And
indistinguishable to the ecosystem check: after rebasing
https://github.com/astral-sh/ruff/pull/17106 on this PR, there's zero
ecosystem impact.
2025-04-01 16:38:23 +00:00
Micha Reiser
5a876ed25e Visit Identifier node as part of the SourceOrderVisitor (#17110)
## Summary

I don't remember exactly when we made `Identifier` a node but it is now
considered a node (it implements `AnyNodeRef`, it has a range). However,
we never updated
the `SourceOrderVisitor` to visit identifiers because we never had a use
case for it and visiting new nodes can change how the formatter
associates comments (breaking change!).
This PR updates the `SourceOrderVisitor` to visit identifiers and
changes the formatter comment visitor to skip identifiers (updating the
visitor might be desired because it could help simplifying some comment
placement logic but this is out of scope for this PR).

## Test Plan

Tests, updated snapshot tests
2025-04-01 16:58:09 +02:00
Alex Waygood
49c25993eb [red-knot] Don't infer Todo for quite so many tuple type expressions (#17116)
## Summary

I noticed we were inferring `Todo` as the declared type for annotations
such as `x: tuple[list[int], list[int]]`. This PR reworks our annotation
parsing so that we instead infer `tuple[Todo, Todo]` for this
annotation, which is quite a bit more precise.

## Test Plan

Existing mdtest updated.
2025-04-01 15:44:02 +01:00
Aarni Koskela
8e6a83b33e CI: Run pre-commit on depot machine (#17120)
## Summary

Sibling/alternate of #17108 (see
https://github.com/astral-sh/ruff/pull/17108#issuecomment-2769200896).

See if running the pre-commit CI step on Depot machines makes
WASM-compiled shellcheck faster.

## Test Plan

> How was it tested?

We're doing it live!
2025-04-01 14:22:02 +01:00
Max Mynter
d0c8eaa092 Error instead of panic! when running Ruff from a deleted directory (#16903) (#17054)
<!--
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?
-->
Closes #16903

## Summary
Check if the current working directory exist. If not, provide an error
instead of panicking.

Fixed a stale comment in `resolve_default_files`.

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

## Test Plan
I added a test to the `resolve_files.rs`. 

Manual testing follows steps of #16903 :
- Terminal 1
```bash
mkdir tmp
cd tmp
```
- Terminal 2
```bash
rm -rf tmp
```
- Terminal 1
```bash
ruff check
```

## Open Issues / Questions to Reviewer
All tests pass when executed with `cargo nextest run`.

However, with `cargo test` the parallelization makes the other tests
fail as we change the `pwd`.

Serial execution with `cargo test` seems to require [another dependency
or some
workarounds](https://stackoverflow.com/questions/51694017/how-can-i-avoid-running-some-tests-in-parallel).

Do you think an additional dependency or test complexity is worth
testing this small edge case, do you have another implementation idea,
or should i rather remove the test?
  
---
P.S.: I'm currently participating in a batch at the [Recurse
Center](https://www.recurse.com/) and would love to contribute more for
the next six weeks to improve my Rust. Let me know if you're open to
mentoring/reviewing and/or if you have specific areas where help would
be most valued.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-01 14:17:07 +02:00
Dylan
aa93005d8d Control flow graph: setup (#17064)
This PR contains the scaffolding for a new control flow graph
implementation, along with its application to the `unreachable` rule. At
the moment, the implementation is a maximal over-approximation: no
control flow is modeled and all statements are counted as reachable.
With each additional statement type we support, this approximation will
improve.

So this PR just contains:
- A `ControlFlowGraph` struct and builder
- Support for printing the flow graph as a Mermaid graph
- Snapshot tests for the actual graphs
- (a very bad!) reimplementation of `unreachable` using the new structs
- Snapshot tests for `unreachable`

# Instructions for Viewing Mermaid snapshots
Unfortunately I don't know how to convince GitHub to render the Mermaid
graphs in the snapshots. However, you can view these locally in VSCode
if you install an extension that supports Mermaid graphs in Markdown,
and then add this to your `settings.json`:

```json
  "files.associations": {
"*.md.snap": "markdown",
  }
  ```
2025-04-01 05:53:42 -05:00
Micha Reiser
0073fd4945 [red-knot] Playground improvements (#17109)
## Summary

A few smaller editor improvements that felt worth pulling out of my
other feature PRs:

* Load the `Editor` lazily: This allows splitting the entire monaco
javascript into a separate async bundle, drastically reducing the size
of the `index.js`
* Fix the name of `to_range` and `text_range` to the more idiomatic js
names `toRange` and `textRange`
* Use one indexed values for `Position::line` and `Position::column`,
which is the same as monaco (reduces the need for `+1` and `-1`
operations spread all over the place)
* Preserve the editor state when navigating between tabs. This ensures
that selections are preserved even when switching between tabs.
* Stop the default handling of the `Enter` key press event when renaming
a file because it resulted in adding a newline in the editor
2025-04-01 10:04:51 +02:00
Micha Reiser
b57c62e6b3 [red-knot] IDE crate (#17045)
## Summary

This PR adds a new but so far empty and unused `red_knot_ide` crate. 

This new crate's purpose is to implement IDE-specific functionality,
such as go to definition, hover, completion, etc., which are used by
both the LSP and the playground.

The crate itself doesn't depend on `lsptypes`. The idea is that the
facade crates (e.g., `red_knot_server`) convert external to internal
types.
Not only allows this to share the logic between server and playground,
it also ensures that the core functionality is easier to test because it
can be tested without needing a full LSP.



## Test Plan

`cargo build`
2025-04-01 09:36:00 +02:00
renovate[bot]
a9dbfebc61 Update dependency vite to v6.2.4 (#17104) 2025-04-01 08:29:59 +02:00
Trevor Manz
53cfaaebc4 [red-knot] Add redundant-cast error (#17100)
## Summary

Following up from earlier discussion on Discord, this PR adds logic to
flag casts as redundant when the inferred type of the expression is the
same as the target type. It should follow the semantics from
[mypy](https://github.com/python/mypy/pull/1705).

Example:

```python
def f() -> int:
    return 10

# error: [redundant-cast] "Value is already of type `int`"
cast(int, f())
```
2025-04-01 00:37:25 +00:00
Matthew Mckee
3ad123bc23 [red-knot] Narrowing on in tuple[...] and in str (#17059)
## Summary

Part of #13694

Seems there a bit more to cover regarding `in` and other types, but i
can cover them in different PRs

## Test Plan
Add `in.md` file in narrowing conditionals folder

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-31 23:38:09 +00:00
Micha Reiser
a1535fbdbd [red-knot] Change venv discovery (#17099)
## Summary

Rewrites the virtual env discovery to:

* Only use of `System` APIs, this ensures that the discovery will also
work when using a memory file system (testing or WASM)
* Don't traverse ancestor directories. We're not convinced that this is
necessary. Let's wait until someone shows us a use case where it is
needed
* Start from the project root and not from the current working
directory. This ensures that Red Knot picks up the right venv even when
using `knot --project ../other-dir`

## Test Plan

Existing tests, @ntBre tested that the `file_watching` tests no longer
pick up his virtual env in a parent directory
2025-03-31 19:39:05 +02:00
Matthew Mckee
4a6fa5fc27 [red-knot] Add assignability of function literals to callables (#17095)
## Summary

Part  of #16953

## Test Plan

Update is_assignable_to.md

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-03-31 15:42:42 +00:00
Aarni Koskela
491a51960e [ruff] Support slices in RUF005 (#17078)
## Summary

Teaches `RUF005` to also consider slices for concatenation. Other
indexing (`foo[0] + [7, 8, 9] + bar[1]`) is explicitly not considered.

```diff
 foo = [4, 5, 6]
-bar = [1, 2, 3] + foo
-slicing1 = foo[:1] + [7, 8, 9]
-slicing2 = [7, 8, 9] + bar[1:]
-slicing3 = foo[:1] + [7, 8, 9] + bar[1:]
+bar = [1, 2, 3, *foo]
+slicing1 = [*foo[:1], 7, 8, 9]
+slicing2 = [7, 8, 9, *bar[1:]]
+slicing3 = [*foo[:1], 7, 8, 9, *bar[1:]]
```

## Test Plan

Manually tested (diff above from `ruff check --diff`), snapshot updated.
2025-03-31 09:09:39 -04:00
David Peter
2d7f118f52 [red-knot] Binary operator inference: generalize code for non-instances (#17081)
## Summary

Generalize the rich-comparison fallback code for binary operator
inference. This gets rid of one `todo_type!(…)` and implements the last
remaining failing case from
https://github.com/astral-sh/ruff/issues/14200.

closes https://github.com/astral-sh/ruff/issues/14200

## Test Plan

New Markdown tests.
2025-03-31 13:01:25 +02:00
David Peter
3d1e5676fb [red-knot] Add ParamSpecArgs and ParamSpecKwargs as KnownClass (#17086)
## Summary

In preparation for #17017, where we will need them to suppress new false
positives (once we understand the `ParamSpec.args`/`ParamSpec.kwargs`
properties).

## Test Plan

Tested on branch #17017
2025-03-31 10:52:23 +00:00
Wei Lee
0b1ab8fd5a [airflow] Combine AIR302 matches (#17080)
<!--
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? -->

* Combine AIR302 matches
* Found a few errors. Will be fixed in another PR

## Test Plan

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

This PR does not change anything. The existing testing fixture should
work as it used to be
2025-03-31 12:17:18 +02:00
David Peter
d9616e61b0 [red-knot] Disallow todo_type! without custom message (#17083)
## Summary

Disallow empty `todo_type!()`s without a custom message. They can lead
to spurious diffs in `mypy_primer` where the only thing that's changed
is the file/line information.
2025-03-31 10:49:19 +02:00
Wei Lee
fa80e10aac [airflow] fix typos in AIR302 implementation and test cases (#17082)
<!--
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? -->

* The following paths are wrong 
* `airflow.providers.amazon.auth_manager.avp.entities` should be
`airflow.providers.amazon.aws.auth_manager.avp.entities`
* `["airflow", "datasets", "manager", "dataset_manager"]` should be
fixed as `airflow.assets.manager` but not
`airflow.assets.manager.asset_manager`
* `["airflow", "datasets.manager", "DatasetManager"]` should be `
["airflow", "datasets", "manager", "DatasetManager"]` instead

## Test Plan

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

the test fixture is updated accordingly
2025-03-31 10:42:04 +02:00
Wei Lee
30a5f69913 [airflow] fix missing or wrong test cases (AIR302) (#16968)
<!--
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? -->
Improve AIR302 test cases

## Test Plan

<!-- How was it tested? -->
test fixtures have been updated accordingly
2025-03-31 10:22:45 +02:00
renovate[bot]
a192d96880 Update pre-commit dependencies (#17073)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[abravalheri/validate-pyproject](https://redirect.github.com/abravalheri/validate-pyproject)
| repository | patch | `v0.24` -> `v0.24.1` |
|
[astral-sh/ruff-pre-commit](https://redirect.github.com/astral-sh/ruff-pre-commit)
| repository | patch | `v0.11.0` -> `v0.11.2` |
| [crate-ci/typos](https://redirect.github.com/crate-ci/typos) |
repository | minor | `v1.30.2` -> `v1.31.0` |
|
[python-jsonschema/check-jsonschema](https://redirect.github.com/python-jsonschema/check-jsonschema)
| repository | minor | `0.31.3` -> `0.32.1` |
|
[woodruffw/zizmor-pre-commit](https://redirect.github.com/woodruffw/zizmor-pre-commit)
| repository | patch | `v1.5.1` -> `v1.5.2` |

---

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

Note: The `pre-commit` manager in Renovate is not supported by the
`pre-commit` maintainers or community. Please do not report any problems
there, instead [create a Discussion in the Renovate
repository](https://redirect.github.com/renovatebot/renovate/discussions/new)
if you have any questions.

---

### Release Notes

<details>
<summary>abravalheri/validate-pyproject
(abravalheri/validate-pyproject)</summary>

###
[`v0.24.1`](https://redirect.github.com/abravalheri/validate-pyproject/releases/tag/v0.24.1)

[Compare
Source](https://redirect.github.com/abravalheri/validate-pyproject/compare/v0.24...v0.24.1)

#### What's Changed

- Fixed multi plugin id was read from the wrong place by
[@&#8203;henryiii](https://redirect.github.com/henryiii) in
[https://github.com/abravalheri/validate-pyproject/pull/240](https://redirect.github.com/abravalheri/validate-pyproject/pull/240)
- Implemented alternative plugin sorting,
[https://github.com/abravalheri/validate-pyproject/pull/243](https://redirect.github.com/abravalheri/validate-pyproject/pull/243)

**Full Changelog**:
https://github.com/abravalheri/validate-pyproject/compare/v0.24...v0.24.1

</details>

<details>
<summary>astral-sh/ruff-pre-commit (astral-sh/ruff-pre-commit)</summary>

###
[`v0.11.2`](https://redirect.github.com/astral-sh/ruff-pre-commit/releases/tag/v0.11.2)

[Compare
Source](https://redirect.github.com/astral-sh/ruff-pre-commit/compare/v0.11.1...v0.11.2)

See: https://github.com/astral-sh/ruff/releases/tag/0.11.2

###
[`v0.11.1`](https://redirect.github.com/astral-sh/ruff-pre-commit/releases/tag/v0.11.1)

[Compare
Source](https://redirect.github.com/astral-sh/ruff-pre-commit/compare/v0.11.0...v0.11.1)

See: https://github.com/astral-sh/ruff/releases/tag/0.11.1

</details>

<details>
<summary>crate-ci/typos (crate-ci/typos)</summary>

###
[`v1.31.0`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.31.0)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.30.3...v1.31.0)

#### \[1.31.0] - 2025-03-28

##### Features

- Updated the dictionary with the [March
2025](https://redirect.github.com/crate-ci/typos/issues/1266) changes

###
[`v1.30.3`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.30.3)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.30.2...v1.30.3)

#### \[1.30.3] - 2025-03-24

##### Features

-   Support detecting `go.work` and `go.work.sum` files

</details>

<details>
<summary>python-jsonschema/check-jsonschema
(python-jsonschema/check-jsonschema)</summary>

###
[`v0.32.1`](https://redirect.github.com/python-jsonschema/check-jsonschema/blob/HEAD/CHANGELOG.rst#0321)

[Compare
Source](https://redirect.github.com/python-jsonschema/check-jsonschema/compare/0.32.0...0.32.1)

-   Fix the `check-meltano` hook to use `types_or`. Thanks
    :user:`edgarrmondragon`! (:pr:`543`)

###
[`v0.32.0`](https://redirect.github.com/python-jsonschema/check-jsonschema/blob/HEAD/CHANGELOG.rst#0320)

[Compare
Source](https://redirect.github.com/python-jsonschema/check-jsonschema/compare/0.31.3...0.32.0)

- Update vendored schemas: circle-ci, compose-spec, dependabot,
github-workflows,
    gitlab-ci, mergify, renovate, taskfile (2025-03-25)
- Add Meltano schema and pre-commit hook. Thanks
:user:`edgarrmondragon`! (:issue:`540`)
- Add Snapcraft schema and pre-commit hook. Thanks :user:`fabolhak`!
(:issue:`535`)

</details>

<details>
<summary>woodruffw/zizmor-pre-commit
(woodruffw/zizmor-pre-commit)</summary>

###
[`v1.5.2`](https://redirect.github.com/woodruffw/zizmor-pre-commit/releases/tag/v1.5.2)

[Compare
Source](https://redirect.github.com/woodruffw/zizmor-pre-commit/compare/v1.5.1...v1.5.2)

See: https://github.com/woodruffw/zizmor/releases/tag/v1.5.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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-31 07:42:15 +00:00
Mike Perlov
5c1fab0661 Fix member lookup for unions & intersections ignoring policy (#17066)
## Summary

A quick fix for how union/intersection member search ins performed in
Knot.

## Test Plan

* Added a dunder method call test for Union, which exhibits the error
* Also added an intersection error, but it is not triggering currently
due to `call` logic not being fully implemented for intersections.

---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-03-31 09:40:47 +02:00
renovate[bot]
5f83a32553 Update Rust crate clap to v4.5.34 (#17070)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.32` -> `4.5.34` |

---

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

---

### Release Notes

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

###
[`v4.5.34`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4534---2025-03-27)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.33...v4.5.34)

##### Fixes

- *(help)* Don't add extra blank lines with `flatten_help(true)` and
subcommands without arguments

###
[`v4.5.33`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4533---2025-03-26)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.32...v4.5.33)

##### Fixes

- *(error)* When showing the usage of a suggestion for an unknown
argument, don't show the group

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:25:20 +02:00
renovate[bot]
6d387e01b4 Update Rust crate log to v0.4.27 (#17071)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [log](https://redirect.github.com/rust-lang/log) |
workspace.dependencies | patch | `0.4.26` -> `0.4.27` |

---

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

---

### Release Notes

<details>
<summary>rust-lang/log (log)</summary>

###
[`v0.4.27`](https://redirect.github.com/rust-lang/log/blob/HEAD/CHANGELOG.md#0427---2025-03-24)

[Compare
Source](https://redirect.github.com/rust-lang/log/compare/0.4.26...0.4.27)

##### What's Changed

- A few minor lint fixes by
[@&#8203;nyurik](https://redirect.github.com/nyurik) in
[https://github.com/rust-lang/log/pull/671](https://redirect.github.com/rust-lang/log/pull/671)
- Enable clippy support for format-like macros by
[@&#8203;nyurik](https://redirect.github.com/nyurik) in
[https://github.com/rust-lang/log/pull/665](https://redirect.github.com/rust-lang/log/pull/665)
- Add an optional logger param by
[@&#8203;tisonkun](https://redirect.github.com/tisonkun) in
[https://github.com/rust-lang/log/pull/664](https://redirect.github.com/rust-lang/log/pull/664)
- Pass global logger by value, supplied logger by ref by
[@&#8203;KodrAus](https://redirect.github.com/KodrAus) in
[https://github.com/rust-lang/log/pull/673](https://redirect.github.com/rust-lang/log/pull/673)

**Full Changelog**:
https://github.com/rust-lang/log/compare/0.4.26...0.4.27

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:25:04 +02:00
renovate[bot]
ef2616446a Update actions/github-script action to v7.0.1 (#17072)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/github-script](https://redirect.github.com/actions/github-script)
| action | patch | `v7` -> `v7.0.1` |

---

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

---

### Release Notes

<details>
<summary>actions/github-script (actions/github-script)</summary>

###
[`v7.0.1`](https://redirect.github.com/actions/github-script/releases/tag/v7.0.1)

[Compare
Source](https://redirect.github.com/actions/github-script/compare/v7...v7.0.1)

#### What's Changed

- Avoid setting `baseUrl` to undefined when input is not provided by
[@&#8203;joshmgross](https://redirect.github.com/joshmgross) in
[https://github.com/actions/github-script/pull/439](https://redirect.github.com/actions/github-script/pull/439)

**Full Changelog**:
https://github.com/actions/github-script/compare/v7.0.0...v7.0.1

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:24:38 +02:00
renovate[bot]
90153e5664 Update PyO3/maturin-action action to v1.47.3 (#17076)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [PyO3/maturin-action](https://redirect.github.com/PyO3/maturin-action)
| action | minor | `v1` -> `v1.47.3` |

---

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

---

### Release Notes

<details>
<summary>PyO3/maturin-action (PyO3/maturin-action)</summary>

###
[`v1.47.3`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.47.3)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.47.2...v1.47.3)

##### What's Changed

-   Install ziglang < 0.14.0

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.47.2...v1.47.3

###
[`v1.47.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.47.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.47.1...v1.47.2)

##### What's Changed

- Fix i686 libatomic install for rustup by
[@&#8203;exFalso](https://redirect.github.com/exFalso) in
[https://github.com/PyO3/maturin-action/pull/330](https://redirect.github.com/PyO3/maturin-action/pull/330)

##### New Contributors

- [@&#8203;exFalso](https://redirect.github.com/exFalso) made their
first contribution in
[https://github.com/PyO3/maturin-action/pull/330](https://redirect.github.com/PyO3/maturin-action/pull/330)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.47.1...v1.47.2

###
[`v1.47.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.47.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.47.0...v1.47.1)

##### What's Changed

- Install libatomic for cargo on i686 Linux targets by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/327](https://redirect.github.com/PyO3/maturin-action/pull/327)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.47.0...v1.47.1

###
[`v1.47.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.47.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.46.0...v1.47.0)

##### What's Changed

- Add GITHUB\_ to ALLOWED_ENV_PREFIXES by
[@&#8203;mnaser](https://redirect.github.com/mnaser) in
[https://github.com/PyO3/maturin-action/pull/323](https://redirect.github.com/PyO3/maturin-action/pull/323)
- fix: upgrade the toolchain by
[@&#8203;kemingy](https://redirect.github.com/kemingy) in
[https://github.com/PyO3/maturin-action/pull/325](https://redirect.github.com/PyO3/maturin-action/pull/325)

##### New Contributors

- [@&#8203;mnaser](https://redirect.github.com/mnaser) made their first
contribution in
[https://github.com/PyO3/maturin-action/pull/323](https://redirect.github.com/PyO3/maturin-action/pull/323)
- [@&#8203;kemingy](https://redirect.github.com/kemingy) made their
first contribution in
[https://github.com/PyO3/maturin-action/pull/325](https://redirect.github.com/PyO3/maturin-action/pull/325)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.46.0...v1.47.0

###
[`v1.46.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.46.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.45.0...v1.46.0)

##### What's Changed

- Add support for arm64 Linux runner by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/316](https://redirect.github.com/PyO3/maturin-action/pull/316)

##### New Contributors

- [@&#8203;dhruvmanila](https://redirect.github.com/dhruvmanila) made
their first contribution in
[https://github.com/PyO3/maturin-action/pull/304](https://redirect.github.com/PyO3/maturin-action/pull/304)
- [@&#8203;cclauss](https://redirect.github.com/cclauss) made their
first contribution in
[https://github.com/PyO3/maturin-action/pull/310](https://redirect.github.com/PyO3/maturin-action/pull/310)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.45.0...v1.46.0

###
[`v1.45.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.45.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.44.0...v1.45.0)

##### What's Changed

- Revert "Ignore cffi installation error" by
[@&#8203;mkniewallner](https://redirect.github.com/mkniewallner) in
[https://github.com/PyO3/maturin-action/pull/285](https://redirect.github.com/PyO3/maturin-action/pull/285)
- Upgrade TOML parser by
[@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) in
[https://github.com/PyO3/maturin-action/pull/295](https://redirect.github.com/PyO3/maturin-action/pull/295)
- Use `pip install --user` by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/296](https://redirect.github.com/PyO3/maturin-action/pull/296)

##### New Contributors

- [@&#8203;mkniewallner](https://redirect.github.com/mkniewallner) made
their first contribution in
[https://github.com/PyO3/maturin-action/pull/285](https://redirect.github.com/PyO3/maturin-action/pull/285)
- [@&#8203;gaborbernat](https://redirect.github.com/gaborbernat) made
their first contribution in
[https://github.com/PyO3/maturin-action/pull/295](https://redirect.github.com/PyO3/maturin-action/pull/295)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.44.0...v1.45.0

###
[`v1.44.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.44.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.43.0...v1.44.0)

##### What's Changed

- Update versions-manifest.json by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[https://github.com/PyO3/maturin-action/pull/269](https://redirect.github.com/PyO3/maturin-action/pull/269)
- Bump braces from 3.0.2 to 3.0.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/PyO3/maturin-action/pull/271](https://redirect.github.com/PyO3/maturin-action/pull/271)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.43.0...v1.44.0

###
[`v1.43.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.43.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.42.2...v1.43.0)

##### What's Changed

- Move before script before sccache setup by
[@&#8203;orf](https://redirect.github.com/orf) in
[https://github.com/PyO3/maturin-action/pull/264](https://redirect.github.com/PyO3/maturin-action/pull/264)
- Find PyPy in tool cache by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/268](https://redirect.github.com/PyO3/maturin-action/pull/268)
- Adds support for docker-in-docker cross platform builds by
[@&#8203;plied](https://redirect.github.com/plied) in
[https://github.com/PyO3/maturin-action/pull/266](https://redirect.github.com/PyO3/maturin-action/pull/266)

##### New Contributors

- [@&#8203;orf](https://redirect.github.com/orf) made their first
contribution in
[https://github.com/PyO3/maturin-action/pull/264](https://redirect.github.com/PyO3/maturin-action/pull/264)
- [@&#8203;plied](https://redirect.github.com/plied) made their first
contribution in
[https://github.com/PyO3/maturin-action/pull/266](https://redirect.github.com/PyO3/maturin-action/pull/266)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.42.2...v1.43.0

###
[`v1.42.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.42.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.42.1...v1.42.2)

##### What's Changed

- Remove `CARGO_HOME` from docker env var by
[@&#8203;dariocurr](https://redirect.github.com/dariocurr) in
[https://github.com/PyO3/maturin-action/pull/262](https://redirect.github.com/PyO3/maturin-action/pull/262)

##### New Contributors

- [@&#8203;dariocurr](https://redirect.github.com/dariocurr) made their
first contribution in
[https://github.com/PyO3/maturin-action/pull/262](https://redirect.github.com/PyO3/maturin-action/pull/262)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.42.1...v1.42.2

###
[`v1.42.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.42.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.42.0...v1.42.1)

##### What's Changed

- Update versions-manifest.json by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[https://github.com/PyO3/maturin-action/pull/252](https://redirect.github.com/PyO3/maturin-action/pull/252)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.42.0...v1.42.1

###
[`v1.42.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.42.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.41.0...v1.42.0)

##### What's Changed

- Add support for `--target=` by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/248](https://redirect.github.com/PyO3/maturin-action/pull/248)
- Add arm-unknown-linux-musleabihf target support by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/250](https://redirect.github.com/PyO3/maturin-action/pull/250)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.41.0...v1.42.0

###
[`v1.41.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.41.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.8...v1.41.0)

##### What's Changed

-   Upgrade to Node 20
- Bump actions/setup-python from 4 to 5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/PyO3/maturin-action/pull/239](https://redirect.github.com/PyO3/maturin-action/pull/239)
- Bump peter-evans/create-pull-request from 5 to 6 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/PyO3/maturin-action/pull/243](https://redirect.github.com/PyO3/maturin-action/pull/243)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.40.8...v1.41.0

###
[`v1.40.8`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.40.8)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.7...v1.40.8)

##### What's Changed

- Pass `CC` and `CXX` environmental variables by
[@&#8203;ijl](https://redirect.github.com/ijl) in
[https://github.com/PyO3/maturin-action/pull/232](https://redirect.github.com/PyO3/maturin-action/pull/232)

##### New Contributors

- [@&#8203;ijl](https://redirect.github.com/ijl) made their first
contribution in
[https://github.com/PyO3/maturin-action/pull/232](https://redirect.github.com/PyO3/maturin-action/pull/232)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.40.7...v1.40.8

###
[`v1.40.7`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.40.7)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.6...v1.40.7)

##### What's Changed

- Allow absolute `working-directory` by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/223](https://redirect.github.com/PyO3/maturin-action/pull/223)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.40.6...v1.40.7

###
[`v1.40.6`](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.5...v1.40.6)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.5...v1.40.6)

###
[`v1.40.5`](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.4...v1.40.5)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.4...v1.40.5)

###
[`v1.40.4`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.40.4)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.3...v1.40.4)

##### What's Changed

- Also find `rust-toolchain` file in parent directories by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/217](https://redirect.github.com/PyO3/maturin-action/pull/217)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.40.3...v1.40.4

###
[`v1.40.3`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.40.3)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.2...v1.40.3)

##### What's Changed

- Bump actions/checkout from 3 to 4 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/PyO3/maturin-action/pull/211](https://redirect.github.com/PyO3/maturin-action/pull/211)
- Correctly compute `pyproject.toml` path by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/213](https://redirect.github.com/PyO3/maturin-action/pull/213)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.40.2...v1.40.3

###
[`v1.40.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.40.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.1...v1.40.2)

##### What's Changed

- Resolve workspace target dir from `cargo metadata` output by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/200](https://redirect.github.com/PyO3/maturin-action/pull/200)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.40.1...v1.40.2

###
[`v1.40.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.40.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.40.0...v1.40.1)

##### What's Changed

- Bump peter-evans/create-pull-request from 4 to 5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/PyO3/maturin-action/pull/174](https://redirect.github.com/PyO3/maturin-action/pull/174)
- Write `run-maturin-action.sh` to a tmpdir by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/194](https://redirect.github.com/PyO3/maturin-action/pull/194)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.40.0...v1.40.1

###
[`v1.40.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.40.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.39.0...v1.40.0)

##### What's Changed

- Automatically pass `CFLAGS`/`CPPFLAGS`/`CXXFLAGS`/`LDFLAGS` by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/172](https://redirect.github.com/PyO3/maturin-action/pull/172)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.39.0...v1.40.0

###
[`v1.39.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.39.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.38.1...v1.39.0)

##### What's Changed

- Add `before-script-linux` option by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/157](https://redirect.github.com/PyO3/maturin-action/pull/157)

For running custom script to configure the build environment on Linux,
for example installing clang for `rust-bindgen`.
For macOS and Windows you can just run the command before
`maturin-action` since the builds are always run on the host machine.

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.38.1...v1.39.0

###
[`v1.38.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.38.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.38.0...v1.38.1)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.38.0...v1.38.1

###
[`v1.38.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.38.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.37.2...v1.38.0)

##### What's Changed

- Add sccache support by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/156](https://redirect.github.com/PyO3/maturin-action/pull/156)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.37.2...v1.38.0

###
[`v1.37.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.37.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.37.1...v1.37.2)

##### What's Changed

- Add support for multiline `rustup-components` option by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/154](https://redirect.github.com/PyO3/maturin-action/pull/154)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.37.1...v1.37.2

###
[`v1.37.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.37.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.37.0...v1.37.1)

##### What's Changed

- Install `cffi` by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/150](https://redirect.github.com/PyO3/maturin-action/pull/150)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.37.0...v1.37.1

###
[`v1.37.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.37.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.36.0...v1.37.0)

##### What's Changed

- Add support for `universal2-apple-darwin` target by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/149](https://redirect.github.com/PyO3/maturin-action/pull/149)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.36.0...v1.37.0

###
[`v1.36.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.36.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.35.2...v1.36.0)

##### What's Changed

- Don't pass `--zig` to unsupported targets by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/143](https://redirect.github.com/PyO3/maturin-action/pull/143)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.35.2...v1.36.0

###
[`v1.35.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.35.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.35.1...v1.35.2)

##### What's Changed

- Use unshift instead of push to allow passing rustc args by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/140](https://redirect.github.com/PyO3/maturin-action/pull/140)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.35.1...v1.35.2

###
[`v1.35.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.35.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.35.0...v1.35.1)

##### What's Changed

- Fix docker image for manylinux\_2\_28 by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/138](https://redirect.github.com/PyO3/maturin-action/pull/138)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.35.0...v1.35.1

###
[`v1.35.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.35.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.34.0...v1.35.0)

##### What's Changed

- Bump json5 from 1.0.1 to 1.0.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/PyO3/maturin-action/pull/133](https://redirect.github.com/PyO3/maturin-action/pull/133)
- Add `docker-options` for passing additional `docker run` options by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/135](https://redirect.github.com/PyO3/maturin-action/pull/135)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.34.0...v1.35.0

###
[`v1.34.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.34.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.33.0...v1.34.0)

##### What's Changed

- Forward SSH agent to Docker container by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/119](https://redirect.github.com/PyO3/maturin-action/pull/119)
- Add support for `de-vri-es/setup-git-credentials` action by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/120](https://redirect.github.com/PyO3/maturin-action/pull/120)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.33.0...v1.34.0

###
[`v1.33.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.33.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.32.2...v1.33.0)

##### What's Changed

- Fallback to local host build when no default docker image found by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/118](https://redirect.github.com/PyO3/maturin-action/pull/118)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.32.2...v1.33.0

###
[`v1.32.2`](https://redirect.github.com/PyO3/maturin-action/compare/v1.32.1...v1.32.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.32.1...v1.32.2)

###
[`v1.32.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.32.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.32.0...v1.32.1)

##### What's Changed

- Remove hardcoded `MACOSX_DEPLOYMENT_TARGET` by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/113](https://redirect.github.com/PyO3/maturin-action/pull/113)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.32.0...v1.32.1

###
[`v1.32.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.32.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.31.0...v1.32.0)

##### What's Changed

- Update links after moving to PyO3 org by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/97](https://redirect.github.com/PyO3/maturin-action/pull/97)
- Add `working-directory` input option by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/PyO3/maturin-action/pull/102](https://redirect.github.com/PyO3/maturin-action/pull/102)

**Full Changelog**:
https://github.com/PyO3/maturin-action/compare/v1.31.0...v1.32.0

###
[`v1.31.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.31.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.30.2...v1.31.0)

##### What's Changed

- Test Python 3.11 by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/92](https://redirect.github.com/messense/maturin-action/pull/92)
- Always use docker on Linux if `container` is set by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/95](https://redirect.github.com/messense/maturin-action/pull/95)
-   Update GitHub Actions Nodejs runtime to 16

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.30.2...v1.31.0

###
[`v1.30.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.30.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.30.1...v1.30.2)

##### What's Changed

- Switch to ghcr.io manylinux cross docker images by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/90](https://redirect.github.com/messense/maturin-action/pull/90)
- chore: update dependencies by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/91](https://redirect.github.com/messense/maturin-action/pull/91)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.30.1...v1.30.2

###
[`v1.30.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.30.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.30.0...v1.30.1)

##### What's Changed

- Remove now obsolete `autoManylinuxVersion` function by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/84](https://redirect.github.com/messense/maturin-action/pull/84)
- Add support for using manylinux version in `container` option by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/85](https://redirect.github.com/messense/maturin-action/pull/85)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.30.0...v1.30.1

###
[`v1.30.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.30.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.29.3...v1.30.0)

##### What's Changed

- Make `manylinux: auto` defaults to `manylinux2014` by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/83](https://redirect.github.com/messense/maturin-action/pull/83)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.29.3...v1.30.0

###
[`v1.29.3`](https://redirect.github.com/PyO3/maturin-action/compare/v1.29.2...v1.29.3)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.29.2...v1.29.3)

###
[`v1.29.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.29.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.29.1...v1.29.2)

##### What's Changed

-   docker: pass `CMAKE_*` and `TARGET_*` env vars

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.29.1...v1.29.2

###
[`v1.29.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.29.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.29.0...v1.29.1)

##### What's Changed

-   Use `GITHUB_TOKEN` env var if available

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.29.0...v1.29.1

###
[`v1.29.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.29.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.28.4...v1.29.0)

##### What's Changed

- Defaults to manylinux2014 when using `auto` with Rust beta/nightly by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/65](https://redirect.github.com/messense/maturin-action/pull/65)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.28.4...v1.29.0

###
[`v1.28.4`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.28.4)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.28.3...v1.28.4)

##### What's Changed

- Update versions-manifest.json by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[https://github.com/messense/maturin-action/pull/59](https://redirect.github.com/messense/maturin-action/pull/59)
- Update versions-manifest.json by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[https://github.com/messense/maturin-action/pull/60](https://redirect.github.com/messense/maturin-action/pull/60)
- Update versions-manifest.json by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[https://github.com/messense/maturin-action/pull/61](https://redirect.github.com/messense/maturin-action/pull/61)
- Exclude manylinux2010 test on Rust nightly by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/62](https://redirect.github.com/messense/maturin-action/pull/62)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.28.3...v1.28.4

###
[`v1.28.3`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.28.3)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.28.2...v1.28.3)

##### What's Changed

-   Fix file permissions for output directory when building with Docker.

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.28.2...v1.28.3

###
[`v1.28.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.28.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.28.1...v1.28.2)

##### What's Changed

- Update versions-manifest.json by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[https://github.com/messense/maturin-action/pull/52](https://redirect.github.com/messense/maturin-action/pull/52)
- Update versions-manifest.json by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[https://github.com/messense/maturin-action/pull/54](https://redirect.github.com/messense/maturin-action/pull/54)

##### New Contributors

- [@&#8203;github-actions](https://redirect.github.com/github-actions)
made their first contribution in
[https://github.com/messense/maturin-action/pull/52](https://redirect.github.com/messense/maturin-action/pull/52)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.28.1...v1.28.2

###
[`v1.28.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.28.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.28.0...v1.28.1)

##### What's Changed

- Support legacy `rust-toolchain` with toml content by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/51](https://redirect.github.com/messense/maturin-action/pull/51)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.28.0...v1.28.1

###
[`v1.28.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.28.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.27.0...v1.28.0)

##### What's Changed

- Update dependencies by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/45](https://redirect.github.com/messense/maturin-action/pull/45)
- Read maturin version from `pyproject.toml` by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/46](https://redirect.github.com/messense/maturin-action/pull/46)
- Add support for rust-toolchain overrides by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/48](https://redirect.github.com/messense/maturin-action/pull/48)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.27.0...v1.28.0

###
[`v1.27.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.27.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.26.0...v1.27.0)

##### What's Changed

- Accept more env vars in docker build by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/42](https://redirect.github.com/messense/maturin-action/pull/42)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.26.0...v1.27.0

###
[`v1.26.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.26.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.25.0...v1.26.0)

##### What's Changed

- Set default images for musllinux\_1\_1 by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/41](https://redirect.github.com/messense/maturin-action/pull/41)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.25.0...v1.26.0

###
[`v1.25.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.25.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.24.1...v1.25.0)

##### What's Changed

- Bump minimist from 1.2.5 to 1.2.6 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/messense/maturin-action/pull/38](https://redirect.github.com/messense/maturin-action/pull/38)
- Add manylinux\_2\_28 cross compiling Docker images by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/40](https://redirect.github.com/messense/maturin-action/pull/40)

##### New Contributors

- [@&#8203;dependabot](https://redirect.github.com/dependabot) made
their first contribution in
[https://github.com/messense/maturin-action/pull/38](https://redirect.github.com/messense/maturin-action/pull/38)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.24.1...v1.25.0

###
[`v1.24.1`](https://redirect.github.com/PyO3/maturin-action/compare/v1.24.0...v1.24.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.24.0...v1.24.1)

###
[`v1.24.0`](https://redirect.github.com/PyO3/maturin-action/compare/v1.23.2...v1.24.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.23.2...v1.24.0)

###
[`v1.23.2`](https://redirect.github.com/PyO3/maturin-action/compare/v1.23.1...v1.23.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.23.1...v1.23.2)

###
[`v1.23.1`](https://redirect.github.com/PyO3/maturin-action/compare/v1.23.0...v1.23.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.23.0...v1.23.1)

###
[`v1.23.0`](https://redirect.github.com/PyO3/maturin-action/compare/v1.22.1...v1.23.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.22.1...v1.23.0)

###
[`v1.22.1`](https://redirect.github.com/PyO3/maturin-action/compare/v1.22.0...v1.22.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.22.0...v1.22.1)

###
[`v1.22.0`](https://redirect.github.com/PyO3/maturin-action/compare/v1.21.0...v1.22.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.21.0...v1.22.0)

###
[`v1.21.0`](https://redirect.github.com/PyO3/maturin-action/compare/v1.20.0...v1.21.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.20.0...v1.21.0)

###
[`v1.20.0`](https://redirect.github.com/PyO3/maturin-action/compare/v1.19.3...v1.20.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.19.3...v1.20.0)

###
[`v1.19.3`](https://redirect.github.com/PyO3/maturin-action/compare/v1.19.2...v1.19.3)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.19.2...v1.19.3)

###
[`v1.19.2`](https://redirect.github.com/PyO3/maturin-action/compare/v1.19.1...v1.19.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.19.1...v1.19.2)

###
[`v1.19.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.19.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.19.0...v1.19.1)

##### What's Changed

- Better support for macOS arm64 by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/22](https://redirect.github.com/messense/maturin-action/pull/22)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.19.0...v1.19.1

###
[`v1.19.0`](https://redirect.github.com/PyO3/maturin-action/compare/v1.18.1...v1.19.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.18.1...v1.19.0)

###
[`v1.18.1`](https://redirect.github.com/PyO3/maturin-action/compare/v1.18.0...v1.18.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.18.0...v1.18.1)

###
[`v1.18.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.18.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.17.0...v1.18.0)

##### What's Changed

- Do not attempt to pull local images by
[@&#8203;Tpt](https://redirect.github.com/Tpt) in
[https://github.com/messense/maturin-action/pull/19](https://redirect.github.com/messense/maturin-action/pull/19)

##### New Contributors

- [@&#8203;Tpt](https://redirect.github.com/Tpt) made their first
contribution in
[https://github.com/messense/maturin-action/pull/19](https://redirect.github.com/messense/maturin-action/pull/19)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.17.0...v1.18.0

###
[`v1.17.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.17.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.16.4...v1.17.0)

##### What's Changed

- Remove fallback maturin latest version by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/18](https://redirect.github.com/messense/maturin-action/pull/18)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.16.4...v1.17.0

###
[`v1.16.4`](https://redirect.github.com/PyO3/maturin-action/compare/v1.16.3...v1.16.4)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.16.3...v1.16.4)

###
[`v1.16.3`](https://redirect.github.com/PyO3/maturin-action/compare/v1.16.2...v1.16.3)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.16.2...v1.16.3)

###
[`v1.16.2`](https://redirect.github.com/PyO3/maturin-action/compare/v1.16.1...v1.16.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.16.1...v1.16.2)

###
[`v1.16.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.16.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.16.0...v1.16.1)

##### What's Changed

- Only add tool cache Python to PATH if no `pythonLocation` specified by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/17](https://redirect.github.com/messense/maturin-action/pull/17)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.16.0...v1.16.1

###
[`v1.16.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.16.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.15.1...v1.16.0)

##### What's Changed

- Add Python versions from tool cache to PATH on macOS by
[@&#8203;messense](https://redirect.github.com/messense) in
[https://github.com/messense/maturin-action/pull/16](https://redirect.github.com/messense/maturin-action/pull/16)

**Full Changelog**:
https://github.com/messense/maturin-action/compare/v1.15.1...v1.16.0

###
[`v1.15.1`](https://redirect.github.com/PyO3/maturin-action/compare/v1.15.0...v1.15.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.15.0...v1.15.1)

###
[`v1.15.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.15.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.14.2...v1.15.0)

-   Removed universal2 support for pyo3 0.13.x

###
[`v1.14.2`](https://redirect.github.com/PyO3/maturin-action/compare/v1.14.1...v1.14.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.14.1...v1.14.2)

###
[`v1.14.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.14.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.14.0...v1.14.1)

-   Update default maturin version to v0.11.3

###
[`v1.14.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.14.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.13.2...v1.14.0)

- Fixed maturin build error with `--cargo-extra-args` on macOS and
Windows.

###
[`v1.13.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.13.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.13.1...v1.13.2)

-   Update default maturin version to v0.11.2

###
[`v1.13.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.13.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.13.0...v1.13.1)

-   Update default maturin version to v0.11.1

###
[`v1.13.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.13.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.12.1...v1.13.0)

-   Add support for self-hosted arm64 runner
-   Update default maturin version to 0.11.0

###
[`v1.12.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.12.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.12.0...v1.12.1)

Allow passing `_PYTHON_SYSCONFIGDATA_NAME` to docker.

###
[`v1.12.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.12.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.11.1...v1.12.0)

Drop manylinux\_2\_24 ppc64 support.

###
[`v1.11.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.11.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.11.0...v1.11.1)

Strip `manylinux` prefix.

###
[`v1.11.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.11.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.10.4...v1.11.0)

Add more default manylinux\_2\_24 cross compile docker images

###
[`v1.10.4`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.10.4)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.10.3...v1.10.4)

Update default maturin version to `v0.10.6`

###
[`v1.10.3`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.10.3)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.10.2...v1.10.3)

Update default maturin version to `v0.10.5`

###
[`v1.10.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.10.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.10.1...v1.10.2)

Add support for x64 and x86 target aliases

###
[`v1.10.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.10.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.10.0...v1.10.1)

Add ppc64 alias

###
[`v1.10.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.10.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.9.0...v1.10.0)

Add support for `powerpc64-unknown-linux-gnu` target

###
[`v1.9.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.9.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.8.2...v1.9.0)

Use `messense/manylinux2014-cross:ppc64le` for ppc64le manylinux2014
cross compiling

###
[`v1.8.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.8.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.8.1...v1.8.2)

Skip target installaton if it is already installed

###
[`v1.8.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.8.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.8.0...v1.8.1)

Support target aliases for example `x86_64` on Linux alias to
`x86_64-unknown-linux-gnu`

###
[`v1.8.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.8.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.7.1...v1.8.0)

Add default containers for MUSL targets.

###
[`v1.7.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.7.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.7.0...v1.7.1)

Support set `manylinux` to auto to build for lowest compatible manylinux
tag

###
[`v1.7.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.7.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.6.2...v1.7.0)

-   Add aliases for manylinux 2010 & 2014
-   Support using QEMU for some architectures
-   Add default containers for `ppc64le` and `s390x`
- Pass `RUST_BACKTRACE`, `PYO3_CROSS` and `PYO3_CROSS_PYTHON_VERSION`
env vars to docker container.

###
[`v1.6.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.6.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.6.1...v1.6.2)

-   Allow building manylinux wheels on host without Docker
-   Set `SDKROOT` env var for macOS universal2 build

###
[`v1.6.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.6.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.6.0...v1.6.1)

Print maturin version after installation.

###
[`v1.6.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.6.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.5.2...v1.6.0)

Add default containers for platforms other than `x86_64`.

###
[`v1.5.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.5.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.5.1...v1.5.2)

Pass some useful env vars to docker run

###
[`v1.5.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.5.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.5.0...v1.5.1)

Run manylinux off jobs on host instead of in Docker

###
[`v1.5.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.5.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.4.2...v1.5.0)

Added support for specifying Rust toolchain

###
[`v1.4.2`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.4.2)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.4.1...v1.4.2)

-   Setup additional env vars for macOS universal2 build
-   Install `aarch64-apple-darwin` Rust target automatically

###
[`v1.4.1`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.4.1)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.4.0...v1.4.1)

Add fallback maturin version in case fetching latest maturin version
failed.

###
[`v1.4.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.4.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.3.0...v1.4.0)

Support vanilla manylinux docker containers

###
[`v1.3.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.3.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.2.0...v1.3.0)

-   Convert codebase to TypeScript
-   Added `target` input argument

###
[`v1.2.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.2.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1.1.0...v1.2.0)

Add `maturin` to PATH

###
[`v1.1.0`](https://redirect.github.com/PyO3/maturin-action/releases/tag/v1.1.0)

[Compare
Source](https://redirect.github.com/PyO3/maturin-action/compare/v1...v1.1.0)

Added support for manylinux build using `konstin2/maturin` docker
images.

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:24:24 +02:00
renovate[bot]
08f86a5ffc Update actions/setup-python digest to 8d9ed9a (#17067)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/setup-python](https://redirect.github.com/actions/setup-python)
| action | digest | `4237552` -> `8d9ed9a` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:23:26 +02:00
renovate[bot]
4cc627ef77 Update astral-sh/setup-uv digest to 0c5e2b8 (#17068)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [astral-sh/setup-uv](https://redirect.github.com/astral-sh/setup-uv) |
action | digest | `2269511` -> `0c5e2b8` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:22:10 +02:00
renovate[bot]
244618a6f5 Update taiki-e/install-action digest to 6aca1cf (#17069)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[taiki-e/install-action](https://redirect.github.com/taiki-e/install-action)
| action | digest | `914ac1e` -> `6aca1cf` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:21:50 +02:00
renovate[bot]
e068ffe929 Update webfactory/ssh-agent action to v0.9.1 (#17074)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[webfactory/ssh-agent](https://redirect.github.com/webfactory/ssh-agent)
| action | patch | `v0.9.0` -> `v0.9.1` |

---

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

---

### Release Notes

<details>
<summary>webfactory/ssh-agent (webfactory/ssh-agent)</summary>

###
[`v0.9.1`](https://redirect.github.com/webfactory/ssh-agent/blob/HEAD/CHANGELOG.md#v091-2024-03-17)

[Compare
Source](https://redirect.github.com/webfactory/ssh-agent/compare/v0.9.0...v0.9.1)

##### Fixed

- Fix path used to execute ssh-agent in cleanup.js to respect custom
paths set by input
([#&#8203;235](https://redirect.github.com/webfactory/ssh-agent/issues/235))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:20:04 +02:00
renovate[bot]
a5f4522078 Update CodSpeedHQ/action action to v3.5.0 (#17075)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [CodSpeedHQ/action](https://redirect.github.com/CodSpeedHQ/action) |
action | minor | `v3` -> `v3.5.0` |

---

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

---

### Release Notes

<details>
<summary>CodSpeedHQ/action (CodSpeedHQ/action)</summary>

###
[`v3.5.0`](https://redirect.github.com/CodSpeedHQ/action/releases/tag/v3.5.0)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/action/compare/v3.4.0...v3.5.0)

#### What's Changed

##### <!-- 0 -->🚀 Features

- Add mode command arg by
[@&#8203;adriencaccia](https://redirect.github.com/adriencaccia) in
[#&#8203;69](https://redirect.github.com/CodSpeedHQ/runner/pull/69)
- Add a setup command by
[@&#8203;art049](https://redirect.github.com/art049) in
[#&#8203;61](https://redirect.github.com/CodSpeedHQ/runner/pull/61)
- Allow usage on any x86 or arm os with a warning by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in [#&#8203;66](https://redirect.github.com/CodSpeedHQ/runner/pull/66)

##### <!-- 1 -->🐛 Bug Fixes

- Fix valgrind version checks by
[@&#8203;art049](https://redirect.github.com/art049) in
[#&#8203;65](https://redirect.github.com/CodSpeedHQ/runner/pull/65)

**Full Changelog**:
https://github.com/CodSpeedHQ/action/compare/v3.4.0...v3.5.0
**Full Runner Changelog**:
https://github.com/CodSpeedHQ/runner/blob/main/CHANGELOG.md

###
[`v3.4.0`](https://redirect.github.com/CodSpeedHQ/action/releases/tag/v3.4.0)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/action/compare/v3.3.1...v3.4.0)

#### What's Changed

##### <!-- 0 -->🚀 Features

- feat: add `GH_MATRIX` and `GH_STRATEGY` env variables by
[@&#8203;fargito](https://redirect.github.com/fargito) in
[https://github.com/CodSpeedHQ/action/pull/123](https://redirect.github.com/CodSpeedHQ/action/pull/123)
- Add run_part to upload metadata by
[@&#8203;fargito](https://redirect.github.com/fargito) in
[#&#8203;57](https://redirect.github.com/CodSpeedHQ/runner/pull/57)

##### <!-- 1 -->🐛 Bug Fixes

- Fix stderr error display by
[@&#8203;art049](https://redirect.github.com/art049) in
[#&#8203;63](https://redirect.github.com/CodSpeedHQ/runner/pull/63)

**Full Changelog**:
https://github.com/CodSpeedHQ/action/compare/v3.3.1...v3.4.0
**Full Runner Changelog**:
https://github.com/CodSpeedHQ/runner/blob/main/CHANGELOG.md

###
[`v3.3.1`](https://redirect.github.com/CodSpeedHQ/action/releases/tag/v3.3.1)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/action/compare/v3.3.0...v3.3.1)

#### What's Changed

##### <!-- 0 -->🚀 Features

- Bail when performance report s3 upload does not work by
[@&#8203;adriencaccia](https://redirect.github.com/adriencaccia)

##### <!-- 1 -->🐛 Bug Fixes

- Catch server error as well as client in upload error handling by
[@&#8203;adriencaccia](https://redirect.github.com/adriencaccia) in
[#&#8203;64](https://redirect.github.com/CodSpeedHQ/runner/pull/64)

**Full Runner Changelog**:
https://github.com/CodSpeedHQ/runner/blob/main/CHANGELOG.md

###
[`v3.3.0`](https://redirect.github.com/CodSpeedHQ/action/releases/tag/v3.3.0)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/action/compare/v3.2.0...v3.3.0)

#### What's Changed

##### <!-- 0 -->🚀 Features

- Allow downgrades while installing valgrind-codspeed by
[@&#8203;art049](https://redirect.github.com/art049)
- Update sysinfo crate by
[@&#8203;adriencaccia](https://redirect.github.com/adriencaccia) in
[#&#8203;62](https://redirect.github.com/CodSpeedHQ/runner/pull/62)

##### <!-- 1 -->🐛 Bug Fixes

- Unify environments between the two modes by
[@&#8203;art049](https://redirect.github.com/art049) in
[#&#8203;59](https://redirect.github.com/CodSpeedHQ/runner/pull/59)

##### <!-- 7 -->⚙️ Internals

- Bump valgrind-codspeed version to 3.24.0-0codspeed1 and change
supported systems by
[@&#8203;art049](https://redirect.github.com/art049)

**Full Runner Changelog**:
https://github.com/CodSpeedHQ/runner/blob/main/CHANGELOG.md

###
[`v3.2.0`](https://redirect.github.com/CodSpeedHQ/action/releases/tag/v3.2.0)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/action/compare/v3.1.0...v3.2.0)

#### Release Notes

##### <!-- 0 -->🚀 Features

- Implement gitlab ci provider by
[@&#8203;fargito](https://redirect.github.com/fargito) in
[#&#8203;47](https://redirect.github.com/CodSpeedHQ/runner/pull/47)
- Add repository provider to upload metadata by
[@&#8203;fargito](https://redirect.github.com/fargito)
- Use system distribution id instead of name by
[@&#8203;fargito](https://redirect.github.com/fargito)

##### <!-- 2 -->🏗️ Refactor

- Move sender out of ghdata by
[@&#8203;fargito](https://redirect.github.com/fargito)
- Rename provider to ci provider by
[@&#8203;fargito](https://redirect.github.com/fargito)
- Use string for runId by
[@&#8203;fargito](https://redirect.github.com/fargito)
- Improve string interpolation by
[@&#8203;fargito](https://redirect.github.com/fargito)

##### <!-- 7 -->⚙️ Internals

- Configure git-cliff for changelog generation by
[@&#8203;art049](https://redirect.github.com/art049)
- Add rust settings by
[@&#8203;fargito](https://redirect.github.com/fargito)

**Associated runner release**:
https://github.com/CodSpeedHQ/runner/releases/tag/v3.2.0
**Full Changelog**:
https://github.com/CodSpeedHQ/action/compare/v3.1.0...v3.2.0

###
[`v3.1.0`](https://redirect.github.com/CodSpeedHQ/action/releases/tag/v3.1.0)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/action/compare/v3.0.1...v3.1.0)

#### What's Changed

This new release includes compatibility with our new `wall time`
instruments, which allow measurement of real execution timings. This
will be very useful for macro benchmarks running on properly isolated
machines. You can now use our **CodSpeed Macro** runners without
changing anything in your existing CI workflows.

Find more info on our Walltime instrument
[here](https://docs.codspeed.io/instruments/walltime/).


![image](https://redirect.github.com/user-attachments/assets/650d1123-5cd6-4309-84e0-d5dd6ced64f3)

**Full Changelog**:
https://github.com/CodSpeedHQ/action/compare/v3.0.1...v3.1.0

###
[`v3.0.1`](https://redirect.github.com/CodSpeedHQ/action/releases/tag/v3.0.1)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/action/compare/v3...v3.0.1)

#### What's Changed

- chore: bump runner version to 3.0.1 by
[@&#8203;github-actions](https://redirect.github.com/github-actions) in
[https://github.com/CodSpeedHQ/action/pull/115](https://redirect.github.com/CodSpeedHQ/action/pull/115)
-   chore: support ubuntu 24.04

**Full Changelog**:
https://github.com/CodSpeedHQ/action/compare/v3.0.0...v3.0.1

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 09:19:16 +02:00
cake-monotone
c6efa93cf7 [red-knot] Handle special case returning NotImplemented (#17034)
## Summary

Closes #16661

This PR includes two changes:

- `NotImplementedType` is now a member of `KnownClass`
- We skip `is_assignable_to` checks for `NotImplemented` when checking
return types

### Limitation

```py
def f(cond: bool) -> int:
    return 1 if cond else NotImplemented
```

The implementation covers cases where `NotImplemented` appears inside a
`Union`.
However, for more complex types (ex. `Intersection`) it will not worked.
In my opinion, supporting such complexity is unnecessary at this point.

## Test Plan

Two `mdtest` files were updated:

- `mdtest/function/return_type.md`
- `mdtest/type_properties/is_singleton.md`

To test `KnownClass`, run:
```bash
cargo test -p red_knot_python_semantic -- types::class::
```
2025-03-30 11:06:12 -07:00
Brent Westbrook
ab1011ce70 [syntax-errors] Single starred assignment target (#17024)
Summary
--

Detects starred assignment targets outside of tuples and lists like `*a
= (1,)`.

This PR only considers assignment statements. I also checked annotated
assigment statements, but these give a separate error that we already
catch, so I think they're okay not to consider:

```pycon
>>> *a: list[int] = []
  File "<python-input-72>", line 1
    *a: list[int] = []
      ^
SyntaxError: invalid syntax
```

Fixes #13759

Test Plan
--

New inline tests, plus a new `SemanticSyntaxError` for an existing
parser test. I also removed a now-invalid case from an otherwise-valid
test fixture.

The new semantic error leads to two errors for the case below:

```python
*foo() = 42
```

but this matches [pyright] too.

[pyright]: https://pyright-play.net/?code=FQMw9mAUCUAEC8sAsAmAUEA
2025-03-29 12:35:47 -04:00
Brent Westbrook
a0819f0c51 [syntax-errors] Store to or delete __debug__ (#16984)
Summary
--

Detect setting or deleting `__debug__`. Assigning to `__debug__` was a
`SyntaxError` on the earliest version I tested (3.8). Deleting
`__debug__` was made a `SyntaxError` in [BPO 45000], which said it was
resolved in Python 3.10. However, `del __debug__` was also a runtime
error (`NameError`) when I tested in Python 3.9.6, so I thought it was
worth including 3.9 in this check.

I don't think it was ever a *good* idea to try `del __debug__`, so I
think there's also an argument for not making this version-dependent at
all. That would only simplify the implementation very slightly, though.

[BPO 45000]: https://github.com/python/cpython/issues/89163

Test Plan
--

New inline tests. This also required adding a `PythonVersion` field to
the `TestContext` that could be taken from the inline `ParseOptions` and
making the version field on the options accessible.
2025-03-29 12:07:20 -04:00
Alex Waygood
8396d7cd63 Use Python 3.13 for most CI jobs (#17053) 2025-03-28 20:35:44 -04:00
Alex Waygood
9ae2900dc3 Run pre-commit via uv in CI (#17052)
Installing pre-commit via pip can take up to 6s sometimes in CI (e.g.
https://github.com/astral-sh/ruff/actions/runs/14137246278/job/39611795976).
Installing pre-commit via uv should be faster. It also simplifies the
workflow and improves the amount we're dogfooding our own tools
2025-03-28 21:16:14 +00:00
Micha Reiser
37a40e30f6 [playground] Allow selecting the diagnostic message (#17051)
## Summary

Allow selecting the diagnostic message so that the message can be copied
(e.g. into an issue)

## Test Plan

<img width="1679" alt="Screenshot 2025-03-28 at 16 52 45"
src="https://github.com/user-attachments/assets/06674d87-6c88-45d4-b46c-0bcb3e151996"
/>
2025-03-28 20:58:05 +00:00
Alex Waygood
98438a77f2 Don't install Rust before running pre-commit in CI (#17050)
Following
29573daef5,
it doesn't look to me like any of the pre-commit hooks run in CI here
are Rust-based:

- `cargo fmt` is Rust-based but it's explicitly skipped as part of this
job and run as a separate CI job:
93052331b0/.pre-commit-config.yaml (L124-L125)
- The `typos` hook is Rust-based, but according to
https://github.com/crate-ci/typos/blob/master/docs/pre-commit.md
pre-commit should install a built binary rather than building the binary
from source

As such, I think this step in the workflow is just taking up 15s of CI
time and not actually speeding up pre-commit at all
2025-03-28 16:57:46 -04:00
Alex Waygood
93052331b0 [red-knot] Allow CallableTypeFromFunction to display the signatures of callable types that are not function literals (#17047)
I found this helpful for understanding some of the stuff that was going
on in https://github.com/astral-sh/ruff/pull/17005.
2025-03-28 20:23:04 +00:00
Micha Reiser
e07741e553 Add as_group methods to AnyNodeRef (#17048)
## Summary

This PR adds `as_<group>` methods to `AnyNodeRef` to e.g. convert an
`AnyNodeRef` to an `ExprRef`.

I need this for go to definition where the fallback is to test if
`AnyNodeRef` is an expression and then call `inferred_type` (listing
this mapping at every call site where we need to convert `AnyNodeRef` to
an `ExprRef` is a bit painful ;))

Split out from https://github.com/astral-sh/ruff/pull/16901

## Test Plan

`cargo test`
2025-03-28 19:42:45 +00:00
Micha Reiser
050f332771 Rename visit_preorder to visit_source_order (#17046)
## Summary

We renamed the `PreorderVisitor` to `SourceOrderVisitor` a long time ago
but it seems that we missed to rename the `visit_preorder` functions to
`visit_source_order`.
This PR renames `visit_preorder` to `visit_source_order`

## Test Plan

`cargo test`
2025-03-28 19:40:26 +00:00
Micha Reiser
6b02c39321 [red-knot] Incorporate recent ruff server improvements into red knot's LSP (#17044) 2025-03-28 18:39:18 +00:00
Eric Mark Martin
78b0b5a3ab [red-knot] Factor out shared unpacking logic (#16595)
## Summary

This PR refactors the common logic for unpacking in assignment, for loops, and with items.

## Test Plan

Make sure existing tests pass.

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-03-28 23:52:51 +05:30
Matthew Mckee
0e48940ea4 [red-knot] Discover local venv folder in cli (#16917)
<!--
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 #16744 

Code from 

bbf4f830b5/crates/uv-python/src/virtualenv.rs (L124-L144)

## Test Plan

Manual testing

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-28 17:59:49 +00:00
Shunsuke Shibayama
aca6254e82 [red-knot] fix eager nested scopes handling (#16916)
## Summary

From #16861, and the continuation of #16915.

This PR fixes the incorrect behavior of
`TypeInferenceBuilder::infer_name_load` in eager nested scopes.

And this PR closes #16341.

## Test Plan

New test cases are added in `annotations/deferred.md`.
2025-03-28 11:11:56 -04:00
Eric Mark Martin
64171744dc [red-knot] support narrowing on or patterns in matches (#17030)
## Summary

Part of #13694

Narrow in or-patterns by taking the type union of the type constraints
in each disjunct pattern.

## Test Plan

Add new tests to narrow/match.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-28 14:27:09 +00:00
David Peter
2e56cd3737 [red-knot] mypy_primer: switch to depot runners (#17037)
## Summary

Move the mypy_primer build to the depot runners to speed them up.

## Test Plan

Previous run of mypy_primer: 3m 49s
Run on this branch: 1m 38s
2025-03-28 14:34:11 +01:00
David Peter
e37a1b02f6 Revert "[red-knot] mypy_primer: switch to depot runners"
This reverts commit 9aa8dc4590.
2025-03-28 09:22:27 -04:00
David Peter
9aa8dc4590 [red-knot] mypy_primer: switch to depot runners 2025-03-28 09:21:22 -04:00
David Peter
df418d94b3 [red-knot] mypy_primer: use debug builds of red_knot (#17036)
## Summary

Use a debug build instead of a release build in order to speed up
mypy_primer runs.

## Test Plan

Previous mypy_primer run: 5m 45s
mypy_primer run on this branch: 3m 49s
2025-03-28 14:17:47 +01:00
David Peter
b90741fb92 [red-knot] Install mypy_primer from specific Git tag (#17035)
## Summary

Instead of installing from a branch, install mypy_primer from a specific
Git tag in order to make changes to the pipeline explicit.
2025-03-28 14:05:17 +01:00
Eric Mark Martin
3acf4e716d [red-knot] support narrowing on constants in matches (#16974)
## Summary

Part of #13694

The implementation here was suspiciously straightforward so please lmk
if I missed something

Also some drive-by changes to DRY things up a bit

## Test Plan

Add new tests to narrow/match.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-28 02:36:51 +00:00
Alex Waygood
992a1af4c2 [red-knot] Reduce false positives on super() and enum-class attribute accesses (#17004)
## Summary

This PR adds some branches so that we infer `Todo` types for attribute
access on instances of `super()` and subtypes of `type[Enum]`. It reduces
false positives in the short term until we implement full support for
these features.

## Test Plan

New mdtests added + mypy_primer report
2025-03-27 17:30:56 -04:00
Alex Waygood
c963b185eb mypy_primer: add typeshed-stats (#17022)
This is a well-typed codebase on which we only emit 23 diagnostics right
now, but which is highlighting some interesting issues. It uses some
modern syntactic features such as `match` statements that aren't used
much in other open-source projects in mypy_primer
2025-03-27 16:21:31 -04:00
Micha Reiser
4067a7e50c [red-knot] Don't check non-python files (#17021)
## Summary

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

## Test Plan

I renamed a python file to `knot.toml` and verified that there are no
diagnostics. Renaming back the file to `*.py` brings back the
diagnostics
2025-03-27 19:45:04 +00:00
Micha Reiser
f9bc80ad55 [red-knot] Fix syntax highlighting for pyi files (#17015)
Monaco supports inferring the language based on the file's extension but
it doesn't seem to support `pyi`. I tried to patch up the python
language definition by adding `.pyi` to the language's `extension` array
but that didn't work. That's why I decided to patch up the language in
React.
2025-03-27 19:27:22 +00:00
David Peter
142fe0d29b [playground] Fix reveal_type (#17013)
## Summary

Capture both `stdout` and `stderr` in a single stream. This fixes
`reveal_type`, which prints to `stderr` by default.

## Test Plan

Tested with a simple `reveal_type(1)` example and got the output:
```
Runtime value is '1'
Runtime type is 'int'
```
2025-03-27 17:21:26 +01:00
InSync
6ef522159d Check pyproject.toml correctly when it is passed via stdin (#16971)
## Summary

Resolves #16950 and [a 1.5-year-old TODO
comment](8d16a5c8c9/crates/ruff/src/diagnostics.rs (L380)).

After this change, a `pyproject.toml` will be linted the same as any
Python files would when passed via stdin.

## Test Plan

Integration tests.
2025-03-27 16:01:45 +00:00
Matthew Mckee
b9a7328789 [red-knot] Make every type a subtype of object (#16960)
## Summary

Mainly for partially fixing #16953

## Test Plan

Update is_subtype tests. And should maybe do these checks for many other
types (is subtype of object but object is not subtype)

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-03-27 14:24:18 +00:00
Micha Reiser
640d821108 [red-knot] reveal-type should return the revaled type (#17007)
## Summary

Return the revealed-type from the monkey-patched `revale_type`
implementation to
preserve the identity behavior.

This PR also isolates different script runs by assigning a different
`globals` dict for each script-run. See
https://github.com/pyodide/pyodide/issues/703
2025-03-27 03:04:57 +00:00
Micha Reiser
43ca85a351 [red-knot] Add run panel (#17002)
## Summary

This PR adds a new secondary panel to the red knot playground that
allows running the python code (current file) with
[pyodide](https://pyodide.org/en/stable/index.html) (currently Python
3.12 only).



## Test Plan


https://github.com/user-attachments/assets/7bda8ef7-19fb-4c2f-8e62-8e49a1416be1
2025-03-26 21:32:07 +00:00
Micha Reiser
338fed98a4 [red-knot] Use React suspense to show loading spinner (#16986)
## Summary

Use React's suspense feature to show a loading spinner while the WASM
module is initializing.
2025-03-26 17:56:14 +00:00
Brent Westbrook
d70a3e6753 [syntax-errors] Multiple assignments in case pattern (#16957)
Summary
--

This PR detects multiple assignments to the same name in `case` patterns
by recursively visiting each pattern.

Test Plan
--

New inline tests.
2025-03-26 13:02:42 -04:00
Brent Westbrook
5697d21fca [syntax-errors] Irrefutable case pattern before final case (#16905)
Summary
--

Detects irrefutable `match` cases before the final case using a modified
version
of the existing `Pattern::is_irrefutable` method from the AST crate. The
modified method helps to retrieve a more precise diagnostic range to
match what
Python 3.13 shows in the REPL.

Test Plan
--

New inline tests, as well as some updates to existing tests that had
irrefutable
patterns before the last block.
2025-03-26 12:27:16 -04:00
Wei Lee
58350ec93b [airflow] refactor: remove unnecessary Some in check_method, check_class_attribute (AIR302) (#16975)
## Summary

remove unnecessary `Some`

## Test Plan

It's a refactoring change. Existing test cases won't be affected
2025-03-26 12:17:34 -04:00
Matthew Mckee
aae4d0f3eb [red-knot] A FunctionType can be a subtype of Callable (but never the other way around) (#16970)
## Summary

Partially fixes #16953

## Test Plan

Update is_subtype_of.md

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-25 22:04:34 +00:00
renovate[bot]
807fce8069 Update dependency vite to v6.2.3 (#16972)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [vite](https://vite.dev)
([source](https://redirect.github.com/vitejs/vite/tree/HEAD/packages/vite))
| [`6.2.2` ->
`6.2.3`](https://renovatebot.com/diffs/npm/vite/6.2.2/6.2.3) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vite/6.2.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite/6.2.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite/6.2.2/6.2.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/6.2.2/6.2.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

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

### GitHub Vulnerability Alerts

####
[CVE-2025-30208](https://redirect.github.com/vitejs/vite/security/advisories/GHSA-x574-m823-4x7w)

### Summary
The contents of arbitrary files can be returned to the browser.

### Impact
Only apps explicitly exposing the Vite dev server to the network (using
`--host` or [`server.host` config
option](https://vitejs.dev/config/server-options.html#server-host)) are
affected.

### Details
`@fs` denies access to files outside of Vite serving allow list. Adding
`?raw??` or `?import&raw??` to the URL bypasses this limitation and
returns the file content if it exists. This bypass exists because
trailing separators such as `?` are removed in several places, but are
not accounted for in query string regexes.

### PoC
```bash
$ npm create vite@latest
$ cd vite-project/
$ npm install
$ npm run dev

$ echo "top secret content" > /tmp/secret.txt

# expected behaviour
$ curl "http://localhost:5173/@&#8203;fs/tmp/secret.txt"

    <body>
      <h1>403 Restricted</h1>
      <p>The request url &quot;/tmp/secret.txt&quot; is outside of Vite serving allow list.

# security bypassed
$ curl "http://localhost:5173/@&#8203;fs/tmp/secret.txt?import&raw??"
export default "top secret content\n"
//# sourceMappingURL=data:application/json;base64,eyJ2...
```

---

### Release Notes

<details>
<summary>vitejs/vite (vite)</summary>

###
[`v6.2.3`](https://redirect.github.com/vitejs/vite/releases/tag/v6.2.3)

[Compare
Source](https://redirect.github.com/vitejs/vite/compare/v6.2.2...v6.2.3)

Please refer to
[CHANGELOG.md](https://redirect.github.com/vitejs/vite/blob/v6.2.3/packages/vite/CHANGELOG.md)
for details.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCIsInNlY3VyaXR5Il19-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 20:17:40 +00:00
Micha Reiser
8d16a5c8c9 [red-knot] Use web-time instead of FileTime::now (#16967)
## Summary

`std::time::now` isn't available on `wasm32-unknown-unknown` but it is
used by `FileTime::now`.

This PR replaces the usages of `FileTime::now` with a target specific
helper function that we already had in the memory file system.
Fixes https://github.com/astral-sh/ruff/issues/16966

## Test Plan

Tested that the playground no longer crash when adding an extra-path
2025-03-25 13:03:30 +00:00
Alex Waygood
4975c2f027 [red-knot] Fix panic on cyclic * imports (#16958)
## Summary

Further work towards https://github.com/astral-sh/ruff/issues/14169.

We currently panic on encountering cyclic `*` imports. This is easily
fixed using fixpoint iteration.

## Test Plan

Added a test that panics on `main`, but passes with this PR
2025-03-24 18:23:02 +00:00
Dhruv Manilawala
dd5b02aaa2 [red-knot] Fix gradual equivalence for callable types (#16887)
## Summary

As mentioned in
https://github.com/astral-sh/ruff/pull/16698#discussion_r2004920075,
part of #15382, this PR updates the `is_gradual_equivalent_to`
implementation between callable types to be similar to
`is_equivalent_to` and checks other attributes of parameters like name,
optionality, and parameter kind.

## Test Plan

Expand the existing test cases to consider other properties but not all
similar to how the tests are structured for subtyping and assignability.
2025-03-24 23:46:06 +05:30
Aleksei Latyshev
68ea2b8b5b [red-knot] simplify "removing" in UnionBuilder::add (#16947)
## Summary

Simplify "removing" in UnionBuilder::add
It's now O(m) instead of O(n + m) and easier to read.

## Test Plan

cargo test (incl. mdtest)
2025-03-24 14:04:03 -04:00
Alex Waygood
e87fee4b3b [red-knot] Add initial support for * imports (#16923)
## Summary

This PR adds initial support for `*` imports to red-knot. The approach
is to implement a standalone query, called from semantic indexing, that
visits the module referenced by the `*` import and collects all
global-scope public names that will be imported by the `*` import. The
`SemanticIndexBuilder` then adds separate definitions for each of these
names, all keyed to the same `ast::Alias` node that represents the `*`
import.

There are many pieces of `*`-import semantics that are still yet to be
done, even with this PR:
- This PR does not attempt to implement any of the semantics to do with
`__all__`. (If a module defines `__all__`, then only the symbols
included in `__all__` are imported, _not_ all public global-scope
symbols.
- With the logic implemented in this PR as it currently stands, we
sometimes incorrectly consider a symbol bound even though it is defined
in a branch that is statically known to be dead code, e.g. (assuming the
target Python version is set to 3.11):

  ```py
  # a.py

  import sys

  if sys.version_info < (3, 10):
      class Foo: ...

  ```

  ```py
  # b.py

  from a import *

  print(Foo)  # this is unbound at runtime on 3.11,
# but we currently consider it bound with the logic in this PR
  ```

Implementing these features is important, but is for now deferred to
followup PRs.

Many thanks to @ntBre, who contributed to this PR in a pairing session
on Friday!

## Test Plan

Assertions in existing mdtests are adjusted, and several new ones are
added.
2025-03-24 17:15:58 +00:00
Micha Reiser
cba197e3c5 [red-knot] Default playground to Python 3.13 for real (#16956)
## Summary

Default to 3.13 for good. 

I incorrectly used `workspace.updateOptions` instead of `updateOptions`
where the latter has a fallback.

## Test Plan

```py
import os

import sys

reveal_type(sys.version_info.minor)
```

reveals 13 on initial page load
2025-03-24 16:40:49 +00:00
Alex Waygood
66d0cf2a72 [red-knot] Add more tests for * imports (#16955)
## Summary

This PR separates out the entirely new tests from
https://github.com/astral-sh/ruff/pull/16923 into a standalone PR. I'll
rebase https://github.com/astral-sh/ruff/pull/16923 on top of this
branch.

The reasons for separating it out are:
- It should make it clearer to see in
<https://github.com/astral-sh/ruff/pull/16923> exactly how the
functionality is changing (we can see the assertions in the tests
_change_, which isn't so obvious if the tests are entirely new)
- The diff on <https://github.com/astral-sh/ruff/pull/16923> is getting
pretty big; this should reduce the diff on that PR somewhat
- These tests seem useful in and of themselves, so even if we need to do
a wholesale revert of <https://github.com/astral-sh/ruff/pull/16923> for
whatever reason, it'll be nice to keep the tests

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-03-24 16:39:16 +00:00
Micha Reiser
85b7f808e1 [red-knot] Default playground to Python 3.13 (#16952)
## Summary

Default playground to Python 3.13 if there's no setting present. Fix
errors when a setting was added / removed.
2025-03-24 15:54:54 +00:00
renovate[bot]
3a97bdf689 Update Rust crate getrandom to v0.3.2 (#16939)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [getrandom](https://redirect.github.com/rust-random/getrandom) |
workspace.dependencies | patch | `0.3.1` -> `0.3.2` |

---

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

---

### Release Notes

<details>
<summary>rust-random/getrandom (getrandom)</summary>

###
[`v0.3.2`](https://redirect.github.com/rust-random/getrandom/blob/HEAD/CHANGELOG.md#032---2025-03-17)

[Compare
Source](https://redirect.github.com/rust-random/getrandom/compare/v0.3.1...v0.3.2)

##### Added

-   `efi_rng` opt-in backend [#&#8203;570]
-   `linux_raw` opt-in backend [#&#8203;572]
-   `.cargo/config.toml` example in the crate-level docs [#&#8203;591]
- `getrandom_test_linux_without_fallback` configuration flag to test
that file fallback
is not triggered in the `linux_android_with_fallback` backend
[#&#8203;605]
-   Built-in support for `*-linux-none` targets [#&#8203;618]
-   Cygwin support [#&#8203;626]

##### Changed

-   Update `wasi` dependency to v0.14 [#&#8203;594]
-   Add `#[inline]` attribute to the inner functions [#&#8203;596]
- Update WASI and Emscripten links in the crate-level docs [#&#8203;597]
- Do not use `dlsym` on MUSL targets in the
`linux_android_with_fallback` backend [#&#8203;602]
- Remove `linux_android.rs` and use `getrandom.rs` instead [#&#8203;603]
- Always use `RtlGenRandom` on Windows targets when compiling with
pre-1.78 Rust [#&#8203;610]
-   Internal representation of the `Error` type [#&#8203;614]
- Remove `windows-targets` dependency and use [`raw-dylib`][raw-dylib]
directly [#&#8203;627]

##### Removed

- `Error::INTERNAL_START` and `Error::CUSTOM_START` associated constants
[#&#8203;614]

[#&#8203;570]:
https://redirect.github.com/rust-random/getrandom/pull/570

[#&#8203;572]:
https://redirect.github.com/rust-random/getrandom/pull/572

[#&#8203;591]:
https://redirect.github.com/rust-random/getrandom/pull/591

[#&#8203;594]:
https://redirect.github.com/rust-random/getrandom/pull/594

[#&#8203;596]:
https://redirect.github.com/rust-random/getrandom/pull/596

[#&#8203;597]:
https://redirect.github.com/rust-random/getrandom/pull/597

[#&#8203;602]:
https://redirect.github.com/rust-random/getrandom/pull/602

[#&#8203;603]:
https://redirect.github.com/rust-random/getrandom/pull/603

[#&#8203;605]:
https://redirect.github.com/rust-random/getrandom/pull/605

[#&#8203;610]:
https://redirect.github.com/rust-random/getrandom/pull/610

[#&#8203;614]:
https://redirect.github.com/rust-random/getrandom/pull/614

[#&#8203;618]:
https://redirect.github.com/rust-random/getrandom/pull/618

[#&#8203;626]:
https://redirect.github.com/rust-random/getrandom/pull/626

[#&#8203;627]:
https://redirect.github.com/rust-random/getrandom/pull/627

[`raw-dylib`]:
https://doc.rust-lang.org/reference/items/external-blocks.html?highlight=link#dylib-versus-raw-dylib

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 15:54:43 +00:00
renovate[bot]
1bee3994aa Update PyO3/maturin-action digest to 22fe573 (#16932)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [PyO3/maturin-action](https://redirect.github.com/PyO3/maturin-action)
| action | digest | `36db840` -> `22fe573` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 15:53:59 +00:00
Alex Waygood
888a910925 [red-knot] Demote the negation_reverses_subtype_order test back to flaky (#16951)
Fixes #16913. See my analysis in the issue for the rationale
2025-03-24 11:37:03 -04:00
Wei Lee
581b7005dc [airflow] refactor: combine similar case condition (AIR302) (#16944)
<!--
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? -->

combine similar case condition in AIR302 

## Test Plan

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

nothing should be changed. existing test case should already cover it
2025-03-24 15:36:33 +00:00
renovate[bot]
b442ba440f Update astral-sh/setup-uv digest to 2269511 (#16937)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [astral-sh/setup-uv](https://redirect.github.com/astral-sh/setup-uv) |
action | digest | `f94ec6b` -> `2269511` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 15:32:27 +00:00
renovate[bot]
5aba72cdbd Update taiki-e/install-action digest to 914ac1e (#16938)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[taiki-e/install-action](https://redirect.github.com/taiki-e/install-action)
| action | digest | `2c41309` -> `914ac1e` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 15:31:24 +00:00
Brent Westbrook
2711e08eb8 [syntax-errors] Fix false positive for parenthesized tuple index (#16948)
Summary
--

Fixes #16943 by checking if the tuple is not parenthesized before
emitting an error.

Test Plan
--

New inline test based on the initial report
2025-03-24 10:34:38 -04:00
Micha Reiser
f5cdf23545 [red-knot] Add settings support to playground (#16929)
## Summary

This PR extends the Red Knot playground by adding configuration support
by adding a `knot.json` file.

<img width="1679" alt="Screenshot 2025-03-23 at 21 12 16"
src="https://github.com/user-attachments/assets/81ff1588-a07a-4847-97d8-61250aa2feda"
/>
2025-03-24 01:38:48 +00:00
renovate[bot]
d98222cd14 Update actions/cache digest to 5a3ec84 (#16934)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/cache](https://redirect.github.com/actions/cache) | action |
digest | `d4323d4` -> `5a3ec84` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 01:38:32 +00:00
renovate[bot]
f7b9089cb8 Update actions/upload-artifact digest to ea165f8 (#16936)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/upload-artifact](https://redirect.github.com/actions/upload-artifact)
| action | digest | `4cec3d8` -> `ea165f8` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 01:27:05 +00:00
renovate[bot]
dfebc1cfe4 Update Rust crate tempfile to v3.19.1 (#16941)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [tempfile](https://stebalien.com/projects/tempfile-rs/)
([source](https://redirect.github.com/Stebalien/tempfile)) |
workspace.dependencies | patch | `3.19.0` -> `3.19.1` |

---

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

---

### Release Notes

<details>
<summary>Stebalien/tempfile (tempfile)</summary>

###
[`v3.19.1`](https://redirect.github.com/Stebalien/tempfile/blob/HEAD/CHANGELOG.md#3191)

[Compare
Source](https://redirect.github.com/Stebalien/tempfile/compare/v3.19.0...v3.19.1)

- Don't unlink temporary files immediately on Windows (fixes
[#&#8203;339](https://redirect.github.com/Stebalien/tempfile/issues/339)).
Unfortunately, this seemed to corrupt the file object (possibly a
Windows kernel bug) in rare cases and isn't strictly speaking necessary.

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 01:26:39 +00:00
renovate[bot]
7e1484a9b1 Update Rust crate mimalloc to v0.1.44 (#16940)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [mimalloc](https://redirect.github.com/purpleprotocol/mimalloc_rust) |
workspace.dependencies | patch | `0.1.43` -> `0.1.44` |

---

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

---

### Release Notes

<details>
<summary>purpleprotocol/mimalloc_rust (mimalloc)</summary>

###
[`v0.1.44`](https://redirect.github.com/purpleprotocol/mimalloc_rust/releases/tag/v0.1.44):
Version 0.1.44

[Compare
Source](https://redirect.github.com/purpleprotocol/mimalloc_rust/compare/v0.1.43...v0.1.44)

##### Changes

-   Mimalloc v2.2.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.

🔕 **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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 01:26:02 +00:00
renovate[bot]
187cac56bd Update actions/download-artifact digest to 95815c3 (#16935)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/download-artifact](https://redirect.github.com/actions/download-artifact)
| action | digest | `cc20338` -> `95815c3` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 01:24:41 +00:00
renovate[bot]
890f79c4ab Update Swatinem/rust-cache digest to 9d47c6a (#16933)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [Swatinem/rust-cache](https://redirect.github.com/Swatinem/rust-cache)
| action | digest | `f0deed1` -> `9d47c6a` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 01:21:42 +00:00
John Stilley
3899f7156f Fixing more spelling errors (#16926)
## Summary

Here I fix the last English spelling errors I could find in the repo.

Again, I am trying not to touch variable/function names, or anything
that might be misspelled in the API. The goal is to make this PR safe
and easy to merge.

## Test Plan

I have run all the unit tests. Though, again, all of the changes I make
here are to docs and docstrings. I make no code changes, which I believe
should greatly mitigate the testing concerns.
2025-03-23 10:55:14 -07:00
InSync
902d86e79e [red-knot] Do not emit invalid-return-type for abstract functions (#16900)
## Summary

Resolves #16895.

`abstractmethod` is now a `KnownFunction`. When a function is decorated
by `abstractmethod` or when the parent class inherits directly from
`Protocol`, `invalid-return-type` won't be emitted for that function.

## Test Plan

Markdown tests.

---------

Co-authored-by: Carl Meyer <carl@oddbird.net>
2025-03-23 17:51:10 +00:00
Daniel Wilton
9fe89ddfba [refurb] Document why UserDict, UserList, UserString are preferred over dict, list, str (FURB189) (#16927)
## Summary

This PR addresses docs issue
https://github.com/astral-sh/ruff/issues/14328.
2025-03-23 13:24:39 -04:00
Matthew Mckee
08a0995108 [red-knot] Disambiguate display for intersection types (#16914)
## Summary

Fixes #16912 

Create a new type `DisplayMaybeParenthesizedType` that is now used in
Union and Intersection display

## Test Plan

Update callable annotations
2025-03-23 07:18:30 -07:00
InSync
2d892bc9f7 Fix typos (#16908)
## Summary

The noun is spelled "descend<strong><em>a</em></strong>nt" and the
adjective "descend<strong><em>e</em></strong>nt".

## Test Plan

[From the English
Wiktionary](https://en.wiktionary.org/wiki/descendent#Usage_notes):

> The adjective, "descending from a biological ancestor", may be spelt
either with an <i>[a](https://en.wiktionary.org/wiki/-ant)</i> or with
an <i>[e](https://en.wiktionary.org/wiki/-ent)</i> in the final syllable
(see [descendant](https://en.wiktionary.org/wiki/descendant)). However,
the noun <i>descendant</i>, "one who is the progeny of someone", may be
spelt only with an <i>[a](https://en.wiktionary.org/wiki/-ant)</i>.
Compare also
<i>[dependent](https://en.wiktionary.org/wiki/dependent#English)</i> and
<i>[dependant](https://en.wiktionary.org/wiki/dependant#English)</i>.
2025-03-23 07:15:56 -07:00
Shunsuke Shibayama
ee51c2a389 [red-knot] fix ordering of ClassDef semantic index building (#16915)
## Summary

From #16861

This PR fixes the incorrect `ClassDef` handling of
`SemanticIndexBuilder::visit_stmt`, which fixes some of the incorrect
behavior of referencing the class itself in the class scope (a complete
fix requires a different fix, which will be done in the another PR).

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-23 13:23:12 +00:00
Vasco Schiavo
bb07ccd783 [pylint] Fix typo in documentation of PLC1802 (#16920) 2025-03-23 06:17:33 -05:00
John Stilley
c35f2bfe32 Fixing various spelling errors (#16924)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

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

## Summary

This is a cleanup PR. I am fixing various English language spelling
errors. This is mostly in docs and docstrings.

## Test Plan

The usual CI tests were run. I tried to build the docs (though I had
some troubles there). The testing needs here are, I trust, very low
impact. (Though I would happily test more.)
2025-03-23 08:08:40 +00:00
Micha Reiser
7fb765d9b6 [red-knot] Log sys-prefix origin for easier debugging (#16921)
## Summary

Log the origin of the sys path prefix. This should help with debugging
if someone doesn't understand
why Red Knot picks up a certain venv.

## Test Plan

Ran the CLI and tested that it logs the origin
2025-03-23 08:06:04 +00:00
Dhruv Manilawala
0360c6b219 [red-knot] Support calling a typing.Callable (#16888)
## Summary

Part of #15382, this PR adds support for calling a variable that's
annotated with `typing.Callable`.

## Test Plan

Add test cases in a new `call/annotation.md` file.
2025-03-23 02:39:33 +05:30
Dhruv Manilawala
1cffb323bc [red-knot] Check assignability for two callable types (#16845)
## Summary

Part of #15382

This PR adds support for checking the assignability of two general
callable types.

This is built on top of #16804 by including the gradual parameters check
and accepting a function that performs the check between the two types.

## Test Plan

Update `is_assignable_to.md` with callable types section.
2025-03-23 02:28:44 +05:30
Matthew Mckee
92028efe3d [red-knot] Fix disambiguate display for union types (#16907)
<!--
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

When callables are displayed in unions, like:
```py
from typing import Callable


def foo(x: Callable[[], int] | None):
    # red-knot: Revealed type is `() -> int | None` [revealed-type]
    reveal_type(x)
```

This leaves the type rather ambiguous, to fix this we can add
parenthesis to callable type in union

Fixes #16893

## Test Plan

Update callable annotations tests

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-22 13:08:51 +01:00
Matthew Mckee
7b86f54c4c [red-knot] Add line number to mdtest panic message about language tag mismatch (#16906)
<!--
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 #16898 

## Test Plan

Update test for lang mismatch panic
2025-03-22 13:05:31 +01:00
Brent Westbrook
e4f5fe8cf7 [syntax-errors] Duplicate type parameter names (#16858)
Summary
--

Detects duplicate type parameter names in function definitions, class
definitions, and type alias statements.

I also boxed the `type_params` field on `StmtTypeAlias` to make it
easier to
`match` with functions and classes. (That's the reason for the red-knot
code
owner review requests, sorry!)

Test Plan
--

New `ruff_python_syntax_errors` unit tests.

Fixes #11119.
2025-03-21 15:06:22 -04:00
Brent Westbrook
2baaedda6c [syntax-errors] Start detecting compile-time syntax errors (#16106)
## Summary

This PR implements the "greeter" approach for checking the AST for
syntax errors emitted by the CPython compiler. It introduces two main
infrastructural changes to support all of the compile-time errors:
1. Adds a new `semantic_errors` module to the parser crate with public
`SemanticSyntaxChecker` and `SemanticSyntaxError` types
2. Embeds a `SemanticSyntaxChecker` in the `ruff_linter::Checker` for
checking these errors in ruff

As a proof of concept, it also implements detection of two syntax
errors:
1. A reimplementation of
[`late-future-import`](https://docs.astral.sh/ruff/rules/late-future-import/)
(`F404`)
2. Detection of rebound comprehension iteration variables
(https://github.com/astral-sh/ruff/issues/14395)

## Test plan
Existing F404 tests, new inline tests in the `ruff_python_parser` crate,
and a linter CLI test showing an example of the `Message` output.

I also tested in VS Code, where `preview = false` and turning off syntax
errors both disable the new errors:


![image](https://github.com/user-attachments/assets/cf453d95-04f7-484b-8440-cb812f29d45e)

And on the playground, where `preview = false` also disables the errors:


![image](https://github.com/user-attachments/assets/a97570c4-1efa-439f-9d99-a54487dd6064)


Fixes #14395

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-21 14:45:25 -04:00
Ash Berlin-Taylor
b1deab83d9 Update replacement paths for AIR302 (#16876)
I am one of the core developers of Airflow and working on the
"airflow.sdk"
package, and this updates the recommended replacments to the correct
user-facing imports.[^1]

cc @Lee-W @uranusjr 

[^1]:
33f0f1d639/task-sdk/src/airflow/sdk/__init__.py (L68-L93)

<!--
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

Hope and pray? 😉 

I'm sure there are some snapshot files I'm supposed to fix first.


<!-- How was it tested? -->
2025-03-21 18:46:56 +01:00
Alex Waygood
d21d639ee0 [red-knot] Avoid false-positive diagnostics on * import statements (#16899)
## Summary

This PR removes false-positive diagnostics for `*` imports. Currently we
always emit a diagnostic for these statements unless the module we're
importing from has a symbol named `"*"` in its symbol table for the
global scope. (And if we were doing everything correctly, no module ever
would have a symbol named `"*"` in its global scope!)

The fix here is sort-of hacky and won't be what we'll want to do
long-term. However, I think it's useful to do this as a first step
since:
- It significantly reduces false positives when running on code that
uses `*` imports
- It "resets" the tests to a cleaner state with many fewer TODOs, making
it easier to see what the hard work is that's still to be done.

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-03-21 14:41:49 +00:00
Alex Waygood
14eb4cac88 [red-knot] Add failing tests for * imports (#16873)
## Summary

This PR adds a suite of tests for wildcard (`*`) imports. The tests
nearly all fail for now, and those that don't, ahem, pass for the wrong
reasons...

I've tried to add TODO comments in all instances for places where we are
currently inferring the incorrect thing, incorrectly emitting a
diagnostic, or emitting a diagnostic with a bad error message.

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-03-21 14:17:15 +00:00
Douglas Creager
c03c28d199 [red-knot] Break up call binding into two phases (#16546)
This breaks up call binding into two phases:

- **_Matching parameters_** just looks at the names and kinds
(positional/keyword) of each formal and actual parameters, and matches
them up. Most of the current call binding errors happen during this
phase.

- Once we have matched up formal and actual parameters, we can **_infer
types_** of each actual parameter, and **_check_** that each one is
assignable to the corresponding formal parameter type.

As part of this, we add information to each formal parameter about
whether it is a type form or not. Once [PEP
747](https://peps.python.org/pep-0747/) is finalized, we can hook that
up to this internal type form representation. This replaces the
`ParameterExpectations` type, which did the same thing in a more ad hoc
way.

While we're here, we add a new fluent API for building `Parameter`s,
which makes our signature constructors a bit nicer to read. We also
eliminate a TODO where we were consuming types from the argument list
instead of the bound parameter list when evaluating our special-case
known functions.

Closes #15460

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-21 09:38:11 -04:00
Brent Westbrook
4773878ee7 Bump 0.11.2 (#16896)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-03-21 09:17:07 -04:00
Junhson Jean-Baptiste
2a4d835132 Use the common OperatorPrecedence for the parser (#16747)
## Summary

This change continues to resolve #16071 (and continues the work started
in #16162). Specifically, this PR changes the code in the parser so that
it uses the `OperatorPrecedence` struct from `ruff_python_ast` instead
of its own version. This is part of an effort to get rid of the
redundant definitions of `OperatorPrecedence` throughout the codebase.

Note that this PR only makes this change for `ruff_python_parser` -- we
still want to make a similar change for the formatter (namely the
`OperatorPrecedence` defined in the expression part of the formatter,
the pattern one is different). I separated the work to keep the PRs
small and easily reviewable.

## Test Plan

Because this is an internal change, I didn't add any additional tests.
Existing tests do pass.
2025-03-21 09:40:37 +05:30
Dhruv Manilawala
04a8756379 [red-knot] Check subtype relation between callable types (#16804)
## Summary

Part of #15382

This PR adds support for checking the subtype relationship between the
two callable types.

The main source of reference used for implementation is
https://typing.python.org/en/latest/spec/callables.html#assignability-rules-for-callables.

The implementation is split into two phases:
1. Check all the positional parameters which includes positional-only,
standard (positional or keyword) and variadic kind
2. Collect all the keywords in a `HashMap` to do the keyword parameters
check via name lookup

For (1), there's a helper struct which is similar to `.zip_longest`
(from `itertools`) except that it allows control over one of the
iterator as that's required when processing a variadic parameter. This
is required because positional parameters needs to be checked as per
their position between the two callable types. The struct also keeps
track of the current iteration element because when the loop is exited
(to move on to the phase 2) the current iteration element would be
carried over to the phase 2 check.

This struct is internal to the `is_subtype_of` method as I don't think
it makes sense to expose it outside. It also allows me to use "self" and
"other" suffixed field names as that's only relevant in that context.

## Test Plan

Add extensive tests in markdown.

Converted all of the code snippets from
https://typing.python.org/en/latest/spec/callables.html#assignability-rules-for-callables
to use `knot_extensions.is_subtype_of` and verified the result.
2025-03-21 03:27:22 +00:00
Dhruv Manilawala
193c38199e [red-knot] Check whether two callable types are equivalent (#16698)
## Summary

This PR checks whether two callable types are equivalent or not.

This is required because for an equivalence relationship, the default
value does not necessarily need to be the same but if the parameter in
one of the callable has a default value then the corresponding parameter
in the other callable should also have a default value. This is the main
reason a manual implementation is required.

And, as per https://typing.python.org/en/latest/spec/callables.html#id4,
the default _type_ doesn't participate in a subtype relationship, only
the optionality (required or not) participates. This means that the
following two callable types are equivalent:

```py
def f1(a: int = 1) -> None: ...
def f2(a: int = 2) -> None: ...
```

Additionally, the name of positional-only, variadic and keyword-variadic
are not required to be the same for an equivalence relation.

A potential solution to avoid the manual implementation would be to only
store whether a parameter has a default value or not but the type is
currently required to check for assignability.

## Test plan

Add tests for callable types in `is_equivalent_to.md`
2025-03-21 03:19:07 +00:00
Matthew Mckee
63e78b41cd [red-knot] Ban most Type::Instance types in type expressions (#16872)
## Summary

Catch some Instances, but raise type error for the rest of them
Fixes #16851 

## Test Plan

Extend invalid.md in annotations

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-03-20 15:19:56 -07:00
Alex Waygood
296d67a496 Special-case value-expression inference of special form subscriptions (#16877)
## Summary

Currently for something like `X = typing.Tuple[str, str]`, we infer the
value of `X` as `object`. That's because `Tuple` (like many of the
symbols in the typing module) is annotated as a `_SpecialForm` instance
in typeshed's stubs:


23382f5f8c/crates/red_knot_vendored/vendor/typeshed/stdlib/typing.pyi (L215)

and we don't understand implicit type aliases yet, and the stub for
`_SpecialForm.__getitem__` says it always returns `object`:


23382f5f8c/crates/red_knot_vendored/vendor/typeshed/stdlib/typing.pyi (L198-L200)

We have existing false positives in our test suite due to this:


23382f5f8c/crates/red_knot_python_semantic/resources/mdtest/annotations/annotated.md (L76-L78)

and it's causing _many_ new false positives in #16872, which tries to
make our annotation-expression parsing stricter in some ways.

This PR therefore adds some small special casing for `KnownInstanceType`
variants that fallback to `_SpecialForm`, so that these false positives
can be avoided.

## Test Plan

Existing mdtest altered.

Cc. @MatthewMckee4
2025-03-20 21:46:02 +00:00
Brent Westbrook
42cbce538b [syntax-errors] Fix star annotation before Python 3.11 (#16878)
Summary
--

Fixes #16874. I previously emitted a syntax error when starred
annotations were _allowed_ rather than when they were actually used.
This caused false positives for any starred parameter name because these
are allowed to have starred annotations but not required to. The fix is
to check if the annotation is actually starred after parsing it.

Test Plan
--

New inline parser tests derived from the initial report and more
examples from the comments, although I think the first case should cover
them all.
2025-03-20 17:44:52 -04:00
Brent Westbrook
67602512b6 Recognize SyntaxError: as an error code for ecosystem checks (#16879)
Summary
--

This updates the regex in `ruff-ecosystem` to catch syntax errors in an
effort to prevent bugs like #16874. This should catch `ParseError`s,
`UnsupportedSyntaxError`s, and the upcoming `SemanticSyntaxError`s.

Test Plan
--

I ran the ecosystem check locally comparing v0.11.0 and v0.11.1 and saw
a large number (2757!) of new syntax errors. I also manually tested the
regex on a few lines before that.

If we merge this before #16878, I'd expect to see that number decrease
substantially in that PR too, as another test.
2025-03-20 17:25:40 -04:00
Shunsuke Shibayama
23382f5f8c [red-knot] add test cases result in false positive errors (#16856)
## Summary

From #16641

The previous PR attempted to fix the errors presented in this PR, but as
discussed in the conversation, it was concluded that the approach was
undesirable and that further work would be needed to fix the errors with
a correct general solution.

In this PR, I instead add the test cases from the previous PR as TODOs,
as a starting point for future work.

## Test Plan

---------

Co-authored-by: Carl Meyer <carl@oddbird.net>
2025-03-20 17:17:54 +00:00
Dylan
c1971fdde2 Bump 0.11.1 (#16871) 2025-03-20 09:50:46 -05:00
Matthew Mckee
cdafd8e32b Allow discovery of venv in VIRTUAL_ENV env variable (#16853)
## Summary

Fixes #16744 

Allows the cli to find a virtual environment from the VIRTUAL_ENV
environment variable if no `--python` is set

## Test Plan

Manual testing, of:
- Virtual environments explicitly activated using `source .venv/bin/activate`
- Virtual environments implicilty activated via `uv run`
- Broken virtual environments with no `pyvenv.cfg` file
2025-03-20 13:55:35 +00:00
Zanie Blue
12725943cd Split git pathspecs in change determination onto separate lines (#16869) 2025-03-20 14:54:56 +01:00
Zanie Blue
9d72685f8d Use the correct base commit for change determination (#16857)
`base.sha` appears to be the commit of the base branch when the pull
request was opened, not the base commit that's used to construct the
test merge commit — which can lead to incorrect "determine changes"
results where commits made to the base ref since the pull request are
opened are included in the results.

We use `git merge-base` to find the correct sha, as I don't think that
GitHub provides this. They provide `merge_commit_sha` but my
understanding is that is equivalent to the actual merge commit we're
testing in CI.

I tested this locally on an example pull request. I don't think it's
worth trying to reproduce a specific situation here.

---------

Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-03-20 08:03:03 -05:00
Junhson Jean-Baptiste
47c4ccff5d Separate BitXorOr into BitXor and BitOr precedence (#16844)
## Summary

This change follows up on the bug-fix requested in #16747 --
`ruff_python_ast::OperatorPrecedence` had an enum variant, `BitXorOr`,
which which gave the same precedence to the `|` and `^` operators. This
goes against [Python's documentation for operator
precedence](https://docs.python.org/3/reference/expressions.html#operator-precedence),
so this PR changes the code so that it's correct.

This is part of the overall effort to unify redundant definitions of
`OperatorPrecedence` throughout the codebase (#16071)

## Test Plan

Because this is an internal change, I only ran existing tests to ensure
nothing was broken.
2025-03-20 16:13:47 +05:30
Dylan
74f64d3f96 Server: Allow FixAll action in presence of version-specific syntax errors (#16848)
The single flag `has_syntax_error` on `LinterResult` is replaced with
two (private) flags: `has_valid_syntax` and
`has_no_unsupported_syntax_errors`, which record whether there are
`ParseError`s or `UnsupportedSyntaxError`s, respectively. Only the
former is used to prevent a `FixAll` action.

An attempt has been made to make consistent the usage of the phrases
"valid syntax" (which seems to be used to refer only to _parser_ errors)
and "syntax error" (which refers to both _parser_ errors and
version-specific syntax errors).

Closes #16841
2025-03-20 05:09:14 -05:00
Vasco Schiavo
999fd4f885 [refurb] Fix starred expressions fix (FURB161) (#16550)
The PR partially solves issue #16457

Specifically, it solves the following problem:

```text
$ cat >furb161_1.py <<'# EOF'
print(bin(*[123]).count("1"))
# EOF

$ python furb161_1.py
6

$ ruff --isolated check --target-version py310 --preview --select FURB161 furb161_1.py --diff 2>&1 | grep error:
error: Fix introduced a syntax error. Reverting all changes.
```

Now starred expressions are corrected handled.
2025-03-19 17:43:58 -04:00
Dylan
433a342656 [flake8-executable] Add pytest and uv run to help message for shebang-missing-python (EXE003) (#16855)
Followup to #16849 per
https://github.com/astral-sh/ruff/pull/16849#issuecomment-2737316564
2025-03-19 13:12:32 -05:00
Matthew Mckee
4ed93b4311 Show more precise messages in invalid type expressions (#16850)
## Summary

Some error messages were not very specific; this PR improves them

## Test Plan

New mdtests added; existing mdtests tweaked
2025-03-19 17:00:30 +00:00
Dylan
98fdc0ebae [flake8-executables] Allow uv run in shebang line for shebang-missing-python (EXE003) (#16849)
Skip the lint for [shebang-missing-python
(EXE003)](https://docs.astral.sh/ruff/rules/shebang-missing-python/#shebang-missing-python-exe003)
if we find `uv run` on the shebang line.

Closes #13021
2025-03-19 10:35:07 -05:00
Josh Cannon
861931795c Add --exit-non-zero-on-format (#16009)
## Summary

Fixes #8191 by introducing `--exit-non-zero-on-format` to `ruff format`
which pretty much does what it says on the tin.

## Test Plan

Added a new test!

---------

Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
2025-03-19 10:55:05 -04:00
Alex Waygood
a3f3d734a1 [red-knot] Ban list literals in most contexts in type expressions (#16847)
## Summary

This PR reworks `TypeInferenceBuilder::infer_type_expression()` so that
we emit diagnostics when encountering a list literal in a type
expression. The only place where a list literal is allowed in a type
expression is if it appears as the first argument to `Callable[]`, and
`Callable` is already heavily special-cased in our type-expression
parsing.

In order to ensure that list literals are _always_ allowed as the
_first_ argument to `Callabler` (but never allowed as the second, third,
etc. argument), I had to do some refactoring of our type-expression
parsing for `Callable` annotations.

## Test Plan

New mdtests added, and existing ones updated
2025-03-19 14:42:42 +00:00
Matthew Mckee
3a5f1d46c0 [red-knot] Make' Type::in_type_expression()' exhaustive for Type::KnownInstance (#16836)
<!--
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 #15048 
We want to handle more types from Type::KnownInstance 

## Test Plan

Add tests for each type added explicitly in the match

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-03-19 07:36:28 -07:00
Alex Waygood
f3f3e55d97 [red-knot] Minor cleanup to infer_parameterized_known_instance_type_expression (#16846)
## Summary

These are just cosmetic changes, but I'm separating them out into a
standalone PR to make a branch I have stacked on top of this easier to
review

## Test Plan

Existing tests all pass
2025-03-19 14:19:13 +00:00
Brent Westbrook
22de00de16 [internal] Return Messages from check_path (#16837)
Summary
--

This PR updates `check_path` in the `ruff_linter` crate to return a
`Vec<Message>` instead of a `Vec<Diagnostic>`. The main motivation for
this is to make it easier to convert semantic syntax errors directly
into `Message`s rather than `Diagnostic`s in #16106. However, this also
has the benefit of keeping the preview check on unsupported syntax
errors in `check_path`, as suggested in
https://github.com/astral-sh/ruff/pull/16429#discussion_r1974748024.

All of the interesting changes are in the first commit. The second
commit just renames variables like `diagnostics` to `messages`, and the
third commit is a tiny import fix.

I also updated the `ExpandedMessage::location` field name, which caused
a few extra commits tidying up the playground code. I thought it was
nicely symmetric with `end_location`, but I'm happy to revert that too.

Test Plan
--

Existing tests. I also tested the playground and server manually.
2025-03-19 10:08:07 -04:00
Dhruv Manilawala
f2a9960fb3 Use the Depot Ubuntu runners instead of GitHub for release workflows (#16843)
## Summary

This is same as https://github.com/astral-sh/uv/pull/11948 and is to
prep for the upcoming Ruff release.
2025-03-19 12:42:13 +00:00
Dhruv Manilawala
fd341bb1b2 Allow dirty files in cargo-dist for action pins (#16842)
## Summary

This is same as https://github.com/astral-sh/uv/pull/12252 and is to
prepare for the upcoming Ruff release.

Upstream issue: https://github.com/axodotdev/cargo-dist/issues/1800
2025-03-19 18:06:53 +05:30
InSync
15a6aeb998 [red-knot] Add missing space between error message and lint code in playground (#16840) 2025-03-19 11:10:59 +01:00
Micha Reiser
81759be14b [playground] Avoid concurrent deployments (#16834)
## Summary

Cancel in-flight deployments when queuing a new deployment.
2025-03-18 17:24:16 +00:00
Dhruv Manilawala
a69f6240cc [red-knot] Infer lambda return type as Unknown (#16695)
## Summary

Part of #15382

This PR infers the return type `lambda` expression as `Unknown`. In the
future, it would be more useful to infer the expression type considering
the surrounding context (#16696).

## Test Plan

Update existing test cases from `@todo` to the (verified) return type.
2025-03-18 22:48:10 +05:30
Dhruv Manilawala
c3d429ddd8 [red-knot] Move name field on parameter kind (#16830)
## Summary

Previously, the `name` field was on `Parameter` which required it to be
always optional regardless of the parameter kind because a
`typing.Callable` signature does not have name for the parameters. This
is the case for positional-only parameters. This wasn't enforced at the
type level which meant that downstream usages would have to unwrap on
`name` even though it's guaranteed to be present.

This commit moves the `name` field from `Parameter` to the
`ParameterKind` variants and makes it optional only for
`ParameterKind::PositionalOnly` variant while required for all other
variants.

One change that's now required is that a `Callable` form using a gradual
form for parameter types (`...`) would have a default `args` and
`kwargs` name used for variadic and keyword-variadic parameter kind
respectively. This is also the case for invalid `Callable` type forms. I
think this is fine as names are not relevant in this context but happy
to make it optional even in variadic variants.

## Test Plan

No new tests; make sure existing tests are passing.
2025-03-18 22:47:44 +05:30
Matthew Mckee
ab3ec4de6a [red-knot] Emit errors for more AST nodes that are invalid (or only valid in specific contexts) in type expressions (#16822)
## Summary

Add error messages for invalid nodes in type expressions

Fixes #16816 

## Test Plan

Extend annotations/invalid.md to handle these invalid AST nodes error
messages
2025-03-18 17:16:50 +00:00
Micha Reiser
a9f5dddbaa [playground] Use cursor for clickable elements (#16833) 2025-03-18 18:06:00 +01:00
Micha Reiser
cc3ddaf070 [red-knot] Deploy playground on main (#16832)
## Summary

Automatically deploy the Red Knot playground for every commit to main
(because we're moving fast ;)).

## Test Plan
2025-03-18 17:40:30 +01:00
Micha Reiser
c027979851 Red Knot Playground (#12681)
## Summary

This PR adds a playground for Red Knot

[Screencast from 2024-08-14
10-33-54.webm](https://github.com/user-attachments/assets/ae81d85f-74a3-4ba6-bb61-4a871b622f05)

Sharing does work 😆 I just forgot to start wrangler. 


It supports:

* Multiple files
* Showing the AST
* Showing the tokens
* Sharing
* Persistence to local storage

Future extensions:

* Configuration support: The `pyproject.toml` would *just* be another
file.
* Showing type information on hover

## Blockers

~~Salsa uses `catch_unwind` to break cycles, which Red Knot uses
extensively when inferring types in the standard library.
However, WASM (at least `wasm32-unknown-unknown`) doesn't support
`catch_unwind` today, so the playground always crashes when the type
inference encounters a cycle.~~

~~I created a discussion in the [salsa
zulip](https://salsa.zulipchat.com/#narrow/stream/333573-salsa-3.2E0/topic/WASM.20support)
to see if it would be possible to **not** use catch unwind to break
cycles.~~

~~[Rust tracking issue for WASM catch unwind
support](https://github.com/rust-lang/rust/issues/118168)~~

~~I tried to build the WASM with the nightly compiler option but ran
into problems because wasm-bindgen doesn't support WASM-exceptions. We
could try to write the binding code by hand.~~

~~Another alternative is to use `wasm32-unknown-emscripten` but it's
rather painful to build~~
2025-03-18 17:17:11 +01:00
Brent Westbrook
dcf31c9348 [syntax-errors] PEP 701 f-strings before Python 3.12 (#16543)
## Summary

This PR detects the use of PEP 701 f-strings before 3.12. This one
sounded difficult and ended up being pretty easy, so I think there's a
good chance I've over-simplified things. However, from experimenting in
the Python REPL and checking with [pyright], I think this is correct.
pyright actually doesn't even flag the comment case, but Python does.

I also checked pyright's implementation for
[quotes](98dc4469cc/packages/pyright-internal/src/analyzer/checker.ts (L1379-L1398))
and
[escapes](98dc4469cc/packages/pyright-internal/src/analyzer/checker.ts (L1365-L1377))
and think I've approximated how they do it.

Python's error messages also point to the simple approach of these
characters simply not being allowed:

```pycon
Python 3.11.11 (main, Feb 12 2025, 14:51:05) [Clang 19.1.6 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f'''multiline {
... expression # comment
... }'''
  File "<stdin>", line 3
    }'''
        ^
SyntaxError: f-string expression part cannot include '#'
>>> f'''{not a line \
... continuation}'''
  File "<stdin>", line 2
    continuation}'''
                    ^
SyntaxError: f-string expression part cannot include a backslash
>>> f'hello {'world'}'
  File "<stdin>", line 1
    f'hello {'world'}'
              ^^^^^
SyntaxError: f-string: expecting '}'
```

And since escapes aren't allowed, I don't think there are any tricky
cases where nested quotes or comments can sneak in.

It's also slightly annoying that the error is repeated for every nested
quote character, but that also mirrors pyright, although they highlight
the whole nested string, which is a little nicer. However, their check
is in the analysis phase, so I don't think we have such easy access to
the quoted range, at least without adding another mini visitor.

## Test Plan

New inline tests

[pyright]:
https://pyright-play.net/?pythonVersion=3.11&strict=true&code=EYQw5gBAvBAmCWBjALgCgO4gHaygRgEoAoEaCAIgBpyiiBiCLAUwGdknYIBHAVwHt2LIgDMA5AFlwSCJhwAuCAG8IoMAG1Rs2KIC6EAL6iIxosbPmLlq5foRWiEAAcmERAAsQAJxAomnltY2wuSKogA6WKIAdABWfPBYqCAE%2BuSBVqbpWVm2iHwAtvlMWMgB2ekiolUAgq4FjgA2TAAeEMieSADWCsoV5qoaqrrGDJ5MiDz%2B8ABuLqosAIREhlXlaybrmyYMXsDw7V4AnoysyAmQ5SIhwYo3d9cheADUeKlv5O%2BpQA
2025-03-18 11:12:15 -04:00
cake-monotone
4ab529803f [red-knot] Refactor property_tests.rs into property_tests module structure (#16827)
## Summary

For now, `property_tests.rs` has grown larger and larger, making the
file difficult to read and maintain.

Although the code has been split, the test paths and full names remain
unchanged. There are no changes affecting test execution.
2025-03-18 12:59:14 +00:00
Alex Waygood
23b7df9b29 [red-knot] Simplify IterationError and ContextManagerError (#16820)
## Summary

This PR simplifies `IterationError` and `ContextManagerError` so that
they no longer "remember" what type it was that was (respectively) not
iterable or not valid as a context manager. Instead, the type that was
iterated over (or was used as a context manager) is passed back in when
calling the error struct's `report_diagnostic` method.

The motivations for this are:
- It significantly simplifies the code
- It reduces the size of these types on the stack

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-03-18 11:30:41 +00:00
cake-monotone
3e2cf5d7c4 [red-knot] Improve property test performance by cloning db instead of holding MutexGuard (#16823)
## Summary

This PR brings an optimization.

- `get_cached_db` no longer returns a `MutexGuard`; instead, it returns
a cloned database.

### `get_cached_db`

Previously, the `MutexGuard` was held inside the property test function
(defined in the macro), which prevented multiple property tests from
running in parallel. More specifically, the program could only test one
random test case at a time, which likely caused a significant
bottleneck.

On my local machine, running:

```
QUICKCHECK_TESTS=100000 cargo test --release -p red_knot_python_semantic -- --ignored stable
```

showed about **a 75% speedup** (from \~60s to \~15s).
2025-03-18 09:09:57 +01:00
Micha Reiser
c9cd0acaeb [playground] Upgrade dependencies (#16825) 2025-03-18 09:07:34 +01:00
Micha Reiser
ded9c69888 [playground] Extract shared components (#16819)
## Summary
Extract components that can be shared with the Red Knot playground.

## Test Plan

`npm start`
2025-03-18 08:43:47 +01:00
Peter Hill
433879d852 [ruff] Fix --statistics reporting for unsafe fixes (#16756)
Fixes #16751

## Summary

Previously, unsafe fixes were counted as "fixable" in
`Printer::write_statistics`, in contrast to the behaviour in
`Printer::write_once`. This changes the behaviour to align with
`write_once`, including them only if `--unsafe-fixes` is set.

We now also reuse `Printer::write_summary` to avoid duplicating the
logic for whether or not to report if there are hidden fixes.

## Test Plan

Existing tests modified to use an unsafe-fixable rule, and new ones
added to cover the case with `--unsafe-fixes`
2025-03-18 08:03:14 +01:00
Kaxil Naik
b7d232cf89 [airflow] Add chain, chain_linear and cross_downstream for AIR302 (#16647)
## Summary

Similar to https://github.com/astral-sh/ruff/pull/16014. PR on Airflow
side: https://github.com/apache/airflow/pull/47639

## Test Plan

A test fixture has been updated
2025-03-18 11:08:45 +05:30
Charlie Marsh
4d3a5afea5 Update Ruff tutorial to avoid non-existent fix in __init__.py (#16818)
## Summary

There were some other stale references too.

Closes https://github.com/astral-sh/ruff/issues/16805.
2025-03-17 23:45:12 -04:00
Micha Reiser
90a8d92b2f [refactor] Convert playground to an NPM workspace (#16806)
## Summary

This is prep-work for the Red Knot playground. We'll have two
playgrounds, one for Red Knot and Ruff.
I want to share some components between the two, a "shared" NPM package
in a local workspace is a great fit for that.
I also want to share the dev dependencies and dev scripts. Again, NPM
workspaces are great for that.

This PR also sets up a CI workflow for the playground to prevent
surprises during the release.

## Test Plan

CI, local `npm install`, `npm start`, ...

I verified that the new CI step fails if there's a typescript or
formatting error.

* [Deployment test
run](https://github.com/astral-sh/ruff/actions/runs/13904914480/job/38905524353)
2025-03-17 17:56:45 +01:00
Micha Reiser
c8bd5eeb56 [ci] Remove MichaReiser as red_knot_python_semantic code owner (#16817) 2025-03-17 17:56:33 +01:00
Andrew Gallant
bd9eab059f red_knot: update diagnostic output snapshots
These should all be minor cosmetic changes. To summarize:

* In many cases, `-` was replaced with `^` for primary annotations.
This is because, previously, whether `-` or `^` was used depended
on the severity. But in the new data model, it's based on whether
the annotation is "primary" or not. We could of course change this
in whatever way we want, but I think we should roll with this for now.

* The "secondary messages" in the old API are rendered as
sub-diagnostics. This in turn results in a small change in the output
format, since previously, the secondary messages were represented as
just another snippet. We use sub-diagnostics because that's the intended
way to enforce relative ordering between messages within a diagnostic.

* The "info:" prefix used in some annotation messages has been dropped.
We could re-add this, but I think I like it better without this prefix.

I believe those 3 cover all of the snapshot changes here.
2025-03-17 12:46:49 -04:00
Andrew Gallant
6883c1dde7 ruff_db: delete old diagnostic renderer
... and switch to the new one.

We do this switch by converting the old diagnostics to a
`Diagnostic`, and then rendering that.

This does not quite emit identical output. There are some
changes. They *could* be fixed to remain the same, but the
changes aren't obviously worse to me and I think the right
way to *improve* them is to move Red Knot to the new `Diagnostic`
API.

The next commit will have the snapshot changes.
2025-03-17 12:46:49 -04:00
Andrew Gallant
9291074ba6 ruff_db: tweak main diagnostic message
In our existing diagnostics, our message is just the diagnostic
ID, and the message goes to the annotation. In reality, the
diagnostic can have its own message distinct from the optional
messages associated with an annotation.

In order to make the outputs match, we do a small tweak here:
when the main diagnostic message is empty, we drop the colon
after the diagnostic ID.

I expect that we'll want to rejigger this output format more
in the future, but for now this was a very simple change to
preserve the status quo.
2025-03-17 12:46:49 -04:00
Andrew Gallant
602a27c4e3 ruff_db: tweak number of line terminators emitted in new diagnostic renderer
When moving over to the new renderer, I noticed that it
was emitting an extra line terminator compared to the status
quo. This removes it by turning the line terminator into a
line delimiter between diagnostics.
2025-03-17 12:46:49 -04:00
Andrew Gallant
ff548b1272 ruff_db: clarify the error conditions of Diagnostic::print 2025-03-17 12:46:49 -04:00
Andrew Gallant
7512a71bbb github: include /.github/ in ripgrep searches by default
Previously, unless you had some other configuration that impacts
ripgrep, `rg -tyaml uses:` would return zero results. After this
changes, it returns more of what you might expect.

This is because ripgrep ignores hidden files and directories by default.
But arguably, searching `.github` by default is probably what we want.

I do the same thing in ripgrep's repository:
de4baa1002/.ignore (L1)
2025-03-17 12:37:57 -04:00
renovate[bot]
7ca5f132ca Update pre-commit dependencies (#16813) 2025-03-17 15:37:14 +00:00
Douglas Creager
743f85f1a4 Add dcreager as red-knot CODEOWNER (#16807)
So that I can keep track of (and start help reviewing) red-knot PRs more
easily
2025-03-17 10:48:20 -04:00
Brent Westbrook
b2e0ae6416 [flake8-gettext] Swap format- and printf-in-get-text-func-call examples (INT002, INT003) (#16769)
Summary
--
Fixes #16735. I also checked `INT001`, and it correctly has an f-string
example.

Test Plan
--
None
2025-03-17 14:37:38 +00:00
Douglas Creager
23ccb52fa6 [red-knot] Handle unions of callables better (#16716)
This cleans up how we handle calling unions of types. #16568 adding a
three-level structure for callable signatures (`Signatures`,
`CallableSignature`, and `Signature`) to handle unions and overloads.

This PR updates the bindings side to mimic that structure. What used to
be called `CallOutcome` is now `Bindings`, and represents the result of
binding actual arguments against a possible union of callables.
`CallableBinding` is the result of binding a single, possibly
overloaded, callable type. `Binding` is the result of binding a single
overload.

While we're here, this also cleans up `CallError` greatly. It was
previously extracting error information from the bindings and storing it
in the error result. It is now a simple enum, carrying no data, that's
used as a status code to talk about whether the overall binding was
successful or not. We are now more consistent about walking the binding
itself to get detailed information about _how_ the binding was
unsucessful.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-17 10:35:52 -04:00
Dhruv Manilawala
3ccc8dbbf9 [red-knot] Fix fully static check for callable type (#16803)
## Summary

This PR fixes a bug in the check for fully static callable type where we
would skip unannotated parameter type.

## Test Plan

Add tests using the new `CallableTypeFromFunction` special form.
2025-03-17 20:01:30 +05:30
Brent Westbrook
75a562d313 [syntax-errors] Parenthesized context managers before Python 3.9 (#16523)
Summary
--

I thought this was very complicated based on the comment here:
https://github.com/astral-sh/ruff/pull/16106#issuecomment-2653505671 and
on some of the discussion in the CPython issue here:
https://github.com/python/cpython/issues/56991. However, after a little
bit of experimentation, I think it boils down to this example:

```python
with (x as y): ...
```

The issue is parentheses around a `with` item with an `optional_var`, as
we (and
[Python](https://docs.python.org/3/library/ast.html#ast.withitem)) call
the trailing variable name (`y` in this case). It's not actually about
line breaks after all, except that line breaks are allowed in
parenthesized expressions, which explains the validity of cases like


```pycon
>>> with (
...     x,
...     y
... ) as foo:
...     pass
... 
```

even on Python 3.8.

I followed [pyright]'s example again here on the diagnostic range (just
the opening paren) and the wording of the error.


Test Plan
--
Inline tests

[pyright]:
https://pyright-play.net/?pythonVersion=3.7&strict=true&code=FAdwlgLgFgBAFAewA4FMB2cBEAzBCB0EAHhJgJQwCGAzjLgmQFwz6tA
2025-03-17 08:54:55 -04:00
Micha Reiser
8d3643f409 [ci]: Disable wheel testing on ppc64le (#16793)
## Summary

The PPC64le wheel testing job spuriously failes due to some race when
installing python dependencies.
This is very annoying because it requires restarting the release process
over and over again until you're lucky and it passes.

This PR disables wheel testing on PPC64le

This is the same as we did in uv, see
https://github.com/astral-sh/uv/issues/11231

## Test Plan

The wheel test step was skipped in CI, see
https://github.com/astral-sh/ruff/actions/runs/13895143309/job/38874065160?pr=16793
but it still runs for other targets
2025-03-17 13:35:44 +01:00
Alex Waygood
50b66dc025 [red-knot] Stabilize negation_reverses_subtype_order property test (#16801)
## Summary

This is a re-creation of https://github.com/astral-sh/ruff/pull/16764 by
@mtshiba, which I closed meaning to immediately reopen (GitHub wasn't
updating the PR with the latest pushed changes), and which GitHub will
not allow me to reopen for some reason. Pasting the summary from that PR
below:

> From https://github.com/astral-sh/ruff/pull/16641
> 
> As stated in this comment
(https://github.com/astral-sh/ruff/pull/16641#discussion_r1996153702),
the current ordering implementation for intersection types is incorrect.
So, I will introduce lexicographic ordering for intersection types.

## Test Plan

One property test stabilised (tested locally with
`QUICKCHECK_TESTS=2000000 cargo test --release -p
red_knot_python_semantic -- --ignored
types::property_tests::stable::negation_reverses_subtype_order`), and
existing mdtests that previously failed now pass.

Primarily-authored-by:
[mtshiba](https://github.com/astral-sh/ruff/commits?author=mtshiba)

---------

Co-authored-by: Shunsuke Shibayama <sbym1346@gmail.com>
2025-03-17 12:33:38 +00:00
Matthew Mckee
24707777af [red-knot] Emit error if int/float/complex/bytes/boolean literals appear in type expressions outside typing.Literal[] (#16765)
## Summary
Fixes https://github.com/astral-sh/ruff/issues/16532

## Test Plan

New mdtest assertions added

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-03-17 11:56:16 +00:00
Micha Reiser
93ca4a96e0 [ci] Use git diff instead of changed-files GH action (#16796)
## Summary

Use bash and `git diff` to determine which steps need to run. 

We previously used the `changed-files` github actions but using `git`
directly seems simple enough.

All credit for the bash magic goes to @zanieb and @geofft. All I did was
replace the paths arguments.


## Test Plan

* [Linter only change](https://github.com/astral-sh/ruff/pull/16800):
See how the fuzzer and formatter steps, and the linter ecosystem checks
are skipped
* [Formatter only change](https://github.com/astral-sh/ruff/pull/16799):
See how the fuzzer and linter ecosystem checks are skipped
2025-03-17 12:40:34 +01:00
Alex Waygood
38bfda94ce [syntax-errors] Improve error message and range for pre-PEP-614 decorator syntax errors (#16581)
## Summary

A small followup to https://github.com/astral-sh/ruff/pull/16386. We now
tell the user exactly what it was about their decorator that constituted
invalid syntax on Python <3.9, and the range now highlights the specific
sub-expression that is invalid rather than highlighting the whole
decorator

## Test Plan

Inline snapshots are updated, and new ones are added.
2025-03-17 11:17:27 +00:00
Mauro Fontana
4da6936ec4 [flake8-bandit] Allow raw strings in suspicious-mark-safe-usage (S308) #16702 (#16770)
## Summary
Stop flagging each invocation of `django.utils.safestring.mark_safe`
(also available at, `django.utils.html.mark_safe`) as an error.

Instead, allow string literals as valid uses for `mark_safe`.

Also, update the documentation, pointing at
`django.utils.html.format_html` for dynamic content generation use
cases.

Closes #16702 

## Test Plan
I verified several possible uses, but string literals, are still
flagged.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-17 11:29:07 +01:00
Dylan
238ec39c56 [refurb] Avoid panicking unwrap in verbose-decimal-constructor (FURB157) (#16777) 2025-03-17 05:09:07 -05:00
Micha Reiser
b04103fa1d [red-knot] Add --color CLI option (#16758)
## Summary

This PR adds a new `--color` CLI option that controls whether the output
should be colorized or not.

This is implements part of
https://github.com/astral-sh/ruff/issues/16727 except that it doesn't
implement the persistent configuration support as initially proposed in
the CLI document. I realized, that having this as a persistent
configuration is somewhat awkward because we may end up writing tracing
logs **before** we loaded and resolved the settings. Arguably, it's
probably fine to color the output up to that point, but it feels like a
somewhat broken experience. That's why I decided not to add the
persistent configuration option for now.


## Test Plan

I tested this change manually by running Red Knot with `--color=always`,
`--color=never`, and `--color=auto` (or no argument) and verified that:

* The diagnostics are or aren't colored
* The tracing output is or isn't colored.

---------

Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
2025-03-17 10:06:34 +00:00
Micha Reiser
c100d519e9 [internal]: Upgrade salsa (#16794)
## Summary

Another salsa upgrade. 

The main motivation is to stay on a recent salsa version because there
are still a lot of breaking changes happening.
The most significant changes in this update:

* Salsa no longer derives `Debug` by default. It now requires
`interned(debug)` (or similar)
* This version ships the foundation for garbage collecting interned
values. However, this comes at the cost that queries now track which
interned values they created (or read). The micro benchmarks in the
salsa repo showed a significant perf regression. Will see if this also
visible in our benchmarks.

## Test Plan

`cargo test`
2025-03-17 11:05:54 +01:00
renovate[bot]
dbdb46dcd2 Pin dependencies (#16791)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [CodSpeedHQ/action](https://redirect.github.com/CodSpeedHQ/action) |
action | pinDigest | -> `0010eb0` |
| [PyO3/maturin-action](https://redirect.github.com/PyO3/maturin-action)
| action | pinDigest | -> `36db840` |
|
[SebRollen/toml-action](https://redirect.github.com/SebRollen/toml-action)
| action | pinDigest | -> `b1b3628` |
| [Swatinem/rust-cache](https://redirect.github.com/Swatinem/rust-cache)
| action | pinDigest | -> `f0deed1` |
| [actions/cache](https://redirect.github.com/actions/cache) | action |
pinDigest | -> `d4323d4` |
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | pinDigest | -> `11bd719` |
|
[actions/download-artifact](https://redirect.github.com/actions/download-artifact)
| action | pinDigest | -> `cc20338` |
|
[actions/github-script](https://redirect.github.com/actions/github-script)
| action | pinDigest | -> `60a0d83` |
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | pinDigest | -> `cdca736` |
|
[actions/setup-python](https://redirect.github.com/actions/setup-python)
| action | pinDigest | -> `4237552` |
|
[actions/upload-artifact](https://redirect.github.com/actions/upload-artifact)
| action | pinDigest | -> `4cec3d8` |
| [astral-sh/setup-uv](https://redirect.github.com/astral-sh/setup-uv) |
action | pinDigest | -> `f94ec6b` |
|
[dawidd6/action-download-artifact](https://redirect.github.com/dawidd6/action-download-artifact)
| action | pinDigest | -> `20319c5` |
|
[docker/build-push-action](https://redirect.github.com/docker/build-push-action)
| action | pinDigest | -> `471d1dc` |
| [docker/login-action](https://redirect.github.com/docker/login-action)
| action | pinDigest | -> `74a5d14` |
|
[docker/metadata-action](https://redirect.github.com/docker/metadata-action)
| action | pinDigest | -> `902fa8e` |
|
[docker/setup-buildx-action](https://redirect.github.com/docker/setup-buildx-action)
| action | pinDigest | -> `b5ca514` |
|
[extractions/setup-just](https://redirect.github.com/extractions/setup-just)
| action | pinDigest | -> `dd310ad` |
|
[jetli/wasm-bindgen-action](https://redirect.github.com/jetli/wasm-bindgen-action)
| action | pinDigest | -> `20b33e2` |
|
[jetli/wasm-pack-action](https://redirect.github.com/jetli/wasm-pack-action)
| action | pinDigest | -> `0d096b0` |
|
[peter-evans/create-or-update-comment](https://redirect.github.com/peter-evans/create-or-update-comment)
| action | pinDigest | -> `71345be` |
|
[peter-evans/find-comment](https://redirect.github.com/peter-evans/find-comment)
| action | pinDigest | -> `3eae4d3` |
|
[taiki-e/install-action](https://redirect.github.com/taiki-e/install-action)
| action | pinDigest | -> `2c41309` |
|
[uraimo/run-on-arch-action](https://redirect.github.com/uraimo/run-on-arch-action)
| action | pinDigest | -> `ac33288` |
|
[webfactory/ssh-agent](https://redirect.github.com/webfactory/ssh-agent)
| action | pinDigest | -> `dc588b6` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 09:44:48 +01:00
Micha Reiser
2a6d43740c [internal]: Update indirect dependencies (#16792)
## Summary

```
❯ cargo update
    Updating crates.io index
    Updating git repository `https://github.com/salsa-rs/salsa.git`
    Updating git repository `https://github.com/astral-sh/lsp-types.git`
     Locking 51 packages to latest compatible versions
    Updating annotate-snippets v0.6.1 -> v0.11.5
    Updating cc v1.2.11 -> v1.2.16
    Removing chic v1.2.2
    Updating clap_complete v4.5.44 -> v4.5.46
    Updating console v0.15.10 -> v0.15.11
    Updating dyn-clone v1.0.18 -> v1.0.19
    Updating either v1.13.0 -> v1.15.0
    Updating equivalent v1.0.1 -> v1.0.2
    Updating flate2 v1.0.35 -> v1.1.0
    Updating foldhash v0.1.4 -> v0.1.5
    Updating half v2.4.1 -> v2.5.0
    Updating hermit-abi v0.4.0 -> v0.5.0
    Updating home v0.5.9 -> v0.5.11
    Updating is-terminal v0.4.15 -> v0.4.16
    Updating itoa v1.0.14 -> v1.0.15
    Updating libcst v1.6.0 -> v1.7.0
    Updating libcst_derive v1.6.0 -> v1.7.0
      Adding linux-raw-sys v0.9.3
    Updating litemap v0.7.4 -> v0.7.5
    Updating miniz_oxide v0.8.3 -> v0.8.5
    Updating once_cell v1.20.2 -> v1.21.1
    Updating oorandom v11.1.4 -> v11.1.5
    Updating os_str_bytes v7.0.0 -> v7.1.0
    Updating peg v0.8.4 -> v0.8.5
    Updating peg-macros v0.8.4 -> v0.8.5
    Updating peg-runtime v0.8.3 -> v0.8.5
    Updating pin-project v1.1.9 -> v1.1.10
    Updating pin-project-internal v1.1.9 -> v1.1.10
    Updating pkg-config v0.3.31 -> v0.3.32
    Updating portable-atomic v1.10.0 -> v1.11.0
    Updating ppv-lite86 v0.2.20 -> v0.2.21
    Updating rand_core v0.9.0 -> v0.9.3
    Updating redox_syscall v0.5.8 -> v0.5.10
      Adding rustix v1.0.2
    Updating rustversion v1.0.19 -> v1.0.20
    Updating ryu v1.0.19 -> v1.0.20
    Updating serde_repr v0.1.19 -> v0.1.20
    Updating tempfile v3.17.1 -> v3.19.0
    Updating terminal_size v0.4.1 -> v0.4.2
    Updating tinyvec v1.8.1 -> v1.9.0
    Updating toml_edit v0.22.23 -> v0.22.24
    Updating typenum v1.17.0 -> v1.18.0
    Updating uuid v1.13.1 -> v1.16.0
    Updating uuid-macro-internal v1.13.1 -> v1.16.0
    Updating wait-timeout v0.2.0 -> v0.2.1
    Updating which v7.0.1 -> v7.0.2
    Updating winnow v0.7.0 -> v0.7.4
    Removing zerocopy v0.7.35
    Removing zerocopy v0.8.14
      Adding zerocopy v0.8.23
    Removing zerocopy-derive v0.7.35
    Removing zerocopy-derive v0.8.14
      Adding zerocopy-derive v0.8.23
    Updating zerofrom v0.1.5 -> v0.1.6
    Updating zerofrom-derive v0.1.5 -> v0.1.6
    Updating zstd-sys v2.0.13+zstd.1.5.6 -> v2.0.14+zstd.1.5.7

```
2025-03-17 09:33:49 +01:00
Micha Reiser
6f5a68608e [ci]: Fixup codspeed upgrade (#16790)
## Summary

Benchmark isn't a required build step. That's why
https://github.com/astral-sh/ruff/pull/16784/ got merged with the step
failing.

This PR fixes up the benchmarking step
2025-03-17 09:14:22 +01:00
renovate[bot]
c61d9c6bb7 Update Rust crate compact_str to 0.9.0 (#16785)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [compact_str](https://redirect.github.com/ParkMyCar/compact_str) |
workspace.dependencies | minor | `0.8.0` -> `0.9.0` |

---

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

---

### Release Notes

<details>
<summary>ParkMyCar/compact_str (compact_str)</summary>

###
[`v0.9.0`](https://redirect.github.com/ParkMyCar/compact_str/blob/HEAD/CHANGELOG.md#090)

[Compare
Source](https://redirect.github.com/ParkMyCar/compact_str/compare/v0.8.1...v0.9.0)

##### February 24, 2025

#### Breaking Changes 💥

- Removed deprecated methods `CompactString::new_inline(...)` and
`CompactString::from_static_str(...)`.
- Implemented in [`fix: delete methods that are documented as deprecated
in v0.9.0`](https://redirect.github.com/ParkMyCar/compact_str/pull/429)
- Changed the `CompactStringExt::join_compact` and
`CompactStringExt::concat_compact` to take a
reference (i.e. `&C`) to a type `C: IntoIterator<Item = &str>` instead
of ownership of a type `C`
    where `&C: IntoIterator<Item = &str>`.
- Fixed
[`issue#412`](https://redirect.github.com/ParkMyCar/compact_str/issues/412)
which made the
        `CompactStringExt` more ergonomic.
- Implemented in [`feat: tweak the CompactStringExt trait so
join_compact and concat_compact work
better`](https://redirect.github.com/ParkMyCar/compact_str/pull/418)

#### Changes

-   Fixed the `borsch` feature in `no_std` environments.
- Implemented in [`fix: The borsch feature with
no-std`](https://redirect.github.com/ParkMyCar/compact_str/pull/428).
- Implemented the [`zeroize::Zeroize`](https://crates.io/crates/zeroize)
trait for `CompactString`.
- Implemented in [`feat: Add support for
zeroize::Zeroize`](https://redirect.github.com/ParkMyCar/compact_str/pull/421).
- Fixed the `CompactString::retain` method to not set length if the
predicate panics.
- Implemented in [`fix: retain not set len if predicate
panics`](https://redirect.github.com/ParkMyCar/compact_str/pull/413).
-   Implement `sqlx::postgres::PgHasArrayType` for `CompactString`.
- Implemented in [`impl
sqlx::postgres::PgHasArrayType`](https://redirect.github.com/ParkMyCar/compact_str/pull/399).
- Bump the [`markup`](https://crates.io/crates/markup) dependency to
`v0.15`.
- Implemented in [`deps: upgrade to markup
v0.8`](https://redirect.github.com/ParkMyCar/compact_str/pull/415).
- Bump the [`rkyv`](https://crates.io/crates/rkyv) dependency to `v0.8`.
- Implemented in [`deps: upgrade to rkyv
v0.8`](https://redirect.github.com/ParkMyCar/compact_str/pull/409).
- Bump the [`sqlx`](https://crates.io/crates/sqlx) dependency to `v0.8`.
- Implemented in [`deps: upgrade to sqlx
v0.8`](https://redirect.github.com/ParkMyCar/compact_str/pull/408).

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-17 09:08:52 +01:00
renovate[bot]
43d371a1c9 Update Rust crate clap to v4.5.32 (#16778)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.31` -> `4.5.32` |

---

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

---

### Release Notes

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

###
[`v4.5.32`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4532---2025-03-10)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.31...v4.5.32)

##### Features

-   Add `Error::remove`

##### Documentation

-   *(cookbook)* Switch from `humantime` to `jiff`
-   *(tutorial)* Better cover required vs optional

##### Internal

-   Update `pulldown-cmark`

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 08:04:26 +00:00
renovate[bot]
5f80129112 Update Rust crate codspeed-criterion-compat to v2.9.1 (#16784)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [codspeed-criterion-compat](https://codspeed.io)
([source](https://redirect.github.com/CodSpeedHQ/codspeed-rust)) |
workspace.dependencies | minor | `2.8.1` -> `2.9.1` |

---

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

---

### Release Notes

<details>
<summary>CodSpeedHQ/codspeed-rust (codspeed-criterion-compat)</summary>

###
[`v2.9.1`](https://redirect.github.com/CodSpeedHQ/codspeed-rust/releases/tag/v2.9.1)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/codspeed-rust/compare/v2.8.1...v2.9.1)

#### What's Changed

- feat: add support for all-features and no-default-features by
[@&#8203;not-matthias](https://redirect.github.com/not-matthias) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/83](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/83)
- feat: add support consts with divan by
[@&#8203;not-matthias](https://redirect.github.com/not-matthias) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/84](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/84)
- feat(cargo-codspeed): rethrow exit code by
[@&#8203;not-matthias](https://redirect.github.com/not-matthias) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/86](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/86)
- chore(divan_compat): remove consts from unsupported features in README
by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/87](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/87)
- feat(criterion_compat): fork criterion and add walltime support by
[@&#8203;not-matthias](https://redirect.github.com/not-matthias) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/85](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/85)

#### New Contributors

- [@&#8203;not-matthias](https://redirect.github.com/not-matthias) made
their first contribution in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/83](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/83)

**Full Changelog**:
https://github.com/CodSpeedHQ/codspeed-rust/compare/v2.8.1...v2.9.1

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 08:04:00 +00:00
renovate[bot]
db4ae242dc Update Rust crate quote to v1.0.40 (#16782)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [quote](https://redirect.github.com/dtolnay/quote) |
workspace.dependencies | patch | `1.0.39` -> `1.0.40` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/quote (quote)</summary>

###
[`v1.0.40`](https://redirect.github.com/dtolnay/quote/releases/tag/1.0.40)

[Compare
Source](https://redirect.github.com/dtolnay/quote/compare/1.0.39...1.0.40)

- Optimize construction of lifetime tokens
([#&#8203;293](https://redirect.github.com/dtolnay/quote/issues/293),
thanks [@&#8203;aatifsyed](https://redirect.github.com/aatifsyed))

</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.

---

- [x] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 07:55:12 +00:00
renovate[bot]
d3b5ef9f0b Update Rust crate ordermap to v0.5.6 (#16781)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ordermap](https://redirect.github.com/indexmap-rs/ordermap) |
workspace.dependencies | patch | `0.5.5` -> `0.5.6` |

---

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

---

### Release Notes

<details>
<summary>indexmap-rs/ordermap (ordermap)</summary>

###
[`v0.5.6`](https://redirect.github.com/indexmap-rs/ordermap/blob/HEAD/RELEASES.md#056-2025-03-10)

[Compare
Source](https://redirect.github.com/indexmap-rs/ordermap/compare/0.5.5...0.5.6)

- Added `ordermap_with_default!` and `orderset_with_default!` to be used
with
    alternative hashers, especially when using the crate without `std`.
-   Updated the `indexmap` dependency to version 2.8.0.

</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.

---

- [x] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 07:54:44 +00:00
renovate[bot]
a7a20a3684 Update cloudflare/wrangler-action action to v3.14.1 (#16783)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[cloudflare/wrangler-action](https://redirect.github.com/cloudflare/wrangler-action)
| action | patch | `v3.14.0` -> `v3.14.1` |

---

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

---

### Release Notes

<details>
<summary>cloudflare/wrangler-action
(cloudflare/wrangler-action)</summary>

###
[`v3.14.1`](https://redirect.github.com/cloudflare/wrangler-action/releases/tag/v3.14.1)

[Compare
Source](https://redirect.github.com/cloudflare/wrangler-action/compare/v3.14.0...v3.14.1)

##### Patch Changes

-
[#&#8203;358](https://redirect.github.com/cloudflare/wrangler-action/pull/358)
[`cd6314a`](cd6314a97b)
Thanks [@&#8203;penalosa](https://redirect.github.com/penalosa)! - Use
`secret bulk` instead of deprecated `secret:bulk` command

</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.

---

- [x] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 07:54:18 +00:00
renovate[bot]
6fc953119f Update Rust crate env_logger to v0.11.7 (#16779)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [env_logger](https://redirect.github.com/rust-cli/env_logger) |
workspace.dependencies | patch | `0.11.6` -> `0.11.7` |

---

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

---

### Release Notes

<details>
<summary>rust-cli/env_logger (env_logger)</summary>

###
[`v0.11.7`](https://redirect.github.com/rust-cli/env_logger/blob/HEAD/CHANGELOG.md#0117---2025-03-10)

[Compare
Source](https://redirect.github.com/rust-cli/env_logger/compare/v0.11.6...v0.11.7)

##### Internal

-   Replaced `humantime` with `jiff`

</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.

---

- [x] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 07:53:50 +00:00
renovate[bot]
405fc7f5cf Update Rust crate libc to v0.2.171 (#16780)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [libc](https://redirect.github.com/rust-lang/libc) |
workspace.dependencies | patch | `0.2.170` -> `0.2.171` |

---

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

---

### Release Notes

<details>
<summary>rust-lang/libc (libc)</summary>

###
[`v0.2.171`](https://redirect.github.com/rust-lang/libc/releases/tag/0.2.171)

[Compare
Source](https://redirect.github.com/rust-lang/libc/compare/0.2.170...0.2.171)

##### Added

- Android: Add `if_nameindex`/`if_freenameindex` support
([#&#8203;4247](https://redirect.github.com/rust-lang/libc/pull/4247))
- Apple: Add missing proc types and constants
([#&#8203;4310](https://redirect.github.com/rust-lang/libc/pull/4310))
- BSD: Add `devname`
([#&#8203;4285](https://redirect.github.com/rust-lang/libc/pull/4285))
- Cygwin: Add PTY and group API
([#&#8203;4309](https://redirect.github.com/rust-lang/libc/pull/4309))
- Cygwin: Add support
([#&#8203;4279](https://redirect.github.com/rust-lang/libc/pull/4279))
- FreeBSD: Make `spawn.h` interfaces available on all FreeBSD-like
systems
([#&#8203;4294](https://redirect.github.com/rust-lang/libc/pull/4294))
- Linux: Add `AF_XDP` structs for all Linux environments
([#&#8203;4163](https://redirect.github.com/rust-lang/libc/pull/4163))
- Linux: Add SysV semaphore constants
([#&#8203;4286](https://redirect.github.com/rust-lang/libc/pull/4286))
- Linux: Add `F_SEAL_EXEC`
([#&#8203;4316](https://redirect.github.com/rust-lang/libc/pull/4316))
- Linux: Add `SO_PREFER_BUSY_POLL` and `SO_BUSY_POLL_BUDGET`
([#&#8203;3917](https://redirect.github.com/rust-lang/libc/pull/3917))
- Linux: Add `devmem` structs
([#&#8203;4299](https://redirect.github.com/rust-lang/libc/pull/4299))
- Linux: Add socket constants up to `SO_DEVMEM_DONTNEED`
([#&#8203;4299](https://redirect.github.com/rust-lang/libc/pull/4299))
- NetBSD, OpenBSD, DragonflyBSD: Add `closefrom`
([#&#8203;4290](https://redirect.github.com/rust-lang/libc/pull/4290))
- NuttX: Add `pw_passwd` field to `passwd`
([#&#8203;4222](https://redirect.github.com/rust-lang/libc/pull/4222))
- Solarish: define `IP_BOUND_IF` and `IPV6_BOUND_IF`
([#&#8203;4287](https://redirect.github.com/rust-lang/libc/pull/4287))
- Wali: Add bindings for `wasm32-wali-linux-musl` target
([#&#8203;4244](https://redirect.github.com/rust-lang/libc/pull/4244))

##### Changed

- AIX: Use `sa_sigaction` instead of a union
([#&#8203;4250](https://redirect.github.com/rust-lang/libc/pull/4250))
- Make `msqid_ds.__msg_cbytes` public
([#&#8203;4301](https://redirect.github.com/rust-lang/libc/pull/4301))
- Unix: Make all `major`, `minor`, `makedev` into `const fn`
([#&#8203;4208](https://redirect.github.com/rust-lang/libc/pull/4208))

##### Deprecated

- Linux: Deprecate obsolete packet filter interfaces
([#&#8203;4267](https://redirect.github.com/rust-lang/libc/pull/4267))

##### Fixed

- Cygwin: Fix strerror_r
([#&#8203;4308](https://redirect.github.com/rust-lang/libc/pull/4308))
- Cygwin: Fix usage of f!
([#&#8203;4308](https://redirect.github.com/rust-lang/libc/pull/4308))
- Hermit: Make `stat::st_size` signed
([#&#8203;4298](https://redirect.github.com/rust-lang/libc/pull/4298))
- Linux: Correct values for `SI_TIMER`, `SI_MESGQ`, `SI_ASYNCIO`
([#&#8203;4292](https://redirect.github.com/rust-lang/libc/pull/4292))
- NuttX: Update `tm_zone` and `d_name` fields to use `c_char` type
([#&#8203;4222](https://redirect.github.com/rust-lang/libc/pull/4222))
- Xous: Include the prelude to define `c_int`
([#&#8203;4304](https://redirect.github.com/rust-lang/libc/pull/4304))

##### Other

- Add labels to FIXMEs
([#&#8203;4231](https://redirect.github.com/rust-lang/libc/pull/4231),
[#&#8203;4232](https://redirect.github.com/rust-lang/libc/pull/4232),
[#&#8203;4234](https://redirect.github.com/rust-lang/libc/pull/4234),
[#&#8203;4235](https://redirect.github.com/rust-lang/libc/pull/4235),
[#&#8203;4236](https://redirect.github.com/rust-lang/libc/pull/4236))
- CI: Fix "cannot find libc" error on Sparc64
([#&#8203;4317](https://redirect.github.com/rust-lang/libc/pull/4317))
- CI: Fix "cannot find libc" error on s390x
([#&#8203;4317](https://redirect.github.com/rust-lang/libc/pull/4317))
- CI: Pass `--no-self-update` to `rustup update`
([#&#8203;4306](https://redirect.github.com/rust-lang/libc/pull/4306))
- CI: Remove tests for the `i586-pc-windows-msvc` target
([#&#8203;4311](https://redirect.github.com/rust-lang/libc/pull/4311))
- CI: Remove the `check_cfg` job
([#&#8203;4322](https://redirect.github.com/rust-lang/libc/pull/4312))
- Change the range syntax that is giving `ctest` problems
([#&#8203;4311](https://redirect.github.com/rust-lang/libc/pull/4311))
- Linux: Split out the stat struct for gnu/b32/mips
([#&#8203;4276](https://redirect.github.com/rust-lang/libc/pull/4276))

##### Removed

- NuttX: Remove `pthread_set_name_np`
([#&#8203;4251](https://redirect.github.com/rust-lang/libc/pull/4251))

</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.

---

- [x] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 07:53:36 +00:00
renovate[bot]
d5e045df47 Update Rust crate etcetera to 0.10.0 (#16786)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [etcetera](https://redirect.github.com/lunacookies/etcetera) |
workspace.dependencies | minor | `0.8.0` -> `0.10.0` |

---

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

---

### Release Notes

<details>
<summary>lunacookies/etcetera (etcetera)</summary>

###
[`v0.10.0`](https://redirect.github.com/lunacookies/etcetera/releases/tag/v0.10.0)

[Compare
Source](https://redirect.github.com/lunacookies/etcetera/compare/v0.9.0...v0.10.0)

#### What's Changed

- Allow compatibility with recent versions of home in
[https://github.com/lunacookies/etcetera/pull/31](https://redirect.github.com/lunacookies/etcetera/pull/31)
- Support non-UTF8 dirs in
[https://github.com/lunacookies/etcetera/pull/32](https://redirect.github.com/lunacookies/etcetera/pull/32)
- Add note about MSRV & fix CI in
[https://github.com/lunacookies/etcetera/pull/33](https://redirect.github.com/lunacookies/etcetera/pull/33)

This version raises MSRV to 1.81.0. But if you pin `home` to `<0.5.11`
in `Cargo.lock`, then the MSRV will be `1.70.0`.

**Full Changelog**:
https://github.com/lunacookies/etcetera/compare/v0.9.0...v0.10.0

###
[`v0.9.0`](https://redirect.github.com/lunacookies/etcetera/releases/tag/v0.9.0)

[Compare
Source](https://redirect.github.com/lunacookies/etcetera/compare/v0.8.0...v0.9.0)

#### What's Changed

- Make macOS bundle ID match the directories crate in
[https://github.com/lunacookies/etcetera/pull/22](https://redirect.github.com/lunacookies/etcetera/pull/22)
- Make the traits dyn-compatible in
[https://github.com/lunacookies/etcetera/pull/25](https://redirect.github.com/lunacookies/etcetera/pull/25)
- windows-sys: bump & replace SHGetFolderPathW with SHGetKnownFolderPath
in
[https://github.com/lunacookies/etcetera/pull/30](https://redirect.github.com/lunacookies/etcetera/pull/30)
- crate: bump to edition 2021 & raise MSRV to 1.70.0 in
[https://github.com/lunacookies/etcetera/pull/30](https://redirect.github.com/lunacookies/etcetera/pull/30)

**Full Changelog**:
https://github.com/lunacookies/etcetera/compare/v0.8.0...v0.9.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 07:52:58 +00:00
renovate[bot]
adac1e6a61 Update Rust crate indexmap to v2.8.0 (#16787)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [indexmap](https://redirect.github.com/indexmap-rs/indexmap) |
workspace.dependencies | minor | `2.7.1` -> `2.8.0` |

---

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

---

### Release Notes

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

###
[`v2.8.0`](https://redirect.github.com/indexmap-rs/indexmap/blob/HEAD/RELEASES.md#280-2025-03-10)

[Compare
Source](https://redirect.github.com/indexmap-rs/indexmap/compare/2.7.1...2.8.0)

- Added `indexmap_with_default!` and `indexset_with_default!` to be used
with
    alternative hashers, especially when using the crate without `std`.
-   Implemented `PartialEq` between each `Slice` and `[]`/arrays.
-   Removed the internal `rustc-rayon` feature and dependency.

</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.

---

- [x] <!-- 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDAuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 07:52:51 +00:00
Micha Reiser
3768f9cb52 Instruct Renovate to pin GitHub Actions based on SHA (#16789)
## Summary

The intent here is that all actions should be pinned to an immutable SHA
(but that Renovate should annotate each SHA with the corresponding
SemVer version).

See https://github.com/astral-sh/uv/pull/12189

## Test plan

```
npx --yes --package renovate -- renovate-config-validator
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated rimraf@2.4.5: Rimraf versions prior to v4 are no longer supported
npm warn deprecated boolean@3.2.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
npm warn deprecated glob@6.0.4: Glob versions prior to v9 are no longer supported
 INFO: Validating .github/renovate.json5
 INFO: Config validated successfully

```
2025-03-17 07:44:59 +00:00
Micha Reiser
01f3ef4e4f [ci]: Remove changed files actions (#16788)
## Summary

tj-actions/changed-files no longer exists due to a malicious commit.
This PR removes it so that we can re-enable CI.

We can follow up with a proper replacement in a separate PR
2025-03-17 08:20:09 +01:00
Carl Meyer
2de8455e43 [red-knot] LSP: only emit WARN logs from non-red-knot sources (#16760)
Currently the red-knot LSP server emits any log messages of level `INFO`
or higher from non-red-knot crates. This makes its output quite verbose,
because Salsa emits an `INFO` level message every time it executes a
query. I use red-knot as LSP with neovim, and this spams the log file
quite a lot.

It seems like a better default to only emit `WARN` or higher messages
from non-red-knot sources.

I confirmed that this fixes the nvim LSP log spam.
2025-03-15 08:47:50 -07:00
github-actions[bot]
1fab292ec1 Sync vendored typeshed stubs (#16762)
Close and reopen this PR to trigger CI

Co-authored-by: typeshedbot <>
2025-03-15 00:38:58 +00:00
David Peter
c755eec91e [red-knot] Extend ecosystem checks (#16761)
## Summary

The ecosystem checks have proven useful so far, so I'm extending the
list a bit. My main selection criteria are:

- Few dependencies (we don't understand -stubs/-types packages yet)
- Fewer than 1000 diagnostics
- No panics

## Test Plan

Ran it locally. We now have ~2k diagnostics in total, across 12 projects
2025-03-14 22:17:38 +01:00
David Peter
ebcad6e641 [red-knot] Use try_call_dunder for augmented assignment (#16717)
## Summary

Uses the `try_call_dunder` infrastructure for augmented assignment and
fixes the logic to work for types other than `Type::Instance(…)`. This
allows us to infer the correct type here:
```py
x = (1, 2)
x += (3, 4)
reveal_type(x)  # revealed: tuple[Literal[1], Literal[2], Literal[3], Literal[4]]
```
Or in this (extremely weird) scenario:
```py
class Meta(type):
    def __iadd__(cls, other: int) -> str:
        return ""

class C(metaclass=Meta): ...

cls = C
cls += 1

reveal_type(cls)  # revealed: str
```

Union and intersection handling could also be improved here, but I made
no attempt to do so in this PR.

## Test Plan

New MD tests
2025-03-14 20:36:09 +01:00
David Peter
fe275725e0 [red-knot] Document current state of attribute assignment diagnostics (#16746)
## Summary

A follow-up to https://github.com/astral-sh/ruff/pull/16705 which
documents various kinds of diagnostics that can appear when assigning to
an attribute.

## Test Plan

New snapshot tests.
2025-03-14 20:34:43 +01:00
Micha Reiser
a467e7c8d3 [red-knot] Case sensitive module resolver (#16521)
## Summary

This PR implements the first part of
https://github.com/astral-sh/ruff/discussions/16440. It ensures that Red
Knot's module resolver is case sensitive on all systems.

This PR combines a few approaches:

1. It uses `canonicalize` on non-case-sensitive systems to get the real
casing of a path. This works for as long as no symlinks or mapped
network drives (the windows `E:\` is mapped to `\\server\share` thingy).
This is the same as what Pyright does
2. If 1. fails, fall back to recursively list the parent directory and
test if the path's file name matches the casing exactly as listed in by
list dir. This is the same approach as CPython takes in its module
resolver. The main downside is that it requires more syscalls because,
unlike CPython, we Red Knot needs to invalidate its caches if a file
name gets renamed (CPython assumes that the folders are immutable).

It's worth noting that the file watching test that I added that renames
`lib.py` to `Lib.py` currently doesn't pass on case-insensitive systems.
Making it pass requires some more involved changes to `Files`. I plan to
work on this next. There's the argument that landing this PR on its own
isn't worth it without this issue being addressed. I think it's still a
good step in the right direction even when some of the details on how
and where the path case sensitive comparison is implemented.

## Test plan

I added multiple integration tests (including a failing one). I tested
that the `case-sensitivity` detection works as expected on Windows,
MacOS and Linux and that the fast-paths are taken accordingly.
2025-03-14 19:16:44 +00:00
Micha Reiser
a128ca761f [red-knot] Very minor simplification of the render tests (#16759) 2025-03-14 19:13:07 +00:00
Brent Westbrook
3a32e56445 [syntax-errors] Unparenthesized assignment expressions in sets and indexes (#16404)
## Summary
This PR detects unparenthesized assignment expressions used in set
literals and comprehensions and in sequence indexes. The link to the
release notes in https://github.com/astral-sh/ruff/issues/6591 just has
this entry:
> * Assignment expressions can now be used unparenthesized within set
literals and set comprehensions, as well as in sequence indexes (but not
slices).

with no other information, so hopefully the test cases I came up with
cover all of the changes. I also tested these out in the Python REPL and
they actually worked in Python 3.9 too. I'm guessing this may be another
case that was "formally made part of the language spec in Python 3.10,
but usable -- and commonly used -- in Python >=3.9" as @AlexWaygood
added to the body of #6591 for context managers. So we may want to
change the version cutoff, but I've gone along with the release notes
for now.

## Test Plan

New inline parser tests and linter CLI tests.
2025-03-14 15:06:42 -04:00
Andrew Gallant
b9d7c36a23 ruff_db: add a new diagnostic renderer
We don't actually hook this up to anything in this PR, but we do
go to some trouble to granularly unit test it. The unit tests caught
plenty of bugs after I initially wrote down the implementation, so they
were very much worth it.

Closes #16506
2025-03-14 14:59:33 -04:00
Andrew Gallant
ef9a825827 ruff_db: add context configuration
Instead of hard-coding a specific context window,
it seemed prudent to make this configurable. That
makes it easier to test different context window
sizes as well.

I am not totally convinced that this is the right
place for this configuration. I could see the context
window size being a property of `Diagnostic` instead,
since we might want to change the context window
size based not just on some end user configuration,
but perhaps also the specific diagnostic.

But for now, I think it's fine for it to live here,
and all of the rendering logic doesn't care where
it lives. So it should be relatively easy to change
in the future.
2025-03-14 14:59:33 -04:00
Andrew Gallant
2bcd2b4147 red_knot: plumb through DiagnosticFormat to the CLI
The CLI calls this `OutputFormat`, and so does the type where the CLI is
defined. But it's called `DiagnosticFormat` in `ruff_db` to be
consistent with `DisplayDiagnosticConfig`.

Ref https://github.com/astral-sh/ruff/issues/15697#issuecomment-2706477278
2025-03-14 14:46:17 -04:00
Andrew Gallant
eb6871d209 ruff_db: add concise diagnostic mode
This adds a new configuration knob to diagnostic rendering that, when
enabled, will make diagnostic rendering much more terse. Specifically,
it will guarantee that each diagnostic will only use one line.

This doesn't actually hook the concise output option up to anything.
We'll do that plumbing in the next commit.
2025-03-14 14:46:17 -04:00
Brent Westbrook
6311412373 [syntax-errors] Star annotations before Python 3.11 (#16545)
Summary
--

This is closely related to (and stacked on)
https://github.com/astral-sh/ruff/pull/16544 and detects star
annotations in function definitions.

I initially called the variant `StarExpressionInAnnotation` to mirror
`StarExpressionInIndex`, but I realized it's not really a "star
expression" in this position and renamed it. `StarAnnotation` seems in
line with the PEP.

Test Plan
--

Two new inline tests. It looked like there was pretty good existing
coverage of this syntax, so I just added simple examples to test the
version cutoff.
2025-03-14 15:20:44 +00:00
Brent Westbrook
4f2851982d [syntax-errors] Star expression in index before Python 3.11 (#16544)
Summary
--

This PR detects tuple unpacking expressions in index/subscript
expressions before Python 3.11.

Test Plan
--

New inline tests
2025-03-14 14:51:34 +00:00
Micha Reiser
2cd25ef641 Ruff 0.11.0 (#16723)
## Summary

Follow-up release for Ruff v0.10 that now includes the following two
changes that we intended to ship but slipped:

* Changes to how the Python version is inferred when a `target-version`
is not specified (#16319)
* `blanket-noqa` (`PGH004`): Also detect blanked file-level noqa
comments (and not just line level comments).

## Test plan

I verified that the binary built on this branch respects the
`requires-python` setting
([logs](https://www.diffchecker.com/qyJWYi6W/), left: v0.10, right:
v0.11)
2025-03-14 13:57:56 +01:00
David Peter
a22d206db2 [red-knot] Preliminary tests for typing.Final (#15917)
## Summary

WIP.

Adds some preliminary tests for `typing.Final`.

## Test Plan

New MD tests
2025-03-14 12:30:13 +01:00
cake-monotone
270318c2e0 [red-knot] fix: improve type inference for binary ops on tuples (#16725)
## Summary

This PR includes minor improvements to binary operation inference,
specifically for tuple concatenation.

### Before

```py
reveal_type((1, 2) + (3, 4))  # revealed: @Todo(return type of decorated function)
# If TODO is ignored, the revealed type would be `tuple[1|2|3|4, ...]`
```

The `builtins.tuple` type stub defines `__add__`, but it appears to only
work for homogeneous tuples. However, I think this limitation is not
ideal for many use cases.

### After

```py
reveal_type((1, 2) + (3, 4))  # revealed: tuple[Literal[1], Literal[2], Literal[3], Literal[4]]
```

## Test Plan

### Added
- `mdtest/binary/tuples.md`

### Affected
- `mdtest/slots.md` (a test have been moved out of the `False-Negative`
block.)
2025-03-14 12:29:57 +01:00
David Peter
d03b12e711 [red-knot] Assignments to attributes (#16705)
## Summary

This changeset adds proper support for assignments to attributes:
```py
obj.attr = value
```

In particular, the following new features are now available:

* We previously didn't raise any errors if you tried to assign to a
non-existing attribute `attr`. This is now fixed.
* If `type(obj).attr` is a data descriptor, we now call its `__set__`
method instead of trying to assign to the load-context type of
`obj.attr`, which can be different for data descriptors.
* An initial attempt was made to support unions and intersections, as
well as possibly-unbound situations. There are some remaining TODOs in
tests, but they only affect edge cases. Having nested diagnostics would
be one way that could help solve the remaining cases, I believe.

## Follow ups

The following things are planned as follow-ups:

- Write a test suite with snapshot diagnostics for various attribute
assignment errors
- Improve the diagnostics. An easy improvement would be to highlight the
right hand side of the assignment as a secondary span (with the rhs type
as additional information). Some other ideas are mentioned in TODO
comments in this PR.
- Improve the union/intersection/possible-unboundness handling
- Add support for calling custom `__setattr__` methods (see new false
positive in the ecosystem results)

## Ecosystem changes

Some changes are related to assignments on attributes with a custom
`__setattr__` method (see above). Since we didn't notice missing
attributes at all in store context previously, these are new.

The other changes are related to properties. We previously used their
read-context type to test the assignment. That results in weird error
messages, as we often see assignments to `self.property` and then we
think that those are instance attributes *and* descriptors, leading to
union types. Now we properly look them up on the meta type, see the
decorated function, and try to overwrite it with the new value (as we
don't understand decorators yet). Long story short: the errors are still
weird, we need to understand decorators to make them go away.

## Test Plan

New Markdown tests
2025-03-14 12:15:41 +01:00
Micha Reiser
14c5ed5d7d [pygrep-hooks]: Detect file-level suppressions comments without rul… (#16720)
## Summary

I accidentially dropped this commit from the Ruff 0.10 release. See
https://github.com/astral-sh/ruff/pull/16699
2025-03-14 09:37:16 +01:00
Micha Reiser
595565015b Fallback to requires-python in certain cases when target-version is not found (#16721)
## Summary

Restores https://github.com/astral-sh/ruff/pull/16319 after it got
dropped from the 0.10 release branch :(

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-03-14 09:36:51 +01:00
Brent Westbrook
2382fe1f25 [syntax-errors] Tuple unpacking in for statement iterator clause before Python 3.9 (#16558)
Summary
--

This PR reuses a slightly modified version of the
`check_tuple_unpacking` method added for detecting unpacking in `return`
and `yield` statements to detect the same issue in the iterator clause
of `for` loops.

I ran into the same issue with a bare `for x in *rest: ...` example
(invalid even on Python 3.13) and added it as a comment on
https://github.com/astral-sh/ruff/issues/16520.

I considered just making this an additional `StarTupleKind` variant as
well, but this change was in a different version of Python, so I kept it
separate.

Test Plan
--

New inline tests.
2025-03-13 15:55:17 -04:00
Micha Reiser
27e9d1fe3e Ruff v0.10 Release (#16708)
Co-authored-by: dylwil3 <dylwil3@gmail.com>
Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-03-13 13:53:11 -04:00
Brent Westbrook
acf35c55f8 Add new noqa specification to the docs (#16703)
## Summary

Adds @dylwil3's new `noqa` specification to the linter `Error
suppression` page instead of the release blog post. Originally taken
from his PR comment
[here](https://github.com/astral-sh/ruff/pull/16483#issuecomment-2711985479).

## Test Plan

None
2025-03-13 12:48:53 -04:00
Dylan
b9b256209b describe requires-python fallback in docs (#16704)
Adds description of `requires-python` fallback to documentation for
configuration file discovery.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-03-13 11:48:12 -05:00
Carl Meyer
abaa18993b [red-knot] handle cycles in MRO/bases resolution (#16693)
There can be semi-cyclic inheritance patterns (e.g. recursive generics)
that are not technically inheritance cycles, but that can cause us to
hit Salsa query cycles in evaluating a type's MRO. Add fixed-point
handling to these MRO-related queries so we don't panic on these cycles.

The details of what queries we hit in what order in this case will
change as we implement support for generics, but ultimately we will
probably need cycle handling for all queries that can re-enter type
inference, otherwise we are susceptible to small changes in query
execution order causing panics.

Fixes #14333
Further reduces the panicking set of seeds in #14737
2025-03-13 08:16:03 -07:00
Shaygan Hooshyari
360ba095ff [red-knot] Auto generate statement nodes (#16645)
<!--
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? -->

Part of #15655 

Replaced statement nodes with autogenerated ones. Reused the stuff we
introduced in #16285. Nothing except for copying the nodes to new
format.

## Test Plan

Tests run without any changes. Also moved the test that checks size of
AST nodes to `generated.rs` since all of the structs that it tests are
now there.
<!-- How was it tested? -->
2025-03-13 15:43:48 +01:00
Micha Reiser
d8159e816f [pylint] Better inference for str.strip (PLE310) (#16671)
## Summary
This PR stabilizes the behavior introduced in
https://github.com/astral-sh/ruff/pull/15985

The new behavior improves the inference of `str.strip` calls:

* before: The rule only considered calls on string or byte literals
(`"abcd".strip`)
* now: The rule also catches calls to `strip` on object where the type
is known to be a `str` or `bytes` (e.g. `a = "abc"; a.strip("//")`)


The new behavior shipped as part of Ruff 0.9.6 on the 10th of Feb which
is a little more than a month ago.
There have been now new issues or PRs related to the new behavior.
2025-03-13 15:37:37 +01:00
Micha Reiser
04ad562afd [pylint] Improve repeated-equality-comparison fix to use a set when all elements are hashable (PLR1714) (#16685)
## Summary

This PR promotes the fix improvements for `PLR1714` that were introduced
in https://github.com/astral-sh/ruff/pull/14372/ to stable.

The improvement is that the fix now proposes to use a set if all
elements are hashable:

```
foo == "bar" or foo == "baz" or foo == "qux"
```

Gets fixed to 

```py
foo in {"bar", "baz", "qux"}
```

where it previously always got fixed to a tuple.

The new fix was first released in ruff 0.8.0 (Nov last year). This is
not a breaking change. The change was preview gated only to get some
extra test coverage.


There are no open issues or PRs related to this changed fix behavior.
2025-03-13 15:37:37 +01:00
Micha Reiser
91674718c4 [pylint/pep8-naming] Check __new__ argument name in bad-staticmethod-argument and not invalid-first-argument-name-for-class-method (PLW0211/N804) (#16676)
## Summary

This PR stabilizes the behavior changes introduced by
https://github.com/astral-sh/ruff/pull/13305 that were gated behind
preview.
The change is that `__new__` methods are now no longer flagged by
`invalid-first-argument-name-for-class-method` (`N804`) but instead by
`bad-staticmethod-argument` (`PLW0211`)

> __new__ methods are technically static methods, with cls as their
first argument. However, Ruff currently classifies them as classmethod,
which causes two issues:

## Test Plan

There have been no new issues or PRs related to `N804` or `PLW0211`
since the behavior change was released in Ruff 0.9.7 (about 3 weeks
ago).
This is a somewhat recent change but I don't think it's necessary to
leave this in preview for another 2 months. The main reason why it was
in preview
is that it is breaking, not because it is a risky change.
2025-03-13 15:37:37 +01:00
Micha Reiser
348815d6d6 [flake8-pyi] Stabilize fix for unused-private-type-var (PYI018) (#16682)
## Summary

This PR stabilizes the fix for `PYI018` introduced in
https://github.com/astral-sh/ruff/pull/15999/ (first released with Ruff
0.9.5 early February)

There are no known issues with the fix or open PRs.
2025-03-13 15:37:37 +01:00
Micha Reiser
1326d55c29 [flake8-bandit] Deprecate suspicious-xmle-tree-usage (S320) (#16680)
## Summary
Deprecate `S320` because defusedxml has deprecated there `lxml` module
and `lxml` has been hardened since.

flake8-bandit has removed their implementation as well
(https://github.com/PyCQA/bandit/pull/1212).

Addresses https://github.com/astral-sh/ruff/issues/13707


## Test Plan

I verified that selecting `S320` prints a warning and fails if the
preview mode is enabled.
2025-03-13 15:37:37 +01:00
Micha Reiser
c19cd58670 [flake8-simplify] Avoid double negation in fixes (SIM103) (#16684)
## Summary

This PR stabilizes the fixes improvements made in
https://github.com/astral-sh/ruff/pull/15562 (released with ruff 0.9.3
in mid January).

There's no open issue or PR related to the changed fix behavior.

This is not a breaking change. The fix was only gated behind preview to
get some more test coverage before releasing.
2025-03-13 15:37:37 +01:00
Micha Reiser
8155197549 [pyupgrade]: Improve diagnostic range for redundant-open-mode (UP015) (#16672)
## Summary

This PR stabilizes the behavior change introduced in
https://github.com/astral-sh/ruff/pull/15872/

The diagnostic range is now the range of the redundant `mode` argument
where it previously was the range of the entire `open` call:

Before:

```
UP015.py:2:1: UP015 [*] Unnecessary mode argument
  |
1 | open("foo", "U")
2 | open("foo", "Ur")
  | ^^^^^^^^^^^^^^^^^ UP015
3 | open("foo", "Ub")
4 | open("foo", "rUb")
  |
  = help: Remove mode argument
```


Now:

```
UP015.py:2:13: UP015 [*] Unnecessary mode argument
  |
1 | open("foo", "U")
2 | open("foo", "Ur")
  |             ^^^^ UP015
3 | open("foo", "Ub")
4 | open("foo", "rUb")
  |
  = help: Remove mode argument
```

This is a breaking change because it may require moving a `noqa` comment
onto a different line, e.g if you have

```py
open(
    "foo",
    "Ur",
) # noqa: UP015
```

Needs to be rewritten to 

```py
open(
    "foo",
    "Ur", # noqa: UP015
)
```

There have been now new issues or PRs since the new preview behavior was
implemented. It first was released as part of Ruff 0.9.5 on the 5th of
Feb (a little more than a month ago)

## Test Plan

I reviewed the snapshot tests
2025-03-13 15:37:37 +01:00
Micha Reiser
92193a3254 Consider all TYPE_CHECKING symbols for type-checking blocks (#16669)
## Summary

This PR stabilizes the preview behavior introduced in
https://github.com/astral-sh/ruff/pull/15719 to recognize all symbols
named `TYPE_CHECKING` as type-checking
checks in `if TYPE_CHECKING` conditions. This ensures compatibility with
mypy and pyright.

This PR also stabilizes the new behavior that removes `if 0:` and `if
False` to be no longer considered type checking blocks.
Since then, this syntax has been removed from the typing spec and was
only used for Python modules that don't have a `typing` module
([comment](https://github.com/astral-sh/ruff/pull/15719#issuecomment-2612787793)).

The preview behavior was first released with Ruff 0.9.5 (6th of
February), which was about a month ago. There are no open issues or PRs
for the changed behavior


## Test Plan

The snapshots for `SIM108` change because `SIM108` ignored type checking
blocks but it can no
simplify `if 0` or `if False` blocks again because they're no longer
considered type checking blocks.

The changes in the `TC005` snapshot or only due to that `if 0` and `if
False` are no longer recognized as type checking blocks

<!-- How was it tested? -->
2025-03-13 15:37:37 +01:00
Micha Reiser
3d2f2a2f8d [pep8-naming]: Ignore methods decorated with @typing.override (invalid-argument-name) (#16667)
## Summary

This PR stabilizes the preview behavior for `invalid-argument-name`
(`N803`)
to ignore argument names of functions decorated with `typing.override`
because
these methods are *out of the authors* control. 

This behavior was introduced in
https://github.com/astral-sh/ruff/pull/15954
and released as part of Ruff 0.9.5 (6th of February). 

There have been no new issues or PRs since this behavior change
(preview) was introduced.
2025-03-13 15:37:37 +01:00
Micha Reiser
0aded52c40 Stabilize FURB169 preview behavior (#16666)
## Summary

This PR stabilizes the preview behavior introduced in
https://github.com/astral-sh/ruff/pull/15905

The behavior change is that the rule now also recognizes `type(expr) is
type(None)` comparisons where `expr` isn't a name expression.
For example, the rule now detects `type(a.b) is type(None)` and suggests
rewriting the comparison to `a.b is None`.

The new behavior was introduced with Ruff 0.9.5 (6th of February), about
a month ago. There are no open issues or PRs related to this rule (or
behavior change).
2025-03-13 15:37:37 +01:00
Micha Reiser
7af5b98606 [pylint] Detect invalid default value type for os.environ.get (PLW1508) (#16674)
## Summary
This PR stabilizes the new behavior introduced in
https://github.com/astral-sh/ruff/pull/14512 to also detect defalut
value arguemnts to `os.environ.get` that have an invalid type (not
`str`).
There's an upstream issue for this behavior change
https://github.com/pylint-dev/pylint/issues/10092 that was accepted and
a PR, but it hasn't been merged yet.

This behavior change was first shipped with Ruff 0.8.1 (Nov 22). 

There has only be one PR since the new behavior was introduced but it
was unrelated to the scope increase
(https://github.com/astral-sh/ruff/pull/14841).
2025-03-13 15:37:37 +01:00
Micha Reiser
b9ed3e3876 [flake8-pytest-style] Allow for loops with empty bodies (PT012, PT031) (#16678)
## Summary

This PR stabilizes the behavior change introduced in
https://github.com/astral-sh/ruff/pull/15542 to allow
for statements with an empty body in `pytest.raises` and `pytest.warns`
with statements.

This raised an error before but is now allowed:

```py
with pytest.raises(KeyError, match='unknown'):
    async for _ in gpt.generate(gpt_request):
        pass
```

The same applies to 

```py
with pytest.raises(KeyError, match='unknown'):
    async for _ in gpt.generate(gpt_request):
        ...
```


There have been now new issues or PRs related to PT012 or PT031 since
this behavior change was introduced in ruff 0.9.3 (January 23rd).
2025-03-13 15:37:37 +01:00
Micha Reiser
e740286bbd [pyupgrade]: Deprecate non-pep604-isinstance (UP038) (#16681)
## Summary

This PR deprecates UP038. Using PEP 604 syntax in `isinstance` and
`issubclass` calls isn't a recommended pattern (or community agreed best
practice)
and it negatively impacts performance. 

Resolves https://github.com/astral-sh/ruff/issues/7871

## Test Plan

I tested that selecting `UP038` results in a warning in no-preview mode
and an error in preview mode
2025-03-13 15:37:37 +01:00
Brent Westbrook
776a401703 [flake8-type-checking] Stabilize runtime-cast-value (TC006) (#16637)
Summary
--

Stabilizes TC006. The test was already in the right place.

Test Plan
--

No open issues or PRs. The last related [issue] was closed on
2025-02-09.

[issue]: https://github.com/astral-sh/ruff/issues/16037
2025-03-13 15:37:37 +01:00
Brent Westbrook
5c3d555950 [flake8-bandit] Stabilize unsafe-markup-use (S704) (#16643)
Summary
--

Stabilizes S704, which is also being recoded from RUF035 in 0.10.

Test Plan
--
Existing tests with `PreviewMode` removed from the settings.

There was one issue closed on 2024-12-20 calling the rule noisy and
asking for a config option, but the option was added and then there were
no more issues or PRs.
2025-03-13 15:37:37 +01:00
Brent Westbrook
ba37c7cdba [flake8-datetimez] Stabilize datetime-min-max (DTZ901) (#16635)
Summary
--

Stabilizes DTZ901, renames the rule function to match the rule name,
removes the `preview_rules` test, and handles some nits in the docs
(mention `min` first to match the rule name too).

Test Plan
--

1 closed issue on 2024-11-12, 4 days after the rule was added. No issues
since
2025-03-13 15:37:37 +01:00
InSync
c605ce6fe2 Use inline snapshots in # noqa unit tests (#16687)
## Summary

Follow-up to #16677.

This change converts all unit tests (69 of them) in `noqa.rs` to use
inline snapshots instead. It extends the file by more than 1000 lines,
but the tests are now much easier to read and reason about.

## Test Plan

`cargo insta test`.
2025-03-13 15:37:37 +01:00
Brent Westbrook
16b0902e28 [ruff] Stabilize unnecessary-nested-literal (RUF041) (#16648)
Summary
--

Stabilizes RUF041. The tests are already in the right place, and the
docs look good.

Test Plan
--

0 issues, 1 [PR] fixing nested literals and unions the day after the
rule was added. No changes since then

I wonder if the fix in that PR could be relevant for
https://github.com/astral-sh/ruff/pull/16639, where I noticed a
potential issue with `Union`. It could be unrelated, though.

[PR]: https://github.com/astral-sh/ruff/pull/14641
2025-03-13 15:37:37 +01:00
Brent Westbrook
5bcc0c460b [flake8-use-pathlib] Stabilize invalid-pathlib-with-suffix (PTH210) (#16656)
Summary
--

Stabilizes PTH210. Tests and docs looked good.

Test Plan
--

Mentioned in 1 open issue around Python 3.14 support (`"."` becomes a
valid suffix in 3.14). Otherwise no issues or PRs since 2024-12-12, 6
days after the rule was added.
2025-03-13 15:37:37 +01:00
InSync
62e9c9e506 Add missing unit tests for # noqa: A-like cases (#16677)
## Summary

Follow-up to #16659.

This change adds tests for these three cases, which are (also) not
covered by existing tests:

* `# noqa: A` (lone incomplete code)
* `# noqa: A123, B` (complete codes, last one incomplete)
* `# noqa: A123B` (squashed codes, last one incomplete)
2025-03-13 15:37:37 +01:00
Brent Westbrook
a6d4e5aae4 [ruff] Stabilize if-key-in-dict-del (RUF051) (#16658)
Summary
--

Stabilizes RUF051. The tests and docs looked good.

Test Plan
--

1 closed documentation issue from 4 days after the rule was added and 1
typo fix from the same day it was added, but no other issues or PRs.
2025-03-13 15:37:37 +01:00
Brent Westbrook
692b651776 [flake8-bugbear] Stabilize batched-without-explicit-strict (B911) (#16655)
Summary
--

Stabilizes B911. Tests and docs looked good.

Test Plan
--

0 issues or PRs, open or closed
2025-03-13 15:37:37 +01:00
Brent Westbrook
2f2d72dc95 [flake8-logging] Stabilize root-logger-call (LOG015) (#16654)
Summary
--

Stabilizes LOG015. The tests and docs looked good.

Test Plan
--

1 closed documentation issue from 4 days after the rule was added, but
no other issues or PRs.
2025-03-13 15:37:37 +01:00
Brent Westbrook
d15641faea [ruff] Stabilize map-int-version-parsing (RUF048) (#16653)
Summary
--

Stabilizes RUF048 and moves its test to the right place. The docs look
good.

Test Plan
--

0 closed or open issues. There was 1 [PR] related to an extension to the
rule, but it was closed without comment.

[PR]: https://github.com/astral-sh/ruff/pull/14701
2025-03-13 15:37:37 +01:00
Brent Westbrook
9b1b3c1859 [ruff] Stabilize unnecessary-cast-to-int (RUF046) (#16649)
Summary
--

Stabilizes RUF046 and moves its test to the right place. The docs look
good.

Test Plan
--

2 closed newline/whitespace issues from early January and 1 closed issue
about really being multiple rules, but otherwise no recent issues or
PRs.
2025-03-13 15:37:37 +01:00
Brent Westbrook
e4b46913d2 [ruff] Stabilize invalid-assert-message-literal-argument (RUF040) (#16646)
Summary
--

Stabilizes RUF040 and fixes a very minor typo in the docs. The tests are
already in the right place.

Test Plan
--

0 issues or PRs
2025-03-13 15:37:37 +01:00
Brent Westbrook
f48bc3aea1 [flake8-use-pathlib] Stabilize os-listdir (PTH208) (#16642)
Summary
--

Stabilizes PTH208. The test was already in the right place, and the docs
look good.

Test Plan
--

0 issues and PRs, open or closed
2025-03-13 15:37:37 +01:00
Brent Westbrook
64b248ccfc [flake8-type-checking] Stabilize unquoted-type-alias (TC007) (#16638)
Summary
--

Stabilizes TC007. The test was already in the right place.

Test Plan
--

No open issues or PRs.
2025-03-13 15:37:37 +01:00
InSync
c236be4320 Add missing unit tests for # noqa:-like cases (#16659) 2025-03-13 15:37:37 +01:00
Dylan
8bd140c99d Make noqa parsing consistent and more robust (#16483)
# Summary
The goal of this PR is to address various issues around parsing
suppression comments by

1. Unifying the logic used to parse in-line (`# noqa`) and file-level
(`# ruff: noqa`) noqa comments
2. Recovering from certain errors and surfacing warnings in these cases

Closes #15682 
Supersedes #12811 
Addresses
https://github.com/astral-sh/ruff/pull/14229#discussion_r1835481018
Related: #14229 , #12809
2025-03-13 15:37:37 +01:00
Brent Westbrook
a04347b7a3 [flake8-builtins] Default to non-strict checking (A005) (#16125)
## Summary

This PR changes the default value of
`lint.flake8-builtins.builtins-strict-checking` added in
https://github.com/astral-sh/ruff/pull/15951 from `true` to `false`.
This also allows simplifying the default option logic and removes the
dependence on preview mode.

https://github.com/astral-sh/ruff/issues/15399 was already closed by
#15951, but this change will finalize the behavior mentioned in
https://github.com/astral-sh/ruff/issues/15399#issuecomment-2587017147.

As an example, strict checking flags modules based on their last
component, so `utils/logging.py` triggers A005. Non-strict checking
checks the path to the module, so `utils/logging.py` is allowed (this is
the example and desired behavior from #15399 exactly) but a top-level
`logging.py` or `logging/__init__.py` is still disallowed.

## Test Plan

Existing tests from #15951 and #16006, with the snapshot updated in
`a005_module_shadowing_strict_default` to reflect the new default.
2025-03-13 15:37:37 +01:00
Brent Westbrook
958e1177ce [pyupgrade] Stabilize non-pep646-unpack (UP044) (#16632)
Summary
--

Stabilizes UP044, renames the module to match the rule name, and removes
the `PreviewMode` from the test settings.

Test Plan
--

2 closed issues in November, just after the rule was added, otherwise no
issues
2025-03-13 15:37:37 +01:00
Brent Westbrook
fce5d892c1 [flake8-simplify] Stabilize split-static-string (SIM905) (#16631)
Summary
--

Stabilizes SIM905 and adds a small addition to the docs. The test was
already in the right place.

Test Plan
--

No issues except 2 recent, general issues about whitespace
normalization.
2025-03-13 15:37:37 +01:00
Alex Waygood
66cae0a3ec [ruff-0.10] [flake8-pyi] Stabilize preview-mode behaviours for custom-type-var-for-self(PYI019) (#16607)
## Summary

This PR stabilizes several preview-only behaviours for
`custom-typevar-for-self` (`PYI019`). Namely:
- A new, more accurate technique is now employed for detecting custom
TypeVars that are replaceable with `Self`. See
https://github.com/astral-sh/ruff/pull/15888 for details.
- The range of the diagnostic is now the full function header rather
than just the return annotation. (Previously, the rule only applied to
methods with return annotations, but this is no longer true due to the
changes in the first bullet point.)
- The fix is now available even when preview mode is not enabled.

## Test Plan

- Existing snapshots that do not have preview mode enabled are updated
- Preview-specific snapshots are removed
- I'll check the ecosystem report on this PR to verify everything's as
expected
2025-03-13 15:37:37 +01:00
Brent Westbrook
bbcddf7e79 [pylint] Stabilize len-test (PLC1802) (#16626)
Summary
--

Stabilizes PLC1802. The tests were already in the right place, and I
just tidied the docs a little bit.

Test Plan
--

1 issue closed 4 days after the rule was added, no other issues
2025-03-13 15:37:37 +01:00
Brent Westbrook
c387a51cad [pylint] Stabilize shallow-copy-environ (PLW1507) (#16627)
Summary
--

Stabilizes PLW1507. The tests were already in the right place, and I
just tidied the docs a little bit.

Test Plan
--

1 issue from 2 weeks ago but just suggesting to mark the fix unsafe. The
shallow vs deep copy *does* change the program behavior, just usually in
a preferable way.
2025-03-13 15:37:37 +01:00
Brent Westbrook
5285e3fcbc [FastAPI] Stabilize fast-api-unused-path-parameter (FAST003) (#16625)
## Summary

Stabilizes FAST003, completing the group with FAST001 and FAST002.

## Test Plan

Last bug fix (false positive) was fixed on 2025-01-13, almost 2 months
ago.

The test case was already in the right place.
2025-03-13 15:37:37 +01:00
Brent Westbrook
ed4152dec6 [flake8-comprehensions] Stabilize unnecessary-dict-comprehension-for-iterable (C420) (#16624)
## Summary

Stabilizes C420 for the 0.10 release.

## Test Plan

No open issues or PRs (except a general issue about [string
normalization](https://github.com/astral-sh/ruff/issues/16579)). The
last (and only) false-negative bug fix was over a month ago.

The tests for this rule were already not on the `preview_rules` test, so
I just changed the `RuleGroup`. The documentation looked okay to me.
2025-03-13 15:37:37 +01:00
InSync
24ec94562c [flake8-builtins] Remove builtins- prefix from option names (#16092)
## Summary

Resolves #15368.

The following options have been renamed:

* `builtins-allowed-modules` &rarr; `allowed-modules`
* `builtins-ignorelist` &rarr; `ignorelist`
* `builtins-strict-checking` &rarr; `strict-checking`

To preserve compatibility, the old names are kept as Serde aliases.

## Test Plan

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

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-13 15:37:37 +01:00
David Salvisberg
c0b1413ecd [flake8-bandit] Move unsafe-markup-use from RUF035 to S704 (#15957)
## Summary

`RUF035` has been backported into bandit as `S704` in this
[PR](https://github.com/PyCQA/bandit/pull/1225)

This moves the rule and its corresponding setting to the `flake8-bandit`
category

## Test Plan

`cargo nextest run`

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-13 15:37:37 +01:00
Dhruv Manilawala
798fa47c2e Server: Remove log notification for printDebugInformation command (#16617)
## Summary

For context, the initial implementation started out by sending a log
notification to the client to include this information in the client
channel. This is a bit ineffective because it doesn't allow the client
to display this information in a more obvious way. In addition to that,
it isn't obvious from a users perspective as to where the information is
being printed unless they actually open the output channel.

The change was to actually return this formatted string that contains
the information and let the client handle how it should display this
information. For example, in the Ruff VS Code extension we open a split
window and show this information which is similar to what rust-analyzer
does.

The notification request was kept as a precaution in case there are
users who are actually utilizing this way. If they exists, it should a
minority as it requires the user to actually dive into the code to
understand how to hook into this notification. With 0.10, we're removing
the old way as it only clobbers the output channel with a long message.

fixes: #16225

## Test Plan

Tested it out locally that the information is not being logged to the
output channel of VS Code.
2025-03-13 15:37:37 +01:00
Micha Reiser
a4b7c4ef70 [formatter] Stabilize fix for single-with-item formatting with trailing comment (#16603)
## Summary

This PR stabilizies the fix for
https://github.com/astral-sh/ruff/issues/14001

We try to only make breaking formatting changes once a year. However,
the plan was to release this fix as part of Ruff 0.9 but I somehow
missed it when promoting all other formatter changes.
I think it's worth making an exception here considering that this is a
bug fix, it improves readability, and it should be rare
(very few files in a single project). Our version policy explicitly
allows breaking formatter changes in any minor release and the idea of
only making breaking formatter changes once a year is mainly to avoid
multiple releases throughout the year that introduce large formatter
changes

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

## Test Plan

Updated snapshot
2025-03-13 15:37:37 +01:00
samypr100
df6c850a53 Bump alpine default tag to 3.21 (#16456)
## Summary

Alpine 3.21 has been released for a few months and `uv` has already
migrated in https://github.com/astral-sh/uv/pull/11157
2025-03-13 15:37:37 +01:00
Peter Hill
a90cf9d59c [ruff] Fix last_tag/commits_since_last_tag for version command (#16686)
## Summary

Since Ruff changed to GitHub releases, tags are no longer annotated and
`git describe` no longer picks them up. Instead, it's necessary to also
search lightweight tags.

This changes fixes the `version` command to give more accurate
`last_tag`/`commits_since_last_tag` information. This only affects
development builds, as this information is not present in releases.

## Test Plan

Testing is a little tricky because this information changes on every
commit. Running manually on current `main` and my branch:

`main`:

```
# cargo run --bin ruff -- version --output-format=text
ruff 0.9.10+2547 (dd2313ab0 2025-03-12)

# cargo run --bin ruff -- version --output-format=json
{
  "version": "0.9.10",
  "commit_info": {
    "short_commit_hash": "dd2313ab0",
    "commit_hash": "dd2313ab0faea90abf66a75f1b5c388e728d9d0a",
    "commit_date": "2025-03-12",
    "last_tag": "v0.4.10",
    "commits_since_last_tag": 2547
  }
}
```

This PR:

```
# cargo run --bin ruff -- version --output-format=text
ruff 0.9.10+46 (11f39f616 2025-03-12)

# cargo run --bin ruff -- version --output-format=json
{
  "version": "0.9.10",
  "commit_info": {
    "short_commit_hash": "11f39f616",
    "commit_hash": "11f39f6166c3d7a521725b938a166659f64abb59",
    "commit_date": "2025-03-12",
    "last_tag": "0.9.10",
    "commits_since_last_tag": 46
  }
}
```
2025-03-13 11:59:54 +00:00
Dhruv Manilawala
58d5fe982e [red-knot] Check gradual equivalence between callable types (#16634) 2025-03-13 08:16:51 +05:30
Dhruv Manilawala
08fa9b4a90 [red-knot] Add CallableTypeFromFunction special form (#16683)
## Summary

This PR adds a new `CallableTypeFromFunction` special form to allow
extracting the abstract signature of a function literal i.e., convert a
`Type::Function` into a `Type::Callable` (`CallableType::General`).

This is done to support testing the `is_gradual_equivalent_to` type
relation specifically the case we want to make sure that a function that
has parameters with no annotations and does not have a return type
annotation is gradual equivalent to `Callable[[Any, Any, ...], Any]`
where the number of parameters should match between the function literal
and callable type.

Refer
https://github.com/astral-sh/ruff/pull/16634#discussion_r1989976692

### Bikeshedding

The name `CallableTypeFromFunction` is a bit too verbose. A possibly
alternative from Carl is `CallableTypeOf` but that would be similar to
`TypeOf` albeit with a limitation that the former only accepts function
literal types and errors on other types.

Some other alternatives:
* `FunctionSignature`
* `SignatureOf` (similar issues as `TypeOf`?)
* ...

## Test Plan

Update `type_api.md` with a new section that tests this special form,
both invalid and valid forms.
2025-03-13 07:49:34 +05:30
David Peter
dd2313ab0f [red-knot] Add mypy_primer usage documentation (#16679)
## Summary

Add documentation on how to run mypy_primer locally.
2025-03-12 16:47:10 +01:00
Carl Meyer
057e497d30 [red-knot] fix red-knot fuzzing (#16675)
The red-knot CLI changed since the fuzzer script was added; update it to
work with current red-knot CLI.

Also add some notes on how to ensure local changes to the fuzzer script
are picked up.
2025-03-12 06:25:29 -07:00
David Peter
083df0cf84 [red-knot] Support custom __getattr__ methods (#16668)
## Summary

Add support for calling custom `__getattr__` methods in case an
attribute is not otherwise found. This allows us to get rid of many
ecosystem false positives where we previously emitted errors when
accessing attributes on `argparse.Namespace`.

closes #16614

## Test Plan

* New Markdown tests
* Observed expected ecosystem changes (the changes for `arrow` also look
fine, since the `Arrow` class has a custom [`__getattr__`
here](1d70d00919/arrow/arrow.py (L802-L815)))
2025-03-12 13:44:11 +01:00
Carl Meyer
a176c1ac80 [red-knot] use fixpoint iteration for all cycles (#14029)
Pulls in the latest Salsa main branch, which supports fixpoint
iteration, and uses it to handle all query cycles.

With this, we no longer need to skip any corpus files to avoid panics.

Latest perf results show a 6% incremental and 1% cold-check regression.
This is not a "no cycles" regression, as tomllib and typeshed do trigger
some definition cycles (previously handled by our old
`infer_definition_types` fallback to `Unknown`). We don't currently have
a benchmark we can use to measure the pure no-cycles regression, though
I expect there would still be some regression; the fixpoint iteration
feature in Salsa does add some overhead even for non-cyclic queries.

I think this regression is within the reasonable range for this feature.
We can do further optimization work later, but I don't think it's the
top priority right now. So going ahead and acknowledging the regression
on CodSpeed.

Mypy primer is happy, so this doesn't regress anything on our
currently-checked projects. I expect it probably unlocks adding a number
of new projects to our ecosystem check that previously would have
panicked.

Fixes #13792
Fixes #14672
2025-03-12 12:41:40 +00:00
David Peter
a6572a57c4 [red-knot] Attribute access on intersection types (#16665)
## Summary

Implements attribute access on intersection types, which didn't
previously work. For example:

```py
from typing import Any

class P: ...
class Q: ...

class A:
    x: P = P()

class B:
    x: Any = Q()

def _(obj: A):
    if isinstance(obj, B):
        reveal_type(obj.x)  # revealed: P & Any
```

Refers to [this comment].

[this comment]:
https://github.com/astral-sh/ruff/pull/16416#discussion_r1985040363

## Test Plan

New Markdown tests
2025-03-12 13:20:17 +01:00
Joey Bar
b250304ad3 [red-knot] Improve is_disjoint for two intersections (#16636)
## Summary

Background - as a follow up to #16611 I noticed that there's a lot of
code duplicated between the `is_assignable_to` and `is_subtype_of`
functions and considered trying to merge them.

[A subtype and an assignable type are pretty much the
same](https://typing.python.org/en/latest/spec/concepts.html#the-assignable-to-or-consistent-subtyping-relation),
except that subtypes are by definition fully static, so I think we can
replace the whole of `is_subtype_of` with:

```
if !self.is_fully_static(db) || !target.is_fully_static(db) {
    return false;
}
return self.is_assignable_to(target)
```

if we move all of the logic to is_assignable_to and delete duplicate
code. Then we can discuss if it even makes sense to have a separate
is_subtype_of function (I think the answer is yes since it's used by a
bunch of other places, but we may be able to basically rip out the
concept).

Anyways while playing with combining the functions I noticed is that the
handling of Intersections in `is_subtype_of` has a special case for two
intersections, which I didn't include in the last PR - rather I first
handled right hand intersections before left hand, which should properly
handle double intersections (hand-wavy explanation I can justify if
needed - (A & B & C) is assignable to (A & B) because the left is
assignable to both A and B, but none of A, B, or C is assignable to (A &
B)).

I took a look at what breaks if I remove the handling for double
intersections, and the reason it is needed is because is_disjoint does
not properly handle intersections with negative conditions (so instead
`is_subtype_of` basically implements the check correctly).

This PR adds support to is_disjoint for properly checking negative
branches, which also lets us simplify `is_subtype_of`, bringing it in
line with `is_assignable_to`

## Test Plan

Added a bunch of tests, most of which failed before this fix

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-12 12:13:04 +00:00
David Peter
11b5cbcd2f [red-knot] Restructure attribute-access and descriptor-protocol test suites. (#16664)
## Summary

This is a pure restructuring of the `attributes.md` and
`descriptor_protocol.md` test suites. They have grown organically and I
didn't want to make major structural changes in my recent PR to keep the
diff clean.
2025-03-12 09:52:21 +01:00
David Peter
3228545598 [red-knot] Minor optimization/cleanup in member lookup (#16663)
## Summary

A follow up to address [this comment]:

> Similarly here, it might be a little more performant to have a single
`Type::instance()` branch with an inner match over `class.known()`
rather than having multiple branches with `if class.is_known()` guards

[this comment]:
https://github.com/astral-sh/ruff/pull/16416#discussion_r1985159037
2025-03-12 09:11:05 +01:00
David Peter
860b95a318 [red-knot] Binary operator inference for union types (#16601)
## Summary

Properly handle binary operator inference for union types.

This fixes a bug I noticed while looking at ecosystem results. The MRE
version of it is this:

```py
def sub(x: float, y: float):
    # Red Knot: Operator `-` is unsupported between objects of type `int | float` and `int | float`
    return x - y
```

## Test Plan

- New Markdown tests.
- Expected diff in the ecosystem checks
2025-03-12 08:21:54 +01:00
Dhruv Manilawala
6de2b2873b [red-knot] Check if callable type is fully static (#16633)
## Summary

Part of #15382 

This PR adds the check for whether a callable type is fully static or
not.

A callable type is fully static if all of the parameter types are fully
static _and_ the return type is fully static _and_ if it does not use
the gradual form (`...`) for its parameters.

## Test Plan

Update `is_fully_static.md` with callable types.

It seems that currently this test is grouped into either fully static or
not, I think it would be useful to split them up in groups like
callable, etc. I intentionally avoided that in this PR but I'll put up a
PR for an appropriate split.

Note: I've an explicit goal of updating the property tests with the new
callable types once all relations are implemented.
2025-03-12 12:13:22 +05:30
Dhruv Manilawala
6b84253679 [red-knot] Callable member lookup, meta type impl (#16618)
## Summary

This PR is a follow-up to https://github.com/astral-sh/ruff/pull/16493
that implements member lookup for the general callable type.

Based on the discussion around [member lookup
here](https://github.com/astral-sh/ruff/pull/16493#discussion_r1982041180)
and [`.to_meta_type()`
here](https://github.com/astral-sh/ruff/pull/16493#discussion_r1985104664).

## Test Plan

Add a new test cases.
2025-03-12 12:01:38 +05:30
Carl Meyer
0340e23395 [red-knot] remove redundant sentence in test (#16660)
Removes a redundant sentence I accidentally left in the test suite from
in #16540 (my mistake).
2025-03-12 04:20:31 +00:00
Shunsuke Shibayama
78b5f0b165 [red-knot] detect invalid return type (#16540)
## Summary

This PR closes #16248.

If the return type of the function isn't assignable to the one
specified, an `invalid-return-type` error occurs.
I thought it would be better to report this as a different kind of error
than the `invalid-assignment` error, so I defined this as a new error.

## Test Plan

All type inconsistencies in the test cases have been replaced with
appropriate ones.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-12 01:58:59 +00:00
Douglas Creager
e17cd350b6 [red-knot] Support multiple overloads when binding parameters at call sites (#16568)
This updates the `Signature` and `CallBinding` machinery to support
multiple overloads for a callable. This is currently only used for
`KnownFunction`s that we special-case in our type inference code. It
does **_not_** yet update the semantic index builder to handle
`@overload` decorators and construct a multi-signature `Overloads`
instance for real Python functions.

While I was here, I updated many of the `try_call` special cases to use
signatures (possibly overloaded ones now) and `bind_call` to check
parameter lists. We still need some of the mutator methods on
`OverloadBinding` for the special cases where we need to update return
types based on some Rust code.
2025-03-11 15:08:17 -04:00
Alex Waygood
c16237ddc0 [red-knot] Rework Type::to_instance() to return Option<Type> (#16428)
## Summary

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

The PR reworks `Type::to_instance()` to return `Option<Type>` rather
than `Type`. This reflects more accurately the fact that some variants
cannot be "turned into an instance", since they _already_ represent
instances of some kind. On `main`, we silently fallback to `Unknown` for
these variants, but this implicit behaviour can be somewhat surprising
and lead to unexpected bugs.

Returning `Option<Type>` rather than `Type` means that each callsite has
to account for the possibility that the type might already represent an
instance, and decide what to do about it.
In general, I think this increases the robustness of the code. Working
on this PR revealed two latent bugs in the code:
- One which has already been fixed by
https://github.com/astral-sh/ruff/pull/16427
- One which is fixed as part of https://github.com/astral-sh/ruff/pull/16608

I added special handling to `KnownClass::to_instance()`: If we fail to find one of these classes and the `test` feature is
_not_ enabled, we log a warning to the terminal saying that we failed to
find the class in typeshed and that we will be falling back to
`Type::Unknown`. A cache is maintained so that we record all classes
that we have already logged a warning for; we only log a warning for
failing to lookup a `KnownClass` if we know that it's the first time
we're looking it up.

## Test Plan

- All existing tests pass
- I ran the property tests via `QUICKCHECK_TESTS=1000000 cargo test
--release -p red_knot_python_semantic -- --ignored
types::property_tests::stable`

I also manually checked that warnings are appropriately printed to the
terminal when `KnownClass::to_instance()` falls back to `Unknown` and
the `test` feature is not enabled. To do this, I applied this diff to
the PR branch:

<details>
<summary>Patch deleting `int` and `str` from buitins</summary>

```diff
diff --git a/crates/red_knot_vendored/vendor/typeshed/stdlib/builtins.pyi b/crates/red_knot_vendored/vendor/typeshed/stdlib/builtins.pyi
index 0a6dc57b0..86636a05b 100644
--- a/crates/red_knot_vendored/vendor/typeshed/stdlib/builtins.pyi
+++ b/crates/red_knot_vendored/vendor/typeshed/stdlib/builtins.pyi
@@ -228,111 +228,6 @@ _PositiveInteger: TypeAlias = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
 _NegativeInteger: TypeAlias = Literal[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20]
 _LiteralInteger = _PositiveInteger | _NegativeInteger | Literal[0]  # noqa: Y026  # TODO: Use TypeAlias once mypy bugs are fixed
 
-class int:
-    @overload
-    def __new__(cls, x: ConvertibleToInt = ..., /) -> Self: ...
-    @overload
-    def __new__(cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self: ...
-    def as_integer_ratio(self) -> tuple[int, Literal[1]]: ...
-    @property
-    def real(self) -> int: ...
-    @property
-    def imag(self) -> Literal[0]: ...
-    @property
-    def numerator(self) -> int: ...
-    @property
-    def denominator(self) -> Literal[1]: ...
-    def conjugate(self) -> int: ...
-    def bit_length(self) -> int: ...
-    if sys.version_info >= (3, 10):
-        def bit_count(self) -> int: ...
-
-    if sys.version_info >= (3, 11):
-        def to_bytes(
-            self, length: SupportsIndex = 1, byteorder: Literal["little", "big"] = "big", *, signed: bool = False
-        ) -> bytes: ...
-        @classmethod
-        def from_bytes(
-            cls,
-            bytes: Iterable[SupportsIndex] | SupportsBytes | ReadableBuffer,
-            byteorder: Literal["little", "big"] = "big",
-            *,
-            signed: bool = False,
-        ) -> Self: ...
-    else:
-        def to_bytes(self, length: SupportsIndex, byteorder: Literal["little", "big"], *, signed: bool = False) -> bytes: ...
-        @classmethod
-        def from_bytes(
-            cls,
-            bytes: Iterable[SupportsIndex] | SupportsBytes | ReadableBuffer,
-            byteorder: Literal["little", "big"],
-            *,
-            signed: bool = False,
-        ) -> Self: ...
-
-    if sys.version_info >= (3, 12):
-        def is_integer(self) -> Literal[True]: ...
-
-    def __add__(self, value: int, /) -> int: ...
-    def __sub__(self, value: int, /) -> int: ...
-    def __mul__(self, value: int, /) -> int: ...
-    def __floordiv__(self, value: int, /) -> int: ...
-    def __truediv__(self, value: int, /) -> float: ...
-    def __mod__(self, value: int, /) -> int: ...
-    def __divmod__(self, value: int, /) -> tuple[int, int]: ...
-    def __radd__(self, value: int, /) -> int: ...
-    def __rsub__(self, value: int, /) -> int: ...
-    def __rmul__(self, value: int, /) -> int: ...
-    def __rfloordiv__(self, value: int, /) -> int: ...
-    def __rtruediv__(self, value: int, /) -> float: ...
-    def __rmod__(self, value: int, /) -> int: ...
-    def __rdivmod__(self, value: int, /) -> tuple[int, int]: ...
-    @overload
-    def __pow__(self, x: Literal[0], /) -> Literal[1]: ...
-    @overload
-    def __pow__(self, value: Literal[0], mod: None, /) -> Literal[1]: ...
-    @overload
-    def __pow__(self, value: _PositiveInteger, mod: None = None, /) -> int: ...
-    @overload
-    def __pow__(self, value: _NegativeInteger, mod: None = None, /) -> float: ...
-    # positive __value -> int; negative __value -> float
-    # return type must be Any as `int | float` causes too many false-positive errors
-    @overload
-    def __pow__(self, value: int, mod: None = None, /) -> Any: ...
-    @overload
-    def __pow__(self, value: int, mod: int, /) -> int: ...
-    def __rpow__(self, value: int, mod: int | None = None, /) -> Any: ...
-    def __and__(self, value: int, /) -> int: ...
-    def __or__(self, value: int, /) -> int: ...
-    def __xor__(self, value: int, /) -> int: ...
-    def __lshift__(self, value: int, /) -> int: ...
-    def __rshift__(self, value: int, /) -> int: ...
-    def __rand__(self, value: int, /) -> int: ...
-    def __ror__(self, value: int, /) -> int: ...
-    def __rxor__(self, value: int, /) -> int: ...
-    def __rlshift__(self, value: int, /) -> int: ...
-    def __rrshift__(self, value: int, /) -> int: ...
-    def __neg__(self) -> int: ...
-    def __pos__(self) -> int: ...
-    def __invert__(self) -> int: ...
-    def __trunc__(self) -> int: ...
-    def __ceil__(self) -> int: ...
-    def __floor__(self) -> int: ...
-    def __round__(self, ndigits: SupportsIndex = ..., /) -> int: ...
-    def __getnewargs__(self) -> tuple[int]: ...
-    def __eq__(self, value: object, /) -> bool: ...
-    def __ne__(self, value: object, /) -> bool: ...
-    def __lt__(self, value: int, /) -> bool: ...
-    def __le__(self, value: int, /) -> bool: ...
-    def __gt__(self, value: int, /) -> bool: ...
-    def __ge__(self, value: int, /) -> bool: ...
-    def __float__(self) -> float: ...
-    def __int__(self) -> int: ...
-    def __abs__(self) -> int: ...
-    def __hash__(self) -> int: ...
-    def __bool__(self) -> bool: ...
-    def __index__(self) -> int: ...
-
 class float:
     def __new__(cls, x: ConvertibleToFloat = ..., /) -> Self: ...
     def as_integer_ratio(self) -> tuple[int, int]: ...
@@ -437,190 +332,6 @@ class _FormatMapMapping(Protocol):
 class _TranslateTable(Protocol):
     def __getitem__(self, key: int, /) -> str | int | None: ...
 
-class str(Sequence[str]):
-    @overload
-    def __new__(cls, object: object = ...) -> Self: ...
-    @overload
-    def __new__(cls, object: ReadableBuffer, encoding: str = ..., errors: str = ...) -> Self: ...
-    @overload
-    def capitalize(self: LiteralString) -> LiteralString: ...
-    @overload
-    def capitalize(self) -> str: ...  # type: ignore[misc]
-    @overload
-    def casefold(self: LiteralString) -> LiteralString: ...
-    @overload
-    def casefold(self) -> str: ...  # type: ignore[misc]
-    @overload
-    def center(self: LiteralString, width: SupportsIndex, fillchar: LiteralString = " ", /) -> LiteralString: ...
-    @overload
-    def center(self, width: SupportsIndex, fillchar: str = " ", /) -> str: ...  # type: ignore[misc]
-    def count(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
-    def encode(self, encoding: str = "utf-8", errors: str = "strict") -> bytes: ...
-    def endswith(
-        self, suffix: str | tuple[str, ...], start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /
-    ) -> bool: ...
-    @overload
-    def expandtabs(self: LiteralString, tabsize: SupportsIndex = 8) -> LiteralString: ...
-    @overload
-    def expandtabs(self, tabsize: SupportsIndex = 8) -> str: ...  # type: ignore[misc]
-    def find(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
-    @overload
-    def format(self: LiteralString, *args: LiteralString, **kwargs: LiteralString) -> LiteralString: ...
-    @overload
-    def format(self, *args: object, **kwargs: object) -> str: ...
-    def format_map(self, mapping: _FormatMapMapping, /) -> str: ...
-    def index(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
-    def isalnum(self) -> bool: ...
-    def isalpha(self) -> bool: ...
-    def isascii(self) -> bool: ...
-    def isdecimal(self) -> bool: ...
-    def isdigit(self) -> bool: ...
-    def isidentifier(self) -> bool: ...
-    def islower(self) -> bool: ...
-    def isnumeric(self) -> bool: ...
-    def isprintable(self) -> bool: ...
-    def isspace(self) -> bool: ...
-    def istitle(self) -> bool: ...
-    def isupper(self) -> bool: ...
-    @overload
-    def join(self: LiteralString, iterable: Iterable[LiteralString], /) -> LiteralString: ...
-    @overload
-    def join(self, iterable: Iterable[str], /) -> str: ...  # type: ignore[misc]
-    @overload
-    def ljust(self: LiteralString, width: SupportsIndex, fillchar: LiteralString = " ", /) -> LiteralString: ...
-    @overload
-    def ljust(self, width: SupportsIndex, fillchar: str = " ", /) -> str: ...  # type: ignore[misc]
-    @overload
-    def lower(self: LiteralString) -> LiteralString: ...
-    @overload
-    def lower(self) -> str: ...  # type: ignore[misc]
-    @overload
-    def lstrip(self: LiteralString, chars: LiteralString | None = None, /) -> LiteralString: ...
-    @overload
-    def lstrip(self, chars: str | None = None, /) -> str: ...  # type: ignore[misc]
-    @overload
-    def partition(self: LiteralString, sep: LiteralString, /) -> tuple[LiteralString, LiteralString, LiteralString]: ...
-    @overload
-    def partition(self, sep: str, /) -> tuple[str, str, str]: ...  # type: ignore[misc]
-    if sys.version_info >= (3, 13):
-        @overload
-        def replace(
-            self: LiteralString, old: LiteralString, new: LiteralString, /, count: SupportsIndex = -1
-        ) -> LiteralString: ...
-        @overload
-        def replace(self, old: str, new: str, /, count: SupportsIndex = -1) -> str: ...  # type: ignore[misc]
-    else:
-        @overload
-        def replace(
-            self: LiteralString, old: LiteralString, new: LiteralString, count: SupportsIndex = -1, /
-        ) -> LiteralString: ...
-        @overload
-        def replace(self, old: str, new: str, count: SupportsIndex = -1, /) -> str: ...  # type: ignore[misc]
-    if sys.version_info >= (3, 9):
-        @overload
-        def removeprefix(self: LiteralString, prefix: LiteralString, /) -> LiteralString: ...
-        @overload
-        def removeprefix(self, prefix: str, /) -> str: ...  # type: ignore[misc]
-        @overload
-        def removesuffix(self: LiteralString, suffix: LiteralString, /) -> LiteralString: ...
-        @overload
-        def removesuffix(self, suffix: str, /) -> str: ...  # type: ignore[misc]
-
-    def rfind(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
-    def rindex(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
-    @overload
-    def rjust(self: LiteralString, width: SupportsIndex, fillchar: LiteralString = " ", /) -> LiteralString: ...
-    @overload
-    def rjust(self, width: SupportsIndex, fillchar: str = " ", /) -> str: ...  # type: ignore[misc]
-    @overload
-    def rpartition(self: LiteralString, sep: LiteralString, /) -> tuple[LiteralString, LiteralString, LiteralString]: ...
-    @overload
-    def rpartition(self, sep: str, /) -> tuple[str, str, str]: ...  # type: ignore[misc]
-    @overload
-    def rsplit(self: LiteralString, sep: LiteralString | None = None, maxsplit: SupportsIndex = -1) -> list[LiteralString]: ...
-    @overload
-    def rsplit(self, sep: str | None = None, maxsplit: SupportsIndex = -1) -> list[str]: ...  # type: ignore[misc]
-    @overload
-    def rstrip(self: LiteralString, chars: LiteralString | None = None, /) -> LiteralString: ...
-    @overload
-    def rstrip(self, chars: str | None = None, /) -> str: ...  # type: ignore[misc]
-    @overload
-    def split(self: LiteralString, sep: LiteralString | None = None, maxsplit: SupportsIndex = -1) -> list[LiteralString]: ...
-    @overload
-    def split(self, sep: str | None = None, maxsplit: SupportsIndex = -1) -> list[str]: ...  # type: ignore[misc]
-    @overload
-    def splitlines(self: LiteralString, keepends: bool = False) -> list[LiteralString]: ...
-    @overload
-    def splitlines(self, keepends: bool = False) -> list[str]: ...  # type: ignore[misc]
-    def startswith(
-        self, prefix: str | tuple[str, ...], start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /
-    ) -> bool: ...
-    @overload
-    def strip(self: LiteralString, chars: LiteralString | None = None, /) -> LiteralString: ...
-    @overload
-    def strip(self, chars: str | None = None, /) -> str: ...  # type: ignore[misc]
-    @overload
-    def swapcase(self: LiteralString) -> LiteralString: ...
-    @overload
-    def swapcase(self) -> str: ...  # type: ignore[misc]
-    @overload
-    def title(self: LiteralString) -> LiteralString: ...
-    @overload
-    def title(self) -> str: ...  # type: ignore[misc]
-    def translate(self, table: _TranslateTable, /) -> str: ...
-    @overload
-    def upper(self: LiteralString) -> LiteralString: ...
-    @overload
-    def upper(self) -> str: ...  # type: ignore[misc]
-    @overload
-    def zfill(self: LiteralString, width: SupportsIndex, /) -> LiteralString: ...
-    @overload
-    def zfill(self, width: SupportsIndex, /) -> str: ...  # type: ignore[misc]
-    @staticmethod
-    @overload
-    def maketrans(x: dict[int, _T] | dict[str, _T] | dict[str | int, _T], /) -> dict[int, _T]: ...
-    @staticmethod
-    @overload
-    def maketrans(x: str, y: str, /) -> dict[int, int]: ...
-    @staticmethod
-    @overload
-    def maketrans(x: str, y: str, z: str, /) -> dict[int, int | None]: ...
-    @overload
-    def __add__(self: LiteralString, value: LiteralString, /) -> LiteralString: ...
-    @overload
-    def __add__(self, value: str, /) -> str: ...  # type: ignore[misc]
-    # Incompatible with Sequence.__contains__
-    def __contains__(self, key: str, /) -> bool: ...  # type: ignore[override]
-    def __eq__(self, value: object, /) -> bool: ...
-    def __ge__(self, value: str, /) -> bool: ...
-    @overload
-    def __getitem__(self: LiteralString, key: SupportsIndex | slice, /) -> LiteralString: ...
-    @overload
-    def __getitem__(self, key: SupportsIndex | slice, /) -> str: ...  # type: ignore[misc]
-    def __gt__(self, value: str, /) -> bool: ...
-    def __hash__(self) -> int: ...
-    @overload
-    def __iter__(self: LiteralString) -> Iterator[LiteralString]: ...
-    @overload
-    def __iter__(self) -> Iterator[str]: ...  # type: ignore[misc]
-    def __le__(self, value: str, /) -> bool: ...
-    def __len__(self) -> int: ...
-    def __lt__(self, value: str, /) -> bool: ...
-    @overload
-    def __mod__(self: LiteralString, value: LiteralString | tuple[LiteralString, ...], /) -> LiteralString: ...
-    @overload
-    def __mod__(self, value: Any, /) -> str: ...
-    @overload
-    def __mul__(self: LiteralString, value: SupportsIndex, /) -> LiteralString: ...
-    @overload
-    def __mul__(self, value: SupportsIndex, /) -> str: ...  # type: ignore[misc]
-    def __ne__(self, value: object, /) -> bool: ...
-    @overload
-    def __rmul__(self: LiteralString, value: SupportsIndex, /) -> LiteralString: ...
-    @overload
-    def __rmul__(self, value: SupportsIndex, /) -> str: ...  # type: ignore[misc]
-    def __getnewargs__(self) -> tuple[str]: ...
-
 class bytes(Sequence[int]):
```

</details>

And then ran red-knot on my
[typeshed-stats](https://github.com/AlexWaygood/typeshed-stats) project
using the command

```
cargo run -p red_knot -- check --project ../typeshed-stats --python-version="3.12" --verbose
```

I observed that the following logs were printed to the terminal, but
that each warning was only printed once (the desired behaviour):

```
INFO Python version: Python 3.12, platform: all
INFO Indexed 15 file(s)
INFO Could not find class `builtins.int` in typeshed on Python 3.12. Falling back to `Unknown` for the symbol instead.
INFO Could not find class `builtins.str` in typeshed on Python 3.12. Falling back to `Unknown` for the symbol instead.
```
2025-03-11 16:42:44 +00:00
Alex Waygood
989075dc16 [red-knot] Add tests asserting that KnownClass::to_instance() doesn't unexpectedly fallback to Type::Unknown with full typeshed stubs (#16608)
## Summary

One of the motivations in https://github.com/astral-sh/ruff/pull/16428
for panicking when the `test` or `debug_assertions` features are enabled
and a lookup of a `KnownClass` fails is that we've had some latent bugs
in our code where certain variants have been silently falling back to
`Unknown` in every typeshed lookup without us realising. But that in
itself isn't a great motivation for panicking in
`KnownClass::to_instance()`, since we can fairly easily add some tests
that assert that we don't unexpectedly fallback to `Unknown` for any
`KnownClass` variant. This PR adds those tests.

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-03-11 16:12:44 +00:00
Joey Bar
e8e24310fb [red-knot] Handle gradual intersection types in assignability (#16611)
## Summary

This mostly fixes #14899

My motivation was similar to the last comment by @sharkdp there. I ran
red_knot on a codebase and the most common error was patterns like this
failing:

```
def foo(x: str): ...

x: Any = ...
if isinstance(x, str):
    foo(x) # Object of type `Any & str` cannot be assigned to parameter 1 (`x`) of function `foo`; expected type `str`
```

The desired behavior is pretty much to ignore Any/Unknown when resolving
intersection assignability - `Any & str` should be assignable to `str`,
and `str` should be assignable to `str & Any`
 
The fix is actually very similar to the existing code in
`is_subtype_of`, we need to correctly handle intersections on either
side, while being careful to handle dynamic types as desired.

This does not fix the second test case from that issue:

```
static_assert(is_assignable_to(Intersection[Unrelated, Any], Not[tuple[Unrelated, Any]]))
```

but that's misleading because the root cause there has nothing to do
with gradual types. I added a simpler test case that also fails:

```
static_assert(is_assignable_to(Unrelated, Not[tuple[Unrelated]]))
```
This is because we don't determine that Unrelated does not subclass from
tuple so we can't rule out this relation. If that logic is improved then
this fix should also handle the case of the intersection

## Test Plan

Added a bunch of is_assignable_to tests, most of which failed before
this fix.
2025-03-11 07:58:56 -07:00
David Peter
3b497716f1 [red-knot] mypy_primer: split installation and execution (#16622)
## Summary

I noticed that the pipeline can succeed if there are problems with tool
installation or dependency resolution. This change makes sure that the
pipeline fails in these cases.
2025-03-11 13:06:04 +01:00
David Peter
0af4985067 [red-knot] mypy_primer: pipeline improvements (#16620)
## Summary

- Add comment to explain `sed` command
- Fix double reporting of diff
- Hide (large) diffs in `<details>`
2025-03-11 11:13:33 +01:00
Dhruv Manilawala
da069aa00c [red-knot] Infer lambda expression (#16547)
## Summary

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

This PR adds support for inferring the `lambda` expression and return
the `CallableType`.

Currently, this is only limited to inferring the parameters and a todo
type for the return type.

For posterity, I tried using the `file_expression_type` to infer the
return type of lambda but it would always lead to cycle. The main reason
is that in `infer_parameter_definition`, the default expression is being
inferred using `file_expression_type`, which is correct, but it then

Take the following source code as an example:
```py
lambda x=1: x
```

Here's how the code will flow:
* `infer_scope_types` for the global scope
* `infer_lambda_expression`
* `infer_expression` for the default value `1`
* `file_expression_type` for the return type using the body expression.
This is because the body creates it's own scope
* `infer_scope_types` (lambda body scope)
* `infer_name_load` for the symbol `x` whose visible binding is the
lambda parameter `x`
* `infer_parameter_definition` for parameter `x`
* `file_expression_type` for the default value `1`
* `infer_scope_types` for the global scope because of the default
expression

This will then reach to `infer_definition` for the parameter `x` again
which then creates the cycle.

## Test Plan

Add tests around `lambda` expression inference.
2025-03-11 11:25:20 +05:30
David Peter
ec9ee93d68 [red-knot] mypy_primer: strip ANSI codes (#16604)
## Summary

Strip ANSI codes in the mypy_primer diff before uploading.

## Test Plan

Successful run here: https://github.com/astral-sh/ruff/pull/16601
2025-03-10 17:32:01 +01:00
David Peter
a73548d0ca [red-knot] mypy_primer: comment on PRs (#16599)
## Summary

Add a new pipeline to comment on PRs if there is a mypy_primer diff
result.

## Test Plan

Not yet, I'm afraid I will have to merge this first to have the pipeline
available on main.
2025-03-10 15:25:42 +01:00
David Peter
c60e8a037a [red-knot] Add support for calling type[…] (#16597)
## Summary

This fixes the non-diagnostics part of #15948.

## Test Plan

New Markdown tests.

Negative diff on the ecosystem checks:

```diff
zipp (https://github.com/jaraco/zipp)
- error: lint:call-non-callable
-    --> /tmp/mypy_primer/projects/zipp/zipp/__init__.py:393:16
-     |
- 392 |     def _next(self, at):
- 393 |         return self.__class__(self.root, at)
-     |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Object of type `type[Unknown]` is not callable
- 394 |
- 395 |     def is_dir(self):
-     |
- 
- Found 9 diagnostics
+ Found 8 diagnostics

arrow (https://github.com/arrow-py/arrow)
+     |
+     |
+ warning: lint:unused-ignore-comment
+    --> /tmp/mypy_primer/projects/arrow/arrow/arrow.py:576:66
+ 574 |                 values.append(1)
+ 575 |
+ 576 |             floor = self.__class__(*values, tzinfo=self.tzinfo)  # type: ignore[misc]
+     |                                                                  -------------------- Unused blanket `type: ignore` directive
+ 577 |
+ 578 |             if frame_absolute == "week":
- error: lint:call-non-callable
-     --> /tmp/mypy_primer/projects/arrow/arrow/arrow.py:1080:16
-      |
- 1078 |           dt = self._datetime.astimezone(tz)
- 1079 |
- 1080 |           return self.__class__(
-      |  ________________^
- 1081 | |             dt.year,
- 1082 | |             dt.month,
- 1083 | |             dt.day,
- 1084 | |             dt.hour,
- 1085 | |             dt.minute,
- 1086 | |             dt.second,
- 1087 | |             dt.microsecond,
- 1088 | |             dt.tzinfo,
- 1089 | |             fold=getattr(dt, "fold", 0),
- 1090 | |         )
-      | |_________^ Object of type `type[Unknown]` is not callable
- 1091 |
- 1092 |       # string output and formatting
-      |

black (https://github.com/psf/black)
- 
-     |
-     |
- error: lint:call-non-callable
-    --> /tmp/mypy_primer/projects/black/src/blib2to3/pgen2/grammar.py:135:15
- 133 |         Copy the grammar.
- 134 |         """
- 135 |         new = self.__class__()
-     |               ^^^^^^^^^^^^^^^^ Object of type `type[@Todo]` is not callable
- 136 |         for dict_attr in (
- 137 |             "symbol2number",
- Found 328 diagnostics
+ Found 327 diagnostics
```
2025-03-10 13:24:13 +01:00
Dhruv Manilawala
f19cb86c5d Update migration guide with the new ruff.configuration (#16567)
## Summary

This PR updates the migration guide to use the new `ruff.configuration`
settings update to provide a better experience.

### Preview

<details><summary>Migration page screenshot</summary>
<p>

![Ruff Editors
Migration](https://github.com/user-attachments/assets/38062dbc-a4c5-44f1-8dba-53f7f5872d77)

</p>
</details>
2025-03-10 11:50:06 +00:00
David Peter
36d12cea47 [red-knot] Add 'mypy_primer' workflow (#16554)
## Summary

Run Red Knot on a small selection of ecosystem projects via a forked
version of `mypy_primer`.

Fork: https://github.com/astral-sh/mypy_primer
Branch: add-red-knot-support

## Test Plan

* Successful run:
https://github.com/astral-sh/ruff/actions/runs/13725319641/job/38390245552?pr=16554
* Intentially failed run where I commented out `unresolved-attribute`
diagnostics reporting:
https://github.com/astral-sh/ruff/actions/runs/13723777105/job/38385224144
2025-03-10 11:14:29 +01:00
renovate[bot]
a4396b3e6b Update Rust crate indoc to v2.0.6 (#16585)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [indoc](https://redirect.github.com/dtolnay/indoc) |
workspace.dependencies | patch | `2.0.5` -> `2.0.6` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/indoc (indoc)</summary>

###
[`v2.0.6`](https://redirect.github.com/dtolnay/indoc/releases/tag/2.0.6)

[Compare
Source](https://redirect.github.com/dtolnay/indoc/compare/2.0.5...2.0.6)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:26:02 +01:00
renovate[bot]
acfb920863 Update Rust crate syn to v2.0.100 (#16590)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [syn](https://redirect.github.com/dtolnay/syn) |
workspace.dependencies | patch | `2.0.98` -> `2.0.100` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/syn (syn)</summary>

###
[`v2.0.100`](https://redirect.github.com/dtolnay/syn/releases/tag/2.0.100)

[Compare
Source](https://redirect.github.com/dtolnay/syn/compare/2.0.99...2.0.100)

- Add `Visit::visit_token_stream`, `VisitMut::visit_token_stream_mut`,
`Fold::fold_token_stream` for processing TokenStream during syntax tree
traversals
([#&#8203;1852](https://redirect.github.com/dtolnay/syn/issues/1852))

###
[`v2.0.99`](https://redirect.github.com/dtolnay/syn/releases/tag/2.0.99)

[Compare
Source](https://redirect.github.com/dtolnay/syn/compare/2.0.98...2.0.99)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:25:53 +01:00
renovate[bot]
08c48b15af Update Rust crate thiserror to v2.0.12 (#16591)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [thiserror](https://redirect.github.com/dtolnay/thiserror) |
workspace.dependencies | patch | `2.0.11` -> `2.0.12` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/thiserror (thiserror)</summary>

###
[`v2.0.12`](https://redirect.github.com/dtolnay/thiserror/releases/tag/2.0.12)

[Compare
Source](https://redirect.github.com/dtolnay/thiserror/compare/2.0.11...2.0.12)

- Prevent elidable_lifetime_names pedantic clippy lint in generated impl
([#&#8203;413](https://redirect.github.com/dtolnay/thiserror/issues/413))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:25:40 +01:00
renovate[bot]
a7095c4196 Update Rust crate serde_json to v1.0.140 (#16589)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [serde_json](https://redirect.github.com/serde-rs/json) |
workspace.dependencies | patch | `1.0.139` -> `1.0.140` |

---

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

---

### Release Notes

<details>
<summary>serde-rs/json (serde_json)</summary>

###
[`v1.0.140`](https://redirect.github.com/serde-rs/json/releases/tag/v1.0.140)

[Compare
Source](https://redirect.github.com/serde-rs/json/compare/v1.0.139...v1.0.140)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:25:30 +01:00
renovate[bot]
e79f9171cf Update Rust crate quote to v1.0.39 (#16587)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [quote](https://redirect.github.com/dtolnay/quote) |
workspace.dependencies | patch | `1.0.38` -> `1.0.39` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/quote (quote)</summary>

###
[`v1.0.39`](https://redirect.github.com/dtolnay/quote/releases/tag/1.0.39)

[Compare
Source](https://redirect.github.com/dtolnay/quote/compare/1.0.38...1.0.39)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:25:21 +01:00
renovate[bot]
e517b44a0a Update Rust crate serde to v1.0.219 (#16588)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [serde](https://serde.rs)
([source](https://redirect.github.com/serde-rs/serde)) |
workspace.dependencies | patch | `1.0.218` -> `1.0.219` |

---

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

---

### Release Notes

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

###
[`v1.0.219`](https://redirect.github.com/serde-rs/serde/releases/tag/v1.0.219)

[Compare
Source](https://redirect.github.com/serde-rs/serde/compare/v1.0.218...v1.0.219)

- Prevent `absolute_paths` Clippy restriction being triggered inside
macro-generated code
([#&#8203;2906](https://redirect.github.com/serde-rs/serde/issues/2906),
thanks [@&#8203;davidzeng0](https://redirect.github.com/davidzeng0))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:25:07 +01:00
renovate[bot]
1275665ecb Update Rust crate proc-macro2 to v1.0.94 (#16586)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [proc-macro2](https://redirect.github.com/dtolnay/proc-macro2) |
workspace.dependencies | patch | `1.0.93` -> `1.0.94` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/proc-macro2 (proc-macro2)</summary>

###
[`v1.0.94`](https://redirect.github.com/dtolnay/proc-macro2/releases/tag/1.0.94)

[Compare
Source](https://redirect.github.com/dtolnay/proc-macro2/compare/1.0.93...1.0.94)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:24:43 +01:00
renovate[bot]
f2b41306d0 Update Rust crate anyhow to v1.0.97 (#16584)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [anyhow](https://redirect.github.com/dtolnay/anyhow) |
workspace.dependencies | patch | `1.0.96` -> `1.0.97` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/anyhow (anyhow)</summary>

###
[`v1.0.97`](https://redirect.github.com/dtolnay/anyhow/releases/tag/1.0.97)

[Compare
Source](https://redirect.github.com/dtolnay/anyhow/compare/1.0.96...1.0.97)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:24:34 +01:00
renovate[bot]
b02a42d99a Update dependency ruff to v0.9.10 (#16593)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ruff](https://docs.astral.sh/ruff)
([source](https://redirect.github.com/astral-sh/ruff),
[changelog](https://redirect.github.com/astral-sh/ruff/blob/main/CHANGELOG.md))
| `==0.9.9` -> `==0.9.10` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/ruff/0.9.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/ruff/0.9.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/ruff/0.9.9/0.9.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/ruff/0.9.9/0.9.10?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>astral-sh/ruff (ruff)</summary>

###
[`v0.9.10`](https://redirect.github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#0910)

[Compare
Source](https://redirect.github.com/astral-sh/ruff/compare/0.9.9...0.9.10)

##### Preview features

- \[`ruff`] Add new rule `RUF059`: Unused unpacked assignment
([#&#8203;16449](https://redirect.github.com/astral-sh/ruff/pull/16449))
- \[`syntax-errors`] Detect assignment expressions before Python 3.8
([#&#8203;16383](https://redirect.github.com/astral-sh/ruff/pull/16383))
- \[`syntax-errors`] Named expressions in decorators before Python 3.9
([#&#8203;16386](https://redirect.github.com/astral-sh/ruff/pull/16386))
- \[`syntax-errors`] Parenthesized keyword argument names after Python
3.8
([#&#8203;16482](https://redirect.github.com/astral-sh/ruff/pull/16482))
- \[`syntax-errors`] Positional-only parameters before Python 3.8
([#&#8203;16481](https://redirect.github.com/astral-sh/ruff/pull/16481))
- \[`syntax-errors`] Tuple unpacking in `return` and `yield` before
Python 3.8
([#&#8203;16485](https://redirect.github.com/astral-sh/ruff/pull/16485))
- \[`syntax-errors`] Type parameter defaults before Python 3.13
([#&#8203;16447](https://redirect.github.com/astral-sh/ruff/pull/16447))
- \[`syntax-errors`] Type parameter lists before Python 3.12
([#&#8203;16479](https://redirect.github.com/astral-sh/ruff/pull/16479))
- \[`syntax-errors`] `except*` before Python 3.11
([#&#8203;16446](https://redirect.github.com/astral-sh/ruff/pull/16446))
- \[`syntax-errors`] `type` statements before Python 3.12
([#&#8203;16478](https://redirect.github.com/astral-sh/ruff/pull/16478))

##### Bug fixes

- Escape template filenames in glob patterns in configuration
([#&#8203;16407](https://redirect.github.com/astral-sh/ruff/pull/16407))
- \[`flake8-simplify`] Exempt unittest context methods for `SIM115` rule
([#&#8203;16439](https://redirect.github.com/astral-sh/ruff/pull/16439))
- Formatter: Fix syntax error location in notebooks
([#&#8203;16499](https://redirect.github.com/astral-sh/ruff/pull/16499))
- \[`pyupgrade`] Do not offer fix when at least one target is
`global`/`nonlocal` (`UP028`)
([#&#8203;16451](https://redirect.github.com/astral-sh/ruff/pull/16451))
- \[`flake8-builtins`] Ignore variables matching module attribute names
(`A001`)
([#&#8203;16454](https://redirect.github.com/astral-sh/ruff/pull/16454))
- \[`pylint`] Convert `code` keyword argument to a positional argument
in fix for (`PLR1722`)
([#&#8203;16424](https://redirect.github.com/astral-sh/ruff/pull/16424))

##### CLI

- Move rule code from `description` to `check_name` in GitLab output
serializer
([#&#8203;16437](https://redirect.github.com/astral-sh/ruff/pull/16437))

##### Documentation

- \[`pydocstyle`] Clarify that `D417` only checks docstrings with an
arguments section
([#&#8203;16494](https://redirect.github.com/astral-sh/ruff/pull/16494))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:24:24 +01:00
renovate[bot]
79443d71eb Update Rust crate unicode-ident to v1.0.18 (#16592)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [unicode-ident](https://redirect.github.com/dtolnay/unicode-ident) |
workspace.dependencies | patch | `1.0.17` -> `1.0.18` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/unicode-ident (unicode-ident)</summary>

###
[`v1.0.18`](https://redirect.github.com/dtolnay/unicode-ident/releases/tag/1.0.18)

[Compare
Source](https://redirect.github.com/dtolnay/unicode-ident/compare/1.0.17...1.0.18)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODUuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4NS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 09:23:32 +01:00
David Peter
ca974706dd [red-knot] Do not ignore typeshed stubs for 'venv' module (#16596)
## Summary

We currently fail to add the stubs for the `venv` stdlib module because
there is a `venv/` ignore pattern in the top-level `.gitignore` file.

## Test Plan

Ran the typeshed sync workflow manually once to see if the `venv/`
folder is now correctly added.
2025-03-10 09:07:48 +01:00
Alex Waygood
b6c7ba4f8e [red-knot] Reduce Salsa lookups in Type::find_name_in_mro (#16582)
## Summary

Theoretically this should be slightly more performant, since the
`class.is_known()` calls each do a separate Salsa lookup, which we can
avoid if we do a single `match` on the value of `class.known()`. It also
ends up being two lines less code overall!

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-03-10 07:55:22 +01:00
Alex Waygood
c970b794d0 Fix broken red-knot property tests (#16574)
## Summary

Fixes #16566, fixes #16575

The semantics of `Type::class_member` changed in
https://github.com/astral-sh/ruff/pull/16416, but the property-test
infrastructure was not updated. That means that the property tests were
panicking on the second `expect_type` call here:


0361021863/crates/red_knot_python_semantic/src/types/property_tests.rs (L151-L158)

With the somewhat unhelpful message:

```
Expected a (possibly unbound) type, not an unbound symbol
```

Applying this patch, and then running `QUICKCHECK_TESTS=1000000 cargo
test --release -p red_knot_python_semantic -- --ignored
types::property_tests::stable::equivalent_to_is_reflexive` showed
clearly that it was no longer able to find _any_ methods on _any_
classes due to the change in semantics of `Type::class_member`:

```diff
--- a/crates/red_knot_python_semantic/src/types/property_tests.rs
+++ b/crates/red_knot_python_semantic/src/types/property_tests.rs
@@ -27,7 +27,7 @@
 use std::sync::{Arc, Mutex, MutexGuard, OnceLock};
 
 use crate::db::tests::{setup_db, TestDb};
-use crate::symbol::{builtins_symbol, known_module_symbol};
+use crate::symbol::{builtins_symbol, known_module_symbol, Symbol};
 use crate::types::{
     BoundMethodType, CallableType, IntersectionBuilder, KnownClass, KnownInstanceType,
     SubclassOfType, TupleType, Type, UnionType,
@@ -150,10 +150,11 @@ impl Ty {
             Ty::BuiltinsFunction(name) => builtins_symbol(db, name).symbol.expect_type(),
             Ty::BuiltinsBoundMethod { class, method } => {
                 let builtins_class = builtins_symbol(db, class).symbol.expect_type();
-                let function = builtins_class
-                    .class_member(db, method.into())
-                    .symbol
-                    .expect_type();
+                let Symbol::Type(function, ..) =
+                    builtins_class.class_member(db, method.into()).symbol
+                else {
+                    panic!("no method `{method}` on class `{class}`");
+                };
 
                 create_bound_method(db, function, builtins_class)
             }
```

This PR updates the property-test infrastructure to use `Type::member`
rather than `Type::class_member`.

## Test Plan

- Ran `QUICKCHECK_TESTS=1000000 cargo test --release -p
red_knot_python_semantic -- --ignored types::property_tests::stable`
successfully
- Checked that there were no remaining uses of `Type::class_member` in
`property_tests.rs`
2025-03-09 17:40:08 +00:00
Alex Waygood
335b264fe2 [red-knot] Consistent spelling of "metaclass" and "meta-type" (#16576)
## Summary

Fixes a small nit of mine -- we are currently inconsistent in our
spelling between "metaclass" and "meta class", and between "meta type"
and "meta-type". This PR means that we consistently use "metaclass" and
"meta-type".

## Test Plan

`uvx pre-commit run -a`
2025-03-09 12:30:32 +00:00
Dhruv Manilawala
0361021863 [red-knot] Understand typing.Callable (#16493)
## Summary

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

This PR implements a general callable type that wraps around a
`Signature` and it uses that new type to represent `typing.Callable`.

It also implements `Display` support for `Callable`. The format is as:
```
([<arg name>][: <arg type>][ = <default type>], ...) -> <return type>
```

The `/` and `*` separators are added at the correct boundary for
positional-only and keyword-only parameters. Now, as `typing.Callable`
only has positional-only parameters, the rendered signature would be:

```py
Callable[[int, str], None]
# (int, str, /) -> None
```

The `/` separator represents that all the arguments are positional-only.

The relationship methods that check assignability, subtype relationship,
etc. are not yet implemented and will be done so as a follow-up.

## Test Plan

Add test cases for display support for `Signature` and various mdtest
for `typing.Callable`.
2025-03-08 03:58:52 +00:00
Eric Mark Martin
24c8b1242e [red-knot] Support unpacking with target (#16469)
## Summary

Resolves #16365

Add support for unpacking `with` statement targets.

## Test Plan

Added some test cases, alike the ones added by #15058.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-08 02:36:35 +00:00
David Peter
820a31af5d [red-knot] Attribute access and the descriptor protocol (#16416)
## Summary

* Attributes/method are now properly looked up on metaclasses, when
called on class objects
* We properly distinguish between data descriptors and non-data
descriptors (but we do not yet support them in store-context, i.e.
`obj.data_descr = …`)
* The descriptor protocol is now implemented in a single unified place
for instances, classes and dunder-calls. Unions and possibly-unbound
symbols are supported in all possible stages of the process by creating
union types as results.
* In general, the handling of "possibly-unbound" symbols has been
improved in a lot of places: meta-class attributes, attributes,
descriptors with possibly-unbound `__get__` methods, instance
attributes, …
* We keep track of type qualifiers in a lot more places. I anticipate
that this will be useful if we import e.g. `Final` symbols from other
modules (see relevant change to typing spec:
https://github.com/python/typing/pull/1937).
* Detection and special-casing of the `typing.Protocol` special form in
order to avoid lots of changes in the test suite due to new `@Todo`
types when looking up attributes on builtin types which have `Protocol`
in their MRO. We previously
looked up attributes in a wrong way, which is why this didn't come up
before.

closes #16367
closes #15966

## Context

The way attribute lookup in `Type::member` worked before was simply
wrong (mostly my own fault). The whole instance-attribute lookup should
probably never have been integrated into `Type::member`. And the
`Type::static_member` function that I introduced in my last descriptor
PR was the wrong abstraction. It's kind of fascinating how far this
approach took us, but I am pretty confident that the new approach
proposed here is what we need to model this correctly.

There are three key pieces that are required to implement attribute
lookups:

- **`Type::class_member`**/**`Type::find_in_mro`**: The
`Type::find_in_mro` method that can look up attributes on class bodies
(and corresponding bases). This is a partial function on types, as it
can not be called on instance types like`Type::Instance(…)` or
`Type::IntLiteral(…)`. For this reason, we usually call it through
`Type::class_member`, which is essentially just
`type.to_meta_type().find_in_mro(…)` plus union/intersection handling.
- **`Type::instance_member`**: This new function is basically the
type-level equivalent to `obj.__dict__[name]` when called on
`Type::Instance(…)`. We use this to discover instance attributes such as
those that we see as declarations on class bodies or as (annotated)
assignments to `self.attr` in methods of a class.
- The implementation of the descriptor protocol. It works slightly
different for instances and for class objects, but it can be described
by the general framework:
- Call `type.class_member("attribute")` to look up "attribute" in the
MRO of the meta type of `type`. Call the resulting `Symbol` `meta_attr`
(even if it's unbound).
- Use `meta_attr.class_member("__get__")` to look up `__get__` on the
*meta type* of `meta_attr`. Call it with `__get__(meta_attr, self,
self.to_meta_type())`. If this fails (either the lookup or the call),
just proceed with `meta_attr`. Otherwise, replace `meta_attr` in the
following with the return type of `__get__`. In this step, we also probe
if a `__set__` or `__delete__` method exists and store it in
`meta_attr_kind` (can be either "data descriptor" or "normal attribute
or non-data descriptor").
  - Compute a `fallback` type.
    - For instances, we use `self.instance_member("attribute")`
- For class objects, we use `class_attr =
self.find_in_mro("attribute")`, and then try to invoke the descriptor
protocol on `class_attr`, i.e. we look up `__get__` on the meta type of
`class_attr` and call it with `__get__(class_attr, None, self)`. This
additional invocation of the descriptor protocol on the fallback type is
one major asymmetry in the otherwise universal descriptor protocol
implementation.
- Finally, we look at `meta_attr`, `meta_attr_kind` and `fallback`, and
handle various cases of (possible) unboundness of these symbols.
- If `meta_attr` is bound and a data descriptor, just return `meta_attr`
- If `meta_attr` is not a data descriptor, and `fallback` is bound, just
return `fallback`
- If `meta_attr` is not a data descriptor, and `fallback` is unbound,
return `meta_attr`
- Return unions of these three possibilities for partially-bound
symbols.

This allows us to handle class objects and instances within the same
framework. There is a minor additional detail where for instances, we do
not allow the fallback type (the instance attribute) to completely
shadow the non-data descriptor. We do this because we (currently) don't
want to pretend that we can statically infer that an instance attribute
is always set.

Dunder method calls can also be embedded into this framework. The only
thing that changes is that *there is no fallback type*. If a dunder
method is called on an instance, we do not fall back to instance
variables. If a dunder method is called on a class object, we only look
it up on the meta class, never on the class itself.

## Test Plan

New Markdown tests.
2025-03-07 22:03:28 +01:00
InSync
a18d8bfa7d [pep8-naming] Add links to ignore-names options in various rules' documentation (#16557)
## Summary

Resolves #16551.

All rules using
[`lint.pep8-naming.ignore-names`](https://docs.astral.sh/ruff/settings/#lint_pep8-naming_ignore-names)
and
[`lint.pep8-naming.extend-ignore-names`](https://docs.astral.sh/ruff/settings/#lint_pep8-naming_extend-ignore-names)
now have their documentation linked to these two options.

## Test Plan

None.
2025-03-07 14:49:08 -05:00
Shunsuke Shibayama
348c196cb3 [red-knot] avoid inferring types if unpacking fails (#16530)
## Summary

This PR closes #15199.

The change I just made is to set all variables to type `Unknown` if
unpacking fails, but in some cases this may be excessive.
For example:

```py
a, b, c = "ab"
reveal_type(a)  # Unknown, but it would be reasonable to think of it as LiteralString
reveal_type(c)  # Unknown
```

```py
# Failed to unpack before the starred expression
(a, b, *c, d, e) = (1,)
reveal_type(a)  # Unknown
reveal_type(b)  # Unknown
...
# Failed to unpack after the starred expression
(a, b, *c, d, e) = (1, 2, 3)
reveal_type(a)  # Unknown, but should it be Literal[1]?
reveal_type(b)  # Unknown, but should it be Literal[2]?
reveal_type(c)  # Todo
reveal_type(d)  # Unknown
reveal_type(e)  # Unknown
```

I will modify it if you think it would be better to make it a different
type than just `Unknown`.

## Test Plan

I have made appropriate modifications to the test cases affected by this
change, and also added some more test cases.
2025-03-07 11:04:44 -08:00
Vasco Schiavo
6d6e524b90 [flake8-bandit] Fix mixed-case hash algorithm names (S324) (#16552)
The PR solves issue #16525
2025-03-07 15:21:07 +00:00
Dylan
0dfa810e9a Bump 0.9.10 (#16556) 2025-03-07 09:00:08 -06:00
Micha Reiser
9cd0cdefd3 Assert that formatted code doesn't introduce any new unsupported syntax errors (#16549)
## Summary

This should give us better coverage for the unsupported syntax error
features and
increases our confidence that the formatter doesn't accidentially
introduce new unsupported
syntax errors. 

A feature like this would have been very useful when working on f-string
formatting
where it took a lot of iteration to find all Python 3.11 or older
incompatibilities.

## Test Plan

I applied my changes on top of
https://github.com/astral-sh/ruff/pull/16523 and
removed the target version check in the with-statement formatting code.
As expected,
the integration tests now failed
2025-03-07 09:12:00 +01:00
Eric Mark Martin
05a4c29344 print MDTEST_TEST_FILTER value in single-quotes (and escaped) (#16548)
<!--
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? -->

If an mdtest fails, the error output will include an example command
that can be run to re-run just the failing test, e.g

```
To rerun this specific test, set the environment variable: MDTEST_TEST_FILTER="sync.md - With statements - Context manager with non-callable `__exit__` attribute"
MDTEST_TEST_FILTER="sync.md - With statements - Context manager with non-callable `__exit__` attribute" cargo test -p red_knot_python_semantic --test mdtest -- mdtest__with_sync
```
This is very helpful, but because we're printing the envvar value
surrounded in double-quotes, the bits between backticks in this example
get interpreted as a shell interpolation. When running this in zsh, for
example, I see

```console
❯ MDTEST_TEST_FILTER="sync.md - With statements - Context manager with non-callable `__exit__` attribute" cargo test -p red_knot_python_semantic --test mdtest -- mdtest__with_sync  
zsh: command not found: __exit__
   Compiling red_knot_python_semantic v0.0.0 (/home/ericmarkmartin/Development/ruff/crates/red_knot_python_semantic)
   Compiling red_knot_test v0.0.0 (/home/ericmarkmartin/Development/ruff/crates/red_knot_test)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 6.09s
     Running tests/mdtest.rs (target/debug/deps/mdtest-149b8f9d937e36bc)

running 1 test
test mdtest__with_sync ... ok
```
[^1]

This is a minor annoyance which we can solve by using single-quotes
instead of double-quotes for this string. To do so safely, we also
escape single-quotes possibly contained within the string.

There is a [shell-quote](https://github.com/allenap/shell-quote) crate,
which seems to handle all this escaping stuff for you but fixing this
issue perfectly isn't a big deal (if there are more things to escape we
can deal with it then), so adding a new dependency (even a dev one)
seemed overkill.

[^1]: The filter does still work---it turns out that the filter
`MDTEST_TEST_FILTER="sync.md - With statements - Context manager with
non-callable attribute"` (what you get after the failed interpolation)
is still good enough

## Test Plan
<!-- How was it tested? -->

I broke the ``## Context manager with non-callable `__exit__`
attribute`` test by deleting the error assertion, then successfully ran
the new command it printed out.
2025-03-07 09:04:52 +01:00
Brent Westbrook
b3c884f4f3 [syntax-errors] Parenthesized keyword argument names after Python 3.8 (#16482)
Summary
--

Unlike the other syntax errors detected so far, parenthesized keyword
arguments are only allowed *before* 3.8. It sounds like they were only
accidentally allowed before that [^1].

As an aside, you get a pretty confusing error from Python for this, so
it's nice that we can catch it:

```pycon
>>> def f(**kwargs): ...
... f((a)=1)
...
  File "<python-input-0>", line 2
    f((a)=1)
       ^^^
SyntaxError: expression cannot contain assignment, perhaps you meant "=="?
>>>
```
Test Plan
--
Inline tests.

[^1]: https://github.com/python/cpython/issues/78822
2025-03-06 12:18:13 -05:00
Brent Westbrook
6c14225c66 [syntax-errors] Tuple unpacking in return and yield before Python 3.8 (#16485)
Summary
--

Checks for tuple unpacking in `return` and `yield` statements before
Python 3.8, as described [here].

Test Plan
--
Inline tests.

[here]: https://github.com/python/cpython/issues/76298
2025-03-06 11:57:20 -05:00
David Peter
0a627ef216 [red-knot] Never is callable and iterable. Arbitrary attributes can be accessed. (#16533)
## Summary

- `Never` is callable
- `Never` is iterable
- Arbitrary attributes can be accessed on `Never`

Split out from #16416 that is going to be required.

## Test Plan

Tests for all properties above.
2025-03-06 15:59:19 +00:00
Micha Reiser
a25be4610a Clarify that D417 only checks docstrings with an arguments section (#16494)
## Summary

This came up in https://github.com/astral-sh/ruff/issues/16477

It's not obvious from the D417 rule's documentation that it only checks
docstrings
with an arguments section. Functions without such a section aren't
checked.

This PR tries to make this clearer in the documentation.
2025-03-06 09:49:35 +00:00
Micha Reiser
ce0018c3cb Add OsSystem support to mdtests (#16518)
## Summary

This PR introduces a new mdtest option `system` that can either be
`in-memory` or `os`
where `in-memory` is the default.

The motivation for supporting `os` is so that we can write OS/system
specific tests
with mdtests. Specifically, I want to write mdtests for the module
resolver,
testing that module resolution is case sensitive. 

## Test Plan

I tested that the case-sensitive module resolver test start failing when
setting `system = "os"`
2025-03-06 10:41:40 +01:00
Micha Reiser
48f906e06c Add tests for case-sensitive module resolution (#16517)
## Summary

Python's module resolver is case sensitive. 

This PR adds mdtests that assert that our module resolution is case
sensitive.

The tests currently all pass because our in memory file system is case
sensitive.
I'll add support for using the real file system to the mdtest framework
in a separate PR.

This PR also adds support for specifying extra search paths to the
mdtest framework.

## Test Plan
The tests fail when running them using the real file system.
2025-03-06 10:19:23 +01:00
Douglas Creager
ebd172e732 [red-knot] Several failing tests for generics (#16509)
To kick off the work of supporting generics, this adds many new
(currently failing) tests, showing the behavior we plan to support.

This is still missing a lot!  Not included:

- typevar tuples
- param specs
- variance
- `Self`

But it's a good start! We can add more failing tests for those once we
tackle these.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-05 17:21:19 -05:00
Carl Meyer
114abc7cfb [red-knot] support empty TypeInference with fallback type (#16510)
This is split out of https://github.com/astral-sh/ruff/pull/14029, to
reduce the size of that PR, and to validate that this "fallback type"
support in `TypeInference` doesn't come with a performance cost. It also
improves the reliability and debuggability of our current (temporary)
cycle handling.

In order to recover from a cycle, we have to be able to construct a
"default" `TypeInference` where all expressions and definitions have
some "default" type. In our current cycle handling, this "default" type
is just unknown or a todo type. With fixpoint iteration, the "default"
type will be `Type::Never`, which is the "bottom" type that fixpoint
iteration starts from.

Since it would be costly (both in space and time) to actually enumerate
all expressions and definitions in a scope, just to insert the same
default type for all of them, instead we add an optional "missing type"
fallback to `TypeInference`, which (if set) is the fallback type for any
expression or definition which doesn't have an explicit type set.

With this change, cycles can no longer result in the dreaded "Missing
key" errors looking up the type of some expression.
2025-03-05 09:12:27 -08:00
Brent Westbrook
318f503714 [syntax-errors] Named expressions in decorators before Python 3.9 (#16386)
Summary
--

This PR detects the relaxed grammar for decorators proposed in [PEP
614](https://peps.python.org/pep-0614/) on Python 3.8 and lower.

The 3.8 grammar for decorators is
[here](https://docs.python.org/3.8/reference/compound_stmts.html#grammar-token-decorators):

```
decorators                ::=  decorator+
decorator                 ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
dotted_name               ::=  identifier ("." identifier)*
```

in contrast to the current grammar
[here](https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-decorators)

```
decorators                ::= decorator+
decorator                 ::= "@" assignment_expression NEWLINE
assignment_expression ::= [identifier ":="] expression
```

Test Plan
--

New inline parser tests.
2025-03-05 17:08:18 +00:00
Brent Westbrook
d0623888b3 [syntax-errors] Positional-only parameters before Python 3.8 (#16481)
Summary
--

Detect positional-only parameters before Python 3.8, as marked by the
`/` separator in a parameter list.

Test Plan
--
Inline tests.
2025-03-05 13:46:43 +00:00
Shaygan Hooshyari
23fd4927ae Auto generate ast expression nodes (#16285)
## Summary

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

- Auto generate AST nodes using definitions in `ast.toml`. I added
attributes similar to
[`Field`](https://github.com/python/cpython/blob/main/Parser/asdl.py#L67)
in ASDL to hold field information

## Test Plan

Nothing outside the `ruff_python_ast` package should change.

---------

Co-authored-by: Douglas Creager <dcreager@dcreager.net>
2025-03-05 08:25:55 -05:00
Andrew Gallant
cc324abcc2 ruff_db: add new Diagnostic type
... with supporting types. This is meant to give us a base to work with
in terms of our new diagnostic data model. I expect the representations
to be tweaked over time, but I think this is a decent start.

I would also like to add doctest examples, but I think it's better if we
wait until an initial version of the renderer is done for that.
2025-03-05 08:23:02 -05:00
Andrew Gallant
80be0a0115 ruff_db: move ParseDiagnostic to old submodule too
This should have been with the previous two commits, but I missed it.
2025-03-05 08:23:02 -05:00
Andrew Gallant
b2e90c3f5c ruff_db: rename ParseDiagnostic to OldParseDiagnostic
I missed this in the previous commits.
2025-03-05 08:23:02 -05:00
Andrew Gallant
d7cbe6b7df ruff_db: move old types into their own sub-module
This puts them out of the way so that they can hopefully be removed more
easily in the (near) future, and so that they don't get in the way of
the new types. This also makes the intent of the migration a bit clearer
in the code and hopefully results in less confusion.
2025-03-05 08:23:02 -05:00
Andrew Gallant
021640a7a6 ruff_db: rename Diagnostic to OldDiagnosticTrait
This trait should eventually go away, so we rename it (and supporting
types) to make room for a new concrete `Diagnostic` type.

This commit is just the rename. In the next commit, we'll move it to a
different module.
2025-03-05 08:23:02 -05:00
Brent Westbrook
81bcdcebd3 [syntax-errors] Type parameter lists before Python 3.12 (#16479)
Summary
--

Another simple one, just detect type parameter lists in functions
and classes. Like pyright, we don't emit a second diagnostic for
`type` alias statements, which were also introduced in 3.12.

Test Plan
--
Inline tests.
2025-03-05 13:19:09 +00:00
Dhruv Manilawala
d94a78a134 [red-knot] De-duplicate symbol table query (#16515)
## Summary

This PR does a small refactor to avoid double
`symbol_table(...).symbol(...)` call to check for `__slots__` and
`TYPE_CHECKING`. It merges them into a single call.

I noticed this while looking at
https://github.com/astral-sh/ruff/pull/16468.
2025-03-05 07:36:21 +00:00
Shunsuke Shibayama
bb44926ca5 [red-knot] Add rule invalid-type-checking-constant (#16501)
## Summary

This PR adds more features to #16468.

* Adds a new error rule `invalid-type-checking-constant`, which occurs
when we try to assign a value other than `False` to a user-defined
`TYPE_CHECKING` variable (it is possible to assign `...` in a stub
file).
* Allows annotated assignment to `TYPE_CHECKING`. Only types that
`False` can be assigned to are allowed. However, the type of
`TYPE_CHECKING` will be inferred to be `Literal[True]` regardless of
what the type is specified.

## Test plan

I ran the tests with `cargo test -p red_knot_python_semantic` and
confirmed that all tests passed.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-04 19:49:34 +00:00
Brent Westbrook
32c66ec4b7 [syntax-errors] type alias statements before Python 3.12 (#16478)
Summary
--
Another simple one, just detect standalone `type` statements. I limited
the diagnostic to `type` itself like [pyright]. That probably makes the
most sense for more complicated examples.

Test Plan
--
Inline tests.

[pyright]:
https://pyright-play.net/?pythonVersion=3.8&strict=true&code=C4TwDgpgBAHlC8UCWA7YQ
2025-03-04 17:20:10 +00:00
Micha Reiser
087d92cbf4 Formatter: Fix syntax error location in notebooks (#16499)
## Summary

Fixes https://github.com/astral-sh/ruff/issues/16476
fixes: #11453

We format notebooks cell by cell. That means, that offsets in parse
errors are relative
to the cell and not the entire document. We didn't account for this fact
when emitting syntax errors for notebooks in the formatter. 

This PR ensures that we correctly offset parse errors by the cell
location.

## Test Plan

Added test (it panicked before)
2025-03-04 18:00:31 +01:00
Brent Westbrook
e7b93f93ef [syntax-errors] Type parameter defaults before Python 3.13 (#16447)
Summary
--

Detects the presence of a [PEP 696] type parameter default before Python
3.13.

Test Plan
--

New inline parser tests for type aliases, generic functions and generic
classes.

[PEP 696]: https://peps.python.org/pep-0696/#grammar-changes
2025-03-04 16:53:38 +00:00
Brent Westbrook
c8a06a9be8 [syntax-errors] Limit except* range to * (#16473)
Summary
--
This is a follow-up to #16446 to fix the diagnostic range to point to
the `*` like `pyright` does
(https://github.com/astral-sh/ruff/pull/16446#discussion_r1976900643).

Storing the range in the `ExceptClauseKind::Star` variant feels slightly
awkward, but we don't store the star itself anywhere on the
`ExceptHandler`. And we can't just take `ExceptHandler.start() +
"except".text_len()` because this code appears to be valid:

```python
try: ...
except    *    Error: ...
```

Test Plan
--
Existing tests.
2025-03-04 16:50:09 +00:00
Shunsuke Shibayama
1977dda079 [red-knot] respect TYPE_CHECKING even if not imported from typing (#16468)
## Summary

This PR closes #15722.

The change is that if the variable `TYPE_CHECKING` is defined/imported,
the type of the variable is interpreted as `Literal[True]` regardless of
what the value is.
This is compatible with the behavior of other type checkers (e.g. mypy,
pyright).

## Test Plan

I ran the tests with `cargo test -p red_knot_python_semantic` and
confirmed that all tests passed.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-03-04 07:58:29 -08:00
Charlie Marsh
c9ab925275 Pull in fonts from a CDN (#16498)
## Summary

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

## Test Plan

![Screenshot 2025-03-04 at 9 20
08 AM](https://github.com/user-attachments/assets/be6cae37-3fa8-4914-9c6b-95c959cd597e)
2025-03-04 09:36:35 -05:00
Brent Westbrook
37fbe58b13 Document LinterResult::has_syntax_error and add Parsed::has_no_syntax_errors (#16443)
Summary
--

This is a follow up addressing the comments on #16425. As @dhruvmanila
pointed out, the naming is a bit tricky. I went with `has_no_errors` to
try to differentiate it from `is_valid`. It actually ends up negated in
most uses, so it would be more convenient to have `has_any_errors` or
`has_errors`, but I thought it would sound too much like the opposite of
`is_valid` in that case. I'm definitely open to suggestions here.

Test Plan
--

Existing tests.
2025-03-04 08:35:38 -05:00
InSync
a3ae76edc0 [pyupgrade] Do not offer fix when at least one target is global/nonlocal (UP028) (#16451)
## Summary

Resolves #16445.

`UP028` is now no longer always fixable: it will not offer a fix when at
least one `ExprName` target is bound to either a `global` or a
`nonlocal` declaration.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-03-04 11:28:01 +01:00
Brent Westbrook
d93ed293eb Escape template filenames in glob patterns (#16407)
## Summary

Fixes #9381. This PR fixes errors like 

```
Cause: error parsing glob '/Users/me/project/{{cookiecutter.project_dirname}}/__pycache__': nested alternate groups are not allowed
```

caused by glob special characters in filenames like
`{{cookiecutter.project_dirname}}`. When the user is matching that
directory exactly, they can use the workaround given by
https://github.com/astral-sh/ruff/issues/7959#issuecomment-1764751734,
but that doesn't work for a nested config file with relative paths. For
example, the directory tree in the reproduction repo linked
[here](https://github.com/astral-sh/ruff/issues/9381#issuecomment-2677696408):

```
.
├── README.md
├── hello.py
├── pyproject.toml
├── uv.lock
└── {{cookiecutter.repo_name}}
    ├── main.py
    ├── pyproject.toml
    └── tests
        └── maintest.py
```

where the inner `pyproject.toml` contains a relative glob:

```toml
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["F811"]
```

## Test Plan

A new CLI test in both the linter and formatter. The formatter test may
not be necessary because I didn't have to modify any additional code to
pass it, but the original report mentioned both `check` and `format`, so
I wanted to be sure both were fixed.
2025-03-03 09:29:58 -05:00
Vasco Schiavo
4d92e20e81 [pylint] Convert a code keyword argument to a positional argument (PLR1722) (#16424)
The PR addresses issue #16396 .

Specifically:

- If the exit statement contains a code keyword argument, it is
converted into a positional argument.
- If retrieving the code from the exit statement is not possible, a
violation is raised without suggesting a fix.

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-03-03 09:20:57 -05:00
Micha Reiser
c4578162d5 [red-knot] Add support for knot check <paths> (#16375)
## Summary

This PR adds support for an optional list of paths that should be
checked to `knot check`.

E.g. to only check the `src` directory

```sh
knot check src
```

The default is to check all files in the project but users can reduce
the included files by specifying one or multiple optional paths.

The main two challenges with adding this feature were:

* We now need to show an error when one of the provided paths doesn't
exist. That's why this PR now collects errors from the project file
indexing phase and adds them to the output diagnostics. The diagnostic
looks similar to ruffs (see CLI test)
* The CLI should pick up new files added to included folders. For
example, `knot check src --watch` should pick up new files that are
added to the `src` folder. This requires that we now filter the files
before adding them to the project. This is a good first step to
supporting `include` and `exclude`.


The PR makes two simplifications:

1. I didn't test the changes with case-insensitive file systems. We may
need to do some extra path normalization to support those well. See
https://github.com/astral-sh/ruff/issues/16400
2. Ideally, we'd accumulate the IO errors from the initial indexing
phase and subsequent incremental indexing operations. For example, we
should preserve the IO diagnostic for a non existing `test.py` if it was
specified as an explicit CLI argument until the file gets created and we
should show it again when the file gets deleted. However, this is
somewhat complicated because we'd need to track which files we revisited
(or were removed because the entire directory is gone). I considered
this too low a priority as it's worth dealing with right now.

The implementation doesn't support symlinks within the project but that
is the same as Ruff and is unchanged from before this PR.



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

## Test Plan

Added CLI and file watching integration tests. Manually testing.
2025-03-03 12:59:56 +00:00
Vasco Schiavo
5d56c2e877 [flake8-builtins] Ignore variables matching module attribute names (A001) (#16454)
This PR (partially) addresses issue #16373
2025-03-03 11:10:23 +01:00
Jelle Zijlstra
c80678a1c0 Add new rule RUF059: Unused unpacked assignment (#16449)
Split from F841 following discussion in #8884.

Fixes #8884.

<!--
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? -->

Add a new rule for unused assignments in tuples. Remove similar behavior
from F841.

## Test Plan

Adapt F841 tests and move them over to the new rule.

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

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-03 10:51:36 +01:00
Micha Reiser
be239b9f25 Upgrade to Tailwind4 (#16471)
## Test Plan

<img width="3360" alt="Screenshot 2025-03-03 at 10 01 19"
src="https://github.com/user-attachments/assets/d1ecfca0-ce51-440b-aabb-9107323fd1a4"
/>
2025-03-03 10:09:09 +01:00
Micha Reiser
8c899c5409 Upgrade to ESlint 9 (#16470)
Closes https://github.com/astral-sh/ruff/issues/12723
2025-03-03 09:59:57 +01:00
renovate[bot]
a08f5edf75 Update NPM Development dependencies (#16466)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@cloudflare/workers-types](https://redirect.github.com/cloudflare/workerd)
| [`4.20250214.0` ->
`4.20250224.0`](https://renovatebot.com/diffs/npm/@cloudflare%2fworkers-types/4.20250214.0/4.20250224.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@cloudflare%2fworkers-types/4.20250224.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@cloudflare%2fworkers-types/4.20250224.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@cloudflare%2fworkers-types/4.20250214.0/4.20250224.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@cloudflare%2fworkers-types/4.20250214.0/4.20250224.0?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.24.1` ->
`8.25.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/8.24.1/8.25.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2feslint-plugin/8.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2feslint-plugin/8.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2feslint-plugin/8.24.1/8.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2feslint-plugin/8.24.1/8.25.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.24.1` ->
`8.25.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.24.1/8.25.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/8.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fparser/8.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fparser/8.24.1/8.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/8.24.1/8.25.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-config-prettier](https://redirect.github.com/prettier/eslint-config-prettier)
| [`10.0.1` ->
`10.0.2`](https://renovatebot.com/diffs/npm/eslint-config-prettier/10.0.1/10.0.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-config-prettier/10.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-config-prettier/10.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-config-prettier/10.0.1/10.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-config-prettier/10.0.1/10.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [eslint-plugin-react-hooks](https://react.dev/)
([source](https://redirect.github.com/facebook/react/tree/HEAD/packages/eslint-plugin-react-hooks))
| [`5.1.0` ->
`5.2.0`](https://renovatebot.com/diffs/npm/eslint-plugin-react-hooks/5.1.0/5.2.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-react-hooks/5.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-plugin-react-hooks/5.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-plugin-react-hooks/5.1.0/5.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-react-hooks/5.1.0/5.2.0?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.20250214.0` ->
`3.20250214.1`](https://renovatebot.com/diffs/npm/miniflare/3.20250214.0/3.20250214.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/miniflare/3.20250214.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/miniflare/3.20250214.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/miniflare/3.20250214.0/3.20250214.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/miniflare/3.20250214.0/3.20250214.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [prettier](https://prettier.io)
([source](https://redirect.github.com/prettier/prettier)) | [`3.5.2` ->
`3.5.3`](https://renovatebot.com/diffs/npm/prettier/3.5.2/3.5.3) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.5.2/3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.5.2/3.5.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [typescript](https://www.typescriptlang.org/)
([source](https://redirect.github.com/microsoft/TypeScript)) | [`5.7.3`
-> `5.8.2`](https://renovatebot.com/diffs/npm/typescript/5.7.3/5.8.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/typescript/5.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/typescript/5.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/typescript/5.7.3/5.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/typescript/5.7.3/5.8.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [vite](https://vite.dev)
([source](https://redirect.github.com/vitejs/vite/tree/HEAD/packages/vite))
| [`6.1.1` ->
`6.2.0`](https://renovatebot.com/diffs/npm/vite/6.1.1/6.2.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vite/6.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite/6.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite/6.1.1/6.2.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/6.1.1/6.2.0?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.109.2` ->
`3.111.0`](https://renovatebot.com/diffs/npm/wrangler/3.109.2/3.111.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/wrangler/3.111.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/wrangler/3.111.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/wrangler/3.109.2/3.111.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/wrangler/3.109.2/3.111.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>cloudflare/workerd (@&#8203;cloudflare/workers-types)</summary>

###
[`v4.20250224.0`](28b2bb16d9...96568b0458)

[Compare
Source](28b2bb16d9...96568b0458)

</details>

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

###
[`v8.25.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8250-2025-02-24)

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

##### 🚀 Features

- **eslint-plugin:** \[no-misused-spread] add suggestions
([#&#8203;10719](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10719))

##### 🩹 Fixes

- **eslint-plugin:** \[prefer-nullish-coalescing] report on chain
expressions in a ternary
([#&#8203;10708](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10708))
- **eslint-plugin:** \[no-deprecated] report usage of deprecated private
identifiers
([#&#8203;10844](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10844))
- **eslint-plugin:** \[unified-signatures] handle getter-setter
([#&#8203;10818](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10818))

##### ❤️ Thank You

- Olivier Zalmanski
[@&#8203;OlivierZal](https://redirect.github.com/OlivierZal)
-   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.25.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8250-2025-02-24)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.24.1...v8.25.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.2`](https://redirect.github.com/prettier/eslint-config-prettier/blob/HEAD/CHANGELOG.md#1002)

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

##### Patch Changes

-
[#&#8203;299](https://redirect.github.com/prettier/eslint-config-prettier/pull/299)
[`e750edc`](e750edc530)
Thanks [@&#8203;Fdawgs](https://redirect.github.com/Fdawgs)! -
chore(package): explicitly declare js module type

</details>

<details>
<summary>facebook/react (eslint-plugin-react-hooks)</summary>

###
[`v5.2.0`](63cde684f5...3607f4838a)

[Compare
Source](63cde684f5...3607f4838a)

</details>

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

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

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

##### Patch Changes

-
[#&#8203;8247](https://redirect.github.com/cloudflare/workers-sdk/pull/8247)
[`a9a4c33`](a9a4c33143)
Thanks [@&#8203;GregBrimble](https://redirect.github.com/GregBrimble)! -
feat: Omits Content-Type header for files of an unknown extension in
Workers Assets

-
[#&#8203;8239](https://redirect.github.com/cloudflare/workers-sdk/pull/8239)
[`6cae13a`](6cae13aa5f)
Thanks [@&#8203;edmundhung](https://redirect.github.com/edmundhung)! -
fix: allow the `fetchMock` option to be parsed upfront before passing it
to Miniflare

</details>

<details>
<summary>prettier/prettier (prettier)</summary>

###
[`v3.5.3`](https://redirect.github.com/prettier/prettier/compare/3.5.2...b51ba9d46765bcfab714ebca982bd04ad25ae562)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.5.2...3.5.3)

</details>

<details>
<summary>microsoft/TypeScript (typescript)</summary>

###
[`v5.8.2`](https://redirect.github.com/microsoft/TypeScript/compare/v5.7.3...beb69e4cdd61b1a0fd9ae21ae58bd4bd409d7217)

[Compare
Source](https://redirect.github.com/microsoft/TypeScript/compare/v5.7.3...v5.8.2)

</details>

<details>
<summary>vitejs/vite (vite)</summary>

###
[`v6.2.0`](https://redirect.github.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#620-2025-02-25)

[Compare
Source](https://redirect.github.com/vitejs/vite/compare/v6.1.1...v6.2.0)

- fix(deps): update all non-major dependencies
([#&#8203;19501](https://redirect.github.com/vitejs/vite/issues/19501))
([c94c9e0](c94c9e0521)),
closes
[#&#8203;19501](https://redirect.github.com/vitejs/vite/issues/19501)
- fix(worker): string interpolation in dynamic worker options
([#&#8203;19476](https://redirect.github.com/vitejs/vite/issues/19476))
([07091a1](07091a1e80)),
closes
[#&#8203;19476](https://redirect.github.com/vitejs/vite/issues/19476)
- chore: use unicode cross icon instead of x
([#&#8203;19497](https://redirect.github.com/vitejs/vite/issues/19497))
([5c70296](5c70296ffb)),
closes
[#&#8203;19497](https://redirect.github.com/vitejs/vite/issues/19497)

</details>

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

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

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

##### Minor Changes

-
[#&#8203;7977](https://redirect.github.com/cloudflare/workers-sdk/pull/7977)
[`36ef9c6`](36ef9c6209)
Thanks [@&#8203;jkoe-cf](https://redirect.github.com/jkoe-cf)! - Added
wrangler r2 commands for bucket lock configuration

##### Patch Changes

-
[#&#8203;8248](https://redirect.github.com/cloudflare/workers-sdk/pull/8248)
[`1cb2d34`](1cb2d3418b)
Thanks [@&#8203;GregBrimble](https://redirect.github.com/GregBrimble)! -
feat: Omits Content-Type header for files of an unknown extension in
Workers Assets

-
[#&#8203;7977](https://redirect.github.com/cloudflare/workers-sdk/pull/7977)
[`36ef9c6`](36ef9c6209)
Thanks [@&#8203;jkoe-cf](https://redirect.github.com/jkoe-cf)! - fixing
the format of the R2 lifecycle rule date input to be parsed as string
instead of number

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

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

##### Minor Changes

-
[#&#8203;8253](https://redirect.github.com/cloudflare/workers-sdk/pull/8253)
[`6dd1e23`](6dd1e2300e)
Thanks
[@&#8203;CarmenPopoviciu](https://redirect.github.com/CarmenPopoviciu)!
- Add `--cwd` global argument to the `wrangler` CLI to allow changing
the current working directory before running any command.

##### Patch Changes

-
[#&#8203;8191](https://redirect.github.com/cloudflare/workers-sdk/pull/8191)
[`968c3d9`](968c3d9c06)
Thanks [@&#8203;vicb](https://redirect.github.com/vicb)! - Optimize
global injection in node compat mode

-
[#&#8203;8247](https://redirect.github.com/cloudflare/workers-sdk/pull/8247)
[`a9a4c33`](a9a4c33143)
Thanks [@&#8203;GregBrimble](https://redirect.github.com/GregBrimble)! -
feat: Omits Content-Type header for files of an unknown extension in
Workers Assets

- Updated dependencies
\[[`a9a4c33`](a9a4c33143),
[`6cae13a`](6cae13aa5f)]:
    -   miniflare@3.20250214.1

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

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

##### Patch Changes

-
[#&#8203;8175](https://redirect.github.com/cloudflare/workers-sdk/pull/8175)
[`eb46f98`](eb46f987cc)
Thanks [@&#8203;edmundhung](https://redirect.github.com/edmundhung)! -
fix: `unstable_splitSqlQuery` should ignore comments when splitting sql
into statements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-03-03 08:04:59 +00:00
renovate[bot]
5efcfd3414 Update dependency ruff to v0.9.9 (#16464)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ruff](https://docs.astral.sh/ruff)
([source](https://redirect.github.com/astral-sh/ruff),
[changelog](https://redirect.github.com/astral-sh/ruff/blob/main/CHANGELOG.md))
| `==0.9.7` -> `==0.9.9` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/ruff/0.9.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/ruff/0.9.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/ruff/0.9.7/0.9.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/ruff/0.9.7/0.9.9?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>astral-sh/ruff (ruff)</summary>

###
[`v0.9.9`](https://redirect.github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#099)

[Compare
Source](https://redirect.github.com/astral-sh/ruff/compare/0.9.8...0.9.9)

##### Preview features

- Fix caching of unsupported-syntax errors
([#&#8203;16425](https://redirect.github.com/astral-sh/ruff/pull/16425))

##### Bug fixes

- Only show unsupported-syntax errors in editors when preview mode is
enabled
([#&#8203;16429](https://redirect.github.com/astral-sh/ruff/pull/16429))

###
[`v0.9.8`](https://redirect.github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#098)

[Compare
Source](https://redirect.github.com/astral-sh/ruff/compare/0.9.7...0.9.8)

##### Preview features

- Start detecting version-related syntax errors in the parser
([#&#8203;16090](https://redirect.github.com/astral-sh/ruff/pull/16090))

##### Rule changes

- \[`pylint`] Mark fix unsafe (`PLW1507`)
([#&#8203;16343](https://redirect.github.com/astral-sh/ruff/pull/16343))
- \[`pylint`] Catch `case np.nan`/`case math.nan` in `match` statements
(`PLW0177`)
([#&#8203;16378](https://redirect.github.com/astral-sh/ruff/pull/16378))
- \[`ruff`] Add more Pydantic models variants to the list of default
copy semantics (`RUF012`)
([#&#8203;16291](https://redirect.github.com/astral-sh/ruff/pull/16291))

##### Server

- Avoid indexing the project if `configurationPreference` is
`editorOnly`
([#&#8203;16381](https://redirect.github.com/astral-sh/ruff/pull/16381))
- Avoid unnecessary info at non-trace server log level
([#&#8203;16389](https://redirect.github.com/astral-sh/ruff/pull/16389))
- Expand `ruff.configuration` to allow inline config
([#&#8203;16296](https://redirect.github.com/astral-sh/ruff/pull/16296))
- Notify users for invalid client settings
([#&#8203;16361](https://redirect.github.com/astral-sh/ruff/pull/16361))

##### Configuration

- Add `per-file-target-version` option
([#&#8203;16257](https://redirect.github.com/astral-sh/ruff/pull/16257))

##### Bug fixes

- \[`refurb`] Do not consider docstring(s) (`FURB156`)
([#&#8203;16391](https://redirect.github.com/astral-sh/ruff/pull/16391))
- \[`flake8-self`] Ignore attribute accesses on instance-like variables
(`SLF001`)
([#&#8203;16149](https://redirect.github.com/astral-sh/ruff/pull/16149))
- \[`pylint`] Fix false positives, add missing methods, and support
positional-only parameters (`PLE0302`)
([#&#8203;16263](https://redirect.github.com/astral-sh/ruff/pull/16263))
- \[`flake8-pyi`] Mark `PYI030` fix unsafe when comments are deleted
([#&#8203;16322](https://redirect.github.com/astral-sh/ruff/pull/16322))

##### Documentation

- Fix example for `S611`
([#&#8203;16316](https://redirect.github.com/astral-sh/ruff/pull/16316))
- Normalize inconsistent markdown headings in docstrings
([#&#8203;16364](https://redirect.github.com/astral-sh/ruff/pull/16364))
- Document MSRV policy
([#&#8203;16384](https://redirect.github.com/astral-sh/ruff/pull/16384))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 13:11:13 +05:30
renovate[bot]
79a2c7eaa2 Update pre-commit dependencies (#16465)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[astral-sh/ruff-pre-commit](https://redirect.github.com/astral-sh/ruff-pre-commit)
| repository | patch | `v0.9.6` -> `v0.9.9` |
| [crate-ci/typos](https://redirect.github.com/crate-ci/typos) |
repository | minor | `v1.29.7` -> `v1.30.0` |
|
[python-jsonschema/check-jsonschema](https://redirect.github.com/python-jsonschema/check-jsonschema)
| repository | patch | `0.31.1` -> `0.31.2` |
|
[rbubley/mirrors-prettier](https://redirect.github.com/rbubley/mirrors-prettier)
| repository | patch | `v3.5.1` -> `v3.5.2` |
|
[woodruffw/zizmor-pre-commit](https://redirect.github.com/woodruffw/zizmor-pre-commit)
| repository | minor | `v1.3.1` -> `v1.4.1` |

---

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

Note: The `pre-commit` manager in Renovate is not supported by the
`pre-commit` maintainers or community. Please do not report any problems
there, instead [create a Discussion in the Renovate
repository](https://redirect.github.com/renovatebot/renovate/discussions/new)
if you have any questions.

---

### Release Notes

<details>
<summary>astral-sh/ruff-pre-commit (astral-sh/ruff-pre-commit)</summary>

###
[`v0.9.9`](https://redirect.github.com/astral-sh/ruff-pre-commit/releases/tag/v0.9.9)

[Compare
Source](https://redirect.github.com/astral-sh/ruff-pre-commit/compare/v0.9.8...v0.9.9)

See: https://github.com/astral-sh/ruff/releases/tag/0.9.9

###
[`v0.9.8`](https://redirect.github.com/astral-sh/ruff-pre-commit/releases/tag/v0.9.8)

[Compare
Source](https://redirect.github.com/astral-sh/ruff-pre-commit/compare/v0.9.7...v0.9.8)

See: https://github.com/astral-sh/ruff/releases/tag/0.9.8

###
[`v0.9.7`](https://redirect.github.com/astral-sh/ruff-pre-commit/releases/tag/v0.9.7)

[Compare
Source](https://redirect.github.com/astral-sh/ruff-pre-commit/compare/v0.9.6...v0.9.7)

See: https://github.com/astral-sh/ruff/releases/tag/0.9.7

</details>

<details>
<summary>crate-ci/typos (crate-ci/typos)</summary>

###
[`v1.30.0`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.30.0)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.29.10...v1.30.0)

#### \[1.30.0] - 2025-03-01

##### Features

- Updated the dictionary with the [February
2025](https://redirect.github.com/crate-ci/typos/issues/1221) changes

###
[`v1.29.10`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.29.10)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.29.9...v1.29.10)

#### \[1.29.10] - 2025-02-25

##### Fixes

-   Also correct `contaminent` as `contaminant`

###
[`v1.29.9`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.29.9)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.29.8...v1.29.9)

#### \[1.29.9] - 2025-02-20

##### Fixes

-   *(action)* Correctly get binary for some aarch64 systems

###
[`v1.29.8`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.29.8)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.29.7...v1.29.8)

#### \[1.29.8] - 2025-02-19

##### Features

-   Attempt to build Linux aarch64 binaries

</details>

<details>
<summary>python-jsonschema/check-jsonschema
(python-jsonschema/check-jsonschema)</summary>

###
[`v0.31.2`](https://redirect.github.com/python-jsonschema/check-jsonschema/blob/HEAD/CHANGELOG.rst#0312)

[Compare
Source](https://redirect.github.com/python-jsonschema/check-jsonschema/compare/0.31.1...0.31.2)

- Update vendored schemas: dependabot, github-workflows, gitlab-ci,
mergify, renovate,
    woodpecker-ci (2025-02-19)

</details>

<details>
<summary>rbubley/mirrors-prettier (rbubley/mirrors-prettier)</summary>

###
[`v3.5.2`](https://redirect.github.com/rbubley/mirrors-prettier/compare/v3.5.1...v3.5.2)

[Compare
Source](https://redirect.github.com/rbubley/mirrors-prettier/compare/v3.5.1...v3.5.2)

</details>

<details>
<summary>woodruffw/zizmor-pre-commit
(woodruffw/zizmor-pre-commit)</summary>

###
[`v1.4.1`](https://redirect.github.com/woodruffw/zizmor-pre-commit/releases/tag/v1.4.1)

[Compare
Source](https://redirect.github.com/woodruffw/zizmor-pre-commit/compare/v1.4.0...v1.4.1)

See: https://github.com/woodruffw/zizmor/releases/tag/v1.4.1

###
[`v1.4.0`](https://redirect.github.com/woodruffw/zizmor-pre-commit/releases/tag/v1.4.0)

[Compare
Source](https://redirect.github.com/woodruffw/zizmor-pre-commit/compare/v1.3.1...v1.4.0)

See: https://github.com/woodruffw/zizmor/releases/tag/v1.4.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-03-03 13:10:46 +05:30
renovate[bot]
eaff95e1ad Update Rust crate globset to v0.4.16 (#16461)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[globset](https://redirect.github.com/BurntSushi/ripgrep/tree/master/crates/globset)
([source](https://redirect.github.com/BurntSushi/ripgrep/tree/HEAD/crates/globset))
| workspace.dependencies | patch | `0.4.15` -> `0.4.16` |

---

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

---

### 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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 12:48:34 +05:30
renovate[bot]
2d9f564ecd Update Rust crate clap to v4.5.31 (#16459)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.30` -> `4.5.31` |

---

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

---

### Release Notes

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

###
[`v4.5.31`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4531---2025-02-24)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.30...v4.5.31)

##### Features

-   Add `ValueParserFactory` for `Saturating<T>`

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 12:46:38 +05:30
renovate[bot]
a6ae86c189 Update Rust crate chrono to v0.4.40 (#16458)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [chrono](https://redirect.github.com/chronotope/chrono) |
workspace.dependencies | patch | `0.4.39` -> `0.4.40` |

---

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

---

### Release Notes

<details>
<summary>chronotope/chrono (chrono)</summary>

###
[`v0.4.40`](https://redirect.github.com/chronotope/chrono/releases/tag/v0.4.40):
0.4.40

[Compare
Source](https://redirect.github.com/chronotope/chrono/compare/v0.4.39...v0.4.40)

#### What's Changed

- Add Month::num_days() by
[@&#8203;djc](https://redirect.github.com/djc) in
[https://github.com/chronotope/chrono/pull/1645](https://redirect.github.com/chronotope/chrono/pull/1645)
- Update Windows dependencies by
[@&#8203;kennykerr](https://redirect.github.com/kennykerr) in
[https://github.com/chronotope/chrono/pull/1646](https://redirect.github.com/chronotope/chrono/pull/1646)
- Feature/round_up method on DurationRound trait by
[@&#8203;MagnumTrader](https://redirect.github.com/MagnumTrader) in
[https://github.com/chronotope/chrono/pull/1651](https://redirect.github.com/chronotope/chrono/pull/1651)
- Expose `write_to` for `DelayedFormat` by
[@&#8203;tugtugtug](https://redirect.github.com/tugtugtug) in
[https://github.com/chronotope/chrono/pull/1654](https://redirect.github.com/chronotope/chrono/pull/1654)
- Update LICENSE.txt by
[@&#8203;maximevtush](https://redirect.github.com/maximevtush) in
[https://github.com/chronotope/chrono/pull/1656](https://redirect.github.com/chronotope/chrono/pull/1656)
- docs: fix minor typo by
[@&#8203;samfolo](https://redirect.github.com/samfolo) in
[https://github.com/chronotope/chrono/pull/1659](https://redirect.github.com/chronotope/chrono/pull/1659)
- Use NaiveDateTime for internal tz_info methods. by
[@&#8203;AVee](https://redirect.github.com/AVee) in
[https://github.com/chronotope/chrono/pull/1658](https://redirect.github.com/chronotope/chrono/pull/1658)
- Upgrade to windows-bindgen 0.60 by
[@&#8203;djc](https://redirect.github.com/djc) in
[https://github.com/chronotope/chrono/pull/1665](https://redirect.github.com/chronotope/chrono/pull/1665)
- Add quarter (%q) date string specifier by
[@&#8203;drinkcat](https://redirect.github.com/drinkcat) in
[https://github.com/chronotope/chrono/pull/1666](https://redirect.github.com/chronotope/chrono/pull/1666)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 12:46:14 +05:30
renovate[bot]
08e11e991d Update Rust crate codspeed-criterion-compat to v2.8.1 (#16460)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [codspeed-criterion-compat](https://codspeed.io)
([source](https://redirect.github.com/CodSpeedHQ/codspeed-rust)) |
workspace.dependencies | patch | `2.8.0` -> `2.8.1` |

---

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

---

### Release Notes

<details>
<summary>CodSpeedHQ/codspeed-rust (codspeed-criterion-compat)</summary>

###
[`v2.8.1`](https://redirect.github.com/CodSpeedHQ/codspeed-rust/releases/tag/v2.8.1)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/codspeed-rust/compare/v2.8.0...v2.8.1)

#### What's Changed

- chore: remove deprecated feature from cargo-codspeed release build by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/76](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/76)
- chore(divan_compat): fix readme typo by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/77](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/77)
- ci: build musl targets for cargo-codspeed binary artifacts by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/80](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/80)
- ci: add targets to moon-repo/setup in binary artifact build by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/81](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/81)

**Full Changelog**:
https://github.com/CodSpeedHQ/codspeed-rust/compare/v2.8.0...v2.8.1

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 12:43:58 +05:30
renovate[bot]
ec311a7ed0 Update Rust crate schemars to v0.8.22 (#16463)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [schemars](https://graham.cool/schemars/)
([source](https://redirect.github.com/GREsau/schemars)) |
workspace.dependencies | patch | `0.8.21` -> `0.8.22` |

---

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

---

### Release Notes

<details>
<summary>GREsau/schemars (schemars)</summary>

###
[`v0.8.22`](https://redirect.github.com/GREsau/schemars/blob/HEAD/CHANGELOG.md#0822---2025-02-25)

[Compare
Source](https://redirect.github.com/GREsau/schemars/compare/v0.8.21...v0.8.22)

##### Fixed:

- Fix compatibility with rust 2024 edition
([https://github.com/GREsau/schemars/pull/378](https://redirect.github.com/GREsau/schemars/pull/378))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 12:43:35 +05:30
renovate[bot]
b7de42686f Update Rust crate insta to v1.42.2 (#16462)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [insta](https://insta.rs/)
([source](https://redirect.github.com/mitsuhiko/insta)) |
workspace.dependencies | patch | `1.42.1` -> `1.42.2` |

---

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

---

### Release Notes

<details>
<summary>mitsuhiko/insta (insta)</summary>

###
[`v1.42.2`](https://redirect.github.com/mitsuhiko/insta/blob/HEAD/CHANGELOG.md#1422)

[Compare
Source](https://redirect.github.com/mitsuhiko/insta/compare/1.42.1...1.42.2)

- Support other indention characters than spaces in inline snapshots.
[#&#8203;679](https://redirect.github.com/mitsuhiko/insta/issues/679)
- Fix an issue where multiple targets with the same root would cause too
many pending snapshots to be reported.
[#&#8203;730](https://redirect.github.com/mitsuhiko/insta/issues/730)
- Hide `unseen` option in CLI, as it's pending deprecation.
[#&#8203;732](https://redirect.github.com/mitsuhiko/insta/issues/732)
- Stop `\t` and `\x1b` (ANSI color escape) from causing snapshots to be
escaped.
[#&#8203;715](https://redirect.github.com/mitsuhiko/insta/issues/715)
- Improved handling of inline snapshots within `allow_duplicates! { ..
}`.
[#&#8203;712](https://redirect.github.com/mitsuhiko/insta/issues/712)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 12:42:46 +05:30
renovate[bot]
ff44500517 Update Rust crate bitflags to v2.9.0 (#16467)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [bitflags](https://redirect.github.com/bitflags/bitflags) |
workspace.dependencies | minor | `2.8.0` -> `2.9.0` |

---

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

---

### Release Notes

<details>
<summary>bitflags/bitflags (bitflags)</summary>

###
[`v2.9.0`](https://redirect.github.com/bitflags/bitflags/blob/HEAD/CHANGELOG.md#290)

[Compare
Source](https://redirect.github.com/bitflags/bitflags/compare/2.8.0...2.9.0)

#### What's Changed

- `Flags` trait: add `clear(&mut self)` method by
[@&#8203;wysiwys](https://redirect.github.com/wysiwys) in
[https://github.com/bitflags/bitflags/pull/437](https://redirect.github.com/bitflags/bitflags/pull/437)
- Fix up UI tests by
[@&#8203;KodrAus](https://redirect.github.com/KodrAus) in
[https://github.com/bitflags/bitflags/pull/438](https://redirect.github.com/bitflags/bitflags/pull/438)

**Full Changelog**:
https://github.com/bitflags/bitflags/compare/2.8.0...2.9.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 12:41:57 +05:30
Brent Westbrook
e924ecbdac [syntax-errors] except* before Python 3.11 (#16446)
Summary
--

One of the simpler ones, just detect the use of `except*` before 3.11.

Test Plan
--

New inline tests.
2025-03-02 18:20:18 +00:00
github-actions[bot]
0d615b8765 Sync vendored typeshed stubs (#16448)
Close and reopen this PR to trigger CI

Co-authored-by: typeshedbot <>
2025-03-01 08:21:03 +01:00
Brent Westbrook
4431978262 [syntax-errors] Assignment expressions before Python 3.8 (#16383)
## Summary
This PR is the first in a series derived from
https://github.com/astral-sh/ruff/pull/16308, each of which add support
for detecting one version-related syntax error from
https://github.com/astral-sh/ruff/issues/6591. This one should be
the largest because it also includes the addition of the 
`Parser::add_unsupported_syntax_error` method

Otherwise I think the general structure will be the same for each syntax
error:
* Detecting the error in the parser
* Inline parser tests for the new error
* New ruff CLI tests for the new error

## Test Plan
As noted above, there are new inline parser tests, as well as new ruff
CLI
tests. Once https://github.com/astral-sh/ruff/pull/16379 is resolved,
there should also be new mdtests for red-knot,
but this PR does not currently include those.
2025-02-28 17:13:46 -05:00
Douglas Creager
ba44e9de13 [red-knot] Don't use separate ID types for each alist (#16415)
Regardless of whether #16408 and #16311 pan out, this part is worth
pulling out as a separate PR.

Before, you had to define a new `IndexVec` index type for each type of
association list you wanted to create. Now there's a single index type
that's internal to the alist implementation, and you use `List<K, V>` to
store a handle to a particular list.

This also adds some property tests for the alist implementation.
2025-02-28 14:55:55 -05:00
Mike Perlov
fdf0915283 [red-knot] treat annotated assignments without RHS in stubs as bindings (#16409) 2025-02-28 16:45:21 +00:00
Adam Johnson
5ca6cc2cc8 Exempt unittest context methods for SIM115 rule (#16439) 2025-02-28 16:29:50 +00:00
Alex Waygood
9bb63495dd [red-knot] Reject HTML comments in mdtest unless they are snapshot-diagnostics or are explicitly allowlisted (#16441) 2025-02-28 16:27:28 +00:00
InSync
980faff176 Move rule code from description to check_name in GitLab output serializer (#16437) 2025-02-28 14:27:01 +00:00
Alex Waygood
0c7c001647 [red-knot] Switch to a handwritten parser for mdtest error assertions (#16422) 2025-02-28 11:33:36 +00:00
Alex Waygood
09d0b227fb [red-knot] Disallow more invalid type expressions (#16427) 2025-02-28 10:04:30 +00:00
Micha Reiser
091d0af2ab Bump version to Ruff 0.9.9 (#16434) 2025-02-28 10:17:38 +01:00
Brent Westbrook
3d72138740 Check LinterSettings::preview for version-related syntax errors (#16429) 2025-02-28 09:58:22 +01:00
Brent Westbrook
4a23756024 Avoid caching files with unsupported syntax errors (#16425) 2025-02-28 09:58:11 +01:00
Dhruv Manilawala
af62f7932b Prioritize "bug" label for changelog sections (#16433)
## Summary

This PR updates the ordering of changelog sections to prioritize `bug`
label such that any PRs that has that label is categorized in "Bug
fixes" section in when generating the changelog irrespective of any
other labels present on the PR.

I think this works because I've seen PRs with both `server` and `bug` in
the "Server" section instead of the "Bug fixes" section. For example,
https://github.com/astral-sh/ruff/pull/16262 in
https://github.com/astral-sh/ruff/releases/tag/0.9.7.

On that note, this also changes the ordering such that any PR with both
`server` and `bug` labels are in the "Bug fixes" section instead of the
"Server" section. This is in line with how "Formatter" is done. I think
it makes sense to instead prefix the entries with "Formatter:" and
"Server:" if they're bug fixes. But, I'm happy to change this such that
any PRs with `formatter` and `server` labels are always in their own
section irrespective of other labels.
2025-02-28 14:17:25 +05:30
InSync
0ced8d053c [flake8-copyright] Add links to applicable options (CPY001) (#16421) 2025-02-28 09:11:14 +01:00
Micha Reiser
a8e171f82c Fix string-length limit in documentation for PYI054 (#16432) 2025-02-28 08:32:08 +01:00
Brent Westbrook
cf83584abb Show version-related syntax errors in the playground (#16419)
## Summary

Fixes part of https://github.com/astral-sh/ruff/issues/16417 by
converting `unsupported_syntax_errors` into playground diagnostics.

## Test Plan

A new `ruff_wasm` test, plus trying out the playground locally:

Default settings:

![image](https://github.com/user-attachments/assets/94377ab5-4d4c-44d3-ae63-fe328a53e083)

`target-version = "py310"`:

![image](https://github.com/user-attachments/assets/51c312ce-70e7-43d3-b6ba-098f2750cb28)
2025-02-27 13:28:37 -05:00
Brent Westbrook
764aa0e6a1 Allow passing ParseOptions to inline tests (#16357)
## Summary

This PR adds support for a pragma-style header for inline parser tests
containing JSON-serialized `ParseOptions`. For example,

```python
# parse_options: { "target-version": "3.9" }
match 2:
    case 1:
        pass
```

The line must start with `# parse_options: ` and then the rest of the
(trimmed) line is deserialized into `ParseOptions` used for parsing the
the test.

## Test Plan

Existing inline tests, plus two new inline tests for
`match-before-py310`.

---------

Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-02-27 10:23:15 -05:00
Brent Westbrook
568cf88c6c Bump version to 0.9.8 (#16414) 2025-02-27 08:56:11 -05:00
Alex Waygood
040071bbc5 [red-knot] Ignore surrounding whitespace when looking for <!-- snapshot-diagnostics --> directives in mdtests (#16380) 2025-02-27 13:25:31 +00:00
Dhruv Manilawala
d56d241317 Notify users for invalid client settings (#16361)
## Summary

As mentioned in
https://github.com/astral-sh/ruff/pull/16296#discussion_r1967047387

This PR updates the client settings resolver to notify the user if there
are any errors in the config using a very basic approach. In addition,
each error related to specific settings are logged.

This isn't the best approach because it can log the same message
multiple times when both workspace and global settings are provided and
they both are the same. This is the case for a single workspace VS Code
instance.

I do have some ideas on how to improve this and will explore them during
my free time (low priority):
* Avoid resolving the global settings multiple times as they're static
* Include the source of the setting (workspace or global?)
* Maybe use a struct (`ResolvedClientSettings` +
`Vec<ClientSettingsResolverError>`) instead to make unit testing easier

## Test Plan

Using:
```jsonc
{
  "ruff.logLevel": "debug",
	
  // Invalid settings
  "ruff.configuration": "$RANDOM",
  "ruff.lint.select": ["RUF000", "I001"],
  "ruff.lint.extendSelect": ["B001", "B002"],
  "ruff.lint.ignore": ["I999", "F401"]
}
```

The error logs:
```
2025-02-27 12:30:04.318736000 ERROR Failed to load settings from `configuration`: error looking key 'RANDOM' up: environment variable not found
2025-02-27 12:30:04.319196000 ERROR Failed to load settings from `configuration`: error looking key 'RANDOM' up: environment variable not found
2025-02-27 12:30:04.320549000 ERROR Unknown rule selectors found in `lint.select`: ["RUF000"]
2025-02-27 12:30:04.320669000 ERROR Unknown rule selectors found in `lint.extendSelect`: ["B001"]
2025-02-27 12:30:04.320764000 ERROR Unknown rule selectors found in `lint.ignore`: ["I999"]
```

Notification preview:

<img width="470" alt="Screenshot 2025-02-27 at 12 29 06 PM"
src="https://github.com/user-attachments/assets/61f41d5c-2558-46b3-a1ed-82114fd8ec22"
/>
2025-02-27 08:28:29 +00:00
Darius Carrier
7dad0c471d Avoid indexing the project if configurationPreference is editorOnly (#16381)
## Summary

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

This change skips building the `index` in RuffSettingsIndex when the
configuration preference, in the editor settings, is set to
`editorOnly`. This is appropriate due to the fact that the indexes will
go unused as long as the configuration preference persists.

## Test Plan

I have tested this in VSCode and can confirm that we skip indexing when
`editorOnly` is set. Upon switching back to `editorFirst` or
`filesystemFirst` we index the settings as normal.

I don't seen any unit tests for setting indexing at the moment, but I am
happy to give it a shot if that is something we want.
2025-02-27 07:46:14 +05:30
Carl Meyer
fb778ee38d [red-knot] unify LoopState and saved_break_states (#16406)
We currently keep two separate pieces of state regarding the current
loop on `SemanticIndexBuilder`. One is an enum simply reflecting whether
we are currently inside a loop, and the other is the saved flow states
for `break` statements found in the current loop.

For adding loopy control flow, I'll need to add some additional loop
state (`continue` states, for example). Prepare for this by
consolidating our existing loop state into a single struct and
simplifying the API for pushing and popping a loop.

This is purely a refactor, so tests are not changed.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-26 22:31:13 +00:00
InSync
671494a620 [pylint] Also reports case np.nan/case math.nan (PLW0177) (#16378)
## Summary

Resolves #16374.

`PLW0177` now also reports the pattern of a case branch if it is an
attribute access whose qualified name is that of either `np.nan` or
`math.nan`.

As the rule is in preview, the changes are not preview-gated.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-26 13:50:21 -05:00
Vasco Schiavo
b89d61bd05 [FURB156] Do not consider docstring(s) (#16391)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-26 16:30:13 +00:00
Brent Westbrook
8c0eac21ab Use is_none_or in stdlib-module-shadowing (#16402)
Summary
--
This resolves a TODO I left behind in #16006 now that our MSRV is 1.83.

Test Plan
--
Existing tests
2025-02-26 11:29:00 -05:00
Micha Reiser
c892fee058 [red-knot] Upgrade salsa to include AtomicPtr perf improvement (#16398) 2025-02-26 17:02:06 +01:00
Micha Reiser
ea3245b8c4 [red-knot] Fix file watching for new non-project files (#16395) 2025-02-26 16:10:13 +01:00
Carl Meyer
592532738f document MSRV policy (#16384)
This documents our minimum supported Rust version policy. See
https://github.com/astral-sh/ruff/issues/16370
2025-02-26 07:09:23 -08:00
Carl Meyer
87d011e1bd [red-knot] fix non-callable reporting for unions (#16387)
Minor follow-up to https://github.com/astral-sh/ruff/pull/16161

This `not_callable` flag wasn't functional, because it could never be
`false`. It was initialized to `true` and then only ever updated with
`|=`, which can never make it `false`.

Add a test that exercises the case where it _should_ be `false` (all of
the union elements are callable) but `bindings` is also empty (all union
elements have binding errors). Before this PR, the added test wrongly
emits a diagnostic that the union `Literal[f1] | Literal[f2]` is not
callable.

And add a test where a union call results in one binding error and one
not-callable error, where we currently give the wrong result (we show
only the binding error), with a TODO.

Also add TODO comments in a couple other tests where ideally we'd report
more than just one error out of a union call.

Also update the flag name to `all_errors_not_callable` to more clearly
indicate the semantics of the flag.
2025-02-26 07:06:04 -08:00
Carl Meyer
dd6f6233bd bump MSRV to 1.83 (#16294)
According to our new MSRV policy (see
https://github.com/astral-sh/ruff/issues/16370 ), bump our MSRV to 1.83
(N - 2), and autofix some new clippy lints.
2025-02-26 06:12:43 -08:00
Dhruv Manilawala
bf2c9a41cd Avoid unnecessary info at non-trace server log level (#16389)
## Summary

Currently, the log messages emitted by the server includes multiple
information which isn't really required most of the time.

Here's the current format:
```
   0.000755625s DEBUG main ruff_server::session::index::ruff_settings: Indexing settings for workspace: /Users/dhruv/playground/ruff
   0.016334666s DEBUG ThreadId(10) ruff_server::session::index::ruff_settings: Ignored path via `exclude`: /Users/dhruv/playground/ruff/.vscode
   0.019954541s  INFO main ruff_server::session::index: Registering workspace: /Users/dhruv/playground/ruff
   0.020160416s TRACE ruff:main notification{method="textDocument/didOpen"}: ruff_server::server::api: enter
   0.020209625s TRACE ruff:worker:0 request{id=1 method="textDocument/diagnostic"}: ruff_server::server::api: enter
   0.020228166s DEBUG ruff:worker:0 request{id=1 method="textDocument/diagnostic"}: ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/test.py
   0.020359833s  INFO     ruff:main ruff_server::server: Configuration file watcher successfully registered
```

This PR updates the following:
* Uses current timestamp (same as red-knot) for all log levels instead
of the uptime value
* Includes the target and thread names only at the trace level

What this means is that the message is reduced to only important
information at DEBUG level:

```
2025-02-26 11:35:02.198375000 DEBUG Indexing settings for workspace: /Users/dhruv/playground/ruff
2025-02-26 11:35:02.209933000 DEBUG Ignored path via `exclude`: /Users/dhruv/playground/ruff/.vscode
2025-02-26 11:35:02.217165000  INFO Registering workspace: /Users/dhruv/playground/ruff
2025-02-26 11:35:02.217631000 DEBUG Included path via `include`: /Users/dhruv/playground/ruff/lsp/test.py
2025-02-26 11:35:02.217684000  INFO Configuration file watcher successfully registered
```

while still showing the other information (thread names and target) at
trace level:
```
2025-02-26 11:35:27.819617000 DEBUG main ruff_server::session::index::ruff_settings: Indexing settings for workspace: /Users/dhruv/playground/ruff
2025-02-26 11:35:27.830500000 DEBUG ThreadId(11) ruff_server::session::index::ruff_settings: Ignored path via `exclude`: /Users/dhruv/playground/ruff/.vscode
2025-02-26 11:35:27.837212000  INFO main ruff_server::session::index: Registering workspace: /Users/dhruv/playground/ruff
2025-02-26 11:35:27.837714000 TRACE ruff:main notification{method="textDocument/didOpen"}: ruff_server::server::api: enter
2025-02-26 11:35:27.838019000  INFO ruff:main ruff_server::server: Configuration file watcher successfully registered
2025-02-26 11:35:27.838084000 TRACE ruff:worker:1 request{id=1 method="textDocument/diagnostic"}: ruff_server::server::api: enter
2025-02-26 11:35:27.838205000 DEBUG ruff:worker:1 request{id=1 method="textDocument/diagnostic"}: ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/test.py
```
2025-02-26 13:31:17 +05:30
Dhruv Manilawala
be03cb04c1 Expand ruff.configuration to allow inline config (#16296)
## Summary

[Internal design
document](https://www.notion.so/astral-sh/In-editor-settings-19e48797e1ca807fa8c2c91b689d9070?pvs=4)

This PR expands `ruff.configuration` to allow inline configuration
directly in the editor. For example:

```json
{
	"ruff.configuration": {
		"line-length": 100,
		"lint": {
			"unfixable": ["F401"],
			"flake8-tidy-imports": {
				"banned-api": {
					"typing.TypedDict": {
						"msg": "Use `typing_extensions.TypedDict` instead"
					}
				}
			}
		},
		"format": {
			"quote-style": "single"
		}
	}
}
```

This means that now `ruff.configuration` accepts either a path to
configuration file or the raw config itself. It's _mostly_ similar to
`--config` with one difference that's highlighted in the following
section. So, it can be said that the format of `ruff.configuration` when
provided the config map is same as the one on the [playground] [^1].

## Limitations

<details><summary><b>Casing (<code>kebab-case</code> v/s/
<code>camelCase</code>)</b></summary>
<p>


The config keys needs to be in `kebab-case` instead of `camelCase` which
is being used for other settings in the editor.

This could be a bit confusing. For example, the `line-length` option can
be set directly via an editor setting or can be configured via
`ruff.configuration`:

```json
{
	"ruff.configuration": {
        "line-length": 100
    },
    "ruff.lineLength": 120
}
```

#### Possible solution

We could use feature flag with [conditional
compilation](https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute)
to indicate that when used in `ruff_server`, we need the `Options`
fields to be renamed as `camelCase` while for other crates it needs to
be renamed as `kebab-case`. But, this might not work very easily because
it will require wrapping the `Options` struct and create two structs in
which we'll have to add `#[cfg_attr(...)]` because otherwise `serde`
will complain:

```
error: duplicate serde attribute `rename_all`
  --> crates/ruff_workspace/src/options.rs:43:38
   |
43 | #[cfg_attr(feature = "editor", serde(rename_all = "camelCase"))]
   |                                      ^^^^^^^^^^
```

</p>
</details> 

<details><summary><b>Nesting (flat v/s nested keys)</b></summary>
<p>

This is the major difference between `--config` flag on the command-line
v/s `ruff.configuration` and it makes it such that `ruff.configuration`
has same value format as [playground] [^1].

The config keys needs to be split up into keys which can result in
nested structure instead of flat structure:

So, the following **won't work**:

```json
{
	"ruff.configuration": {
		"format.quote-style": "single",
		"lint.flake8-tidy-imports.banned-api.\"typing.TypedDict\".msg": "Use `typing_extensions.TypedDict` instead"
	}
}
```

But, instead it would need to be split up like the following:
```json
{
	"ruff.configuration": {
		"format": {
			"quote-style": "single"
		},
		"lint": {
			"flake8-tidy-imports": {
				"banned-api": {
					"typing.TypedDict": {
						"msg": "Use `typing_extensions.TypedDict` instead"
					}
				}
			}
		}
	}
}
```

#### Possible solution (1)

The way we could solve this and make it same as `--config` would be to
add a manual logic of converting the JSON map into an equivalent TOML
string which would be then parsed into `Options`.

So, the following JSON map:
```json
{ "lint.flake8-tidy-imports": { "banned-api": {"\"typing.TypedDict\".msg": "Use typing_extensions.TypedDict instead"}}}
```

would need to be converted into the following TOML string:
```toml
lint.flake8-tidy-imports = { banned-api = { "typing.TypedDict".msg = "Use typing_extensions.TypedDict instead" } }
```

by recursively convering `"key": value` into `key = value` which is to
remove the quotes from key and replacing `:` with `=`.

#### Possible solution (2)

Another would be to just accept `Map<String, String>` strictly and
convert it into `key = value` and then parse it as a TOML string. This
would also match `--config` but quotes might become a nuisance because
JSON only allows double quotes and so it'll require escaping any inner
quotes or use single quotes.

</p>
</details> 

## Test Plan

### VS Code

**Requires https://github.com/astral-sh/ruff-vscode/pull/702**

**`settings.json`**:
```json
{
  "ruff.lint.extendSelect": ["TID"],
  "ruff.configuration": {
    "line-length": 50,
    "format": {
      "quote-style": "single"
    },
    "lint": {
      "unfixable": ["F401"],
      "flake8-tidy-imports": {
        "banned-api": {
          "typing.TypedDict": {
            "msg": "Use `typing_extensions.TypedDict` instead"
          }
        }
      }
    }
  }
}
```

Following video showcases me doing the following:
1. Check diagnostics that it includes `TID`
2. Run `Ruff: Fix all auto-fixable problems` to test `unfixable`
3. Run `Format: Document` to test `line-length` and `quote-style`


https://github.com/user-attachments/assets/0a38176f-3fb0-4960-a213-73b2ea5b1180

### Neovim

**`init.lua`**:
```lua
require('lspconfig').ruff.setup {
  init_options = {
    settings = {
      lint = {
        extendSelect = { 'TID' },
      },
      configuration = {
        ['line-length'] = 50,
        format = {
          ['quote-style'] = 'single',
        },
        lint = {
          unfixable = { 'F401' },
          ['flake8-tidy-imports'] = {
            ['banned-api'] = {
              ['typing.TypedDict'] = {
                msg = 'Use typing_extensions.TypedDict instead',
              },
            },
          },
        },
      },
    },
  },
}
```

Same steps as in the VS Code test:



https://github.com/user-attachments/assets/cfe49a9b-9a89-43d7-94f2-7f565d6e3c9d

## Documentation Preview



https://github.com/user-attachments/assets/e0062f58-6ec8-4e01-889d-fac76fd8b3c7



[playground]: https://play.ruff.rs

[^1]: This has one advantage that the value can be copy-pasted directly
into the playground
2025-02-26 10:17:11 +05:30
Brent Westbrook
78806361fd Start detecting version-related syntax errors in the parser (#16090)
## Summary

This PR builds on the changes in #16220 to pass a target Python version
to the parser. It also adds the `Parser::unsupported_syntax_errors` field, which
collects version-related syntax errors while parsing. These syntax
errors are then turned into `Message`s in ruff (in preview mode).

This PR only detects one syntax error (`match` statement before Python
3.10), but it has been pretty quick to extend to several other simple
errors (see #16308 for example).

## Test Plan

The current tests are CLI tests in the linter crate, but these could be
supplemented with inline parser tests after #16357.

I also tested the display of these syntax errors in VS Code:


![image](https://github.com/user-attachments/assets/062b4441-740e-46c3-887c-a954049ef26e)

![image](https://github.com/user-attachments/assets/101f55b8-146c-4d59-b6b0-922f19bcd0fa)

---------

Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-02-25 23:03:48 -05:00
Douglas Creager
b39a4ad01d [red-knot] Rename constraint to predicate (#16382)
In https://github.com/astral-sh/ruff/pull/16306#discussion_r1966290700,
@carljm pointed out that #16306 introduced a terminology problem, with
too many things called a "constraint". This is a follow-up PR that
renames `Constraint` to `Predicate` to hopefully clear things up a bit.
So now we have that:

- a _predicate_ is a Python expression that might influence type
inference
- a _narrowing constraint_ is a list of predicates that constraint the
type of a binding that is visible at a use
- a _visibility constraint_ is a ternary formula of predicates that
define whether a binding is visible or a statement is reachable

This is a pure renaming, with no behavioral changes.
2025-02-25 14:52:40 -05:00
David Peter
86b01d2d3c [red-knot] Correct modeling of dunder calls (#16368)
## Summary

Model dunder-calls correctly (and in one single place), by implementing
this behavior (using `__getitem__` as an example).

```py
def getitem_desugared(obj: object, key: object) -> object:
    getitem_callable = find_in_mro(type(obj), "__getitem__")
    if hasattr(getitem_callable, "__get__"):
        getitem_callable = getitem_callable.__get__(obj, type(obj))

    return getitem_callable(key)
```

See the new `calls/dunder.md` test suite for more information. The new
behavior also needs much fewer lines of code (the diff is positive due
to new tests).

## Test Plan

New tests; fix TODOs in existing tests.
2025-02-25 20:38:15 +01:00
David Peter
f88328eedd [red-knot] Handle possibly-unbound instance members (#16363)
## Summary

Adds support for possibly-unbound/undeclared instance members.

## Test Plan

New MD tests.
2025-02-25 20:00:38 +01:00
Douglas Creager
fa76f6cbb2 [red-knot] Use arena-allocated association lists for narrowing constraints (#16306)
This PR adds an implementation of [association
lists](https://en.wikipedia.org/wiki/Association_list), and uses them to
replace the previous `BitSet`/`SmallVec` representation for narrowing
constraints.

An association list is a linked list of key/value pairs. We additionally
guarantee that the elements of an association list are sorted (by their
keys), and that they do not contain any entries with duplicate keys.

Association lists have fallen out of favor in recent decades, since you
often need operations that are inefficient on them. In particular,
looking up a random element by index is O(n), just like a linked list;
and looking up an element by key is also O(n), since you must do a
linear scan of the list to find the matching element. Luckily we don't
need either of those operations for narrowing constraints!

The typical implementation also suffers from poor cache locality and
high memory allocation overhead, since individual list cells are
typically allocated separately from the heap. We solve that last problem
by storing the cells of an association list in an `IndexVec` arena.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-02-25 10:58:56 -05:00
Alex Waygood
5c007db7e2 [red-knot] Rewrite Type::try_iterate() to improve type inference and diagnostic messages (#16321) 2025-02-25 14:02:03 +00:00
Zanie Blue
1be0dc6885 Add issue templates (#16213)
Follows https://github.com/astral-sh/ruff/pull/15651

Preview: https://github.com/dhruvmanila/ruff-issue-templates/issues

GitHub made the interface for single-template repositories worse. While
they might fix it, it encouragement to just do this work. They still
haven't fixed the teeny tiny emojis which makes me think this won't be
fixed quickly.

Before:

<img width="1267" alt="Screenshot 2025-02-17 at 8 26 08 AM"
src="https://github.com/user-attachments/assets/e69ef630-4296-470e-ab4d-a22d55785444"
/>

After:

<img width="1688" alt="Screenshot 2025-02-24 at 3 05 35 PM"
src="https://github.com/user-attachments/assets/61033666-1fe5-421b-a69c-1aa79bcc85b5"
/>

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-02-25 16:29:16 +05:30
Muspi Merol
a1a536b2c5 Normalize inconsistent markdown headings in docstrings (#16364)
I am working on a project that uses ruff linters' docs to generate a
fine-tuning dataset for LLMs.

To achieve this, I first ran the command `ruff rule --all
--output-format json` to retrieve all the rules. Then, I parsed the
explanation field to get these 3 consistent sections:

- `Why is this bad?`
- `What it does`
- `Example`

However, during the initial processing, I noticed that the markdown
headings are not that consistent. For instance:

- In most cases, `Use instead` appears as a normal paragraph within the
`Example` section, but in the file
`crates/ruff_linter/src/rules/flake8_bandit/rules/django_extra.rs` it is
a level-2 heading
- The heading "What it does**?**" is used in some places, while others
consistently use "What it does"
- There are 831 `Example` headings and 65 `Examples`. But all of them
only have one example case

This PR normalized these across all rules.

## Test Plan

CI are passed.
2025-02-25 15:42:55 +05:30
David Peter
aac79e453a [red-knot] Better diagnostics for method calls (#16362)
## Summary

Add better error messages and additional spans for method calls. Can be
reviewed commit-by-commit.

before:

```
error: lint:invalid-argument-type
 --> /home/shark/playground/test.py:6:10
  |
5 | c = C()
6 | c.square("hello")  # error: [invalid-argument-type]
  |          ^^^^^^^ Object of type `Literal["hello"]` cannot be assigned to parameter 2 (`x`); expected type `int`
7 |
8 | # import inspect
  |
```

after:

```
error: lint:invalid-argument-type
 --> /home/shark/playground/test.py:6:10
  |
5 | c = C()
6 | c.square("hello")  # error: [invalid-argument-type]
  |          ^^^^^^^ Object of type `Literal["hello"]` cannot be assigned to parameter 2 (`x`) of bound method `square`; expected type `int`
7 |
8 | # import inspect
  |
 ::: /home/shark/playground/test.py:2:22
  |
1 | class C:
2 |     def square(self, x: int) -> int:
  |                      ------ info: parameter declared in function definition here
3 |         return x * x
  |
```

## Test Plan

New snapshot test
2025-02-25 09:58:08 +01:00
Micha Reiser
fd7b3c83ad [red-knot] Add argfile and windows glob path support (#16353) 2025-02-25 08:43:13 +01:00
Micha Reiser
d895ee0014 [red-knot] Handle pipe-errors gracefully (#16354) 2025-02-25 08:42:52 +01:00
Micha Reiser
4732c58829 Rename venv-path to python (#16347) 2025-02-24 19:41:06 +01:00
Alex Waygood
45bae29a4b [red-knot] Fixup some formatting in infer.rs (#16348) 2025-02-24 14:44:49 +00:00
Alex Waygood
7059f4249b [red-knot] Restrict visibility of more things in class.rs (#16346) 2025-02-24 14:30:56 +00:00
Mike Perlov
68991d09a8 [red-knot] Add diagnostic for class-object access to pure instance variables (#16036)
## Summary

Add a diagnostic if a pure instance variable is accessed on a class object. For example

```py
class C:
    instance_only: str

    def __init__(self):
        self.instance_only = "a"

# error: Attribute `instance_only` can only be accessed on instances, not on the class object `Literal[C]` itself.
C.instance_only
```


---------

Co-authored-by: David Peter <mail@david-peter.de>
2025-02-24 15:17:16 +01:00
Brent Westbrook
e7a6c19e3a Add per-file-target-version option (#16257)
## Summary

This PR is another step in preparing to detect syntax errors in the
parser. It introduces the new `per-file-target-version` top-level
configuration option, which holds a mapping of compiled glob patterns to
Python versions. I intend to use the
`LinterSettings::resolve_target_version` method here to pass to the
parser:


f50849aeef/crates/ruff_linter/src/linter.rs (L491-L493)

## Test Plan

I added two new CLI tests to show that the `per-file-target-version` is
respected in both the formatter and the linter.
2025-02-24 08:47:13 -05:00
Vasco Schiavo
42a5f5ef6a [PLW1507] Mark fix unsafe (#16343) 2025-02-24 13:42:44 +01:00
Alex Waygood
5bac4f6bd4 [red-knot] Add a test to ensure that KnownClass::try_from_file_and_name() is kept up to date (#16326) 2025-02-24 12:14:20 +00:00
Micha Reiser
320a3c68ae Extract class and instance types (#16337) 2025-02-24 11:36:20 +00:00
Dhruv Manilawala
24e08d17c4 Re-order changelog entries for 0.9.7 (#16344)
## Summary

This is mainly on me for not noticing this during the last release but I
noticed in the last changelog that there's only 1 bug fix which didn't
seem correct as I saw multiple of them so I looked at a couple of PRs
that are in "Rule changes" section and the PRs that were marked with the
`bug` label was categorized there because

1. It _also_ had other labels like `rule` and `fixes`
(https://github.com/astral-sh/ruff/pull/16080,
https://github.com/astral-sh/ruff/pull/16110,
https://github.com/astral-sh/ruff/pull/16219, etc.)
2. Some PRs didn't have the `bug` label (but the issue as marked as
`bug`) but _only_ labels like "fixes"
(https://github.com/astral-sh/ruff/pull/16011,
https://github.com/astral-sh/ruff/pull/16132, etc.)
2025-02-24 09:10:14 +00:00
David Peter
141ba253da [red-knot] Add support for @classmethods (#16305)
## Summary

Add support for `@classmethod`s.

```py
class C:
    @classmethod
    def f(cls, x: int) -> str:
        return "a"

reveal_type(C.f(1))  # revealed: str
```

## Test Plan

New Markdown tests
2025-02-24 09:55:34 +01:00
Micha Reiser
81a57656d8 Update Salsa (#16338) 2025-02-24 09:44:19 +01:00
Micha Reiser
5eaf225fc3 Update Salsa part 1 (#16340) 2025-02-24 09:35:21 +01:00
Micha Reiser
bc018bf2e5 Upgrade Rust toolchain to 1.85.0 (#16339) 2025-02-24 09:20:22 +01:00
renovate[bot]
0fad53d203 Update NPM Development dependencies (#16327)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 08:26:14 +01:00
renovate[bot]
e6b1c89fb7 Update Rust crate clap to v4.5.30 (#16329)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.29` -> `4.5.30` |

---

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

---

### Release Notes

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

###
[`v4.5.30`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4530---2025-02-17)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.29...v4.5.30)

##### Fixes

-   *(assert)* Allow `num_args(0..=1)` to be used with `SetTrue`
-   *(assert)* Clean up rendering of `takes_values` assertions

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 12:18:48 +05:30
renovate[bot]
222588645b Update dependency ruff to v0.9.7 (#16336)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ruff](https://docs.astral.sh/ruff)
([source](https://redirect.github.com/astral-sh/ruff),
[changelog](https://redirect.github.com/astral-sh/ruff/blob/main/CHANGELOG.md))
| `==0.9.6` -> `==0.9.7` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/ruff/0.9.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/ruff/0.9.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/ruff/0.9.6/0.9.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/ruff/0.9.6/0.9.7?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>astral-sh/ruff (ruff)</summary>

###
[`v0.9.7`](https://redirect.github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#097)

[Compare
Source](https://redirect.github.com/astral-sh/ruff/compare/0.9.6...0.9.7)

##### Preview features

- Consider `__new__` methods as special function type for enforcing
class method or static method rules
([#&#8203;13305](https://redirect.github.com/astral-sh/ruff/pull/13305))
- \[`airflow`] Improve the internal logic to differentiate deprecated
symbols (`AIR303`)
([#&#8203;16013](https://redirect.github.com/astral-sh/ruff/pull/16013))
- \[`refurb`] Manual timezone monkeypatching (`FURB162`)
([#&#8203;16113](https://redirect.github.com/astral-sh/ruff/pull/16113))
- \[`ruff`] Implicit class variable in dataclass (`RUF045`)
([#&#8203;14349](https://redirect.github.com/astral-sh/ruff/pull/14349))
- \[`ruff`] Skip singleton starred expressions for
`incorrectly-parenthesized-tuple-in-subscript` (`RUF031`)
([#&#8203;16083](https://redirect.github.com/astral-sh/ruff/pull/16083))
- \[`refurb`] Check for subclasses includes subscript expressions
(`FURB189`)
([#&#8203;16155](https://redirect.github.com/astral-sh/ruff/pull/16155))

##### Rule changes

- \[`flake8-comprehensions`]: Handle trailing comma in `C403` fix
([#&#8203;16110](https://redirect.github.com/astral-sh/ruff/pull/16110))
- \[`flake8-debugger`] Also flag `sys.breakpointhook` and
`sys.__breakpointhook__` (`T100`)
([#&#8203;16191](https://redirect.github.com/astral-sh/ruff/pull/16191))
- \[`pydocstyle`] Handle arguments with the same names as sections
(`D417`)
([#&#8203;16011](https://redirect.github.com/astral-sh/ruff/pull/16011))
- \[`pylint`] Correct ordering of arguments in fix for `if-stmt-min-max`
(`PLR1730`)
([#&#8203;16080](https://redirect.github.com/astral-sh/ruff/pull/16080))
- \[`pylint`] Do not offer fix for raw strings (`PLE251`)
([#&#8203;16132](https://redirect.github.com/astral-sh/ruff/pull/16132))
- \[`pyupgrade`] Do not upgrade functional `TypedDicts` with private
field names to the class-based syntax (`UP013`)
([#&#8203;16219](https://redirect.github.com/astral-sh/ruff/pull/16219))
- \[`pyupgrade`] Handle micro version numbers correctly (`UP036`)
([#&#8203;16091](https://redirect.github.com/astral-sh/ruff/pull/16091))
- \[`pyupgrade`] Unwrap unary expressions correctly (`UP018`)
([#&#8203;15919](https://redirect.github.com/astral-sh/ruff/pull/15919))
- \[`ruff`] Skip `RUF001` diagnostics when visiting string type
definitions
([#&#8203;16122](https://redirect.github.com/astral-sh/ruff/pull/16122))
- \[`flake8-pyi`] Avoid flagging `custom-typevar-for-self` on metaclass
methods (`PYI019`)
([#&#8203;16141](https://redirect.github.com/astral-sh/ruff/pull/16141))
- \[`pycodestyle`] Exempt `site.addsitedir(...)` calls (`E402`)
([#&#8203;16251](https://redirect.github.com/astral-sh/ruff/pull/16251))

##### Formatter

- Fix unstable formatting of trailing end-of-line comments of
parenthesized attribute values
([#&#8203;16187](https://redirect.github.com/astral-sh/ruff/pull/16187))

##### Server

- Fix handling of requests received after shutdown message
([#&#8203;16262](https://redirect.github.com/astral-sh/ruff/pull/16262))
- Ignore `source.organizeImports.ruff` and `source.fixAll.ruff` code
actions for a notebook cell
([#&#8203;16154](https://redirect.github.com/astral-sh/ruff/pull/16154))
- Include document specific debug info for `ruff.printDebugInformation`
([#&#8203;16215](https://redirect.github.com/astral-sh/ruff/pull/16215))
- Update server to return the debug info as string with
`ruff.printDebugInformation`
([#&#8203;16214](https://redirect.github.com/astral-sh/ruff/pull/16214))

##### CLI

- Warn on invalid `noqa` even when there are no diagnostics
([#&#8203;16178](https://redirect.github.com/astral-sh/ruff/pull/16178))
- Better error messages while loading configuration `extend`s
([#&#8203;15658](https://redirect.github.com/astral-sh/ruff/pull/15658))

##### Bug fixes

- \[`refurb`] Correctly handle lengths of literal strings in
`slice-to-remove-prefix-or-suffix` (`FURB188`)
([#&#8203;16237](https://redirect.github.com/astral-sh/ruff/pull/16237))

##### Documentation

- Add FAQ entry for `source.*` code actions in Notebook
([#&#8203;16212](https://redirect.github.com/astral-sh/ruff/pull/16212))
- Add `SECURITY.md`
([#&#8203;16224](https://redirect.github.com/astral-sh/ruff/pull/16224))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 12:01:55 +05:30
renovate[bot]
b7dab13c79 Update Rust crate anyhow to v1.0.96 (#16328)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [anyhow](https://redirect.github.com/dtolnay/anyhow) |
workspace.dependencies | patch | `1.0.95` -> `1.0.96` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/anyhow (anyhow)</summary>

###
[`v1.0.96`](https://redirect.github.com/dtolnay/anyhow/releases/tag/1.0.96)

[Compare
Source](https://redirect.github.com/dtolnay/anyhow/compare/1.0.95...1.0.96)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 12:01:08 +05:30
renovate[bot]
81f6561af4 Update Rust crate libc to v0.2.170 (#16330)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [libc](https://redirect.github.com/rust-lang/libc) |
workspace.dependencies | patch | `0.2.169` -> `0.2.170` |

---

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

---

### Release Notes

<details>
<summary>rust-lang/libc (libc)</summary>

###
[`v0.2.170`](https://redirect.github.com/rust-lang/libc/releases/tag/0.2.170)

[Compare
Source](https://redirect.github.com/rust-lang/libc/compare/0.2.169...0.2.170)

##### Added

- Android: Declare `setdomainname` and `getdomainname`
[#&#8203;4212](https://redirect.github.com/rust-lang/libc/pull/4212)
- FreeBSD: Add `evdev` structures
[#&#8203;3756](https://redirect.github.com/rust-lang/libc/pull/3756)
- FreeBSD: Add the new `st_filerev` field to `stat32`
([#&#8203;4254](https://redirect.github.com/rust-lang/libc/pull/4254))
- Linux: Add ` SI_*`` and `TRAP_\*\`\` signal codes
[#&#8203;4225](https://redirect.github.com/rust-lang/libc/pull/4225)
- Linux: Add experimental configuration to enable 64-bit time in kernel
APIs, set by `RUST_LIBC_UNSTABLE_LINUX_TIME_BITS64`.
[#&#8203;4148](https://redirect.github.com/rust-lang/libc/pull/4148)
- Linux: Add recent socket timestamping flags
[#&#8203;4273](https://redirect.github.com/rust-lang/libc/pull/4273)
- Linux: Added new CANFD_FDF flag for the flags field of canfd_frame
[#&#8203;4223](https://redirect.github.com/rust-lang/libc/pull/4223)
- Musl: add CLONE_NEWTIME
[#&#8203;4226](https://redirect.github.com/rust-lang/libc/pull/4226)
- Solarish: add the posix_spawn family of functions
[#&#8203;4259](https://redirect.github.com/rust-lang/libc/pull/4259)

##### Deprecated

- Linux: deprecate kernel modules syscalls
[#&#8203;4228](https://redirect.github.com/rust-lang/libc/pull/4228)

##### Changed

- Emscripten: Assume version is at least 3.1.42
[#&#8203;4243](https://redirect.github.com/rust-lang/libc/pull/4243)

##### Fixed

- BSD: Correct the definition of `WEXITSTATUS`
[#&#8203;4213](https://redirect.github.com/rust-lang/libc/pull/4213)
- Hurd: Fix CMSG_DATA on 64bit systems
([#&#8203;4240](https://redirect.github.com/rust-lang/libc/pull/424))
- NetBSD: fix `getmntinfo`
([#&#8203;4265](https://redirect.github.com/rust-lang/libc/pull/4265)
- VxWorks: Fix the size of `time_t`
[#&#8203;426](https://redirect.github.com/rust-lang/libc/pull/426)

##### Other

- Add labels to FIXMEs
[#&#8203;4230](https://redirect.github.com/rust-lang/libc/pull/4230),
[#&#8203;4229](https://redirect.github.com/rust-lang/libc/pull/4229),
[#&#8203;4237](https://redirect.github.com/rust-lang/libc/pull/4237)
- CI: Bump FreeBSD CI to 13.4 and 14.2
[#&#8203;4260](https://redirect.github.com/rust-lang/libc/pull/4260)
- Copy definitions from core::ffi and centralize them
[#&#8203;4256](https://redirect.github.com/rust-lang/libc/pull/4256)
- Define c_char at top-level and remove per-target c_char definitions
[#&#8203;4202](https://redirect.github.com/rust-lang/libc/pull/4202)
- Port style.rs to syn and add tests for the style checker
[#&#8203;4220](https://redirect.github.com/rust-lang/libc/pull/4220)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 11:58:01 +05:30
renovate[bot]
c37c078142 Update Rust crate serde_json to v1.0.139 (#16333)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [serde_json](https://redirect.github.com/serde-rs/json) |
workspace.dependencies | patch | `1.0.138` -> `1.0.139` |

---

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

---

### Release Notes

<details>
<summary>serde-rs/json (serde_json)</summary>

###
[`v1.0.139`](https://redirect.github.com/serde-rs/json/releases/tag/v1.0.139)

[Compare
Source](https://redirect.github.com/serde-rs/json/compare/v1.0.138...v1.0.139)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 11:53:12 +05:30
renovate[bot]
dd5f9d1df9 Update Rust crate log to v0.4.26 (#16331)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [log](https://redirect.github.com/rust-lang/log) |
workspace.dependencies | patch | `0.4.25` -> `0.4.26` |

---

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

---

### Release Notes

<details>
<summary>rust-lang/log (log)</summary>

###
[`v0.4.26`](https://redirect.github.com/rust-lang/log/blob/HEAD/CHANGELOG.md#0426---2025-02-18)

[Compare
Source](https://redirect.github.com/rust-lang/log/compare/0.4.25...0.4.26)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 11:52:58 +05:30
renovate[bot]
f05cfe134e Update Rust crate serde to v1.0.218 (#16332)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [serde](https://serde.rs)
([source](https://redirect.github.com/serde-rs/serde)) |
workspace.dependencies | patch | `1.0.217` -> `1.0.218` |

---

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

---

### Release Notes

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

###
[`v1.0.218`](https://redirect.github.com/serde-rs/serde/releases/tag/v1.0.218)

[Compare
Source](https://redirect.github.com/serde-rs/serde/compare/v1.0.217...v1.0.218)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 11:52:14 +05:30
renovate[bot]
a3d8b31cdd Update Rust crate tempfile to v3.17.1 (#16334)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [tempfile](https://stebalien.com/projects/tempfile-rs/)
([source](https://redirect.github.com/Stebalien/tempfile)) |
workspace.dependencies | patch | `3.17.0` -> `3.17.1` |

---

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

---

### Release Notes

<details>
<summary>Stebalien/tempfile (tempfile)</summary>

###
[`v3.17.1`](https://redirect.github.com/Stebalien/tempfile/blob/HEAD/CHANGELOG.md#3171)

[Compare
Source](https://redirect.github.com/Stebalien/tempfile/compare/v3.17.0...v3.17.1)

- Fix build with `windows-sys` 0.52. Unfortunately, we have no CI for
older `windows-sys` versions at the moment...

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 11:51:38 +05:30
renovate[bot]
558282649e Update Rust crate unicode-ident to v1.0.17 (#16335)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [unicode-ident](https://redirect.github.com/dtolnay/unicode-ident) |
workspace.dependencies | patch | `1.0.16` -> `1.0.17` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/unicode-ident (unicode-ident)</summary>

###
[`v1.0.17`](https://redirect.github.com/dtolnay/unicode-ident/releases/tag/1.0.17)

[Compare
Source](https://redirect.github.com/dtolnay/unicode-ident/compare/1.0.16...1.0.17)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 11:50:48 +05:30
Vasco Schiavo
b312b53c2e [flake8-pyi] Mark PYI030 fix unsafe when comments are deleted (#16322) 2025-02-23 21:22:14 +00:00
InSync
c814745643 [flake8-self] Ignore attribute accesses on instance-like variables (SLF001) (#16149) 2025-02-23 10:00:49 +00:00
Ari Pollak
aa88f2dbe5 Fix example for S611 (#16316)
## Summary

* Existing example did not include RawSQL() call like it should
* Also clarify the example a bit to make it clearer that the code is not
secure
## Test Plan

N/A, only documentation updated
2025-02-22 14:15:29 -05:00
Alex Waygood
64effa4aea [red-knot] Add a regression test for recent improvement to TypeInferenceBuilder::infer_name_load() (#16310) 2025-02-21 22:28:42 +00:00
Alex Waygood
224a36f5f3 Teach red-knot that type(x) is the same as x.__class__ (#16301) 2025-02-21 21:05:48 +00:00
Alex Waygood
5347abc766 [red-knot] Generalise special-casing for KnownClasses in Type::bool (#16300) 2025-02-21 20:46:36 +00:00
Micha Reiser
5fab97f1ef [red-knot] Diagnostics for incorrect bool usages (#16238) 2025-02-21 19:26:05 +01:00
David Peter
3aa7ba31b1 [red-knot] Fix descriptor __get__ call on class objects (#16304)
## Summary

I spotted a minor mistake in my descriptor protocol implementation where
`C.descriptor` would pass the meta type (`type`) of the type of `C`
(`Literal[C]`) as the owner argument to `__get__`, instead of passing
`Literal[C]` directly.

## Test Plan

New test.
2025-02-21 15:35:41 +01:00
Douglas Creager
4dae09ecff [red-knot] Better handling of visibility constraint copies (#16276)
Two related changes.  For context:

1. We were maintaining two separate arenas of `Constraint`s in each
use-def map. One was used for narrowing constraints, and the other for
visibility constraints. The visibility constraint arena was interned,
ensuring that we always used the same ID for any particular
`Constraint`. The narrowing constraint arena was not interned.

2. The TDD code relies on _all_ TDD nodes being interned and reduced.
This is an important requirement for TDDs to be a canonical form, which
allows us to use a single int comparison to test for "always true/false"
and to compare two TDDs for equivalence. But we also need to support an
individual `Constraint` having multiple values in a TDD evaluation (e.g.
to handle a `while` condition having different values the first time
it's evaluated vs later times). Previously, we handled that by
introducing a "copy" number, which was only there as a disambiguator, to
allow an interned, deduplicated constraint ID to appear in the TDD
formula multiple times.

A better way to handle (2) is to not intern the constraints in the
visibility constraint arena! The caller now gets to decide: if they add
a `Constraint` to the arena more than once, they get distinct
`ScopedConstraintId`s — which the TDD code will treat as distinct
variables, allowing them to take on different values in the ternary
function.

With that in place, we can then consolidate on a single (non-interned)
arena, which is shared for both narrowing and visibility constraints.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-02-21 09:16:25 -05:00
Darius Carrier
b9b094869a [pylint] Fix false positives, add missing methods, and support positional-only parameters (PLE0302) (#16263)
## Summary

Resolves 3/4 requests in #16217:

-  Remove not special methods: `__cmp__`, `__div__`, `__nonzero__`, and
`__unicode__`.
-  Add special methods: `__next__`, `__buffer__`, `__class_getitem__`,
`__mro_entries__`, `__release_buffer__`, and `__subclasshook__`.
-  Support positional-only arguments.
-  Add support for module functions `__dir__` and `__getattr__`. As
mentioned in the issue the check is scoped for methods rather than
module functions. I am hesitant to expand the scope of this check
without a discussion.

## Test Plan

- Manually confirmed each example file from the issue functioned as
expected.
- Ran cargo nextest to ensure `unexpected_special_method_signature` test
still passed.

Fixes #16217.
2025-02-21 08:38:51 -05:00
Alex Waygood
b3c5932fda [red-knot] Restrict visibility of the module_type_symbols function (#16290) 2025-02-21 10:55:22 +00:00
Alex Waygood
fe3ae587ea [red-knot] Fix subtle detail in where the types.ModuleType attribute lookup should happen in TypeInferenceBuilder::infer_name_load() (#16284) 2025-02-21 10:48:52 +00:00
Dhruv Manilawala
c2b9fa84f7 Refactor workspace logic into workspace.rs (#16295)
## Summary

This is just a small refactor to move workspace related structs and impl
out from `server.rs` where `Server` is defined and into a new
`workspace.rs`.
2025-02-21 08:37:29 +00:00
Victorien
793264db13 [ruff] Add more Pydantic models variants to the list of default copy semantics (RUF012) (#16291) 2025-02-21 08:28:13 +01:00
Carl Meyer
4d63c16c19 [red-knot] update to latest Salsa (#16293)
Update to latest Salsa main branch. This provides a point of comparison
for the perf impact of fixpoint iteration, which is based on latest
Salsa main.

This requires an update to the locked version of our boxcar dep, since
Salsa now depends on a newer version of boxcar.
2025-02-20 18:15:58 -08:00
David Peter
d2e034adcd [red-knot] Method calls and the descriptor protocol (#16121)
## Summary

This PR achieves the following:

* Add support for checking method calls, and inferring return types from
method calls. For example:
  ```py
  reveal_type("abcde".find("abc"))  # revealed: int
  reveal_type("foo".encode(encoding="utf-8"))  # revealed: bytes
  
  "abcde".find(123)  # error: [invalid-argument-type]
  
  class C:
      def f(self) -> int:
          pass
  
  reveal_type(C.f)  # revealed: <function `f`>
  reveal_type(C().f)  # revealed: <bound method: `f` of `C`>
  
  C.f()  # error: [missing-argument]
  reveal_type(C().f())  # revealed: int
  ```
* Implement the descriptor protocol, i.e. properly call the `__get__`
method when a descriptor object is accessed through a class object or an
instance of a class. For example:
  ```py
  from typing import Literal
  
  class Ten:
def __get__(self, instance: object, owner: type | None = None) ->
Literal[10]:
          return 10
  
  class C:
      ten: Ten = Ten()
  
  reveal_type(C.ten)  # revealed: Literal[10]
  reveal_type(C().ten)  # revealed: Literal[10]
  ```
* Add support for member lookup on intersection types.
* Support type inference for `inspect.getattr_static(obj, attr)` calls.
This was mostly used as a debugging tool during development, but seems
more generally useful. It can be used to bypass the descriptor protocol.
For the example above:
  ```py
  from inspect import getattr_static
  
  reveal_type(getattr_static(C, "ten"))  # revealed: Ten
  ```
* Add a new `Type::Callable(…)` variant with the following sub-variants:
* `Type::Callable(CallableType::BoundMethod(…))` — represents bound
method objects, e.g. `C().f` above
* `Type::Callable(CallableType::MethodWrapperDunderGet(…))` — represents
`f.__get__` where `f` is a function
* `Type::Callable(WrapperDescriptorDunderGet)` — represents
`FunctionType.__get__`
* Add new known classes:
  * `types.MethodType`
  * `types.MethodWrapperType`
  * `types.WrapperDescriptorType`
  * `builtins.range`

## Performance analysis

On this branch, we do more work. We need to do more call checking, since
we now check all method calls. We also need to do ~twice as many member
lookups, because we need to check if a `__get__` attribute exists on
accessed members.

A brief analysis on `tomllib` shows that we now call `Type::call` 1780
times, compared to 612 calls before.

## Limitations

* Data descriptors are not yet supported, i.e. we do not infer correct
types for descriptor attribute accesses in `Store` context and do not
check writes to descriptor attributes. I felt like this was something
that could be split out as a follow-up without risking a major
architectural change.
* We currently distinguish between `Type::member` (with descriptor
protocol) and `Type::static_member` (without descriptor protocol). The
former corresponds to `obj.attr`, the latter corresponds to
`getattr_static(obj, "attr")`. However, to model some details correctly,
we would also need to distinguish between a static member lookup *with*
and *without* instance variables. The lookup without instance variables
corresponds to `find_name_in_mro`
[here](https://docs.python.org/3/howto/descriptor.html#invocation-from-an-instance).
We currently approximate both using `member_static`, which leads to two
open TODOs. Changing this would be a larger refactoring of
`Type::own_instance_member`, so I chose to leave it out of this PR.

## Test Plan

* New `call/methods.md` test suite for method calls
* New tests in `descriptor_protocol.md`
* New `call/getattr_static.md` test suite for `inspect.getattr_static`
* Various updated tests
2025-02-20 23:22:26 +01:00
David Peter
f62e5406f2 [red-knot] Short-circuit bool calls on bool (#16292)
## Summary

This avoids looking up `__bool__` on class `bool` for every
`Type::Instance(bool).bool()` call. 1% performance win on cold cache, 4%
win on incremental performance.
2025-02-20 23:06:11 +01:00
Douglas Creager
1be4394155 [red-knot] Consolidate SymbolBindings/SymbolDeclarations state (#16286)
This updates the `SymbolBindings` and `SymbolDeclarations` types to use
a single smallvec of live bindings/declarations, instead of splitting
that out into separate containers for each field.

I'm seeing an 11-13% `cargo bench` performance improvement with this
locally (for both cold and incremental). I'm interested to see if
Codspeed agrees!

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-02-20 16:20:23 -05:00
Micha Reiser
470f852f04 [red-knot] Prevent cross-module query dependencies in own_instance_member (#16268) 2025-02-20 18:46:45 +01:00
Brent Westbrook
b385c7d22a Specify the wasm-pack version for release workflows (#16278)
This PR uses the same version specified in
https://github.com/astral-sh/ruff/pull/14465 for the CI workflow to
prevent random versions from being pulled like in the 0.9.7
[release](https://github.com/astral-sh/ruff/actions/runs/13436100909/job/37539387595).
2025-02-20 10:17:58 -05:00
Douglas Creager
529950fba1 [red-knot] Separate definitions_by_definition into separate fields (#16277)
A minor cleanup that breaks up a `HashMap` of an enum into separate
`HashMap`s for each variant. (These separate fields were already how
this cache was being described in the big comment at the top of the
file!)
2025-02-20 09:47:01 -05:00
Andrew Gallant
205222ca6b red_knot_python_semantic: avoid adding callable_ty to CallBindingError
This is a small tweak to avoid adding the callable `Type` on the error
value itself. Namely, it's always available regardless of the error, and
it's easy to pass it down explicitly to the diagnostic generating code.

It's likely that the other `CallBindingError` variants will also want
the callable `Type` to improve diagnostics too. This way, we don't have
to duplicate the `Type` on each variant. It's just available to all of
them.

Ref https://github.com/astral-sh/ruff/pull/16239#discussion_r1962352646
2025-02-20 08:18:59 -05:00
Brent Westbrook
54fccb3ee2 Bump version to 0.9.7 (#16271) 2025-02-20 08:12:11 -05:00
David Peter
8198668fc3 [red-knot] MDTest: Use custom class names instead of builtins (#16269)
## Summary

Follow up on the discussion
[here](https://github.com/astral-sh/ruff/pull/16121#discussion_r1962973298).
Replace builtin classes with custom placeholder names, which should
hopefully make the tests a bit easier to understand.

I carefully renamed things one after the other, to make sure that there
is no functional change in the tests.
2025-02-20 12:25:55 +00:00
Dhruv Manilawala
fc6b03c8da Handle requests received after shutdown message (#16262)
## Summary

This PR should help in
https://github.com/astral-sh/ruff-vscode/issues/676.

There are two issues that this is trying to fix all related to the way
shutdown should happen as per the protocol:
1. After the server handled the [shutdown
request](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#shutdown)
and while waiting for the exit notification:
	
> If a server receives requests after a shutdown request those requests
should error with `InvalidRequest`.
    
But, we raised an error and exited. This PR fixes it by entering a loop
which responds to any request during this period with `InvalidRequest`

2. If the server received an [exit
notification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#exit)
but the shutdown request was never received, the server handled that by
logging and exiting with success but as per the spec:

> The server should exit with success code 0 if the shutdown request has
been received before; otherwise with error code 1.

    So, this PR fixes that as well by raising an error in this case.

## Test Plan

I'm not sure how to go about testing this without using a mock server.
2025-02-20 11:10:42 +00:00
Micha Reiser
fb09d63e55 [red-knot] Prefix Type::call and dunder_call with try (#16261) 2025-02-20 09:05:04 +00:00
Alex Waygood
16d0625dfb Improve internal docs for various string-node APIs (#16256) 2025-02-19 16:13:45 +00:00
Alex Waygood
25920fe489 Rename ExprStringLiteral::as_unconcatenated_string() to ExprStringLiteral::as_single_part_string() (#16253) 2025-02-19 16:06:57 +00:00
Brent Westbrook
97d0659ce3 Pass ParserOptions to the parser (#16220)
## Summary

This is part of the preparation for detecting syntax errors in the
parser from https://github.com/astral-sh/ruff/pull/16090/. As suggested
in [this
comment](https://github.com/astral-sh/ruff/pull/16090/#discussion_r1953084509),
I started working on a `ParseOptions` struct that could be stored in the
parser. For this initial refactor, I only made it hold the existing
`Mode` option, but for syntax errors, we will also need it to have a
`PythonVersion`. For that use case, I'm picturing something like a
`ParseOptions::with_python_version` method, so you can extend the
current calls to something like

```rust
ParseOptions::from(mode).with_python_version(settings.target_version)
```

But I thought it was worth adding `ParseOptions` alone without changing
any other behavior first.

Most of the diff is just updating call sites taking `Mode` to take
`ParseOptions::from(Mode)` or those taking `PySourceType`s to take
`ParseOptions::from(PySourceType)`. The interesting changes are in the
new `parser/options.rs` file and smaller parts of `parser/mod.rs` and
`ruff_python_parser/src/lib.rs`.

## Test Plan

Existing tests, this should not change any behavior.
2025-02-19 10:50:50 -05:00
Douglas Creager
cfc6941d5c [red-knot] Resolve references in eager nested scopes eagerly (#16079)
We now resolve references in "eager" scopes correctly — using the
bindings and declarations that are visible at the point where the eager
scope is created, not the "public" type of the symbol (typically the
bindings visible at the end of the scope).

---------

Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-02-19 10:22:30 -05:00
Alex Waygood
f50849aeef Add text_len() methods to more *Prefix enums in ruff_python_ast (#16254) 2025-02-19 14:47:07 +00:00
Micha Reiser
55ea09401a [red-knot] Allow any Ranged argument for report_lint and report_diagnostic (#16252) 2025-02-19 14:34:56 +01:00
Vasco Schiavo
3032867603 [pycodestyle] Exempt site.addsitedir(...) calls (E402) (#16251) 2025-02-19 14:31:47 +01:00
Andrew Gallant
3ea32e2cdd red_knot_python_semantic: improve diagnostic message for "invalid argument type"
This uses the refactoring and support for secondary diagnostic messages
to improve the diagnostic for "invalid argument type." The main
improvement here is that we show where the function being called is
defined, and annotate the span corresponding to the invalid parameter.
2025-02-19 08:24:19 -05:00
Andrew Gallant
87668e24b1 ruff_db: add "secondary" messages to Diagnostic trait
This is a small little hack to make the `Diagnostic` trait
capable of supporting attaching multiple spans.

This design should be considered transient. This was just the
quickest way that I could see to pass multiple spans through from
the type checker to the diagnostic renderer.
2025-02-19 08:24:19 -05:00
Andrew Gallant
18a9eddf60 ruff_db: refactor snippet rendering
This commit has no behavioral changes.

This refactor moves the logic for turning a `D: Diagnostic` into
an `annotate_snippets::Message` into its own types. This would
ideally just be a function or something, but the `annotate-snippets`
types want borrowed data, and sometimes we need to produce owned
data. So we gather everything we need into our own types and then
spit it back out in the format that `annotate-snippets` wants.

This factor was motivated by wanting to render multiple snippets.
The logic for generating a code frame is complicated enough that
it's worth splitting out so that we can reuse it for other spans.

(Note that one should consider this prototype-level code. It is
unlikely to survive for long.)
2025-02-19 08:24:19 -05:00
Andrew Gallant
222660170c red_knot_python_semantic: remove Ranged impl for TypeCheckDiagnostic
It seems nothing is using it, and I'm not sure if it makes semantic
sense. Particularly if we want to support multiple ranges. One could
make an argument that this ought to correspond to the "primary"
range (which we should have), but I think such a concept is better
expressed as an explicit routine if possible.
2025-02-19 08:24:19 -05:00
Micha Reiser
e84985e9b3 [red-knot] Refactor infer_chained_boolean_types to have access to TypeInferenceBuilder (#16222) 2025-02-19 11:13:35 +01:00
InSync
01c3e6b94f Add red_knot/README.md (#16230)
## Summary

Resolves #15979.

The file explains what Red Knot is (a type checker), what state it is in
(not yet ready for user testing), what its goals ("extremely fast") and
non-goals (not a drop-in replacement for other type checkers) are as
well as what the crates contain.

## Test Plan

None.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-18 23:31:02 -08:00
Wei Lee
e92d43dfcd [airflow] move class attributed related cases to AIR302_class_attribute (AIR302) (#16226)
## Summary


Move class attribute (property, methods, variables) related cases in
AIR302_names to AIR302_class_attribute

## Test Plan


No functionality change. Test fixture is reogranized
2025-02-19 11:13:17 +05:30
David Peter
877c1066d3 [red-knot] Update tests for attributes inferred from parameters (#16208)
## Summary

Update description and remove TODOs from out `attributes.md` test suite
to reflect our current intentions.

closes https://github.com/astral-sh/ruff/issues/15960
2025-02-18 22:43:11 +01:00
Carl Meyer
00b022d472 [red-knot] update TODO comment in mdtest (#16242)
This comment gave wrong/misleading info about the reason for the wrong
output, just updating it to be correct to avoid confusing our future
selves.
2025-02-18 20:52:17 +00:00
Dylan
a23e489c79 [refurb] Correctly handle lengths of literal strings in slice-to-remove-prefix-or-suffix (FURB188) (#16237)
Fixes false negative when slice bound uses length of string literal.

We were meant to check the following, for example. Given:

```python
  text[:bound] if text.endswith(suffix) else text
```
We want to know whether:
   - `suffix` is a string literal and `bound` is a number literal
   - `suffix` is an expression and `bound` is
       exactly `-len(suffix)` (as AST nodes, prior to evaluation.)
       
The issue is that negative number literals like `-10` are stored as
unary operators applied to a number literal in the AST. So when `suffix`
was a string literal but `bound` was `-len(suffix)` we were getting
caught in the match arm where `bound` needed to be a number. This is now
fixed with a guard.


Closes #16231
2025-02-18 12:52:26 -06:00
Brent Westbrook
1907e60fab Pass ast::PythonVersion to type_hint_resolves_to_any (#16236)
This is a follow-up to #16170 to use `ast::PythonVersion` in the
`type_hint_resolves_to_any` call chain, as suggested (and implemented!)
by Alex
[here](https://github.com/astral-sh/ruff/pull/16170#discussion_r1960015181).

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-18 13:22:50 -05:00
Brent Westbrook
a9efdea113 Use ast::PythonVersion internally in the formatter and linter (#16170)
## Summary

This PR updates the formatter and linter to use the `PythonVersion`
struct from the `ruff_python_ast` crate internally. While this doesn't
remove the need for the `linter::PythonVersion` enum, it does remove the
`formatter::PythonVersion` enum and limits the use in the linter to
deserializing from CLI arguments and config files and moves most of the
remaining methods to the `ast::PythonVersion` struct.

## Test Plan

Existing tests, with some inputs and outputs updated to reflect the new
(de)serialization format. I think these are test-specific and shouldn't
affect any external (de)serialization.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-18 12:03:13 -05:00
InSync
0868e73d2c Add SECURITY.md (#16224)
## Summary

Resolves #16206.

The file was copied almost verbatim from
[uv's](929e7c3ad9/SECURITY.md),
with the first section removed.

## Test Plan

None.
2025-02-18 08:42:55 -06:00
InSync
711af0d929 [refurb] Manual timezone monkeypatching (FURB162) (#16113)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-18 14:35:33 +01:00
sobolevn
d8e3fcca97 [pyupgrade] Do not upgrade functional TypedDicts with private field names to the class-based syntax (UP013) (#16219) 2025-02-18 13:03:27 +00:00
Alex Waygood
66a0467305 Improve docs for PYI019 (#16229) 2025-02-18 12:52:46 +00:00
Micha Reiser
4ed5db0d42 Refactor CallOutcome to Result (#16161) 2025-02-18 13:34:39 +01:00
Alex Waygood
5cd0de3e4c Fix minor punctuation errors (#16228)
Co-authored-by: eqsdxr <rxdsqe@gmail.com>
2025-02-18 12:24:57 +00:00
Dhruv Manilawala
ed9c18d9b4 Include document specific debug info (#16215)
## Summary

Related https://github.com/astral-sh/ruff-vscode/pull/692.

## Test Plan

**When there's no active text document:**

```
[Info  - 10:57:03 PM] Global:
executable = /Users/dhruv/work/astral/ruff/target/debug/ruff
version = 0.9.6
position_encoding = UTF16
workspace_root_folders = [
    "/Users/dhruv/playground/ruff",
]
indexed_configuration_files = [
    "/Users/dhruv/playground/ruff/pyproject.toml",
    "/Users/dhruv/playground/ruff/formatter/ruff.toml",
]
open_documents = 0
client_capabilities = ResolvedClientCapabilities {
    code_action_deferred_edit_resolution: true,
    apply_edit: true,
    document_changes: true,
    workspace_refresh: true,
    pull_diagnostics: true,
}

global_client_settings = ResolvedClientSettings {
    fix_all: true,
    organize_imports: true,
    lint_enable: true,
    disable_rule_comment_enable: true,
    fix_violation_enable: true,
    show_syntax_errors: true,
    editor_settings: ResolvedEditorSettings {
        configuration: None,
        lint_preview: None,
        format_preview: None,
        select: None,
        extend_select: None,
        ignore: None,
        exclude: None,
        line_length: None,
        configuration_preference: EditorFirst,
    },
}
```

**When there's an active text document that's been passed as param:**

```
[Info  - 10:53:33 PM] Global:
executable = /Users/dhruv/work/astral/ruff/target/debug/ruff
version = 0.9.6
position_encoding = UTF16
workspace_root_folders = [
    "/Users/dhruv/playground/ruff",
]
indexed_configuration_files = [
    "/Users/dhruv/playground/ruff/pyproject.toml",
    "/Users/dhruv/playground/ruff/formatter/ruff.toml",
]
open_documents = 1
client_capabilities = ResolvedClientCapabilities {
    code_action_deferred_edit_resolution: true,
    apply_edit: true,
    document_changes: true,
    workspace_refresh: true,
    pull_diagnostics: true,
}

Document:
uri = file:///Users/dhruv/playground/ruff/lsp/play.py
kind = Text
version = 1
client_settings = ResolvedClientSettings {
    fix_all: true,
    organize_imports: true,
    lint_enable: true,
    disable_rule_comment_enable: true,
    fix_violation_enable: true,
    show_syntax_errors: true,
    editor_settings: ResolvedEditorSettings {
        configuration: None,
        lint_preview: None,
        format_preview: None,
        select: None,
        extend_select: None,
        ignore: None,
        exclude: None,
        line_length: None,
        configuration_preference: EditorFirst,
    },
}
config_path = Some("/Users/dhruv/playground/ruff/pyproject.toml")

...
```

Replace `...` at the end with the output of `ruff check --show-settings
path.py`
2025-02-18 15:38:30 +05:30
Dhruv Manilawala
bb2a712f6a Update server to return the debug info as string (#16214)
## Summary

This PR updates the `ruff.printDebugInformation` command to return the
info as string in the response. Currently, we send a `window/logMessage`
request with the info but that has the disadvantage that it's not
visible to the user directly.

What `rust-analyzer` does with it's `rust-analyzer/status` request which
returns it as a string which then the client can just display it in a
separate window. This is what I'm thinking of doing as well.

Other editors can also benefit from it by directly opening a temporary
file with this information that the user can see directly.

There are couple of options here:
1. Keep using the command, keep the log request and return the string
2. Keep using the command, remove the log request and return the string
3. Create a new request similar to `rust-analyzer/status` which returns
a string

This PR implements (1) but I'd want to move towards (2) and remove the
log request completely. We haven't advertised it as such so this would
only require updating the VS Code extension to handle it by opening a
new document with the debug content.

## Test plan

For VS Code, refer to https://github.com/astral-sh/ruff-vscode/pull/694.

For Neovim, one could do:
```lua
local function execute_ruff_command(command)
  local client = vim.lsp.get_clients({ 
    bufnr = vim.api.nvim_get_current_buf(), 
    name = name,
    method = 'workspace/executeCommand',
  })[1]
  if not client then
    return
  end
  client.request('workspace/executeCommand', {
    command = command,
    arguments = {
      { uri = vim.uri_from_bufnr(0) }
    },
    function(err, result)
      if err then
        -- log error
        return
      end
      vim.print(result)
      -- Or, open a new window with the `result` content
    end
  }
```
2025-02-18 15:16:41 +05:30
Wei Lee
2d8ccfe6f2 [airflow] Group ImportPathMoved and ProviderName to avoid misusing (AIR303) (#16157)
## Summary

Separate ImportPathMoved and ProviderName to avoid misusing (AIR303)

## Test Plan

only code arrangement is updated. existing test fixture should be not be
changed
2025-02-18 15:11:58 +05:30
Micha Reiser
31180a84e4 Fix unstable formatting of trailing end-of-line comments of parenthesized attribute values (#16187) 2025-02-18 08:43:51 +01:00
Dhruv Manilawala
82eae511ca Ignore source code actions for a notebook cell (#16154)
## Summary

Related to https://github.com/astral-sh/ruff-vscode/pull/686, this PR
ignores handling source code actions for notebooks which are not
prefixed with `notebook`.

The main motivation is that the native server does not actually handle
it well which results in gibberish code. There's some context about this
in
https://github.com/astral-sh/ruff-vscode/issues/680#issuecomment-2647490812
and the following comments.

closes: https://github.com/astral-sh/ruff-vscode/issues/680

## Test Plan

Running a notebook with the following does nothing except log the
message:
```json
  "notebook.codeActionsOnSave": {
    "source.organizeImports.ruff": "explicit",
  },
```

while, including the `notebook` code actions does make the edit (as
usual):
```json
  "notebook.codeActionsOnSave": {
    "notebook.source.organizeImports.ruff": "explicit"
  },
```
2025-02-18 10:28:03 +05:30
Dhruv Manilawala
b5cd4f2f70 Add FAQ entry for source.* code actions in Notebook (#16212)
## Summary

This PR adds a FAQ entry to provide a brief explanation on why Ruff does
not support `source.*` code actions for Notebook.
2025-02-17 20:04:33 +05:30
Dhruv Manilawala
9f111eaebf red-knot: move symbol lookups in symbol.rs (#16152)
## Summary

This PR does the following:
* Moves the following from `types.rs` in `symbol.rs`:
	* `symbol`
	* `global_symbol`
	* `imported_symbol`
	* `symbol_from_bindings`
	* `symbol_from_declarations`
	* `SymbolAndQualifiers`
	* `SymbolFromDeclarationsResult`
* Moves the following from `stdlib.rs` in `symbol.rs` and removes
`stdlib.rs`:
	* `known_module_symbol`
	* `builtins_symbol`
	* `typing_symbol` (only for tests)
	* `typing_extensions_symbol`
	* `builtins_module_scope`
	* `core_module_scope`
* Add `symbol_from_bindings_impl` and `symbol_from_declarations_impl` to
keep `RequiresExplicitReExport` an implementation detail
* Make `declaration_type` a `pub(crate)` as it's required in
`symbol_from_declarations` (`binding_type` is already `pub(crate)`

The main motivation is to keep the implementation details private and
only expose an ergonomic API which uses sane defaults for various
scenario to avoid any mistakes from the caller. Refer to
https://github.com/astral-sh/ruff/pull/16133#discussion_r1955262772,
https://github.com/astral-sh/ruff/pull/16133#issue-2850146612 for
details.
2025-02-17 17:45:38 +05:30
purajit
9304fdf4ec better error messages while loading configuration extends (#15658)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-17 10:35:30 +01:00
Micha Reiser
0babbca43f Format index.css (#16207)
## Summary

I did ran the NPM dev commands before merging
https://github.com/astral-sh/ruff/pull/16199 but I didn't notice that
one file got reformatted.

This PR formats the `index.css` with the now used Prettier version.
2025-02-17 08:38:26 +00:00
Alex Waygood
b6b1947010 Improve API exposed on ExprStringLiteral nodes (#16192)
## Summary

This PR makes the following changes:
- It adjusts various callsites to use the new
`ast::StringLiteral::contents_range()` method that was introduced in
https://github.com/astral-sh/ruff/pull/16183. This is less verbose and
more type-safe than using the `ast::str::raw_contents()` helper
function.
- It adds a new `ast::ExprStringLiteral::as_unconcatenated_literal()`
helper method, and adjusts various callsites to use it. This addresses
@MichaReiser's review comment at
https://github.com/astral-sh/ruff/pull/16183#discussion_r1957334365.
There is no functional change here, but it helps readability to make it
clearer that we're differentiating between implicitly concatenated
strings and unconcatenated strings at various points.
- It renames the `StringLiteralValue::flags()` method to
`StringLiteralFlags::first_literal_flags()`. If you're dealing with an
implicitly concatenated string `string_node`,
`string_node.value.flags().closer_len()` could give an incorrect result;
this renaming makes it clearer that the `StringLiteralFlags` instance
returned by the method is only guaranteed to give accurate information
for the first `StringLiteral` contained in the `ExprStringLiteral` node.
- It deletes the unused `BytesLiteralValue::flags()` method. This seems
prone to misuse in the same way as `StringLiteralValue::flags()`: if
it's an implicitly concatenated bytestring, the `BytesLiteralFlags`
instance returned by the method would only give accurate information for
the first `BytesLiteral` in the bytestring.

## Test Plan

`cargo test`
2025-02-17 07:58:54 +00:00
renovate[bot]
21999b3be7 Update Rust crate tempfile to v3.17.0 (#16202)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [tempfile](https://stebalien.com/projects/tempfile-rs/)
([source](https://redirect.github.com/Stebalien/tempfile)) |
workspace.dependencies | minor | `3.16.0` -> `3.17.0` |

---

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

---

### Release Notes

<details>
<summary>Stebalien/tempfile (tempfile)</summary>

###
[`v3.17.0`](https://redirect.github.com/Stebalien/tempfile/blob/HEAD/CHANGELOG.md#3170)

[Compare
Source](https://redirect.github.com/Stebalien/tempfile/compare/v3.16.0...v3.17.0)

- Make sure to use absolute paths in when creating unnamed temporary
files (avoids a small race in the "immediate unlink" logic) and in
`Builder::make_in` (when creating temporary files of arbitrary types).
- Prevent a theoretical crash that could (maybe) happen when a temporary
file is created from a drop function run in a TLS destructor. Nobody has
actually reported a case of this happening in practice and I have been
unable to create this scenario in a test.
- When reseeding with `getrandom`, use platform (e.g., CPU) specific
randomness sources where possible.
-   Clarify some documentation.
- Unlink unnamed temporary files on windows *immediately* when possible
instead of waiting for the handle to be closed. We open files with
"Unix" semantics, so this is generally possible.

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-17 08:37:33 +01:00
renovate[bot]
1ecc6a0d19 Update cloudflare/wrangler-action action to v3.14.0 (#16203)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[cloudflare/wrangler-action](https://redirect.github.com/cloudflare/wrangler-action)
| action | minor | `v3.13.1` -> `v3.14.0` |

---

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

---

### Release Notes

<details>
<summary>cloudflare/wrangler-action
(cloudflare/wrangler-action)</summary>

###
[`v3.14.0`](https://redirect.github.com/cloudflare/wrangler-action/releases/tag/v3.14.0)

[Compare
Source](https://redirect.github.com/cloudflare/wrangler-action/compare/v3.13.1...v3.14.0)

##### Minor Changes

-
[#&#8203;351](https://redirect.github.com/cloudflare/wrangler-action/pull/351)
[`4ff07f4`](4ff07f4310)
Thanks [@&#8203;Maximo-Guk](https://redirect.github.com/Maximo-Guk)! -
Use wrangler outputs for version upload and wrangler deploy

##### Patch Changes

-
[#&#8203;350](https://redirect.github.com/cloudflare/wrangler-action/pull/350)
[`e209094`](e209094e62)
Thanks [@&#8203;Maximo-Guk](https://redirect.github.com/Maximo-Guk)! -
Handle failures in createGitHubDeployment and createGitHubJobSummary

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:32:33 +01:00
renovate[bot]
79f43c9cab Update NPM Development dependencies (#16199)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@cloudflare/workers-types](https://redirect.github.com/cloudflare/workerd)
| [`4.20250204.0` ->
`4.20250214.0`](https://renovatebot.com/diffs/npm/@cloudflare%2fworkers-types/4.20250204.0/4.20250214.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@cloudflare%2fworkers-types/4.20250214.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@cloudflare%2fworkers-types/4.20250214.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@cloudflare%2fworkers-types/4.20250204.0/4.20250214.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@cloudflare%2fworkers-types/4.20250204.0/4.20250214.0?slim=true)](https://docs.renovatebot.com/merge-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.8` ->
`19.0.9`](https://renovatebot.com/diffs/npm/@types%2freact/19.0.8/19.0.9)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2freact/19.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2freact/19.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2freact/19.0.8/19.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2freact/19.0.8/19.0.9?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.23.0` ->
`8.24.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2feslint-plugin/8.23.0/8.24.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2feslint-plugin/8.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2feslint-plugin/8.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2feslint-plugin/8.23.0/8.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2feslint-plugin/8.23.0/8.24.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.23.0` ->
`8.24.0`](https://renovatebot.com/diffs/npm/@typescript-eslint%2fparser/8.23.0/8.24.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@typescript-eslint%2fparser/8.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@typescript-eslint%2fparser/8.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@typescript-eslint%2fparser/8.23.0/8.24.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@typescript-eslint%2fparser/8.23.0/8.24.0?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.20250129.0` ->
`3.20250204.1`](https://renovatebot.com/diffs/npm/miniflare/3.20250129.0/3.20250204.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/miniflare/3.20250204.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/miniflare/3.20250204.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/miniflare/3.20250129.0/3.20250204.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/miniflare/3.20250129.0/3.20250204.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [postcss](https://postcss.org/)
([source](https://redirect.github.com/postcss/postcss)) | [`8.5.1` ->
`8.5.2`](https://renovatebot.com/diffs/npm/postcss/8.5.1/8.5.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/postcss/8.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/postcss/8.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/postcss/8.5.1/8.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/postcss/8.5.1/8.5.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [prettier](https://prettier.io)
([source](https://redirect.github.com/prettier/prettier)) | [`3.5.0` ->
`3.5.1`](https://renovatebot.com/diffs/npm/prettier/3.5.0/3.5.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.5.0/3.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.5.0/3.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.107.3` ->
`3.109.1`](https://renovatebot.com/diffs/npm/wrangler/3.107.3/3.109.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/wrangler/3.109.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/wrangler/3.109.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/wrangler/3.107.3/3.109.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/wrangler/3.107.3/3.109.1?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>cloudflare/workerd (@&#8203;cloudflare/workers-types)</summary>

###
[`v4.20250214.0`](2c2b2d00d5...28b2bb16d9)

[Compare
Source](2c2b2d00d5...28b2bb16d9)

</details>

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

###
[`v8.24.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#8240-2025-02-10)

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

##### 🚀 Features

- **eslint-plugin:** \[no-unnecessary-condition] make
`allowConstantLoopConditions` more granular
([#&#8203;10639](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10639))

##### 🩹 Fixes

- **eslint-plugin:** \[no-misused-spread] correct and elaborate string
spread report message
([#&#8203;10751](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10751))
- **eslint-plugin:** \[restrict-plus-operands] report adding bigints to
strings when `allowNumberAndString` is `false`
([#&#8203;10737](https://redirect.github.com/typescript-eslint/typescript-eslint/pull/10737))

##### ❤️ Thank You

-   Josh Goldberg 
-   noah
-   Ronen Amiel

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.24.0`](https://redirect.github.com/typescript-eslint/typescript-eslint/blob/HEAD/packages/parser/CHANGELOG.md#8240-2025-02-10)

[Compare
Source](https://redirect.github.com/typescript-eslint/typescript-eslint/compare/v8.23.0...v8.24.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>cloudflare/workers-sdk (miniflare)</summary>

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

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

##### Patch Changes

-
[#&#8203;7950](https://redirect.github.com/cloudflare/workers-sdk/pull/7950)
[`4db1fb5`](4db1fb5696)
Thanks [@&#8203;cmackenzie1](https://redirect.github.com/cmackenzie1)! -
Add local binding support for Worker Pipelines

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

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

##### Patch Changes

-
[#&#8203;8032](https://redirect.github.com/cloudflare/workers-sdk/pull/8032)
[`c80dbd8`](c80dbd8d5e)
Thanks
[@&#8203;dependabot](https://redirect.github.com/apps/dependabot)! -
chore: update dependencies of "miniflare" package

    The following dependency versions have been updated:

    | Dependency                | From          | To            |
    | ------------------------- | ------------- | ------------- |
    | workerd                   | 1.20250129.0  | 1.20250204.0  |
|
[@&#8203;cloudflare/workers-types](https://redirect.github.com/cloudflare/workers-types)
| ^4.20250129.0 | ^4.20250204.0 |

-
[#&#8203;7290](https://redirect.github.com/cloudflare/workers-sdk/pull/7290)
[`0c0374c`](0c0374cce3)
Thanks [@&#8203;emily-shen](https://redirect.github.com/emily-shen)! -
fix: add support for workers with assets when running multiple workers
in one `wrangler dev` instance


[https://github.com/cloudflare/workers-sdk/pull/7251](https://redirect.github.com/cloudflare/workers-sdk/pull/7251)
added support for running multiple Workers in one `wrangler
dev`/miniflare session. e.g. `wrangler dev -c wrangler.toml -c
../worker2/wrangler.toml`, which among other things, allowed
cross-service RPC to Durable Objects.

However this did not work in the same way as production when there was a
Worker with assets - this PR should fix that.

</details>

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

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

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

- Fixed end position of rules with semicolon (by
[@&#8203;romainmenke](https://redirect.github.com/romainmenke)).

</details>

<details>
<summary>prettier/prettier (prettier)</summary>

###
[`v3.5.1`](https://redirect.github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#351)

[Compare
Source](https://redirect.github.com/prettier/prettier/compare/3.5.0...3.5.1)


[diff](https://redirect.github.com/prettier/prettier/compare/3.5.0...3.5.1)

##### Fix CLI crash when cache for old version exists
([#&#8203;17100](https://redirect.github.com/prettier/prettier/pull/17100)
by [@&#8203;sosukesuzuki](https://redirect.github.com/sosukesuzuki))

Prettier 3.5 uses a different cache format than previous versions,
Prettier 3.5.0 crashes when reading existing cache file, Prettier 3.5.1
fixed the problem.

##### Support dockercompose and github-actions-workflow in VSCode
([#&#8203;17101](https://redirect.github.com/prettier/prettier/pull/17101)
by [@&#8203;remcohaszing](https://redirect.github.com/remcohaszing))

Prettier now supports the `dockercompose` and `github-actions-workflow`
languages in Visual Studio Code.

</details>

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

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

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

##### Patch Changes

-
[#&#8203;8021](https://redirect.github.com/cloudflare/workers-sdk/pull/8021)
[`28b1dc7`](28b1dc7c6f)
Thanks [@&#8203;0xD34DC0DE](https://redirect.github.com/0xD34DC0DE)! -
fix: prevent \__cf_cjs name collision in the hybrid Nodejs compat plugin

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

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

##### Minor Changes

-
[#&#8203;8120](https://redirect.github.com/cloudflare/workers-sdk/pull/8120)
[`3fb801f`](3fb801f734)
Thanks [@&#8203;sdnts](https://redirect.github.com/sdnts)! - Add a new
`update` subcommand for Queues to allow updating Queue settings

-
[#&#8203;8120](https://redirect.github.com/cloudflare/workers-sdk/pull/8120)
[`3fb801f`](3fb801f734)
Thanks [@&#8203;sdnts](https://redirect.github.com/sdnts)! - Allow
overriding message retention duration when creating Queues

-
[#&#8203;8026](https://redirect.github.com/cloudflare/workers-sdk/pull/8026)
[`542c6ea`](542c6ead5d)
Thanks [@&#8203;penalosa](https://redirect.github.com/penalosa)! - Add
`--outfile` to `wrangler deploy` for generating a worker bundle.

This is an advanced feature that most users won't need to use. When set,
Wrangler will output your built Worker bundle in a Cloudflare specific
format that captures all information needed to deploy a Worker using the
[Worker Upload
API](https://developers.cloudflare.com/api/resources/workers/subresources/scripts/methods/update/)

-
[#&#8203;8026](https://redirect.github.com/cloudflare/workers-sdk/pull/8026)
[`542c6ea`](542c6ead5d)
Thanks [@&#8203;penalosa](https://redirect.github.com/penalosa)! - Add a
`wrangler check startup` command to generate a CPU profile of your
Worker's startup phase.

This can be imported into Chrome DevTools or opened directly in VSCode
to view a flamegraph of your Worker's startup phase. Additionally, when
a Worker deployment fails with a startup time error Wrangler will
automatically generate a CPU profile for easy investigation.

    Advanced usage:

- `--args`: to customise the way `wrangler check startup` builds your
Worker for analysis, provide the exact arguments you use when deploying
your Worker with `wrangler deploy`. For instance, if you deploy your
Worker with `wrangler deploy --no-bundle`, you should use `wrangler
check startup --args="--no-bundle"` to profile the startup phase.
- `--worker-bundle`: if you don't use Wrangler to deploy your Worker,
you can use this argument to provide a Worker bundle to analyse. This
should be a file path to a serialised multipart upload, with the exact
same format as the API expects:
https://developers.cloudflare.com/api/resources/workers/subresources/scripts/methods/update/

##### Patch Changes

-
[#&#8203;8112](https://redirect.github.com/cloudflare/workers-sdk/pull/8112)
[`fff677e`](fff677e35f)
Thanks [@&#8203;penalosa](https://redirect.github.com/penalosa)! - When
reporting errors to Sentry, Wrangler will now include the console output
as additional metadata

-
[#&#8203;8120](https://redirect.github.com/cloudflare/workers-sdk/pull/8120)
[`3fb801f`](3fb801f734)
Thanks [@&#8203;sdnts](https://redirect.github.com/sdnts)! - Check
bounds when overriding delivery delay when creating Queues

-
[#&#8203;7950](https://redirect.github.com/cloudflare/workers-sdk/pull/7950)
[`4db1fb5`](4db1fb5696)
Thanks [@&#8203;cmackenzie1](https://redirect.github.com/cmackenzie1)! -
Add local binding support for Worker Pipelines

-
[#&#8203;8119](https://redirect.github.com/cloudflare/workers-sdk/pull/8119)
[`1bc60d7`](1bc60d761e)
Thanks [@&#8203;penalosa](https://redirect.github.com/penalosa)! -
Output correct config format from `wrangler d1 create`. Previously, this
command would always output TOML, regardless of the config file format

-
[#&#8203;8130](https://redirect.github.com/cloudflare/workers-sdk/pull/8130)
[`1aa2a91`](1aa2a91985)
Thanks [@&#8203;emily-shen](https://redirect.github.com/emily-shen)! -
Include default values for wrangler types --path and --x-include-runtime
in telemetry

    User provided strings are still left redacted as always.

-
[#&#8203;8061](https://redirect.github.com/cloudflare/workers-sdk/pull/8061)
[`35710e5`](35710e590f)
Thanks [@&#8203;emily-shen](https://redirect.github.com/emily-shen)! -
fix: respect `WRANGLER_LOG` in `wrangler dev`

Previously, `--log-level=debug` was the only way to see debug logs in
`wrangler dev`, which was unlike all other commands.

- Updated dependencies
\[[`4db1fb5`](4db1fb5696)]:
    -   miniflare@3.20250204.1

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

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

##### Patch Changes

-
[#&#8203;8103](https://redirect.github.com/cloudflare/workers-sdk/pull/8103)
[`a025ad2`](a025ad2ecb)
Thanks [@&#8203;emily-shen](https://redirect.github.com/emily-shen)! -
fix: fix bug where `wrangler secret list --format=json` was printing the
wrangler banner.

-   Updated dependencies \[]:
    -   miniflare@3.20250204.0

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

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

##### Minor Changes

-
[#&#8203;7990](https://redirect.github.com/cloudflare/workers-sdk/pull/7990)
[`b1966df`](b1966dfe57)
Thanks [@&#8203;cmsparks](https://redirect.github.com/cmsparks)! - Add
WRANGLER_CI_OVERRIDE_NAME for Workers CI

-
[#&#8203;8028](https://redirect.github.com/cloudflare/workers-sdk/pull/8028)
[`b2dca9a`](b2dca9a2fb)
Thanks [@&#8203;emily-shen](https://redirect.github.com/emily-shen)! -
feat: Also log when *no* bindings are found.

We currently print a worker's bindings during dev, versions upload and
deploy. This just also prints something when there's no bindings found,
in case you *were* expecting bindings.

-
[#&#8203;8037](https://redirect.github.com/cloudflare/workers-sdk/pull/8037)
[`71fd250`](71fd250f67)
Thanks
[@&#8203;WillTaylorDev](https://redirect.github.com/WillTaylorDev)! -
Provides unsafe.metadata configurations when using wrangler versions
secret put.

##### Patch Changes

-
[#&#8203;8058](https://redirect.github.com/cloudflare/workers-sdk/pull/8058)
[`1f80d69`](1f80d69f56)
Thanks
[@&#8203;WillTaylorDev](https://redirect.github.com/WillTaylorDev)! -
Bugfix: Modified versions secret put to inherit all known bindings,
which circumvents a limitation in the API which does not return all
fields for all bindings.

-
[#&#8203;7986](https://redirect.github.com/cloudflare/workers-sdk/pull/7986)
[`88514c8`](88514c82d4)
Thanks [@&#8203;andyjessop](https://redirect.github.com/andyjessop)! -
docs: clarifies that local resources are "simulated locally" or
"connected to remote resource", and adds console messages to help
explain local dev

-
[#&#8203;8008](https://redirect.github.com/cloudflare/workers-sdk/pull/8008)
[`9d08af8`](9d08af8189)
Thanks [@&#8203;ns476](https://redirect.github.com/ns476)! - Add support
for Images bindings (in private beta for now), with optional local
support for platforms where Sharp is available.

-
[#&#8203;7769](https://redirect.github.com/cloudflare/workers-sdk/pull/7769)
[`6abe69c`](6abe69c3fe)
Thanks [@&#8203;cmackenzie1](https://redirect.github.com/cmackenzie1)! -
Adds the following new option for `wrangler pipelines create` and
`wrangler pipelines update` commands:

--cors-origins CORS origin allowlist for HTTP endpoint (use * for any
origin) [array]

-
[#&#8203;7290](https://redirect.github.com/cloudflare/workers-sdk/pull/7290)
[`0c0374c`](0c0374cce3)
Thanks [@&#8203;emily-shen](https://redirect.github.com/emily-shen)! -
fix: add support for workers with assets when running multiple workers
in one `wrangler dev` instance


[https://github.com/cloudflare/workers-sdk/pull/7251](https://redirect.github.com/cloudflare/workers-sdk/pull/7251)
added support for running multiple Workers in one `wrangler
dev`/miniflare session. e.g. `wrangler dev -c wrangler.toml -c
../worker2/wrangler.toml`, which among other things, allowed
cross-service RPC to Durable Objects.

However this did not work in the same way as production when there was a
Worker with assets - this PR should fix that.

-
[#&#8203;7769](https://redirect.github.com/cloudflare/workers-sdk/pull/7769)
[`6abe69c`](6abe69c3fe)
Thanks [@&#8203;cmackenzie1](https://redirect.github.com/cmackenzie1)! -
Rename wrangler pipelines \<create|update> flags

    The following parameters have been renamed:

    | Previous Name     | New Name              |
    | ----------------- | --------------------- |
    | access-key-id     | r2-access-key-id      |
    | secret-access-key | r2-secret-access-key  |
    | transform         | transform-worker      |
    | r2                | r2-bucket             |
    | prefix            | r2-prefix             |
    | binding           | enable-worker-binding |
    | http              | enable-http           |
    | authentication    | require-http-auth     |
    | filename          | file-template         |
    | filepath          | partition-template    |

-
[#&#8203;8012](https://redirect.github.com/cloudflare/workers-sdk/pull/8012)
[`c412a31`](c412a31985)
Thanks [@&#8203;mtlemilio](https://redirect.github.com/mtlemilio)! - Use
fetchPagedListResult when listing Hyperdrive configs from the API

    This fixes an issue where only 20 configs were being listed.

-
[#&#8203;8077](https://redirect.github.com/cloudflare/workers-sdk/pull/8077)
[`60310cd`](60310cd796)
Thanks [@&#8203;emily-shen](https://redirect.github.com/emily-shen)! -
feat: add telemetry to experimental auto-provisioning

- Updated dependencies
\[[`c80dbd8`](c80dbd8d5e),
[`0c0374c`](0c0374cce3)]:
    -   miniflare@3.20250204.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:32:14 +01:00
renovate[bot]
4ea397adb0 Update Rust crate smallvec to v1.14.0 (#16201)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [smallvec](https://redirect.github.com/servo/rust-smallvec) |
workspace.dependencies | minor | `1.13.2` -> `1.14.0` |

---

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

---

### Release Notes

<details>
<summary>servo/rust-smallvec (smallvec)</summary>

###
[`v1.14.0`](https://redirect.github.com/servo/rust-smallvec/releases/tag/v1.14.0)

[Compare
Source](https://redirect.github.com/servo/rust-smallvec/compare/v1.13.2...v1.14.0)

#### What's Changed

- Implement `MallocSizeOf` for SmallVec (v1) by
[@&#8203;nicoburns](https://redirect.github.com/nicoburns) in
[https://github.com/servo/rust-smallvec/pull/370](https://redirect.github.com/servo/rust-smallvec/pull/370)

#### New Contributors

- [@&#8203;nicoburns](https://redirect.github.com/nicoburns) made their
first contribution in
[https://github.com/servo/rust-smallvec/pull/370](https://redirect.github.com/servo/rust-smallvec/pull/370)

**Full Changelog**:
https://github.com/servo/rust-smallvec/compare/v1.13.2...v1.14.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:24:24 +01:00
renovate[bot]
033f16233d Update Rust crate codspeed-criterion-compat to v2.8.0 (#16200)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [codspeed-criterion-compat](https://codspeed.io)
([source](https://redirect.github.com/CodSpeedHQ/codspeed-rust)) |
workspace.dependencies | minor | `2.7.2` -> `2.8.0` |

---

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

---

### Release Notes

<details>
<summary>CodSpeedHQ/codspeed-rust (codspeed-criterion-compat)</summary>

###
[`v2.8.0`](https://redirect.github.com/CodSpeedHQ/codspeed-rust/releases/tag/v2.8.0)

[Compare
Source](https://redirect.github.com/CodSpeedHQ/codspeed-rust/compare/v2.7.2...v2.8.0)

#### What's Changed

This introduces Divan compatibility layer and also Wall Time support.
Check out the documentation to try it out
[here](https://docs.codspeed.io/benchmarks/rust/divan).

##### Details

- ci: bump actions/checkout to v4 by
[@&#8203;fargito](https://redirect.github.com/fargito) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/56](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/56)
- docs: simplify rust benchmarks definition by
[@&#8203;adriencaccia](https://redirect.github.com/adriencaccia) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/44](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/44)
- Support walltime runs with divan by
[@&#8203;art049](https://redirect.github.com/art049) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/66](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/66)
- Make `cargo-codspeed` build targets to different directories between
walltime and instrumented by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/68](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/68)
- feat: make codspeed raw results in the walltime directory as well by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/70](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/70)
- chore: add an internal divan fork by
[@&#8203;art049](https://redirect.github.com/art049) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/69](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/69)
- Add codspeed<>divan compat layer by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/65](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/65)
- fix: only show walltime collection warning when appropriate by
[@&#8203;art049](https://redirect.github.com/art049) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/71](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/71)
- feat(divan_compat): support types and manage types and args in
codspeed uri by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/72](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/72)
- feat: add some TheAlgorithm benches by
[@&#8203;art049](https://redirect.github.com/art049) in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/73](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/73)
- Add divan_compat msrv check in CI by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/74](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/74)
- feat: add readme to divan_compat by
[@&#8203;GuillaumeLagrange](https://redirect.github.com/GuillaumeLagrange)
in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/75](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/75)

#### New Contributors

- [@&#8203;fargito](https://redirect.github.com/fargito) made their
first contribution in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/56](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/56)

#### New Contributors

- [@&#8203;fargito](https://redirect.github.com/fargito) made their
first contribution in
[https://github.com/CodSpeedHQ/codspeed-rust/pull/56](https://redirect.github.com/CodSpeedHQ/codspeed-rust/pull/56)

**Full Changelog**:
https://github.com/CodSpeedHQ/codspeed-rust/compare/v2.7.2...v2.8.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:24:03 +01:00
renovate[bot]
b10be97eae Update Rust crate strum to v0.27.1 (#16195)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [strum](https://redirect.github.com/Peternator7/strum) |
workspace.dependencies | patch | `0.27.0` -> `0.27.1` |

---

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

---

### Release Notes

<details>
<summary>Peternator7/strum (strum)</summary>

###
[`v0.27.1`](https://redirect.github.com/Peternator7/strum/blob/HEAD/CHANGELOG.md#0271)

[Compare
Source](https://redirect.github.com/Peternator7/strum/compare/v0.27.0...v0.27.1)

- [#&#8203;414](https://redirect.github.com/Peternator7/strum/pull/414):
Fix docrs build error.
- [#&#8203;417](https://redirect.github.com/Peternator7/strum/pull/417):
Mention `parse_error_ty` and `parse_error_fn` that had been
    left out of the docs accidentally.
-
[#&#8203;421](https://redirect.github.com/Peternator7/strum/pull/421)[#&#8203;331](https://redirect.github.com/Peternator7/strum/pull/331):
Implement
`#[strum(transparent)]` attribute on `IntoStaticStr`, `Display` and
`AsRefStr` that forwards the implmenentation to
the inner value. Note that for static strings, the inner value must be
convertible to an `&'static str`.

    ```rust
    #[derive(strum::Display)]
    enum SurveyResponse {
      Yes,
      No,
      #[strum(transparent)]
      Other(String)
    }

    fn main() {
      let response = SurveyResponse::Other("It was good".into());
      println!("Question: Did you have fun?");
      println!("Answer: {}", response);
      // prints: Answer: It was good
    }
    ```

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:22:44 +01:00
renovate[bot]
f3743e30d0 Update Rust crate clap to v4.5.29 (#16194)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.28` -> `4.5.29` |

---

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

---

### Release Notes

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

###
[`v4.5.29`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4529---2025-02-11)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.28...v4.5.29)

##### Fixes

- Change `ArgMatches::args_present` so not-present flags are considered
not-present (matching the documentation)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:22:31 +01:00
renovate[bot]
4d083e579d Update Rust crate strum_macros to v0.27.1 (#16196)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [strum_macros](https://redirect.github.com/Peternator7/strum) |
workspace.dependencies | patch | `0.27.0` -> `0.27.1` |

---

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

---

### Release Notes

<details>
<summary>Peternator7/strum (strum_macros)</summary>

###
[`v0.27.1`](https://redirect.github.com/Peternator7/strum/blob/HEAD/CHANGELOG.md#0271)

[Compare
Source](https://redirect.github.com/Peternator7/strum/compare/v0.27.0...v0.27.1)

- [#&#8203;414](https://redirect.github.com/Peternator7/strum/pull/414):
Fix docrs build error.
- [#&#8203;417](https://redirect.github.com/Peternator7/strum/pull/417):
Mention `parse_error_ty` and `parse_error_fn` that had been
    left out of the docs accidentally.
-
[#&#8203;421](https://redirect.github.com/Peternator7/strum/pull/421)[#&#8203;331](https://redirect.github.com/Peternator7/strum/pull/331):
Implement
`#[strum(transparent)]` attribute on `IntoStaticStr`, `Display` and
`AsRefStr` that forwards the implmenentation to
the inner value. Note that for static strings, the inner value must be
convertible to an `&'static str`.

    ```rust
    #[derive(strum::Display)]
    enum SurveyResponse {
      Yes,
      No,
      #[strum(transparent)]
      Other(String)
    }

    fn main() {
      let response = SurveyResponse::Other("It was good".into());
      println!("Question: Did you have fun?");
      println!("Answer: {}", response);
      // prints: Answer: It was good
    }
    ```

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:22:15 +01:00
renovate[bot]
7899e8756e Update pre-commit dependencies (#16198)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[astral-sh/ruff-pre-commit](https://redirect.github.com/astral-sh/ruff-pre-commit)
| repository | patch | `v0.9.5` -> `v0.9.6` |
| [crate-ci/typos](https://redirect.github.com/crate-ci/typos) |
repository | patch | `v1.29.5` -> `v1.29.7` |
|
[rbubley/mirrors-prettier](https://redirect.github.com/rbubley/mirrors-prettier)
| repository | minor | `v3.4.2` -> `v3.5.1` |

---

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

Note: The `pre-commit` manager in Renovate is not supported by the
`pre-commit` maintainers or community. Please do not report any problems
there, instead [create a Discussion in the Renovate
repository](https://redirect.github.com/renovatebot/renovate/discussions/new)
if you have any questions.

---

### Release Notes

<details>
<summary>astral-sh/ruff-pre-commit (astral-sh/ruff-pre-commit)</summary>

###
[`v0.9.6`](https://redirect.github.com/astral-sh/ruff-pre-commit/releases/tag/v0.9.6)

[Compare
Source](https://redirect.github.com/astral-sh/ruff-pre-commit/compare/v0.9.5...v0.9.6)

See: https://github.com/astral-sh/ruff/releases/tag/0.9.6

</details>

<details>
<summary>crate-ci/typos (crate-ci/typos)</summary>

###
[`v1.29.7`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.29.7)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.29.6...v1.29.7)

#### \[1.29.7] - 2025-02-13

##### Fixes

-   Don't correct `implementors`

###
[`v1.29.6`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.29.6)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.29.5...v1.29.6)

#### \[1.29.6] - 2025-02-13

##### Features

- Updated the dictionary with the [January
2025](https://redirect.github.com/crate-ci/typos/issues/1200) changes

</details>

<details>
<summary>rbubley/mirrors-prettier (rbubley/mirrors-prettier)</summary>

###
[`v3.5.1`](https://redirect.github.com/rbubley/mirrors-prettier/compare/v3.5.0...v3.5.1)

[Compare
Source](https://redirect.github.com/rbubley/mirrors-prettier/compare/v3.5.0...v3.5.1)

###
[`v3.5.0`](https://redirect.github.com/rbubley/mirrors-prettier/compare/v3.4.2...v3.5.0)

[Compare
Source](https://redirect.github.com/rbubley/mirrors-prettier/compare/v3.4.2...v3.5.0)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:21:44 +01:00
renovate[bot]
f3d1bf845e Update dependency ruff to v0.9.6 (#16197)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ruff](https://docs.astral.sh/ruff)
([source](https://redirect.github.com/astral-sh/ruff),
[changelog](https://redirect.github.com/astral-sh/ruff/blob/main/CHANGELOG.md))
| `==0.9.5` -> `==0.9.6` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/ruff/0.9.6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/ruff/0.9.6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/ruff/0.9.5/0.9.6?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/ruff/0.9.5/0.9.6?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>astral-sh/ruff (ruff)</summary>

###
[`v0.9.6`](https://redirect.github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#096)

[Compare
Source](https://redirect.github.com/astral-sh/ruff/compare/0.9.5...0.9.6)

##### Preview features

- \[`airflow`] Add `external_task.{ExternalTaskMarker,
ExternalTaskSensor}` for `AIR302`
([#&#8203;16014](https://redirect.github.com/astral-sh/ruff/pull/16014))
- \[`flake8-builtins`] Make strict module name comparison optional
(`A005`)
([#&#8203;15951](https://redirect.github.com/astral-sh/ruff/pull/15951))
- \[`flake8-pyi`] Extend fix to Python <= 3.9 for
`redundant-none-literal` (`PYI061`)
([#&#8203;16044](https://redirect.github.com/astral-sh/ruff/pull/16044))
- \[`pylint`] Also report when the object isn't a literal (`PLE1310`)
([#&#8203;15985](https://redirect.github.com/astral-sh/ruff/pull/15985))
- \[`ruff`] Implement `indented-form-feed` (`RUF054`)
([#&#8203;16049](https://redirect.github.com/astral-sh/ruff/pull/16049))
- \[`ruff`] Skip type definitions for `missing-f-string-syntax`
(`RUF027`)
([#&#8203;16054](https://redirect.github.com/astral-sh/ruff/pull/16054))

##### Rule changes

- \[`flake8-annotations`] Correct syntax for `typing.Union` in suggested
return type fixes for `ANN20x` rules
([#&#8203;16025](https://redirect.github.com/astral-sh/ruff/pull/16025))
- \[`flake8-builtins`] Match upstream module name comparison (`A005`)
([#&#8203;16006](https://redirect.github.com/astral-sh/ruff/pull/16006))
- \[`flake8-comprehensions`] Detect overshadowed `list`/`set`/`dict`,
ignore variadics and named expressions (`C417`)
([#&#8203;15955](https://redirect.github.com/astral-sh/ruff/pull/15955))
- \[`flake8-pie`] Remove following comma correctly when the unpacked
dictionary is empty (`PIE800`)
([#&#8203;16008](https://redirect.github.com/astral-sh/ruff/pull/16008))
- \[`flake8-simplify`] Only trigger `SIM401` on known dictionaries
([#&#8203;15995](https://redirect.github.com/astral-sh/ruff/pull/15995))
- \[`pylint`] Do not report calls when object type and argument type
mismatch, remove custom escape handling logic (`PLE1310`)
([#&#8203;15984](https://redirect.github.com/astral-sh/ruff/pull/15984))
- \[`pyupgrade`] Comments within parenthesized value ranges should not
affect applicability (`UP040`)
([#&#8203;16027](https://redirect.github.com/astral-sh/ruff/pull/16027))
- \[`pyupgrade`] Don't introduce invalid syntax when upgrading old-style
type aliases with parenthesized multiline values (`UP040`)
([#&#8203;16026](https://redirect.github.com/astral-sh/ruff/pull/16026))
- \[`pyupgrade`] Ensure we do not rename two type parameters to the same
name (`UP049`)
([#&#8203;16038](https://redirect.github.com/astral-sh/ruff/pull/16038))
- \[`pyupgrade`] \[`ruff`] Don't apply renamings if the new name is
shadowed in a scope of one of the references to the binding (`UP049`,
`RUF052`)
([#&#8203;16032](https://redirect.github.com/astral-sh/ruff/pull/16032))
- \[`ruff`] Update `RUF009` to behave similar to `B008` and ignore
attributes with immutable types
([#&#8203;16048](https://redirect.github.com/astral-sh/ruff/pull/16048))

##### Server

- Root exclusions in the server to project root
([#&#8203;16043](https://redirect.github.com/astral-sh/ruff/pull/16043))

##### Bug fixes

- \[`flake8-datetime`] Ignore `.replace()` calls while looking for
`.astimezone`
([#&#8203;16050](https://redirect.github.com/astral-sh/ruff/pull/16050))
- \[`flake8-type-checking`] Avoid `TC004` false positive where the
runtime definition is provided by `__getattr__`
([#&#8203;16052](https://redirect.github.com/astral-sh/ruff/pull/16052))

##### Documentation

- Improve `ruff-lsp` migration document
([#&#8203;16072](https://redirect.github.com/astral-sh/ruff/pull/16072))
- Undeprecate `ruff.nativeServer`
([#&#8203;16039](https://redirect.github.com/astral-sh/ruff/pull/16039))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2Ny4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 08:21:29 +01:00
Alex Waygood
4941975e74 [red-knot] Recognize ... as a singleton (#16184) 2025-02-16 22:01:02 +00:00
Dylan
d4b4f65e20 [pep8-naming] Clarify preview behavior in invalid-first-argument-name-for-class-method (N804) (#16193)
Adds clarification in the documentation for
[invalid-first-argument-name-for-class-method
(N804)](https://docs.astral.sh/ruff/rules/invalid-first-argument-name-for-class-method/#invalid-first-argument-name-for-class-method-n804)

(Also fixes an unrelated typo).
2025-02-16 15:02:50 -06:00
cake-monotone
96dd1b1587 Consider __new__ methods as special function type for enforcing class method or static method rules (#13305)
## Summary

`__new__` methods are technically static methods, with `cls` as their
first argument. However, Ruff currently classifies them as classmethod,
which causes two issues:

- It conveys incorrect information, leading to confusion. For example,
in cases like ARG003, `__new__` is explicitly treated as a classmethod.
- Future rules that should apply to staticmethod may not be applied
correctly due to this misclassification.

Motivated by this, the current PR makes the following adjustments:

1. Introduces `FunctionType::NewMethod` as an enum variant, since, for
the purposes of lint rules, `__new__` sometimes behaves like a static
method and other times like a class method. This is an internal change.

2. The following rule behaviors and messages are totally unchanged:
- [too-many-arguments
(PLR0913)](https://docs.astral.sh/ruff/rules/too-many-arguments/#too-many-arguments-plr0913)
- [too-many-positional-arguments
(PLR0917)](https://docs.astral.sh/ruff/rules/too-many-positional-arguments/#too-many-positional-arguments-plr0917)
3. The following rule behaviors are unchanged, but the messages have
been changed for correctness to use "`__new__` method" instead of "class
method":
- [self-or-cls-assignment
(PLW0642)](https://docs.astral.sh/ruff/rules/self-or-cls-assignment/#self-or-cls-assignment-plw0642)
4. The following rules are changed _unconditionally_ (not gated behind
preview) because their current behavior is an honest bug: it just isn't
true that `__new__` is a class method, and it _is_ true that `__new__`
is a static method:
- [unused-class-method-argument
(ARG003)](https://docs.astral.sh/ruff/rules/unused-class-method-argument/#unused-class-method-argument-arg003)
no longer applies to `__new__`
- [unused-static-method-argument
(ARG004)](https://docs.astral.sh/ruff/rules/unused-static-method-argument/#unused-static-method-argument-arg004)
now applies to `__new__`
5. The only changes which differ based on `preview` are the following:
- [invalid-first-argument-name-for-class-method
(N804)](https://docs.astral.sh/ruff/rules/invalid-first-argument-name-for-class-method/#invalid-first-argument-name-for-class-method-n804):
This is _skipped_ when `preview` is _enabled_. When `preview` is
_disabled_, the rule is the same but the _message_ has been modified to
say "`__new__` method" instead of "class method".
- [bad-staticmethod-argument
(PLW0211)](https://docs.astral.sh/ruff/rules/bad-staticmethod-argument/#bad-staticmethod-argument-plw0211):
When `preview` is enabled, this now applies to `__new__`.

Closes #13154

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-16 14:12:25 -06:00
Dylan
f29c7b03ec Warn on invalid noqa even when there are no diagnostics (#16178)
On `main` we warn the user if there is an invalid noqa comment[^1] and
at least one of the following holds:

- There is at least one diagnostic
- A lint rule related to `noqa`s is enabled (e.g. `RUF100`)

This is probably strange behavior from the point of view of the user, so
we now show invalid `noqa`s even when there are no diagnostics.

Closes #12831

[^1]: For the current definition of "invalid noqa comment", which may be
expanded in #12811 . This PR is independent of loc. cit. in the sense
that the CLI warnings should be consistent, regardless of which `noqa`
comments are considered invalid.
2025-02-16 13:58:18 -06:00
Brent Westbrook
3a0d45c85b [flake8-debugger] Also flag sys.breakpointhook and sys.__breakpointhook__ (T100) (#16191)
## Summary

Fixes #16189.

Only `sys.breakpointhook` is flagged by the upstream linter:

007a745c86/pylint/checkers/stdlib.py (L38)

but I think it makes sense to flag
[`__breakpointhook__`](https://docs.python.org/3/library/sys.html#sys.__breakpointhook__)
too, as suggested in the issue because it
> contain[s] the original value of breakpointhook [...] in case [it
happens] to get replaced with broken or alternative objects.

## Test Plan

New T100 test cases
2025-02-16 14:50:16 -05:00
Aaron Gokaslan
1f17916224 Add doc about usedforsecurity flag for S324 (#16190)
## Summary

Provides documentation about the FIPS compliant flag for Python hashlib
`usedforsecurity`
Fixes #16188 

## Test Plan

* pre-commit hooks

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-02-16 13:06:55 -05:00
Alex Waygood
61fef0a64a Reduce memory usage of Docstring struct (#16183) 2025-02-16 15:23:52 +00:00
Alex Waygood
93aff36147 [red-knot] Improve handling of inherited class attributes (#16160) 2025-02-15 18:22:35 +00:00
Ayush Baweja
df45a9db64 [flake8-comprehensions]: Handle trailing comma in C403 fix (#16110)
## Summary

Resolves [#16099 ](https://github.com/astral-sh/ruff/issues/16099) based
on [#15929 ](https://github.com/astral-sh/ruff/pull/15929)

## Test Plan

Added test case `s = set([x for x in range(3)],)` and updated snapshot.

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-02-15 11:45:41 -06:00
InSync
3c69b685ee [ruff] Implicit class variable in dataclass (RUF045) (#14349)
## Summary

Implement lint rule to flag un-annotated variable assignments in dataclass definitions.

Resolves #12877.

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-02-15 09:08:13 -06:00
github-actions[bot]
171facd960 Sync vendored typeshed stubs (#16173)
Close and reopen this PR to trigger CI

Co-authored-by: typeshedbot <>
2025-02-15 10:01:34 +00:00
InSync
977447f9b8 Sort linters alphabetically (#16168)
## Summary

Resolves #16164.

Linters are now sorted by their names case-insensitively.

## Test Plan


![](https://github.com/user-attachments/assets/87ffd4d8-1ba5-4a4b-8fed-dd21a020bd27)

Also unit tests.
2025-02-14 22:05:08 +01:00
Micha Reiser
b3e99b25bf Fix missing serde feature for red_knot_python_semantic (#16169)
## Summary

Running `cargo test -p red_knot_python_semantic` failed because of a
missing serde feature. This PR enables the `ruff_python_ast`'`s `serde`
if the crate's `serde` feature is enabled

## Test Plan

`cargo test -p red_knot_python_semantic` compiles again
2025-02-14 20:31:55 +00:00
Carl Meyer
dcabb948f3 [red-knot] add special case for float/complex (#16166)
When adjusting the existing tests, I aimed to avoid dealing with the
special case in other tests if it's not necessary to do so (that is,
avoid using `float` and `complex` as examples where we just need "some
type"), and keep the tests for the special case mostly collected in the
mdtest dedicated to that purpose.

Fixes https://github.com/astral-sh/ruff/issues/14932
2025-02-14 12:24:10 -08:00
Vlad Nedelcu
219712860c [refurb] Check for subclasses includes subscript expressions (FURB189) (#16155)
## Summary

Added checks for subscript expressions on builtin classes as in FURB189.
The object is changed to use the collections objects and the types from
the subscript are kept.

Resolves #16130 

> Note: Added some comments in the code explaining why
## Test Plan


- Added a subscript dict and list class to the test file.
- Tested locally to check that the symbols are changed and the types are
kept.
- No modifications changed on optional `str` values.
2025-02-14 20:21:26 +01:00
Brent Westbrook
f58a54f043 Move red_knot_python_semantic::PythonVersion to the ruff_python_ast crate (#16147)
## Summary

This PR moves the `PythonVersion` struct from the
`red_knot_python_semantic` crate to the `ruff_python_ast` crate so that
it can be used more easily in the syntax error detection work. Compared
to that [prototype](https://github.com/astral-sh/ruff/pull/16090/) these
changes reduce us from 2 `PythonVersion` structs to 1.

This does not unify any of the `PythonVersion` *enums*, but I hope to
make some progress on that in a follow-up.

## Test Plan

Existing tests, this should not change any external behavior.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-14 12:48:08 -05:00
Junhson Jean-Baptiste
fa28dc5ccf [internal] Move Linter OperatorPrecedence into ruff_python_ast crate (#16162)
## Summary

This change begins to resolve #16071 by moving the `OperatorPrecedence`
structs from the `ruff_python_linter` crate into `ruff_python_ast`. This
PR also implements `precedence()` methods on the `Expr` and `ExprRef`
enums.

## Test Plan

Since this change mainly shifts existing logic, I didn't add any
additional tests. Existing tests do pass.
2025-02-14 15:55:07 +01:00
Dhruv Manilawala
63dd68e0ed Refactor symbol lookup APIs to hide re-export implementation details (#16133)
## Summary

This PR refactors the symbol lookup APIs to better facilitate the
re-export implementation. Specifically,
* Add `module_type_symbol` which returns the `Symbol` that's a member of
`types.ModuleType`
* Rename `symbol` -> `symbol_impl`; add `symbol` which delegates to
`symbol_impl` with `RequireExplicitReExport::No`
* Update `global_symbol` to do `symbol_impl` -> fall back to
`module_type_symbol` and default to `RequireExplicitReExport::No`
* Add `imported_symbol` to do `symbol_impl` with
`RequireExplicitReExport` as `Yes` if the module is in a stub file else
`No`
* Update `known_module_symbol` to use `imported_symbol` with a fallback
to `module_type_symbol`
* Update `ModuleLiteralType::member` to use `imported_symbol` with a
custom fallback

We could potentially also update `symbol_from_declarations` and
`symbol_from_bindings` to avoid passing in the `RequireExplicitReExport`
as it would be always `No` if called directly. We could add
`symbol_from_declarations_impl` and `symbol_from_bindings_impl`.

Looking at the `_impl` functions, I think we should move all of these
symbol related logic into `symbol.rs` where `Symbol` is defined and the
`_impl` could be private while we expose the public APIs at the crate
level. This would also make the `RequireExplicitReExport` an
implementation detail and the caller doesn't need to worry about it.
2025-02-14 15:25:48 +05:30
Dhruv Manilawala
60b3ef2c98 [red-knot] Support re-export conventions for stub files (#16073)
This is an alternative implementation to #15848.

## Summary

This PR adds support for re-export conventions for imports for stub
files.

**How does this work?**
* Add a new flag on the `Import` and `ImportFrom` definitions to
indicate whether they're being exported or not
* Add a new enum to indicate whether the symbol lookup is happening
within the same file or is being queried from another file (e.g., an
import statement)
* When a `Symbol` is being queried, we'll skip the definitions that are
(a) coming from a stub file (b) external lookup and (c) check the
re-export flag on the definition

This implementation does not yet support `__all__` and `*` imports as
both are features that needs to be implemented independently.

closes: #14099
closes: #15476 

## Test Plan

Add test cases, update existing ones if required.
2025-02-14 15:17:51 +05:30
InSync
3d0a58eb60 [pyupgrade] Unwrap unary expressions correctly (UP018) (#15919)
## Summary

Resolves #15859.

The rule now adds parentheses if the original call wraps an unary
expression and is:

* The left-hand side of a binary expression where the operator is `**`.
* The caller of a call expression.
* The subscripted of a subscript expression.
* The object of an attribute access.

The fix will also be marked as unsafe if there are any comments in its
range.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-14 08:42:00 +01:00
InSync
1db8392a5a Check for backtick-quoted shortcut links in CI (#16114)
## Summary

Follow-up to #16035.

`check_docs_formatted.py` will now report backtick-quoted shortcut links
in rule documentation. It uses a regular expression to find them. Such a
link:

* Starts with `[`, followed by <code>\`</code>, then a "name" sequence
of at least one non-backtick non-newline character, followed by another
<code>\`</code>, then ends with `]`.
* Is not followed by either a `[` or a `(`.
* Is not placed within a code block.

If the name is a known Ruff option name, that link is not considered a
violation.

## Test Plan

Manual.
2025-02-14 08:37:46 +01:00
Micha Reiser
81e202ed52 Make CallBinding::callable_ty required (#16135)
## Summary

The `callable_ty` is always known except in some TODO code where we can
use a `TODO` type instead.

## Test Plan

`cargo test`
2025-02-14 08:15:24 +01:00
Vlad Nedelcu
63c67750b1 Replace dead link for rome tools playground (#16153)
## Summary

Rome Tools Playground was renamed to Biome Playground. The link was
replaced to the new website.

Resolves #16143


## Test Plan

- Checked the linked is accessible from the README
2025-02-14 12:27:14 +05:30
Shaygan Hooshyari
0a75a1d56b Replace is-macro with implementation in enums (#16144) 2025-02-13 22:49:00 +00:00
Shaygan Hooshyari
bb15c7653a Use ubuntu-24 to run benchmarks (#16145) 2025-02-13 22:05:51 +00:00
Vlad Nedelcu
cb8b23d609 [flake8-pyi] Avoid flagging custom-typevar-for-self on metaclass methods (PYI019) (#16141) 2025-02-13 18:44:11 +00:00
Alex Waygood
be49151a3d [red-knot] Remove a parameter from the symbol_by_id() query (#16138) 2025-02-13 13:33:40 +00:00
InSync
7d2e40be2d [pylint] Do not offer fix for raw strings (PLE251) (#16132)
## Summary

Resolves #13294, follow-up to #13882.

At #13882, it was concluded that a fix should not be offered for raw
strings. This change implements that. The five rules in question are now
no longer always fixable.

## Test Plan

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

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-13 08:36:11 +00:00
Brent Westbrook
f8093b65ea [flake8-builtins] Update documentation (A005) (#16097)
Follow-up to https://github.com/astral-sh/ruff/pull/15951 to update
* the options links in A005 to reference
`lint.flake8-builtins.builtins-strict-checking`
* the description of the rule to explain strict vs non-strict checking
* the option documentation to point back to the rule
2025-02-12 12:50:13 -05:00
Alex Waygood
c31352f52b [ruff] Skip RUF001 diagnostics when visiting string type definitions (#16122) 2025-02-12 16:27:38 +00:00
Andrew Gallant
a9671e7008 ruff_db: add a vector for configuring diagnostic output (#16118)
For now, the only thing one can configure is whether color is enabled or
not. This avoids needing to ask the `colored` crate whether colors have
been globally enabled or disabled. And, more crucially, avoids the need
to _set_ this global flag for testing diagnostic output. Doing so can
have unintended consequences, as outlined in #16115.

Fixes #16115
2025-02-12 14:38:05 +00:00
Micha Reiser
03f08283ad [red-knot] Fallback to requires-python if no python-version is specified (#16028)
## Summary

Add support for the `project.requires-python` field in `pyproject.toml`
files.

Fall back to the resolved lower bound of `project.requires-python` if
the `environment.python-version` field is `None` (or more accurately,
initialize `environment.python-version with `requires-python`'s lower
bound if left unspecified).

## UX design

There are two options on how we can handle the fallback to
`requires-python`'s lower bound:

1. Store the resolved lower bound in `environment.python-version` if
that field is `None` (Implemented in this PR)
2. Store the `requires-python` constraint separately. 

There's no observed difference unless a user-level configuration (or any
other inherited configuration is used). Let's discuss it on the given
example


**User configuration**

```toml
[environment]
python-version = "3.10"
```

**Project configuration (`pyproject.toml`)**

```toml
[project]
name = "test"
requires-python = ">= 3.12"

[tool.knot]
# No environment table
```

The resolved version for 1. is 3.12 because the `requires-python`
constraint precedence takes precedence over the `python-version` in the
user configuration. 2. resolves to 3.10 because all `python-version`
constraints take precedence before falling back to `requires-python`.

Ruff implements 1. It's also the easier to implement and it does seem
intuitive to me that the more local `requires-python` constraint takes
precedence.


## Test plan

Added CLI and unit tests.
2025-02-12 11:47:59 +00:00
Vasco Schiavo
ae1b381c06 [pylint] Correct ordering of arguments in fix for if-stmt-min-max (PLR1730) (#16080)
The PR addresses the issue #16040 .

---

The logic used into the rule is the following:

Suppose to have an expression of the form 

```python
if a cmp b:
    c = d
```
where `a`,` b`, `c` and `d` are Python obj and `cmp` one of `<`, `>`,
`<=`, `>=`.

Then:

- `if a=c and b=d`
    
    - if `<=` fix with `a = max(b, a)`
    - if `>=`  fix with `a = min(b, a)`
    - if `>` fix with `a = min(a, b)`
    - if `<` fix with `a = max(a, b)`

- `if a=d and b=c`

    - if `<=` fix with `b = min(a, b)`
    - if `>=`  fix with `b = max(a, b)`
    - if `>` fix with `b = max(b, a)`
    - if `<` fix with `b = min(b, a)`
 
- do nothing, i.e., we cannot fix this case.

---

In total we have 8 different and possible cases.

```

| Case  | Expression       | Fix           |
|-------|------------------|---------------|
| 1     | if a >= b: a = b | a = min(b, a) |
| 2     | if a <= b: a = b | a = max(b, a) |
| 3     | if a <= b: b = a | b = min(a, b) |
| 4     | if a >= b: b = a | b = max(a, b) |
| 5     | if a > b: a = b  | a = min(a, b) |
| 6     | if a < b: a = b  | a = max(a, b) |
| 7     | if a < b: b = a  | b = min(b, a) |
| 8     | if a > b: b = a  | b = max(b, a) |
```

I added them in the tests. 

Please double-check that I didn't make any mistakes. It's quite easy to
mix up > and <.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-12 10:27:46 +01:00
David Peter
366ae1feaa [red-knot] Document 'public type of undeclared symbols' behavior (#16096)
## Summary

After I was asked twice within the same day, I thought it would be a
good idea to write some *user facing* documentation that explains our
reasoning behind inferring `Unknown | T_inferred` for public uses of
undeclared symbols. This is a major deviation from the behavior of other
type checkers and it seems like a good practice to defend our choice
like this.
2025-02-12 08:52:11 +01:00
Wei Lee
86c5cba472 [airflow] Fix ImportPathMoved / ProviderName misuse (AIR303) (#16013)
## Summary


* fix ImportPathMoved / ProviderName misuse
* oncrete names, such as `["airflow", "config_templates",
"default_celery", "DEFAULT_CELERY_CONFIG"]`, should use `ProviderName`.
In contrast, module paths like `"airflow", "operators", "weekday", ...`
should use `ImportPathMoved`. Misuse may lead to incorrect detection.

## Test Plan

update test fixture
2025-02-12 12:34:16 +05:30
Andrew Gallant
6e34f74c16 add diagnostic Span (couples File and TextRange) (#16101)
This essentially makes it impossible to construct a `Diagnostic`
that has a `TextRange` but no `File`.

This is meant to be a precursor to multi-span support.

(Note that I consider this more of a prototyping-change and not
necessarily what this is going to look like longer term.)

Reviewers can probably review this PR as one big diff instead of
commit-by-commit.
2025-02-11 14:55:12 -05:00
Micha Reiser
9c179314ed Remove Hash and Eq from AstNodeRef for types not implementing Eq or Hash (#16100)
## Summary

This is a follow up to
https://github.com/astral-sh/ruff/pull/15763#discussion_r1949681336

It reverts the change to using ptr equality for `AstNodeRef`s, which in
turn removes the `Eq`, `PartialEq`, and `Hash` implementations for
`AstNodeRef`s parametrized with AST nodes.
Cheap comparisons shouldn't be needed because the node field is
generally marked as `[#tracked]` and `#[no_eq]` and removing the
implementations even enforces that those
attributes are set on all `AstNodeRef` fields (which is good).

The only downside this has is that we technically wouldn't have to mark
the `Unpack::target` as `#[tracked]` because
the `target` field is accessed in every query accepting `Unpack` as an
argument.

Overall, enforcing the use of `#[tracked]` seems like a good trade off,
espacially considering that it's very likely that
we'd probably forget to mark the `Unpack::target` field as tracked if we
add a new `Unpack` query that doesn't access the target.

## Test Plan

`cargo test`
2025-02-11 19:55:50 +01:00
Micha Reiser
ce31c2693b Fix release build warning about unused todo type message (#16102) 2025-02-11 18:38:41 +00:00
Brent Westbrook
7b487d853a [pydocstyle] Handle arguments with the same names as sections (D417) (#16011)
## Summary

Fixes #16007. The logic from the last fix for this (#9427) was
sufficient, it just wasn't being applied because `Attributes` sections
aren't expected to have nested sections. I just deleted the outer
conditional, which should hopefully fix this for all section types.

## Test Plan

New regression test, plus the existing D417 tests.
2025-02-11 12:05:29 -05:00
Alex Waygood
df1d430294 [red-knot] Reduce usage of From<Type> implementations when working with Symbols (#16076) 2025-02-11 11:09:37 +00:00
Ibraheem Ahmed
69d86d1d69 Transition to salsa coarse-grained tracked structs (#15763)
## Summary

Transition to using coarse-grained tracked structs (depends on
https://github.com/salsa-rs/salsa/pull/657). For now, this PR doesn't
add any `#[tracked]` fields, meaning that any changes cause the entire
struct to be invalidated. It also changes `AstNodeRef` to be
compared/hashed by pointer address, instead of performing a deep AST
comparison.

## Test Plan

This yields a 10-15% improvement on my machine (though weirdly some runs
were 5-10% without being flagged as inconsistent by criterion, is there
some non-determinism involved?). It's possible that some of this is
unrelated, I'll try applying the patch to the current salsa version to
make sure.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-11 11:38:50 +01:00
InSync
7fbd89cb39 [pyupgrade] Handle micro version numbers correctly (UP036) (#16091)
## Summary

Resolves #16082.

`UP036` will now also take into consideration whether or not a micro
version number is set:

* If a third element doesn't exist, the existing logic is preserved.
* If it exists but is not an integer literal, the check will not be
reported.
* If it is an integer literal but doesn't fit into a `u8`, the check
will be reported as invalid.
* Otherwise, the compared version is determined to always be less than
the target version when:
	* The target's minor version is smaller than that of the comparator, or
* The operator is `<`, the micro version is 0, and the two minor
versions compare equal.

As this is considered a bugfix, it is not preview-gated.

## Test Plan

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

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-11 07:40:56 +00:00
David Peter
0019d39f6e [red-knot] T | object == object (#16088)
## Summary

- Simplify unions with `object` to `object`.
- Add a new `Type::object(db)` constructor to abbreviate
`KnownClass::Object.to_instance(db)` in some places.
- Add a `Type::is_object` and `Class::is_object` function to make some
tests for a bit easier to read.

closes #16084

## Test Plan

New Markdown tests.
2025-02-10 23:07:06 +01:00
Dylan
f30fac6326 [ruff] Skip singleton starred expressions for incorrectly-parenthesized-tuple-in-subscript (RUF031) (#16083)
The index in subscript access like `d[*y]` will not be linted or
autofixed with parentheses, even when
`lint.ruff.parenthesize-tuple-in-subscript = true`.

Closes #16077
2025-02-10 11:30:07 -06:00
Micha Reiser
a4c8c49ac2 Delete left-over `verbosity.rs (#16081) 2025-02-10 16:06:05 +00:00
Micha Reiser
af832560fc [red-knot] User-level configuration (#16021)
## Summary

This PR adds support for user-level configurations
(`~/.config/knot/knot.toml`) to Red Knot.

Red Knot will watch the user-level configuration file for changes but
only if it exists
when the process start. It doesn't watch for new configurations, 
mainly to simplify things for now (it would require watching the entire
`.config` directory because the `knot` subfolder might not exist
either).

The new `ConfigurationFile` struct seems a bit overkill for now but I
plan to use it for
hierarchical configurations as well. 


Red Knot uses the same strategy as uv and Ruff by using the etcetera
crate.

## Test Plan

Added CLI and file watching test
2025-02-10 16:44:23 +01:00
Micha Reiser
f7819e553f Add user_configuration_directory to System (#16020)
## Summary

This PR adds a new `user_configuration_directory` method to `System`. We
need it to resolve where to lookup a user-level `knot.toml`
configuration file.
The method belongs to `System` because not all platforms have a
convention of where to store such configuration files (e.g. wasm).


I refactored `TestSystem` to be a simple wrapper around an `Arc<dyn
System...>` and use the `System.as_any` method instead to cast it down
to an `InMemory` system. I also removed some `System` specific methods
from `InMemoryFileSystem`, they don't belong there.

This PR removes the `os` feature as a default feature from `ruff_db`.
Most crates depending on `ruff_db` don't need it because they only
depend on `System` or only depend on `os` for testing. This was
necessary to fix a compile error with `red_knot_wasm`

## Test Plan

I'll make use of the method in my next PR. So I guess we won't know if
it works before then but I copied the code from Ruff/uv, so I have high
confidence that it is correct.

`cargo test`
2025-02-10 15:50:55 +01:00
Micha Reiser
678b0c2d39 [red-knot] Resolve Options to Settings (#16000)
## Summary

This PR generalize the idea that we may want to emit diagnostics for 
invalid or incompatible configuration values similar to how we already 
do it for `rules`. 

This PR introduces a new `Settings` struct that is similar to `Options`
but, unlike
`Options`, are fields have their default values filled in and they use a
representation optimized for reads.

The diagnostics created during loading the `Settings` are stored on the
`Project` so that we can emit them when calling `check`.

The motivation for this work is that it simplifies adding new settings.
That's also why I went ahead and added the `terminal.error-on-warning`
setting to demonstrate how new settings are added.

## Test Plan

Existing tests, new CLI test.
2025-02-10 15:28:45 +01:00
Dhruv Manilawala
524cf6e515 Bump version to 0.9.6 (#16074) 2025-02-10 18:14:04 +05:30
Dhruv Manilawala
857cf0deb0 Revert tailwindcss v4 update (#16075)
## Summary

Revert the v4 update for now until the codebase is updated
(https://github.com/astral-sh/ruff/pull/16069).

Update renovate config to disable updating it.

## Test Plan

```console
$ npx --yes --package renovate -- renovate-config-validator
(node:98977) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
 INFO: Validating .github/renovate.json5
 INFO: Config validated successfully
```

And run `npm run build` in the `playground/` directory.
2025-02-10 18:13:32 +05:30
Dhruv Manilawala
0f1eb1e2fc Improve migration document (#16072)
## Summary

This PR improves the migration document based on recent feedback.

[Rendered
version](https://github.com/astral-sh/ruff/blob/dhruv/migration/docs/editors/migration.md)

### Preview

<img width="1897" alt="Screenshot 2025-02-10 at 2 52 31 PM"
src="https://github.com/user-attachments/assets/596a3217-6598-4274-ab49-a89b9cb60fe0"
/>
2025-02-10 16:30:03 +05:30
InSync
b69eb9099a Fix reference definition labels for backtick-quoted shortcut links (#16035)
## Summary

Resolves #16010.

The changes boil down to something like this:

```diff
-/// The [FastAPI documentation] recommends the use of [`typing.Annotated`]
+/// The [FastAPI documentation] recommends the use of [`typing.Annotated`][typing-annotated]

-/// [typing.Annotated]: https://docs.python.org/3/library/typing.html#typing.Annotated
+/// [typing-annotated]: https://docs.python.org/3/library/typing.html#typing.Annotated
```

## Test Plan

Mkdocs:


![](https://github.com/user-attachments/assets/a2e6bf22-56fa-4b2c-9500-1c1256c5a218)

GitHub:

> ## Why is this bad?
> The [FastAPI documentation] recommends the use of
[`typing.Annotated`][typing-annotated]
> 
> ...
>
> [FastAPI documentation]:
https://fastapi.tiangolo.com/tutorial/query-params-str-validations/?h=annotated#advantages-of-annotated
> [typing-annotated]:
https://docs.python.org/3/library/typing.html#typing.Annotated

[CommonMark
dingus](https://spec.commonmark.org/dingus/?text=%23%23%20Why%20is%20this%20bad%3F%0AThe%20%5BFastAPI%20documentation%5D%20recommends%20the%20use%20of%20%5B%60typing.Annotated%60%5D%5Btyping-annotated%5D%0A%0A...%0A%0A%5BFastAPI%20documentation%5D%3A%20https%3A%2F%2Ffastapi.tiangolo.com%2Ftutorial%2Fquery-params-str-validations%2F%3Fh%3Dannotated%23advantages-of-annotated%0A%5Btyping-annotated%5D%3A%20https%3A%2F%2Fdocs.python.org%2F3%2Flibrary%2Ftyping.html%23typing.Annotated):

```html
<h2>Why is this bad?</h2>
<p>The <a href="https://fastapi.tiangolo.com/tutorial/query-params-str-validations/?h=annotated#advantages-of-annotated">FastAPI documentation</a> recommends the use of <a href="https://docs.python.org/3/library/typing.html#typing.Annotated"><code>typing.Annotated</code></a></p>
<p>...</p>
```
2025-02-10 09:54:22 +01:00
ABDULRAHMAN ALRAHMA
d2f661f795 RUF009 should behave similar to B008 and ignore attributes with immutable types (#16048)
This PR resolved #15772

Before PR:
```
def _(
    this_is_fine: int = f(),           # No error
    this_is_not: list[int] = f()       # B008: Do not perform function call `f` in argument defaults
): ...


@dataclass
class _:
    this_is_not_fine: list[int] = f()  # RUF009: Do not perform function call `f` in dataclass defaults
    this_is_also_not: int = f()        # RUF009: Do not perform function call `f` in dataclass defaults
```

After PR:
```
def _(
    this_is_fine: int = f(),           # No error
    this_is_not: list[int] = f()       # B008: Do not perform function call `f` in argument defaults
): ...


@dataclass
class _:
    this_is_not_fine: list[int] = f()  # RUF009: Do not perform function call `f` in dataclass defaults
    this_is_fine: int = f()
```
2025-02-10 09:46:23 +01:00
InSync
07cf8852a3 [pylint] Also report when the object isn't a literal (PLE1310) (#15985)
## Summary

Follow-up to #15984.

Previously, `PLE1310` would only report when the object is a literal:

```python
'a'.strip('//')  # error

foo = ''
foo.strip('//')  # no error
```

After this change, objects whose type can be inferred to be either `str`
or `bytes` will also be reported in preview.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-10 09:31:27 +01:00
renovate[bot]
c08989692b Update Rust crate rustc-hash to v2.1.1 (#16060)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [rustc-hash](https://redirect.github.com/rust-lang/rustc-hash) |
workspace.dependencies | patch | `2.1.0` -> `2.1.1` |

---

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

---

### Release Notes

<details>
<summary>rust-lang/rustc-hash (rustc-hash)</summary>

###
[`v2.1.1`](https://redirect.github.com/rust-lang/rustc-hash/blob/HEAD/CHANGELOG.md#211)

[Compare
Source](https://redirect.github.com/rust-lang/rustc-hash/compare/v2.1.0...v2.1.1)

-   Change the internal algorithm to better accomodate large hashmaps.
This mitigates a [regression with 2.0 in
rustc](https://redirect.github.com/rust-lang/rust/issues/135477).
See [PR#55](https://redirect.github.com/rust-lang/rustc-hash/pull/55)
for more details on the change (this PR was not merged).
This problem might be improved with changes to hashbrown in the future.

#### 2.1.0

-   Implement `Clone` for `FxRandomState`
-   Implement `Clone` for `FxSeededState`
-   Use SPDX license expression in license field

#### 2.0.0

-   Replace hash with faster and better finalized hash.
    This replaces the previous "fxhash" algorithm originating in Firefox
with a custom hasher designed and implemented by Orson Peters
([`@orlp`](https://redirect.github.com/orlp)).
It was measured to have slightly better performance for rustc, has
better theoretical properties
    and also includes a significantly better string hasher.
-   Fix `no_std` builds

#### 1.2.0 (**YANKED**)

**Note: This version has been yanked due to issues with the `no_std`
feature!**

-   Add a `FxBuildHasher` unit struct
-   Improve documentation
-   Add seed API for supplying custom seeds other than 0
- Add `FxRandomState` based on `rand` (behind the `rand` feature) for
random seeds
-   Make many functions `const fn`
-   Implement `Clone` for `FxHasher` struct

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjQuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE2NC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-10 08:22:52 +01:00
Dhruv Manilawala
869a9543e4 Root exclusions in the server to project root (#16043)
## Summary

fixes: #16041 

## Test Plan

Using the [project](https://github.com/bwcc-clan/polebot) in the linked
issue:

Notice how the project "polebot" is in the "play" directory which is
included in the `exclude` setting as:

```toml
exclude = ["play"]
```

**Before this fix**

```
DEBUG ruff:worker:0 ruff_server::resolve: Ignored path via `exclude`: /private/tmp/ruff-test/play/polebot/src/utils/log_tools.py
```

**After this fix**

```
DEBUG ruff:worker:2 ruff_server::resolve: Included path via `include`: /private/tmp/ruff-test/play/polebot/src/utils/log_tools.py
```

I also updated the same project to remove the "play" directory from the
`exclude` setting and made sure that anything under the `polebot/play`
directory is included:

```
DEBUG  ruff:worker:4 ruff_server::resolve: Included path via `include`: /private/tmp/ruff-test/play/polebot/play/test.py
```

And, excluded when I add the directory back:

```
DEBUG  ruff:worker:2 ruff_server::resolve: Ignored path via `exclude`: /private/tmp/ruff-test/play/polebot/play/test.py
```
2025-02-10 04:57:14 +00:00
Dhruv Manilawala
cc0a5dd14a Directly include Settings struct for the server (#16042)
## Summary

This PR refactors the `RuffSettings` struct to directly include the
resolved `Settings` instead of including the specific fields from it.
The server utilizes a lot of it already, so it makes sense to just
include the entire struct for simplicity.

### `Deref`

I implemented `Deref` on `RuffSettings` to return the `Settings` because
`RuffSettings` is now basically a wrapper around it with the config path
as the other field. This path field is only used for debugging
("printDebugInformation" command).
2025-02-10 10:20:01 +05:30
renovate[bot]
b54e390cb4 Update Rust crate clap to v4.5.28 (#16059) 2025-02-09 21:36:36 -05:00
renovate[bot]
5e1403a8a6 Update Rust crate strum_macros to 0.27.0 (#16065) 2025-02-10 02:36:08 +00:00
renovate[bot]
a6b86e3de2 Update NPM Development dependencies (#16067) 2025-02-09 21:29:45 -05:00
renovate[bot]
798725ccf9 Update Rust crate uuid to v1.13.1 (#16066) 2025-02-09 21:29:38 -05:00
renovate[bot]
81749164bc Update Rust crate strum to 0.27.0 (#16064) 2025-02-09 21:29:20 -05:00
renovate[bot]
b3ea17f128 Update pre-commit dependencies (#16063) 2025-02-09 21:29:12 -05:00
renovate[bot]
8fb69d3b05 Update dependency ruff to v0.9.5 (#16062) 2025-02-09 21:29:05 -05:00
renovate[bot]
3b69a8833d Update Rust crate toml to v0.8.20 (#16061) 2025-02-09 21:28:58 -05:00
Brent Westbrook
88b543d73a [flake8-builtins] Make strict module name comparison optional (A005) (#15951)
## Summary

This PR adds the configuration option
`lint.flake8-builtins.builtins-strict-checking`, which is used in A005
to determine whether the fully-qualified module name (relative to the
project root or source directories) should be checked instead of just
the final component as is currently the case.

As discussed in
https://github.com/astral-sh/ruff/issues/15399#issuecomment-2587017147,
the default value of the new option is `false` on preview, so modules
like `utils.logging` from the initial report are no longer flagged by
default. For non-preview the default is still strict checking.

## Test Plan

New A005 test module with the structure reported in #15399.

Fixes #15399
2025-02-09 19:33:03 -05:00
InSync
f367aa8367 [ruff] Indented form feeds (RUF054) (#16049)
## Summary

Resolves #12321.

The physical-line-based `RUF054` checks for form feed characters that
are preceded by only tabs and spaces, but not any other characters,
including form feeds.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-09 19:23:48 -05:00
David Salvisberg
9ae98d4a09 [flake8-type-checking] Avoid TC004 false positive with __getattr__ (#16052) 2025-02-09 16:27:06 +00:00
Dylan
0af4b23d9f [ruff] Skip type definitions for missing-f-string-syntax (RUF027) (#16054)
As an f-string is never correct in a type definition context, we skip
[missing-f-string-syntax
(RUF027)](https://docs.astral.sh/ruff/rules/missing-f-string-syntax/#missing-f-string-syntax-ruf027)
in this case.

Closes #16037
2025-02-09 10:16:28 -06:00
Dylan
f178ecc2d7 [flake8-pyi] Extend fix to Python <= 3.9 for redundant-none-literal (PYI061) (#16044)
This PR extends the fix offered for [redundant-none-literal
(PYI061)](https://docs.astral.sh/ruff/rules/redundant-none-literal/#redundant-none-literal-pyi061)
to include Python versions <= 3.9 by using `typing.Optional` instead of
the operator `|`. We also offer the fix with `|` for any target version
on stub files.

Closes #15795
2025-02-09 09:58:53 -06:00
InSync
a46fbda948 [flake8-datetime] Ignore .replace() calls while looking for .astimezone (#16050)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-02-09 15:48:59 +00:00
Alex Waygood
fc59e1b17f [red-knot] Merge TypeInferenceBuilder::infer_name_load and TypeInferenceBuilder::lookup_name (#16019)
## Summary

No functional change here; this is another simplification split out from
my outcome-refactor branch to reduce the diff there. This merges
`TypeInferenceBuilder::infer_name_load` and
`TypeInferenceBuilder::lookup_name`. This removes the need to have
extensive doc-comments about the purpose of
`TypeInferenceBuilder::lookup_name`, since the method only makes sense
when called from the specific context of
`TypeInferenceBuilder::infer_name_load`.

## Test Plan

`cargo test -p red_knot_python_semantic`
2025-02-08 19:42:14 +00:00
Dhruv Manilawala
1f3ff48b4f Undeprecate ruff.nativeServer (#16039)
Related to https://github.com/astral-sh/ruff-vscode/pull/684.
2025-02-08 22:29:07 +05:30
Carlos Martin
5e027a43ff Add JAX to users list. (#16031)
This PR adds [JAX](https://github.com/jax-ml/jax) to the
[list](https://github.com/astral-sh/ruff?tab=readme-ov-file#whos-using-ruff)
of open-source projects using Ruff.
2025-02-08 16:45:30 +00:00
Alex Waygood
22728808aa [pyupgrade] Ensure we do not rename two type parameters to the same name (UP049) (#16038)
Fixes #16024

## Summary

This PR adds proper isolation for `UP049` fixes so that two type
parameters are not renamed to the same name, which would introduce
invalid syntax. E.g. for this:

```py
class Foo[_T, __T]: ...
```

we cannot apply two autofixes to the class, as that would produce
invalid syntax -- this:

```py
class Foo[T, T]: ...
```

The "isolation" here means that Ruff won't apply more than one fix to
the same type-parameter list in a single iteration of the loop it does
to apply all autofixes. This means that after the first autofix has been
done, the semantic model will have recalculated which variables are
available in the scope, meaning that the diagnostic for the second
parameter will be deemed unfixable since it collides with an existing
name in the same scope (the name we autofixed the first parameter to in
an earlier iteration of the autofix loop).

Cc. @ntBre, for interest!

## Test Plan

I added an integration test that reproduces the bug on `main`.
2025-02-08 15:44:04 +00:00
InSync
a04ddf2a55 [pyupgrade] [ruff] Don't apply renamings if the new name is shadowed in a scope of one of the references to the binding (UP049, RUF052) (#16032)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-02-08 11:25:23 +00:00
Dylan
3a806ecaa1 [flake8-annotations] Correct syntax for typing.Union in suggested return type fixes for ANN20x rules (#16025)
When suggesting a return type as a union in Python <=3.9, we now avoid a
`TypeError` by correctly suggesting syntax like `Union[int,str,None]`
instead of `Union[int | str | None]`.
2025-02-07 17:17:20 -06:00
InSync
a29009e4ed [pyupgrade] Comments within parenthesized value ranges should not affect applicability (UP040) (#16027)
## Summary

Follow-up to #16026.

Previously, the fix for this would be marked as unsafe, even though all
comments are preserved:

```python
# .pyi
T: TypeAlias = (  # Comment
	int | str
)
```

Now it is safe: comments within the parenthesized range no longer affect
applicability.

## Test Plan

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

---------

Co-authored-by: Dylan <53534755+dylwil3@users.noreply.github.com>
2025-02-07 14:44:33 -06:00
InSync
19f3424a1a [pylint] Do not report calls when object type and argument type mismatch, remove custom escape handling logic (PLE1310) (#15984)
## Summary

Resolves #15968.

Previously, these would be considered violations:

```python
b''.strip('//')
''.lstrip('//', foo = "bar")
```

...while these are not:

```python
b''.strip(b'//')
''.strip('\\b\\x08')
```

Ruff will now not report when the types of the object and that of the
argument mismatch, or when there are extra arguments.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-07 14:31:07 -06:00
Brent Westbrook
d4a5772d96 [flake8-builtins] Match upstream module name comparison (A005) (#16006)
See #15951 for the original discussion and reviews. This is just the
first half of that PR (reaching parity with `flake8-builtins` without
adding any new configuration options) split out for nicer changelog
entries.

For posterity, here's a script for generating the module structure that
was useful for interactive testing and creating the table
[here](https://github.com/astral-sh/ruff/pull/15951#issuecomment-2640662041).
The results for this branch are the same as the `Strict` column there,
as expected.

```shell
mkdir abc collections foobar urlparse

for i in */
do
	touch $i/__init__.py
done	

cp -r abc foobar collections/.
cp -r abc collections foobar/.

touch ruff.toml

touch foobar/logging.py
```

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-07 13:55:56 -05:00
Alex Waygood
efa8a3ddcc [pyupgrade] Don't introduce invalid syntax when upgrading old-style type aliases with parenthesized multiline values (UP040) (#16026) 2025-02-07 17:05:17 +00:00
Dylan
46fe17767d Pass Checker by immutable reference to lint rules (#16012)
This very large PR changes the field `.diagnostics` in the `Checker`
from a `Vec<Diagnostic>` to a `RefCell<Vec<Diagnostic>>`, adds methods
to push new diagnostics to this cell, and then removes unnecessary
mutability throughout all of our lint rule implementations.

Consequently, the compiler may now enforce what was, till now, the
_convention_ that the only changes to the `Checker` that can happen
during a lint are the addition of diagnostics[^1].

The PR is best reviewed commit-by-commit. I have tried to keep the large
commits limited to "bulk actions that you can easily see are performing
the same find/replace on a large number of files", and separate anything
ad-hoc or with larger diffs. Please let me know if there's anything else
I can do to make this easier to review!

Many thanks to [`ast-grep`](https://github.com/ast-grep/ast-grep),
[`helix`](https://github.com/helix-editor/helix), and good ol'
fashioned`git` magic, without which this PR would have taken the rest of
my natural life.

[^1]: And randomly also the seen variables violating `flake8-bugbear`?
2025-02-07 09:05:50 -06:00
David Peter
1f7a29d347 [red-knot] Unpacker: Make invariant explicit and directly return a Type (#16018)
## Summary

- Do not return `Option<Type<…>>` from `Unpacker::get`, but just `Type`.
Panic otherwise.
- Rename `Unpacker::get` to `Unpacker::expression_type`
2025-02-07 12:00:04 +00:00
Wei Lee
618bfaf884 [airflow] Add external_task.{ExternalTaskMarker, ExternalTaskSensor} for AIR302 (#16014)
## Summary

Apply suggestions similar to
https://github.com/astral-sh/ruff/pull/15922#discussion_r1940697704


## Test Plan

a test fixture has been updated
2025-02-07 16:38:34 +05:30
Alex Waygood
b1c61cb2ee [ruff] Fix invalid annotation in docs example (#16016) 2025-02-07 10:45:51 +00:00
David Peter
97e6fc3793 [red-knot] Unpacking and for loop assignments to attributes (#16004)
## Summary

* Support assignments to attributes in more cases:
    - assignments in `for` loops
    - in unpacking assignments
* Add test for multi-target assignments
* Add tests for all other possible assignments to attributes that could
   possibly occur (in decreasing order of likeliness):
    - augmented attribute assignments
    - attribute assignments in `with` statements
    - attribute assignments in comprehensions
- Note: assignments to attributes in named expressions are not
   syntactically allowed

closes #15962

## Test Plan

New Markdown tests
2025-02-07 11:30:51 +01:00
Micha Reiser
38351e00ee [red-knot] Partial revert of relative import handling for files in the root of a search path (#16001)
## Summary

This PR reverts the behavior changes from
https://github.com/astral-sh/ruff/pull/15990

But it isn't just a revert, it also:

* Adds a test covering this specific behavior
* Preserves the improvement to use `saturating_sub` in the package case
to avoid overflows in the case of invalid syntax
* Use `ancestors` instead of a `for` loop

## Test Plan

Added test
2025-02-07 11:04:09 +01:00
Micha Reiser
26c37b1e0e Add knot.toml schema (#15735)
## Summary

Adds a JSON schema generation step for Red Knot. This PR doesn't yet add
a publishing step because it's still a bit early for that


## Test plan

I tested the schema in Zed, VS Code and PyCharm:

* PyCharm: You have to manually add a schema mapping (settings JSON
Schema Mappings)
* Zed and VS code support the inline schema specification

```toml
#:schema /Users/micha/astral/ruff/knot.schema.json


[environment]
extra-paths = []


[rules]
call-possibly-unbound-method = "error"
unknown-rule = "error"

# duplicate-base = "error"
```

```json
{
    "$schema": "file:///Users/micha/astral/ruff/knot.schema.json",

    "environment": {
        "python-version": "3.13",
        "python-platform": "linux2"
    },

    "rules": {
        "unknown-rule": "error"
    }
}
```


https://github.com/user-attachments/assets/a18fcd96-7cbe-4110-985b-9f1935584411


The Schema overall works but all editors have their own quirks:

* PyCharm: Hovering a name always shows the section description instead
of the description of the specific setting. But it's the same for other
settings in `pyproject.toml` files 🤷
* VS Code (JSON): Using the generated schema in a JSON file gives
exactly the experience I want
* VS Code (TOML): 
* Properties with multiple possible values are repeated during
auto-completion without giving any hint how they're different. ![Screen
Shot 2025-02-06 at 14 05 35
PM](https://github.com/user-attachments/assets/d7f3c2a9-2351-4226-9fc1-b91aa192a237)
* The property description mushes together the description of the
property and the value, which looks sort of ridiculous. ![Screen Shot
2025-02-06 at 14 04 40
PM](https://github.com/user-attachments/assets/8b72f04a-c62a-49b5-810f-7ddd472884d0)
* Autocompletion and documentation hovering works (except the
limitations mentioned above)
* Zed:
* Very similar to VS Code with the exception that it uses the
description attribute to distinguish settings with multiple possible
values ![Screen Shot 2025-02-06 at 14 08 19
PM](https://github.com/user-attachments/assets/78a7f849-ff4e-44ff-8317-708eaf02dc1f)


I don't think there's much we can do here other than hope (or help)
editors improve their auto completion. The same short comings also apply
to ruff, so this isn't something new. For now, I think this is good
enough
2025-02-07 10:59:40 +01:00
InSync
7db5a924af [flake8-comprehensions] Detect overshadowed list/set/dict, ignore variadics and named expressions (C417) (#15955)
## Summary

Part of #15809 and #15876.

This change brings several bugfixes:

* The nested `map()` call in `list(map(lambda x: x, []))` where `list`
is overshadowed is now correctly reported.
* The call will no longer reported if:
	* Any arguments given to `map()` are variadic.
	* Any of the iterables contain a named expression.

## Test Plan

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

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-07 08:58:05 +00:00
Junhson Jean-Baptiste
349f93389e [flake8-simplify] Only trigger SIM401 on known dictionaries (SIM401) (#15995)
## Summary

This change resolves #15814 to ensure that `SIM401` is only triggered on
known dictionary types. Before, the rule was getting triggered even on
types that _resemble_ a dictionary but are not actually a dictionary.

I did this using the `is_known_to_be_of_type_dict(...)` functionality.
The logic for this function was duplicated in a few spots, so I moved
the code to a central location, removed redundant definitions, and
updated existing calls to use the single definition of the function!

## Test Plan

Since this PR only modifies an existing rule, I made changes to the
existing test instead of adding new ones. I made sure that `SIM401` is
triggered on types that are clearly dictionaries and that it's not
triggered on a simple custom dictionary-like type (using a modified
version of [the code in the issue](#15814))

The additional changes to de-duplicate `is_known_to_be_of_type_dict`
don't break any existing tests -- I think this should be fine since the
logic remains the same (please let me know if you think otherwise, I'm
excited to get feedback and work towards a good fix 🙂).

---------

Co-authored-by: Junhson Jean-Baptiste <junhsonjb@naan.mynetworksettings.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-07 08:25:20 +00:00
InSync
bb979e05ac [flake8-pie] Remove following comma correctly when the unpacked dictionary is empty (PIE800) (#16008)
## Summary

Resolves #15997.

Ruff used to introduce syntax errors while fixing these cases, but no
longer will:

```python
{"a": [], **{},}
#         ^^^^ Removed, leaving two contiguous commas

{"a": [], **({})}
#         ^^^^^ Removed, leaving a stray closing parentheses
```

Previously, the function would take a shortcut if the unpacked
dictionary is empty; now, both cases are handled using the same logic
introduced in #15394. This change slightly modifies that logic to also
remove the first comma following the dictionary, if and only if it is
empty.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-07 08:52:10 +01:00
Dylan
10d3e64ccd Bump version to 0.9.5 (#16002) 2025-02-06 13:24:45 -06:00
InSync
84ceddcbd9 [ruff] Classes with mixed type variable style (RUF053) (#15841) 2025-02-06 18:35:51 +00:00
Ayush Baweja
ba2f0e998d [flake8-pyi] Add autofix for unused-private-type-var (PYI018) (#15999)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-06 18:08:36 +00:00
Alex Waygood
18b497a913 [red-knot] Fixup a couple of nits in the red_knot_test README (#15996) 2025-02-06 15:04:27 +00:00
Micha Reiser
7cac0da44d Workaround Even Better TOML crash related to allOf (#15992)
## Summary

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

Even Better TOML doesn't support `allOf` well. In fact, it just crashes.

This PR works around this limitation by avoid using `allOf` in the
automatically
derived schema for the docstring formatting setting. 

### Alternatives

schemars introduces `allOf` whenver it sees a `$ref` alongside other
object properties
because this is no longer valid according to Draft 7. We could replace
the
visitor performing the rewrite but I prefer not to because replacing
`allOf` with `oneOf`
is only valid for objects that don't have any other `oneOf` or `anyOf`
schema.

## Test Plan


https://github.com/user-attachments/assets/25d73b2a-fee1-4ba6-9ffe-869b2c3bc64e
2025-02-06 16:00:50 +01:00
Dhruv Manilawala
b66cc94f9b Add deprecation warning for ruff-lsp related settings (#15850)
## Summary

This PR updates the documentation to add deprecated warning for
`ruff-lsp` specific settings

### Preview


https://github.com/user-attachments/assets/64e11e4b-7178-43ab-be5b-421e7f4689de

## Test Plan

Build the documentation locally and test out the links. Refer to the
preview video above.
2025-02-06 20:12:41 +05:30
David Peter
e345307260 [red-knot] Fix diagnostic range for non-iterable unpacking assignments (#15994)
## Summary

I noticed that the diagnostic range in specific unpacking assignments is
wrong. For this example

```py
a, b = 1
```

we previously got (see first commit):

```
error: lint:not-iterable
 --> /src/mdtest_snippet.py:1:1
  |
1 | a, b = 1
  | ^^^^ Object of type `Literal[1]` is not iterable
  |
```

and with this change, we get:

```
error: lint:not-iterable
 --> /src/mdtest_snippet.py:1:8
  |
1 | a, b = 1
  |        ^ Object of type `Literal[1]` is not iterable
  |
```

## Test Plan

New snapshot tests.
2025-02-06 15:36:22 +01:00
Micha Reiser
5588c75d65 [red-knot] Fix relative imports in src.root (#15990)
## Summary

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

Red Knot failed to resolve relative imports if the importing module is
located at a search path root.

The issue was that the module resolver returned an `Err(TooManyDots)` as
soon as the parent of the current module is `None` (which is the case
for a module at the search path root).
However, this is incorrect if a `tail` (a module name) exists.
2025-02-06 14:08:20 +00:00
Raymond Berger
9d2105b863 add instance variable examples to RUF012 (#15982)
## Summary

Closes #15804 

Add more examples to the documentation.

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-06 14:01:09 +00:00
David Salvisberg
8fcac0ff36 Recognize all symbols named TYPE_CHECKING for in_type_checking_block (#15719)
Closes #15681

## Summary

This changes `analyze::typing::is_type_checking_block` to recognize all
symbols named "TYPE_CHECKING".
This matches the current behavior of mypy and pyright as well as
`flake8-type-checking`.

It also drops support for detecting `if False:` and `if 0:` as type
checking blocks. This used to be an option for
providing backwards compatibility with Python versions that did not have
a `typing` module, but has since
been removed from the typing spec and is no longer supported by any of
the mainstream type checkers.

## Test Plan

`cargo nextest run`

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-06 14:45:12 +01:00
Vasco Schiavo
81059d05fc [pep8-naming] Consider any number of leading underscore for N801 (#15988)
## Summary

The PR addresses the issue #15939 

Let me know if you think there are other test cases I should add ;-)
2025-02-06 14:08:27 +05:30
Vasco Schiavo
24bab7e82e [pycodestyle] Exempt sys.path += ... calls (E402) (#15980)
## Summary

The PR addresses issue #15886 .
2025-02-06 08:51:51 +01:00
David Peter
d0555f7b5c [red-knot] Litate tests: minor follow-up (#15987)
## Summary

- Minor wording update
- Code improvement (thanks Alex)
- Removed all unnecessary filenames throughout our Markdown tests (two
new ones were added in the meantime)
- Minor rewording of the statically-known-branches introduction
2025-02-06 07:15:26 +00:00
Douglas Creager
0906554357 [red-knot] Combine terminal statement support with statically known branches (#15817)
This example from @sharkdp shows how terminal statements can appear in
statically known branches:
https://github.com/astral-sh/ruff/pull/15676#issuecomment-2618809716

```py
def _(cond: bool):
    x = "a"
    if cond:
        x = "b"
        if True:
            return

    reveal_type(x)  # revealed: "a", "b"; should be "a"
```

We now use visibility constraints to track reachability, which allows us
to model this correctly. There are two related changes as a result:

- New bindings are not assumed to be visible; they inherit the current
"scope start" visibility, which effectively means that new bindings are
visible if/when the current flow is reachable

- When simplifying visibility constraints after branching control flow,
we only simplify if none of the intervening branches included a terminal
statement. That is, earlier unaffected bindings are only _actually_
unaffected if all branches make it to the merge point.
2025-02-05 17:47:49 -05:00
David Peter
d296f602e7 [red-knot] Merge Markdown code blocks inside a single section (#15950)
## Summary

Allow for literate style in Markdown tests and merge multiple (unnamed)
code blocks into a single embedded file.

closes #15941

## Test Plan

- Interactively made sure that error-lines were reported correctly in
  multi-snippet sections.
2025-02-05 22:26:15 +01:00
Andrew Gallant
d47088c8f8 [red-knot] fix unresolvable import range (#15976)
This causes the diagnostic to highlight the actual unresovable import
instead of the entire `from ... import ...` statement.

While we're here, we expand the test coverage to cover all of the
possible ways that an `import` or a `from ... import` can fail.

Some considerations:

* The first commit in this PR adds a regression test for the current
behavior.
* This creates a new `mdtest/diagnostics` directory. Are folks cool
with this? I guess the idea is to put tests more devoted to diagnostics
than semantics in this directory. (Although I'm guessing there will
be some overlap.)

Fixes #15866
2025-02-05 14:01:58 -05:00
David Peter
1f0ad675d3 [red-knot] Initial set of descriptor protocol tests (#15972)
## Summary

This is a first step towards creating a test suite for
[descriptors](https://docs.python.org/3/howto/descriptor.html). It does
not (yet) aim to be exhaustive.

relevant ticket: #15966 

## Test Plan

Compared desired behavior with the runtime behavior and the behavior of
existing type checkers.

---------

Co-authored-by: Mike Perlov <mishamsk@gmail.com>
2025-02-05 19:47:43 +01:00
Andrew Gallant
a84b27e679 red_knot_test: add support for diagnostic snapshotting
This ties together everything from the previous commits.
Some interesting bits here are how the snapshot is generated
(where we include relevant info to make it easier to review
the snapshots) and also a tweak to how inline assertions are
processed.

This commit also includes some example snapshots just to get
a sense of what they look like. Follow-up work should add
more of these I think.
2025-02-05 13:02:54 -05:00
Andrew Gallant
8d4679b3ae red_knot_test: update README with section on diagnostic snapshotting
I split this out into a separate commit and put it here
so that reviewers can get a conceptual model of what the
code is doing before seeing the code. (Hopefully that helps.)
2025-02-05 13:02:54 -05:00
Andrew Gallant
b40a7cce15 red_knot_test: add snapshot path
This makes it possible for callers to set where snapshots
should be stored. In general, I think we expect this to
always be set, since otherwise snapshots will end up in
`red_knot_test`, which is where the tests are actually run.
But that's overall counter-intuitive. This permits us to
store snapshots from mdtests alongside the mdtests themselves.
2025-02-05 13:02:54 -05:00
Andrew Gallant
54b3849dfb ruff_db: add more dyn Diagnostic impls
I found it useful to have the `&dyn Diagnostic` trait impl
specifically. I added `Arc<dyn Diagnostic>` for completeness.

(I do kind of wonder if we should be preferring `Arc<dyn ...>`
over something like `Box<dyn ...>` more generally, especially
for things with immutable APIs. It would make cloning cheap.)
2025-02-05 13:02:54 -05:00
Andrew Gallant
ffd94e9ace red_knot_test: generate names for unnamed files using more local reasoning
This change was done to reduce snapshot churn. Previously,
if one added a new section to an Markdown test suite, then
the snapshots of all sections with unnamed files below it would
necessarily change because of the unnamed file count being
global to the test suite.

Instead, we track counts based on section. While adding new
unnamed files within a section will still change unnamed
files below it, I believe this will be less "churn" because
the snapshot will need to change anyway. Some churn is still
possible, e.g., if code blocks are re-ordered. But I think this
is an acceptable trade-off.
2025-02-05 13:02:54 -05:00
Alex Waygood
c816542704 [red-knot] Fix some instance-attribute TODOs around ModuleType (#15974) 2025-02-05 15:33:37 +00:00
Zanie Blue
3f958a9d4c Use a larger runner for the cargo build (msrv) job (#15973) 2025-02-05 09:03:55 -06:00
Alex Waygood
2ebb5e8d4b [red-knot] Make Symbol::or_fall_back_to() lazy (#15943) 2025-02-05 14:51:02 +00:00
Dylan
c69b19fe1d [flake8-comprehensions] Handle trailing comma in fixes for unnecessary-generator-list/set (C400,C401) (#15929)
The unsafe fixes for the rules [unnecessary-generator-list
(C400)](https://docs.astral.sh/ruff/rules/unnecessary-generator-list/#unnecessary-generator-list-c400)
and [unnecessary-generator-set
(C401)](https://docs.astral.sh/ruff/rules/unnecessary-generator-set/#unnecessary-generator-set-c401)
used to introduce syntax errors if the argument to `list` or `set` had a
trailing comma, because the fix would retain the comma after
transforming the function call to a comprehension.

This PR accounts for the trailing comma when replacing the end of the
call with a `]` or `}`.

Closes #15852
2025-02-05 07:38:03 -06:00
Brent Westbrook
076d35fb93 [minor] Mention UP049 in UP046 and UP047, add See also section to UP040 (#15956)
## Summary

Minor docs follow-up to #15862 to mention UP049 in the UP046 and UP047
`See also` sections. I wanted to mention it in UP040 too but realized it
didn't have a `See also` section, so I also added that, adapted from the
other two rules.

## Test Plan

cargo test
2025-02-05 08:34:47 -05:00
Dylan
16f2a93fca [ruff] Analyze deferred annotations before enforcing mutable-(data)class-default and function-call-in-dataclass-default-argument (RUF008,RUF009,RUF012) (#15921) 2025-02-05 06:44:19 -06:00
David Peter
eb08345fd5 [red-knot] Extend instance/class attribute tests (#15959)
## Summary

In preparation for creating some (sub) issues for
https://github.com/astral-sh/ruff/issues/14164, I'm trying to document
the current behavior (and a bug) a bit better.
2025-02-05 12:45:00 +01:00
Alex Waygood
7ca778f492 [refurb] Minor nits regarding for-loop-writes and for-loop-set-mutations (#15958) 2025-02-05 10:21:36 +00:00
Vasco Schiavo
827a076a2f [pylint] Fix PL1730: min/max auto-fix and suggestion (#15930)
## Summary

The PR addresses the issue #15887 

For two objects `a` and `b`, we ensure that the auto-fix and the
suggestion is of the form `a = min(a, b)` (or `a = max(a, b)`). This is
because we want to be consistent with the python implementation of the
methods: `min` and `max`. See the above issue for more details.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-05 09:29:10 +00:00
InSync
4855e0b288 [refurb] Handle unparenthesized tuples correctly (FURB122, FURB142) (#15953)
## Summary

Resolves #15936.

The fixes will now attempt to preserve the original iterable's format
and quote it if necessary. For `FURB142`, comments within the fix range
will make it unsafe as well.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-05 10:16:54 +01:00
InSync
44ddd98d7e [pyupgrade] Better messages and diagnostic range (UP015) (#15872)
## Summary

Resolves #15863.

In preview, diagnostic ranges will now be limited to that of the
argument. Rule documentation, variable names, error messages and fix
titles have all been modified to use "argument" consistently.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-05 09:44:26 +01:00
InSync
82cb8675dd [pep8-naming] Ignore @override methods (N803) (#15954)
## Summary

Resolves #15925.

`N803` now checks for functions instead of parameters. In preview mode,
if a method is decorated with `@override` and the current scope is that
of a class, it will be ignored.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-02-05 09:35:57 +01:00
InSync
5852217198 [refurb] Also report non-name expressions (FURB169) (#15905)
## Summary

Follow-up to #15779.

Prior to this change, non-name expressions are not reported at all:

```python
type(a.b) is type(None)  # no error
```

This change enhances the rule so that such cases are also reported in
preview. Additionally:

* The fix will now be marked as unsafe if there are any comments within
its range.
* Error messages are slightly modified.

## Test Plan

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

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-05 08:46:37 +01:00
Dylan
700e969c56 Config error only when flake8-import-conventions alias conflicts with isort.required-imports bound name (#15918)
Previously an error was emitted any time the configuration required both
an import of a module and an alias for that module. However, required
imports could themselves contain an alias, which may or may not agree
with the required alias.

To wit: requiring `import pandas as pd` does not conflict with the
`flake8-import-conventions.alias` config `{"pandas":"pd"}`.

This PR refines the check before throwing an error.

Closes #15911
2025-02-04 17:05:35 -06:00
InSync
4c15d7a559 Fix a typo in non_pep695_generic_class.rs (#15946)
(Accidentally introduced in #15904.)
2025-02-04 22:16:18 +00:00
Mike Perlov
e15419396c [red-knot] Fix Stack overflow in Type::bool (#15843)
## Summary

This PR adds `Type::call_bound` method for calls that should follow
descriptor protocol calling convention. The PR is intentionally shallow
in scope and only fixes #15672

Couple of obvious things that weren't done:

* Switch to `call_bound` everywhere it should be used
* Address the fact, that red_knot resolves `__bool__ = bool` as a Union,
which includes `Type::Dynamic` and hence fails to infer that the
truthiness is always false for such a class (I've added a todo comment
in mdtests)
* Doesn't try to invent a new type for descriptors, although I have a
gut feeling it may be more convenient in the end, instead of doing
method lookup each time like I did in `call_bound`

## Test Plan

* extended mdtests with 2 examples from the issue
* cargo neatest run
2025-02-04 12:40:07 -08:00
Douglas Creager
444b055cec [red-knot] Use ternary decision diagrams (TDDs) for visibility constraints (#15861)
We now use ternary decision diagrams (TDDs) to represent visibility
constraints. A TDD is just like a BDD ([_binary_ decision
diagram](https://en.wikipedia.org/wiki/Binary_decision_diagram)), but
with "ambiguous" as an additional allowed value. Unlike the previous
representation, TDDs are strongly normalizing, so equivalent ternary
formulas are represented by exactly the same graph node, and can be
compared for equality in constant time.

We currently have a slight 1-3% performance regression with this in
place, according to local testing. However, we also have a _5× increase_
in performance for pathological cases, since we can now remove the
recursion limit when we evaluate visibility constraints.

As follow-on work, we are now closer to being able to remove the
`simplify_visibility_constraint` calls in the semantic index builder. In
the vast majority of cases, we now see (for instance) that the
visibility constraint after an `if` statement, for bindings of symbols
that weren't rebound in any branch, simplifies back to `true`. But there
are still some cases we generate constraints that are cyclic. With
fixed-point cycle support in salsa, or with some careful analysis of the
still-failing cases, we might be able to remove those.
2025-02-04 14:32:11 -05:00
Brent Westbrook
6bb32355ef [pyupgrade] Rename private type parameters in PEP 695 generics (UP049) (#15862)
## Summary

This is a new rule to implement the renaming of PEP 695 type parameters
with leading underscores after they have (presumably) been converted
from standalone type variables by either UP046 or UP047. Part of #15642.

I'm not 100% sure the fix is always safe, but I haven't come up with any
counterexamples yet. `Renamer` seems pretty precise, so I don't think
the usual issues with comments apply.

I initially tried writing this as a rule that receives a `Stmt` rather
than a `Binding`, but in that case the
`checker.semantic().current_scope()` was the global scope, rather than
the scope of the type parameters as I needed. Most of the other rules
using `Renamer` also used `Binding`s, but it does have the downside of
offering separate diagnostics for each parameter to rename.

## Test Plan

New snapshot tests for UP049 alone and the combination of UP046, UP049,
and PYI018.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-04 13:22:57 -05:00
Alex Waygood
cb71393332 Simplify the StringFlags trait (#15944) 2025-02-04 18:14:28 +00:00
Alex Waygood
64e64d2681 [flake8-pyi] Make PYI019 autofixable for .py files in preview mode as well as stubs (#15889) 2025-02-04 16:41:22 +00:00
Alexander Nordin
9d83e76a3b Docs (linter.md): clarify that Python files are always searched for in subdirectories (#15882)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-04 15:36:16 +00:00
Alex Waygood
5bf0e2e95e [flake8-pyi] Make PEP-695 functions with multiple type parameters fixable by PYI019 again (#15938) 2025-02-04 14:38:22 +00:00
David Peter
24c1cf71cb [red-knot] Use unambiguous invalid-syntax-construct for suppression comment test (#15933)
## Summary

I experimented with [not trimming trailing newlines in code
snippets](https://github.com/astral-sh/ruff/pull/15926#discussion_r1940992090),
but since came to the conclusion that the current behavior is better
because otherwise, there is no way to write snippets without a trailing
newline at all. And when you copy the code from a Markdown snippet in
GitHub, you also don't get a trailing newline.

I was surprised to see some test failures when I played with this
though, and decided to make this test independent from this
implementation detail.
2025-02-04 15:24:50 +01:00
Alex Waygood
f23802e219 Make Binding::range() point to the range of a type parameter's name, not the full type parameter (#15935)
Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-02-04 14:14:21 +00:00
Micha Reiser
ff87ea8d42 Update black deviations (#15928) 2025-02-04 14:04:24 +00:00
David Peter
cc60701b59 [red-knot] MDTest: Fix line numbers in error messages (#15932)
## Summary

Fix line number reporting in MDTest error messages.

## Test Plan

Introduced an error in a Markdown test and made sure that the line in
the error message matches.
2025-02-04 13:44:05 +00:00
Brent Westbrook
b5e5271adf Preserve triple quotes and prefixes for strings (#15818)
## Summary

This is a follow-up to #15726, #15778, and #15794 to preserve the triple
quote and prefix flags in plain strings, bytestrings, and f-strings.

I also added a `StringLiteralFlags::without_triple_quotes` method to
avoid passing along triple quotes in rules like SIM905 where it might
not make sense, as discussed
[here](https://github.com/astral-sh/ruff/pull/15726#discussion_r1930532426).

## Test Plan

Existing tests, plus many new cases in the `generator::tests::quote`
test that should cover all combinations of quotes and prefixes, at least
for simple string bodies.

Closes #7799 when combined with #15694, #15726, #15778, and #15794.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-04 08:41:06 -05:00
David Peter
9a33924a65 [red-knot] Hand-written MDTest parser (#15926)
## Summary

Replaces our existing Markdown test parser with a fully hand-written
parser. I tried to fix this bug using the old approach and kept running
into problems. Eventually this seemed like the easier way. It's more
code (+50 lines, excluding the new test), but I hope it's relatively
straightforward to understand, compared to the complex interplay between
the byte-stream-manipulation and regex-parsing that we had before.

I did not really focus on performance, as the parsing time does not
dominate the test execution time, but this seems to be slightly faster
than what we had before (executing all MD tests; debug):

| Command | Mean [s] | Min [s] | Max [s] | Relative |
|:---|---:|---:|---:|---:|
| this branch | 2.775 ± 0.072 | 2.690 | 2.877 | 1.00 |
| `main` | 2.921 ± 0.034 | 2.865 | 2.967 | 1.05 ± 0.03 |

closes #15923

## Test Plan

One new regression test.
2025-02-04 14:01:53 +01:00
Mike Perlov
15dd3b5ebd [pylint] Fix missing parens in unsafe fix for unnecessary-dunder-call (PLC2801) (#15762)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-04 09:54:01 +00:00
Alexander Nordin
b848afeae8 nit: docs for ignore & select (#15883) 2025-02-04 10:05:41 +01:00
Wei Lee
de4d9979eb [airflow] BashOperator has been moved to airflow.providers.standard.operators.bash.BashOperator (AIR302) (#15922)
## Summary

Extend AIR302 with 

* `airflow.operators.bash.BashOperator →
airflow.providers.standard.operators.bash.BashOperator`
* change existing rules `airflow.operators.bash_operator.BashOperator →
airflow.operators.bash.BashOperator` to
`airflow.operators.bash_operator.BashOperator →
airflow.providers.standard.operators.bash.BashOperator`

## Test Plan

a test fixture has been updated
2025-02-04 14:28:00 +05:30
InSync
ba02294af3 [flake8-logging] .exception() and exc_info= outside exception handlers (LOG004, LOG014) (#15799) 2025-02-04 09:52:12 +01:00
InSync
11cfe2ea8a [red-knot] Enforce specifying paths for mdtest code blocks in a separate preceding line (#15890)
## Summary

Resolves #15695, rework of #15704.

This change modifies the Mdtests framework so that:

* Paths must now be specified in a separate preceding line:

	`````markdown
	`a.py`:

	```py
	x = 1
	```
	`````

If the path of a file conflicts with its `lang`, an error will be
thrown.

* Configs are no longer accepted. The pattern still take them into
account, however, to avoid "Unterminated code block" errors.
* Unnamed files are now assigned unique, `lang`-respecting paths
automatically.

Additionally, all legacy usages have been updated.

## Test Plan

Unit tests and Markdown tests.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-02-04 08:27:17 +01:00
Douglas Creager
0529ad67d7 [red-knot] Internal refactoring of visibility constraints API (#15913)
This extracts some pure refactoring noise from
https://github.com/astral-sh/ruff/pull/15861. This changes the API for
creating and evaluating visibility constraints, but does not change how
they are respresented internally. There should be no behavioral or
performance changes in this PR.

Changes:

- Hide the internal representation isn't changed, so that we can make
changes to it in #15861.
- Add a separate builder type for visibility constraints. (With TDDs, we
will have some additional builder state that we can throw away once
we're done constructing.)
- Remove a layer of helper methods from `UseDefMapBuilder`, making
`SemanticIndexBuilder` responsible for constructing whatever visibility
constraints it needs.
2025-02-03 15:13:09 -05:00
David Peter
102c2eec12 [red-knot] Implicit instance attributes (#15811)
## Summary

Add support for implicitly-defined instance attributes, i.e. support
type inference for cases like this:
```py
class C:
    def __init__(self) -> None:
        self.x: int = 1
        self.y = None

reveal_type(C().x)  # int
reveal_type(C().y)  # Unknown | None
```

## Benchmarks

Codspeed reports no change in a cold-cache benchmark, and a -1%
regression in the incremental benchmark. On `black`'s `src` folder, I
don't see a statistically significant difference between the branches:

| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|:---|---:|---:|---:|---:|
| `./red_knot_main check --project /home/shark/black/src` | 133.7 ± 9.5 | 126.7 | 164.7 | 1.01 ± 0.08 |
| `./red_knot_feature check --project /home/shark/black/src` | 132.2 ± 5.1 | 118.1 | 140.9 | 1.00 |

## Test Plan

Updated and new Markdown tests
2025-02-03 19:34:23 +01:00
Justin Bramley
dc5e922221 [flake8-comprehensions] Handle extraneous parentheses around list comprehension (C403) (#15877)
## Summary

Given the following code:

```python
set(([x for x in range(5)]))
```

the current implementation of C403 results in

```python
{(x for x in range(5))}
```

which is a set containing a generator rather than the result of the
generator.

This change removes the extraneous parentheses so that the resulting
code is:

```python
{x for x in range(5)}
```


## Test Plan

`cargo nextest run` and `cargo insta test`
2025-02-03 13:26:03 -05:00
Alex Waygood
62075afe4f [flake8-pyi] Significantly improve accuracy of PYI019 if preview mode is enabled (#15888) 2025-02-03 15:45:10 +00:00
InSync
dfe1b849d0 Convert .md links in rule documentation to full URLs (#15904) 2025-02-03 15:33:03 +01:00
Alex Waygood
9c64d65552 [flake8-pyi] Rename PYI019 and improve its diagnostic message (#15885) 2025-02-03 14:23:58 +00:00
Vasco Schiavo
83243de93d Improve Docs: Pylint subcategories' codes (#15909) 2025-02-03 13:53:36 +01:00
renovate[bot]
638186afbd Update Rust crate rand to 0.9.0 (#15899)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-03 12:25:57 +01:00
Dhruv Manilawala
d082c1b202 [red-knot] Add missing imports in mdtests (#15869)
## Summary

Related to #15848, this PR adds the imports explicitly as we'll now flag
these symbols as undefined.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-03 09:27:29 +00:00
InSync
30d5e9a2af [red-knot] Support --exit-zero and --error-on-warning (#15746)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-03 07:35:30 +00:00
renovate[bot]
a613345274 Update Rust crate imara-diff to v0.1.8 (#15891)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [imara-diff](https://redirect.github.com/pascalkuthe/imara-diff) |
workspace.dependencies | patch | `0.1.7` -> `0.1.8` |

---

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

---

### Release Notes

<details>
<summary>pascalkuthe/imara-diff (imara-diff)</summary>

###
[`v0.1.8`](https://redirect.github.com/pascalkuthe/imara-diff/blob/HEAD/CHANGELOG.md#018---2025-2-1)

[Compare
Source](https://redirect.github.com/pascalkuthe/imara-diff/compare/v0.1.7...v0.1.8)

##### Changed

-   update MSRV to 1.71
- drop ahash dependency in favour of hashbrowns default hasher
(foldhash)

##### Fixed

-   incomplete documentation for sink and interner

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 12:29:53 +05:30
renovate[bot]
c81f6c0bd2 Update dependency mdformat to v0.7.22 (#15896)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [mdformat](https://redirect.github.com/hukkin/mdformat)
([changelog](https://mdformat.readthedocs.io/en/stable/users/changelog.html))
| `==0.7.21` -> `==0.7.22` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/mdformat/0.7.22?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/mdformat/0.7.22?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/mdformat/0.7.21/0.7.22?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/mdformat/0.7.21/0.7.22?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/mdformat (mdformat)</summary>

###
[`v0.7.22`](https://redirect.github.com/hukkin/mdformat/compare/0.7.21...0.7.22)

[Compare
Source](https://redirect.github.com/hukkin/mdformat/compare/0.7.21...0.7.22)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 12:24:31 +05:30
renovate[bot]
ba534d1931 Update Rust crate serde_json to v1.0.138 (#15893)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [serde_json](https://redirect.github.com/serde-rs/json) |
workspace.dependencies | patch | `1.0.137` -> `1.0.138` |

---

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

---

### Release Notes

<details>
<summary>serde-rs/json (serde_json)</summary>

###
[`v1.0.138`](https://redirect.github.com/serde-rs/json/releases/tag/v1.0.138)

[Compare
Source](https://redirect.github.com/serde-rs/json/compare/v1.0.137...v1.0.138)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 12:22:32 +05:30
renovate[bot]
7e1db01041 Update Rust crate indicatif to v0.17.11 (#15892)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [indicatif](https://redirect.github.com/console-rs/indicatif) |
workspace.dependencies | patch | `0.17.9` -> `0.17.11` |

---

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

---

### Release Notes

<details>
<summary>console-rs/indicatif (indicatif)</summary>

###
[`v0.17.11`](https://redirect.github.com/console-rs/indicatif/releases/tag/0.17.11)

[Compare
Source](https://redirect.github.com/console-rs/indicatif/compare/0.17.10...0.17.11)

#### What's Changed

- Change `OnceCell` to `OnceLock` in `TabExpandedString` by
[@&#8203;tgross35](https://redirect.github.com/tgross35) in
[https://github.com/console-rs/indicatif/pull/694](https://redirect.github.com/console-rs/indicatif/pull/694)

###
[`v0.17.10`](https://redirect.github.com/console-rs/indicatif/releases/tag/0.17.10)

[Compare
Source](https://redirect.github.com/console-rs/indicatif/compare/0.17.9...0.17.10)

#### What's Changed

With some great performance improvements from
[@&#8203;jaheba](https://redirect.github.com/jaheba).

- Fix bar-less text output by
[@&#8203;spoutn1k](https://redirect.github.com/spoutn1k) in
[https://github.com/console-rs/indicatif/pull/659](https://redirect.github.com/console-rs/indicatif/pull/659)
- add tracing-indicatif create to integration list by
[@&#8203;emersonford](https://redirect.github.com/emersonford) in
[https://github.com/console-rs/indicatif/pull/673](https://redirect.github.com/console-rs/indicatif/pull/673)
- Fix double prints by
[@&#8203;spoutn1k](https://redirect.github.com/spoutn1k) in
[https://github.com/console-rs/indicatif/pull/671](https://redirect.github.com/console-rs/indicatif/pull/671)
- Only get draw_target-width when we actually draw by
[@&#8203;jaheba](https://redirect.github.com/jaheba) in
[https://github.com/console-rs/indicatif/pull/683](https://redirect.github.com/console-rs/indicatif/pull/683)
- Make tab extension lazy by
[@&#8203;jaheba](https://redirect.github.com/jaheba) in
[https://github.com/console-rs/indicatif/pull/684](https://redirect.github.com/console-rs/indicatif/pull/684)
- Make `ProgressBar:set_tab_with` take `&self` by
[@&#8203;jaheba](https://redirect.github.com/jaheba) in
[https://github.com/console-rs/indicatif/pull/685](https://redirect.github.com/console-rs/indicatif/pull/685)
- Remove unnecessary spinner display in multi examples by
[@&#8203;shuntaka9576](https://redirect.github.com/shuntaka9576) in
[https://github.com/console-rs/indicatif/pull/682](https://redirect.github.com/console-rs/indicatif/pull/682)
- Add `dec` and `dec_length` to `ProgressBar` by
[@&#8203;jaheba](https://redirect.github.com/jaheba) in
[https://github.com/console-rs/indicatif/pull/690](https://redirect.github.com/console-rs/indicatif/pull/690)
- Update rand requirement from 0.8 to 0.9 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/console-rs/indicatif/pull/693](https://redirect.github.com/console-rs/indicatif/pull/693)

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 12:22:11 +05:30
renovate[bot]
6331dd6272 Update Rust crate syn to v2.0.98 (#15894)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [syn](https://redirect.github.com/dtolnay/syn) |
workspace.dependencies | patch | `2.0.96` -> `2.0.98` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/syn (syn)</summary>

###
[`v2.0.98`](https://redirect.github.com/dtolnay/syn/releases/tag/2.0.98)

[Compare
Source](https://redirect.github.com/dtolnay/syn/compare/2.0.97...2.0.98)

- Allow lifetimes in function pointer return values in
`ParseStream::call` and `Punctuated` parsers
([#&#8203;1847](https://redirect.github.com/dtolnay/syn/issues/1847))

###
[`v2.0.97`](https://redirect.github.com/dtolnay/syn/releases/tag/2.0.97)

[Compare
Source](https://redirect.github.com/dtolnay/syn/compare/2.0.96...2.0.97)

-   Documentation improvements

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 12:19:48 +05:30
renovate[bot]
4fe78db16c Update Rust crate unicode-ident to v1.0.16 (#15895)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [unicode-ident](https://redirect.github.com/dtolnay/unicode-ident) |
workspace.dependencies | patch | `1.0.15` -> `1.0.16` |

---

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

---

### Release Notes

<details>
<summary>dtolnay/unicode-ident (unicode-ident)</summary>

###
[`v1.0.16`](https://redirect.github.com/dtolnay/unicode-ident/releases/tag/1.0.16)

[Compare
Source](https://redirect.github.com/dtolnay/unicode-ident/compare/1.0.15...1.0.16)

- Update `rand` dev dependency to 0.9
([#&#8203;29](https://redirect.github.com/dtolnay/unicode-ident/issues/29))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 12:18:59 +05:30
renovate[bot]
f5f74c95c5 Update Rust crate tempfile to v3.16.0 (#15900)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [tempfile](https://stebalien.com/projects/tempfile-rs/)
([source](https://redirect.github.com/Stebalien/tempfile)) |
workspace.dependencies | minor | `3.15.0` -> `3.16.0` |

---

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

---

### Release Notes

<details>
<summary>Stebalien/tempfile (tempfile)</summary>

###
[`v3.16.0`](https://redirect.github.com/Stebalien/tempfile/blob/HEAD/CHANGELOG.md#3160)

[Compare
Source](https://redirect.github.com/Stebalien/tempfile/compare/v3.15.0...v3.16.0)

- Update `getrandom` to `0.3.0` (thanks to
[@&#8203;paolobarbolini](https://redirect.github.com/paolobarbolini)).
- Allow `windows-sys` versions `0.59.x` in addition to `0.59.0` (thanks
[@&#8203;ErichDonGubler](https://redirect.github.com/ErichDonGubler)).
- Improved security documentation (thanks to
[@&#8203;n0toose](https://redirect.github.com/n0toose) for collaborating
with me on this).

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 12:17:44 +05:30
renovate[bot]
464a893f5d Update pre-commit dependencies (#15898)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[astral-sh/ruff-pre-commit](https://redirect.github.com/astral-sh/ruff-pre-commit)
| repository | patch | `v0.9.3` -> `v0.9.4` |
| [crate-ci/typos](https://redirect.github.com/crate-ci/typos) |
repository | patch | `v1.29.4` -> `v1.29.5` |
|
[executablebooks/mdformat](https://redirect.github.com/executablebooks/mdformat)
| repository | patch | `0.7.21` -> `0.7.22` |
|
[python-jsonschema/check-jsonschema](https://redirect.github.com/python-jsonschema/check-jsonschema)
| repository | patch | `0.31.0` -> `0.31.1` |
|
[woodruffw/zizmor-pre-commit](https://redirect.github.com/woodruffw/zizmor-pre-commit)
| repository | minor | `v1.2.2` -> `v1.3.0` |

---

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

Note: The `pre-commit` manager in Renovate is not supported by the
`pre-commit` maintainers or community. Please do not report any problems
there, instead [create a Discussion in the Renovate
repository](https://redirect.github.com/renovatebot/renovate/discussions/new)
if you have any questions.

---

### Release Notes

<details>
<summary>astral-sh/ruff-pre-commit (astral-sh/ruff-pre-commit)</summary>

###
[`v0.9.4`](https://redirect.github.com/astral-sh/ruff-pre-commit/releases/tag/v0.9.4)

[Compare
Source](https://redirect.github.com/astral-sh/ruff-pre-commit/compare/v0.9.3...v0.9.4)

See: https://github.com/astral-sh/ruff/releases/tag/0.9.4

</details>

<details>
<summary>crate-ci/typos (crate-ci/typos)</summary>

###
[`v1.29.5`](https://redirect.github.com/crate-ci/typos/releases/tag/v1.29.5)

[Compare
Source](https://redirect.github.com/crate-ci/typos/compare/v1.29.4...v1.29.5)

#### \[1.29.5] - 2025-01-30

##### Internal

-   Update a dependency

</details>

<details>
<summary>executablebooks/mdformat (executablebooks/mdformat)</summary>

###
[`v0.7.22`](https://redirect.github.com/executablebooks/mdformat/compare/0.7.21...0.7.22)

[Compare
Source](https://redirect.github.com/executablebooks/mdformat/compare/0.7.21...0.7.22)

</details>

<details>
<summary>python-jsonschema/check-jsonschema
(python-jsonschema/check-jsonschema)</summary>

###
[`v0.31.1`](https://redirect.github.com/python-jsonschema/check-jsonschema/blob/HEAD/CHANGELOG.rst#0311)

[Compare
Source](https://redirect.github.com/python-jsonschema/check-jsonschema/compare/0.31.0...0.31.1)

- Update vendored schemas: buildkite, cloudbuild, compose-spec, mergify,
    renovate (2025-01-26)
-   Update the `gitlab` and `renovate` hooks to use
`--regex-variant nonunicode`. Thanks :user:`quentin-ag` and
:user:`Callek`
    for reporting! (:issue:`516`, :issue:`518`)
-   Update the required `ruamel.yaml` version to a range,
    `>=0.18.10,<0.19.0`.

</details>

<details>
<summary>woodruffw/zizmor-pre-commit
(woodruffw/zizmor-pre-commit)</summary>

###
[`v1.3.0`](https://redirect.github.com/woodruffw/zizmor-pre-commit/releases/tag/v1.3.0)

[Compare
Source](https://redirect.github.com/woodruffw/zizmor-pre-commit/compare/v1.2.2...v1.3.0)

See: https://github.com/woodruffw/zizmor/releases/tag/v1.3.0

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 00:32:32 +00:00
renovate[bot]
a53626a8b2 Update dependency ruff to v0.9.4 (#15897)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ruff](https://docs.astral.sh/ruff)
([source](https://redirect.github.com/astral-sh/ruff),
[changelog](https://redirect.github.com/astral-sh/ruff/blob/main/CHANGELOG.md))
| `==0.9.3` -> `==0.9.4` |
[![age](https://developer.mend.io/api/mc/badges/age/pypi/ruff/0.9.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/pypi/ruff/0.9.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/pypi/ruff/0.9.3/0.9.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/pypi/ruff/0.9.3/0.9.4?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>astral-sh/ruff (ruff)</summary>

###
[`v0.9.4`](https://redirect.github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#094)

[Compare
Source](https://redirect.github.com/astral-sh/ruff/compare/0.9.3...0.9.4)

##### Preview features

- \[`airflow`] Extend airflow context parameter check for
`BaseOperator.execute` (`AIR302`)
([#&#8203;15713](https://redirect.github.com/astral-sh/ruff/pull/15713))
- \[`airflow`] Update `AIR302` to check for deprecated context keys
([#&#8203;15144](https://redirect.github.com/astral-sh/ruff/pull/15144))
- \[`flake8-bandit`] Permit suspicious imports within stub files (`S4`)
([#&#8203;15822](https://redirect.github.com/astral-sh/ruff/pull/15822))
- \[`pylint`] Do not trigger `PLR6201` on empty collections
([#&#8203;15732](https://redirect.github.com/astral-sh/ruff/pull/15732))
- \[`refurb`] Do not emit diagnostic when loop variables are used
outside loop body (`FURB122`)
([#&#8203;15757](https://redirect.github.com/astral-sh/ruff/pull/15757))
- \[`ruff`] Add support for more `re` patterns (`RUF055`)
([#&#8203;15764](https://redirect.github.com/astral-sh/ruff/pull/15764))
- \[`ruff`] Check for shadowed `map` before suggesting fix (`RUF058`)
([#&#8203;15790](https://redirect.github.com/astral-sh/ruff/pull/15790))
- \[`ruff`] Do not emit diagnostic when all arguments to `zip()` are
variadic (`RUF058`)
([#&#8203;15744](https://redirect.github.com/astral-sh/ruff/pull/15744))
- \[`ruff`] Parenthesize fix when argument spans multiple lines for
`unnecessary-round` (`RUF057`)
([#&#8203;15703](https://redirect.github.com/astral-sh/ruff/pull/15703))

##### Rule changes

- Preserve quote style in generated code
([#&#8203;15726](https://redirect.github.com/astral-sh/ruff/pull/15726),
[#&#8203;15778](https://redirect.github.com/astral-sh/ruff/pull/15778),
[#&#8203;15794](https://redirect.github.com/astral-sh/ruff/pull/15794))
- \[`flake8-bugbear`] Exempt `NewType` calls where the original type is
immutable (`B008`)
([#&#8203;15765](https://redirect.github.com/astral-sh/ruff/pull/15765))
- \[`pylint`] Honor banned top-level imports by `TID253` in `PLC0415`.
([#&#8203;15628](https://redirect.github.com/astral-sh/ruff/pull/15628))
- \[`pyupgrade`] Ignore `is_typeddict` and `TypedDict` for
`deprecated-import` (`UP035`)
([#&#8203;15800](https://redirect.github.com/astral-sh/ruff/pull/15800))

##### CLI

- Fix formatter warning message for `flake8-quotes` option
([#&#8203;15788](https://redirect.github.com/astral-sh/ruff/pull/15788))
- Implement tab autocomplete for `ruff config`
([#&#8203;15603](https://redirect.github.com/astral-sh/ruff/pull/15603))

##### Bug fixes

- \[`flake8-comprehensions`] Do not emit `unnecessary-map` diagnostic
when lambda has different arity (`C417`)
([#&#8203;15802](https://redirect.github.com/astral-sh/ruff/pull/15802))
- \[`flake8-comprehensions`] Parenthesize `sorted` when needed for
`unnecessary-call-around-sorted` (`C413`)
([#&#8203;15825](https://redirect.github.com/astral-sh/ruff/pull/15825))
- \[`pyupgrade`] Handle end-of-line comments for `quoted-annotation`
(`UP037`)
([#&#8203;15824](https://redirect.github.com/astral-sh/ruff/pull/15824))

##### Documentation

- Add missing config docstrings
([#&#8203;15803](https://redirect.github.com/astral-sh/ruff/pull/15803))
- Add references to `trio.run_process` and `anyio.run_process`
([#&#8203;15761](https://redirect.github.com/astral-sh/ruff/pull/15761))
- Use `uv init --lib` in tutorial
([#&#8203;15718](https://redirect.github.com/astral-sh/ruff/pull/15718))

</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:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNDUuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE0NS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJpbnRlcm5hbCJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-03 00:31:02 +00:00
Alex Waygood
b08ce5fb18 [flake8-pyi] Minor cosmetic changes to PYI019 (#15881) 2025-02-02 19:20:05 +00:00
Alex Waygood
418aa35041 [flake8-pyi] Avoid an unnecessary .unwrap() call in PYI019 autofix (#15880) 2025-02-02 19:04:41 +00:00
Tom Kuson
813a76e9e2 [red-knot] Add version command (#15823)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-02-02 18:56:51 +00:00
InSync
3c09100484 [flake8-pyi] Fix more complex cases (PYI019) (#15821)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-02 18:38:49 +00:00
Micha Reiser
770b7f3439 Vendor benchmark test files (#15878)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-02-02 18:16:07 +00:00
Alex Waygood
d9a1034db0 Add convenience helper methods for AST nodes representing function parameters (#15871) 2025-02-01 17:16:32 +00:00
Alex Waygood
bcdb3f9840 Use Diagnostic::try_set_fix in bad-generator-return-type (#15873) 2025-02-01 15:44:42 +00:00
github-actions[bot]
942d7f395a Sync vendored typeshed stubs (#15864)
Close and reopen this PR to trigger CI

Co-authored-by: typeshedbot <>
2025-02-01 01:01:58 +00:00
Andrew Gallant
b58f2c399e [red-knot] ruff_db: make diagnostic rendering prettier (#15856)
This change does a simple swap of the existing renderer for one that
uses our vendored copy of `annotate-snippets`. We don't change anything
about the diagnostic data model, but this alone already makes
diagnostics look a lot nicer!
2025-01-31 16:37:02 -05:00
Douglas Creager
fab86de3ef [red-knot] Should A ∧ !A always be false? (#15839)
This mimics a simplification we have on the OR side, where we simplify
`A ∨ !A` to true. This requires changes to how we add `while` statements
to the semantic index, since we now need distinct
`VisibilityConstraint`s if we need to model evaluating a `Constraint`
multiple times at different points in the execution of the program.
2025-01-31 14:06:52 -05:00
Alex Waygood
c5c0b724fb [flake8-pyi] Minor simplification for PYI019 (#15855) 2025-01-31 16:54:38 +00:00
Alex Waygood
0d191a13c1 [flake8-pyi] Fix incorrect behaviour of custom-typevar-return-type preview-mode autofix if typing was already imported (PYI019) (#15853) 2025-01-31 16:46:31 +00:00
InSync
b2cb757fa8 [flake8-pyi] Remove type parameter correctly when it is the last (PYI019) (#15854) 2025-01-31 16:22:54 +00:00
Carl Meyer
ce769f6ae2 [red-knot] gather type prevalence statistics (#15834)
Something Alex and I threw together during our 1:1 this morning. Allows
us to collect statistics on the prevalence of various types in a file,
most usefully TODO types or other dynamic types.
2025-01-31 07:10:00 -08:00
Alex Waygood
44ac17b3ba [flake8-pyi] Fix several correctness issues with custom-type-var-return-type (PYI019) (#15851) 2025-01-31 14:19:35 +00:00
Brent Westbrook
f1418be81c [pyupgrade] Reuse replacement logic from UP046 and UP047 (UP040) (#15840)
## Summary

This is a follow-up to #15565, tracked in #15642, to reuse the string
replacement logic from the other PEP 695 rules instead of the
`Generator`, which has the benefit of preserving more comments. However,
comments in some places are still dropped, so I added a check for this
and update the fix safety accordingly. I also added a `## Fix safety`
section to the docs to reflect this and the existing `isinstance`
caveat.

## Test Plan

Existing UP040 tests, plus some new cases.
2025-01-31 08:10:53 -05:00
InSync
59be5f5278 [refurb] Avoid None | None as well as better detection and fix (FURB168) (#15779) 2025-01-31 11:34:57 +00:00
Dhruv Manilawala
4df0796d61 Remove non-existing lint.extendIgnore editor setting (#15844)
This setting doesn't exist in the first place. I must've added it by
mistake thinking that it exists similar to `extendSelect`. One reason to
have auto-generated docs.


988be01fbe/crates/ruff_server/src/session/settings.rs (L124-L133)

Closes: #14665
2025-01-31 06:00:17 +00:00
InSync
172f62d8f4 [refurb] Mark fix as unsafe if there are comments (FURB171) (#15832)
## Summary

Resolves #10063 and follow-up to #15521.

The fix is now marked as unsafe if there are any comments within its
range. Tests are adapted from that of #15521.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-01-30 17:21:07 -06:00
Dylan
071862af5a [flake8-comprehensions] Skip when TypeError present from too many (kw)args for C410,C411, and C418 (#15838)
Both `list` and `dict` expect only a single positional argument. Giving
more positional arguments, or a keyword argument, is a `TypeError` and
neither the lint rule nor its fix make sense in that context.

Closes #15810
2025-01-30 17:10:43 -06:00
Brent Westbrook
fe516e24f5 [pyflakes] Visit forward annotations in TypeAliasType as types (F401) (#15829)
## Summary

Fixes https://github.com/astral-sh/ruff/issues/15812 by visiting the
second argument as a type definition.

## Test Plan

New F401 tests based on the report.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-30 18:06:38 -05:00
Dylan
4f2aea8d50 [flake8-comprehensions] Handle builtins at top of file correctly for unnecessary-dict-comprehension-for-iterable (C420) (#15837)
Builtin bindings are given a range of `0..0`, which causes strange
behavior when range checks are made at the top of the file. In this
case, the logic of the rule demands that the value of the dict
comprehension is not self-referential (i.e. it does not contain
definitions for any of the variables used within it). This logic was
confused by builtins which looked like they were defined "in the
comprehension", if the comprehension appeared at the top of the file.

Closes #15830
2025-01-30 15:49:13 -06:00
Dylan
5c77898693 Downgrade tailwind (#15835)
The new version of tailwindcss [sounds very
exciting](https://tailwindcss.com/blog/tailwindcss-v4), but upgrading
will requite some refactoring. For now, let's revert.
2025-01-30 13:55:07 -06:00
Dylan
854ab03078 Bump version to 0.9.4 (#15831)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-30 11:29:22 -06:00
Leo Gaskin
b0b8b06241 Remove semicolon after TypeScript interface definition (#15827)
## Summary

This PR removes a trailing semicolon after an interface definition in
the custom TypeScript section of `ruff_wasm`. Currently, this semicolon
triggers the error "TS1036: Statements are not allowed in ambient
contexts" when including the file and compiling with e.g `tsc`.

## Test Plan

I made the change, ran `wasm-pack` and copied the generated directory
manually to my `node_modules` folder. I then compiled a file importing
`@astral-sh/ruff-wasm-web` again and confirmed that the compilation
error was gone.
2025-01-30 20:40:16 +05:30
David Peter
451f251a31 [red-knot] Clarify behavior when redeclaring base class attributes (#15826)
# Summary

Clarify the behavior regarding re-declaration of attributes from base
classes following [this
discussion](https://github.com/astral-sh/ruff/pull/15808#discussion_r1934236095)
2025-01-30 14:49:23 +01:00
Dylan
13cf3e65f1 [flake8-comprehensions] Parenthesize sorted when needed for unnecessary-call-around-sorted (C413) (#15825)
If there is any `ParenthesizedWhitespace` (in the sense of LibCST) after
the function name `sorted` and before the arguments, then we must wrap
`sorted` with parentheses after removing the surrounding function.

Closes #15789
2025-01-30 07:10:56 -06:00
Dylan
56f956a238 [pyupgrade] Handle end-of-line comments for quoted-annotation (UP037) (#15824)
This PR uses the tokens of the parsed annotation available in the
`Checker`, instead of re-lexing (using `SimpleTokenizer`) the
annotation. This avoids some limitations of the `SimpleTokenizer`, such
as not being able to handle number and string literals.

Closes #15816 .
2025-01-30 00:03:05 -06:00
Tom Kuson
7a10a40b0d [flake8-bandit] Permit suspicious imports within stub files (S4) (#15822)
## Summary

Permits suspicious imports (the `S4` namespaced diagnostics) from stub
files.

Closes #15207.

## Test Plan

Added tests and ran `cargo nextest run`. The test files are copied from
the `.py` variants.
2025-01-29 23:42:56 -06:00
Alex Waygood
3125332ec1 [red-knot] Format mdtest snippets with the latest version of black (#15819) 2025-01-29 23:05:43 +00:00
Douglas Creager
15d886a502 [red-knot] Consider all definitions after terminal statements unreachable (#15676)
`FlowSnapshot` now tracks a `reachable` bool, which indicates whether we
have encountered a terminal statement on that control flow path. When
merging flow states together, we skip any that have been marked
unreachable. This ensures that bindings that can only be reached through
unreachable paths are not considered visible.

## Test Plan

The new mdtests failed (with incorrect `reveal_type` results, and
spurious `possibly-unresolved-reference` errors) before adding the new
visibility constraints.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-01-29 14:06:57 -05:00
InSync
e1c9d10863 [flake8-comprehensions] Do not emit unnecessary-map diagnostic when lambda has different arity (C417) (#15802) 2025-01-29 18:45:55 +00:00
Brent Westbrook
23c98849fc Preserve quotes in generated f-strings (#15794)
## Summary

This is another follow-up to #15726 and #15778, extending the
quote-preserving behavior to f-strings and deleting the now-unused
`Generator::quote` field.

## Details
I also made one unrelated change to `rules/flynt/helpers.rs` to remove a
`to_string` call for making a `Box<str>` and tweaked some arguments to
some of the `Generator::unparse_f_string` methods to make the code
easier to follow, in my opinion. Happy to revert especially the latter
of these if needed.

Unfortunately this still does not fix the issue in #9660, which appears
to be more of an escaping issue than a quote-preservation issue. After
#15726, the result is now `a = f'# {"".join([])}' if 1 else ""` instead
of `a = f"# {''.join([])}" if 1 else ""` (single quotes on the outside
now), but we still don't have the desired behavior of double quotes
everywhere on Python 3.12+. I added a test for this but split it off
into another branch since it ended up being unaddressed here, but my
`dbg!` statements showed the correct preferred quotes going into
[`UnicodeEscape::with_preferred_quote`](https://github.com/astral-sh/ruff/blob/main/crates/ruff_python_literal/src/escape.rs#L54).

## Test Plan

Existing rule and `Generator` tests.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-29 13:28:22 -05:00
InSync
d151ca85d3 [pyupgrade] Ignore is_typeddict and TypedDict for deprecated-import (UP035) (#15800) 2025-01-29 18:05:46 +00:00
Garrett Reynolds
6c1e19592e [ruff] Add support for more re patterns (RUF055) (#15764)
## Summary
Implements some of #14738, by adding support for 6 new patterns:
```py
re.search("abc", s) is None       # ⇒ "abc" not in s
re.search("abc", s) is not None   # ⇒ "abc" in s

re.match("abc", s) is None       # ⇒ not s.startswith("abc")  
re.match("abc", s) is not None   # ⇒ s.startswith("abc")

re.fullmatch("abc", s) is None       # ⇒ s != "abc"
re.fullmatch("abc", s) is not None   # ⇒ s == "abc"
```


## Test Plan

```shell
cargo nextest run
cargo insta review
```

And ran the fix on my startup's repo.


## Note

One minor limitation here:

```py
if not re.match('abc', s) is None:
    pass
```

will get fixed to this (technically correct, just not nice):
```py
if not not s.startswith('abc'):
    pass
```

This seems fine given that Ruff has this covered: the initial code
should be caught by
[E714](https://docs.astral.sh/ruff/rules/not-is-test/) and the fixed
code should be caught by
[SIM208](https://docs.astral.sh/ruff/rules/double-negation/).
2025-01-29 10:14:44 -05:00
David Peter
0f1035b930 [red-knot] Extend instance-attribute tests (#15808)
## Summary

When we discussed the plan on how to proceed with instance attributes,
we said that we should first extend our research into the behavior of
existing type checkers. The result of this research is summarized in the
newly added / modified tests in this PR. The TODO comments align with
existing behavior of other type checkers. If we deviate from the
behavior, it is described in a comment.
2025-01-29 14:06:32 +01:00
Marek Hanuš
2c3d889dbb Fix formatter warning message for flake8-quotes option (#15788)
## Summary

Fix wrong option name in warning message about docstring quotes
incompatibility.

## Test Plan

Only in CI. No manual testing.
2025-01-29 16:30:28 +05:30
InSync
4bec8ba731 [flake8-bugbear] Exempt NewType calls where the original type is immutable (B008) (#15765)
## Summary

Resolves #12717.

This change incorporates the logic added in #15588.

## Test Plan

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

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-01-29 10:26:17 +00:00
Mike Perlov
6090408f65 Add missing config docstrings (#15803)
## Summary

As promised in #15603 - the **highly** sophisticated change - adding
missing config docstrings that are used in command completions.

## Test Plan

I actually made a local change to emit all empty items and verified
there are none now, before opening the PR.
2025-01-29 09:02:05 +05:30
InSync
72a4d343ff [refurb] Do not emit diagnostic when loop variables are used outside loop body (FURB122) (#15757)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-01-28 19:16:21 +00:00
Brent Westbrook
786099a872 [ruff] Check for shadowed map before suggesting fix (RUF058) (#15790)
## Summary

Fixes #15786 by not suggesting a fix if `map` doesn't have its builtin
binding.

## Test Plan

New test taken from the report in #15786.
2025-01-28 14:15:37 -05:00
David Peter
ca53eefa6f [red-knot] Do not use explicit knot_extensions.Unknown declaration (#15787)
## Summary

Do not use an explict `knot_extensions.Unknown` declaration, as per
[this
comment](https://github.com/astral-sh/ruff/pull/15766#discussion_r1930997592).
Instead, use an undefined name to achieve the same effect.
2025-01-28 17:18:22 +01:00
Brent Westbrook
98d20a8219 Preserve quotes in generated byte strings (#15778)
## Summary

This is a very closely related follow-up to #15726, adding the same
quote-preserving behavior to bytestrings. Only one rule (UP018) was
affected this time, and it was easy to mirror the plain string changes.

## Test Plan

Existing tests
2025-01-28 08:19:40 -05:00
Alex Waygood
9c938442e5 [minor] Simplify some ExprStringLiteral creation logic (#15775) 2025-01-27 18:51:13 +00:00
Brent Westbrook
9bf138c45a Preserve quote style in generated code (#15726)
## Summary

This is a first step toward fixing #7799 by using the quoting style
stored in the `flags` field on `ast::StringLiteral`s to select a quoting
style. This PR does not include support for f-strings or byte strings.

Several rules also needed small updates to pass along existing quoting
styles instead of using `StringLiteralFlags::default()`. The remaining
snapshot changes are intentional and should preserve the quotes from the
input strings.

## Test Plan

Existing tests with some accepted updates, plus a few new RUF055 tests
for raw strings.

---------

Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2025-01-27 13:41:03 -05:00
Dhruv Manilawala
e994970538 Rename internal helper functions (#15771)
Refer:
https://github.com/astral-sh/ruff/pull/15713#discussion_r1930700717
2025-01-27 15:25:45 +00:00
Wei Lee
c161e4fb12 [airflow] Extend airflow context parameter check for BaseOperator.execute (AIR302) (#15713)
## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
* feat
* add is_execute_method_inherits_from_airflow_operator for checking the
removed context key in the execute method
* refactor: rename
    * is_airflow_task as is_airflow_task_function_def
    * in_airflow_task as in_airflow_task_function_def
    * removed_in_3 as airflow_3_removal_expr
    * removed_in_3_function_def as airflow_3_removal_function_def
* test:
    * reorganize test cases

## Test Plan

a test fixture has been updated

---------

Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2025-01-27 20:48:18 +05:30
Mike Perlov
646f1942aa Implement tab autocomplete for ruff config (#15603)
## Summary

Not the most important feature, but hey... was marked as the good first
issue ;-) fixes #4551

Unfortunately, looks like clap only generates proper completions for
zsh, so this would not make any difference for bash/fish.

## Test Plan

- cargo nextest run
- manual test by sourcing completions and then triggering autocomplete:
 
```shell
misha@PandaBook ruff % source <(target/debug/ruff generate-shell-completion zsh)
misha@PandaBook ruff % target/debug/ruff config lin
line-length                                                         -- The line length to use when enforcing long-lines violations
lint                                                                -- Configures how Ruff checks your code.
lint.allowed-confusables                                            -- A list of allowed 'confusable' Unicode characters to ignore
lint.dummy-variable-rgx                                             -- A regular expression used to identify 'dummy' variables, or
lint.exclude                                                        -- A list of file patterns to exclude from linting in addition
lint.explicit-preview-rules                                         -- Whether to require exact codes to select preview rules. Whe
lint.extend-fixable                                                 -- A list of rule codes or prefixes to consider fixable, in ad
lint.extend-ignore                                                  -- A list of rule codes or prefixes to ignore, in addition to
lint.extend-per-file-ignores                                        -- A list of mappings from file pattern to rule codes or prefi
lint.extend-safe-fixes                                              -- A list of rule codes or prefixes for which unsafe fixes sho
lint.extend-select                                                  -- A list of rule codes or prefixes to enable, in addition to
lint.extend-unsafe-fixes                                            -- A list of rule codes or prefixes for which safe fixes shoul
lint.external                                                       -- A list of rule codes or prefixes that are unsupported by Ru
lint.fixable                                                        -- A list of rule codes or prefixes to consider fixable. By de
lint.flake8-annotations                                             -- Print a list of available options
lint.flake8-annotations.allow-star-arg-any                          -- Whether to suppress `ANN401` for dynamically typed `*args`

...
```

- check command help
```shell
❯ target/debug/ruff config -h
List or describe the available configuration options

Usage: ruff config [OPTIONS] [OPTION]

Arguments:
  [OPTION]  Config key to show

Options:
      --output-format <OUTPUT_FORMAT>  Output format [default: text] [possible values: text, json]
  -h, --help                           Print help

Log levels:
  -v, --verbose  Enable verbose logging
  -q, --quiet    Print diagnostics, but nothing else
  -s, --silent   Disable all logging (but still exit with status code "1" upon detecting diagnostics)

Global options:
      --config <CONFIG_OPTION>  Either a path to a TOML configuration file (`pyproject.toml` or `ruff.toml`), or a TOML `<KEY> =
                                <VALUE>` pair (such as you might find in a `ruff.toml` configuration file) overriding a specific
                                configuration option. Overrides of individual settings using this option always take precedence over
                                all configuration files, including configuration files that were also specified using `--config`
      --isolated                Ignore all configuration files
```

- running original command
```shell
❯ target/debug/ruff config
cache-dir
extend
output-format
fix
unsafe-fixes
fix-only
show-fixes
required-version
preview
exclude
extend-exclude
extend-include
force-exclude
include
respect-gitignore
builtins
namespace-packages
target-version
src
line-length
indent-width
lint
format
analyze
```
2025-01-27 20:39:04 +05:30
Alex Waygood
0a2139f496 Run cargo update (#15769) 2025-01-27 14:06:32 +00:00
David Peter
2ef94e5f3e [red-knot] Document public symbol type inferece (#15766)
## Summary

Adds a slightly more comprehensive documentation of our behavior
regarding type inference for public uses of symbols. In particular:

- What public type do we infer for `x: int = any()`?
- What public type do we infer for `x: Unknown = 1`?
2025-01-27 10:52:13 +01:00
renovate[bot]
3a08570a68 Update dawidd6/action-download-artifact action to v8 (#15760) 2025-01-26 22:26:28 -05:00
renovate[bot]
2da8c3776b Update NPM Development dependencies (#15758) 2025-01-26 22:26:15 -05:00
renovate[bot]
fac0360310 Update pre-commit dependencies (#15756) 2025-01-26 22:26:01 -05:00
renovate[bot]
0ff71bc3f3 Update dependency ruff to v0.9.3 (#15755) 2025-01-26 22:25:55 -05:00
renovate[bot]
43fbbdc71b Update dependency mdformat-mkdocs to v4.1.2 (#15754) 2025-01-26 22:25:49 -05:00
renovate[bot]
a8fb6f0f87 Update Rust crate uuid to v1.12.1 (#15753) 2025-01-26 22:25:42 -05:00
renovate[bot]
23baf3a2c8 Update Rust crate unicode-ident to v1.0.15 (#15752) 2025-01-26 22:25:35 -05:00
Marcus Näslund
d0709093fe Fix docstring in ruff_annotate_snippets (#15748)
## Summary

Found a comment that looks to be intended as docstring but accidentally
is just a normal comment.

Didn't create an issue as the readme said it's not neccessary for
trivial changes.

## Test Plan

<!-- How was it tested? -->
Can be tested by regenerating the docs.

Co-authored-by: Marcus Näslund <vidaochmarcus@gmail.com>
2025-01-26 22:25:29 -05:00
renovate[bot]
101a6ba805 Update Rust crate insta to v1.42.1 (#15751) 2025-01-26 22:25:15 -05:00
renovate[bot]
5bb87f8eb6 Update Rust crate clap to v4.5.27 (#15750) 2025-01-26 22:25:06 -05:00
Charlie Marsh
37925ac442 Add references to trio.run_process and anyio.run_process (#15761)
## Summary

Closes https://github.com/astral-sh/ruff/issues/14806.
2025-01-27 01:52:03 +00:00
InSync
cb3361e682 [ruff] Do not emit diagnostic when all arguments to zip() are variadic (RUF058) (#15744) 2025-01-25 18:42:28 +00:00
Alex Waygood
c824140fa8 [red-knot] Ensure differently ordered unions are considered equivalent when they appear inside tuples inside top-level intersections (#15743) 2025-01-25 18:19:28 +00:00
Alex Waygood
f85ea1bf46 [red-knot] Ensure differently ordered unions and intersections are understood as equivalent even inside arbitrarily nested tuples (#15740)
## Summary

On `main`, red-knot:
- Considers `P | Q` equivalent to `Q | P`
- Considered `tuple[P | Q]` equivalent to `tuple[Q | P]`
- Considers `tuple[P | tuple[P | Q]]` equivalent to `tuple[tuple[Q | P]
| P]`
- ‼️ Does _not_ consider `tuple[tuple[P | Q]]` equivalent to
`tuple[tuple[Q | P]]`

The key difference for the last one of these is that the union appears
inside a tuple that is directly nested inside another tuple.

This PR fixes this so that differently ordered unions are considered
equivalent even when they appear inside arbitrarily nested tuple types.

## Test Plan

- Added mdtests that fails on `main`
- Checked that all property tests continue to pass with this PR
2025-01-25 16:39:07 +00:00
Alex Waygood
a77a32b7d4 [red-knot] Promote the all_type_pairs_are_assignable_to_their_union property test to stable (#15739) 2025-01-25 16:26:37 +00:00
Jelle Zijlstra
d8c2d20325 [pylint] Do not trigger PLR6201 on empty collections (#15732)
Fixes #15729.
2025-01-24 20:42:49 -06:00
Zanie Blue
fcd0f349f9 Improve the file watching failure error message (#15728)
I really misunderstood this in
https://github.com/astral-sh/ruff/pull/15664#issuecomment-2613079710
2025-01-24 15:28:30 -06:00
Douglas Creager
5a9d71a5f1 Speed symbol state merging back up (#15731)
This is a follow-up to #15702 that hopefully claws back the 1%
performance regression. Assuming it works, the trick is to iterate over
the constraints vectors via mut reference (aka a single pointer), so
that we're not copying `BitSet`s into and out of the zip tuples as we
iterate. We use `std::mem::take` as a poor-man's move constructor only
at the very end, when we're ready to emplace it into the result. (C++
idioms intended! 😄)

With local testing via hyperfine, I'm seeing this be 1-3% faster than
`main` most of the time — though a small number of runs (1 in 10,
maybe?) are a wash or have `main` faster. Codspeed reports a 2%
gain.
2025-01-24 16:07:31 -05:00
Micha Reiser
9353482a5a Add check command (#15692) 2025-01-24 17:00:30 +01:00
Douglas Creager
716b246cf3 [red-knot] Use itertools to clean up SymbolState::merge (#15702)
[`merge_join_by`](https://docs.rs/itertools/latest/itertools/trait.Itertools.html#method.merge_join_by)
handles the "merge two sorted iterators" bit, and `zip` handles
iterating through the bindings/definitions along with their associated
constraints.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2025-01-24 10:21:29 -05:00
Micha Reiser
4e3982cf95 [red-knot] Add --ignore, --warn, and --error CLI arguments (#15689) 2025-01-24 16:20:15 +01:00
Charlie Marsh
ab2e1905c4 Use uv init --lib in tutorial (#15718)
## Summary

Closes https://github.com/astral-sh/uv/issues/10933.
2025-01-24 14:53:20 +00:00
David Peter
1feb3cf41a [red-knot] Use Unknown | T_inferred for undeclared public symbols (#15674)
## Summary

Use `Unknown | T_inferred` as the type for *undeclared* public symbols.

## Test Plan

- Updated existing tests
- New test for external `__slots__` modifications.
- New tests for external modifications of public symbols.
2025-01-24 12:47:48 +01:00
Dylan
7778d1d646 [ruff] Parenthesize fix when argument spans multiple lines for unnecessary-round (RUF057) (#15703) 2025-01-24 04:34:56 -06:00
David Peter
fb58a9b610 [red-knot] Rename TestDbBuilder::typeshed to .custom_typeshed (#15712)
## Summary

Correcting a small oversight by me
(https://github.com/astral-sh/ruff/pull/15683#discussion_r1926830914).
2025-01-24 10:25:23 +00:00
Mike Perlov
17a8a55f08 Honor banned top level imports by TID253 in PLC0415. (#15628)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-01-24 11:07:21 +01:00
Dhruv Manilawala
99d8ec6769 Apply AIR302-context check only in @task function (#15711)
This PR updates `AIR302` to only apply the context keys check in `@task`
decorated function.

Ref: https://github.com/astral-sh/ruff/pull/15144
2025-01-24 07:30:35 +00:00
Ankit Chaurasia
34cc3cab98 [airflow] Update AIR302 to check for deprecated context keys (#15144)
**Summary**

Airflow 3.0 removes a set of deprecated context variables that were
phased out in 2.x. This PR introduces lint rules to detect usage of
these removed variables in various patterns, helping identify
incompatibilities. The removed context variables include:

```
conf
execution_date
next_ds
next_ds_nodash
next_execution_date
prev_ds
prev_ds_nodash
prev_execution_date
prev_execution_date_success
tomorrow_ds
yesterday_ds
yesterday_ds_nodash
```

**Detected Patterns and Examples**

The linter now flags the use of removed context variables in the
following scenarios:

1. **Direct Subscript Access**  
   ```python
   execution_date = context["execution_date"]  # Flagged
   ```
   
2. **`.get("key")` Method Calls**  
   ```python
   print(context.get("execution_date"))  # Flagged
   ```
   
3. **Variables Assigned from `get_current_context()`**  
If a variable is assigned from `get_current_context()` and then used to
access a removed key:
   ```python
   c = get_current_context()
   print(c.get("execution_date"))  # Flagged
   ```
   
4. **Function Parameters in `@task`-Decorated Functions**  
Parameters named after removed context variables in functions decorated
with `@task` are flagged:
   ```python
   from airflow.decorators import task
   
   @task
def my_task(execution_date, **kwargs): # Parameter 'execution_date'
flagged
       pass
   ```
   
5. **Removed Keys in Task Decorator `kwargs` and Other Scenarios**  
Other similar patterns where removed context variables appear (e.g., as
part of `kwargs` in a `@task` function) are also detected.
```
from airflow.decorators import task

@task
def process_with_execution_date(**context):
    execution_date = lambda: context["execution_date"]  # flagged
    print(execution_date)

@task(kwargs={"execution_date": "2021-01-01"})   # flagged
def task_with_kwargs(**context):  
    pass
```

**Test Plan**

Test fixtures covering various patterns of deprecated context usage are
included in this PR. For example:

```python
from airflow.decorators import task, dag, get_current_context
from airflow.models import DAG
from airflow.operators.dummy import DummyOperator
import pendulum
from datetime import datetime

@task
def access_invalid_key_task(**context):
    print(context.get("conf"))  # 'conf' flagged

@task
def print_config(**context):
    execution_date = context["execution_date"]  # Flagged
    prev_ds = context["prev_ds"]                # Flagged

@task
def from_current_context():
    context = get_current_context()
    print(context["execution_date"])            # Flagged

# Usage outside of a task decorated function
c = get_current_context()
print(c.get("execution_date"))                 # Flagged

@task
def some_task(execution_date, **kwargs):
    print("execution date", execution_date)     # Parameter flagged

@dag(
    start_date=pendulum.datetime(2021, 1, 1, tz="UTC")
)
def my_dag():
    task1 = DummyOperator(
        task_id="task1",
        params={
            "execution_date": "{{ execution_date }}",  # Flagged in template context
        },
    )

    access_invalid_key_task()
    print_config()
    from_current_context()
    
dag = my_dag()

class CustomOperator(BaseOperator):
    def execute(self, context):
        execution_date = context.get("execution_date")                      # Flagged
        next_ds = context.get("next_ds")                                               # Flagged
        next_execution_date = context["next_execution_date"]          # Flagged
```

Ruff will emit `AIR302` diagnostics for each deprecated usage, with
suggestions when applicable, aiding in code migration to Airflow 3.0.

related: https://github.com/apache/airflow/issues/44409,
https://github.com/apache/airflow/issues/41641

---------

Co-authored-by: Wei Lee <weilee.rx@gmail.com>
2025-01-24 11:25:05 +05:30
Dhruv Manilawala
9384ba4b91 Remove test rules from JSON schema (#15627)
Closes: #15707
2025-01-24 10:17:59 +05:30
Dylan
2b3550c85f Add two missing commits to changelog (#15701)
Some commits appeared between the creation and merging of the "bump to
v0.9.3" branch.

Also made the same changes to the Releases on githhub.
2025-01-23 15:32:00 -06:00
Dylan
90589372da Fix grep for version number in docker build (#15699)
Grep now only returns _first_ result and "version" has to be at start of
line.
2025-01-23 13:14:58 -06:00
Dylan
b5ffb404de Bump version to 0.9.3 (#15698) 2025-01-23 12:43:56 -06:00
Brent Westbrook
cffd1866ce Preserve raw string prefix and escapes (#15694)
## Summary

Fixes #9663 and also improves the fixes for
[RUF055](https://docs.astral.sh/ruff/rules/unnecessary-regular-expression/)
since regular expressions are often written as raw strings.

This doesn't include raw f-strings.

## Test Plan

Existing snapshots for RUF055 and PT009, plus a new `Generator` test and
a regression test for the reported `PIE810` issue.
2025-01-23 12:12:10 -05:00
InSync
569060f46c [flake8-pytest-style] Rewrite references to .exception (PT027) (#15680) 2025-01-23 17:50:40 +01:00
David Peter
15394a8028 [red-knot] MDTests: Do not depend on precise public-symbol type inference (#15691)
## Summary

Another small PR to focus #15674 solely on the relevant changes. This
makes our Markdown tests less dependent on precise types of public
symbols, without actually changing anything semantically in these tests.

Best reviewed using ignore-whitespace-mode.

## Test Plan

Tested these changes on `main` and on the branch from #15674.
2025-01-23 13:51:33 +00:00
David Peter
fc2ebea736 [red-knot] Make infer.rs unit tests independent of public symbol inference (#15690)
## Summary

Make the remaining `infer.rs` unit tests independent from public symbol
type inference decisions (see upcoming change in #15674).

## Test Plan

- Made sure that the unit tests actually fail if one of the
  `assert_type` assertions is changed.
2025-01-23 14:30:18 +01:00
Micha Reiser
43160b4c3e Tidy knot CLI tests (#15685) 2025-01-23 14:06:07 +01:00
David Peter
0173738eef [red-knot] Port comprehension tests to Markdown (#15688)
## Summary

Port comprehension tests from Rust to Markdown

I don' think the remaining tests in `infer.rs` should be ported to
Markdown, maybe except for the incremental-checking tests when (if ever)
we have support for that in the MD tests.


closes #13696
2025-01-23 12:49:30 +00:00
Micha Reiser
05ea77b1d4 Create Unknown rule diagnostics with a source range (#15648) 2025-01-23 12:50:43 +01:00
David Peter
1e790d3885 [red-knot] Port 'deferred annotations' unit tests to Markdown (#15686)
## Summary

- Port "deferred annotations" unit tests to Markdown
- Port `implicit_global_in_function` unit test to Markdown
- Removed `resolve_method` and `local_inference` unit tests. These seem
  like relics from a time where type inference was in it's early stages.
  There is no way that these tests would fail today without lots of other
  things going wrong as well.

part of #13696
based on #15683 

## Test Plan

New MD tests for existing Rust unit tests.
2025-01-23 11:45:05 +00:00
David Peter
7855f03735 [red-knot] Support custom typeshed Markdown tests (#15683)
## Summary

- Add feature to specify a custom typeshed from within Markdown-based
  tests
- Port "builtins" unit tests from `infer.rs` to Markdown tests, part of
  #13696

## Test Plan

- Tests for the custom typeshed feature
- New Markdown tests for deleted Rust unit tests
2025-01-23 12:36:38 +01:00
Alex Waygood
84301a7300 Don't run the linter ecosystem check on PRs that only touch red-knot crates (#15687) 2025-01-23 10:47:12 +00:00
Micha Reiser
7b17c9c445 Add rules table to configuration (#15645) 2025-01-23 10:56:58 +01:00
Micha Reiser
23c222368e [red-knot] Make Diagnostic::file optional (#15640) 2025-01-23 10:43:14 +01:00
David Peter
1ecd97855e [red-knot] Add test for nested attribute access (#15684)
## Summary

Add a new test for attribute accesses in case of nested modules /
classes. Resolves this comment:

https://github.com/astral-sh/ruff/pull/15613#discussion_r1925637561

## Test Plan

New MD test.
2025-01-23 10:26:34 +01:00
Micha Reiser
39e2df7ada [red-knot] Anchor relative paths in configurations (#15634) 2025-01-23 10:14:01 +01:00
Brent Westbrook
ce8110332c [pyupgrade] Handle multiple base classes for PEP 695 generics (UP046) (#15659)
## Summary

Addresses the second follow up to #15565 in #15642. This was easier than
expected by using this cool destructuring syntax I hadn't used before,
and by assuming
[PYI059](https://docs.astral.sh/ruff/rules/generic-not-last-base-class/)
(`generic-not-last-base-class`).

## Test Plan

Using an existing test, plus two new tests combining multiple base
classes and multiple generics. It looks like I deleted a relevant test,
which I did, but I meant to rename this in #15565. It looks like instead
I copied it and renamed the copy.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-22 20:19:13 -05:00
Alex Waygood
555b3a6a2c [pyflakes] Treat arguments passed to the default= parameter of TypeVar as type expressions (F821) (#15679) 2025-01-22 23:04:20 +00:00
Alex Waygood
05abd642a8 Upgrade zizmor to the latest version in CI (#15649) 2025-01-22 17:00:10 +00:00
Brent Westbrook
bb6fb4686d [pyupgrade] Add rules to use PEP 695 generics in classes and functions (UP046, UP047) (#15565)
## Summary

This PR extends our [PEP 695](https://peps.python.org/pep-0695) handling
from the type aliases handled by `UP040` to generic function and class
parameters, as suggested in the latter two examples from #4617:

```python
# Input
T = TypeVar("T", bound=float)
class A(Generic[T]):
    ...

def f(t: T):
    ...

# Output
class A[T: float]:
    ...

def f[T: float](t: T):
    ...
```

I first implemented this as part of `UP040`, but based on a brief
discussion during a very helpful pairing session with @AlexWaygood, I
opted to split them into rules separate from `UP040` and then also
separate from each other. From a quick look, and based on [this
issue](https://github.com/asottile/pyupgrade/issues/836), I'm pretty
sure neither of these rules is currently in pyupgrade, so I just took
the next available codes, `UP046` and `UP047`.

The last main TODO, noted in the rule file and in the fixture, is to
handle generic method parameters not included in the class itself, `S`
in this case:

```python
T = TypeVar("T")
S = TypeVar("S")

class Foo(Generic[T]):
    def bar(self, x: T, y: S) -> S: ...
```

but Alex mentioned that that might be okay to leave for a follow-up PR.

I also left a TODO about handling multiple subclasses instead of bailing
out when more than one is present. I'm not sure how common that would
be, but I can still handle it here, or follow up on that too.

I think this is unrelated to the PR, but when I ran `cargo dev
generate-all`, it removed the rule code `PLW0101` from
`ruff.schema.json`. It seemed unrelated, so I left that out, but I
wanted to mention it just in case.

## Test Plan

New test fixture, `cargo nextest run`

Closes #4617, closes #12542

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-22 11:35:21 -05:00
Alex Waygood
b4877f1661 [red-knot] Ensure a gradual type can always be assigned to itself (#15675) 2025-01-22 16:01:13 +00:00
David Peter
3235cd8019 [red-knot] Fix possible TOCTOU mistake in mdtest runner (#15673)
## Summary

Somehow, I managed to crash the `mdtest` runner today. I struggled to
reproduce this again to see if it's actually fixed (even with an
artificial `sleep` between the two `cargo test` invocations), but the
original backtrace clearly showed that this is where the problem
originated from. And it seems like a clear TOCTOU problem.
2025-01-22 15:24:25 +00:00
David Peter
13e7afca42 [red-knot] Improved error message for attribute-assignments (#15668)
## Summary

Slightly improved error message for attribute assignments.
2025-01-22 11:04:38 +00:00
David Peter
f349dab4fc [red-knot] Invalid assignments to attributes (#15613)
## Summary

Raise "invalid-assignment" diagnostics for incorrect assignments to
attributes, for example:

```py
class C:
    var: str = "a"

C.var = 1  # error: "Object of type `Literal[1]` is not assignable to `str`"
```

closes #15456 

## Test Plan

- Updated test assertions
- New test for assignments to module-attributes
2025-01-22 10:42:47 +01:00
Dhruv Manilawala
df713bc507 Allow disabling (most of) CI with no-test label (#14622)
Ref: https://github.com/astral-sh/uv/pull/9456
2025-01-22 13:59:14 +05:30
Dhruv Manilawala
043ff61a0b Consider unsafe-fixes settings for code actions (#15666)
## Summary

Closes: #13960 

## Test Plan

Using the example from
https://github.com/astral-sh/ruff-vscode/issues/672:


https://github.com/user-attachments/assets/7bdb01ef-8752-4cb7-9b5d-8a0d131984da
2025-01-22 13:44:13 +05:30
David Peter
792f9e357e [red-knot] Rename *_ty functions (#15617)
## Summary

General rules:

* Change the `_ty` suffix of all functions to `_type`.
* `_type_and_qualifiers` suffixes seem too long, so we ignore the
existence of qualifiers and still speak of "types"
* Functions only have a `_type` suffix if they return either `Type`,
`Option<Type>`, or `TypeAndQualifiers`

Free functions:

* `binding_ty` => `binding_type`
* `declaration_ty` => `declaration_type`
* `definition_expression_ty` => `definition_expression_type`

Methods:

* `CallDunderResult::return_ty` => `return_type`
* `NotCallableError::return_ty` => `return_type`
* `NotCallableError::called_ty` => `called_type`
* `TypeAndQualifiers::inner_ty` => `inner_type`
* `TypeAliasType::value_ty` => `value_type`
* `TypeInference::expression_ty` => `expression_type`
* `TypeInference::try_expression_ty` => `try_expression_type`
* `TypeInference::binding_ty` => `binding_type`
* `TypeInference::declaration_ty` => `declaration_type` 
* `TypeInferenceBuilder::expression_ty` => `expression_type`
* `TypeInferenceBuilder::file_expression_ty` => `file_expression_type`
* `TypeInferenceBuilder::module_ty_from_name` => `module_type_from_name`
* `ClassBase::try_from_ty` => `try_from_type`
* `Parameter::annotated_ty` => `annotated_type`
* `Parameter::default_ty` => `default_type`
* `CallOutcome::return_ty` => `return_type`
* `CallOutcome::return_ty_result` => `return_type_result`
* `CallBinding::from_return_ty` => `from_return_type`
* `CallBinding::set_return_ty` => `set_return_type`
* `CallBinding::return_ty` => `return_type`
* `CallBinding::parameter_tys` => `parameter_types`
* `CallBinding::one_parameter_ty` => `one_parameter_type`
* `CallBinding::two_parameter_tys` => `two_parameter_types`
* `Unpacker::tuple_ty_elements` => `tuple_type_elements`
* `StringPartsCollector::ty` => `string_type`

Traits

* `HasTy` => `HasType`
* `HasTy::ty` => `inferred_type`

Test functions:

* `assert_public_ty` => `assert_public_type`
* `assert_scope_ty` => `assert_scope_type`

closes #15569

## Test Plan

—
2025-01-22 09:06:56 +01:00
InSync
6fe404a40f Bring back issue template (#15651) 2025-01-22 08:48:34 +01:00
renovate[bot]
770b844fa5 Update dependency vite to v6.0.9 (#15656)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-22 08:29:02 +01:00
Zanie Blue
7841cddb34 Cache the Rust toolchain in CI (#15660)
We're spending a full 1.5m installing the Rust toolchain on Windows,
e.g.,
https://github.com/astral-sh/ruff/actions/runs/12893749773/job/35950838258

In contrast, in uv this is instant (e.g.
https://github.com/astral-sh/uv/actions/runs/12897572530/job/35962989190)
because we are caching the toolchain.

This shifts the rust-cache action earlier in all the CI jobs.
2025-01-22 01:10:03 -06:00
Zanie Blue
d4efef2382 Add slow-test reporting to nextest in CI (#15662)
This is helpful for spotting tests that are running slow. In uv, we use
a 10s threshold. Here, it looks like we could use something smaller.

e.g.

<img width="964" alt="Screenshot 2025-01-21 at 6 08 00 PM"
src="https://github.com/user-attachments/assets/b32bbc61-9815-4a43-938d-17cd0cf8b0de"
/>
2025-01-22 01:09:47 -06:00
Zanie Blue
e220c74163 Set NEXTEST_PROFILE=ci on Windows (#15663)
This is set in the other jobs, perhaps an oversight here
2025-01-22 01:09:36 -06:00
InSync
f54b82147e [flake8-bandit] Add missing single-line/dotall regex flag (S608) (#15654)
## Summary

Resolves #15653.

## Test Plan

`cargo nextest run` and `cargo insta test`.
2025-01-22 10:20:22 +05:30
Wei Lee
1e053531b6 [airflow] Argument fail_stop in DAG has been renamed as fail_fast (AIR302) (#15633)
## Summary

argument `fail_stop` in DAG has been renamed as `fail_fast` (AIR302)

## Test Plan

a test fixture has been updated
2025-01-22 09:18:57 +05:30
4212 changed files with 267061 additions and 87521 deletions

View File

@@ -8,3 +8,7 @@ benchmark = "bench -p ruff_benchmark --bench linter --bench formatter --"
# See: https://github.com/astral-sh/ruff/issues/11503
[target.'cfg(all(target_env="msvc", target_os = "windows"))']
rustflags = ["-C", "target-feature=+crt-static"]
[target.'wasm32-unknown-unknown']
# See https://docs.rs/getrandom/latest/getrandom/#webassembly-support
rustflags = ["--cfg", 'getrandom_backend="wasm_js"']

View File

@@ -6,3 +6,10 @@ failure-output = "immediate-final"
fail-fast = false
status-level = "skip"
# Mark tests that take longer than 1s as slow.
# Terminate after 60s as a stop-gap measure to terminate on deadlock.
slow-timeout = { period = "1s", terminate-after = 60 }
# Show slow jobs in the final summary
final-status-level = "slow"

7
.gitattributes vendored
View File

@@ -12,9 +12,16 @@ crates/ruff_python_parser/resources/invalid/re_lexing/line_continuation_windows_
crates/ruff_python_parser/resources/invalid/re_lex_logical_token_windows_eol.py text eol=crlf
crates/ruff_python_parser/resources/invalid/re_lex_logical_token_mac_eol.py text eol=cr
crates/ruff_linter/resources/test/fixtures/ruff/RUF046_CR.py text eol=cr
crates/ruff_linter/resources/test/fixtures/ruff/RUF046_LF.py text eol=lf
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_CR.py text eol=cr
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_LF.py text eol=lf
crates/ruff_python_parser/resources/inline linguist-generated=true
ruff.schema.json -diff linguist-generated=true text=auto eol=lf
ty.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

11
.github/CODEOWNERS vendored
View File

@@ -14,10 +14,11 @@
# flake8-pyi
/crates/ruff_linter/src/rules/flake8_pyi/ @AlexWaygood
# Script for fuzzing the parser/red-knot etc.
# Script for fuzzing the parser/ty etc.
/python/py-fuzzer/ @AlexWaygood
# red-knot
/crates/red_knot* @carljm @MichaReiser @AlexWaygood @sharkdp
/crates/ruff_db/ @carljm @MichaReiser @AlexWaygood @sharkdp
/scripts/knot_benchmark/ @carljm @MichaReiser @AlexWaygood @sharkdp
# ty
/crates/ty* @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
/crates/ruff_db/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
/scripts/ty_benchmark/ @carljm @MichaReiser @AlexWaygood @sharkdp @dcreager
/crates/ty_python_semantic @carljm @AlexWaygood @sharkdp @dcreager

View File

@@ -0,0 +1,31 @@
name: Bug report
description: Report an error or unexpected behavior
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to report an issue! We're glad to have you involved with Ruff.
**Before reporting, please make sure to search through [existing issues](https://github.com/astral-sh/ruff/issues?q=is:issue+is:open+label:bug) (including [closed](https://github.com/astral-sh/ruff/issues?q=is:issue%20state:closed%20label:bug)).**
- type: textarea
attributes:
label: Summary
description: |
A clear and concise description of the bug, including a minimal reproducible example.
Be sure to include the command you invoked (e.g., `ruff check /path/to/file.py --fix`), ideally including the `--isolated` flag and
the current Ruff settings (e.g., relevant sections from your `pyproject.toml`).
If possible, try to include the [playground](https://play.ruff.rs) link that reproduces this issue.
validations:
required: true
- type: input
attributes:
label: Version
description: What version of ruff are you using? (see `ruff version`)
placeholder: e.g., ruff 0.9.3 (90589372d 2025-01-23)
validations:
required: false

View File

@@ -0,0 +1,10 @@
name: Rule request
description: Anything related to lint rules (proposing new rules, changes to existing rules, auto-fixes, etc.)
body:
- type: textarea
attributes:
label: Summary
description: |
A clear and concise description of the relevant request. If applicable, please describe the current behavior as well.
validations:
required: true

18
.github/ISSUE_TEMPLATE/3_question.yaml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: Question
description: Ask a question about Ruff
labels: ["question"]
body:
- type: textarea
attributes:
label: Question
description: Describe your question in detail.
validations:
required: true
- type: input
attributes:
label: Version
description: What version of ruff are you using? (see `ruff version`)
placeholder: e.g., ruff 0.9.3 (90589372d 2025-01-23)
validations:
required: false

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
blank_issues_enabled: true
contact_links:
- name: Report an issue with ty
url: https://github.com/astral-sh/ty/issues/new/choose
about: Please report issues for our type checker ty in the ty repository.
- name: Documentation
url: https://docs.astral.sh/ruff
about: Please consult the documentation before creating an issue.
- name: Community
url: https://discord.com/invite/astral-sh
about: Join our Discord community to ask questions and collaborate.

View File

@@ -1,8 +1,9 @@
<!--
Thank you for contributing to Ruff! To help us out with reviewing, please consider the following:
Thank you for contributing to Ruff/ty! 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 a descriptive title? (Please prefix with `[ty]` for ty pull
requests.)
- Does this pull request include references to any relevant issues?
-->

View File

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

8
.github/mypy-primer-ty.toml vendored Normal file
View File

@@ -0,0 +1,8 @@
#:schema ../ty.schema.json
# Configuration overrides for the mypy primer run
# Enable off-by-default rules.
[rules]
possibly-unresolved-reference = "warn"
unused-ignore-comment = "warn"
division-by-zero = "warn"

View File

@@ -40,6 +40,17 @@
enabled: true,
},
packageRules: [
// Pin GitHub Actions to immutable SHAs.
{
matchDepTypes: ["action"],
pinDigests: true,
},
// Annotate GitHub Actions SHAs with a SemVer version.
{
extends: ["helpers:pinGitHubActionDigests"],
extractVersion: "^(?<version>v?\\d+\\.\\d+\\.\\d+)$",
versioning: "regex:^v?(?<major>\\d+)(\\.(?<minor>\\d+)\\.(?<patch>\\d+))?$",
},
{
// Group upload/download artifact updates, the versions are dependent
groupName: "Artifact GitHub Actions dependencies",
@@ -95,14 +106,7 @@
matchManagers: ["cargo"],
matchPackageNames: ["strum"],
description: "Weekly update of strum dependencies",
},
{
groupName: "ESLint",
matchManagers: ["npm"],
matchPackageNames: ["eslint"],
allowedVersions: "<9",
description: "Constraint ESLint to version 8 until TypeScript-eslint supports ESLint 9", // https://github.com/typescript-eslint/typescript-eslint/issues/8211
},
}
],
vulnerabilityAlerts: {
commitMessageSuffix: "",

View File

@@ -23,10 +23,12 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
env:
PACKAGE_NAME: ruff
MODULE_NAME: ruff
PYTHON_VERSION: "3.11"
PYTHON_VERSION: "3.13"
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
@@ -37,17 +39,17 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build sdist"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
command: sdist
args: --out dist
@@ -57,7 +59,7 @@ jobs:
"${MODULE_NAME}" --help
python -m "${MODULE_NAME}" --help
- name: "Upload sdist"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: wheels-sdist
path: dist
@@ -66,23 +68,23 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels - x86_64"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
target: x86_64
args: --release --locked --out dist
- name: "Upload wheels"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: wheels-macos-x86_64
path: dist
@@ -97,7 +99,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: artifacts-macos-x86_64
path: |
@@ -108,18 +110,18 @@ jobs:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-build') }}
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: arm64
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels - aarch64"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
target: aarch64
args: --release --locked --out dist
@@ -129,7 +131,7 @@ jobs:
ruff --help
python -m ruff --help
- name: "Upload wheels"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: wheels-aarch64-apple-darwin
path: dist
@@ -144,7 +146,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: artifacts-aarch64-apple-darwin
path: |
@@ -164,18 +166,18 @@ jobs:
- target: aarch64-pc-windows-msvc
arch: x64
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: ${{ matrix.platform.arch }}
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
target: ${{ matrix.platform.target }}
args: --release --locked --out dist
@@ -190,7 +192,7 @@ jobs:
"${MODULE_NAME}" --help
python -m "${MODULE_NAME}" --help
- name: "Upload wheels"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: wheels-${{ matrix.platform.target }}
path: dist
@@ -201,7 +203,7 @@ jobs:
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: artifacts-${{ matrix.platform.target }}
path: |
@@ -217,18 +219,18 @@ jobs:
- x86_64-unknown-linux-gnu
- i686-unknown-linux-gnu
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
target: ${{ matrix.target }}
manylinux: auto
@@ -240,7 +242,7 @@ jobs:
"${MODULE_NAME}" --help
python -m "${MODULE_NAME}" --help
- name: "Upload wheels"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: wheels-${{ matrix.target }}
path: dist
@@ -258,7 +260,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: artifacts-${{ matrix.target }}
path: |
@@ -292,24 +294,24 @@ jobs:
arch: arm
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
target: ${{ matrix.platform.target }}
manylinux: auto
docker-options: ${{ matrix.platform.maturin_docker_options }}
args: --release --locked --out dist
- uses: uraimo/run-on-arch-action@v2
if: matrix.platform.arch != 'ppc64'
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1
if: ${{ matrix.platform.arch != 'ppc64' && matrix.platform.arch != 'ppc64le'}}
name: Test wheel
with:
arch: ${{ matrix.platform.arch == 'arm' && 'armv6' || matrix.platform.arch }}
@@ -323,7 +325,7 @@ jobs:
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
ruff --help
- name: "Upload wheels"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: wheels-${{ matrix.platform.target }}
path: dist
@@ -341,7 +343,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: artifacts-${{ matrix.platform.target }}
path: |
@@ -357,25 +359,25 @@ jobs:
- x86_64-unknown-linux-musl
- i686-unknown-linux-musl
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
target: ${{ matrix.target }}
manylinux: musllinux_1_2
args: --release --locked --out dist
- name: "Test wheel"
if: matrix.target == 'x86_64-unknown-linux-musl'
uses: addnab/docker-run-action@v3
uses: addnab/docker-run-action@4f65fabd2431ebc8d299f8e5a018d79a769ae185 # v3
with:
image: alpine:latest
options: -v ${{ github.workspace }}:/io -w /io
@@ -385,7 +387,7 @@ jobs:
.venv/bin/pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
.venv/bin/${{ env.MODULE_NAME }} --help
- name: "Upload wheels"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: wheels-${{ matrix.target }}
path: dist
@@ -403,7 +405,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: artifacts-${{ matrix.target }}
path: |
@@ -423,23 +425,23 @@ jobs:
arch: armv7
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
target: ${{ matrix.platform.target }}
manylinux: musllinux_1_2
args: --release --locked --out dist
docker-options: ${{ matrix.platform.maturin_docker_options }}
- uses: uraimo/run-on-arch-action@v2
- uses: uraimo/run-on-arch-action@d94c13912ea685de38fccc1109385b83fd79427d # v3.0.1
name: Test wheel
with:
arch: ${{ matrix.platform.arch }}
@@ -452,7 +454,7 @@ jobs:
.venv/bin/pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
.venv/bin/${{ env.MODULE_NAME }} --help
- name: "Upload wheels"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: wheels-${{ matrix.platform.target }}
path: dist
@@ -470,7 +472,7 @@ jobs:
tar czvf $ARCHIVE_FILE $ARCHIVE_NAME
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: artifacts-${{ matrix.platform.target }}
path: |

View File

@@ -33,14 +33,14 @@ jobs:
- linux/amd64
- linux/arm64
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
submodules: recursive
persist-credentials: false
- uses: docker/setup-buildx-action@v3
- uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- uses: docker/login-action@v3
- uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -51,7 +51,7 @@ jobs:
env:
TAG: ${{ inputs.plan != '' && fromJson(inputs.plan).announcement_tag || 'dry-run' }}
run: |
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
version=$(grep -m 1 "^version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
if [ "${TAG}" != "${version}" ]; then
echo "The input tag does not match the version from pyproject.toml:" >&2
echo "${TAG}" >&2
@@ -63,7 +63,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: ${{ env.RUFF_BASE_IMG }}
# Defining this makes sure the org.opencontainers.image.version OCI label becomes the actual release version and not the branch name
@@ -79,7 +79,7 @@ jobs:
# Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
platforms: ${{ matrix.platform }}
@@ -96,7 +96,7 @@ jobs:
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digests
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: digests-${{ env.PLATFORM_TUPLE }}
path: /tmp/digests/*
@@ -113,17 +113,17 @@ jobs:
if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}
steps:
- name: Download digests
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- uses: docker/setup-buildx-action@v3
- uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: ${{ env.RUFF_BASE_IMG }}
# Order is on purpose such that the label org.opencontainers.image.version has the first pattern with the full version
@@ -131,7 +131,7 @@ jobs:
type=pep440,pattern={{ version }},value=${{ fromJson(inputs.plan).announcement_tag }}
type=pep440,pattern={{ major }}.{{ minor }},value=${{ fromJson(inputs.plan).announcement_tag }}
- uses: docker/login-action@v3
- uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -163,13 +163,13 @@ jobs:
# Mapping of base image followed by a comma followed by one or more base tags (comma separated)
# Note, org.opencontainers.image.version label will use the first base tag (use the most specific tag first)
image-mapping:
- alpine:3.20,alpine3.20,alpine
- alpine:3.21,alpine3.21,alpine
- debian:bookworm-slim,bookworm-slim,debian-slim
- buildpack-deps:bookworm,bookworm,debian
steps:
- uses: docker/setup-buildx-action@v3
- uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- uses: docker/login-action@v3
- uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
@@ -219,7 +219,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
# ghcr.io prefers index level annotations
env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: index
@@ -231,7 +231,7 @@ jobs:
${{ env.TAG_PATTERNS }}
- name: Build and push
uses: docker/build-push-action@v6
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
platforms: linux/amd64,linux/arm64
@@ -256,17 +256,17 @@ jobs:
if: ${{ inputs.plan != '' && !fromJson(inputs.plan).announcement_tag_is_implicit }}
steps:
- name: Download digests
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- uses: docker/setup-buildx-action@v3
- uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: index
with:
@@ -276,7 +276,7 @@ jobs:
type=pep440,pattern={{ version }},value=${{ fromJson(inputs.plan).announcement_tag }}
type=pep440,pattern={{ major }}.{{ minor }},value=${{ fromJson(inputs.plan).announcement_tag }}
- uses: docker/login-action@v3
- uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}

View File

@@ -1,5 +1,7 @@
name: CI
permissions: {}
on:
push:
branches: [main]
@@ -16,7 +18,7 @@ env:
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
PACKAGE_NAME: ruff
PYTHON_VERSION: "3.12"
PYTHON_VERSION: "3.13"
jobs:
determine_changes:
@@ -24,82 +26,177 @@ jobs:
runs-on: ubuntu-latest
outputs:
# Flag that is raised when any code that affects parser is changed
parser: ${{ steps.changed.outputs.parser_any_changed }}
parser: ${{ steps.check_parser.outputs.changed }}
# Flag that is raised when any code that affects linter is changed
linter: ${{ steps.changed.outputs.linter_any_changed }}
linter: ${{ steps.check_linter.outputs.changed }}
# Flag that is raised when any code that affects formatter is changed
formatter: ${{ steps.changed.outputs.formatter_any_changed }}
formatter: ${{ steps.check_formatter.outputs.changed }}
# Flag that is raised when any code is changed
# This is superset of the linter and formatter
code: ${{ steps.changed.outputs.code_any_changed }}
code: ${{ steps.check_code.outputs.changed }}
# Flag that is raised when any code that affects the fuzzer is changed
fuzz: ${{ steps.changed.outputs.fuzz_any_changed }}
fuzz: ${{ steps.check_fuzzer.outputs.changed }}
# Flag that is set to "true" when code related to ty changes.
ty: ${{ steps.check_ty.outputs.changed }}
# Flag that is set to "true" when code related to the playground changes.
playground: ${{ steps.check_playground.outputs.changed }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false
- uses: tj-actions/changed-files@v45
id: changed
with:
files_yaml: |
parser:
- Cargo.toml
- Cargo.lock
- crates/ruff_python_trivia/**
- crates/ruff_source_file/**
- crates/ruff_text_size/**
- crates/ruff_python_ast/**
- crates/ruff_python_parser/**
- python/py-fuzzer/**
- .github/workflows/ci.yaml
- name: Determine merge base
id: merge_base
env:
BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
run: |
sha=$(git merge-base HEAD "origin/${BASE_REF}")
echo "sha=${sha}" >> "$GITHUB_OUTPUT"
linter:
- Cargo.toml
- Cargo.lock
- crates/**
- "!crates/ruff_python_formatter/**"
- "!crates/ruff_formatter/**"
- "!crates/ruff_dev/**"
- scripts/*
- python/**
- .github/workflows/ci.yaml
- name: Check if the parser code changed
id: check_parser
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- \
':Cargo.toml' \
':Cargo.lock' \
':crates/ruff_python_trivia/**' \
':crates/ruff_source_file/**' \
':crates/ruff_text_size/**' \
':crates/ruff_python_ast/**' \
':crates/ruff_python_parser/**' \
':python/py-fuzzer/**' \
':.github/workflows/ci.yaml' \
; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
formatter:
- Cargo.toml
- Cargo.lock
- crates/ruff_python_formatter/**
- crates/ruff_formatter/**
- crates/ruff_python_trivia/**
- crates/ruff_python_ast/**
- crates/ruff_source_file/**
- crates/ruff_python_index/**
- crates/ruff_text_size/**
- crates/ruff_python_parser/**
- crates/ruff_dev/**
- scripts/*
- python/**
- .github/workflows/ci.yaml
- name: Check if the linter code changed
id: check_linter
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- ':Cargo.toml' \
':Cargo.lock' \
':crates/**' \
':!crates/ty*/**' \
':!crates/ruff_python_formatter/**' \
':!crates/ruff_formatter/**' \
':!crates/ruff_dev/**' \
':!crates/ruff_db/**' \
':scripts/*' \
':python/**' \
':.github/workflows/ci.yaml' \
; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
fuzz:
- fuzz/Cargo.toml
- fuzz/Cargo.lock
- fuzz/fuzz_targets/**
- name: Check if the formatter code changed
id: check_formatter
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- ':Cargo.toml' \
':Cargo.lock' \
':crates/ruff_python_formatter/**' \
':crates/ruff_formatter/**' \
':crates/ruff_python_trivia/**' \
':crates/ruff_python_ast/**' \
':crates/ruff_source_file/**' \
':crates/ruff_python_index/**' \
':crates/ruff_python_index/**' \
':crates/ruff_text_size/**' \
':crates/ruff_python_parser/**' \
':scripts/*' \
':python/**' \
':.github/workflows/ci.yaml' \
; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
code:
- "**/*"
- "!**/*.md"
- "crates/red_knot_python_semantic/resources/mdtest/**/*.md"
- "!docs/**"
- "!assets/**"
- name: Check if the fuzzer code changed
id: check_fuzzer
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- ':Cargo.toml' \
':Cargo.lock' \
':fuzz/fuzz_targets/**' \
':.github/workflows/ci.yaml' \
; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Check if there was any code related change
id: check_code
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- ':**' \
':!**/*.md' \
':crates/ty_python_semantic/resources/mdtest/**/*.md' \
':!docs/**' \
':!assets/**' \
':.github/workflows/ci.yaml' \
; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Check if there was any playground related change
id: check_playground
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- \
':playground/**' \
; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Check if the ty code changed
id: check_ty
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
if git diff --quiet "${MERGE_BASE}...HEAD" -- \
':Cargo.toml' \
':Cargo.lock' \
':crates/ty*/**' \
':crates/ruff_db/**' \
':crates/ruff_annotate_snippets/**' \
':crates/ruff_python_ast/**' \
':crates/ruff_python_parser/**' \
':crates/ruff_python_trivia/**' \
':crates/ruff_source_file/**' \
':crates/ruff_text_size/**' \
':.github/workflows/ci.yaml' \
; then
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
cargo-fmt:
name: "cargo fmt"
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Install Rust toolchain"
@@ -113,42 +210,50 @@ jobs:
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
run: |
rustup component add clippy
rustup target add wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
- name: "Clippy"
run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
- name: "Clippy (wasm)"
run: cargo clippy -p ruff_wasm -p red_knot_wasm --target wasm32-unknown-unknown --all-features --locked -- -D warnings
run: cargo clippy -p ruff_wasm -p ty_wasm --target wasm32-unknown-unknown --all-features --locked -- -D warnings
cargo-test-linux:
name: "cargo test (linux)"
runs-on: depot-ubuntu-22.04-16
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
run: rustup show
- name: "Install mold"
uses: rui314/setup-mold@v1
uses: rui314/setup-mold@67424c1b3680e35255d95971cbd5de0047bf31c3 # v1
- name: "Install cargo nextest"
uses: taiki-e/install-action@v2
uses: taiki-e/install-action@735e5933943122c5ac182670a935f54a949265c1 # v2.52.4
with:
tool: cargo-nextest
- name: "Install cargo insta"
uses: taiki-e/install-action@v2
uses: taiki-e/install-action@735e5933943122c5ac182670a935f54a949265c1 # v2.52.4
with:
tool: cargo-insta
- uses: Swatinem/rust-cache@v2
- name: ty mdtests (GitHub annotations)
if: ${{ needs.determine_changes.outputs.ty == 'true' }}
env:
NO_COLOR: 1
MDTEST_GITHUB_ANNOTATIONS_FORMAT: 1
# Ignore errors if this step fails; we want to continue to later steps in the workflow anyway.
# This step is just to get nice GitHub annotations on the PR diff in the files-changed tab.
run: cargo test -p ty_python_semantic --test mdtest || true
- name: "Run tests"
shell: bash
env:
@@ -163,38 +268,42 @@ jobs:
# sync, not just public items. Eventually we should do this for all
# crates; for now add crates here as they are warning-clean to prevent
# regression.
- run: cargo doc --no-deps -p red_knot_python_semantic -p red_knot -p red_knot_test -p ruff_db --document-private-items
- run: cargo doc --no-deps -p ty_python_semantic -p ty -p ty_test -p ruff_db --document-private-items
env:
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
RUSTDOCFLAGS: "-D warnings"
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ruff
path: target/debug/ruff
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ty
path: target/debug/ty
cargo-test-linux-release:
name: "cargo test (linux, release)"
runs-on: depot-ubuntu-22.04-16
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
run: rustup show
- name: "Install mold"
uses: rui314/setup-mold@v1
uses: rui314/setup-mold@67424c1b3680e35255d95971cbd5de0047bf31c3 # v1
- name: "Install cargo nextest"
uses: taiki-e/install-action@v2
uses: taiki-e/install-action@735e5933943122c5ac182670a935f54a949265c1 # v2.52.4
with:
tool: cargo-nextest
- name: "Install cargo insta"
uses: taiki-e/install-action@v2
uses: taiki-e/install-action@735e5933943122c5ac182670a935f54a949265c1 # v2.52.4
with:
tool: cargo-insta
- uses: Swatinem/rust-cache@v2
- name: "Run tests"
shell: bash
env:
@@ -205,22 +314,23 @@ jobs:
name: "cargo test (windows)"
runs-on: github-windows-2025-x86_64-16
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
run: rustup show
- name: "Install cargo nextest"
uses: taiki-e/install-action@v2
uses: taiki-e/install-action@735e5933943122c5ac182670a935f54a949265c1 # v2.52.4
with:
tool: cargo-nextest
- uses: Swatinem/rust-cache@v2
- name: "Run tests"
shell: bash
env:
NEXTEST_PROFILE: "ci"
# Workaround for <https://github.com/nextest-rs/nextest/issues/1493>.
RUSTUP_WINDOWS_PATH_ADD_BIN: 1
run: |
@@ -231,30 +341,30 @@ jobs:
name: "cargo test (wasm)"
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 20
cache: "npm"
cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-pack-action@v0.4.0
- uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0
with:
version: v0.13.1
- uses: Swatinem/rust-cache@v2
- name: "Test ruff_wasm"
run: |
cd crates/ruff_wasm
wasm-pack test --node
- name: "Test red_knot_wasm"
- name: "Test ty_wasm"
run: |
cd crates/red_knot_wasm
cd crates/ty_wasm
wasm-pack test --node
cargo-build-release:
@@ -263,47 +373,47 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
run: rustup show
- name: "Install mold"
uses: rui314/setup-mold@v1
- uses: Swatinem/rust-cache@v2
uses: rui314/setup-mold@67424c1b3680e35255d95971cbd5de0047bf31c3 # v1
- name: "Build"
run: cargo build --release --locked
cargo-build-msrv:
name: "cargo build (msrv)"
runs-on: ubuntu-latest
runs-on: depot-ubuntu-latest-8
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: SebRollen/toml-action@v1.2.0
- uses: SebRollen/toml-action@b1b3628f55fc3a28208d4203ada8b737e9687876 # v1.2.0
id: msrv
with:
file: "Cargo.toml"
field: "workspace.package.rust-version"
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
env:
MSRV: ${{ steps.msrv.outputs.value }}
run: rustup default "${MSRV}"
- name: "Install mold"
uses: rui314/setup-mold@v1
uses: rui314/setup-mold@67424c1b3680e35255d95971cbd5de0047bf31c3 # v1
- name: "Install cargo nextest"
uses: taiki-e/install-action@v2
uses: taiki-e/install-action@735e5933943122c5ac182670a935f54a949265c1 # v2.52.4
with:
tool: cargo-nextest
- name: "Install cargo insta"
uses: taiki-e/install-action@v2
uses: taiki-e/install-action@735e5933943122c5ac182670a935f54a949265c1 # v2.52.4
with:
tool: cargo-insta
- uses: Swatinem/rust-cache@v2
- name: "Run tests"
shell: bash
env:
@@ -318,16 +428,16 @@ jobs:
if: ${{ github.ref == 'refs/heads/main' || needs.determine_changes.outputs.fuzz == 'true' || needs.determine_changes.outputs.code == 'true' }}
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
with:
workspaces: "fuzz -> target"
- name: "Install Rust toolchain"
run: rustup show
- name: "Install cargo-binstall"
uses: cargo-bins/cargo-binstall@main
uses: cargo-bins/cargo-binstall@e8c9cc3599f6c4063d143083205f98ca25d91677 # v1.12.6
with:
tool: cargo-fuzz@0.11.2
- name: "Install cargo-fuzz"
@@ -341,16 +451,16 @@ jobs:
needs:
- cargo-test-linux
- determine_changes
if: ${{ needs.determine_changes.outputs.parser == 'true' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && needs.determine_changes.outputs.parser == 'true' }}
timeout-minutes: 20
env:
FORCE_COLOR: 1
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: astral-sh/setup-uv@v5
- uses: actions/download-artifact@v4
- uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
name: Download Ruff binary to test
id: download-cached-binary
with:
@@ -377,15 +487,15 @@ jobs:
name: "test scripts"
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- 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
@@ -394,12 +504,10 @@ jobs:
# 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
- run: |
./scripts/add_plugin.py test --url https://pypi.org/project/-test/0.1.0/ --prefix TST
./scripts/add_rule.py --name FirstRule --prefix TST --code 001 --linter test
- run: cargo check
- run: cargo fmt --all --check
ecosystem:
name: "ecosystem"
@@ -409,24 +517,24 @@ jobs:
- determine_changes
# Only runs on pull requests, since that is the only we way we can find the base version for comparison.
# Ecosystem check needs linter and/or formatter changes.
if: ${{ github.event_name == 'pull_request' && needs.determine_changes.outputs.code == 'true' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && needs.determine_changes.outputs.code == 'true' }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
name: Download comparison Ruff binary
id: ruff-target
with:
name: ruff
path: target/debug
- uses: dawidd6/action-download-artifact@v7
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
name: Download baseline Ruff binary
with:
name: ruff
@@ -514,28 +622,75 @@ jobs:
run: |
echo ${{ github.event.number }} > pr-number
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
name: Upload PR Number
with:
name: pr-number
path: pr-number
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
name: Upload Results
with:
name: ecosystem-result
path: ecosystem-result
fuzz-ty:
name: "Fuzz for new ty panics"
runs-on: depot-ubuntu-22.04-16
needs:
- cargo-test-linux
- determine_changes
# Only runs on pull requests, since that is the only we way we can find the base version for comparison.
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && needs.determine_changes.outputs.ty == 'true' }}
timeout-minutes: 20
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
name: Download new ty binary
id: ty-new
with:
name: ty
path: target/debug
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
name: Download baseline ty binary
with:
name: ty
branch: ${{ github.event.pull_request.base.ref }}
workflow: "ci.yaml"
check_artifacts: true
- uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
- name: Fuzz
env:
FORCE_COLOR: 1
NEW_TY: ${{ steps.ty-new.outputs.download-path }}
run: |
# Make executable, since artifact download doesn't preserve this
chmod +x "${PWD}/ty" "${NEW_TY}/ty"
(
uvx \
--python="${PYTHON_VERSION}" \
--from=./python/py-fuzzer \
fuzz \
--test-executable="${NEW_TY}/ty" \
--baseline-executable="${PWD}/ty" \
--only-new-bugs \
--bin=ty \
0-500
)
cargo-shear:
name: "cargo shear"
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: cargo-bins/cargo-binstall@main
- uses: cargo-bins/cargo-binstall@e8c9cc3599f6c4063d143083205f98ca25d91677 # v1.12.6
- run: cargo binstall --no-confirm cargo-shear
- run: cargo shear
@@ -543,19 +698,20 @@ jobs:
name: "python package"
runs-on: ubuntu-latest
timeout-minutes: 20
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: PyO3/maturin-action@v1
uses: PyO3/maturin-action@aef21716ff3dcae8a1c301d23ec3e4446972a6e3 # v1.49.1
with:
args: --out dist
- name: "Test wheel"
@@ -568,22 +724,19 @@ jobs:
pre-commit:
name: "pre-commit"
runs-on: ubuntu-latest
runs-on: depot-ubuntu-22.04-16
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-python@v5
- uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v2
- name: "Install pre-commit"
run: pip install pre-commit
node-version: 22
- name: "Cache pre-commit"
uses: actions/cache@v4
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
@@ -592,7 +745,7 @@ jobs:
echo '```console' > "$GITHUB_STEP_SUMMARY"
# Enable color output for pre-commit and remove it for the summary
# Use --hook-stage=manual to enable slower pre-commit hooks that are skipped by default
SKIP=cargo-fmt,clippy,dev-generate-all pre-commit run --all-files --show-diff-on-failure --color=always --hook-stage=manual | \
SKIP=cargo-fmt,clippy,dev-generate-all uvx --python="${PYTHON_VERSION}" pre-commit run --all-files --show-diff-on-failure --color=always --hook-stage=manual | \
tee >(sed -E 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})*)?[mGK]//g' >> "$GITHUB_STEP_SUMMARY") >&1
exit_code="${PIPESTATUS[0]}"
echo '```' >> "$GITHUB_STEP_SUMMARY"
@@ -605,22 +758,22 @@ jobs:
env:
MKDOCS_INSIDERS_SSH_KEY_EXISTS: ${{ secrets.MKDOCS_INSIDERS_SSH_KEY != '' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.13"
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Add SSH key"
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
uses: webfactory/ssh-agent@v0.9.0
uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
with:
ssh-private-key: ${{ secrets.MKDOCS_INSIDERS_SSH_KEY }}
- name: "Install Rust toolchain"
run: rustup show
- name: Install uv
uses: astral-sh/setup-uv@v5
- uses: Swatinem/rust-cache@v2
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
- name: "Install Insiders dependencies"
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
run: uv pip install -r docs/requirements-insiders.txt --system
@@ -644,16 +797,15 @@ jobs:
name: "formatter instabilities and black similarity"
runs-on: ubuntu-latest
needs: determine_changes
if: needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main'
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
run: rustup show
- name: "Cache rust"
uses: Swatinem/rust-cache@v2
- name: "Run checks"
run: scripts/formatter_ecosystem_checks.sh
- name: "Github step summary"
@@ -668,23 +820,24 @@ jobs:
needs:
- cargo-test-linux
- determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
steps:
- uses: extractions/setup-just@v2
- uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
name: "Download ruff-lsp source"
with:
persist-credentials: false
repository: "astral-sh/ruff-lsp"
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ env.PYTHON_VERSION }}
# installation fails on 3.13 and newer
python-version: "3.12"
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
name: Download development ruff binary
id: ruff-target
with:
@@ -707,32 +860,65 @@ jobs:
just test
check-playground:
name: "check playground"
runs-on: ubuntu-latest
timeout-minutes: 5
needs:
- determine_changes
if: ${{ (needs.determine_changes.outputs.playground == 'true') }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: "npm"
cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
- name: "Install Node dependencies"
run: npm ci
working-directory: playground
- name: "Build playgrounds"
run: npm run dev:wasm
working-directory: playground
- name: "Run TypeScript checks"
run: npm run check
working-directory: playground
- name: "Check formatting"
run: npm run fmt:check
working-directory: playground
benchmarks:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
needs: determine_changes
if: ${{ github.repository == 'astral-sh/ruff' && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
if: ${{ github.repository == 'astral-sh/ruff' && !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
timeout-minutes: 20
steps:
- name: "Checkout Branch"
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Rust toolchain"
run: rustup show
- name: "Install codspeed"
uses: taiki-e/install-action@v2
uses: taiki-e/install-action@735e5933943122c5ac182670a935f54a949265c1 # v2.52.4
with:
tool: cargo-codspeed
- uses: Swatinem/rust-cache@v2
- name: "Build benchmarks"
run: cargo codspeed build --features codspeed -p ruff_benchmark
- name: "Run benchmarks"
uses: CodSpeedHQ/action@v3
uses: CodSpeedHQ/action@0010eb0ca6e89b80c88e8edaaa07cfe5f3e6664d # v3.5.0
with:
run: cargo codspeed run
token: ${{ secrets.CODSPEED_TOKEN }}

View File

@@ -31,15 +31,15 @@ jobs:
# Don't run the cron job on forks:
if: ${{ github.repository == 'astral-sh/ruff' || github.event_name != 'schedule' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: astral-sh/setup-uv@v5
- uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
- name: "Install Rust toolchain"
run: rustup show
- name: "Install mold"
uses: rui314/setup-mold@v1
- uses: Swatinem/rust-cache@v2
uses: rui314/setup-mold@67424c1b3680e35255d95971cbd5de0047bf31c3 # v1
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: Build ruff
# A debug build means the script runs slower once it gets started,
# but this is outweighed by the fact that a release build takes *much* longer to compile in CI
@@ -65,7 +65,7 @@ jobs:
permissions:
issues: write
steps:
- uses: actions/github-script@v7
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@@ -1,71 +0,0 @@
name: Daily property test run
on:
workflow_dispatch:
schedule:
- cron: "0 12 * * *"
pull_request:
paths:
- ".github/workflows/daily_property_tests.yaml"
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
FORCE_COLOR: 1
jobs:
property_tests:
name: Property tests
runs-on: ubuntu-latest
timeout-minutes: 20
# Don't run the cron job on forks:
if: ${{ github.repository == 'astral-sh/ruff' || github.event_name != 'schedule' }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: "Install Rust toolchain"
run: rustup show
- name: "Install mold"
uses: rui314/setup-mold@v1
- uses: Swatinem/rust-cache@v2
- name: Build Red Knot
# A release build takes longer (2 min vs 1 min), but the property tests run much faster in release
# mode (1.5 min vs 14 min), so the overall time is shorter with a release build.
run: cargo build --locked --release --package red_knot_python_semantic --tests
- name: Run property tests
shell: bash
run: |
export QUICKCHECK_TESTS=100000
for _ in {1..5}; do
cargo test --locked --release --package red_knot_python_semantic -- --ignored types::property_tests::stable
done
create-issue-on-failure:
name: Create an issue if the daily property test run surfaced any bugs
runs-on: ubuntu-latest
needs: property_tests
if: ${{ github.repository == 'astral-sh/ruff' && always() && github.event_name == 'schedule' && needs.property_tests.result == 'failure' }}
permissions:
issues: write
steps:
- uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
await github.rest.issues.create({
owner: "astral-sh",
repo: "ruff",
title: `Daily property test run failed on ${new Date().toDateString()}`,
body: "Run listed here: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
labels: ["bug", "red-knot", "testing"],
})

101
.github/workflows/mypy_primer.yaml vendored Normal file
View File

@@ -0,0 +1,101 @@
name: Run mypy_primer
permissions: {}
on:
pull_request:
paths:
- "crates/ty*/**"
- "crates/ruff_db"
- "crates/ruff_python_ast"
- "crates/ruff_python_parser"
- ".github/workflows/mypy_primer.yaml"
- ".github/workflows/mypy_primer_comment.yaml"
- "Cargo.lock"
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
RUST_BACKTRACE: 1
jobs:
mypy_primer:
name: Run mypy_primer
runs-on: depot-ubuntu-22.04-32
timeout-minutes: 20
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: ruff
fetch-depth: 0
persist-credentials: false
- name: Install the latest version of uv
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
with:
workspaces: "ruff"
- name: Install Rust toolchain
run: rustup show
- name: Run mypy_primer
shell: bash
run: |
cd ruff
echo "Enabling mypy primer specific configuration overloads (see .github/mypy-primer-ty.toml)"
mkdir -p ~/.config/ty
cp .github/mypy-primer-ty.toml ~/.config/ty/ty.toml
PRIMER_SELECTOR="$(paste -s -d'|' crates/ty_python_semantic/resources/primer/good.txt)"
echo "new commit"
git rev-list --format=%s --max-count=1 "$GITHUB_SHA"
MERGE_BASE="$(git merge-base "$GITHUB_SHA" "origin/$GITHUB_BASE_REF")"
git checkout -b base_commit "$MERGE_BASE"
echo "base commit"
git rev-list --format=%s --max-count=1 base_commit
cd ..
echo "Project selector: $PRIMER_SELECTOR"
# Allow the exit code to be 0 or 1, only fail for actual mypy_primer crashes/bugs
uvx \
--from="git+https://github.com/hauntsaninja/mypy_primer@01a7ca325f674433c58e02416a867178d1571128" \
mypy_primer \
--repo ruff \
--type-checker ty \
--old base_commit \
--new "$GITHUB_SHA" \
--project-selector "/($PRIMER_SELECTOR)\$" \
--output concise \
--debug > mypy_primer.diff || [ $? -eq 1 ]
# Output diff with ANSI color codes
cat mypy_primer.diff
# Remove ANSI color codes before uploading
sed -ie 's/\x1b\[[0-9;]*m//g' mypy_primer.diff
echo ${{ github.event.number }} > pr-number
- name: Upload diff
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: mypy_primer_diff
path: mypy_primer.diff
- name: Upload pr-number
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: pr-number
path: pr-number

View File

@@ -0,0 +1,97 @@
name: PR comment (mypy_primer)
on: # zizmor: ignore[dangerous-triggers]
workflow_run:
workflows: [Run mypy_primer]
types: [completed]
workflow_dispatch:
inputs:
workflow_run_id:
description: The mypy_primer workflow that triggers the workflow run
required: true
jobs:
comment:
runs-on: ubuntu-24.04
permissions:
pull-requests: write
steps:
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
name: Download PR number
with:
name: pr-number
run_id: ${{ github.event.workflow_run.id || github.event.inputs.workflow_run_id }}
if_no_artifact_found: ignore
allow_forks: true
- name: Parse pull request number
id: pr-number
run: |
if [[ -f pr-number ]]
then
echo "pr-number=$(<pr-number)" >> "$GITHUB_OUTPUT"
fi
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
name: "Download mypy_primer results"
id: download-mypy_primer_diff
if: steps.pr-number.outputs.pr-number
with:
name: mypy_primer_diff
workflow: mypy_primer.yaml
pr: ${{ steps.pr-number.outputs.pr-number }}
path: pr/mypy_primer_diff
workflow_conclusion: completed
if_no_artifact_found: ignore
allow_forks: true
- name: Generate comment content
id: generate-comment
if: steps.download-mypy_primer_diff.outputs.found_artifact == 'true'
run: |
# Guard against malicious mypy_primer results that symlink to a secret
# file on this runner
if [[ -L pr/mypy_primer_diff/mypy_primer.diff ]]
then
echo "Error: mypy_primer.diff cannot be a symlink"
exit 1
fi
# Note this identifier is used to find the comment to update on
# subsequent runs
echo '<!-- generated-comment mypy_primer -->' >> comment.txt
echo '## `mypy_primer` results' >> comment.txt
if [ -s "pr/mypy_primer_diff/mypy_primer.diff" ]; then
echo '<details>' >> comment.txt
echo '<summary>Changes were detected when running on open source projects</summary>' >> comment.txt
echo '' >> comment.txt
echo '```diff' >> comment.txt
cat pr/mypy_primer_diff/mypy_primer.diff >> comment.txt
echo '```' >> comment.txt
echo '</details>' >> comment.txt
else
echo 'No ecosystem changes detected ✅' >> comment.txt
fi
echo 'comment<<EOF' >> "$GITHUB_OUTPUT"
cat comment.txt >> "$GITHUB_OUTPUT"
echo 'EOF' >> "$GITHUB_OUTPUT"
- name: Find existing comment
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0
if: steps.generate-comment.outcome == 'success'
id: find-comment
with:
issue-number: ${{ steps.pr-number.outputs.pr-number }}
comment-author: "github-actions[bot]"
body-includes: "<!-- generated-comment mypy_primer -->"
- name: Create or update comment
if: steps.find-comment.outcome == 'success'
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
with:
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ steps.pr-number.outputs.pr-number }}
body-path: comment.txt
edit-mode: replace

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: "Update pre-commit mirror"
uses: actions/github-script@v7
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ secrets.RUFF_PRE_COMMIT_PAT }}
script: |

View File

@@ -16,7 +16,7 @@ jobs:
permissions:
pull-requests: write
steps:
- uses: dawidd6/action-download-artifact@v7
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
name: Download pull request number
with:
name: pr-number
@@ -32,7 +32,7 @@ jobs:
echo "pr-number=$(<pr-number)" >> "$GITHUB_OUTPUT"
fi
- uses: dawidd6/action-download-artifact@v7
- uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8
name: "Download ecosystem results"
id: download-ecosystem-result
if: steps.pr-number.outputs.pr-number
@@ -70,7 +70,7 @@ jobs:
echo 'EOF' >> "$GITHUB_OUTPUT"
- name: Find existing comment
uses: peter-evans/find-comment@v3
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0
if: steps.generate-comment.outcome == 'success'
id: find-comment
with:
@@ -80,7 +80,7 @@ jobs:
- name: Create or update comment
if: steps.find-comment.outcome == 'success'
uses: peter-evans/create-or-update-comment@v4
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
with:
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ steps.pr-number.outputs.pr-number }}

View File

@@ -23,12 +23,12 @@ jobs:
env:
MKDOCS_INSIDERS_SSH_KEY_EXISTS: ${{ secrets.MKDOCS_INSIDERS_SSH_KEY != '' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.ref }}
persist-credentials: true
- uses: actions/setup-python@v5
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: 3.12
@@ -61,14 +61,14 @@ jobs:
- name: "Add SSH key"
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
uses: webfactory/ssh-agent@v0.9.0
uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
with:
ssh-private-key: ${{ secrets.MKDOCS_INSIDERS_SSH_KEY }}
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
- name: "Install Insiders dependencies"
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}

View File

@@ -24,34 +24,31 @@ jobs:
env:
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 20
node-version: 22
cache: "npm"
cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-pack-action@v0.4.0
- uses: jetli/wasm-bindgen-action@v0.2.0
- name: "Run wasm-pack"
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff_wasm
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
- name: "Install Node dependencies"
run: npm ci
working-directory: playground
- name: "Run TypeScript checks"
run: npm run check
working-directory: playground
- name: "Build JavaScript bundle"
run: npm run build
- name: "Build Ruff playground"
run: npm run build --workspace ruff-playground
working-directory: playground
- name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@v3.13.1
uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
# `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production
command: pages deploy playground/dist --project-name=ruff-playground --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}
command: pages deploy playground/ruff/dist --project-name=ruff-playground --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}

View File

@@ -22,8 +22,8 @@ jobs:
id-token: write
steps:
- name: "Install uv"
uses: astral-sh/setup-uv@v5
- uses: actions/download-artifact@v4
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v6.1.0
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
pattern: wheels-*
path: wheels

View File

@@ -0,0 +1,58 @@
# Publish the ty playground.
name: "[ty Playground] Release"
permissions: {}
on:
push:
branches: [main]
paths:
- "crates/ty*/**"
- "crates/ruff_db/**"
- "crates/ruff_python_ast/**"
- "crates/ruff_python_parser/**"
- "playground/**"
- ".github/workflows/publish-ty-playground.yml"
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUSTUP_MAX_RETRIES: 10
jobs:
publish:
runs-on: ubuntu-latest
env:
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
- name: "Install Node dependencies"
run: npm ci
working-directory: playground
- name: "Run TypeScript checks"
run: npm run check
working-directory: playground
- name: "Build ty playground"
run: npm run build --workspace ty-playground
working-directory: playground
- name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@da0e0dfe58b7a431659754fdf3f186c529afbe65 # v3.14.1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
# `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production
command: pages deploy playground/ty/dist --project-name=ty-playground --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}

View File

@@ -29,13 +29,15 @@ jobs:
target: [web, bundler, nodejs]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: jetli/wasm-pack-action@v0.4.0
- uses: jetli/wasm-bindgen-action@v0.2.0
- uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0
with:
version: v0.13.1
- uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0
- name: "Run wasm-pack build"
run: wasm-pack build --target ${{ matrix.target }} crates/ruff_wasm
- name: "Rename generated package"
@@ -43,7 +45,7 @@ jobs:
jq '.name="@astral-sh/ruff-wasm-${{ matrix.target }}"' crates/ruff_wasm/pkg/package.json > /tmp/package.json
mv /tmp/package.json crates/ruff_wasm/pkg
- run: cp LICENSE crates/ruff_wasm/pkg # wasm-pack does not put the LICENSE file in the pkg
- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 20
registry-url: "https://registry.npmjs.org"

View File

@@ -1,6 +1,7 @@
# This file was autogenerated by dist: https://opensource.axo.dev/cargo-dist/
# This file was autogenerated by dist: https://github.com/astral-sh/cargo-dist
#
# Copyright 2022-2024, axodotdev
# Copyright 2025 Astral Software Inc.
# SPDX-License-Identifier: MIT or Apache-2.0
#
# CI that:
@@ -39,6 +40,7 @@ permissions:
# If there's a prerelease-style suffix to the version, then the release(s)
# will be marked as a prerelease.
on:
pull_request:
workflow_dispatch:
inputs:
tag:
@@ -50,7 +52,7 @@ on:
jobs:
# Run 'dist plan' (or host) to determine what tasks we need to do
plan:
runs-on: "ubuntu-20.04"
runs-on: "depot-ubuntu-latest-4"
outputs:
val: ${{ steps.plan.outputs.manifest }}
tag: ${{ (inputs.tag != 'dry-run' && inputs.tag) || '' }}
@@ -59,16 +61,17 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
with:
persist-credentials: false
submodules: recursive
- name: Install dist
# we specify bash to get pipefail; it guards against the `curl` command
# failing. otherwise `sh` won't catch that `curl` returned non-0
shell: bash
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.25.2-prerelease.3/cargo-dist-installer.sh | sh"
run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/astral-sh/cargo-dist/releases/download/v0.28.5-prerelease.1/cargo-dist-installer.sh | sh"
- name: Cache dist
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47
with:
name: cargo-dist-cache
path: ~/.cargo/bin/dist
@@ -84,7 +87,7 @@ jobs:
cat plan-dist-manifest.json
echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
- name: "Upload dist-manifest.json"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47
with:
name: artifacts-plan-dist-manifest
path: plan-dist-manifest.json
@@ -116,23 +119,24 @@ jobs:
- plan
- custom-build-binaries
- custom-build-docker
runs-on: "ubuntu-20.04"
runs-on: "depot-ubuntu-latest-4"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
with:
persist-credentials: false
submodules: recursive
- name: Install cached dist
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist
# Get all the local artifacts for the global tasks to use (for e.g. checksums)
- name: Fetch local artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: artifacts-*
path: target/distrib/
@@ -150,7 +154,7 @@ jobs:
cp dist-manifest.json "$BUILD_MANIFEST_NAME"
- name: "Upload artifacts"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47
with:
name: artifacts-build-global
path: |
@@ -167,22 +171,23 @@ jobs:
if: ${{ always() && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.custom-build-binaries.result == 'skipped' || needs.custom-build-binaries.result == 'success') && (needs.custom-build-docker.result == 'skipped' || needs.custom-build-docker.result == 'success') }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
runs-on: "ubuntu-20.04"
runs-on: "depot-ubuntu-latest-4"
outputs:
val: ${{ steps.host.outputs.manifest }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
with:
persist-credentials: false
submodules: recursive
- name: Install cached dist
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist
# Fetch artifacts from scratch-storage
- name: Fetch artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: artifacts-*
path: target/distrib/
@@ -196,7 +201,7 @@ jobs:
cat dist-manifest.json
echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
- name: "Upload dist-manifest.json"
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47
with:
# Overwrite the previous copy
name: artifacts-dist-manifest
@@ -242,16 +247,17 @@ jobs:
# 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-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"
runs-on: "depot-ubuntu-latest-4"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
with:
persist-credentials: false
submodules: recursive
# Create a GitHub Release while uploading all files to it
- name: "Download GitHub Artifacts"
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: artifacts-*
path: artifacts

View File

@@ -21,12 +21,12 @@ jobs:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
name: Checkout Ruff
with:
path: ruff
persist-credentials: true
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
name: Checkout typeshed
with:
repository: python/typeshed
@@ -39,13 +39,13 @@ jobs:
- name: Sync typeshed
id: sync
run: |
rm -rf ruff/crates/red_knot_vendored/vendor/typeshed
mkdir ruff/crates/red_knot_vendored/vendor/typeshed
cp typeshed/README.md ruff/crates/red_knot_vendored/vendor/typeshed
cp typeshed/LICENSE ruff/crates/red_knot_vendored/vendor/typeshed
cp -r typeshed/stdlib ruff/crates/red_knot_vendored/vendor/typeshed/stdlib
rm -rf ruff/crates/red_knot_vendored/vendor/typeshed/stdlib/@tests
git -C typeshed rev-parse HEAD > ruff/crates/red_knot_vendored/vendor/typeshed/source_commit.txt
rm -rf ruff/crates/ty_vendored/vendor/typeshed
mkdir ruff/crates/ty_vendored/vendor/typeshed
cp typeshed/README.md ruff/crates/ty_vendored/vendor/typeshed
cp typeshed/LICENSE ruff/crates/ty_vendored/vendor/typeshed
cp -r typeshed/stdlib ruff/crates/ty_vendored/vendor/typeshed/stdlib
rm -rf ruff/crates/ty_vendored/vendor/typeshed/stdlib/@tests
git -C typeshed rev-parse HEAD > ruff/crates/ty_vendored/vendor/typeshed/source_commit.txt
- name: Commit the changes
id: commit
if: ${{ steps.sync.outcome == 'success' }}
@@ -70,7 +70,7 @@ jobs:
permissions:
issues: write
steps:
- uses: actions/github-script@v7
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
@@ -79,5 +79,5 @@ jobs:
repo: "ruff",
title: `Automated typeshed sync failed on ${new Date().toDateString()}`,
body: "Run listed here: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
labels: ["bug", "red-knot"],
labels: ["bug", "ty"],
})

7
.github/zizmor.yml vendored
View File

@@ -10,3 +10,10 @@ rules:
ignore:
- build-docker.yml
- publish-playground.yml
excessive-permissions:
# it's hard to test what the impact of removing these ignores would be
# without actually running the release workflow...
ignore:
- build-docker.yml
- publish-playground.yml
- publish-docs.yml

4
.gitignore vendored
View File

@@ -29,6 +29,10 @@ tracing.folded
tracing-flamechart.svg
tracing-flamegraph.svg
# insta
*.rs.pending-snap
###
# Rust.gitignore
###

1
.ignore Normal file
View File

@@ -0,0 +1 @@
!/.github/

View File

@@ -29,3 +29,7 @@ MD024:
#
# Ref: https://github.com/astral-sh/ruff/pull/15011#issuecomment-2544790854
MD046: false
# Link text should be descriptive
# Disallows link text like *here* which is annoying.
MD059: false

View File

@@ -3,8 +3,10 @@ fail_fast: false
exclude: |
(?x)^(
.github/workflows/release.yml|
crates/red_knot_vendored/vendor/.*|
crates/red_knot_project/resources/.*|
crates/ty_vendored/vendor/.*|
crates/ty_project/resources/.*|
crates/ty/docs/(configuration|rules|cli).md|
crates/ruff_benchmark/resources/.*|
crates/ruff_linter/resources/.*|
crates/ruff_linter/src/rules/.*/snapshots/.*|
crates/ruff_notebook/resources/.*|
@@ -17,13 +19,18 @@ exclude: |
)$
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-merge-conflict
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23
rev: v0.24.1
hooks:
- id: validate-pyproject
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.21
rev: 0.7.22
hooks:
- id: mdformat
additional_dependencies:
@@ -36,7 +43,7 @@ repos:
)$
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.43.0
rev: v0.45.0
hooks:
- id: markdownlint-fix
exclude: |
@@ -56,10 +63,10 @@ repos:
.*?invalid(_.+)*_syntax\.md
)$
additional_dependencies:
- black==24.10.0
- black==25.1.0
- repo: https://github.com/crate-ci/typos
rev: v1.29.4
rev: v1.32.0
hooks:
- id: typos
@@ -73,7 +80,7 @@ repos:
pass_filenames: false # This makes it a lot faster
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.2
rev: v0.11.12
hooks:
- id: ruff-format
- id: ruff
@@ -83,7 +90,7 @@ repos:
# Prettier
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.4.2
rev: v3.5.3
hooks:
- id: prettier
types: [yaml]
@@ -91,12 +98,12 @@ 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.1.1
rev: v1.9.0
hooks:
- id: zizmor
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.31.0
rev: 0.33.0
hooks:
- id: check-github-workflows

View File

@@ -1,5 +1,55 @@
# Breaking Changes
## 0.11.0
This is a follow-up to release 0.10.0. Because of a mistake in the release process, the `requires-python` inference changes were not included in that release. Ruff 0.11.0 now includes this change as well as the stabilization of the preview behavior for `PGH004`.
- **Changes to how the Python version is inferred when a `target-version` is not specified** ([#16319](https://github.com/astral-sh/ruff/pull/16319))
In previous versions of Ruff, you could specify your Python version with:
- The `target-version` option in a `ruff.toml` file or the `[tool.ruff]` section of a pyproject.toml file.
- The `project.requires-python` field in a `pyproject.toml` file with a `[tool.ruff]` section.
These options worked well in most cases, and are still recommended for fine control of the Python version. However, because of the way Ruff discovers config files, `pyproject.toml` files without a `[tool.ruff]` section would be ignored, including the `requires-python` setting. Ruff would then use the default Python version (3.9 as of this writing) instead, which is surprising when you've attempted to request another version.
In v0.10, config discovery has been updated to address this issue:
- If Ruff finds a `ruff.toml` file without a `target-version`, it will check
for a `pyproject.toml` file in the same directory and respect its
`requires-python` version, even if it does not contain a `[tool.ruff]`
section.
- If Ruff finds a user-level configuration, the `requires-python` field of the closest `pyproject.toml` in a parent directory will take precedence.
- If there is no config file (`ruff.toml`or `pyproject.toml` with a
`[tool.ruff]` section) in the directory of the file being checked, Ruff will
search for the closest `pyproject.toml` in the parent directories and use its
`requires-python` setting.
## 0.10.0
- **Changes to how the Python version is inferred when a `target-version` is not specified** ([#16319](https://github.com/astral-sh/ruff/pull/16319))
Because of a mistake in the release process, the `requires-python` inference changes are not included in this release and instead shipped as part of 0.11.0.
You can find a description of this change in the 0.11.0 section.
- **Updated `TYPE_CHECKING` behavior** ([#16669](https://github.com/astral-sh/ruff/pull/16669))
Previously, Ruff only recognized typechecking blocks that tested the `typing.TYPE_CHECKING` symbol. Now, Ruff recognizes any local variable named `TYPE_CHECKING`. This release also removes support for the legacy `if 0:` and `if False:` typechecking checks. Use a local `TYPE_CHECKING` variable instead.
- **More robust noqa parsing** ([#16483](https://github.com/astral-sh/ruff/pull/16483))
The syntax for both file-level and in-line suppression comments has been unified and made more robust to certain errors. In most cases, this will result in more suppression comments being read by Ruff, but there are a few instances where previously read comments will now log an error to the user instead. Please refer to the documentation on [_Error suppression_](https://docs.astral.sh/ruff/linter/#error-suppression) for the full specification.
- **Avoid unnecessary parentheses around with statements with a single context manager and a trailing comment** ([#14005](https://github.com/astral-sh/ruff/pull/14005))
This change fixes a bug in the formatter where it introduced unnecessary parentheses around with statements with a single context manager and a trailing comment. This change may result in a change in formatting for some users.
- **Bump alpine default tag to 3.21 for derived Docker images** ([#16456](https://github.com/astral-sh/ruff/pull/16456))
Alpine 3.21 was released in Dec 2024 and is used in the official Alpine-based Python images. Now the ruff:alpine image will use 3.21 instead of 3.20 and ruff:alpine3.20 will no longer be updated.
- **\[`unsafe-markup-use`\]: `RUF035` has been recoded to `S704`** ([#15957](https://github.com/astral-sh/ruff/pull/15957))
## 0.9.0
Ruff now formats your code according to the 2025 style guide. As a result, your code might now get formatted differently. See the [changelog](./CHANGELOG.md#090) for a detailed list of changes.
@@ -209,8 +259,8 @@ This change only affects those using Ruff under its default rule set. Users that
### Remove support for emoji identifiers ([#7212](https://github.com/astral-sh/ruff/pull/7212))
Previously, Ruff supported the non-standard compliant emoji identifiers e.g. `📦 = 1`.
We decided to remove this non-standard language extension, and Ruff now reports syntax errors for emoji identifiers in your code, the same as CPython.
Previously, Ruff supported non-standards-compliant emoji identifiers such as `📦 = 1`.
We decided to remove this non-standard language extension. Ruff now reports syntax errors for invalid emoji identifiers in your code, the same as CPython.
### Improved GitLab fingerprints ([#7203](https://github.com/astral-sh/ruff/pull/7203))

View File

@@ -1,5 +1,775 @@
# Changelog
## 0.11.12
### Preview features
- \[`airflow`\] Revise fix titles (`AIR3`) ([#18215](https://github.com/astral-sh/ruff/pull/18215))
- \[`pylint`\] Implement `missing-maxsplit-arg` (`PLC0207`) ([#17454](https://github.com/astral-sh/ruff/pull/17454))
- \[`pyupgrade`\] New rule `UP050` (`useless-class-metaclass-type`) ([#18334](https://github.com/astral-sh/ruff/pull/18334))
- \[`flake8-use-pathlib`\] Replace `os.symlink` with `Path.symlink_to` (`PTH211`) ([#18337](https://github.com/astral-sh/ruff/pull/18337))
### Bug fixes
- \[`flake8-bugbear`\] Ignore `__debug__` attribute in `B010` ([#18357](https://github.com/astral-sh/ruff/pull/18357))
- \[`flake8-async`\] Fix `anyio.sleep` argument name (`ASYNC115`, `ASYNC116`) ([#18262](https://github.com/astral-sh/ruff/pull/18262))
- \[`refurb`\] Fix `FURB129` autofix generating invalid syntax ([#18235](https://github.com/astral-sh/ruff/pull/18235))
### Rule changes
- \[`flake8-implicit-str-concat`\] Add autofix for `ISC003` ([#18256](https://github.com/astral-sh/ruff/pull/18256))
- \[`pycodestyle`\] Improve the diagnostic message for `E712` ([#18328](https://github.com/astral-sh/ruff/pull/18328))
- \[`flake8-2020`\] Fix diagnostic message for `!=` comparisons (`YTT201`) ([#18293](https://github.com/astral-sh/ruff/pull/18293))
- \[`pyupgrade`\] Make fix unsafe if it deletes comments (`UP010`) ([#18291](https://github.com/astral-sh/ruff/pull/18291))
### Documentation
- Simplify rules table to improve readability ([#18297](https://github.com/astral-sh/ruff/pull/18297))
- Update editor integrations link in README ([#17977](https://github.com/astral-sh/ruff/pull/17977))
- \[`flake8-bugbear`\] Add fix safety section (`B006`) ([#17652](https://github.com/astral-sh/ruff/pull/17652))
## 0.11.11
### Preview features
- \[`airflow`\] Add autofixes for `AIR302` and `AIR312` ([#17942](https://github.com/astral-sh/ruff/pull/17942))
- \[`airflow`\] Move rules from `AIR312` to `AIR302` ([#17940](https://github.com/astral-sh/ruff/pull/17940))
- \[`airflow`\] Update `AIR301` and `AIR311` with the latest Airflow implementations ([#17985](https://github.com/astral-sh/ruff/pull/17985))
- \[`flake8-simplify`\] Enable fix in preview mode (`SIM117`) ([#18208](https://github.com/astral-sh/ruff/pull/18208))
### Bug fixes
- Fix inconsistent formatting of match-case on `[]` and `_` ([#18147](https://github.com/astral-sh/ruff/pull/18147))
- \[`pylint`\] Fix `PLW1514` not recognizing the `encoding` positional argument of `codecs.open` ([#18109](https://github.com/astral-sh/ruff/pull/18109))
### CLI
- Add full option name in formatter warning ([#18217](https://github.com/astral-sh/ruff/pull/18217))
### Documentation
- Fix rendering of admonition in docs ([#18163](https://github.com/astral-sh/ruff/pull/18163))
- \[`flake8-print`\] Improve print/pprint docs for `T201` and `T203` ([#18130](https://github.com/astral-sh/ruff/pull/18130))
- \[`flake8-simplify`\] Add fix safety section (`SIM110`,`SIM210`) ([#18114](https://github.com/astral-sh/ruff/pull/18114),[#18100](https://github.com/astral-sh/ruff/pull/18100))
- \[`pylint`\] Fix docs example that produced different output (`PLW0603`) ([#18216](https://github.com/astral-sh/ruff/pull/18216))
## 0.11.10
### Preview features
- \[`ruff`\] Implement a recursive check for `RUF060` ([#17976](https://github.com/astral-sh/ruff/pull/17976))
- \[`airflow`\] Enable autofixes for `AIR301` and `AIR311` ([#17941](https://github.com/astral-sh/ruff/pull/17941))
- \[`airflow`\] Apply try catch guard to all `AIR3` rules ([#17887](https://github.com/astral-sh/ruff/pull/17887))
- \[`airflow`\] Extend `AIR311` rules ([#17913](https://github.com/astral-sh/ruff/pull/17913))
### Bug fixes
- \[`flake8-bugbear`\] Ignore `B028` if `skip_file_prefixes` is present ([#18047](https://github.com/astral-sh/ruff/pull/18047))
- \[`flake8-pie`\] Mark autofix for `PIE804` as unsafe if the dictionary contains comments ([#18046](https://github.com/astral-sh/ruff/pull/18046))
- \[`flake8-simplify`\] Correct behavior for `str.split`/`rsplit` with `maxsplit=0` (`SIM905`) ([#18075](https://github.com/astral-sh/ruff/pull/18075))
- \[`flake8-simplify`\] Fix `SIM905` autofix for `rsplit` creating a reversed list literal ([#18045](https://github.com/astral-sh/ruff/pull/18045))
- \[`flake8-use-pathlib`\] Suppress diagnostics for all `os.*` functions that have the `dir_fd` parameter (`PTH`) ([#17968](https://github.com/astral-sh/ruff/pull/17968))
- \[`refurb`\] Mark autofix as safe only for number literals (`FURB116`) ([#17692](https://github.com/astral-sh/ruff/pull/17692))
### Rule changes
- \[`flake8-bandit`\] Skip `S608` for expressionless f-strings ([#17999](https://github.com/astral-sh/ruff/pull/17999))
- \[`flake8-pytest-style`\] Don't recommend `usefixtures` for `parametrize` values (`PT019`) ([#17650](https://github.com/astral-sh/ruff/pull/17650))
- \[`pyupgrade`\] Add `resource.error` as deprecated alias of `OSError` (`UP024`) ([#17933](https://github.com/astral-sh/ruff/pull/17933))
### CLI
- Disable jemalloc on Android ([#18033](https://github.com/astral-sh/ruff/pull/18033))
### Documentation
- Update Neovim setup docs ([#18108](https://github.com/astral-sh/ruff/pull/18108))
- \[`flake8-simplify`\] Add fix safety section (`SIM103`) ([#18086](https://github.com/astral-sh/ruff/pull/18086))
- \[`flake8-simplify`\] Add fix safety section (`SIM112`) ([#18099](https://github.com/astral-sh/ruff/pull/18099))
- \[`pylint`\] Add fix safety section (`PLC0414`) ([#17802](https://github.com/astral-sh/ruff/pull/17802))
- \[`pylint`\] Add fix safety section (`PLE4703`) ([#17824](https://github.com/astral-sh/ruff/pull/17824))
- \[`pylint`\] Add fix safety section (`PLW1514`) ([#17932](https://github.com/astral-sh/ruff/pull/17932))
- \[`pylint`\] Add fix safety section (`PLW3301`) ([#17878](https://github.com/astral-sh/ruff/pull/17878))
- \[`ruff`\] Add fix safety section (`RUF007`) ([#17755](https://github.com/astral-sh/ruff/pull/17755))
- \[`ruff`\] Add fix safety section (`RUF033`) ([#17760](https://github.com/astral-sh/ruff/pull/17760))
## 0.11.9
### Preview features
- Default to latest supported Python version for version-related syntax errors ([#17529](https://github.com/astral-sh/ruff/pull/17529))
- Implement deferred annotations for Python 3.14 ([#17658](https://github.com/astral-sh/ruff/pull/17658))
- \[`airflow`\] Fix `SQLTableCheckOperator` typo (`AIR302`) ([#17946](https://github.com/astral-sh/ruff/pull/17946))
- \[`airflow`\] Remove `airflow.utils.dag_parsing_context.get_parsing_context` (`AIR301`) ([#17852](https://github.com/astral-sh/ruff/pull/17852))
- \[`airflow`\] Skip attribute check in try catch block (`AIR301`) ([#17790](https://github.com/astral-sh/ruff/pull/17790))
- \[`flake8-bandit`\] Mark tuples of string literals as trusted input in `S603` ([#17801](https://github.com/astral-sh/ruff/pull/17801))
- \[`isort`\] Check full module path against project root(s) when categorizing first-party imports ([#16565](https://github.com/astral-sh/ruff/pull/16565))
- \[`ruff`\] Add new rule `in-empty-collection` (`RUF060`) ([#16480](https://github.com/astral-sh/ruff/pull/16480))
### Bug fixes
- Fix missing `combine` call for `lint.typing-extensions` setting ([#17823](https://github.com/astral-sh/ruff/pull/17823))
- \[`flake8-async`\] Fix module name in `ASYNC110`, `ASYNC115`, and `ASYNC116` fixes ([#17774](https://github.com/astral-sh/ruff/pull/17774))
- \[`pyupgrade`\] Add spaces between tokens as necessary to avoid syntax errors in `UP018` autofix ([#17648](https://github.com/astral-sh/ruff/pull/17648))
- \[`refurb`\] Fix false positive for float and complex numbers in `FURB116` ([#17661](https://github.com/astral-sh/ruff/pull/17661))
- [parser] Flag single unparenthesized generator expr with trailing comma in arguments. ([#17893](https://github.com/astral-sh/ruff/pull/17893))
### Documentation
- Add instructions on how to upgrade to a newer Rust version ([#17928](https://github.com/astral-sh/ruff/pull/17928))
- Update code of conduct email address ([#17875](https://github.com/astral-sh/ruff/pull/17875))
- Add fix safety sections to `PLC2801`, `PLR1722`, and `RUF013` ([#17825](https://github.com/astral-sh/ruff/pull/17825), [#17826](https://github.com/astral-sh/ruff/pull/17826), [#17759](https://github.com/astral-sh/ruff/pull/17759))
- Add link to `check-typed-exception` from `S110` and `S112` ([#17786](https://github.com/astral-sh/ruff/pull/17786))
### Other changes
- Allow passing a virtual environment to `ruff analyze graph` ([#17743](https://github.com/astral-sh/ruff/pull/17743))
## 0.11.8
### Preview features
- \[`airflow`\] Apply auto fixes to cases where the names have changed in Airflow 3 (`AIR302`, `AIR311`) ([#17553](https://github.com/astral-sh/ruff/pull/17553), [#17570](https://github.com/astral-sh/ruff/pull/17570), [#17571](https://github.com/astral-sh/ruff/pull/17571))
- \[`airflow`\] Extend `AIR301` rule ([#17598](https://github.com/astral-sh/ruff/pull/17598))
- \[`airflow`\] Update existing `AIR302` rules with better suggestions ([#17542](https://github.com/astral-sh/ruff/pull/17542))
- \[`refurb`\] Mark fix as safe for `readlines-in-for` (`FURB129`) ([#17644](https://github.com/astral-sh/ruff/pull/17644))
- [syntax-errors] `nonlocal` declaration at module level ([#17559](https://github.com/astral-sh/ruff/pull/17559))
- [syntax-errors] Detect single starred expression assignment `x = *y` ([#17624](https://github.com/astral-sh/ruff/pull/17624))
### Bug fixes
- \[`flake8-pyi`\] Ensure `Literal[None,] | Literal[None,]` is not autofixed to `None | None` (`PYI061`) ([#17659](https://github.com/astral-sh/ruff/pull/17659))
- \[`flake8-use-pathlib`\] Avoid suggesting `Path.iterdir()` for `os.listdir` with file descriptor (`PTH208`) ([#17715](https://github.com/astral-sh/ruff/pull/17715))
- \[`flake8-use-pathlib`\] Fix `PTH104` false positive when `rename` is passed a file descriptor ([#17712](https://github.com/astral-sh/ruff/pull/17712))
- \[`flake8-use-pathlib`\] Fix `PTH116` false positive when `stat` is passed a file descriptor ([#17709](https://github.com/astral-sh/ruff/pull/17709))
- \[`flake8-use-pathlib`\] Fix `PTH123` false positive when `open` is passed a file descriptor from a function call ([#17705](https://github.com/astral-sh/ruff/pull/17705))
- \[`pycodestyle`\] Fix duplicated diagnostic in `E712` ([#17651](https://github.com/astral-sh/ruff/pull/17651))
- \[`pylint`\] Detect `global` declarations in module scope (`PLE0118`) ([#17411](https://github.com/astral-sh/ruff/pull/17411))
- [syntax-errors] Make `async-comprehension-in-sync-comprehension` more specific ([#17460](https://github.com/astral-sh/ruff/pull/17460))
### Configuration
- Add option to disable `typing_extensions` imports ([#17611](https://github.com/astral-sh/ruff/pull/17611))
### Documentation
- Fix example syntax for the `lint.pydocstyle.ignore-var-parameters` option ([#17740](https://github.com/astral-sh/ruff/pull/17740))
- Add fix safety sections (`ASYNC116`, `FLY002`, `D200`, `RUF005`, `RUF017`, `RUF027`, `RUF028`, `RUF057`) ([#17497](https://github.com/astral-sh/ruff/pull/17497), [#17496](https://github.com/astral-sh/ruff/pull/17496), [#17502](https://github.com/astral-sh/ruff/pull/17502), [#17484](https://github.com/astral-sh/ruff/pull/17484), [#17480](https://github.com/astral-sh/ruff/pull/17480), [#17485](https://github.com/astral-sh/ruff/pull/17485), [#17722](https://github.com/astral-sh/ruff/pull/17722), [#17483](https://github.com/astral-sh/ruff/pull/17483))
### Other changes
- Add Python 3.14 to configuration options ([#17647](https://github.com/astral-sh/ruff/pull/17647))
- Make syntax error for unparenthesized except tuples version specific to before 3.14 ([#17660](https://github.com/astral-sh/ruff/pull/17660))
## 0.11.7
### Preview features
- \[`airflow`\] Apply auto fixes to cases where the names have changed in Airflow 3 (`AIR301`) ([#17355](https://github.com/astral-sh/ruff/pull/17355))
- \[`perflint`\] Implement fix for `manual-dict-comprehension` (`PERF403`) ([#16719](https://github.com/astral-sh/ruff/pull/16719))
- [syntax-errors] Make duplicate parameter names a semantic error ([#17131](https://github.com/astral-sh/ruff/pull/17131))
### Bug fixes
- \[`airflow`\] Fix typos in provider package names (`AIR302`, `AIR312`) ([#17574](https://github.com/astral-sh/ruff/pull/17574))
- \[`flake8-type-checking`\] Visit keyword arguments in checks involving `typing.cast`/`typing.NewType` arguments ([#17538](https://github.com/astral-sh/ruff/pull/17538))
- \[`pyupgrade`\] Preserve parenthesis when fixing native literals containing newlines (`UP018`) ([#17220](https://github.com/astral-sh/ruff/pull/17220))
- \[`refurb`\] Mark the `FURB161` fix unsafe except for integers and booleans ([#17240](https://github.com/astral-sh/ruff/pull/17240))
### Rule changes
- \[`perflint`\] Allow list function calls to be replaced with a comprehension (`PERF401`) ([#17519](https://github.com/astral-sh/ruff/pull/17519))
- \[`pycodestyle`\] Auto-fix redundant boolean comparison (`E712`) ([#17090](https://github.com/astral-sh/ruff/pull/17090))
- \[`pylint`\] make fix unsafe if delete comments (`PLR1730`) ([#17459](https://github.com/astral-sh/ruff/pull/17459))
### Documentation
- Add fix safety sections to docs for several rules ([#17410](https://github.com/astral-sh/ruff/pull/17410),[#17440](https://github.com/astral-sh/ruff/pull/17440),[#17441](https://github.com/astral-sh/ruff/pull/17441),[#17443](https://github.com/astral-sh/ruff/pull/17443),[#17444](https://github.com/astral-sh/ruff/pull/17444))
## 0.11.6
### Preview features
- Avoid adding whitespace to the end of a docstring after an escaped quote ([#17216](https://github.com/astral-sh/ruff/pull/17216))
- \[`airflow`\] Extract `AIR311` from `AIR301` rules (`AIR301`, `AIR311`) ([#17310](https://github.com/astral-sh/ruff/pull/17310), [#17422](https://github.com/astral-sh/ruff/pull/17422))
### Bug fixes
- Raise syntax error when `\` is at end of file ([#17409](https://github.com/astral-sh/ruff/pull/17409))
## 0.11.5
### Preview features
- \[`airflow`\] Add missing `AIR302` attribute check ([#17115](https://github.com/astral-sh/ruff/pull/17115))
- \[`airflow`\] Expand module path check to individual symbols (`AIR302`) ([#17278](https://github.com/astral-sh/ruff/pull/17278))
- \[`airflow`\] Extract `AIR312` from `AIR302` rules (`AIR302`, `AIR312`) ([#17152](https://github.com/astral-sh/ruff/pull/17152))
- \[`airflow`\] Update oudated `AIR301`, `AIR302` rules ([#17123](https://github.com/astral-sh/ruff/pull/17123))
- [syntax-errors] Async comprehension in sync comprehension ([#17177](https://github.com/astral-sh/ruff/pull/17177))
- [syntax-errors] Check annotations in annotated assignments ([#17283](https://github.com/astral-sh/ruff/pull/17283))
- [syntax-errors] Extend annotation checks to `await` ([#17282](https://github.com/astral-sh/ruff/pull/17282))
### Bug fixes
- \[`flake8-pie`\] Avoid false positive for multiple assignment with `auto()` (`PIE796`) ([#17274](https://github.com/astral-sh/ruff/pull/17274))
### Rule changes
- \[`ruff`\] Fix `RUF100` to detect unused file-level `noqa` directives with specific codes (#17042) ([#17061](https://github.com/astral-sh/ruff/pull/17061))
- \[`flake8-pytest-style`\] Avoid false positive for legacy form of `pytest.raises` (`PT011`) ([#17231](https://github.com/astral-sh/ruff/pull/17231))
### Documentation
- Fix formatting of "See Style Guide" link ([#17272](https://github.com/astral-sh/ruff/pull/17272))
## 0.11.4
### Preview features
- \[`ruff`\] Implement `invalid-rule-code` as `RUF102` ([#17138](https://github.com/astral-sh/ruff/pull/17138))
- [syntax-errors] Detect duplicate keys in `match` mapping patterns ([#17129](https://github.com/astral-sh/ruff/pull/17129))
- [syntax-errors] Detect duplicate attributes in `match` class patterns ([#17186](https://github.com/astral-sh/ruff/pull/17186))
- [syntax-errors] Detect invalid syntax in annotations ([#17101](https://github.com/astral-sh/ruff/pull/17101))
### Bug fixes
- [syntax-errors] Fix multiple assignment error for class fields in `match` patterns ([#17184](https://github.com/astral-sh/ruff/pull/17184))
- Don't skip visiting non-tuple slice in `typing.Annotated` subscripts ([#17201](https://github.com/astral-sh/ruff/pull/17201))
## 0.11.3
### Preview features
- \[`airflow`\] Add more autofixes for `AIR302` ([#16876](https://github.com/astral-sh/ruff/pull/16876), [#16977](https://github.com/astral-sh/ruff/pull/16977), [#16976](https://github.com/astral-sh/ruff/pull/16976), [#16965](https://github.com/astral-sh/ruff/pull/16965))
- \[`airflow`\] Move `AIR301` to `AIR002` ([#16978](https://github.com/astral-sh/ruff/pull/16978))
- \[`airflow`\] Move `AIR302` to `AIR301` and `AIR303` to `AIR302` ([#17151](https://github.com/astral-sh/ruff/pull/17151))
- \[`flake8-bandit`\] Mark `str` and `list[str]` literals as trusted input (`S603`) ([#17136](https://github.com/astral-sh/ruff/pull/17136))
- \[`ruff`\] Support slices in `RUF005` ([#17078](https://github.com/astral-sh/ruff/pull/17078))
- [syntax-errors] Start detecting compile-time syntax errors ([#16106](https://github.com/astral-sh/ruff/pull/16106))
- [syntax-errors] Duplicate type parameter names ([#16858](https://github.com/astral-sh/ruff/pull/16858))
- [syntax-errors] Irrefutable `case` pattern before final case ([#16905](https://github.com/astral-sh/ruff/pull/16905))
- [syntax-errors] Multiple assignments in `case` pattern ([#16957](https://github.com/astral-sh/ruff/pull/16957))
- [syntax-errors] Single starred assignment target ([#17024](https://github.com/astral-sh/ruff/pull/17024))
- [syntax-errors] Starred expressions in `return`, `yield`, and `for` ([#17134](https://github.com/astral-sh/ruff/pull/17134))
- [syntax-errors] Store to or delete `__debug__` ([#16984](https://github.com/astral-sh/ruff/pull/16984))
### Bug fixes
- Error instead of `panic!` when running Ruff from a deleted directory (#16903) ([#17054](https://github.com/astral-sh/ruff/pull/17054))
- [syntax-errors] Fix false positive for parenthesized tuple index ([#16948](https://github.com/astral-sh/ruff/pull/16948))
### CLI
- Check `pyproject.toml` correctly when it is passed via stdin ([#16971](https://github.com/astral-sh/ruff/pull/16971))
### Configuration
- \[`flake8-import-conventions`\] Add import `numpy.typing as npt` to default `flake8-import-conventions.aliases` ([#17133](https://github.com/astral-sh/ruff/pull/17133))
### Documentation
- \[`refurb`\] Document why `UserDict`, `UserList`, and `UserString` are preferred over `dict`, `list`, and `str` (`FURB189`) ([#16927](https://github.com/astral-sh/ruff/pull/16927))
## 0.11.2
### Preview features
- [syntax-errors] Fix false-positive syntax errors emitted for annotations on variadic parameters before Python 3.11 ([#16878](https://github.com/astral-sh/ruff/pull/16878))
## 0.11.1
### Preview features
- \[`airflow`\] Add `chain`, `chain_linear` and `cross_downstream` for `AIR302` ([#16647](https://github.com/astral-sh/ruff/pull/16647))
- [syntax-errors] Improve error message and range for pre-PEP-614 decorator syntax errors ([#16581](https://github.com/astral-sh/ruff/pull/16581))
- [syntax-errors] PEP 701 f-strings before Python 3.12 ([#16543](https://github.com/astral-sh/ruff/pull/16543))
- [syntax-errors] Parenthesized context managers before Python 3.9 ([#16523](https://github.com/astral-sh/ruff/pull/16523))
- [syntax-errors] Star annotations before Python 3.11 ([#16545](https://github.com/astral-sh/ruff/pull/16545))
- [syntax-errors] Star expression in index before Python 3.11 ([#16544](https://github.com/astral-sh/ruff/pull/16544))
- [syntax-errors] Unparenthesized assignment expressions in sets and indexes ([#16404](https://github.com/astral-sh/ruff/pull/16404))
### Bug fixes
- Server: Allow `FixAll` action in presence of version-specific syntax errors ([#16848](https://github.com/astral-sh/ruff/pull/16848))
- \[`flake8-bandit`\] Allow raw strings in `suspicious-mark-safe-usage` (`S308`) #16702 ([#16770](https://github.com/astral-sh/ruff/pull/16770))
- \[`refurb`\] Avoid panicking `unwrap` in `verbose-decimal-constructor` (`FURB157`) ([#16777](https://github.com/astral-sh/ruff/pull/16777))
- \[`refurb`\] Fix starred expressions fix (`FURB161`) ([#16550](https://github.com/astral-sh/ruff/pull/16550))
- Fix `--statistics` reporting for unsafe fixes ([#16756](https://github.com/astral-sh/ruff/pull/16756))
### Rule changes
- \[`flake8-executables`\] Allow `uv run` in shebang line for `shebang-missing-python` (`EXE003`) ([#16849](https://github.com/astral-sh/ruff/pull/16849),[#16855](https://github.com/astral-sh/ruff/pull/16855))
### CLI
- Add `--exit-non-zero-on-format` ([#16009](https://github.com/astral-sh/ruff/pull/16009))
### Documentation
- Update Ruff tutorial to avoid non-existent fix in `__init__.py` ([#16818](https://github.com/astral-sh/ruff/pull/16818))
- \[`flake8-gettext`\] Swap `format-` and `printf-in-get-text-func-call` examples (`INT002`, `INT003`) ([#16769](https://github.com/astral-sh/ruff/pull/16769))
## 0.11.0
This is a follow-up to release 0.10.0. Because of a mistake in the release process, the `requires-python` inference changes were not included in that release. Ruff 0.11.0 now includes this change as well as the stabilization of the preview behavior for `PGH004`.
### Breaking changes
- **Changes to how the Python version is inferred when a `target-version` is not specified** ([#16319](https://github.com/astral-sh/ruff/pull/16319))
In previous versions of Ruff, you could specify your Python version with:
- The `target-version` option in a `ruff.toml` file or the `[tool.ruff]` section of a pyproject.toml file.
- The `project.requires-python` field in a `pyproject.toml` file with a `[tool.ruff]` section.
These options worked well in most cases, and are still recommended for fine control of the Python version. However, because of the way Ruff discovers config files, `pyproject.toml` files without a `[tool.ruff]` section would be ignored, including the `requires-python` setting. Ruff would then use the default Python version (3.9 as of this writing) instead, which is surprising when you've attempted to request another version.
In v0.10, config discovery has been updated to address this issue:
- If Ruff finds a `ruff.toml` file without a `target-version`, it will check
for a `pyproject.toml` file in the same directory and respect its
`requires-python` version, even if it does not contain a `[tool.ruff]`
section.
- If Ruff finds a user-level configuration, the `requires-python` field of the closest `pyproject.toml` in a parent directory will take precedence.
- If there is no config file (`ruff.toml`or `pyproject.toml` with a
`[tool.ruff]` section) in the directory of the file being checked, Ruff will
search for the closest `pyproject.toml` in the parent directories and use its
`requires-python` setting.
### Stabilization
The following behaviors have been stabilized:
- [`blanket-noqa`](https://docs.astral.sh/ruff/rules/blanket-noqa/) (`PGH004`): Also detect blanked file-level noqa comments (and not just line level comments).
### Preview features
- [syntax-errors] Tuple unpacking in `for` statement iterator clause before Python 3.9 ([#16558](https://github.com/astral-sh/ruff/pull/16558))
## 0.10.0
Check out the [blog post](https://astral.sh/blog/ruff-v0.10.0) for a migration guide and overview of the changes!
### Breaking changes
See also, the "Remapped rules" section which may result in disabled rules.
- **Changes to how the Python version is inferred when a `target-version` is not specified** ([#16319](https://github.com/astral-sh/ruff/pull/16319))
Because of a mistake in the release process, the `requires-python` inference changes are not included in this release and instead shipped as part of 0.11.0.
You can find a description of this change in the 0.11.0 section.
- **Updated `TYPE_CHECKING` behavior** ([#16669](https://github.com/astral-sh/ruff/pull/16669))
Previously, Ruff only recognized typechecking blocks that tested the `typing.TYPE_CHECKING` symbol. Now, Ruff recognizes any local variable named `TYPE_CHECKING`. This release also removes support for the legacy `if 0:` and `if False:` typechecking checks. Use a local `TYPE_CHECKING` variable instead.
- **More robust noqa parsing** ([#16483](https://github.com/astral-sh/ruff/pull/16483))
The syntax for both file-level and in-line suppression comments has been unified and made more robust to certain errors. In most cases, this will result in more suppression comments being read by Ruff, but there are a few instances where previously read comments will now log an error to the user instead. Please refer to the documentation on [*Error suppression*](https://docs.astral.sh/ruff/linter/#error-suppression) for the full specification.
- **Avoid unnecessary parentheses around with statements with a single context manager and a trailing comment** ([#14005](https://github.com/astral-sh/ruff/pull/14005))
This change fixes a bug in the formatter where it introduced unnecessary parentheses around with statements with a single context manager and a trailing comment. This change may result in a change in formatting for some users.
- **Bump alpine default tag to 3.21 for derived Docker images** ([#16456](https://github.com/astral-sh/ruff/pull/16456))
Alpine 3.21 was released in Dec 2024 and is used in the official Alpine-based Python images. Now the ruff:alpine image will use 3.21 instead of 3.20 and ruff:alpine3.20 will no longer be updated.
### Deprecated Rules
The following rules have been deprecated:
- [`non-pep604-isinstance`](https://docs.astral.sh/ruff/rules/non-pep604-isinstance/) (`UP038`)
- [`suspicious-xmle-tree-usage`](https://docs.astral.sh/ruff/rules/suspicious-xmle-tree-usage/) (`S320`)
### Remapped rules
The following rules have been remapped to new rule codes:
- \[`unsafe-markup-use`\]: `RUF035` to `S704`
### Stabilization
The following rules have been stabilized and are no longer in preview:
- [`batched-without-explicit-strict`](https://docs.astral.sh/ruff/rules/batched-without-explicit-strict) (`B911`)
- [`unnecessary-dict-comprehension-for-iterable`](https://docs.astral.sh/ruff/rules/unnecessary-dict-comprehension-for-iterable) (`C420`)
- [`datetime-min-max`](https://docs.astral.sh/ruff/rules/datetime-min-max) (`DTZ901`)
- [`fast-api-unused-path-parameter`](https://docs.astral.sh/ruff/rules/fast-api-unused-path-parameter) (`FAST003`)
- [`root-logger-call`](https://docs.astral.sh/ruff/rules/root-logger-call) (`LOG015`)
- [`len-test`](https://docs.astral.sh/ruff/rules/len-test) (`PLC1802`)
- [`shallow-copy-environ`](https://docs.astral.sh/ruff/rules/shallow-copy-environ) (`PLW1507`)
- [`os-listdir`](https://docs.astral.sh/ruff/rules/os-listdir) (`PTH208`)
- [`invalid-pathlib-with-suffix`](https://docs.astral.sh/ruff/rules/invalid-pathlib-with-suffix) (`PTH210`)
- [`invalid-assert-message-literal-argument`](https://docs.astral.sh/ruff/rules/invalid-assert-message-literal-argument) (`RUF040`)
- [`unnecessary-nested-literal`](https://docs.astral.sh/ruff/rules/unnecessary-nested-literal) (`RUF041`)
- [`unnecessary-cast-to-int`](https://docs.astral.sh/ruff/rules/unnecessary-cast-to-int) (`RUF046`)
- [`map-int-version-parsing`](https://docs.astral.sh/ruff/rules/map-int-version-parsing) (`RUF048`)
- [`if-key-in-dict-del`](https://docs.astral.sh/ruff/rules/if-key-in-dict-del) (`RUF051`)
- [`unsafe-markup-use`](https://docs.astral.sh/ruff/rules/unsafe-markup-use) (`S704`). This rule has also been renamed from `RUF035`.
- [`split-static-string`](https://docs.astral.sh/ruff/rules/split-static-string) (`SIM905`)
- [`runtime-cast-value`](https://docs.astral.sh/ruff/rules/runtime-cast-value) (`TC006`)
- [`unquoted-type-alias`](https://docs.astral.sh/ruff/rules/unquoted-type-alias) (`TC007`)
- [`non-pep646-unpack`](https://docs.astral.sh/ruff/rules/non-pep646-unpack) (`UP044`)
The following behaviors have been stabilized:
- [`bad-staticmethod-argument`](https://docs.astral.sh/ruff/rules/bad-staticmethod-argument/) (`PLW0211`) [`invalid-first-argument-name-for-class-method`](https://docs.astral.sh/ruff/rules/invalid-first-argument-name-for-class-method/) (`N804`): `__new__` methods are now no longer flagged by `invalid-first-argument-name-for-class-method` (`N804`) but instead by `bad-staticmethod-argument` (`PLW0211`)
- [`bad-str-strip-call`](https://docs.astral.sh/ruff/rules/bad-str-strip-call/) (`PLE1310`): The rule now applies to objects which are known to have type `str` or `bytes`.
- [`custom-type-var-for-self`](https://docs.astral.sh/ruff/rules/custom-type-var-for-self/) (`PYI019`): More accurate detection of custom `TypeVars` replaceable by `Self`. The range of the diagnostic is now the full function header rather than just the return annotation.
- [`invalid-argument-name`](https://docs.astral.sh/ruff/rules/invalid-argument-name/) (`N803`): Ignore argument names of functions decorated with `typing.override`
- [`invalid-envvar-default`](https://docs.astral.sh/ruff/rules/invalid-envvar-default/) (`PLW1508`): Detect default value arguments to `os.environ.get` with invalid type.
- [`pytest-raises-with-multiple-statements`](https://docs.astral.sh/ruff/rules/pytest-raises-with-multiple-statements/) (`PT012`) [`pytest-warns-with-multiple-statements`](https://docs.astral.sh/ruff/rules/pytest-warns-with-multiple-statements/) (`PT031`): Allow `for` statements with an empty body in `pytest.raises` and `pytest.warns` `with` statements.
- [`redundant-open-modes`](https://docs.astral.sh/ruff/rules/redundant-open-modes/) (`UP015`): The diagnostic range is now the range of the redundant mode argument where it previously was the range of the entire open call. You may have to replace your `noqa` comments when suppressing `UP015`.
- [`stdlib-module-shadowing`](https://docs.astral.sh/ruff/rules/stdlib-module-shadowing/) (`A005`): Changes the default value of `lint.flake8-builtins.strict-checking` from `true` to `false`.
- [`type-none-comparison`](https://docs.astral.sh/ruff/rules/type-none-comparison/) (`FURB169`): Now also recognizes `type(expr) is type(None)` comparisons where `expr` isn't a name expression.
The following fixes or improvements to fixes have been stabilized:
- [`repeated-equality-comparison`](https://docs.astral.sh/ruff/rules/repeated-equality-comparison/) (`PLR1714`) ([#16685](https://github.com/astral-sh/ruff/pull/16685))
- [`needless-bool`](https://docs.astral.sh/ruff/rules/needless-bool/) (`SIM103`) ([#16684](https://github.com/astral-sh/ruff/pull/16684))
- [`unused-private-type-var`](https://docs.astral.sh/ruff/rules/unused-private-type-var/) (`PYI018`) ([#16682](https://github.com/astral-sh/ruff/pull/16682))
### Server
- Remove logging output for `ruff.printDebugInformation` ([#16617](https://github.com/astral-sh/ruff/pull/16617))
### Configuration
- \[`flake8-builtins`\] Deprecate the `builtins-` prefixed options in favor of the unprefixed options (e.g. `builtins-allowed-modules` is now deprecated in favor of `allowed-modules`) ([#16092](https://github.com/astral-sh/ruff/pull/16092))
### Bug fixes
- [flake8-bandit] Fix mixed-case hash algorithm names (S324) ([#16552](https://github.com/astral-sh/ruff/pull/16552))
### CLI
- [ruff] Fix `last_tag`/`commits_since_last_tag` for `version` command ([#16686](https://github.com/astral-sh/ruff/pull/16686))
## 0.9.10
### Preview features
- \[`ruff`\] Add new rule `RUF059`: Unused unpacked assignment ([#16449](https://github.com/astral-sh/ruff/pull/16449))
- \[`syntax-errors`\] Detect assignment expressions before Python 3.8 ([#16383](https://github.com/astral-sh/ruff/pull/16383))
- \[`syntax-errors`\] Named expressions in decorators before Python 3.9 ([#16386](https://github.com/astral-sh/ruff/pull/16386))
- \[`syntax-errors`\] Parenthesized keyword argument names after Python 3.8 ([#16482](https://github.com/astral-sh/ruff/pull/16482))
- \[`syntax-errors`\] Positional-only parameters before Python 3.8 ([#16481](https://github.com/astral-sh/ruff/pull/16481))
- \[`syntax-errors`\] Tuple unpacking in `return` and `yield` before Python 3.8 ([#16485](https://github.com/astral-sh/ruff/pull/16485))
- \[`syntax-errors`\] Type parameter defaults before Python 3.13 ([#16447](https://github.com/astral-sh/ruff/pull/16447))
- \[`syntax-errors`\] Type parameter lists before Python 3.12 ([#16479](https://github.com/astral-sh/ruff/pull/16479))
- \[`syntax-errors`\] `except*` before Python 3.11 ([#16446](https://github.com/astral-sh/ruff/pull/16446))
- \[`syntax-errors`\] `type` statements before Python 3.12 ([#16478](https://github.com/astral-sh/ruff/pull/16478))
### Bug fixes
- Escape template filenames in glob patterns in configuration ([#16407](https://github.com/astral-sh/ruff/pull/16407))
- \[`flake8-simplify`\] Exempt unittest context methods for `SIM115` rule ([#16439](https://github.com/astral-sh/ruff/pull/16439))
- Formatter: Fix syntax error location in notebooks ([#16499](https://github.com/astral-sh/ruff/pull/16499))
- \[`pyupgrade`\] Do not offer fix when at least one target is `global`/`nonlocal` (`UP028`) ([#16451](https://github.com/astral-sh/ruff/pull/16451))
- \[`flake8-builtins`\] Ignore variables matching module attribute names (`A001`) ([#16454](https://github.com/astral-sh/ruff/pull/16454))
- \[`pylint`\] Convert `code` keyword argument to a positional argument in fix for (`PLR1722`) ([#16424](https://github.com/astral-sh/ruff/pull/16424))
### CLI
- Move rule code from `description` to `check_name` in GitLab output serializer ([#16437](https://github.com/astral-sh/ruff/pull/16437))
### Documentation
- \[`pydocstyle`\] Clarify that `D417` only checks docstrings with an arguments section ([#16494](https://github.com/astral-sh/ruff/pull/16494))
## 0.9.9
### Preview features
- Fix caching of unsupported-syntax errors ([#16425](https://github.com/astral-sh/ruff/pull/16425))
### Bug fixes
- Only show unsupported-syntax errors in editors when preview mode is enabled ([#16429](https://github.com/astral-sh/ruff/pull/16429))
## 0.9.8
### Preview features
- Start detecting version-related syntax errors in the parser ([#16090](https://github.com/astral-sh/ruff/pull/16090))
### Rule changes
- \[`pylint`\] Mark fix unsafe (`PLW1507`) ([#16343](https://github.com/astral-sh/ruff/pull/16343))
- \[`pylint`\] Catch `case np.nan`/`case math.nan` in `match` statements (`PLW0177`) ([#16378](https://github.com/astral-sh/ruff/pull/16378))
- \[`ruff`\] Add more Pydantic models variants to the list of default copy semantics (`RUF012`) ([#16291](https://github.com/astral-sh/ruff/pull/16291))
### Server
- Avoid indexing the project if `configurationPreference` is `editorOnly` ([#16381](https://github.com/astral-sh/ruff/pull/16381))
- Avoid unnecessary info at non-trace server log level ([#16389](https://github.com/astral-sh/ruff/pull/16389))
- Expand `ruff.configuration` to allow inline config ([#16296](https://github.com/astral-sh/ruff/pull/16296))
- Notify users for invalid client settings ([#16361](https://github.com/astral-sh/ruff/pull/16361))
### Configuration
- Add `per-file-target-version` option ([#16257](https://github.com/astral-sh/ruff/pull/16257))
### Bug fixes
- \[`refurb`\] Do not consider docstring(s) (`FURB156`) ([#16391](https://github.com/astral-sh/ruff/pull/16391))
- \[`flake8-self`\] Ignore attribute accesses on instance-like variables (`SLF001`) ([#16149](https://github.com/astral-sh/ruff/pull/16149))
- \[`pylint`\] Fix false positives, add missing methods, and support positional-only parameters (`PLE0302`) ([#16263](https://github.com/astral-sh/ruff/pull/16263))
- \[`flake8-pyi`\] Mark `PYI030` fix unsafe when comments are deleted ([#16322](https://github.com/astral-sh/ruff/pull/16322))
### Documentation
- Fix example for `S611` ([#16316](https://github.com/astral-sh/ruff/pull/16316))
- Normalize inconsistent markdown headings in docstrings ([#16364](https://github.com/astral-sh/ruff/pull/16364))
- Document MSRV policy ([#16384](https://github.com/astral-sh/ruff/pull/16384))
## 0.9.7
### Preview features
- Consider `__new__` methods as special function type for enforcing class method or static method rules ([#13305](https://github.com/astral-sh/ruff/pull/13305))
- \[`airflow`\] Improve the internal logic to differentiate deprecated symbols (`AIR303`) ([#16013](https://github.com/astral-sh/ruff/pull/16013))
- \[`refurb`\] Manual timezone monkeypatching (`FURB162`) ([#16113](https://github.com/astral-sh/ruff/pull/16113))
- \[`ruff`\] Implicit class variable in dataclass (`RUF045`) ([#14349](https://github.com/astral-sh/ruff/pull/14349))
- \[`ruff`\] Skip singleton starred expressions for `incorrectly-parenthesized-tuple-in-subscript` (`RUF031`) ([#16083](https://github.com/astral-sh/ruff/pull/16083))
- \[`refurb`\] Check for subclasses includes subscript expressions (`FURB189`) ([#16155](https://github.com/astral-sh/ruff/pull/16155))
### Rule changes
- \[`flake8-debugger`\] Also flag `sys.breakpointhook` and `sys.__breakpointhook__` (`T100`) ([#16191](https://github.com/astral-sh/ruff/pull/16191))
- \[`pycodestyle`\] Exempt `site.addsitedir(...)` calls (`E402`) ([#16251](https://github.com/astral-sh/ruff/pull/16251))
### Formatter
- Fix unstable formatting of trailing end-of-line comments of parenthesized attribute values ([#16187](https://github.com/astral-sh/ruff/pull/16187))
### Server
- Fix handling of requests received after shutdown message ([#16262](https://github.com/astral-sh/ruff/pull/16262))
- Ignore `source.organizeImports.ruff` and `source.fixAll.ruff` code actions for a notebook cell ([#16154](https://github.com/astral-sh/ruff/pull/16154))
- Include document specific debug info for `ruff.printDebugInformation` ([#16215](https://github.com/astral-sh/ruff/pull/16215))
- Update server to return the debug info as string with `ruff.printDebugInformation` ([#16214](https://github.com/astral-sh/ruff/pull/16214))
### CLI
- Warn on invalid `noqa` even when there are no diagnostics ([#16178](https://github.com/astral-sh/ruff/pull/16178))
- Better error messages while loading configuration `extend`s ([#15658](https://github.com/astral-sh/ruff/pull/15658))
### Bug fixes
- \[`flake8-comprehensions`\] Handle trailing comma in `C403` fix ([#16110](https://github.com/astral-sh/ruff/pull/16110))
- \[`flake8-pyi`\] Avoid flagging `custom-typevar-for-self` on metaclass methods (`PYI019`) ([#16141](https://github.com/astral-sh/ruff/pull/16141))
- \[`pydocstyle`\] Handle arguments with the same names as sections (`D417`) ([#16011](https://github.com/astral-sh/ruff/pull/16011))
- \[`pylint`\] Correct ordering of arguments in fix for `if-stmt-min-max` (`PLR1730`) ([#16080](https://github.com/astral-sh/ruff/pull/16080))
- \[`pylint`\] Do not offer fix for raw strings (`PLE251`) ([#16132](https://github.com/astral-sh/ruff/pull/16132))
- \[`pyupgrade`\] Do not upgrade functional `TypedDicts` with private field names to the class-based syntax (`UP013`) ([#16219](https://github.com/astral-sh/ruff/pull/16219))
- \[`pyupgrade`\] Handle micro version numbers correctly (`UP036`) ([#16091](https://github.com/astral-sh/ruff/pull/16091))
- \[`pyupgrade`\] Unwrap unary expressions correctly (`UP018`) ([#15919](https://github.com/astral-sh/ruff/pull/15919))
- \[`refurb`\] Correctly handle lengths of literal strings in `slice-to-remove-prefix-or-suffix` (`FURB188`) ([#16237](https://github.com/astral-sh/ruff/pull/16237))
- \[`ruff`\] Skip `RUF001` diagnostics when visiting string type definitions ([#16122](https://github.com/astral-sh/ruff/pull/16122))
### Documentation
- Add FAQ entry for `source.*` code actions in Notebook ([#16212](https://github.com/astral-sh/ruff/pull/16212))
- Add `SECURITY.md` ([#16224](https://github.com/astral-sh/ruff/pull/16224))
## 0.9.6
### Preview features
- \[`airflow`\] Add `external_task.{ExternalTaskMarker, ExternalTaskSensor}` for `AIR302` ([#16014](https://github.com/astral-sh/ruff/pull/16014))
- \[`flake8-builtins`\] Make strict module name comparison optional (`A005`) ([#15951](https://github.com/astral-sh/ruff/pull/15951))
- \[`flake8-pyi`\] Extend fix to Python \<= 3.9 for `redundant-none-literal` (`PYI061`) ([#16044](https://github.com/astral-sh/ruff/pull/16044))
- \[`pylint`\] Also report when the object isn't a literal (`PLE1310`) ([#15985](https://github.com/astral-sh/ruff/pull/15985))
- \[`ruff`\] Implement `indented-form-feed` (`RUF054`) ([#16049](https://github.com/astral-sh/ruff/pull/16049))
- \[`ruff`\] Skip type definitions for `missing-f-string-syntax` (`RUF027`) ([#16054](https://github.com/astral-sh/ruff/pull/16054))
### Rule changes
- \[`flake8-annotations`\] Correct syntax for `typing.Union` in suggested return type fixes for `ANN20x` rules ([#16025](https://github.com/astral-sh/ruff/pull/16025))
- \[`flake8-builtins`\] Match upstream module name comparison (`A005`) ([#16006](https://github.com/astral-sh/ruff/pull/16006))
- \[`flake8-comprehensions`\] Detect overshadowed `list`/`set`/`dict`, ignore variadics and named expressions (`C417`) ([#15955](https://github.com/astral-sh/ruff/pull/15955))
- \[`flake8-pie`\] Remove following comma correctly when the unpacked dictionary is empty (`PIE800`) ([#16008](https://github.com/astral-sh/ruff/pull/16008))
- \[`flake8-simplify`\] Only trigger `SIM401` on known dictionaries ([#15995](https://github.com/astral-sh/ruff/pull/15995))
- \[`pylint`\] Do not report calls when object type and argument type mismatch, remove custom escape handling logic (`PLE1310`) ([#15984](https://github.com/astral-sh/ruff/pull/15984))
- \[`pyupgrade`\] Comments within parenthesized value ranges should not affect applicability (`UP040`) ([#16027](https://github.com/astral-sh/ruff/pull/16027))
- \[`pyupgrade`\] Don't introduce invalid syntax when upgrading old-style type aliases with parenthesized multiline values (`UP040`) ([#16026](https://github.com/astral-sh/ruff/pull/16026))
- \[`pyupgrade`\] Ensure we do not rename two type parameters to the same name (`UP049`) ([#16038](https://github.com/astral-sh/ruff/pull/16038))
- \[`pyupgrade`\] \[`ruff`\] Don't apply renamings if the new name is shadowed in a scope of one of the references to the binding (`UP049`, `RUF052`) ([#16032](https://github.com/astral-sh/ruff/pull/16032))
- \[`ruff`\] Update `RUF009` to behave similar to `B008` and ignore attributes with immutable types ([#16048](https://github.com/astral-sh/ruff/pull/16048))
### Server
- Root exclusions in the server to project root ([#16043](https://github.com/astral-sh/ruff/pull/16043))
### Bug fixes
- \[`flake8-datetime`\] Ignore `.replace()` calls while looking for `.astimezone` ([#16050](https://github.com/astral-sh/ruff/pull/16050))
- \[`flake8-type-checking`\] Avoid `TC004` false positive where the runtime definition is provided by `__getattr__` ([#16052](https://github.com/astral-sh/ruff/pull/16052))
### Documentation
- Improve `ruff-lsp` migration document ([#16072](https://github.com/astral-sh/ruff/pull/16072))
- Undeprecate `ruff.nativeServer` ([#16039](https://github.com/astral-sh/ruff/pull/16039))
## 0.9.5
### Preview features
- Recognize all symbols named `TYPE_CHECKING` for `in_type_checking_block` ([#15719](https://github.com/astral-sh/ruff/pull/15719))
- \[`flake8-comprehensions`\] Handle builtins at top of file correctly for `unnecessary-dict-comprehension-for-iterable` (`C420`) ([#15837](https://github.com/astral-sh/ruff/pull/15837))
- \[`flake8-logging`\] `.exception()` and `exc_info=` outside exception handlers (`LOG004`, `LOG014`) ([#15799](https://github.com/astral-sh/ruff/pull/15799))
- \[`flake8-pyi`\] Fix incorrect behaviour of `custom-typevar-return-type` preview-mode autofix if `typing` was already imported (`PYI019`) ([#15853](https://github.com/astral-sh/ruff/pull/15853))
- \[`flake8-pyi`\] Fix more complex cases (`PYI019`) ([#15821](https://github.com/astral-sh/ruff/pull/15821))
- \[`flake8-pyi`\] Make `PYI019` autofixable for `.py` files in preview mode as well as stubs ([#15889](https://github.com/astral-sh/ruff/pull/15889))
- \[`flake8-pyi`\] Remove type parameter correctly when it is the last (`PYI019`) ([#15854](https://github.com/astral-sh/ruff/pull/15854))
- \[`pylint`\] Fix missing parens in unsafe fix for `unnecessary-dunder-call` (`PLC2801`) ([#15762](https://github.com/astral-sh/ruff/pull/15762))
- \[`pyupgrade`\] Better messages and diagnostic range (`UP015`) ([#15872](https://github.com/astral-sh/ruff/pull/15872))
- \[`pyupgrade`\] Rename private type parameters in PEP 695 generics (`UP049`) ([#15862](https://github.com/astral-sh/ruff/pull/15862))
- \[`refurb`\] Also report non-name expressions (`FURB169`) ([#15905](https://github.com/astral-sh/ruff/pull/15905))
- \[`refurb`\] Mark fix as unsafe if there are comments (`FURB171`) ([#15832](https://github.com/astral-sh/ruff/pull/15832))
- \[`ruff`\] Classes with mixed type variable style (`RUF053`) ([#15841](https://github.com/astral-sh/ruff/pull/15841))
- \[`airflow`\] `BashOperator` has been moved to `airflow.providers.standard.operators.bash.BashOperator` (`AIR302`) ([#15922](https://github.com/astral-sh/ruff/pull/15922))
- \[`flake8-pyi`\] Add autofix for unused-private-type-var (`PYI018`) ([#15999](https://github.com/astral-sh/ruff/pull/15999))
- \[`flake8-pyi`\] Significantly improve accuracy of `PYI019` if preview mode is enabled ([#15888](https://github.com/astral-sh/ruff/pull/15888))
### Rule changes
- Preserve triple quotes and prefixes for strings ([#15818](https://github.com/astral-sh/ruff/pull/15818))
- \[`flake8-comprehensions`\] Skip when `TypeError` present from too many (kw)args for `C410`,`C411`, and `C418` ([#15838](https://github.com/astral-sh/ruff/pull/15838))
- \[`flake8-pyi`\] Rename `PYI019` and improve its diagnostic message ([#15885](https://github.com/astral-sh/ruff/pull/15885))
- \[`pep8-naming`\] Ignore `@override` methods (`N803`) ([#15954](https://github.com/astral-sh/ruff/pull/15954))
- \[`pyupgrade`\] Reuse replacement logic from `UP046` and `UP047` to preserve more comments (`UP040`) ([#15840](https://github.com/astral-sh/ruff/pull/15840))
- \[`ruff`\] Analyze deferred annotations before enforcing `mutable-(data)class-default` and `function-call-in-dataclass-default-argument` (`RUF008`,`RUF009`,`RUF012`) ([#15921](https://github.com/astral-sh/ruff/pull/15921))
- \[`pycodestyle`\] Exempt `sys.path += ...` calls (`E402`) ([#15980](https://github.com/astral-sh/ruff/pull/15980))
### Configuration
- Config error only when `flake8-import-conventions` alias conflicts with `isort.required-imports` bound name ([#15918](https://github.com/astral-sh/ruff/pull/15918))
- Workaround Even Better TOML crash related to `allOf` ([#15992](https://github.com/astral-sh/ruff/pull/15992))
### Bug fixes
- \[`flake8-comprehensions`\] Unnecessary `list` comprehension (rewrite as a `set` comprehension) (`C403`) - Handle extraneous parentheses around list comprehension ([#15877](https://github.com/astral-sh/ruff/pull/15877))
- \[`flake8-comprehensions`\] Handle trailing comma in fixes for `unnecessary-generator-list/set` (`C400`,`C401`) ([#15929](https://github.com/astral-sh/ruff/pull/15929))
- \[`flake8-pyi`\] Fix several correctness issues with `custom-type-var-return-type` (`PYI019`) ([#15851](https://github.com/astral-sh/ruff/pull/15851))
- \[`pep8-naming`\] Consider any number of leading underscore for `N801` ([#15988](https://github.com/astral-sh/ruff/pull/15988))
- \[`pyflakes`\] Visit forward annotations in `TypeAliasType` as types (`F401`) ([#15829](https://github.com/astral-sh/ruff/pull/15829))
- \[`pylint`\] Correct min/max auto-fix and suggestion for (`PL1730`) ([#15930](https://github.com/astral-sh/ruff/pull/15930))
- \[`refurb`\] Handle unparenthesized tuples correctly (`FURB122`, `FURB142`) ([#15953](https://github.com/astral-sh/ruff/pull/15953))
- \[`refurb`\] Avoid `None | None` as well as better detection and fix (`FURB168`) ([#15779](https://github.com/astral-sh/ruff/pull/15779))
### Documentation
- Add deprecation warning for `ruff-lsp` related settings ([#15850](https://github.com/astral-sh/ruff/pull/15850))
- Docs (`linter.md`): clarify that Python files are always searched for in subdirectories ([#15882](https://github.com/astral-sh/ruff/pull/15882))
- Fix a typo in `non_pep695_generic_class.rs` ([#15946](https://github.com/astral-sh/ruff/pull/15946))
- Improve Docs: Pylint subcategories' codes ([#15909](https://github.com/astral-sh/ruff/pull/15909))
- Remove non-existing `lint.extendIgnore` editor setting ([#15844](https://github.com/astral-sh/ruff/pull/15844))
- Update black deviations ([#15928](https://github.com/astral-sh/ruff/pull/15928))
- Mention `UP049` in `UP046` and `UP047`, add `See also` section to `UP040` ([#15956](https://github.com/astral-sh/ruff/pull/15956))
- Add instance variable examples to `RUF012` ([#15982](https://github.com/astral-sh/ruff/pull/15982))
- Explain precedence for `ignore` and `select` config ([#15883](https://github.com/astral-sh/ruff/pull/15883))
## 0.9.4
### Preview features
- \[`airflow`\] Extend airflow context parameter check for `BaseOperator.execute` (`AIR302`) ([#15713](https://github.com/astral-sh/ruff/pull/15713))
- \[`airflow`\] Update `AIR302` to check for deprecated context keys ([#15144](https://github.com/astral-sh/ruff/pull/15144))
- \[`flake8-bandit`\] Permit suspicious imports within stub files (`S4`) ([#15822](https://github.com/astral-sh/ruff/pull/15822))
- \[`pylint`\] Do not trigger `PLR6201` on empty collections ([#15732](https://github.com/astral-sh/ruff/pull/15732))
- \[`refurb`\] Do not emit diagnostic when loop variables are used outside loop body (`FURB122`) ([#15757](https://github.com/astral-sh/ruff/pull/15757))
- \[`ruff`\] Add support for more `re` patterns (`RUF055`) ([#15764](https://github.com/astral-sh/ruff/pull/15764))
- \[`ruff`\] Check for shadowed `map` before suggesting fix (`RUF058`) ([#15790](https://github.com/astral-sh/ruff/pull/15790))
- \[`ruff`\] Do not emit diagnostic when all arguments to `zip()` are variadic (`RUF058`) ([#15744](https://github.com/astral-sh/ruff/pull/15744))
- \[`ruff`\] Parenthesize fix when argument spans multiple lines for `unnecessary-round` (`RUF057`) ([#15703](https://github.com/astral-sh/ruff/pull/15703))
### Rule changes
- Preserve quote style in generated code ([#15726](https://github.com/astral-sh/ruff/pull/15726), [#15778](https://github.com/astral-sh/ruff/pull/15778), [#15794](https://github.com/astral-sh/ruff/pull/15794))
- \[`flake8-bugbear`\] Exempt `NewType` calls where the original type is immutable (`B008`) ([#15765](https://github.com/astral-sh/ruff/pull/15765))
- \[`pylint`\] Honor banned top-level imports by `TID253` in `PLC0415`. ([#15628](https://github.com/astral-sh/ruff/pull/15628))
- \[`pyupgrade`\] Ignore `is_typeddict` and `TypedDict` for `deprecated-import` (`UP035`) ([#15800](https://github.com/astral-sh/ruff/pull/15800))
### CLI
- Fix formatter warning message for `flake8-quotes` option ([#15788](https://github.com/astral-sh/ruff/pull/15788))
- Implement tab autocomplete for `ruff config` ([#15603](https://github.com/astral-sh/ruff/pull/15603))
### Bug fixes
- \[`flake8-comprehensions`\] Do not emit `unnecessary-map` diagnostic when lambda has different arity (`C417`) ([#15802](https://github.com/astral-sh/ruff/pull/15802))
- \[`flake8-comprehensions`\] Parenthesize `sorted` when needed for `unnecessary-call-around-sorted` (`C413`) ([#15825](https://github.com/astral-sh/ruff/pull/15825))
- \[`pyupgrade`\] Handle end-of-line comments for `quoted-annotation` (`UP037`) ([#15824](https://github.com/astral-sh/ruff/pull/15824))
### Documentation
- Add missing config docstrings ([#15803](https://github.com/astral-sh/ruff/pull/15803))
- Add references to `trio.run_process` and `anyio.run_process` ([#15761](https://github.com/astral-sh/ruff/pull/15761))
- Use `uv init --lib` in tutorial ([#15718](https://github.com/astral-sh/ruff/pull/15718))
## 0.9.3
### Preview features
- \[`airflow`\] Argument `fail_stop` in DAG has been renamed as `fail_fast` (`AIR302`) ([#15633](https://github.com/astral-sh/ruff/pull/15633))
- \[`airflow`\] Extend `AIR303` with more symbols ([#15611](https://github.com/astral-sh/ruff/pull/15611))
- \[`flake8-bandit`\] Report all references to suspicious functions (`S3`) ([#15541](https://github.com/astral-sh/ruff/pull/15541))
- \[`flake8-pytest-style`\] Do not emit diagnostics for empty `for` loops (`PT012`, `PT031`) ([#15542](https://github.com/astral-sh/ruff/pull/15542))
- \[`flake8-simplify`\] Avoid double negations (`SIM103`) ([#15562](https://github.com/astral-sh/ruff/pull/15562))
- \[`pyflakes`\] Fix infinite loop with unused local import in `__init__.py` (`F401`) ([#15517](https://github.com/astral-sh/ruff/pull/15517))
- \[`pylint`\] Do not report methods with only one `EM101`-compatible `raise` (`PLR6301`) ([#15507](https://github.com/astral-sh/ruff/pull/15507))
- \[`pylint`\] Implement `redefined-slots-in-subclass` (`W0244`) ([#9640](https://github.com/astral-sh/ruff/pull/9640))
- \[`pyupgrade`\] Add rules to use PEP 695 generics in classes and functions (`UP046`, `UP047`) ([#15565](https://github.com/astral-sh/ruff/pull/15565), [#15659](https://github.com/astral-sh/ruff/pull/15659))
- \[`refurb`\] Implement `for-loop-writes` (`FURB122`) ([#10630](https://github.com/astral-sh/ruff/pull/10630))
- \[`ruff`\] Implement `needless-else` clause (`RUF047`) ([#15051](https://github.com/astral-sh/ruff/pull/15051))
- \[`ruff`\] Implement `starmap-zip` (`RUF058`) ([#15483](https://github.com/astral-sh/ruff/pull/15483))
### Rule changes
- \[`flake8-bugbear`\] Do not raise error if keyword argument is present and target-python version is less or equals than 3.9 (`B903`) ([#15549](https://github.com/astral-sh/ruff/pull/15549))
- \[`flake8-comprehensions`\] strip parentheses around generators in `unnecessary-generator-set` (`C401`) ([#15553](https://github.com/astral-sh/ruff/pull/15553))
- \[`flake8-pytest-style`\] Rewrite references to `.exception` (`PT027`) ([#15680](https://github.com/astral-sh/ruff/pull/15680))
- \[`flake8-simplify`\] Mark fixes as unsafe (`SIM201`, `SIM202`) ([#15626](https://github.com/astral-sh/ruff/pull/15626))
- \[`flake8-type-checking`\] Fix some safe fixes being labeled unsafe (`TC006`,`TC008`) ([#15638](https://github.com/astral-sh/ruff/pull/15638))
- \[`isort`\] Omit trailing whitespace in `unsorted-imports` (`I001`) ([#15518](https://github.com/astral-sh/ruff/pull/15518))
- \[`pydoclint`\] Allow ignoring one line docstrings for `DOC` rules ([#13302](https://github.com/astral-sh/ruff/pull/13302))
- \[`pyflakes`\] Apply redefinition fixes by source code order (`F811`) ([#15575](https://github.com/astral-sh/ruff/pull/15575))
- \[`pyflakes`\] Avoid removing too many imports in `redefined-while-unused` (`F811`) ([#15585](https://github.com/astral-sh/ruff/pull/15585))
- \[`pyflakes`\] Group redefinition fixes by source statement (`F811`) ([#15574](https://github.com/astral-sh/ruff/pull/15574))
- \[`pylint`\] Include name of base class in message for `redefined-slots-in-subclass` (`W0244`) ([#15559](https://github.com/astral-sh/ruff/pull/15559))
- \[`ruff`\] Update fix for `RUF055` to use `var == value` ([#15605](https://github.com/astral-sh/ruff/pull/15605))
### Formatter
- Fix bracket spacing for single-element tuples in f-string expressions ([#15537](https://github.com/astral-sh/ruff/pull/15537))
- Fix unstable f-string formatting for expressions containing a trailing comma ([#15545](https://github.com/astral-sh/ruff/pull/15545))
### Performance
- Avoid quadratic membership check in import fixes ([#15576](https://github.com/astral-sh/ruff/pull/15576))
### Server
- Allow `unsafe-fixes` settings for code actions ([#15666](https://github.com/astral-sh/ruff/pull/15666))
### Bug fixes
- \[`flake8-bandit`\] Add missing single-line/dotall regex flag (`S608`) ([#15654](https://github.com/astral-sh/ruff/pull/15654))
- \[`flake8-import-conventions`\] Fix infinite loop between `ICN001` and `I002` (`ICN001`) ([#15480](https://github.com/astral-sh/ruff/pull/15480))
- \[`flake8-simplify`\] Do not emit diagnostics for expressions inside string type annotations (`SIM222`, `SIM223`) ([#15405](https://github.com/astral-sh/ruff/pull/15405))
- \[`pyflakes`\] Treat arguments passed to the `default=` parameter of `TypeVar` as type expressions (`F821`) ([#15679](https://github.com/astral-sh/ruff/pull/15679))
- \[`pyupgrade`\] Avoid syntax error when the iterable is a non-parenthesized tuple (`UP028`) ([#15543](https://github.com/astral-sh/ruff/pull/15543))
- \[`ruff`\] Exempt `NewType` calls where the original type is immutable (`RUF009`) ([#15588](https://github.com/astral-sh/ruff/pull/15588))
- Preserve raw string prefix and escapes in all codegen fixes ([#15694](https://github.com/astral-sh/ruff/pull/15694))
### Documentation
- Generate documentation redirects for lowercase rule codes ([#15564](https://github.com/astral-sh/ruff/pull/15564))
- `TRY300`: Add some extra notes on not catching exceptions you didn't expect ([#15036](https://github.com/astral-sh/ruff/pull/15036))
## 0.9.2
### Preview features
@@ -921,11 +1691,11 @@ The following rules have been stabilized and are no longer in preview:
The following behaviors have been stabilized:
- [`cancel-scope-no-checkpoint`](https://docs.astral.sh/ruff/rules/cancel-scope-no-checkpoint/) (`ASYNC100`): Support `asyncio` and `anyio` context mangers.
- [`async-function-with-timeout`](https://docs.astral.sh/ruff/rules/async-function-with-timeout/) (`ASYNC109`): Support `asyncio` and `anyio` context mangers.
- [`async-busy-wait`](https://docs.astral.sh/ruff/rules/async-busy-wait/) (`ASYNC110`): Support `asyncio` and `anyio` context mangers.
- [`async-zero-sleep`](https://docs.astral.sh/ruff/rules/async-zero-sleep/) (`ASYNC115`): Support `anyio` context mangers.
- [`long-sleep-not-forever`](https://docs.astral.sh/ruff/rules/long-sleep-not-forever/) (`ASYNC116`): Support `anyio` context mangers.
- [`cancel-scope-no-checkpoint`](https://docs.astral.sh/ruff/rules/cancel-scope-no-checkpoint/) (`ASYNC100`): Support `asyncio` and `anyio` context managers.
- [`async-function-with-timeout`](https://docs.astral.sh/ruff/rules/async-function-with-timeout/) (`ASYNC109`): Support `asyncio` and `anyio` context managers.
- [`async-busy-wait`](https://docs.astral.sh/ruff/rules/async-busy-wait/) (`ASYNC110`): Support `asyncio` and `anyio` context managers.
- [`async-zero-sleep`](https://docs.astral.sh/ruff/rules/async-zero-sleep/) (`ASYNC115`): Support `anyio` context managers.
- [`long-sleep-not-forever`](https://docs.astral.sh/ruff/rules/long-sleep-not-forever/) (`ASYNC116`): Support `anyio` context managers.
The following fixes have been stabilized:

View File

@@ -71,8 +71,7 @@ representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
<charlie.r.marsh@gmail.com>.
reported to the community leaders responsible for enforcement at <hey@astral.sh>.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@@ -2,6 +2,11 @@
Welcome! We're happy to have you here. Thank you in advance for your contribution to Ruff.
> [!NOTE]
>
> This guide is for Ruff. If you're looking to contribute to ty, please see [the ty contributing
> guide](https://github.com/astral-sh/ruff/blob/main/crates/ty/CONTRIBUTING.md).
## The Basics
Ruff welcomes contributions in the form of pull requests.
@@ -366,6 +371,15 @@ uvx --from ./python/ruff-ecosystem ruff-ecosystem format ruff "./target/debug/ru
See the [ruff-ecosystem package](https://github.com/astral-sh/ruff/tree/main/python/ruff-ecosystem) for more details.
## Upgrading Rust
1. Change the `channel` in `./rust-toolchain.toml` to the new Rust version (`<latest>`)
1. Change the `rust-version` in the `./Cargo.toml` to `<latest> - 2` (e.g. 1.84 if the latest is 1.86)
1. Run `cargo clippy --fix --allow-dirty --allow-staged` to fix new clippy warnings
1. Create and merge the PR
1. Bump the Rust version in Ruff's conda forge recipe. See [this PR](https://github.com/conda-forge/ruff-feedstock/pull/266) for an example.
1. Enjoy the new Rust version!
## Benchmarking and Profiling
We have several ways of benchmarking and profiling Ruff:
@@ -397,7 +411,7 @@ cargo install hyperfine
To benchmark the release build:
```shell
cargo build --release && hyperfine --warmup 10 \
cargo build --release --bin ruff && hyperfine --warmup 10 \
"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ --no-cache -e" \
"./target/release/ruff check ./crates/ruff_linter/resources/test/cpython/ -e"
@@ -526,7 +540,7 @@ cargo benchmark
#### Benchmark-driven Development
Ruff uses [Criterion.rs](https://bheisler.github.io/criterion.rs/book/) for benchmarks. You can use
`--save-baseline=<name>` to store an initial baseline benchmark (e.g. on `main`) and then use
`--save-baseline=<name>` to store an initial baseline benchmark (e.g., on `main`) and then use
`--benchmark=<name>` to compare against that benchmark. Criterion will print a message telling you
if the benchmark improved/regressed compared to that baseline.
@@ -596,8 +610,7 @@ Then convert the recorded profile
perf script -F +pid > /tmp/test.perf
```
You can now view the converted file with [firefox profiler](https://profiler.firefox.com/), with a
more in-depth guide [here](https://profiler.firefox.com/docs/#/./guide-perf-profiling)
You can now view the converted file with [firefox profiler](https://profiler.firefox.com/). To learn more about Firefox profiler, read the [Firefox profiler profiling-guide](https://profiler.firefox.com/docs/#/./guide-perf-profiling).
An alternative is to convert the perf data to `flamegraph.svg` using
[flamegraph](https://github.com/flamegraph-rs/flamegraph) (`cargo install flamegraph`):
@@ -678,9 +691,9 @@ utils with it:
23 Newline 24
```
- `cargo dev print-cst <file>`: Print the CST of a python file using
- `cargo dev print-cst <file>`: Print the CST of a Python file using
[LibCST](https://github.com/Instagram/LibCST), which is used in addition to the RustPython parser
in Ruff. E.g. for `if True: pass # comment` everything including the whitespace is represented:
in Ruff. For example, for `if True: pass # comment`, everything, including the whitespace, is represented:
```text
Module {

2145
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,9 @@ members = ["crates/*"]
resolver = "2"
[workspace.package]
edition = "2021"
rust-version = "1.80"
# Please update rustfmt.toml when bumping the Rust edition
edition = "2024"
rust-version = "1.85"
homepage = "https://docs.astral.sh/ruff"
documentation = "https://docs.astral.sh/ruff"
repository = "https://github.com/astral-sh/ruff"
@@ -23,6 +24,7 @@ ruff_index = { path = "crates/ruff_index" }
ruff_linter = { path = "crates/ruff_linter" }
ruff_macros = { path = "crates/ruff_macros" }
ruff_notebook = { path = "crates/ruff_notebook" }
ruff_options_metadata = { path = "crates/ruff_options_metadata" }
ruff_python_ast = { path = "crates/ruff_python_ast" }
ruff_python_codegen = { path = "crates/ruff_python_codegen" }
ruff_python_formatter = { path = "crates/ruff_python_formatter" }
@@ -35,13 +37,15 @@ ruff_python_trivia = { path = "crates/ruff_python_trivia" }
ruff_server = { path = "crates/ruff_server" }
ruff_source_file = { path = "crates/ruff_source_file" }
ruff_text_size = { path = "crates/ruff_text_size" }
red_knot_vendored = { path = "crates/red_knot_vendored" }
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_project = { path = "crates/red_knot_project", default-features = false }
ty = { path = "crates/ty" }
ty_ide = { path = "crates/ty_ide" }
ty_project = { path = "crates/ty_project", default-features = false }
ty_python_semantic = { path = "crates/ty_python_semantic" }
ty_server = { path = "crates/ty_server" }
ty_test = { path = "crates/ty_test" }
ty_vendored = { path = "crates/ty_vendored" }
aho-corasick = { version = "1.1.3" }
anstream = { version = "0.6.18" }
@@ -49,12 +53,11 @@ anstyle = { version = "1.0.10" }
anyhow = { version = "1.0.80" }
assert_fs = { version = "1.1.0" }
argfile = { version = "0.2.0" }
bincode = { version = "1.3.3" }
bincode = { version = "2.0.0" }
bitflags = { version = "2.5.0" }
bstr = { version = "1.9.1" }
cachedir = { version = "0.3.1" }
camino = { version = "1.1.7" }
chrono = { version = "0.4.35", default-features = false, features = ["clock"] }
clap = { version = "4.5.3", features = ["derive"] }
clap_complete_command = { version = "0.6.0" }
clearscreen = { version = "4.0.0" }
@@ -63,24 +66,27 @@ colored = { version = "3.0.0" }
console_error_panic_hook = { version = "0.1.7" }
console_log = { version = "1.0.0" }
countme = { version = "3.0.1" }
compact_str = "0.8.0"
criterion = { version = "0.5.1", default-features = false }
compact_str = "0.9.0"
criterion = { version = "0.6.0", default-features = false }
crossbeam = { version = "0.8.4" }
dashmap = { version = "6.0.1" }
dir-test = { version = "0.4.0" }
dunce = { version = "1.0.5" }
drop_bomb = { version = "0.1.5" }
env_logger = { version = "0.11.0" }
etcetera = { version = "0.8.0" }
etcetera = { version = "0.10.0" }
fern = { version = "0.7.0" }
filetime = { version = "0.2.23" }
getrandom = { version = "0.3.1" }
glob = { version = "0.3.1" }
globset = { version = "0.4.14" }
globwalk = { version = "0.9.1" }
hashbrown = { version = "0.15.0", default-features = false, features = [
"raw-entry",
"equivalent",
"inline-more",
] }
heck = "0.5.0"
ignore = { version = "0.4.22" }
imara-diff = { version = "0.1.5" }
imperative = { version = "1.0.4" }
@@ -92,8 +98,9 @@ insta-cmd = { version = "0.6.0" }
is-macro = { version = "0.3.5" }
is-wsl = { version = "0.4.0" }
itertools = { version = "0.14.0" }
jiff = { version = "0.2.0" }
js-sys = { version = "0.3.69" }
jod-thread = { version = "0.1.2" }
jod-thread = { version = "1.0.0" }
libc = { version = "0.2.153" }
libcst = { version = "1.1.0", default-features = false }
log = { version = "0.4.17" }
@@ -116,12 +123,13 @@ proc-macro2 = { version = "1.0.79" }
pyproject-toml = { version = "0.13.4" }
quick-junit = { version = "0.5.0" }
quote = { version = "1.0.23" }
rand = { version = "0.8.5" }
rand = { version = "0.9.0" }
rayon = { version = "1.10.0" }
regex = { version = "1.10.2" }
rustc-hash = { version = "2.0.0" }
rustc-stable-hash = { version = "0.1.2" }
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "88a1d7774d78f048fbd77d40abca9ebd729fd1f0" }
salsa = { git = "https://github.com/carljm/salsa.git", rev = "0f6d406f6c309964279baef71588746b8c67b4a3" }
schemars = { version = "0.8.16" }
seahash = { version = "4.1.0" }
serde = { version = "1.0.197", features = ["derive"] }
@@ -134,10 +142,15 @@ serde_with = { version = "3.6.0", default-features = false, features = [
shellexpand = { version = "3.0.0" }
similar = { version = "2.4.0", features = ["inline"] }
smallvec = { version = "1.13.2" }
snapbox = { version = "0.6.0", features = ["diff", "term-svg", "cmd", "examples"] }
snapbox = { version = "0.6.0", features = [
"diff",
"term-svg",
"cmd",
"examples",
] }
static_assertions = "1.1.0"
strum = { version = "0.26.0", features = ["strum_macros"] }
strum_macros = { version = "0.26.0" }
strum = { version = "0.27.0", features = ["strum_macros"] }
strum_macros = { version = "0.27.0" }
syn = { version = "2.0.55" }
tempfile = { version = "3.9.0" }
test-case = { version = "3.3.1" }
@@ -147,11 +160,13 @@ toml = { version = "0.8.11" }
tracing = { version = "0.1.40" }
tracing-flame = { version = "0.2.0" }
tracing-indicatif = { version = "0.3.6" }
tracing-log = { version = "0.2.0" }
tracing-subscriber = { version = "0.3.18", default-features = false, features = [
"env-filter",
"fmt",
"ansi",
"smallvec"
] }
tracing-tree = { version = "0.4.0" }
tryfn = { version = "0.2.1" }
typed-arena = { version = "2.0.2" }
unic-ucd-category = { version = "0.9" }
@@ -159,13 +174,11 @@ unicode-ident = { version = "1.0.12" }
unicode-width = { version = "0.2.0" }
unicode_names2 = { version = "1.2.2" }
unicode-normalization = { version = "0.1.23" }
ureq = { version = "2.9.6" }
url = { version = "2.5.0" }
uuid = { version = "1.6.1", features = [
"v4",
"fast-rng",
"macro-diagnostics",
"js",
] }
walkdir = { version = "2.3.2" }
wasm-bindgen = { version = "0.2.92" }
@@ -173,6 +186,10 @@ wasm-bindgen-test = { version = "0.3.42" }
wild = { version = "2" }
zip = { version = "0.6.6", default-features = false }
[workspace.metadata.cargo-shear]
ignored = ["getrandom", "ruff_options_metadata", "uuid"]
[workspace.lints.rust]
unsafe_code = "warn"
unreachable_pub = "warn"
@@ -197,6 +214,8 @@ must_use_candidate = "allow"
similar_names = "allow"
single_match_else = "allow"
too_many_lines = "allow"
needless_continue = "allow" # An explicit continue can be more readable, especially if the alternative is an empty block.
unnecessary_debug_formatting = "allow" # too many instances, the display also doesn't quote the path which is often desired in logs where we use them the most often.
# Without the hashes we run into a `rustfmt` bug in some snapshot tests, see #13250
needless_raw_string_hashes = "allow"
# Disallowed restriction lints
@@ -241,6 +260,9 @@ opt-level = 3
[profile.dev.package.similar]
opt-level = 3
[profile.dev.package.salsa]
opt-level = 3
# Reduce complexity of a parser function that would trigger a locals limit in a wasm tool.
# https://github.com/bytecodealliance/wasm-tools/blob/b5c3d98e40590512a3b12470ef358d5c7b983b15/crates/wasmparser/src/limits.rs#L29
[profile.dev.package.ruff_python_parser]
@@ -255,60 +277,3 @@ debug = 1
# The profile that 'cargo dist' will build with.
[profile.dist]
inherits = "release"
# Config for 'dist'
[workspace.metadata.dist]
# The preferred dist version to use in CI (Cargo.toml SemVer syntax)
cargo-dist-version = "0.25.2-prerelease.3"
# CI backends to support
ci = "github"
# The installers to generate for each app
installers = ["shell", "powershell"]
# The archive format to use for windows builds (defaults .zip)
windows-archive = ".zip"
# The archive format to use for non-windows builds (defaults .tar.xz)
unix-archive = ".tar.gz"
# Target platforms to build apps for (Rust target-triple syntax)
targets = [
"aarch64-apple-darwin",
"aarch64-pc-windows-msvc",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"arm-unknown-linux-musleabihf",
"armv7-unknown-linux-gnueabihf",
"armv7-unknown-linux-musleabihf",
"i686-pc-windows-msvc",
"i686-unknown-linux-gnu",
"i686-unknown-linux-musl",
"powerpc64-unknown-linux-gnu",
"powerpc64le-unknown-linux-gnu",
"s390x-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
"x86_64-unknown-linux-musl",
]
# Whether to auto-include files like READMEs, LICENSEs, and CHANGELOGs (default true)
auto-includes = false
# Whether dist should create a Github Release or use an existing draft
create-release = true
# Which actions to run on pull requests
pr-run-mode = "skip"
# Whether CI should trigger releases with dispatches instead of tag pushes
dispatch-releases = true
# Which phase dist should use to create the GitHub release
github-release = "announce"
# Whether CI should include auto-generated code to build local artifacts
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-pypi", "./publish-wasm"]
# Post-announce jobs to run in CI
post-announce-jobs = ["./notify-dependents", "./publish-docs", "./publish-playground"]
# Custom permissions for GitHub Jobs
github-custom-job-permissions = { "build-docker" = { packages = "write", contents = "read" }, "publish-wasm" = { contents = "read", id-token = "write", packages = "write" } }
# Whether to install an updater program
install-updater = false
# Path that installers should place binaries in
install-path = ["$XDG_BIN_HOME/", "$XDG_DATA_HOME/../bin", "~/.local/bin"]

View File

@@ -34,8 +34,7 @@ An extremely fast Python linter and code formatter, written in Rust.
- 🔧 Fix support, for automatic error correction (e.g., automatically remove unused imports)
- 📏 Over [800 built-in rules](https://docs.astral.sh/ruff/rules/), with native re-implementations
of popular Flake8 plugins, like flake8-bugbear
- ⌨️ First-party [editor integrations](https://docs.astral.sh/ruff/integrations/) for
[VS Code](https://github.com/astral-sh/ruff-vscode) and [more](https://docs.astral.sh/ruff/editors/setup)
- ⌨️ First-party [editor integrations](https://docs.astral.sh/ruff/editors) for [VS Code](https://github.com/astral-sh/ruff-vscode) and [more](https://docs.astral.sh/ruff/editors/setup)
- 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](https://docs.astral.sh/ruff/configuration/#config-file-discovery)
Ruff aims to be orders of magnitude faster than alternative tools while integrating more
@@ -149,8 +148,8 @@ curl -LsSf https://astral.sh/ruff/install.sh | sh
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"
# For a specific version.
curl -LsSf https://astral.sh/ruff/0.9.2/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.9.2/install.ps1 | iex"
curl -LsSf https://astral.sh/ruff/0.11.12/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.11.12/install.ps1 | iex"
```
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
@@ -183,7 +182,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.9.2
rev: v0.11.12
hooks:
# Run the linter.
- id: ruff
@@ -255,7 +254,7 @@ indent-width = 4
target-version = "py39"
[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
select = ["E4", "E7", "E9", "F"]
ignore = []
@@ -452,6 +451,7 @@ Ruff is used by a number of major open-source projects and companies, including:
- ING Bank ([popmon](https://github.com/ing-bank/popmon), [probatus](https://github.com/ing-bank/probatus))
- [Ibis](https://github.com/ibis-project/ibis)
- [ivy](https://github.com/unifyai/ivy)
- [JAX](https://github.com/jax-ml/jax)
- [Jupyter](https://github.com/jupyter-server/jupyter_server)
- [Kraken Tech](https://kraken.tech/)
- [LangChain](https://github.com/hwchase17/langchain)

15
SECURITY.md Normal file
View File

@@ -0,0 +1,15 @@
# Security policy
## Reporting a vulnerability
If you have found a possible vulnerability, please email `security at astral dot sh`.
## Bug bounties
While we sincerely appreciate and encourage reports of suspected security problems, please note that
Astral does not currently run any bug bounty programs.
## Vulnerability disclosures
Critical vulnerabilities will be disclosed via GitHub's
[security advisory](https://github.com/astral-sh/ruff/security) system.

View File

@@ -1,9 +1,13 @@
[files]
# https://github.com/crate-ci/typos/issues/868
extend-exclude = [
"crates/red_knot_vendored/vendor/**/*",
"crates/ty_vendored/vendor/**/*",
"**/resources/**/*",
"**/snapshots/**/*",
# Completion tests tend to have a lot of incomplete
# words naturally. It's annoying to have to make all
# of them actually words. So just ignore typos here.
"crates/ty_ide/src/completion.rs",
]
[default.extend-words]
@@ -23,6 +27,10 @@ extend-ignore-re = [
# Line ignore with trailing "spellchecker:disable-line"
"(?Rm)^.*#\\s*spellchecker:disable-line$",
"LICENSEs",
# Various third party dependencies uses `typ` as struct field names (e.g., lsp_types::LogMessageParams)
"typ",
# TODO: Remove this once the `TYP` redirects are removed from `rule_redirects.rs`
"TYP",
]
[default.extend-identifiers]

View File

@@ -1,6 +1,7 @@
doc-valid-idents = [
"..",
"CodeQL",
"CPython",
"FastAPI",
"IPython",
"LangChain",
@@ -14,7 +15,7 @@ doc-valid-idents = [
"SNMPv1",
"SNMPv2",
"SNMPv3",
"PyFlakes"
"PyFlakes",
]
ignore-interior-mutability = [

View File

@@ -1,360 +0,0 @@
use std::process::{ExitCode, Termination};
use std::sync::Mutex;
use anyhow::{anyhow, Context};
use clap::Parser;
use colored::Colorize;
use crossbeam::channel as crossbeam_channel;
use python_version::PythonVersion;
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 ruff_db::diagnostic::Diagnostic;
use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf};
use salsa::plumbing::ZalsaDatabase;
use crate::logging::{setup_tracing, Verbosity};
mod logging;
mod python_version;
mod verbosity;
#[derive(Debug, Parser)]
#[command(
author,
name = "red-knot",
about = "An extremely fast Python type checker."
)]
#[command(version)]
struct Args {
#[command(subcommand)]
pub(crate) command: Option<Command>,
/// Run the command within the given project directory.
///
/// All `pyproject.toml` files will be discovered by walking up the directory tree from the given project directory,
/// as will the project's virtual environment (`.venv`) unless the `venv-path` option is set.
///
/// Other command-line arguments (such as relative paths) will be resolved relative to the current working directory.
#[arg(long, value_name = "PROJECT")]
project: Option<SystemPathBuf>,
/// Path to the virtual environment the project uses.
///
/// If provided, red-knot will use the `site-packages` directory of this virtual environment
/// to resolve type information for the project's third-party dependencies.
#[arg(long, value_name = "PATH")]
venv_path: Option<SystemPathBuf>,
/// Custom directory to use for stdlib typeshed stubs.
#[arg(long, value_name = "PATH", alias = "custom-typeshed-dir")]
typeshed: Option<SystemPathBuf>,
/// Additional path to use as a module-resolution source (can be passed multiple times).
#[arg(long, value_name = "PATH")]
extra_search_path: Option<Vec<SystemPathBuf>>,
/// Python version to assume when resolving types.
#[arg(long, value_name = "VERSION", alias = "target-version")]
python_version: Option<PythonVersion>,
#[clap(flatten)]
verbosity: Verbosity,
/// Run in watch mode by re-running whenever files change.
#[arg(long, short = 'W')]
watch: bool,
}
impl Args {
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()
}
}
}
#[derive(Debug, clap::Subcommand)]
pub enum Command {
/// Start the language server
Server,
}
#[allow(clippy::print_stdout, clippy::unnecessary_wraps, clippy::print_stderr)]
pub fn main() -> ExitStatus {
run().unwrap_or_else(|error| {
use std::io::Write;
// Use `writeln` instead of `eprintln` to avoid panicking when the stderr pipe is broken.
let mut stderr = std::io::stderr().lock();
// This communicates that this isn't a linter error but Red Knot itself hard-errored for
// some reason (e.g. failed to resolve the configuration)
writeln!(stderr, "{}", "Red Knot failed".red().bold()).ok();
// Currently we generally only see one error, but e.g. with io errors when resolving
// the configuration it is help to chain errors ("resolving configuration failed" ->
// "failed to read file: subdir/pyproject.toml")
for cause in error.chain() {
writeln!(stderr, " {} {cause}", "Cause:".bold()).ok();
}
ExitStatus::Error
})
}
fn run() -> anyhow::Result<ExitStatus> {
let args = Args::parse_from(std::env::args());
if matches!(args.command, Some(Command::Server)) {
return run_server().map(|()| ExitStatus::Success);
}
let verbosity = args.verbosity.level();
countme::enable(verbosity.is_trace());
let _guard = setup_tracing(verbosity)?;
// The base path to which all CLI arguments are relative to.
let cli_base_path = {
let cwd = std::env::current_dir().context("Failed to get the current working directory")?;
SystemPathBuf::from_path_buf(cwd)
.map_err(|path| {
anyhow!(
"The current working directory `{}` contains non-Unicode characters. Red Knot only supports Unicode paths.",
path.display()
)
})?
};
let cwd = args
.project
.as_ref()
.map(|cwd| {
if cwd.as_std_path().is_dir() {
Ok(SystemPath::absolute(cwd, &cli_base_path))
} else {
Err(anyhow!("Provided project path `{cwd}` is not a directory"))
}
})
.transpose()?
.unwrap_or_else(|| cli_base_path.clone());
let system = OsSystem::new(cwd.clone());
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());
let mut db = ProjectDatabase::new(workspace_metadata, system)?;
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));
ctrlc::set_handler(move || {
let mut lock = main_loop_cancellation_token.lock().unwrap();
if let Some(token) = lock.take() {
token.stop();
}
})?;
let exit_status = if args.watch {
main_loop.watch(&mut db)?
} else {
main_loop.run(&mut db)
};
tracing::trace!("Counts for entire CLI run:\n{}", countme::get_all());
std::mem::forget(db);
Ok(exit_status)
}
#[derive(Copy, Clone)]
pub enum ExitStatus {
/// Checking was successful and there were no errors.
Success = 0,
/// Checking was successful but there were errors.
Failure = 1,
/// Checking failed.
Error = 2,
}
impl Termination for ExitStatus {
fn report(self) -> ExitCode {
ExitCode::from(self as u8)
}
}
struct MainLoop {
/// Sender that can be used to send messages to the main loop.
sender: crossbeam_channel::Sender<MainLoopMessage>,
/// Receiver for the messages sent **to** the main loop.
receiver: crossbeam_channel::Receiver<MainLoopMessage>,
/// The file system watcher, if running in watch mode.
watcher: Option<ProjectWatcher>,
cli_options: Options,
}
impl MainLoop {
fn new(cli_options: Options) -> (Self, MainLoopCancellationToken) {
let (sender, receiver) = crossbeam_channel::bounded(10);
(
Self {
sender: sender.clone(),
receiver,
watcher: None,
cli_options,
},
MainLoopCancellationToken { sender },
)
}
fn watch(mut self, db: &mut ProjectDatabase) -> anyhow::Result<ExitStatus> {
tracing::debug!("Starting watch mode");
let sender = self.sender.clone();
let watcher = watch::directory_watcher(move |event| {
sender.send(MainLoopMessage::ApplyChanges(event)).unwrap();
})?;
self.watcher = Some(ProjectWatcher::new(watcher, db));
self.run(db);
Ok(ExitStatus::Success)
}
fn run(mut self, db: &mut ProjectDatabase) -> ExitStatus {
self.sender.send(MainLoopMessage::CheckWorkspace).unwrap();
let result = self.main_loop(db);
tracing::debug!("Exiting main loop");
result
}
fn main_loop(&mut self, db: &mut ProjectDatabase) -> ExitStatus {
// Schedule the first check.
tracing::debug!("Starting main loop");
let mut revision = 0u64;
while let Ok(message) = self.receiver.recv() {
match message {
MainLoopMessage::CheckWorkspace => {
let db = db.clone();
let sender = self.sender.clone();
// Spawn a new task that checks the project. This needs to be done in a separate thread
// to prevent blocking the main loop here.
rayon::spawn(move || {
if let Ok(result) = db.check() {
// Send the result back to the main loop for printing.
sender
.send(MainLoopMessage::CheckCompleted { result, revision })
.unwrap();
}
});
}
MainLoopMessage::CheckCompleted {
result,
revision: check_revision,
} => {
let has_diagnostics = !result.is_empty();
if check_revision == revision {
#[allow(clippy::print_stdout)]
for diagnostic in result {
println!("{}", diagnostic.display(db));
}
} else {
tracing::debug!(
"Discarding check result for outdated revision: current: {revision}, result revision: {check_revision}"
);
}
if self.watcher.is_none() {
return if has_diagnostics {
ExitStatus::Failure
} else {
ExitStatus::Success
};
}
tracing::trace!("Counts after last check:\n{}", countme::get_all());
}
MainLoopMessage::ApplyChanges(changes) => {
revision += 1;
// Automatically cancels any pending queries and waits for them to complete.
db.apply_changes(changes, Some(&self.cli_options));
if let Some(watcher) = self.watcher.as_mut() {
watcher.update(db);
}
self.sender.send(MainLoopMessage::CheckWorkspace).unwrap();
}
MainLoopMessage::Exit => {
// Cancel any pending queries and wait for them to complete.
// TODO: Don't use Salsa internal APIs
// [Zulip-Thread](https://salsa.zulipchat.com/#narrow/stream/333573-salsa-3.2E0/topic/Expose.20an.20API.20to.20cancel.20other.20queries)
let _ = db.zalsa_mut();
return ExitStatus::Success;
}
}
tracing::debug!("Waiting for next main loop message.");
}
ExitStatus::Success
}
}
#[derive(Debug)]
struct MainLoopCancellationToken {
sender: crossbeam_channel::Sender<MainLoopMessage>,
}
impl MainLoopCancellationToken {
fn stop(self) {
self.sender.send(MainLoopMessage::Exit).unwrap();
}
}
/// Message sent from the orchestrator to the main loop.
#[derive(Debug)]
enum MainLoopMessage {
CheckWorkspace,
CheckCompleted {
result: Vec<Box<dyn Diagnostic>>,
revision: u64,
},
ApplyChanges(Vec<watch::ChangeEvent>),
Exit,
}

View File

@@ -1 +0,0 @@

View File

@@ -1,60 +0,0 @@
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

@@ -1,221 +0,0 @@
use crate::db::{Db, ProjectDatabase};
use crate::metadata::options::Options;
use crate::watch::{ChangeEvent, CreatedKind, DeletedKind};
use crate::{Project, ProjectMetadata};
use red_knot_python_semantic::Program;
use ruff_db::files::{system_path_to_file, File, Files};
use ruff_db::system::walk_directory::WalkState;
use ruff_db::system::SystemPath;
use ruff_db::Db as _;
use rustc_hash::FxHashSet;
impl ProjectDatabase {
#[tracing::instrument(level = "debug", skip(self, changes, cli_options))]
pub fn apply_changes(&mut self, changes: Vec<ChangeEvent>, cli_options: Option<&Options>) {
let mut project = self.project();
let project_path = project.root(self).to_path_buf();
let program = Program::get(self);
let custom_stdlib_versions_path = program
.custom_stdlib_search_path(self)
.map(|path| path.join("VERSIONS"));
// Are there structural changes to the project
let mut project_changed = false;
// Changes to a custom stdlib path's VERSIONS
let mut custom_stdlib_change = false;
// Paths that were added
let mut added_paths = FxHashSet::default();
// Deduplicate the `sync` calls. Many file watchers emit multiple events for the same path.
let mut synced_files = FxHashSet::default();
let mut synced_recursively = FxHashSet::default();
let mut sync_path = |db: &mut ProjectDatabase, path: &SystemPath| {
if synced_files.insert(path.to_path_buf()) {
File::sync_path(db, path);
}
};
let mut sync_recursively = |db: &mut ProjectDatabase, path: &SystemPath| {
if synced_recursively.insert(path.to_path_buf()) {
Files::sync_recursively(db, path);
}
};
for change in changes {
if let Some(path) = change.system_path() {
if matches!(
path.file_name(),
Some(".gitignore" | ".ignore" | "ruff.toml" | ".ruff.toml" | "pyproject.toml")
) {
// Changes to ignore files or settings can change the project structure or add/remove files.
project_changed = true;
continue;
}
if Some(path) == custom_stdlib_versions_path.as_deref() {
custom_stdlib_change = true;
}
}
match change {
ChangeEvent::Changed { path, kind: _ } | ChangeEvent::Opened(path) => {
sync_path(self, &path);
}
ChangeEvent::Created { kind, path } => {
match kind {
CreatedKind::File => sync_path(self, &path),
CreatedKind::Directory | CreatedKind::Any => {
sync_recursively(self, &path);
}
}
if self.system().is_file(&path) {
// Add the parent directory because `walkdir` always visits explicitly passed files
// even if they match an exclude filter.
added_paths.insert(path.parent().unwrap().to_path_buf());
} else {
added_paths.insert(path);
}
}
ChangeEvent::Deleted { kind, path } => {
let is_file = match kind {
DeletedKind::File => true,
DeletedKind::Directory => {
// file watchers emit an event for every deleted file. No need to scan the entire dir.
continue;
}
DeletedKind::Any => self
.files
.try_system(self, &path)
.is_some_and(|file| file.exists(self)),
};
if is_file {
sync_path(self, &path);
if let Some(file) = self.files().try_system(self, &path) {
project.remove_file(self, file);
}
} else {
sync_recursively(self, &path);
if custom_stdlib_versions_path
.as_ref()
.is_some_and(|versions_path| versions_path.starts_with(&path))
{
custom_stdlib_change = true;
}
// Perform a full-reload in case the deleted directory contained the pyproject.toml.
// We may want to make this more clever in the future, to e.g. iterate over the
// indexed files and remove the once that start with the same path, unless
// the deleted path is the project configuration.
project_changed = true;
}
}
ChangeEvent::CreatedVirtual(path) | ChangeEvent::ChangedVirtual(path) => {
File::sync_virtual_path(self, &path);
}
ChangeEvent::DeletedVirtual(path) => {
if let Some(virtual_file) = self.files().try_virtual_file(&path) {
virtual_file.close(self);
}
}
ChangeEvent::Rescan => {
project_changed = true;
Files::sync_all(self);
break;
}
}
}
if project_changed {
match ProjectMetadata::discover(&project_path, self.system()) {
Ok(mut metadata) => {
if let Some(cli_options) = cli_options {
metadata.apply_cli_options(cli_options.clone());
}
let program_settings = metadata.to_program_settings(self.system());
let program = Program::get(self);
if let Err(error) = program.update_from_settings(self, program_settings) {
tracing::error!("Failed to update the program settings, keeping the old program settings: {error}");
};
if metadata.root() == project.root(self) {
tracing::debug!("Reloading project after structural change");
project.reload(self, metadata);
} else {
tracing::debug!("Replace project after structural change");
project = Project::from_metadata(self, metadata);
self.project = Some(project);
}
}
Err(error) => {
tracing::error!(
"Failed to load project, keeping old project configuration: {error}"
);
}
}
return;
} else if custom_stdlib_change {
let search_paths = project
.metadata(self)
.to_program_settings(self.system())
.search_paths;
if let Err(error) = program.update_search_paths(self, &search_paths) {
tracing::error!("Failed to set the new search paths: {error}");
}
}
let mut added_paths = added_paths.into_iter();
// Use directory walking to discover newly added files.
if let Some(path) = added_paths.next() {
let mut walker = self.system().walk_directory(&path);
for extra_path in added_paths {
walker = walker.add(&extra_path);
}
let added_paths = std::sync::Mutex::new(Vec::default());
walker.run(|| {
Box::new(|entry| {
let Ok(entry) = entry else {
return WalkState::Continue;
};
if !entry.file_type().is_file() {
return WalkState::Continue;
}
let mut paths = added_paths.lock().unwrap();
paths.push(entry.into_path());
WalkState::Continue
})
});
for path in added_paths.into_inner().unwrap() {
let file = system_path_to_file(self, &path);
if let Ok(file) = file {
project.add_file(self, file);
}
}
}
}
}

View File

@@ -1,470 +0,0 @@
#![allow(clippy::ref_option)]
use red_knot_python_semantic::lint::{LintRegistry, LintRegistryBuilder};
use red_knot_python_semantic::register_lints;
use red_knot_python_semantic::types::check_types;
use ruff_db::diagnostic::{Diagnostic, DiagnosticId, ParseDiagnostic, Severity};
use ruff_db::files::{system_path_to_file, File};
use ruff_db::parsed::parsed_module;
use ruff_db::source::{source_text, SourceTextError};
use ruff_db::system::walk_directory::WalkState;
use ruff_db::system::{FileType, SystemPath};
use ruff_python_ast::PySourceType;
use ruff_text_size::TextRange;
use rustc_hash::{FxBuildHasher, FxHashSet};
use salsa::Durability;
use salsa::Setter;
use std::borrow::Cow;
use std::sync::Arc;
pub use db::{Db, ProjectDatabase};
use files::{Index, Indexed, IndexedFiles};
pub use metadata::{ProjectDiscoveryError, ProjectMetadata};
pub mod combine;
mod db;
mod files;
pub mod metadata;
pub mod watch;
pub static DEFAULT_LINT_REGISTRY: std::sync::LazyLock<LintRegistry> =
std::sync::LazyLock::new(default_lints_registry);
pub fn default_lints_registry() -> LintRegistry {
let mut builder = LintRegistryBuilder::default();
register_lints(&mut builder);
builder.build()
}
/// The project as a Salsa ingredient.
///
/// ## How is a project different from a program?
/// There are two (related) motivations:
///
/// 1. Program is defined in `ruff_db` and it can't reference the settings types for the linter and formatter
/// without introducing a cyclic dependency. The project is defined in a higher level crate
/// where it can reference these setting types.
/// 2. Running `ruff check` with different target versions results in different programs (settings) but
/// it remains the same project. That's why program is a narrowed view of the project only
/// holding on to the most fundamental settings required for checking.
#[salsa::input]
pub struct Project {
/// The files that are open in the project.
///
/// Setting the open files to a non-`None` value changes `check` to only check the
/// open files rather than all files in the project.
#[return_ref]
#[default]
open_fileset: Option<Arc<FxHashSet<File>>>,
/// The first-party files of this project.
#[default]
#[return_ref]
file_set: IndexedFiles,
/// The metadata describing the project, including the unresolved options.
#[return_ref]
pub metadata: ProjectMetadata,
}
impl Project {
pub fn from_metadata(db: &dyn Db, metadata: ProjectMetadata) -> Self {
Project::builder(metadata)
.durability(Durability::MEDIUM)
.open_fileset_durability(Durability::LOW)
.file_set_durability(Durability::LOW)
.new(db)
}
pub fn root(self, db: &dyn Db) -> &SystemPath {
self.metadata(db).root()
}
pub fn name(self, db: &dyn Db) -> &str {
self.metadata(db).name()
}
pub fn reload(self, db: &mut dyn Db, metadata: ProjectMetadata) {
tracing::debug!("Reloading project");
assert_eq!(self.root(db), metadata.root());
if &metadata != self.metadata(db) {
self.set_metadata(db).to(metadata);
}
self.reload_files(db);
}
/// Checks all open files in the project and its dependencies.
pub fn check(self, db: &ProjectDatabase) -> Vec<Box<dyn Diagnostic>> {
let project_span = tracing::debug_span!("Project::check");
let _span = project_span.enter();
tracing::debug!("Checking project '{name}'", name = self.name(db));
let result = Arc::new(std::sync::Mutex::new(Vec::new()));
let inner_result = Arc::clone(&result);
let db = db.clone();
let project_span = project_span.clone();
rayon::scope(move |scope| {
let files = ProjectFiles::new(&db, self);
for file in &files {
let result = inner_result.clone();
let db = db.clone();
let project_span = project_span.clone();
scope.spawn(move |_| {
let check_file_span = tracing::debug_span!(parent: &project_span, "check_file", file=%file.path(&db));
let _entered = check_file_span.entered();
let file_diagnostics = check_file(&db, file);
result.lock().unwrap().extend(file_diagnostics);
});
}
});
Arc::into_inner(result).unwrap().into_inner().unwrap()
}
/// Opens a file in the project.
///
/// This changes the behavior of `check` to only check the open files rather than all files in the project.
pub fn open_file(self, db: &mut dyn Db, file: File) {
tracing::debug!("Opening file `{}`", file.path(db));
let mut open_files = self.take_open_files(db);
open_files.insert(file);
self.set_open_files(db, open_files);
}
/// Closes a file in the project.
pub fn close_file(self, db: &mut dyn Db, file: File) -> bool {
tracing::debug!("Closing file `{}`", file.path(db));
let mut open_files = self.take_open_files(db);
let removed = open_files.remove(&file);
if removed {
self.set_open_files(db, open_files);
}
removed
}
/// Returns the open files in the project or `None` if the entire project should be checked.
pub fn open_files(self, db: &dyn Db) -> Option<&FxHashSet<File>> {
self.open_fileset(db).as_deref()
}
/// Sets the open files in the project.
///
/// This changes the behavior of `check` to only check the open files rather than all files in the project.
#[tracing::instrument(level = "debug", skip(self, db))]
pub fn set_open_files(self, db: &mut dyn Db, open_files: FxHashSet<File>) {
tracing::debug!("Set open project files (count: {})", open_files.len());
self.set_open_fileset(db).to(Some(Arc::new(open_files)));
}
/// This takes the open files from the project and returns them.
///
/// This changes the behavior of `check` to check all files in the project instead of just the open files.
fn take_open_files(self, db: &mut dyn Db) -> FxHashSet<File> {
tracing::debug!("Take open project files");
// Salsa will cancel any pending queries and remove its own reference to `open_files`
// so that the reference counter to `open_files` now drops to 1.
let open_files = self.set_open_fileset(db).to(None);
if let Some(open_files) = open_files {
Arc::try_unwrap(open_files).unwrap()
} else {
FxHashSet::default()
}
}
/// Returns `true` if the file is open in the project.
///
/// A file is considered open when:
/// * explicitly set as an open file using [`open_file`](Self::open_file)
/// * It has a [`SystemPath`] and belongs to a package's `src` files
/// * It has a [`SystemVirtualPath`](ruff_db::system::SystemVirtualPath)
pub fn is_file_open(self, db: &dyn Db, file: File) -> bool {
if let Some(open_files) = self.open_files(db) {
open_files.contains(&file)
} else if file.path(db).is_system_path() {
self.contains_file(db, file)
} else {
file.path(db).is_system_virtual_path()
}
}
/// Returns `true` if `file` is a first-party file part of this package.
pub fn contains_file(self, db: &dyn Db, file: File) -> bool {
self.files(db).contains(&file)
}
#[tracing::instrument(level = "debug", skip(db))]
pub fn remove_file(self, db: &mut dyn Db, file: File) {
tracing::debug!(
"Removing file `{}` from project `{}`",
file.path(db),
self.name(db)
);
let Some(mut index) = IndexedFiles::indexed_mut(db, self) else {
return;
};
index.remove(file);
}
pub fn add_file(self, db: &mut dyn Db, file: File) {
tracing::debug!(
"Adding file `{}` to project `{}`",
file.path(db),
self.name(db)
);
let Some(mut index) = IndexedFiles::indexed_mut(db, self) else {
return;
};
index.insert(file);
}
/// Returns the files belonging to this project.
pub fn files(self, db: &dyn Db) -> Indexed<'_> {
let files = self.file_set(db);
let indexed = match files.get() {
Index::Lazy(vacant) => {
let _entered =
tracing::debug_span!("Project::index_files", package = %self.name(db))
.entered();
let files = discover_project_files(db, self);
tracing::info!("Found {} files in project `{}`", files.len(), self.name(db));
vacant.set(files)
}
Index::Indexed(indexed) => indexed,
};
indexed
}
pub fn reload_files(self, db: &mut dyn Db) {
tracing::debug!("Reloading files for project `{}`", self.name(db));
if !self.file_set(db).is_lazy() {
// Force a re-index of the files in the next revision.
self.set_file_set(db).to(IndexedFiles::lazy());
}
}
}
pub(crate) fn check_file(db: &dyn Db, file: File) -> Vec<Box<dyn Diagnostic>> {
let mut diagnostics: Vec<Box<dyn Diagnostic>> = Vec::new();
// Abort checking if there are IO errors.
let source = source_text(db.upcast(), file);
if let Some(read_error) = source.read_error() {
diagnostics.push(Box::new(IOErrorDiagnostic {
file,
error: read_error.clone(),
}));
return diagnostics;
}
let parsed = parsed_module(db.upcast(), file);
diagnostics.extend(parsed.errors().iter().map(|error| {
let diagnostic: Box<dyn Diagnostic> = Box::new(ParseDiagnostic::new(file, error.clone()));
diagnostic
}));
diagnostics.extend(check_types(db.upcast(), file).iter().map(|diagnostic| {
let boxed: Box<dyn Diagnostic> = Box::new(diagnostic.clone());
boxed
}));
diagnostics.sort_unstable_by_key(|diagnostic| diagnostic.range().unwrap_or_default().start());
diagnostics
}
fn discover_project_files(db: &dyn Db, project: Project) -> FxHashSet<File> {
let paths = std::sync::Mutex::new(Vec::new());
db.system().walk_directory(project.root(db)).run(|| {
Box::new(|entry| {
match entry {
Ok(entry) => {
// Skip over any non python files to avoid creating too many entries in `Files`.
match entry.file_type() {
FileType::File => {
if entry
.path()
.extension()
.and_then(PySourceType::try_from_extension)
.is_some()
{
let mut paths = paths.lock().unwrap();
paths.push(entry.into_path());
}
}
FileType::Directory | FileType::Symlink => {}
}
}
Err(error) => {
// TODO Handle error
tracing::error!("Failed to walk path: {error}");
}
}
WalkState::Continue
})
});
let paths = paths.into_inner().unwrap();
let mut files = FxHashSet::with_capacity_and_hasher(paths.len(), FxBuildHasher);
for path in paths {
// If this returns `None`, then the file was deleted between the `walk_directory` call and now.
// We can ignore this.
if let Ok(file) = system_path_to_file(db.upcast(), &path) {
files.insert(file);
}
}
files
}
#[derive(Debug)]
enum ProjectFiles<'a> {
OpenFiles(&'a FxHashSet<File>),
Indexed(files::Indexed<'a>),
}
impl<'a> ProjectFiles<'a> {
fn new(db: &'a dyn Db, project: Project) -> Self {
if let Some(open_files) = project.open_files(db) {
ProjectFiles::OpenFiles(open_files)
} else {
ProjectFiles::Indexed(project.files(db))
}
}
}
impl<'a> IntoIterator for &'a ProjectFiles<'a> {
type Item = File;
type IntoIter = ProjectFilesIter<'a>;
fn into_iter(self) -> Self::IntoIter {
match self {
ProjectFiles::OpenFiles(files) => ProjectFilesIter::OpenFiles(files.iter()),
ProjectFiles::Indexed(indexed) => ProjectFilesIter::Indexed {
files: indexed.into_iter(),
},
}
}
}
enum ProjectFilesIter<'db> {
OpenFiles(std::collections::hash_set::Iter<'db, File>),
Indexed { files: files::IndexedIter<'db> },
}
impl Iterator for ProjectFilesIter<'_> {
type Item = File;
fn next(&mut self) -> Option<Self::Item> {
match self {
ProjectFilesIter::OpenFiles(files) => files.next().copied(),
ProjectFilesIter::Indexed { files } => files.next(),
}
}
}
#[derive(Debug)]
pub struct IOErrorDiagnostic {
file: File,
error: SourceTextError,
}
impl Diagnostic for IOErrorDiagnostic {
fn id(&self) -> DiagnosticId {
DiagnosticId::Io
}
fn message(&self) -> Cow<str> {
self.error.to_string().into()
}
fn file(&self) -> File {
self.file
}
fn range(&self) -> Option<TextRange> {
None
}
fn severity(&self) -> Severity {
Severity::Error
}
}
#[cfg(test)]
mod tests {
use crate::db::tests::TestDb;
use crate::{check_file, ProjectMetadata};
use red_knot_python_semantic::types::check_types;
use ruff_db::diagnostic::Diagnostic;
use ruff_db::files::system_path_to_file;
use ruff_db::source::source_text;
use ruff_db::system::{DbWithTestSystem, SystemPath, SystemPathBuf};
use ruff_db::testing::assert_function_query_was_not_run;
use ruff_python_ast::name::Name;
#[test]
fn check_file_skips_type_checking_when_file_cant_be_read() -> ruff_db::system::Result<()> {
let project = ProjectMetadata::new(Name::new_static("test"), SystemPathBuf::from("/"));
let mut db = TestDb::new(project);
let path = SystemPath::new("test.py");
db.write_file(path, "x = 10")?;
let file = system_path_to_file(&db, path).unwrap();
// Now the file gets deleted before we had a chance to read its source text.
db.memory_file_system().remove_file(path)?;
file.sync(&mut db);
assert_eq!(source_text(&db, file).as_str(), "");
assert_eq!(
check_file(&db, file)
.into_iter()
.map(|diagnostic| diagnostic.message().into_owned())
.collect::<Vec<_>>(),
vec!["Failed to read file: No such file or directory".to_string()]
);
let events = db.take_salsa_events();
assert_function_query_was_not_run(&db, check_types, file, &events);
// The user now creates a new file with an empty text. The source text
// content returned by `source_text` remains unchanged, but the diagnostics should get updated.
db.write_file(path, "").unwrap();
assert_eq!(source_text(&db, file).as_str(), "");
assert_eq!(
check_file(&db, file)
.into_iter()
.map(|diagnostic| diagnostic.message().into_owned())
.collect::<Vec<_>>(),
vec![] as Vec<String>
);
Ok(())
}
}

View File

@@ -1,522 +0,0 @@
use red_knot_python_semantic::ProgramSettings;
use ruff_db::system::{System, SystemPath, SystemPathBuf};
use ruff_python_ast::name::Name;
use thiserror::Error;
use crate::combine::Combine;
use crate::metadata::pyproject::{Project, PyProject, PyProjectError};
use options::KnotTomlError;
use options::Options;
pub mod options;
pub mod pyproject;
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize))]
pub struct ProjectMetadata {
pub(super) name: Name,
pub(super) root: SystemPathBuf,
/// The raw options
pub(super) options: Options,
}
impl ProjectMetadata {
/// Creates a project with the given name and root that uses the default options.
pub fn new(name: Name, root: SystemPathBuf) -> Self {
Self {
name,
root,
options: Options::default(),
}
}
/// Loads a project from a `pyproject.toml` file.
pub(crate) fn from_pyproject(pyproject: PyProject, root: SystemPathBuf) -> Self {
Self::from_options(
pyproject
.tool
.and_then(|tool| tool.knot)
.unwrap_or_default(),
root,
pyproject.project.as_ref(),
)
}
/// Loads a project from a set of options with an optional pyproject-project table.
pub(crate) fn from_options(
options: Options,
root: SystemPathBuf,
project: Option<&Project>,
) -> Self {
let name = project
.and_then(|project| project.name.as_ref())
.map(|name| Name::new(&**name))
.unwrap_or_else(|| Name::new(root.file_name().unwrap_or("root")));
// TODO(https://github.com/astral-sh/ruff/issues/15491): Respect requires-python
Self {
name,
root,
options,
}
}
/// Discovers the closest project at `path` and returns its metadata.
///
/// The algorithm traverses upwards in the `path`'s ancestor chain and uses the following precedence
/// the resolve the project's root.
///
/// 1. The closest `pyproject.toml` with a `tool.knot` section or `knot.toml`.
/// 1. The closest `pyproject.toml`.
/// 1. Fallback to use `path` as the root and use the default settings.
pub fn discover(
path: &SystemPath,
system: &dyn System,
) -> Result<ProjectMetadata, ProjectDiscoveryError> {
tracing::debug!("Searching for a project in '{path}'");
if !system.is_directory(path) {
return Err(ProjectDiscoveryError::NotADirectory(path.to_path_buf()));
}
let mut closest_project: Option<ProjectMetadata> = None;
for project_root in path.ancestors() {
let pyproject_path = project_root.join("pyproject.toml");
let pyproject = if let Ok(pyproject_str) = system.read_to_string(&pyproject_path) {
match PyProject::from_toml_str(&pyproject_str) {
Ok(pyproject) => Some(pyproject),
Err(error) => {
return Err(ProjectDiscoveryError::InvalidPyProject {
path: pyproject_path,
source: Box::new(error),
})
}
}
} else {
None
};
// A `knot.toml` takes precedence over a `pyproject.toml`.
let knot_toml_path = project_root.join("knot.toml");
if let Ok(knot_str) = system.read_to_string(&knot_toml_path) {
let options = match Options::from_toml_str(&knot_str) {
Ok(options) => options,
Err(error) => {
return Err(ProjectDiscoveryError::InvalidKnotToml {
path: knot_toml_path,
source: Box::new(error),
})
}
};
if pyproject
.as_ref()
.is_some_and(|project| project.knot().is_some())
{
// TODO: Consider using a diagnostic here
tracing::warn!("Ignoring the `tool.knot` section in `{pyproject_path}` because `{knot_toml_path}` takes precedence.");
}
tracing::debug!("Found project at '{}'", project_root);
return Ok(ProjectMetadata::from_options(
options,
project_root.to_path_buf(),
pyproject
.as_ref()
.and_then(|pyproject| pyproject.project.as_ref()),
));
}
if let Some(pyproject) = pyproject {
let has_knot_section = pyproject.knot().is_some();
let metadata =
ProjectMetadata::from_pyproject(pyproject, project_root.to_path_buf());
if has_knot_section {
tracing::debug!("Found project at '{}'", project_root);
return Ok(metadata);
}
// Not a project itself, keep looking for an enclosing project.
if closest_project.is_none() {
closest_project = Some(metadata);
}
}
}
// No project found, but maybe a pyproject.toml was found.
let metadata = if let Some(closest_project) = closest_project {
tracing::debug!(
"Project without `tool.knot` section: '{}'",
closest_project.root()
);
closest_project
} else {
tracing::debug!("The ancestor directories contain no `pyproject.toml`. Falling back to a virtual project.");
// Create a project with a default configuration
Self::new(
path.file_name().unwrap_or("root").into(),
path.to_path_buf(),
)
};
Ok(metadata)
}
pub fn root(&self) -> &SystemPath {
&self.root
}
pub fn name(&self) -> &str {
&self.name
}
pub fn options(&self) -> &Options {
&self.options
}
pub fn to_program_settings(&self, system: &dyn System) -> ProgramSettings {
self.options.to_program_settings(self.root(), system)
}
/// Combine the project options with the CLI options where the CLI options take precedence.
pub fn apply_cli_options(&mut self, options: Options) {
self.options = options.combine(std::mem::take(&mut self.options));
}
/// Combine the project options with the user options where project options take precedence.
pub fn apply_user_options(&mut self, options: Options) {
self.options.combine_with(options);
}
}
#[derive(Debug, Error)]
pub enum ProjectDiscoveryError {
#[error("project path '{0}' is not a directory")]
NotADirectory(SystemPathBuf),
#[error("{path} is not a valid `pyproject.toml`: {source}")]
InvalidPyProject {
source: Box<PyProjectError>,
path: SystemPathBuf,
},
#[error("{path} is not a valid `knot.toml`: {source}")]
InvalidKnotToml {
source: Box<KnotTomlError>,
path: SystemPathBuf,
},
}
#[cfg(test)]
mod tests {
//! Integration tests for project discovery
use crate::snapshot_project;
use anyhow::{anyhow, Context};
use insta::assert_ron_snapshot;
use ruff_db::system::{SystemPathBuf, TestSystem};
use crate::{ProjectDiscoveryError, ProjectMetadata};
#[test]
fn project_without_pyproject() -> anyhow::Result<()> {
let system = TestSystem::default();
let root = SystemPathBuf::from("/app");
system
.memory_file_system()
.write_files([(root.join("foo.py"), ""), (root.join("bar.py"), "")])
.context("Failed to write files")?;
let project =
ProjectMetadata::discover(&root, &system).context("Failed to discover project")?;
assert_eq!(project.root(), &*root);
snapshot_project!(project);
Ok(())
}
#[test]
fn project_with_pyproject() -> anyhow::Result<()> {
let system = TestSystem::default();
let root = SystemPathBuf::from("/app");
system
.memory_file_system()
.write_files([
(
root.join("pyproject.toml"),
r#"
[project]
name = "backend"
"#,
),
(root.join("db/__init__.py"), ""),
])
.context("Failed to write files")?;
let project =
ProjectMetadata::discover(&root, &system).context("Failed to discover project")?;
assert_eq!(project.root(), &*root);
snapshot_project!(project);
// Discovering the same package from a subdirectory should give the same result
let from_src = ProjectMetadata::discover(&root.join("db"), &system)
.context("Failed to discover project from src sub-directory")?;
assert_eq!(from_src, project);
Ok(())
}
#[test]
fn project_with_invalid_pyproject() -> anyhow::Result<()> {
let system = TestSystem::default();
let root = SystemPathBuf::from("/app");
system
.memory_file_system()
.write_files([
(
root.join("pyproject.toml"),
r#"
[project]
name = "backend"
[tool.knot
"#,
),
(root.join("db/__init__.py"), ""),
])
.context("Failed to write files")?;
let Err(error) = ProjectMetadata::discover(&root, &system) else {
return Err(anyhow!("Expected project discovery to fail because of invalid syntax in the pyproject.toml"));
};
assert_error_eq(
&error,
r#"/app/pyproject.toml is not a valid `pyproject.toml`: TOML parse error at line 5, column 31
|
5 | [tool.knot
| ^
invalid table header
expected `.`, `]`
"#,
);
Ok(())
}
#[test]
fn nested_projects_in_sub_project() -> anyhow::Result<()> {
let system = TestSystem::default();
let root = SystemPathBuf::from("/app");
system
.memory_file_system()
.write_files([
(
root.join("pyproject.toml"),
r#"
[project]
name = "project-root"
[tool.knot.src]
root = "src"
"#,
),
(
root.join("packages/a/pyproject.toml"),
r#"
[project]
name = "nested-project"
[tool.knot.src]
root = "src"
"#,
),
])
.context("Failed to write files")?;
let sub_project = ProjectMetadata::discover(&root.join("packages/a"), &system)?;
snapshot_project!(sub_project);
Ok(())
}
#[test]
fn nested_projects_in_root_project() -> anyhow::Result<()> {
let system = TestSystem::default();
let root = SystemPathBuf::from("/app");
system
.memory_file_system()
.write_files([
(
root.join("pyproject.toml"),
r#"
[project]
name = "project-root"
[tool.knot.src]
root = "src"
"#,
),
(
root.join("packages/a/pyproject.toml"),
r#"
[project]
name = "nested-project"
[tool.knot.src]
root = "src"
"#,
),
])
.context("Failed to write files")?;
let root = ProjectMetadata::discover(&root, &system)?;
snapshot_project!(root);
Ok(())
}
#[test]
fn nested_projects_without_knot_sections() -> anyhow::Result<()> {
let system = TestSystem::default();
let root = SystemPathBuf::from("/app");
system
.memory_file_system()
.write_files([
(
root.join("pyproject.toml"),
r#"
[project]
name = "project-root"
"#,
),
(
root.join("packages/a/pyproject.toml"),
r#"
[project]
name = "nested-project"
"#,
),
])
.context("Failed to write files")?;
let sub_project = ProjectMetadata::discover(&root.join("packages/a"), &system)?;
snapshot_project!(sub_project);
Ok(())
}
#[test]
fn nested_projects_with_outer_knot_section() -> anyhow::Result<()> {
let system = TestSystem::default();
let root = SystemPathBuf::from("/app");
system
.memory_file_system()
.write_files([
(
root.join("pyproject.toml"),
r#"
[project]
name = "project-root"
[tool.knot.environment]
python-version = "3.10"
"#,
),
(
root.join("packages/a/pyproject.toml"),
r#"
[project]
name = "nested-project"
"#,
),
])
.context("Failed to write files")?;
let root = ProjectMetadata::discover(&root.join("packages/a"), &system)?;
snapshot_project!(root);
Ok(())
}
/// A `knot.toml` takes precedence over any `pyproject.toml`.
///
/// However, the `pyproject.toml` is still loaded to get the project name and, in the future,
/// the requires-python constraint.
#[test]
fn project_with_knot_and_pyproject_toml() -> anyhow::Result<()> {
let system = TestSystem::default();
let root = SystemPathBuf::from("/app");
system
.memory_file_system()
.write_files([
(
root.join("pyproject.toml"),
r#"
[project]
name = "super-app"
requires-python = ">=3.12"
[tool.knot.src]
root = "this_option_is_ignored"
"#,
),
(
root.join("knot.toml"),
r#"
[src]
root = "src"
"#,
),
])
.context("Failed to write files")?;
let root = ProjectMetadata::discover(&root, &system)?;
snapshot_project!(root);
Ok(())
}
#[track_caller]
fn assert_error_eq(error: &ProjectDiscoveryError, message: &str) {
assert_eq!(error.to_string().replace('\\', "/"), message);
}
/// Snapshots a project but with all paths using unix separators.
#[macro_export]
macro_rules! snapshot_project {
($project:expr) => {{
assert_ron_snapshot!($project,{
".root" => insta::dynamic_redaction(|content, _content_path| {
content.as_str().unwrap().replace("\\", "/")
}),
});
}};
}
}

View File

@@ -1,117 +0,0 @@
use red_knot_python_semantic::{
ProgramSettings, PythonPlatform, PythonVersion, SearchPathSettings, SitePackages,
};
use ruff_db::system::{System, SystemPath, SystemPathBuf};
use ruff_macros::Combine;
use serde::{Deserialize, Serialize};
use thiserror::Error;
/// The options for the project.
#[derive(Debug, Default, Clone, PartialEq, Eq, Combine, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct Options {
pub environment: Option<EnvironmentOptions>,
pub src: Option<SrcOptions>,
}
impl Options {
pub(crate) fn from_toml_str(content: &str) -> Result<Self, KnotTomlError> {
let options = toml::from_str(content)?;
Ok(options)
}
pub(crate) fn to_program_settings(
&self,
project_root: &SystemPath,
system: &dyn System,
) -> ProgramSettings {
let (python_version, python_platform) = self
.environment
.as_ref()
.map(|env| (env.python_version, env.python_platform.as_ref()))
.unwrap_or_default();
ProgramSettings {
python_version: python_version.unwrap_or_default(),
python_platform: python_platform.cloned().unwrap_or_default(),
search_paths: self.to_search_path_settings(project_root, system),
}
}
fn to_search_path_settings(
&self,
project_root: &SystemPath,
system: &dyn System,
) -> SearchPathSettings {
let src_roots =
if let Some(src_root) = self.src.as_ref().and_then(|src| src.root.as_deref()) {
vec![src_root.to_path_buf()]
} else {
let src = project_root.join("src");
// Default to `src` and the project root if `src` exists and the root hasn't been specified.
if system.is_directory(&src) {
vec![project_root.to_path_buf(), src]
} else {
vec![project_root.to_path_buf()]
}
};
let (extra_paths, python, typeshed) = self
.environment
.as_ref()
.map(|env| {
(
env.extra_paths.clone(),
env.venv_path.clone(),
env.typeshed.clone(),
)
})
.unwrap_or_default();
SearchPathSettings {
extra_paths: extra_paths.unwrap_or_default(),
src_roots,
typeshed,
site_packages: python
.map(|venv_path| SitePackages::Derived { venv_path })
.unwrap_or(SitePackages::Known(vec![])),
}
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct EnvironmentOptions {
pub python_version: Option<PythonVersion>,
pub python_platform: Option<PythonPlatform>,
/// List of user-provided paths that should take first priority in the module resolution.
/// Examples in other type checkers are mypy's MYPYPATH environment variable,
/// or pyright's stubPath configuration setting.
pub extra_paths: Option<Vec<SystemPathBuf>>,
/// Optional path to a "typeshed" directory on disk for us to use for standard-library types.
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
/// bundled as a zip file in the binary
pub typeshed: Option<SystemPathBuf>,
// TODO: Rename to python, see https://github.com/astral-sh/ruff/issues/15530
/// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.
pub venv_path: Option<SystemPathBuf>,
}
#[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct SrcOptions {
/// The root of the project, used for finding first-party modules.
pub root: Option<SystemPathBuf>,
}
#[derive(Error, Debug)]
pub enum KnotTomlError {
#[error(transparent)]
TomlSyntax(#[from] toml::de::Error),
}

View File

@@ -1,14 +0,0 @@
---
source: crates/red_knot_project/src/metadata.rs
expression: root
---
ProjectMetadata(
name: Name("project-root"),
root: "/app",
options: Options(
environment: None,
src: Some(SrcOptions(
root: Some("src"),
)),
),
)

View File

@@ -1,14 +0,0 @@
---
source: crates/red_knot_project/src/metadata.rs
expression: sub_project
---
ProjectMetadata(
name: Name("nested-project"),
root: "/app/packages/a",
options: Options(
environment: None,
src: Some(SrcOptions(
root: Some("src"),
)),
),
)

View File

@@ -1,18 +0,0 @@
---
source: crates/red_knot_project/src/metadata.rs
expression: root
---
ProjectMetadata(
name: Name("project-root"),
root: "/app",
options: Options(
environment: Some(EnvironmentOptions(
r#python-version: Some("3.10"),
r#python-platform: None,
r#extra-paths: None,
typeshed: None,
r#venv-path: None,
)),
src: None,
),
)

View File

@@ -1,12 +0,0 @@
---
source: crates/red_knot_project/src/metadata.rs
expression: sub_project
---
ProjectMetadata(
name: Name("nested-project"),
root: "/app/packages/a",
options: Options(
environment: None,
src: None,
),
)

View File

@@ -1,14 +0,0 @@
---
source: crates/red_knot_project/src/metadata.rs
expression: root
---
ProjectMetadata(
name: Name("super-app"),
root: "/app",
options: Options(
environment: None,
src: Some(SrcOptions(
root: Some("src"),
)),
),
)

View File

@@ -1,12 +0,0 @@
---
source: crates/red_knot_project/src/metadata.rs
expression: project
---
ProjectMetadata(
name: Name("backend"),
root: "/app",
options: Options(
environment: None,
src: None,
),
)

View File

@@ -1,12 +0,0 @@
---
source: crates/red_knot_project/src/metadata.rs
expression: project
---
ProjectMetadata(
name: Name("app"),
root: "/app",
options: Options(
environment: None,
src: None,
),
)

View File

@@ -1,83 +0,0 @@
# Any
## Annotation
`typing.Any` is a way to name the Any type.
```py
from typing import Any
x: Any = 1
x = "foo"
def f():
reveal_type(x) # revealed: Any
```
## Aliased to a different name
If you alias `typing.Any` to another name, we still recognize that as a spelling of the Any type.
```py
from typing import Any as RenamedAny
x: RenamedAny = 1
x = "foo"
def f():
reveal_type(x) # revealed: Any
```
## Shadowed class
If you define your own class named `Any`, using that in a type expression refers to your class, and
isn't a spelling of the Any type.
```py
class Any: ...
x: Any
def f():
reveal_type(x) # revealed: Any
# This verifies that we're not accidentally seeing typing.Any, since str is assignable
# to that but not to our locally defined class.
y: Any = "not an Any" # error: [invalid-assignment]
```
## Subclass
The spec allows you to define subclasses of `Any`.
TODO: Handle assignments correctly. `Subclass` has an unknown superclass, which might be `int`. The
assignment to `x` should not be allowed, even when the unknown superclass is `int`. The assignment
to `y` should be allowed, since `Subclass` might have `int` as a superclass, and is therefore
assignable to `int`.
```py
from typing import Any
class Subclass(Any): ...
reveal_type(Subclass.__mro__) # revealed: tuple[Literal[Subclass], Any, Literal[object]]
x: Subclass = 1 # error: [invalid-assignment]
# TODO: no diagnostic
y: int = Subclass() # error: [invalid-assignment]
def _(s: Subclass):
reveal_type(s) # revealed: Subclass
```
## Invalid
`Any` cannot be parameterized:
```py
from typing import Any
# error: [invalid-type-form] "Type `typing.Any` expected no type parameter"
def f(x: Any[int]):
reveal_type(x) # revealed: Unknown
```

View File

@@ -1,127 +0,0 @@
# Typing-module aliases to other stdlib classes
The `typing` module has various aliases to other stdlib classes. These are a legacy feature, but
still need to be supported by a type checker.
## Correspondence
All of the following symbols can be mapped one-to-one with the actual type:
```py
import typing
def f(
list_bare: typing.List,
list_parametrized: typing.List[int],
dict_bare: typing.Dict,
dict_parametrized: typing.Dict[int, str],
set_bare: typing.Set,
set_parametrized: typing.Set[int],
frozen_set_bare: typing.FrozenSet,
frozen_set_parametrized: typing.FrozenSet[str],
chain_map_bare: typing.ChainMap,
chain_map_parametrized: typing.ChainMap[int],
counter_bare: typing.Counter,
counter_parametrized: typing.Counter[int],
default_dict_bare: typing.DefaultDict,
default_dict_parametrized: typing.DefaultDict[str, int],
deque_bare: typing.Deque,
deque_parametrized: typing.Deque[str],
ordered_dict_bare: typing.OrderedDict,
ordered_dict_parametrized: typing.OrderedDict[int, str],
):
reveal_type(list_bare) # revealed: list
reveal_type(list_parametrized) # revealed: list
reveal_type(dict_bare) # revealed: dict
reveal_type(dict_parametrized) # revealed: dict
reveal_type(set_bare) # revealed: set
reveal_type(set_parametrized) # revealed: set
reveal_type(frozen_set_bare) # revealed: frozenset
reveal_type(frozen_set_parametrized) # revealed: frozenset
reveal_type(chain_map_bare) # revealed: ChainMap
reveal_type(chain_map_parametrized) # revealed: ChainMap
reveal_type(counter_bare) # revealed: Counter
reveal_type(counter_parametrized) # revealed: Counter
reveal_type(default_dict_bare) # revealed: defaultdict
reveal_type(default_dict_parametrized) # revealed: defaultdict
reveal_type(deque_bare) # revealed: deque
reveal_type(deque_parametrized) # revealed: deque
reveal_type(ordered_dict_bare) # revealed: OrderedDict
reveal_type(ordered_dict_parametrized) # revealed: OrderedDict
```
## Inheritance
The aliases can be inherited from. Some of these are still partially or wholly TODOs.
```py
import typing
####################
### Built-ins
class ListSubclass(typing.List): ...
# TODO: should have `Generic`, should not have `Unknown`
# revealed: tuple[Literal[ListSubclass], Literal[list], Unknown, Literal[object]]
reveal_type(ListSubclass.__mro__)
class DictSubclass(typing.Dict): ...
# TODO: should have `Generic`, should not have `Unknown`
# revealed: tuple[Literal[DictSubclass], Literal[dict], Unknown, Literal[object]]
reveal_type(DictSubclass.__mro__)
class SetSubclass(typing.Set): ...
# TODO: should have `Generic`, should not have `Unknown`
# revealed: tuple[Literal[SetSubclass], Literal[set], Unknown, Literal[object]]
reveal_type(SetSubclass.__mro__)
class FrozenSetSubclass(typing.FrozenSet): ...
# TODO: should have `Generic`, should not have `Unknown`
# revealed: tuple[Literal[FrozenSetSubclass], Literal[frozenset], Unknown, Literal[object]]
reveal_type(FrozenSetSubclass.__mro__)
####################
### `collections`
class ChainMapSubclass(typing.ChainMap): ...
# TODO: Should be (ChainMapSubclass, ChainMap, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object)
# revealed: tuple[Literal[ChainMapSubclass], Literal[ChainMap], Unknown, Literal[object]]
reveal_type(ChainMapSubclass.__mro__)
class CounterSubclass(typing.Counter): ...
# TODO: Should be (CounterSubclass, Counter, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object)
# revealed: tuple[Literal[CounterSubclass], Literal[Counter], Unknown, Literal[object]]
reveal_type(CounterSubclass.__mro__)
class DefaultDictSubclass(typing.DefaultDict): ...
# TODO: Should be (DefaultDictSubclass, defaultdict, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object)
# revealed: tuple[Literal[DefaultDictSubclass], Literal[defaultdict], Unknown, Literal[object]]
reveal_type(DefaultDictSubclass.__mro__)
class DequeSubclass(typing.Deque): ...
# TODO: Should be (DequeSubclass, deque, MutableSequence, Sequence, Reversible, Collection, Sized, Iterable, Container, Generic, object)
# revealed: tuple[Literal[DequeSubclass], Literal[deque], Unknown, Literal[object]]
reveal_type(DequeSubclass.__mro__)
class OrderedDictSubclass(typing.OrderedDict): ...
# TODO: Should be (OrderedDictSubclass, OrderedDict, dict, MutableMapping, Mapping, Collection, Sized, Iterable, Container, Generic, object)
# revealed: tuple[Literal[OrderedDictSubclass], Literal[OrderedDict], Unknown, Literal[object]]
reveal_type(OrderedDictSubclass.__mro__)
```

View File

@@ -1,71 +0,0 @@
# Unsupported special forms
## Not yet supported
Several special forms are unsupported by red-knot currently. However, we also don't emit
false-positive errors if you use one in an annotation:
```py
from typing_extensions import Self, TypeVarTuple, Unpack, TypeGuard, TypeIs, Concatenate, ParamSpec, TypeAlias, Callable, TypeVar
P = ParamSpec("P")
Ts = TypeVarTuple("Ts")
R_co = TypeVar("R_co", covariant=True)
Alias: TypeAlias = int
def f(*args: Unpack[Ts]) -> tuple[Unpack[Ts]]:
# TODO: should understand the annotation
reveal_type(args) # revealed: tuple
reveal_type(Alias) # revealed: @Todo(Unsupported or invalid type in a type expression)
def g() -> TypeGuard[int]: ...
def h() -> TypeIs[int]: ...
def i(callback: Callable[Concatenate[int, P], R_co], *args: P.args, **kwargs: P.kwargs) -> R_co:
# TODO: should understand the annotation
reveal_type(args) # revealed: tuple
# TODO: should understand the annotation
reveal_type(kwargs) # revealed: dict
return callback(42, *args, **kwargs)
class Foo:
def method(self, x: Self):
reveal_type(x) # revealed: @Todo(Unsupported or invalid type in a type expression)
```
## Inheritance
You can't inherit from most of these. `typing.Callable` is an exception.
```py
from typing import Callable
from typing_extensions import Self, Unpack, TypeGuard, TypeIs, Concatenate
class A(Self): ... # error: [invalid-base]
class B(Unpack): ... # error: [invalid-base]
class C(TypeGuard): ... # error: [invalid-base]
class D(TypeIs): ... # error: [invalid-base]
class E(Concatenate): ... # error: [invalid-base]
class F(Callable): ...
reveal_type(F.__mro__) # revealed: tuple[Literal[F], @Todo(Support for Callable as a base class), Literal[object]]
```
## Subscriptability
Some of these are not subscriptable:
```py
from typing_extensions import Self, TypeAlias
X: TypeAlias[T] = int # error: [invalid-type-form]
class Foo[T]:
# error: [invalid-type-form] "Special form `typing.Self` expected no type parameter"
# error: [invalid-type-form] "Special form `typing.Self` expected no type parameter"
def method(self: Self[int]) -> Self[int]:
reveal_type(self) # revealed: Unknown
```

View File

@@ -1,34 +0,0 @@
# Unsupported type qualifiers
## Not yet supported
Several type qualifiers are unsupported by red-knot currently. However, we also don't emit
false-positive errors if you use one in an annotation:
```py
from typing_extensions import Final, Required, NotRequired, ReadOnly, TypedDict
X: Final = 42
Y: Final[int] = 42
# TODO: `TypedDict` is actually valid as a base
# error: [invalid-base]
class Bar(TypedDict):
x: Required[int]
y: NotRequired[str]
z: ReadOnly[bytes]
```
## Inheritance
You can't inherit from a type qualifier.
```py
from typing_extensions import Final, ClassVar, Required, NotRequired, ReadOnly
class A(Final): ... # error: [invalid-base]
class B(ClassVar): ... # error: [invalid-base]
class C(Required): ... # error: [invalid-base]
class D(NotRequired): ... # error: [invalid-base]
class E(ReadOnly): ... # error: [invalid-base]
```

View File

@@ -1,512 +0,0 @@
# Attributes
Tests for attribute access on various kinds of types.
## Class and instance variables
### Pure instance variables
#### Variable only declared/bound in `__init__`
Variables only declared and/or bound in `__init__` are pure instance variables. They cannot be
accessed on the class itself.
```py
class C:
def __init__(self, value2: int, flag: bool = False) -> None:
# bound but not declared
self.pure_instance_variable1 = "value set in __init__"
# bound but not declared - with type inferred from parameter
self.pure_instance_variable2 = value2
# declared but not bound
self.pure_instance_variable3: bytes
# declared and bound
self.pure_instance_variable4: bool = True
# possibly undeclared/unbound
if flag:
self.pure_instance_variable5: str = "possibly set in __init__"
c_instance = C(1)
# TODO: should be `Literal["value set in __init__"]`, or `Unknown | Literal[…]` to allow
# assignments to this unannotated attribute from other scopes.
reveal_type(c_instance.pure_instance_variable1) # revealed: @Todo(implicit instance attribute)
# TODO: should be `int`
reveal_type(c_instance.pure_instance_variable2) # revealed: @Todo(implicit instance attribute)
# TODO: should be `bytes`
reveal_type(c_instance.pure_instance_variable3) # revealed: @Todo(implicit instance attribute)
# TODO: should be `bool`
reveal_type(c_instance.pure_instance_variable4) # revealed: @Todo(implicit instance attribute)
# TODO: should be `str`
# We probably don't want to emit a diagnostic for this being possibly undeclared/unbound.
# mypy and pyright do not show an error here.
reveal_type(c_instance.pure_instance_variable5) # revealed: @Todo(implicit instance attribute)
# TODO: If we choose to infer a precise `Literal[…]` type for the instance attribute (see
# above), this should be an error: incompatible types in assignment. If we choose to infer
# a gradual `Unknown | Literal[…]` type, this assignment is fine.
c_instance.pure_instance_variable1 = "value set on instance"
# TODO: this should be an error (incompatible types in assignment)
c_instance.pure_instance_variable2 = "incompatible"
# TODO: we already show an error here but the message might be improved?
# mypy shows no error here, but pyright raises "reportAttributeAccessIssue"
# error: [unresolved-attribute] "Type `Literal[C]` has no attribute `pure_instance_variable1`"
reveal_type(C.pure_instance_variable1) # revealed: Unknown
# TODO: this should be an error (pure instance variables cannot be accessed on the class)
# mypy shows no error here, but pyright raises "reportAttributeAccessIssue"
C.pure_instance_variable1 = "overwritten on class"
c_instance.pure_instance_variable4 = False
# TODO: After this assignment to the attribute within this scope, we may eventually want to narrow
# the `bool` type (see above) for this instance variable to `Literal[False]` here. This is unsound
# in general (we don't know what else happened to `c_instance` between the assignment and the use
# here), but mypy and pyright support this. In conclusion, this could be `bool` but should probably
# be `Literal[False]`.
reveal_type(c_instance.pure_instance_variable4) # revealed: @Todo(implicit instance attribute)
```
#### Variable declared in class body and declared/bound in `__init__`
The same rule applies even if the variable is *declared* (not bound!) in the class body: it is still
a pure instance variable.
```py
class C:
pure_instance_variable: str
def __init__(self) -> None:
self.pure_instance_variable = "value set in __init__"
c_instance = C()
reveal_type(c_instance.pure_instance_variable) # revealed: str
# TODO: we currently plan to emit a diagnostic here. Note that both mypy
# and pyright show no error in this case! So we may reconsider this in
# the future, if it turns out to produce too many false positives.
reveal_type(C.pure_instance_variable) # revealed: str
# TODO: same as above. We plan to emit a diagnostic here, even if both mypy
# and pyright allow this.
C.pure_instance_variable = "overwritten on class"
# TODO: this should be an error (incompatible types in assignment)
c_instance.pure_instance_variable = 1
```
#### Variable only defined in unrelated method
We also recognize pure instance variables if they are defined in a method that is not `__init__`.
```py
class C:
def set_instance_variable(self) -> None:
self.pure_instance_variable = "value set in method"
c_instance = C()
# Not that we would use this in static analysis, but for a more realistic example, let's actually
# call the method, so that the attribute is bound if this example is actually run.
c_instance.set_instance_variable()
# TODO: should be `Literal["value set in method"]` or `Unknown | Literal[…]` (see above).
reveal_type(c_instance.pure_instance_variable) # revealed: @Todo(implicit instance attribute)
# TODO: We already show an error here, but the message might be improved?
# error: [unresolved-attribute]
reveal_type(C.pure_instance_variable) # revealed: Unknown
# TODO: this should be an error
C.pure_instance_variable = "overwritten on class"
```
#### Variable declared in class body and not bound anywhere
If a variable is declared in the class body but not bound anywhere, we still consider it a pure
instance variable and allow access to it via instances.
```py
class C:
pure_instance_variable: str
c_instance = C()
reveal_type(c_instance.pure_instance_variable) # revealed: str
# TODO: mypy and pyright do not show an error here, but we plan to emit a diagnostic.
# The type could be changed to 'Unknown' if we decide to emit an error?
reveal_type(C.pure_instance_variable) # revealed: str
# TODO: mypy and pyright do not show an error here, but we plan to emit one.
C.pure_instance_variable = "overwritten on class"
```
### Pure class variables (`ClassVar`)
#### Annotated with `ClassVar` type qualifier
Class variables annotated with the [`typing.ClassVar`] type qualifier are pure class variables. They
cannot be overwritten on instances, but they can be accessed on instances.
For more details, see the [typing spec on `ClassVar`].
```py
from typing import ClassVar
class C:
pure_class_variable1: ClassVar[str] = "value in class body"
pure_class_variable2: ClassVar = 1
def method(self):
# TODO: this should be an error
self.pure_class_variable1 = "value set through instance"
reveal_type(C.pure_class_variable1) # revealed: str
# TODO: this should be `Literal[1]`, or `Unknown | Literal[1]`.
reveal_type(C.pure_class_variable2) # revealed: Unknown
c_instance = C()
# It is okay to access a pure class variable on an instance.
reveal_type(c_instance.pure_class_variable1) # revealed: str
# TODO: Should be `Unknown | Literal[1]`.
reveal_type(c_instance.pure_class_variable2) # revealed: Unknown
# error: [invalid-attribute-access] "Cannot assign to ClassVar `pure_class_variable1` from an instance of type `C`"
c_instance.pure_class_variable1 = "value set on instance"
C.pure_class_variable1 = "overwritten on class"
# TODO: should raise an error (incompatible types in assignment)
C.pure_class_variable1 = 1
class Subclass(C):
pure_class_variable1: ClassVar[str] = "overwritten on subclass"
reveal_type(Subclass.pure_class_variable1) # revealed: str
```
#### Variable only mentioned in a class method
We also consider a class variable to be a pure class variable if it is only mentioned in a class
method.
```py
class C:
@classmethod
def class_method(cls):
cls.pure_class_variable = "value set in class method"
# for a more realistic example, let's actually call the method
C.class_method()
# TODO: We currently plan to support this and show no error here.
# mypy shows an error here, pyright does not.
# error: [unresolved-attribute]
reveal_type(C.pure_class_variable) # revealed: Unknown
C.pure_class_variable = "overwritten on class"
# TODO: should be `Literal["overwritten on class"]`
# error: [unresolved-attribute]
reveal_type(C.pure_class_variable) # revealed: Unknown
c_instance = C()
# TODO: should be `Literal["overwritten on class"]`
reveal_type(c_instance.pure_class_variable) # revealed: @Todo(implicit instance attribute)
# TODO: should raise an error.
c_instance.pure_class_variable = "value set on instance"
```
### Instance variables with class-level default values
These are instance attributes, but the fact that we can see that they have a binding (not a
declaration) in the class body means that reading the value from the class directly is also
permitted. This is the only difference for these attributes as opposed to "pure" instance
attributes.
#### Basic
```py
class C:
variable_with_class_default1: str = "value in class body"
variable_with_class_default2 = 1
def instance_method(self):
self.variable_with_class_default1 = "value set in instance method"
reveal_type(C.variable_with_class_default1) # revealed: str
# TODO: this should be `Unknown | Literal[1]`.
reveal_type(C.variable_with_class_default2) # revealed: Literal[1]
c_instance = C()
reveal_type(c_instance.variable_with_class_default1) # revealed: str
reveal_type(c_instance.variable_with_class_default2) # revealed: Unknown | Literal[1]
c_instance.variable_with_class_default1 = "value set on instance"
reveal_type(C.variable_with_class_default1) # revealed: str
# TODO: Could be Literal["value set on instance"], or still `str` if we choose not to
# narrow the type.
reveal_type(c_instance.variable_with_class_default1) # revealed: str
C.variable_with_class_default1 = "overwritten on class"
# TODO: Could be `Literal["overwritten on class"]`, or still `str` if we choose not to
# narrow the type.
reveal_type(C.variable_with_class_default1) # revealed: str
# TODO: should still be `Literal["value set on instance"]`, or `str`.
reveal_type(c_instance.variable_with_class_default1) # revealed: str
```
## Union of attributes
```py
def _(flag: bool):
if flag:
class C1:
x = 1
else:
class C1:
x = 2
class C2:
if flag:
x = 3
else:
x = 4
reveal_type(C1.x) # revealed: Literal[1, 2]
reveal_type(C2.x) # revealed: Literal[3, 4]
```
## Inherited class attributes
### Basic
```py
class A:
X = "foo"
class B(A): ...
class C(B): ...
reveal_type(C.X) # revealed: Literal["foo"]
```
### Multiple inheritance
```py
class O: ...
class F(O):
X = 56
class E(O):
X = 42
class D(O): ...
class C(D, F): ...
class B(E, D): ...
class A(B, C): ...
# revealed: tuple[Literal[A], Literal[B], Literal[E], Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
reveal_type(A.__mro__)
# `E` is earlier in the MRO than `F`, so we should use the type of `E.X`
reveal_type(A.X) # revealed: Literal[42]
```
## Unions with possibly unbound paths
### Definite boundness within a class
In this example, the `x` attribute is not defined in the `C2` element of the union:
```py
def _(flag1: bool, flag2: bool):
class C1:
x = 1
class C2: ...
class C3:
x = 3
C = C1 if flag1 else C2 if flag2 else C3
# error: [possibly-unbound-attribute] "Attribute `x` on type `Literal[C1, C2, C3]` is possibly unbound"
reveal_type(C.x) # revealed: Literal[1, 3]
```
### Possibly-unbound within a class
We raise the same diagnostic if the attribute is possibly-unbound in at least one element of the
union:
```py
def _(flag: bool, flag1: bool, flag2: bool):
class C1:
x = 1
class C2:
if flag:
x = 2
class C3:
x = 3
C = C1 if flag1 else C2 if flag2 else C3
# error: [possibly-unbound-attribute] "Attribute `x` on type `Literal[C1, C2, C3]` is possibly unbound"
reveal_type(C.x) # revealed: Literal[1, 2, 3]
```
### Unions with all paths unbound
If the symbol is unbound in all elements of the union, we detect that:
```py
def _(flag: bool):
class C1: ...
class C2: ...
C = C1 if flag else C2
# error: [unresolved-attribute] "Type `Literal[C1, C2]` has no attribute `x`"
reveal_type(C.x) # revealed: Unknown
```
## Objects of all types have a `__class__` method
```py
import typing_extensions
reveal_type(typing_extensions.__class__) # revealed: Literal[ModuleType]
a = 42
reveal_type(a.__class__) # revealed: Literal[int]
b = "42"
reveal_type(b.__class__) # revealed: Literal[str]
c = b"42"
reveal_type(c.__class__) # revealed: Literal[bytes]
d = True
reveal_type(d.__class__) # revealed: Literal[bool]
e = (42, 42)
reveal_type(e.__class__) # revealed: Literal[tuple]
def f(a: int, b: typing_extensions.LiteralString, c: int | str, d: type[str]):
reveal_type(a.__class__) # revealed: type[int]
reveal_type(b.__class__) # revealed: Literal[str]
reveal_type(c.__class__) # revealed: type[int] | type[str]
# `type[type]`, a.k.a., either the class `type` or some subclass of `type`.
# It would be incorrect to infer `Literal[type]` here,
# as `c` could be some subclass of `str` with a custom metaclass.
# All we know is that the metaclass must be a (non-strict) subclass of `type`.
reveal_type(d.__class__) # revealed: type[type]
reveal_type(f.__class__) # revealed: Literal[FunctionType]
class Foo: ...
reveal_type(Foo.__class__) # revealed: Literal[type]
```
## Literal types
### Function-literal attributes
Most attribute accesses on function-literal types are delegated to `types.FunctionType`, since all
functions are instances of that class:
```py path=a.py
def f(): ...
reveal_type(f.__defaults__) # revealed: @Todo(full tuple[...] support) | None
reveal_type(f.__kwdefaults__) # revealed: @Todo(generics) | None
```
Some attributes are special-cased, however:
```py path=b.py
def f(): ...
reveal_type(f.__get__) # revealed: @Todo(`__get__` method on functions)
reveal_type(f.__call__) # revealed: @Todo(`__call__` method on functions)
```
### Int-literal attributes
Most attribute accesses on int-literal types are delegated to `builtins.int`, since all literal
integers are instances of that class:
```py path=a.py
reveal_type((2).bit_length) # revealed: @Todo(bound method)
reveal_type((2).denominator) # revealed: @Todo(@property)
```
Some attributes are special-cased, however:
```py path=b.py
reveal_type((2).numerator) # revealed: Literal[2]
reveal_type((2).real) # revealed: Literal[2]
```
### Bool-literal attributes
Most attribute accesses on bool-literal types are delegated to `builtins.bool`, since all literal
bols are instances of that class:
```py path=a.py
reveal_type(True.__and__) # revealed: @Todo(bound method)
reveal_type(False.__or__) # revealed: @Todo(bound method)
```
Some attributes are special-cased, however:
```py path=b.py
reveal_type(True.numerator) # revealed: Literal[1]
reveal_type(False.real) # revealed: Literal[0]
```
### Bytes-literal attributes
All attribute access on literal `bytes` types is currently delegated to `buitins.bytes`:
```py
reveal_type(b"foo".join) # revealed: @Todo(bound method)
reveal_type(b"foo".endswith) # revealed: @Todo(bound method)
```
## References
Some of the tests in the *Class and instance variables* section draw inspiration from
[pyright's documentation] on this topic.
[pyright's documentation]: https://microsoft.github.io/pyright/#/type-concepts-advanced?id=class-and-instance-variables
[typing spec on `classvar`]: https://typing.readthedocs.io/en/latest/spec/class-compat.html#classvar
[`typing.classvar`]: https://docs.python.org/3/library/typing.html#typing.ClassVar

View File

@@ -1,95 +0,0 @@
## Binary operations on booleans
## Basic Arithmetic
We try to be precise and all operations except for division will result in Literal type.
```py
a = True
b = False
reveal_type(a + a) # revealed: Literal[2]
reveal_type(a + b) # revealed: Literal[1]
reveal_type(b + a) # revealed: Literal[1]
reveal_type(b + b) # revealed: Literal[0]
reveal_type(a - a) # revealed: Literal[0]
reveal_type(a - b) # revealed: Literal[1]
reveal_type(b - a) # revealed: Literal[-1]
reveal_type(b - b) # revealed: Literal[0]
reveal_type(a * a) # revealed: Literal[1]
reveal_type(a * b) # revealed: Literal[0]
reveal_type(b * a) # revealed: Literal[0]
reveal_type(b * b) # revealed: Literal[0]
reveal_type(a % a) # revealed: Literal[0]
reveal_type(b % a) # revealed: Literal[0]
reveal_type(a // a) # revealed: Literal[1]
reveal_type(b // a) # revealed: Literal[0]
reveal_type(a**a) # revealed: Literal[1]
reveal_type(a**b) # revealed: Literal[1]
reveal_type(b**a) # revealed: Literal[0]
reveal_type(b**b) # revealed: Literal[1]
# Division
reveal_type(a / a) # revealed: float
reveal_type(b / a) # revealed: float
b / b # error: [division-by-zero] "Cannot divide object of type `Literal[False]` by zero"
a / b # error: [division-by-zero] "Cannot divide object of type `Literal[True]` by zero"
# bitwise OR
reveal_type(a | a) # revealed: Literal[True]
reveal_type(a | b) # revealed: Literal[True]
reveal_type(b | a) # revealed: Literal[True]
reveal_type(b | b) # revealed: Literal[False]
```
## Arithmetic with a variable
```py
a = True
b = False
def lhs_is_int(x: int):
reveal_type(x + a) # revealed: int
reveal_type(x - a) # revealed: int
reveal_type(x * a) # revealed: int
reveal_type(x // a) # revealed: int
reveal_type(x / a) # revealed: float
reveal_type(x % a) # revealed: int
def rhs_is_int(x: int):
reveal_type(a + x) # revealed: int
reveal_type(a - x) # revealed: int
reveal_type(a * x) # revealed: int
reveal_type(a // x) # revealed: int
reveal_type(a / x) # revealed: float
reveal_type(a % x) # revealed: int
def lhs_is_bool(x: bool):
reveal_type(x + a) # revealed: int
reveal_type(x - a) # revealed: int
reveal_type(x * a) # revealed: int
reveal_type(x // a) # revealed: int
reveal_type(x / a) # revealed: float
reveal_type(x % a) # revealed: int
def rhs_is_bool(x: bool):
reveal_type(a + x) # revealed: int
reveal_type(a - x) # revealed: int
reveal_type(a * x) # revealed: int
reveal_type(a // x) # revealed: int
reveal_type(a / x) # revealed: float
reveal_type(a % x) # revealed: int
def both_are_bool(x: bool, y: bool):
reveal_type(x + y) # revealed: int
reveal_type(x - y) # revealed: int
reveal_type(x * y) # revealed: int
reveal_type(x // y) # revealed: int
reveal_type(x / y) # revealed: float
reveal_type(x % y) # revealed: int
```

View File

@@ -1,209 +0,0 @@
# Boundness and declaredness: public uses
This document demonstrates how type-inference and diagnostics works for *public* uses of a symbol,
that is, a use of a symbol from another scope. If a symbol has a declared type in its local scope
(e.g. `int`), we use that as the symbol's "public type" (the type of the symbol from the perspective
of other scopes) even if there is a more precise local inferred type for the symbol (`Literal[1]`).
We test the whole matrix of possible boundness and declaredness states. The current behavior is
summarized in the following table, while the tests below demonstrate each case. Note that some of
this behavior is questionable and might change in the future. See the TODOs in `symbol_by_id`
(`types.rs`) and [this issue](https://github.com/astral-sh/ruff/issues/14297) for more information.
In particular, we should raise errors in the "possibly-undeclared-and-unbound" as well as the
"undeclared-and-possibly-unbound" cases (marked with a "?").
| **Public type** | declared | possibly-undeclared | undeclared |
| ---------------- | ------------ | -------------------------- | ------------ |
| bound | `T_declared` | `T_declared \| T_inferred` | `T_inferred` |
| possibly-unbound | `T_declared` | `T_declared \| T_inferred` | `T_inferred` |
| unbound | `T_declared` | `T_declared` | `Unknown` |
| **Diagnostic** | declared | possibly-undeclared | undeclared |
| ---------------- | -------- | ------------------------- | ------------------- |
| bound | | | |
| possibly-unbound | | `possibly-unbound-import` | ? |
| unbound | | ? | `unresolved-import` |
## Declared
### Declared and bound
If a symbol has a declared type (`int`), we use that even if there is a more precise inferred type
(`Literal[1]`), or a conflicting inferred type (`Literal[2]`):
```py path=mod.py
x: int = 1
# error: [invalid-assignment]
y: str = 2
```
```py
from mod import x, y
reveal_type(x) # revealed: int
reveal_type(y) # revealed: str
```
### Declared and possibly unbound
If a symbol is declared and *possibly* unbound, we trust that other module and use the declared type
without raising an error.
```py path=mod.py
def flag() -> bool: ...
x: int
y: str
if flag:
x = 1
# error: [invalid-assignment]
y = 2
```
```py
from mod import x, y
reveal_type(x) # revealed: int
reveal_type(y) # revealed: str
```
### Declared and unbound
Similarly, if a symbol is declared but unbound, we do not raise an error. We trust that this symbol
is available somehow and simply use the declared type.
```py path=mod.py
x: int
```
```py
from mod import x
reveal_type(x) # revealed: int
```
## Possibly undeclared
### Possibly undeclared and bound
If a symbol is possibly undeclared but definitely bound, we use the union of the declared and
inferred types:
```py path=mod.py
from typing import Any
def flag() -> bool: ...
x = 1
y = 2
if flag():
x: Any
# error: [invalid-declaration]
y: str
```
```py
from mod import x, y
reveal_type(x) # revealed: Literal[1] | Any
reveal_type(y) # revealed: Literal[2] | Unknown
```
### Possibly undeclared and possibly unbound
If a symbol is possibly undeclared and possibly unbound, we also use the union of the declared and
inferred types. This case is interesting because the "possibly declared" definition might not be the
same as the "possibly bound" definition (symbol `y`). Note that we raise a `possibly-unbound-import`
error for both `x` and `y`:
```py path=mod.py
def flag() -> bool: ...
if flag():
x: Any = 1
y = 2
else:
y: str
```
```py
# error: [possibly-unbound-import]
# error: [possibly-unbound-import]
from mod import x, y
reveal_type(x) # revealed: Literal[1] | Any
reveal_type(y) # revealed: Literal[2] | str
```
### Possibly undeclared and unbound
If a symbol is possibly undeclared and definitely unbound, we currently do not raise an error. This
seems inconsistent when compared to the case just above.
```py path=mod.py
def flag() -> bool: ...
if flag():
x: int
```
```py
# TODO: this should raise an error. Once we fix this, update the section description and the table
# on top of this document.
from mod import x
reveal_type(x) # revealed: int
```
## Undeclared
### Undeclared but bound
We use the inferred type as the public type, if a symbol has no declared type.
```py path=mod.py
x = 1
```
```py
from mod import x
reveal_type(x) # revealed: Literal[1]
```
### Undeclared and possibly unbound
If a symbol is undeclared and *possibly* unbound, we currently do not raise an error. This seems
inconsistent when compared to the "possibly-undeclared-and-possibly-unbound" case.
```py path=mod.py
def flag() -> bool: ...
if flag:
x = 1
```
```py
# TODO: this should raise an error. Once we fix this, update the section description and the table
# on top of this document.
from mod import x
reveal_type(x) # revealed: Literal[1]
```
### Undeclared and unbound
If a symbol is undeclared *and* unbound, we infer `Unknown` and raise an error.
```py path=mod.py
if False:
x: int = 1
```
```py
# error: [unresolved-import]
from mod import x
reveal_type(x) # revealed: Unknown
```

View File

@@ -1,7 +0,0 @@
# Constructor
```py
class Foo: ...
reveal_type(Foo()) # revealed: Foo
```

View File

@@ -1,77 +0,0 @@
# Unions in calls
## Union of return types
```py
def _(flag: bool):
if flag:
def f() -> int:
return 1
else:
def f() -> str:
return "foo"
reveal_type(f()) # revealed: int | str
```
## Calling with an unknown union
```py
from nonexistent import f # error: [unresolved-import] "Cannot resolve import `nonexistent`"
def coinflip() -> bool:
return True
if coinflip():
def f() -> int:
return 1
reveal_type(f()) # revealed: Unknown | int
```
## Non-callable elements in a union
Calling a union with a non-callable element should emit a diagnostic.
```py
def _(flag: bool):
if flag:
f = 1
else:
def f() -> int:
return 1
x = f() # error: "Object of type `Literal[1] | Literal[f]` is not callable (due to union element `Literal[1]`)"
reveal_type(x) # revealed: Unknown | int
```
## Multiple non-callable elements in a union
Calling a union with multiple non-callable elements should mention all of them in the diagnostic.
```py
def _(flag: bool, flag2: bool):
if flag:
f = 1
elif flag2:
f = "foo"
else:
def f() -> int:
return 1
# error: "Object of type `Literal[1, "foo"] | Literal[f]` is not callable (due to union elements Literal[1], Literal["foo"])"
# revealed: Unknown | int
reveal_type(f())
```
## All non-callable union elements
Calling a union with no callable elements can emit a simpler diagnostic.
```py
def _(flag: bool):
if flag:
f = 1
else:
f = "foo"
x = f() # error: "Object of type `Literal[1, "foo"]` is not callable"
reveal_type(x) # revealed: Unknown
```

View File

@@ -1,320 +0,0 @@
# Comparison: Rich Comparison
Rich comparison operations (`==`, `!=`, `<`, `<=`, `>`, `>=`) in Python are implemented through
double-underscore methods that allow customization of comparison behavior.
For references, see:
- <https://docs.python.org/3/reference/datamodel.html#object.__lt__>
- <https://snarky.ca/unravelling-rich-comparison-operators/>
## Rich Comparison Dunder Implementations For Same Class
Classes can support rich comparison by implementing dunder methods like `__eq__`, `__ne__`, etc. The
most common case involves implementing these methods for the same type:
```py
from __future__ import annotations
class A:
def __eq__(self, other: A) -> int:
return 42
def __ne__(self, other: A) -> float:
return 42.0
def __lt__(self, other: A) -> str:
return "42"
def __le__(self, other: A) -> bytes:
return b"42"
def __gt__(self, other: A) -> list:
return [42]
def __ge__(self, other: A) -> set:
return {42}
reveal_type(A() == A()) # revealed: int
reveal_type(A() != A()) # revealed: float
reveal_type(A() < A()) # revealed: str
reveal_type(A() <= A()) # revealed: bytes
reveal_type(A() > A()) # revealed: list
reveal_type(A() >= A()) # revealed: set
```
## Rich Comparison Dunder Implementations for Other Class
In some cases, classes may implement rich comparison dunder methods for comparisons with a different
type:
```py
from __future__ import annotations
class A:
def __eq__(self, other: B) -> int:
return 42
def __ne__(self, other: B) -> float:
return 42.0
def __lt__(self, other: B) -> str:
return "42"
def __le__(self, other: B) -> bytes:
return b"42"
def __gt__(self, other: B) -> list:
return [42]
def __ge__(self, other: B) -> set:
return {42}
class B: ...
reveal_type(A() == B()) # revealed: int
reveal_type(A() != B()) # revealed: float
reveal_type(A() < B()) # revealed: str
reveal_type(A() <= B()) # revealed: bytes
reveal_type(A() > B()) # revealed: list
reveal_type(A() >= B()) # revealed: set
```
## Reflected Comparisons
Fallback to the right-hand sides comparison methods occurs when the left-hand side does not define
them. Note: class `B` has its own `__eq__` and `__ne__` methods to override those of `object`, but
these methods will be ignored here because they require a mismatched operand type.
```py
from __future__ import annotations
class A:
def __eq__(self, other: B) -> int:
return 42
def __ne__(self, other: B) -> float:
return 42.0
def __lt__(self, other: B) -> str:
return "42"
def __le__(self, other: B) -> bytes:
return b"42"
def __gt__(self, other: B) -> list:
return [42]
def __ge__(self, other: B) -> set:
return {42}
class B:
# To override builtins.object.__eq__ and builtins.object.__ne__
# TODO these should emit an invalid override diagnostic
def __eq__(self, other: str) -> B:
return B()
def __ne__(self, other: str) -> B:
return B()
# TODO: should be `int` and `float`.
# Need to check arg type and fall back to `rhs.__eq__` and `rhs.__ne__`.
#
# Because `object.__eq__` and `object.__ne__` accept `object` in typeshed,
# this can only happen with an invalid override of these methods,
# but we still support it.
reveal_type(B() == A()) # revealed: B
reveal_type(B() != A()) # revealed: B
reveal_type(B() < A()) # revealed: list
reveal_type(B() <= A()) # revealed: set
reveal_type(B() > A()) # revealed: str
reveal_type(B() >= A()) # revealed: bytes
class C:
def __gt__(self, other: C) -> int:
return 42
def __ge__(self, other: C) -> float:
return 42.0
reveal_type(C() < C()) # revealed: int
reveal_type(C() <= C()) # revealed: float
```
## Reflected Comparisons with Subclasses
When subclasses override comparison methods, these overridden methods take precedence over those in
the parent class. Class `B` inherits from `A` and redefines comparison methods to return types other
than `A`.
```py
from __future__ import annotations
class A:
def __eq__(self, other: A) -> A:
return A()
def __ne__(self, other: A) -> A:
return A()
def __lt__(self, other: A) -> A:
return A()
def __le__(self, other: A) -> A:
return A()
def __gt__(self, other: A) -> A:
return A()
def __ge__(self, other: A) -> A:
return A()
class B(A):
def __eq__(self, other: A) -> int:
return 42
def __ne__(self, other: A) -> float:
return 42.0
def __lt__(self, other: A) -> str:
return "42"
def __le__(self, other: A) -> bytes:
return b"42"
def __gt__(self, other: A) -> list:
return [42]
def __ge__(self, other: A) -> set:
return {42}
reveal_type(A() == B()) # revealed: int
reveal_type(A() != B()) # revealed: float
reveal_type(A() < B()) # revealed: list
reveal_type(A() <= B()) # revealed: set
reveal_type(A() > B()) # revealed: str
reveal_type(A() >= B()) # revealed: bytes
```
## Reflected Comparisons with Subclass But Falls Back to LHS
In the case of a subclass, the right-hand side has priority. However, if the overridden dunder
method has an mismatched type to operand, the comparison will fall back to the left-hand side.
```py
from __future__ import annotations
class A:
def __lt__(self, other: A) -> A:
return A()
def __gt__(self, other: A) -> A:
return A()
class B(A):
def __lt__(self, other: int) -> B:
return B()
def __gt__(self, other: int) -> B:
return B()
# TODO: should be `A`, need to check argument type and fall back to LHS method
reveal_type(A() < B()) # revealed: B
reveal_type(A() > B()) # revealed: B
```
## Operations involving instances of classes inheriting from `Any`
`Any` and `Unknown` represent a set of possible runtime objects, wherein the bounds of the set are
unknown. Whether the left-hand operand's dunder or the right-hand operand's reflected dunder depends
on whether the right-hand operand is an instance of a class that is a subclass of the left-hand
operand's class and overrides the reflected dunder. In the following example, because of the
unknowable nature of `Any`/`Unknown`, we must consider both possibilities: `Any`/`Unknown` might
resolve to an unknown third class that inherits from `X` and overrides `__gt__`; but it also might
not. Thus, the correct answer here for the `reveal_type` is `int | Unknown`.
(This test is referenced from `mdtest/binary/instances.md`)
```py
from does_not_exist import Foo # error: [unresolved-import]
reveal_type(Foo) # revealed: Unknown
class X:
def __lt__(self, other: object) -> int:
return 42
class Y(Foo): ...
# TODO: Should be `int | Unknown`; see above discussion.
reveal_type(X() < Y()) # revealed: int
```
## Equality and Inequality Fallback
This test confirms that `==` and `!=` comparisons default to identity comparisons (`is`, `is not`)
when argument types do not match the method signature.
Please refer to the [docs](https://docs.python.org/3/reference/datamodel.html#object.__eq__)
```py
from __future__ import annotations
class A:
# TODO both these overrides should emit invalid-override diagnostic
def __eq__(self, other: int) -> A:
return A()
def __ne__(self, other: int) -> A:
return A()
# TODO: it should be `bool`, need to check arg type and fall back to `is` and `is not`
reveal_type(A() == A()) # revealed: A
reveal_type(A() != A()) # revealed: A
```
## Object Comparisons with Typeshed
```py
class A: ...
reveal_type(A() == object()) # revealed: bool
reveal_type(A() != object()) # revealed: bool
reveal_type(object() == A()) # revealed: bool
reveal_type(object() != A()) # revealed: bool
# error: [unsupported-operator] "Operator `<` is not supported for types `A` and `object`"
# revealed: Unknown
reveal_type(A() < object())
```
## Numbers Comparison with typeshed
```py
reveal_type(1 == 1.0) # revealed: bool
reveal_type(1 != 1.0) # revealed: bool
reveal_type(1 < 1.0) # revealed: bool
reveal_type(1 <= 1.0) # revealed: bool
reveal_type(1 > 1.0) # revealed: bool
reveal_type(1 >= 1.0) # revealed: bool
reveal_type(1 == 2j) # revealed: bool
reveal_type(1 != 2j) # revealed: bool
# TODO: should be Unknown and emit diagnostic,
# need to check arg type and should be failed
reveal_type(1 < 2j) # revealed: bool
reveal_type(1 <= 2j) # revealed: bool
reveal_type(1 > 2j) # revealed: bool
reveal_type(1 >= 2j) # revealed: bool
def f(x: bool, y: int):
reveal_type(x < y) # revealed: bool
reveal_type(y < x) # revealed: bool
reveal_type(4.2 < x) # revealed: bool
reveal_type(x < 4.2) # revealed: bool
```

View File

@@ -1,45 +0,0 @@
# Pattern matching
## With wildcard
```py
def _(target: int):
match target:
case 1:
y = 2
case _:
y = 3
reveal_type(y) # revealed: Literal[2, 3]
```
## Without wildcard
```py
def _(target: int):
match target:
case 1:
y = 2
case 2:
y = 3
# revealed: Literal[2, 3]
# error: [possibly-unresolved-reference]
reveal_type(y)
```
## Basic match
```py
def _(target: int):
y = 1
y = 2
match target:
case 1:
y = 3
case 2:
y = 4
reveal_type(y) # revealed: Literal[2, 3, 4]
```

View File

@@ -1,27 +0,0 @@
# `cast`
`cast()` takes two arguments, one type and one value, and returns a value of the given type.
The (inferred) type of the value and the given type do not need to have any correlation.
```py
from typing import Literal, cast
reveal_type(True) # revealed: Literal[True]
reveal_type(cast(str, True)) # revealed: str
reveal_type(cast("str", True)) # revealed: str
reveal_type(cast(int | str, 1)) # revealed: int | str
# error: [invalid-type-form]
reveal_type(cast(Literal, True)) # revealed: Unknown
# TODO: These should be errors
cast(1)
cast(str)
cast(str, b"ar", "foo")
# TODO: Either support keyword arguments properly,
# or give a comprehensible error message saying they're unsupported
cast(val="foo", typ=int) # error: [unresolved-reference] "Name `foo` used when not defined"
```

View File

@@ -1,66 +0,0 @@
# `except*`
`except*` is only available in Python 3.11 and later:
```toml
[environment]
python-version = "3.11"
```
## `except*` with `BaseException`
```py
try:
help()
except* BaseException as e:
# TODO: should be `BaseExceptionGroup[BaseException]` --Alex
reveal_type(e) # revealed: BaseExceptionGroup
```
## `except*` with specific exception
```py
try:
help()
except* OSError as e:
# TODO: more precise would be `ExceptionGroup[OSError]` --Alex
# (needs homogenous tuples + generics)
reveal_type(e) # revealed: BaseExceptionGroup
```
## `except*` with multiple exceptions
```py
try:
help()
except* (TypeError, AttributeError) as e:
# TODO: more precise would be `ExceptionGroup[TypeError | AttributeError]` --Alex
# (needs homogenous tuples + generics)
reveal_type(e) # revealed: BaseExceptionGroup
```
## `except*` with mix of `Exception`s and `BaseException`s
```py
try:
help()
except* (KeyboardInterrupt, AttributeError) as e:
# TODO: more precise would be `BaseExceptionGroup[KeyboardInterrupt | AttributeError]` --Alex
reveal_type(e) # revealed: BaseExceptionGroup
```
## Invalid `except*` handlers
```py
try:
help()
except* 3 as e: # error: [invalid-exception-caught]
# TODO: Should be `BaseExceptionGroup[Unknown]` --Alex
reveal_type(e) # revealed: BaseExceptionGroup
try:
help()
except* (AttributeError, 42) as e: # error: [invalid-exception-caught]
# TODO: Should be `BaseExceptionGroup[AttributeError | Unknown]` --Alex
reveal_type(e) # revealed: BaseExceptionGroup
```

View File

@@ -1,27 +0,0 @@
# Attribute access
## Boundness
```py
def _(flag: bool):
class A:
always_bound = 1
if flag:
union = 1
else:
union = "abc"
if flag:
possibly_unbound = "abc"
reveal_type(A.always_bound) # revealed: Literal[1]
reveal_type(A.union) # revealed: Literal[1, "abc"]
# error: [possibly-unbound-attribute] "Attribute `possibly_unbound` on type `Literal[A]` is possibly unbound"
reveal_type(A.possibly_unbound) # revealed: Literal["abc"]
# error: [unresolved-attribute] "Type `Literal[A]` has no attribute `non_existent`"
reveal_type(A.non_existent) # revealed: Unknown
```

View File

@@ -1,81 +0,0 @@
# PEP 695 Generics
## Class Declarations
Basic PEP 695 generics
```py
class MyBox[T]:
data: T
box_model_number = 695
def __init__(self, data: T):
self.data = data
box: MyBox[int] = MyBox(5)
# TODO should emit a diagnostic here (str is not assignable to int)
wrong_innards: MyBox[int] = MyBox("five")
# TODO reveal int, do not leak the typevar
reveal_type(box.data) # revealed: T
reveal_type(MyBox.box_model_number) # revealed: Literal[695]
```
## Subclassing
```py
class MyBox[T]:
data: T
def __init__(self, data: T):
self.data = data
# TODO not error on the subscripting
# error: [non-subscriptable]
class MySecureBox[T](MyBox[T]): ...
secure_box: MySecureBox[int] = MySecureBox(5)
reveal_type(secure_box) # revealed: MySecureBox
# TODO reveal int
# The @Todo(…) is misleading here. We currently treat `MyBox[T]` as a dynamic base class because we
# don't understand generics and therefore infer `Unknown` for the `MyBox[T]` base of `MySecureBox[T]`.
reveal_type(secure_box.data) # revealed: @Todo(instance attribute on class with dynamic base)
```
## Cyclical class definition
In type stubs, classes can reference themselves in their base class definitions. For example, in
`typeshed`, we have `class str(Sequence[str]): ...`.
This should hold true even with generics at play.
```py path=a.pyi
class Seq[T]: ...
# TODO not error on the subscripting
class S[T](Seq[S]): ... # error: [non-subscriptable]
reveal_type(S) # revealed: Literal[S]
```
## Type params
A PEP695 type variable defines a value of type `typing.TypeVar`.
```py
def f[T]():
reveal_type(T) # revealed: T
reveal_type(T.__name__) # revealed: Literal["T"]
```
## Minimum two constraints
A typevar with less than two constraints emits a diagnostic:
```py
# error: [invalid-type-variable-constraints] "TypeVar must have at least two constrained types"
def f[T: (int,)]():
pass
```

View File

@@ -1,106 +0,0 @@
# Structures
## Class import following
```py
from b import C as D
E = D
reveal_type(E) # revealed: Literal[C]
```
```py path=b.py
class C: ...
```
## Module member resolution
```py
import b
D = b.C
reveal_type(D) # revealed: Literal[C]
```
```py path=b.py
class C: ...
```
## Nested
```py
import a.b
reveal_type(a.b.C) # revealed: Literal[C]
```
```py path=a/__init__.py
```
```py path=a/b.py
class C: ...
```
## Deeply nested
```py
import a.b.c
reveal_type(a.b.c.C) # revealed: Literal[C]
```
```py path=a/__init__.py
```
```py path=a/b/__init__.py
```
```py path=a/b/c.py
class C: ...
```
## Nested with rename
```py
import a.b as b
reveal_type(b.C) # revealed: Literal[C]
```
```py path=a/__init__.py
```
```py path=a/b.py
class C: ...
```
## Deeply nested with rename
```py
import a.b.c as c
reveal_type(c.C) # revealed: Literal[C]
```
```py path=a/__init__.py
```
```py path=a/b/__init__.py
```
```py path=a/b/c.py
class C: ...
```
## Unresolvable submodule imports
```py
# Topmost component resolvable, submodule not resolvable:
import a.foo # error: [unresolved-import] "Cannot resolve import `a.foo`"
# Topmost component unresolvable:
import b.foo # error: [unresolved-import] "Cannot resolve import `b.foo`"
```
```py path=a/__init__.py
```

View File

@@ -1,8 +0,0 @@
# Importing builtin module
```py
import builtins
x = builtins.chr
reveal_type(x) # revealed: Literal[chr]
```

View File

@@ -1,164 +0,0 @@
# Relative
## Non-existent
```py path=package/__init__.py
```
```py path=package/bar.py
from .foo import X # error: [unresolved-import]
reveal_type(X) # revealed: Unknown
```
## Simple
```py path=package/__init__.py
```
```py path=package/foo.py
X = 42
```
```py path=package/bar.py
from .foo import X
reveal_type(X) # revealed: Literal[42]
```
## Dotted
```py path=package/__init__.py
```
```py path=package/foo/bar/baz.py
X = 42
```
```py path=package/bar.py
from .foo.bar.baz import X
reveal_type(X) # revealed: Literal[42]
```
## Bare to package
```py path=package/__init__.py
X = 42
```
```py path=package/bar.py
from . import X
reveal_type(X) # revealed: Literal[42]
```
## Non-existent + bare to package
```py path=package/bar.py
from . import X # error: [unresolved-import]
reveal_type(X) # revealed: Unknown
```
## Dunder init
```py path=package/__init__.py
from .foo import X
reveal_type(X) # revealed: Literal[42]
```
```py path=package/foo.py
X = 42
```
## Non-existent + dunder init
```py path=package/__init__.py
from .foo import X # error: [unresolved-import]
reveal_type(X) # revealed: Unknown
```
## Long relative import
```py path=package/__init__.py
```
```py path=package/foo.py
X = 42
```
```py path=package/subpackage/subsubpackage/bar.py
from ...foo import X
reveal_type(X) # revealed: Literal[42]
```
## Unbound symbol
```py path=package/__init__.py
```
```py path=package/foo.py
x # error: [unresolved-reference]
```
```py path=package/bar.py
from .foo import x # error: [unresolved-import]
reveal_type(x) # revealed: Unknown
```
## Bare to module
```py path=package/__init__.py
```
```py path=package/foo.py
X = 42
```
```py path=package/bar.py
from . import foo
reveal_type(foo.X) # revealed: Literal[42]
```
## Non-existent + bare to module
This test verifies that we emit an error when we try to import a symbol that is neither a submodule
nor an attribute of `package`.
```py path=package/__init__.py
```
```py path=package/bar.py
from . import foo # error: [unresolved-import]
reveal_type(foo) # revealed: Unknown
```
## Import submodule from self
We don't currently consider `from...import` statements when building up the `imported_modules` set
in the semantic index. When accessing an attribute of a module, we only consider it a potential
submodule when that submodule name appears in the `imported_modules` set. That means that submodules
that are imported via `from...import` are not visible to our type inference if you also access that
submodule via the attribute on its parent package.
```py path=package/__init__.py
```
```py path=package/foo.py
X = 42
```
```py path=package/bar.py
from . import foo
import package
# error: [unresolved-attribute] "Type `<module 'package'>` has no attribute `foo`"
reveal_type(package.foo.X) # revealed: Unknown
```

View File

@@ -1,52 +0,0 @@
# Known constants
## `typing.TYPE_CHECKING`
This constant is `True` when in type-checking mode, `False` otherwise. The symbol is defined to be
`False` at runtime. In typeshed, it is annotated as `bool`. This test makes sure that we infer
`Literal[True]` for it anyways.
### Basic
```py
from typing import TYPE_CHECKING
import typing
reveal_type(TYPE_CHECKING) # revealed: Literal[True]
reveal_type(typing.TYPE_CHECKING) # revealed: Literal[True]
```
### Aliased
Make sure that we still infer the correct type if the constant has been given a different name:
```py
from typing import TYPE_CHECKING as TC
reveal_type(TC) # revealed: Literal[True]
```
### Must originate from `typing`
Make sure we only use our special handling for `typing.TYPE_CHECKING` and not for other constants
with the same name:
```py path=constants.py
TYPE_CHECKING: bool = False
```
```py
from constants import TYPE_CHECKING
reveal_type(TYPE_CHECKING) # revealed: bool
```
### `typing_extensions` re-export
This should behave in the same way as `typing.TYPE_CHECKING`:
```py
from typing_extensions import TYPE_CHECKING
reveal_type(TYPE_CHECKING) # revealed: Literal[True]
```

View File

@@ -1,7 +0,0 @@
# Dictionaries
## Empty dictionary
```py
reveal_type({}) # revealed: dict
```

View File

@@ -1,7 +0,0 @@
# Lists
## Empty list
```py
reveal_type([]) # revealed: list
```

View File

@@ -1,7 +0,0 @@
# Sets
## Basic set
```py
reveal_type({1, 2}) # revealed: set
```

View File

@@ -1,267 +0,0 @@
# For loops
## Basic `for` loop
```py
class IntIterator:
def __next__(self) -> int:
return 42
class IntIterable:
def __iter__(self) -> IntIterator:
return IntIterator()
for x in IntIterable():
pass
# revealed: int
# error: [possibly-unresolved-reference]
reveal_type(x)
```
## With previous definition
```py
class IntIterator:
def __next__(self) -> int:
return 42
class IntIterable:
def __iter__(self) -> IntIterator:
return IntIterator()
x = "foo"
for x in IntIterable():
pass
reveal_type(x) # revealed: Literal["foo"] | int
```
## With `else` (no break)
```py
class IntIterator:
def __next__(self) -> int:
return 42
class IntIterable:
def __iter__(self) -> IntIterator:
return IntIterator()
for x in IntIterable():
pass
else:
x = "foo"
reveal_type(x) # revealed: Literal["foo"]
```
## May `break`
```py
class IntIterator:
def __next__(self) -> int:
return 42
class IntIterable:
def __iter__(self) -> IntIterator:
return IntIterator()
for x in IntIterable():
if x > 5:
break
else:
x = "foo"
reveal_type(x) # revealed: int | Literal["foo"]
```
## With old-style iteration protocol
```py
class OldStyleIterable:
def __getitem__(self, key: int) -> int:
return 42
for x in OldStyleIterable():
pass
# revealed: int
# error: [possibly-unresolved-reference]
reveal_type(x)
```
## With heterogeneous tuple
```py
for x in (1, "a", b"foo"):
pass
# revealed: Literal[1, "a", b"foo"]
# error: [possibly-unresolved-reference]
reveal_type(x)
```
## With non-callable iterator
```py
def _(flag: bool):
class NotIterable:
if flag:
__iter__ = 1
else:
__iter__ = None
for x in NotIterable(): # error: "Object of type `NotIterable` is not iterable"
pass
# revealed: Unknown
# error: [possibly-unresolved-reference]
reveal_type(x)
```
## Invalid iterable
```py
nonsense = 123
for x in nonsense: # error: "Object of type `Literal[123]` is not iterable"
pass
```
## New over old style iteration protocol
```py
class NotIterable:
def __getitem__(self, key: int) -> int:
return 42
__iter__ = None
for x in NotIterable(): # error: "Object of type `NotIterable` is not iterable"
pass
```
## Union type as iterable
```py
class TestIter:
def __next__(self) -> int:
return 42
class Test:
def __iter__(self) -> TestIter:
return TestIter()
class Test2:
def __iter__(self) -> TestIter:
return TestIter()
def _(flag: bool):
for x in Test() if flag else Test2():
reveal_type(x) # revealed: int
```
## Union type as iterator
```py
class TestIter:
def __next__(self) -> int:
return 42
class TestIter2:
def __next__(self) -> int:
return 42
class Test:
def __iter__(self) -> TestIter | TestIter2:
return TestIter()
for x in Test():
reveal_type(x) # revealed: int
```
## Union type as iterable and union type as iterator
```py
class TestIter:
def __next__(self) -> int | Exception:
return 42
class TestIter2:
def __next__(self) -> str | tuple[int, int]:
return "42"
class TestIter3:
def __next__(self) -> bytes:
return b"42"
class TestIter4:
def __next__(self) -> memoryview:
return memoryview(b"42")
class Test:
def __iter__(self) -> TestIter | TestIter2:
return TestIter()
class Test2:
def __iter__(self) -> TestIter3 | TestIter4:
return TestIter3()
def _(flag: bool):
for x in Test() if flag else Test2():
reveal_type(x) # revealed: int | Exception | str | tuple[int, int] | bytes | memoryview
```
## Union type as iterable where one union element has no `__iter__` method
```py
class TestIter:
def __next__(self) -> int:
return 42
class Test:
def __iter__(self) -> TestIter:
return TestIter()
def _(flag: bool):
# error: [not-iterable] "Object of type `Test | Literal[42]` is not iterable because its `__iter__` method is possibly unbound"
for x in Test() if flag else 42:
reveal_type(x) # revealed: int
```
## Union type as iterable where one union element has invalid `__iter__` method
```py
class TestIter:
def __next__(self) -> int:
return 42
class Test:
def __iter__(self) -> TestIter:
return TestIter()
class Test2:
def __iter__(self) -> int:
return 42
def _(flag: bool):
# error: "Object of type `Test | Test2` is not iterable"
for x in Test() if flag else Test2():
reveal_type(x) # revealed: Unknown
```
## Union type as iterator where one union element has no `__next__` method
```py
class TestIter:
def __next__(self) -> int:
return 42
class Test:
def __iter__(self) -> TestIter | int:
return TestIter()
# error: [not-iterable] "Object of type `Test` is not iterable"
for x in Test():
reveal_type(x) # revealed: Unknown
```

View File

@@ -1,408 +0,0 @@
# Method Resolution Order tests
Tests that assert that we can infer the correct type for a class's `__mro__` attribute.
This attribute is rarely accessed directly at runtime. However, it's extremely important for *us* to
know the precise possible values of a class's Method Resolution Order, or we won't be able to infer
the correct type of attributes accessed from instances.
For documentation on method resolution orders, see:
- <https://docs.python.org/3/glossary.html#term-method-resolution-order>
- <https://docs.python.org/3/howto/mro.html#python-2-3-mro>
## No bases
```py
class C: ...
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[object]]
```
## The special case: `object` itself
```py
reveal_type(object.__mro__) # revealed: tuple[Literal[object]]
```
## Explicit inheritance from `object`
```py
class C(object): ...
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[object]]
```
## Explicit inheritance from non-`object` single base
```py
class A: ...
class B(A): ...
reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[A], Literal[object]]
```
## Linearization of multiple bases
```py
class A: ...
class B: ...
class C(A, B): ...
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[A], Literal[B], Literal[object]]
```
## Complex diamond inheritance (1)
This is "ex_2" from <https://docs.python.org/3/howto/mro.html#the-end>
```py
class O: ...
class X(O): ...
class Y(O): ...
class A(X, Y): ...
class B(Y, X): ...
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[X], Literal[Y], Literal[O], Literal[object]]
reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[Y], Literal[X], Literal[O], Literal[object]]
```
## Complex diamond inheritance (2)
This is "ex_5" from <https://docs.python.org/3/howto/mro.html#the-end>
```py
class O: ...
class F(O): ...
class E(O): ...
class D(O): ...
class C(D, F): ...
class B(D, E): ...
class A(B, C): ...
# revealed: tuple[Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
reveal_type(C.__mro__)
# revealed: tuple[Literal[B], Literal[D], Literal[E], Literal[O], Literal[object]]
reveal_type(B.__mro__)
# revealed: tuple[Literal[A], Literal[B], Literal[C], Literal[D], Literal[E], Literal[F], Literal[O], Literal[object]]
reveal_type(A.__mro__)
```
## Complex diamond inheritance (3)
This is "ex_6" from <https://docs.python.org/3/howto/mro.html#the-end>
```py
class O: ...
class F(O): ...
class E(O): ...
class D(O): ...
class C(D, F): ...
class B(E, D): ...
class A(B, C): ...
# revealed: tuple[Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
reveal_type(C.__mro__)
# revealed: tuple[Literal[B], Literal[E], Literal[D], Literal[O], Literal[object]]
reveal_type(B.__mro__)
# revealed: tuple[Literal[A], Literal[B], Literal[E], Literal[C], Literal[D], Literal[F], Literal[O], Literal[object]]
reveal_type(A.__mro__)
```
## Complex diamond inheritance (4)
This is "ex_9" from <https://docs.python.org/3/howto/mro.html#the-end>
```py
class O: ...
class A(O): ...
class B(O): ...
class C(O): ...
class D(O): ...
class E(O): ...
class K1(A, B, C): ...
class K2(D, B, E): ...
class K3(D, A): ...
class Z(K1, K2, K3): ...
# revealed: tuple[Literal[K1], Literal[A], Literal[B], Literal[C], Literal[O], Literal[object]]
reveal_type(K1.__mro__)
# revealed: tuple[Literal[K2], Literal[D], Literal[B], Literal[E], Literal[O], Literal[object]]
reveal_type(K2.__mro__)
# revealed: tuple[Literal[K3], Literal[D], Literal[A], Literal[O], Literal[object]]
reveal_type(K3.__mro__)
# revealed: tuple[Literal[Z], Literal[K1], Literal[K2], Literal[K3], Literal[D], Literal[A], Literal[B], Literal[C], Literal[E], Literal[O], Literal[object]]
reveal_type(Z.__mro__)
```
## Inheritance from `Unknown`
```py
from does_not_exist import DoesNotExist # error: [unresolved-import]
class A(DoesNotExist): ...
class B: ...
class C: ...
class D(A, B, C): ...
class E(B, C): ...
class F(E, A): ...
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Unknown, Literal[object]]
reveal_type(D.__mro__) # revealed: tuple[Literal[D], Literal[A], Unknown, Literal[B], Literal[C], Literal[object]]
reveal_type(E.__mro__) # revealed: tuple[Literal[E], Literal[B], Literal[C], Literal[object]]
reveal_type(F.__mro__) # revealed: tuple[Literal[F], Literal[E], Literal[B], Literal[C], Literal[A], Unknown, Literal[object]]
```
## `__bases__` lists that cause errors at runtime
If the class's `__bases__` cause an exception to be raised at runtime and therefore the class
creation to fail, we infer the class's `__mro__` as being `[<class>, Unknown, object]`:
```py
# error: [inconsistent-mro] "Cannot create a consistent method resolution order (MRO) for class `Foo` with bases list `[<class 'object'>, <class 'int'>]`"
class Foo(object, int): ...
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
class Bar(Foo): ...
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Literal[Foo], Unknown, Literal[object]]
# This is the `TypeError` at the bottom of "ex_2"
# in the examples at <https://docs.python.org/3/howto/mro.html#the-end>
class O: ...
class X(O): ...
class Y(O): ...
class A(X, Y): ...
class B(Y, X): ...
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[X], Literal[Y], Literal[O], Literal[object]]
reveal_type(B.__mro__) # revealed: tuple[Literal[B], Literal[Y], Literal[X], Literal[O], Literal[object]]
# error: [inconsistent-mro] "Cannot create a consistent method resolution order (MRO) for class `Z` with bases list `[<class 'A'>, <class 'B'>]`"
class Z(A, B): ...
reveal_type(Z.__mro__) # revealed: tuple[Literal[Z], Unknown, Literal[object]]
class AA(Z): ...
reveal_type(AA.__mro__) # revealed: tuple[Literal[AA], Literal[Z], Unknown, Literal[object]]
```
## `__bases__` includes a `Union`
We don't support union types in a class's bases; a base must resolve to a single `ClassLiteralType`.
If we find a union type in a class's bases, we infer the class's `__mro__` as being
`[<class>, Unknown, object]`, the same as for MROs that cause errors at runtime.
```py
def returns_bool() -> bool:
return True
class A: ...
class B: ...
if returns_bool():
x = A
else:
x = B
reveal_type(x) # revealed: Literal[A, B]
# error: 11 [invalid-base] "Invalid class base with type `Literal[A, B]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
class Foo(x): ...
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
```
## `__bases__` includes multiple `Union`s
```py
def returns_bool() -> bool:
return True
class A: ...
class B: ...
class C: ...
class D: ...
if returns_bool():
x = A
else:
x = B
if returns_bool():
y = C
else:
y = D
reveal_type(x) # revealed: Literal[A, B]
reveal_type(y) # revealed: Literal[C, D]
# error: 11 [invalid-base] "Invalid class base with type `Literal[A, B]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
# error: 14 [invalid-base] "Invalid class base with type `Literal[C, D]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
class Foo(x, y): ...
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
```
## `__bases__` lists that cause errors... now with `Union`s
```py
def returns_bool() -> bool:
return True
class O: ...
class X(O): ...
class Y(O): ...
if returns_bool():
foo = Y
else:
foo = object
# error: 21 [invalid-base] "Invalid class base with type `Literal[Y, object]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
class PossibleError(foo, X): ...
reveal_type(PossibleError.__mro__) # revealed: tuple[Literal[PossibleError], Unknown, Literal[object]]
class A(X, Y): ...
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Literal[X], Literal[Y], Literal[O], Literal[object]]
if returns_bool():
class B(X, Y): ...
else:
class B(Y, X): ...
# revealed: tuple[Literal[B], Literal[X], Literal[Y], Literal[O], Literal[object]] | tuple[Literal[B], Literal[Y], Literal[X], Literal[O], Literal[object]]
reveal_type(B.__mro__)
# error: 12 [invalid-base] "Invalid class base with type `Literal[B, B]` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
class Z(A, B): ...
reveal_type(Z.__mro__) # revealed: tuple[Literal[Z], Unknown, Literal[object]]
```
## `__bases__` lists with duplicate bases
```py
class Foo(str, str): ... # error: 16 [duplicate-base] "Duplicate base class `str`"
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
class Spam: ...
class Eggs: ...
class Ham(
Spam,
Eggs,
Spam, # error: [duplicate-base] "Duplicate base class `Spam`"
Eggs, # error: [duplicate-base] "Duplicate base class `Eggs`"
): ...
reveal_type(Ham.__mro__) # revealed: tuple[Literal[Ham], Unknown, Literal[object]]
class Mushrooms: ...
class Omelette(Spam, Eggs, Mushrooms, Mushrooms): ... # error: [duplicate-base]
reveal_type(Omelette.__mro__) # revealed: tuple[Literal[Omelette], Unknown, Literal[object]]
```
## `__bases__` lists with duplicate `Unknown` bases
```py
# error: [unresolved-import]
# error: [unresolved-import]
from does_not_exist import unknown_object_1, unknown_object_2
reveal_type(unknown_object_1) # revealed: Unknown
reveal_type(unknown_object_2) # revealed: Unknown
# We *should* emit an error here to warn the user that we have no idea
# what the MRO of this class should really be.
# However, we don't complain about "duplicate base classes" here,
# even though two classes are both inferred as being `Unknown`.
#
# (TODO: should we revisit this? Does it violate the gradual guarantee?
# Should we just silently infer `[Foo, Unknown, object]` as the MRO here
# without emitting any error at all? Not sure...)
#
# error: [inconsistent-mro] "Cannot create a consistent method resolution order (MRO) for class `Foo` with bases list `[Unknown, Unknown]`"
class Foo(unknown_object_1, unknown_object_2): ...
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
```
## Unrelated objects inferred as `Any`/`Unknown` do not have special `__mro__` attributes
```py
from does_not_exist import unknown_object # error: [unresolved-import]
reveal_type(unknown_object) # revealed: Unknown
reveal_type(unknown_object.__mro__) # revealed: Unknown
```
## Classes that inherit from themselves
These are invalid, but we need to be able to handle them gracefully without panicking.
```py path=a.pyi
class Foo(Foo): ... # error: [cyclic-class-definition]
reveal_type(Foo) # revealed: Literal[Foo]
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
class Bar: ...
class Baz: ...
class Boz(Bar, Baz, Boz): ... # error: [cyclic-class-definition]
reveal_type(Boz) # revealed: Literal[Boz]
reveal_type(Boz.__mro__) # revealed: tuple[Literal[Boz], Unknown, Literal[object]]
```
## Classes with indirect cycles in their MROs
These are similarly unlikely, but we still shouldn't crash:
```py path=a.pyi
class Foo(Bar): ... # error: [cyclic-class-definition]
class Bar(Baz): ... # error: [cyclic-class-definition]
class Baz(Foo): ... # error: [cyclic-class-definition]
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Unknown, Literal[object]]
reveal_type(Baz.__mro__) # revealed: tuple[Literal[Baz], Unknown, Literal[object]]
```
## Classes with cycles in their MROs, and multiple inheritance
```py path=a.pyi
class Spam: ...
class Foo(Bar): ... # error: [cyclic-class-definition]
class Bar(Baz): ... # error: [cyclic-class-definition]
class Baz(Foo, Spam): ... # error: [cyclic-class-definition]
reveal_type(Foo.__mro__) # revealed: tuple[Literal[Foo], Unknown, Literal[object]]
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Unknown, Literal[object]]
reveal_type(Baz.__mro__) # revealed: tuple[Literal[Baz], Unknown, Literal[object]]
```
## Classes with cycles in their MRO, and a sub-graph
```py path=a.pyi
class FooCycle(BarCycle): ... # error: [cyclic-class-definition]
class Foo: ...
class BarCycle(FooCycle): ... # error: [cyclic-class-definition]
class Bar(Foo): ...
# Avoid emitting the errors for these. The classes have cyclic superclasses,
# but are not themselves cyclic...
class Baz(Bar, BarCycle): ...
class Spam(Baz): ...
reveal_type(FooCycle.__mro__) # revealed: tuple[Literal[FooCycle], Unknown, Literal[object]]
reveal_type(BarCycle.__mro__) # revealed: tuple[Literal[BarCycle], Unknown, Literal[object]]
reveal_type(Baz.__mro__) # revealed: tuple[Literal[Baz], Unknown, Literal[object]]
reveal_type(Spam.__mro__) # revealed: tuple[Literal[Spam], Unknown, Literal[object]]
```

View File

@@ -1,47 +0,0 @@
# Narrowing for nested conditionals
## Multiple negative contributions
```py
def _(x: int):
if x != 1:
if x != 2:
if x != 3:
reveal_type(x) # revealed: int & ~Literal[1] & ~Literal[2] & ~Literal[3]
```
## Multiple negative contributions with simplification
```py
def _(flag1: bool, flag2: bool):
x = 1 if flag1 else 2 if flag2 else 3
if x != 1:
reveal_type(x) # revealed: Literal[2, 3]
if x != 2:
reveal_type(x) # revealed: Literal[3]
```
## elif-else blocks
```py
def _(flag1: bool, flag2: bool):
x = 1 if flag1 else 2 if flag2 else 3
if x != 1:
reveal_type(x) # revealed: Literal[2, 3]
if x == 2:
# TODO should be `Literal[2]`
reveal_type(x) # revealed: Literal[2, 3]
elif x == 3:
reveal_type(x) # revealed: Literal[3]
else:
reveal_type(x) # revealed: Never
elif x != 2:
# TODO should be Literal[1]
reveal_type(x) # revealed: Literal[1, 3]
else:
# TODO should be Never
reveal_type(x) # revealed: Literal[1, 2, 3]
```

View File

@@ -1,91 +0,0 @@
# Narrowing for `!=` conditionals
## `x != None`
```py
def _(flag: bool):
x = None if flag else 1
if x != None:
reveal_type(x) # revealed: Literal[1]
else:
# TODO should be None
reveal_type(x) # revealed: None | Literal[1]
```
## `!=` for other singleton types
```py
def _(flag: bool):
x = True if flag else False
if x != False:
reveal_type(x) # revealed: Literal[True]
else:
# TODO should be Literal[False]
reveal_type(x) # revealed: bool
```
## `x != y` where `y` is of literal type
```py
def _(flag: bool):
x = 1 if flag else 2
if x != 1:
reveal_type(x) # revealed: Literal[2]
```
## `x != y` where `y` is a single-valued type
```py
def _(flag: bool):
class A: ...
class B: ...
C = A if flag else B
if C != A:
reveal_type(C) # revealed: Literal[B]
else:
# TODO should be Literal[A]
reveal_type(C) # revealed: Literal[A, B]
```
## `x != y` where `y` has multiple single-valued options
```py
def _(flag1: bool, flag2: bool):
x = 1 if flag1 else 2
y = 2 if flag2 else 3
if x != y:
reveal_type(x) # revealed: Literal[1, 2]
else:
# TODO should be Literal[2]
reveal_type(x) # revealed: Literal[1, 2]
```
## `!=` for non-single-valued types
Only single-valued types should narrow the type:
```py
def _(flag: bool, a: int, y: int):
x = a if flag else None
if x != y:
reveal_type(x) # revealed: int | None
```
## Mix of single-valued and non-single-valued types
```py
def _(flag1: bool, flag2: bool, a: int):
x = 1 if flag1 else 2
y = 2 if flag2 else a
if x != y:
reveal_type(x) # revealed: Literal[1, 2]
else:
reveal_type(x) # revealed: Literal[1, 2]
```

View File

@@ -1,63 +0,0 @@
# Narrowing for `match` statements
## Single `match` pattern
```py
def _(flag: bool):
x = None if flag else 1
reveal_type(x) # revealed: None | Literal[1]
y = 0
match x:
case None:
y = x
reveal_type(y) # revealed: Literal[0] | None
```
## Class patterns
```py
def get_object() -> object: ...
class A: ...
class B: ...
x = get_object()
reveal_type(x) # revealed: object
match x:
case A():
reveal_type(x) # revealed: A
case B():
# TODO could be `B & ~A`
reveal_type(x) # revealed: B
reveal_type(x) # revealed: object
```
## Class pattern with guard
```py
def get_object() -> object: ...
class A:
def y() -> int: ...
class B: ...
x = get_object()
reveal_type(x) # revealed: object
match x:
case A() if reveal_type(x): # revealed: A
pass
case B() if reveal_type(x): # revealed: B
pass
reveal_type(x) # revealed: object
```

View File

@@ -1,136 +0,0 @@
# Implicit globals from `types.ModuleType`
## Implicit `ModuleType` globals
All modules are instances of `types.ModuleType`. If a name can't be found in any local or global
scope, we look it up as an attribute on `types.ModuleType` in typeshed before deciding that the name
is unbound.
```py
reveal_type(__name__) # revealed: str
reveal_type(__file__) # revealed: str | None
reveal_type(__loader__) # revealed: LoaderProtocol | None
reveal_type(__package__) # revealed: str | None
reveal_type(__doc__) # revealed: str | None
# TODO: Should be `ModuleSpec | None`
# (needs support for `*` imports)
reveal_type(__spec__) # revealed: Unknown | None
reveal_type(__path__) # revealed: @Todo(generics)
class X:
reveal_type(__name__) # revealed: str
def foo():
reveal_type(__name__) # revealed: str
```
However, three attributes on `types.ModuleType` are not present as implicit module globals; these
are excluded:
```py path=unbound_dunders.py
# error: [unresolved-reference]
# revealed: Unknown
reveal_type(__getattr__)
# error: [unresolved-reference]
# revealed: Unknown
reveal_type(__dict__)
# error: [unresolved-reference]
# revealed: Unknown
reveal_type(__init__)
```
## Accessed as attributes
`ModuleType` attributes can also be accessed as attributes on module-literal types. The special
attributes `__dict__` and `__init__`, and all attributes on `builtins.object`, can also be accessed
as attributes on module-literal types, despite the fact that these are inaccessible as globals from
inside the module:
```py
import typing
reveal_type(typing.__name__) # revealed: str
reveal_type(typing.__init__) # revealed: Literal[__init__]
# These come from `builtins.object`, not `types.ModuleType`:
reveal_type(typing.__eq__) # revealed: Literal[__eq__]
reveal_type(typing.__class__) # revealed: Literal[ModuleType]
# TODO: needs support for attribute access on instances, properties and generics;
# should be `dict[str, Any]`
reveal_type(typing.__dict__) # revealed: @Todo(@property)
```
Typeshed includes a fake `__getattr__` method in the stub for `types.ModuleType` to help out with
dynamic imports; but we ignore that for module-literal types where we know exactly which module
we're dealing with:
```py path=__getattr__.py
import typing
# error: [unresolved-attribute]
reveal_type(typing.__getattr__) # revealed: Unknown
```
## `types.ModuleType.__dict__` takes precedence over global variable `__dict__`
It's impossible to override the `__dict__` attribute of `types.ModuleType` instances from inside the
module; we should prioritise the attribute in the `types.ModuleType` stub over a variable named
`__dict__` in the module's global namespace:
```py path=foo.py
__dict__ = "foo"
reveal_type(__dict__) # revealed: Literal["foo"]
```
```py path=bar.py
import foo
from foo import __dict__ as foo_dict
# TODO: needs support for attribute access on instances, properties, and generics;
# should be `dict[str, Any]` for both of these:
reveal_type(foo.__dict__) # revealed: @Todo(@property)
reveal_type(foo_dict) # revealed: @Todo(@property)
```
## Conditionally global or `ModuleType` attribute
Attributes overridden in the module namespace take priority. If a builtin name is conditionally
defined as a global, however, a name lookup should union the `ModuleType` type with the
conditionally defined type:
```py
__file__ = 42
def returns_bool() -> bool:
return True
if returns_bool():
__name__ = 1
reveal_type(__file__) # revealed: Literal[42]
reveal_type(__name__) # revealed: Literal[1] | str
```
## Conditionally global or `ModuleType` attribute, with annotation
The same is true if the name is annotated:
```py
__file__: int = 42
def returns_bool() -> bool:
return True
if returns_bool():
__name__: int = 1
reveal_type(__file__) # revealed: Literal[42]
reveal_type(__name__) # revealed: Literal[1] | str
```

View File

@@ -1,17 +0,0 @@
# Class definitions in stubs
## Cyclical class definition
In type stubs, classes can reference themselves in their base class definitions. For example, in
`typeshed`, we have `class str(Sequence[str]): ...`.
```py path=a.pyi
class Foo[T]: ...
# TODO: actually is subscriptable
# error: [non-subscriptable]
class Bar(Foo[Bar]): ...
reveal_type(Bar) # revealed: Literal[Bar]
reveal_type(Bar.__mro__) # revealed: tuple[Literal[Bar], Unknown, Literal[object]]
```

View File

@@ -1,37 +0,0 @@
# List subscripts
## Indexing into lists
A list can be indexed into with:
- numbers
- slices
```py
x = [1, 2, 3]
reveal_type(x) # revealed: list
# TODO reveal int
reveal_type(x[0]) # revealed: @Todo(return type)
# TODO reveal list
reveal_type(x[0:1]) # revealed: @Todo(return type)
# TODO error
reveal_type(x["a"]) # revealed: @Todo(return type)
```
## Assignments within list assignment
In assignment, we might also have a named assignment. This should also get type checked.
```py
x = [1, 2, 3]
x[0 if (y := 2) else 1] = 5
# TODO error? (indeterminite index type)
x["a" if (y := 2) else 1] = 6
# TODO error (can't index via string)
x["a" if (y := 2) else "b"] = 6
```

View File

@@ -1,95 +0,0 @@
# String subscripts
## Indexing
```py
s = "abcde"
reveal_type(s[0]) # revealed: Literal["a"]
reveal_type(s[1]) # revealed: Literal["b"]
reveal_type(s[-1]) # revealed: Literal["e"]
reveal_type(s[-2]) # revealed: Literal["d"]
reveal_type(s[False]) # revealed: Literal["a"]
reveal_type(s[True]) # revealed: Literal["b"]
a = s[8] # error: [index-out-of-bounds] "Index 8 is out of bounds for string `Literal["abcde"]` with length 5"
reveal_type(a) # revealed: Unknown
b = s[-8] # error: [index-out-of-bounds] "Index -8 is out of bounds for string `Literal["abcde"]` with length 5"
reveal_type(b) # revealed: Unknown
def _(n: int):
a = "abcde"[n]
# TODO: Support overloads... Should be `str`
reveal_type(a) # revealed: @Todo(return type)
```
## Slices
```py
s = "abcde"
reveal_type(s[0:0]) # revealed: Literal[""]
reveal_type(s[0:1]) # revealed: Literal["a"]
reveal_type(s[0:2]) # revealed: Literal["ab"]
reveal_type(s[0:5]) # revealed: Literal["abcde"]
reveal_type(s[0:6]) # revealed: Literal["abcde"]
reveal_type(s[1:3]) # revealed: Literal["bc"]
reveal_type(s[-3:5]) # revealed: Literal["cde"]
reveal_type(s[-4:-2]) # revealed: Literal["bc"]
reveal_type(s[-10:10]) # revealed: Literal["abcde"]
reveal_type(s[0:]) # revealed: Literal["abcde"]
reveal_type(s[2:]) # revealed: Literal["cde"]
reveal_type(s[5:]) # revealed: Literal[""]
reveal_type(s[:2]) # revealed: Literal["ab"]
reveal_type(s[:0]) # revealed: Literal[""]
reveal_type(s[:2]) # revealed: Literal["ab"]
reveal_type(s[:10]) # revealed: Literal["abcde"]
reveal_type(s[:]) # revealed: Literal["abcde"]
reveal_type(s[::-1]) # revealed: Literal["edcba"]
reveal_type(s[::2]) # revealed: Literal["ace"]
reveal_type(s[-2:-5:-1]) # revealed: Literal["dcb"]
reveal_type(s[::-2]) # revealed: Literal["eca"]
reveal_type(s[-1::-3]) # revealed: Literal["eb"]
reveal_type(s[None:2:None]) # revealed: Literal["ab"]
reveal_type(s[1:None:1]) # revealed: Literal["bcde"]
reveal_type(s[None:None:None]) # revealed: Literal["abcde"]
start = 1
stop = None
step = 2
reveal_type(s[start:stop:step]) # revealed: Literal["bd"]
reveal_type(s[False:True]) # revealed: Literal["a"]
reveal_type(s[True:3]) # revealed: Literal["bc"]
s[0:4:0] # error: [zero-stepsize-in-slice]
s[:4:0] # error: [zero-stepsize-in-slice]
s[0::0] # error: [zero-stepsize-in-slice]
s[::0] # error: [zero-stepsize-in-slice]
def _(m: int, n: int, s2: str):
substring1 = s[m:n]
# TODO: Support overloads... Should be `LiteralString`
reveal_type(substring1) # revealed: @Todo(return type)
substring2 = s2[0:5]
# TODO: Support overloads... Should be `str`
reveal_type(substring2) # revealed: @Todo(return type)
```
## Unsupported slice types
```py
# TODO: It would be great if we raised an error here. This can be done once
# we have support for overloads and generics, and once typeshed has a more
# precise annotation for `str.__getitem__`, that makes use of the generic
# `slice[..]` type. We could then infer `slice[str, str]` here and see that
# it doesn't match the signature of `str.__getitem__`.
"foo"["bar":"baz"]
```

View File

@@ -1,123 +0,0 @@
# Tuple subscripts
## Indexing
```py
t = (1, "a", "b")
reveal_type(t[0]) # revealed: Literal[1]
reveal_type(t[1]) # revealed: Literal["a"]
reveal_type(t[-1]) # revealed: Literal["b"]
reveal_type(t[-2]) # revealed: Literal["a"]
reveal_type(t[False]) # revealed: Literal[1]
reveal_type(t[True]) # revealed: Literal["a"]
a = t[4] # error: [index-out-of-bounds]
reveal_type(a) # revealed: Unknown
b = t[-4] # error: [index-out-of-bounds]
reveal_type(b) # revealed: Unknown
```
## Slices
```py
t = (1, "a", None, b"b")
reveal_type(t[0:0]) # revealed: tuple[()]
reveal_type(t[0:1]) # revealed: tuple[Literal[1]]
reveal_type(t[0:2]) # revealed: tuple[Literal[1], Literal["a"]]
reveal_type(t[0:4]) # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[0:5]) # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[1:3]) # revealed: tuple[Literal["a"], None]
reveal_type(t[-2:4]) # revealed: tuple[None, Literal[b"b"]]
reveal_type(t[-3:-1]) # revealed: tuple[Literal["a"], None]
reveal_type(t[-10:10]) # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[0:]) # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[2:]) # revealed: tuple[None, Literal[b"b"]]
reveal_type(t[4:]) # revealed: tuple[()]
reveal_type(t[:0]) # revealed: tuple[()]
reveal_type(t[:2]) # revealed: tuple[Literal[1], Literal["a"]]
reveal_type(t[:10]) # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[:]) # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
reveal_type(t[::-1]) # revealed: tuple[Literal[b"b"], None, Literal["a"], Literal[1]]
reveal_type(t[::2]) # revealed: tuple[Literal[1], None]
reveal_type(t[-2:-5:-1]) # revealed: tuple[None, Literal["a"], Literal[1]]
reveal_type(t[::-2]) # revealed: tuple[Literal[b"b"], Literal["a"]]
reveal_type(t[-1::-3]) # revealed: tuple[Literal[b"b"], Literal[1]]
reveal_type(t[None:2:None]) # revealed: tuple[Literal[1], Literal["a"]]
reveal_type(t[1:None:1]) # revealed: tuple[Literal["a"], None, Literal[b"b"]]
reveal_type(t[None:None:None]) # revealed: tuple[Literal[1], Literal["a"], None, Literal[b"b"]]
start = 1
stop = None
step = 2
reveal_type(t[start:stop:step]) # revealed: tuple[Literal["a"], Literal[b"b"]]
reveal_type(t[False:True]) # revealed: tuple[Literal[1]]
reveal_type(t[True:3]) # revealed: tuple[Literal["a"], None]
t[0:4:0] # error: [zero-stepsize-in-slice]
t[:4:0] # error: [zero-stepsize-in-slice]
t[0::0] # error: [zero-stepsize-in-slice]
t[::0] # error: [zero-stepsize-in-slice]
def _(m: int, n: int):
tuple_slice = t[m:n]
# TODO: Support overloads... Should be `tuple[Literal[1, 'a', b"b"] | None, ...]`
reveal_type(tuple_slice) # revealed: @Todo(return type)
```
## Inheritance
```toml
[environment]
python-version = "3.9"
```
```py
# TODO: `tuple[int, str]` is a valid base (generics)
# error: [invalid-base] "Invalid class base with type `GenericAlias` (all bases must be a class, `Any`, `Unknown` or `Todo`)"
class A(tuple[int, str]): ...
# Runtime value: `(A, tuple, object)`
# TODO: Generics
reveal_type(A.__mro__) # revealed: tuple[Literal[A], Unknown, Literal[object]]
```
## `typing.Tuple`
### Correspondence with `tuple`
`typing.Tuple` can be used interchangeably with `tuple`:
```py
from typing import Tuple
class A: ...
def _(c: Tuple, d: Tuple[int, A], e: Tuple[Any, ...]):
reveal_type(c) # revealed: tuple
reveal_type(d) # revealed: tuple[int, A]
reveal_type(e) # revealed: @Todo(full tuple[...] support)
```
### Inheritance
Inheriting from `Tuple` results in a MRO with `builtins.tuple` and `typing.Generic`. `Tuple` itself
is not a class.
```py
from typing import Tuple
class C(Tuple): ...
# Runtime value: `(C, tuple, typing.Generic, object)`
# TODO: Add `Generic` to the MRO
reveal_type(C.__mro__) # revealed: tuple[Literal[C], Literal[tuple], Unknown, Literal[object]]
```

View File

@@ -1,182 +0,0 @@
# Suppressing errors with `knot: ignore`
Type check errors can be suppressed by a `knot: ignore` comment on the same line as the violation.
## Simple `knot: ignore`
```py
a = 4 + test # knot: ignore
```
## Suppressing a specific code
```py
a = 4 + test # knot: ignore[unresolved-reference]
```
## Unused suppression
```py
test = 10
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'possibly-unresolved-reference'"
a = test + 3 # knot: ignore[possibly-unresolved-reference]
```
## Unused suppression if the error codes don't match
```py
# error: [unresolved-reference]
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'possibly-unresolved-reference'"
a = test + 3 # knot: ignore[possibly-unresolved-reference]
```
## Suppressed unused comment
```py
# error: [unused-ignore-comment]
a = 10 / 2 # knot: ignore[division-by-zero]
a = 10 / 2 # knot: ignore[division-by-zero, unused-ignore-comment]
a = 10 / 2 # knot: ignore[unused-ignore-comment, division-by-zero]
a = 10 / 2 # knot: ignore[unused-ignore-comment] # type: ignore
a = 10 / 2 # type: ignore # knot: ignore[unused-ignore-comment]
```
## Unused ignore comment
```py
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unused-ignore-comment'"
a = 10 / 0 # knot: ignore[division-by-zero, unused-ignore-comment]
```
## Multiple unused comments
Today, Red Knot emits a diagnostic for every unused code. We might want to group the codes by
comment at some point in the future.
```py
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'division-by-zero'"
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unresolved-reference'"
a = 10 / 2 # knot: ignore[division-by-zero, unresolved-reference]
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'invalid-assignment'"
# error: [unused-ignore-comment] "Unused `knot: ignore` directive: 'unresolved-reference'"
a = 10 / 0 # knot: ignore[invalid-assignment, division-by-zero, unresolved-reference]
```
## Multiple suppressions
```py
# fmt: off
def test(a: f"f-string type annotation", b: b"byte-string-type-annotation"): ... # knot: ignore[fstring-type-annotation, byte-string-type-annotation]
```
## Can't suppress syntax errors
<!-- blacken-docs:off -->
```py
# error: [invalid-syntax]
# error: [unused-ignore-comment]
def test( # knot: ignore
```
<!-- blacken-docs:on -->
## Can't suppress `revealed-type` diagnostics
```py
a = 10
# revealed: Literal[10]
# error: [unknown-rule] "Unknown rule `revealed-type`"
reveal_type(a) # knot: ignore[revealed-type]
```
## Extra whitespace in type ignore comments is allowed
```py
a = 10 / 0 # knot : ignore
a = 10 / 0 # knot: ignore [ division-by-zero ]
```
## Whitespace is optional
```py
# fmt: off
a = 10 / 0 #knot:ignore[division-by-zero]
```
## Trailing codes comma
Trailing commas in the codes section are allowed:
```py
a = 10 / 0 # knot: ignore[division-by-zero,]
```
## Invalid characters in codes
```py
# error: [division-by-zero]
# error: [invalid-ignore-comment] "Invalid `knot: ignore` comment: expected a alphanumeric character or `-` or `_` as code"
a = 10 / 0 # knot: ignore[*-*]
```
## Trailing whitespace
<!-- blacken-docs:off -->
```py
a = 10 / 0 # knot: ignore[division-by-zero]
# ^^^^^^ trailing whitespace
```
<!-- blacken-docs:on -->
## Missing comma
A missing comma results in an invalid suppression comment. We may want to recover from this in the
future.
```py
# error: [unresolved-reference]
# error: [invalid-ignore-comment] "Invalid `knot: ignore` comment: expected a comma separating the rule codes"
a = x / 0 # knot: ignore[division-by-zero unresolved-reference]
```
## Missing closing bracket
```py
# error: [unresolved-reference] "Name `x` used when not defined"
# error: [invalid-ignore-comment] "Invalid `knot: ignore` comment: expected a comma separating the rule codes"
a = x / 2 # knot: ignore[unresolved-reference
```
## Empty codes
An empty codes array suppresses no-diagnostics and is always useless
```py
# error: [division-by-zero]
# error: [unused-ignore-comment] "Unused `knot: ignore` without a code"
a = 4 / 0 # knot: ignore[]
```
## File-level suppression comments
File level suppression comments are currently intentionally unsupported because we've yet to decide
if they should use a different syntax that also supports enabling rules or changing the rule's
severity: `knot: possibly-undefined-reference=error`
```py
# error: [unused-ignore-comment]
# knot: ignore[division-by-zero]
a = 4 / 0 # error: [division-by-zero]
```
## Unknown rule
```py
# error: [unknown-rule] "Unknown rule `is-equal-14`"
a = 10 + 4 # knot: ignore[is-equal-14]
```

View File

@@ -1,352 +0,0 @@
# Assignable-to relation
The `is_assignable_to(S, T)` relation below checks if type `S` is assignable to type `T` (target).
This allows us to check if a type `S` can be used in a context where a type `T` is expected
(function arguments, variable assignments). See the [typing documentation] for a precise definition
of this concept.
## Basic types
### Fully static
Fully static types participate in subtyping. If a type `S` is a subtype of `T`, `S` will also be
assignable to `T`. Two equivalent types are subtypes of each other:
```py
from knot_extensions import static_assert, is_assignable_to
class Parent: ...
class Child1(Parent): ...
class Child2(Parent): ...
class Grandchild(Child1, Child2): ...
class Unrelated: ...
static_assert(is_assignable_to(int, int))
static_assert(is_assignable_to(Parent, Parent))
static_assert(is_assignable_to(Child1, Parent))
static_assert(is_assignable_to(Grandchild, Parent))
static_assert(is_assignable_to(Unrelated, Unrelated))
static_assert(not is_assignable_to(str, int))
static_assert(not is_assignable_to(object, int))
static_assert(not is_assignable_to(Parent, Child1))
static_assert(not is_assignable_to(Unrelated, Parent))
static_assert(not is_assignable_to(Child1, Child2))
```
### Gradual types
Gradual types do not participate in subtyping, but can still be assignable to other types (and
static types can be assignable to gradual types):
```py
from knot_extensions import static_assert, is_assignable_to, Unknown
from typing import Any
static_assert(is_assignable_to(Unknown, Literal[1]))
static_assert(is_assignable_to(Any, Literal[1]))
static_assert(is_assignable_to(Literal[1], Unknown))
static_assert(is_assignable_to(Literal[1], Any))
```
## Literal types
### Boolean literals
`Literal[True]` and `Literal[False]` are both subtypes of (and therefore assignable to) `bool`,
which is in turn a subtype of `int`:
```py
from knot_extensions import static_assert, is_assignable_to
from typing import Literal
static_assert(is_assignable_to(Literal[True], Literal[True]))
static_assert(is_assignable_to(Literal[True], bool))
static_assert(is_assignable_to(Literal[True], int))
static_assert(not is_assignable_to(Literal[True], Literal[False]))
static_assert(not is_assignable_to(bool, Literal[True]))
```
### Integer literals
```py
from knot_extensions import static_assert, is_assignable_to
from typing import Literal
static_assert(is_assignable_to(Literal[1], Literal[1]))
static_assert(is_assignable_to(Literal[1], int))
static_assert(not is_assignable_to(Literal[1], Literal[2]))
static_assert(not is_assignable_to(int, Literal[1]))
static_assert(not is_assignable_to(Literal[1], str))
```
### String literals and `LiteralString`
All string-literal types are subtypes of (and therefore assignable to) `LiteralString`, which is in
turn a subtype of `str`:
```py
from knot_extensions import static_assert, is_assignable_to
from typing_extensions import Literal, LiteralString
static_assert(is_assignable_to(Literal["foo"], Literal["foo"]))
static_assert(is_assignable_to(Literal["foo"], LiteralString))
static_assert(is_assignable_to(Literal["foo"], str))
static_assert(is_assignable_to(LiteralString, str))
static_assert(not is_assignable_to(Literal["foo"], Literal["bar"]))
static_assert(not is_assignable_to(str, Literal["foo"]))
static_assert(not is_assignable_to(str, LiteralString))
```
### Byte literals
```py
from knot_extensions import static_assert, is_assignable_to
from typing_extensions import Literal, LiteralString
static_assert(is_assignable_to(Literal[b"foo"], bytes))
static_assert(is_assignable_to(Literal[b"foo"], Literal[b"foo"]))
static_assert(not is_assignable_to(Literal[b"foo"], str))
static_assert(not is_assignable_to(Literal[b"foo"], LiteralString))
static_assert(not is_assignable_to(Literal[b"foo"], Literal[b"bar"]))
static_assert(not is_assignable_to(Literal[b"foo"], Literal["foo"]))
static_assert(not is_assignable_to(Literal["foo"], Literal[b"foo"]))
```
## `type[…]` and class literals
In the following tests, `TypeOf[str]` is a singleton type with a single inhabitant, the class `str`.
This contrasts with `type[str]`, which represents "all possible subclasses of `str`".
Both `TypeOf[str]` and `type[str]` are subtypes of `type` and `type[object]`, which both represent
"all possible instances of `type`"; therefore both `type[str]` and `TypeOf[str]` are assignable to
`type`. `type[Any]`, on the other hand, represents a type of unknown size or inhabitants, but which
is known to be no larger than the set of possible objects represented by `type`.
```py
from knot_extensions import static_assert, is_assignable_to, Unknown, TypeOf
from typing import Any
static_assert(is_assignable_to(type, type))
static_assert(is_assignable_to(type[object], type[object]))
static_assert(is_assignable_to(type, type[object]))
static_assert(is_assignable_to(type[object], type))
static_assert(is_assignable_to(type[str], type[object]))
static_assert(is_assignable_to(TypeOf[str], type[object]))
static_assert(is_assignable_to(type[str], type))
static_assert(is_assignable_to(TypeOf[str], type))
static_assert(is_assignable_to(type[str], type[str]))
static_assert(is_assignable_to(TypeOf[str], type[str]))
static_assert(not is_assignable_to(TypeOf[int], type[str]))
static_assert(not is_assignable_to(type, type[str]))
static_assert(not is_assignable_to(type[object], type[str]))
static_assert(is_assignable_to(type[Any], type[Any]))
static_assert(is_assignable_to(type[Any], type[object]))
static_assert(is_assignable_to(type[object], type[Any]))
static_assert(is_assignable_to(type, type[Any]))
static_assert(is_assignable_to(type[Any], type[str]))
static_assert(is_assignable_to(type[str], type[Any]))
static_assert(is_assignable_to(TypeOf[str], type[Any]))
static_assert(is_assignable_to(type[Unknown], type[Unknown]))
static_assert(is_assignable_to(type[Unknown], type[object]))
static_assert(is_assignable_to(type[object], type[Unknown]))
static_assert(is_assignable_to(type, type[Unknown]))
static_assert(is_assignable_to(type[Unknown], type[str]))
static_assert(is_assignable_to(type[str], type[Unknown]))
static_assert(is_assignable_to(TypeOf[str], type[Unknown]))
static_assert(is_assignable_to(type[Unknown], type[Any]))
static_assert(is_assignable_to(type[Any], type[Unknown]))
static_assert(not is_assignable_to(object, type[Any]))
static_assert(not is_assignable_to(str, type[Any]))
class Meta(type): ...
static_assert(is_assignable_to(type[Any], Meta))
static_assert(is_assignable_to(type[Unknown], Meta))
static_assert(is_assignable_to(Meta, type[Any]))
static_assert(is_assignable_to(Meta, type[Unknown]))
```
## Tuple types
```py
from knot_extensions import static_assert, is_assignable_to
from typing import Literal, Any
static_assert(is_assignable_to(tuple[()], tuple[()]))
static_assert(is_assignable_to(tuple[int], tuple[int]))
static_assert(is_assignable_to(tuple[int], tuple[Any]))
static_assert(is_assignable_to(tuple[Any], tuple[int]))
static_assert(is_assignable_to(tuple[int, str], tuple[int, str]))
static_assert(is_assignable_to(tuple[Literal[1], Literal[2]], tuple[int, int]))
static_assert(is_assignable_to(tuple[Any, Literal[2]], tuple[int, int]))
static_assert(is_assignable_to(tuple[Literal[1], Any], tuple[int, int]))
static_assert(not is_assignable_to(tuple[()], tuple[int]))
static_assert(not is_assignable_to(tuple[int], tuple[str]))
static_assert(not is_assignable_to(tuple[int], tuple[int, str]))
static_assert(not is_assignable_to(tuple[int, str], tuple[int]))
static_assert(not is_assignable_to(tuple[int, int], tuple[Literal[1], int]))
static_assert(not is_assignable_to(tuple[Any, Literal[2]], tuple[int, str]))
```
## Union types
```py
from knot_extensions import static_assert, is_assignable_to, Unknown
from typing import Literal, Any
static_assert(is_assignable_to(int, int | str))
static_assert(is_assignable_to(str, int | str))
static_assert(is_assignable_to(int | str, int | str))
static_assert(is_assignable_to(str | int, int | str))
static_assert(is_assignable_to(Literal[1], int | str))
static_assert(is_assignable_to(Literal[1], Unknown | str))
static_assert(is_assignable_to(Literal[1] | Literal[2], Literal[1] | Literal[2]))
static_assert(is_assignable_to(Literal[1] | Literal[2], int))
static_assert(is_assignable_to(Literal[1] | None, int | None))
static_assert(is_assignable_to(Any, int | str))
static_assert(is_assignable_to(Any | int, int))
static_assert(is_assignable_to(str, int | Any))
static_assert(not is_assignable_to(int | None, int))
static_assert(not is_assignable_to(int | None, str | None))
static_assert(not is_assignable_to(Literal[1] | None, int))
static_assert(not is_assignable_to(Literal[1] | None, str | None))
static_assert(not is_assignable_to(Any | int | str, int))
```
## Intersection types
```py
from knot_extensions import static_assert, is_assignable_to, Intersection, Not
from typing_extensions import Any, Literal
class Parent: ...
class Child1(Parent): ...
class Child2(Parent): ...
class Grandchild(Child1, Child2): ...
class Unrelated: ...
static_assert(is_assignable_to(Intersection[Child1, Child2], Child1))
static_assert(is_assignable_to(Intersection[Child1, Child2], Child2))
static_assert(is_assignable_to(Intersection[Child1, Child2], Parent))
static_assert(is_assignable_to(Intersection[Child1, Parent], Parent))
static_assert(is_assignable_to(Intersection[Parent, Unrelated], Parent))
static_assert(is_assignable_to(Intersection[Child1, Unrelated], Child1))
static_assert(is_assignable_to(Intersection[Child1, Not[Child2]], Child1))
static_assert(is_assignable_to(Intersection[Child1, Not[Child2]], Parent))
static_assert(is_assignable_to(Intersection[Child1, Not[Grandchild]], Parent))
static_assert(is_assignable_to(Intersection[Child1, Child2], Intersection[Child1, Child2]))
static_assert(is_assignable_to(Intersection[Child1, Child2], Intersection[Child2, Child1]))
static_assert(is_assignable_to(Grandchild, Intersection[Child1, Child2]))
static_assert(not is_assignable_to(Parent, Intersection[Parent, Unrelated]))
static_assert(not is_assignable_to(int, Intersection[int, Not[Literal[1]]]))
static_assert(not is_assignable_to(int, Not[int]))
static_assert(not is_assignable_to(int, Not[Literal[1]]))
static_assert(not is_assignable_to(Intersection[Any, Parent], Unrelated))
# TODO: The following assertions should not fail (see https://github.com/astral-sh/ruff/issues/14899)
# error: [static-assert-error]
static_assert(is_assignable_to(Intersection[Any, int], int))
# error: [static-assert-error]
static_assert(is_assignable_to(Intersection[Unrelated, Any], Intersection[Unrelated, Any]))
# error: [static-assert-error]
static_assert(is_assignable_to(Intersection[Unrelated, Any], Intersection[Unrelated, Not[Any]]))
# error: [static-assert-error]
static_assert(is_assignable_to(Intersection[Unrelated, Any], Not[tuple[Unrelated, Any]]))
```
## General properties
See also: our property tests in `property_tests.rs`.
### Everything is assignable to `object`
`object` is Python's top type; the set of all possible objects at runtime:
```py
from knot_extensions import static_assert, is_assignable_to, Unknown
from typing import Literal, Any
static_assert(is_assignable_to(str, object))
static_assert(is_assignable_to(Literal[1], object))
static_assert(is_assignable_to(object, object))
static_assert(is_assignable_to(type, object))
static_assert(is_assignable_to(Any, object))
static_assert(is_assignable_to(Unknown, object))
static_assert(is_assignable_to(type[object], object))
static_assert(is_assignable_to(type[str], object))
static_assert(is_assignable_to(type[Any], object))
```
### Every type is assignable to `Any` / `Unknown`
`Any` and `Unknown` are gradual types. They could materialize to any given type at runtime, and so
any type is assignable to them:
```py
from knot_extensions import static_assert, is_assignable_to, Unknown
from typing import Literal, Any
static_assert(is_assignable_to(str, Any))
static_assert(is_assignable_to(Literal[1], Any))
static_assert(is_assignable_to(object, Any))
static_assert(is_assignable_to(type, Any))
static_assert(is_assignable_to(Any, Any))
static_assert(is_assignable_to(Unknown, Any))
static_assert(is_assignable_to(type[object], Any))
static_assert(is_assignable_to(type[str], Any))
static_assert(is_assignable_to(type[Any], Any))
static_assert(is_assignable_to(str, Unknown))
static_assert(is_assignable_to(Literal[1], Unknown))
static_assert(is_assignable_to(object, Unknown))
static_assert(is_assignable_to(type, Unknown))
static_assert(is_assignable_to(Any, Unknown))
static_assert(is_assignable_to(Unknown, Unknown))
static_assert(is_assignable_to(type[object], Unknown))
static_assert(is_assignable_to(type[str], Unknown))
static_assert(is_assignable_to(type[Any], Unknown))
```
### `Never` is assignable to every type
`Never` is Python's bottom type: the empty set, a type with no inhabitants. It is therefore
assignable to any arbitrary type.
```py
from knot_extensions import static_assert, is_assignable_to, Unknown
from typing_extensions import Never, Any
static_assert(is_assignable_to(Never, str))
static_assert(is_assignable_to(Never, Literal[1]))
static_assert(is_assignable_to(Never, object))
static_assert(is_assignable_to(Never, type))
static_assert(is_assignable_to(Never, Any))
static_assert(is_assignable_to(Never, Unknown))
static_assert(is_assignable_to(Never, type[object]))
static_assert(is_assignable_to(Never, type[str]))
static_assert(is_assignable_to(Never, type[Any]))
```
[typing documentation]: https://typing.readthedocs.io/en/latest/spec/concepts.html#the-assignable-to-or-consistent-subtyping-relation

View File

@@ -1,87 +0,0 @@
# Equivalence relation
`is_equivalent_to` implements [the equivalence relation] for fully static types.
Two types `A` and `B` are equivalent iff `A` is a subtype of `B` and `B` is a subtype of `A`.
## Basic
```py
from typing import Any
from typing_extensions import Literal
from knot_extensions import Unknown, is_equivalent_to, static_assert
static_assert(is_equivalent_to(Literal[1, 2], Literal[1, 2]))
static_assert(is_equivalent_to(type[object], type))
static_assert(not is_equivalent_to(Any, Any))
static_assert(not is_equivalent_to(Unknown, Unknown))
static_assert(not is_equivalent_to(Any, None))
static_assert(not is_equivalent_to(Literal[1, 2], Literal[1, 0]))
static_assert(not is_equivalent_to(Literal[1, 2], Literal[1, 2, 3]))
```
## Equivalence is commutative
```py
from typing_extensions import Literal
from knot_extensions import is_equivalent_to, static_assert
static_assert(is_equivalent_to(type, type[object]))
static_assert(not is_equivalent_to(Literal[1, 0], Literal[1, 2]))
static_assert(not is_equivalent_to(Literal[1, 2, 3], Literal[1, 2]))
```
## Differently ordered intersections and unions are equivalent
```py
from knot_extensions import is_equivalent_to, static_assert, Intersection, Not
class P: ...
class Q: ...
class R: ...
class S: ...
static_assert(is_equivalent_to(P | Q | R, P | R | Q)) # 1
static_assert(is_equivalent_to(P | Q | R, Q | P | R)) # 2
static_assert(is_equivalent_to(P | Q | R, Q | R | P)) # 3
static_assert(is_equivalent_to(P | Q | R, R | P | Q)) # 4
static_assert(is_equivalent_to(P | Q | R, R | Q | P)) # 5
static_assert(is_equivalent_to(P | R | Q, Q | P | R)) # 6
static_assert(is_equivalent_to(P | R | Q, Q | R | P)) # 7
static_assert(is_equivalent_to(P | R | Q, R | P | Q)) # 8
static_assert(is_equivalent_to(P | R | Q, R | Q | P)) # 9
static_assert(is_equivalent_to(Q | P | R, Q | R | P)) # 10
static_assert(is_equivalent_to(Q | P | R, R | P | Q)) # 11
static_assert(is_equivalent_to(Q | P | R, R | Q | P)) # 12
static_assert(is_equivalent_to(Q | R | P, R | P | Q)) # 13
static_assert(is_equivalent_to(Q | R | P, R | Q | P)) # 14
static_assert(is_equivalent_to(R | P | Q, R | Q | P)) # 15
static_assert(is_equivalent_to(str | None, None | str))
static_assert(is_equivalent_to(Intersection[P, Q], Intersection[Q, P]))
static_assert(is_equivalent_to(Intersection[Q, Not[P]], Intersection[Not[P], Q]))
static_assert(is_equivalent_to(Intersection[Q, R, Not[P]], Intersection[Not[P], R, Q]))
static_assert(is_equivalent_to(Intersection[Q | R, Not[P | S]], Intersection[Not[S | P], R | Q]))
```
## Tuples containing equivalent but differently ordered unions/intersections are equivalent
```py
from knot_extensions import is_equivalent_to, TypeOf, static_assert, Intersection, Not
from typing import Literal
class P: ...
class Q: ...
class R: ...
class S: ...
static_assert(is_equivalent_to(tuple[P | Q], tuple[Q | P]))
static_assert(is_equivalent_to(tuple[P | None], tuple[None | P]))
static_assert(
is_equivalent_to(tuple[Intersection[P, Q] | Intersection[R, Not[S]]], tuple[Intersection[Not[S], R] | Intersection[Q, P]])
)
```
[the equivalence relation]: https://typing.readthedocs.io/en/latest/spec/glossary.html#term-equivalent

View File

@@ -1,54 +0,0 @@
# Fully-static types
A type is fully static iff it does not contain any gradual forms.
## Fully-static
```py
from typing_extensions import Literal, LiteralString, Never
from knot_extensions import Intersection, Not, TypeOf, is_fully_static, static_assert
static_assert(is_fully_static(Never))
static_assert(is_fully_static(None))
static_assert(is_fully_static(Literal[1]))
static_assert(is_fully_static(Literal[True]))
static_assert(is_fully_static(Literal["abc"]))
static_assert(is_fully_static(Literal[b"abc"]))
static_assert(is_fully_static(LiteralString))
static_assert(is_fully_static(str))
static_assert(is_fully_static(object))
static_assert(is_fully_static(type))
static_assert(is_fully_static(TypeOf[str]))
static_assert(is_fully_static(TypeOf[Literal]))
static_assert(is_fully_static(str | None))
static_assert(is_fully_static(Intersection[str, Not[LiteralString]]))
static_assert(is_fully_static(tuple[()]))
static_assert(is_fully_static(tuple[int, object]))
static_assert(is_fully_static(type[str]))
static_assert(is_fully_static(type[object]))
```
## Non-fully-static
```py
from typing_extensions import Any, Literal, LiteralString
from knot_extensions import Intersection, Not, TypeOf, Unknown, is_fully_static, static_assert
static_assert(not is_fully_static(Any))
static_assert(not is_fully_static(Unknown))
static_assert(not is_fully_static(Any | str))
static_assert(not is_fully_static(str | Unknown))
static_assert(not is_fully_static(Intersection[Any, Not[LiteralString]]))
static_assert(not is_fully_static(tuple[Any, ...]))
static_assert(not is_fully_static(tuple[int, Any]))
static_assert(not is_fully_static(type[Any]))
```

View File

@@ -1,64 +0,0 @@
# Gradual equivalence relation
Two gradual types `A` and `B` are equivalent if all [materializations] of `A` are also
materializations of `B`, and all materializations of `B` are also materializations of `A`.
## Basic
```py
from typing import Any
from typing_extensions import Literal, LiteralString, Never
from knot_extensions import AlwaysFalsy, AlwaysTruthy, TypeOf, Unknown, is_gradual_equivalent_to, static_assert
static_assert(is_gradual_equivalent_to(Any, Any))
static_assert(is_gradual_equivalent_to(Unknown, Unknown))
static_assert(is_gradual_equivalent_to(Any, Unknown))
static_assert(is_gradual_equivalent_to(Never, Never))
static_assert(is_gradual_equivalent_to(AlwaysTruthy, AlwaysTruthy))
static_assert(is_gradual_equivalent_to(AlwaysFalsy, AlwaysFalsy))
static_assert(is_gradual_equivalent_to(LiteralString, LiteralString))
static_assert(is_gradual_equivalent_to(Literal[True], Literal[True]))
static_assert(is_gradual_equivalent_to(Literal[False], Literal[False]))
static_assert(is_gradual_equivalent_to(TypeOf[0:1:2], TypeOf[0:1:2]))
static_assert(is_gradual_equivalent_to(TypeOf[str], TypeOf[str]))
static_assert(is_gradual_equivalent_to(type, type[object]))
static_assert(not is_gradual_equivalent_to(type, type[Any]))
static_assert(not is_gradual_equivalent_to(type[object], type[Any]))
```
## Unions and intersections
```py
from typing import Any
from knot_extensions import Intersection, Not, Unknown, is_gradual_equivalent_to, static_assert
static_assert(is_gradual_equivalent_to(str | int, str | int))
static_assert(is_gradual_equivalent_to(str | int | Any, str | int | Unknown))
static_assert(is_gradual_equivalent_to(str | int, int | str))
static_assert(
is_gradual_equivalent_to(Intersection[str, int, Not[bytes], Not[None]], Intersection[int, str, Not[None], Not[bytes]])
)
# TODO: `~type[Any]` shoudld be gradually equivalent to `~type[Unknown]`
# error: [static-assert-error]
static_assert(is_gradual_equivalent_to(Intersection[str | int, Not[type[Any]]], Intersection[int | str, Not[type[Unknown]]]))
static_assert(not is_gradual_equivalent_to(str | int, int | str | bytes))
static_assert(not is_gradual_equivalent_to(str | int | bytes, int | str | dict))
```
## Tuples
```py
from knot_extensions import Unknown, is_gradual_equivalent_to, static_assert
static_assert(is_gradual_equivalent_to(tuple[str, Any], tuple[str, Unknown]))
static_assert(not is_gradual_equivalent_to(tuple[str, int], tuple[str, int, bytes]))
static_assert(not is_gradual_equivalent_to(tuple[str, int], tuple[int, str]))
```
[materializations]: https://typing.readthedocs.io/en/latest/spec/glossary.html#term-materialize

View File

@@ -1,56 +0,0 @@
# Singleton types
A type is a singleton type iff it has exactly one inhabitant.
## Basic
```py
from typing_extensions import Literal, Never
from knot_extensions import is_singleton, static_assert
static_assert(is_singleton(None))
static_assert(is_singleton(Literal[True]))
static_assert(is_singleton(Literal[False]))
static_assert(is_singleton(type[bool]))
static_assert(not is_singleton(Never))
static_assert(not is_singleton(str))
static_assert(not is_singleton(Literal[345]))
static_assert(not is_singleton(Literal[1, 2]))
static_assert(not is_singleton(tuple[()]))
static_assert(not is_singleton(tuple[None]))
static_assert(not is_singleton(tuple[None, Literal[True]]))
```
## `NoDefault`
### 3.12
```toml
[environment]
python-version = "3.12"
```
```py
from typing_extensions import _NoDefaultType
from knot_extensions import is_singleton, static_assert
static_assert(is_singleton(_NoDefaultType))
```
### 3.13
```toml
[environment]
python-version = "3.13"
```
```py
from typing import _NoDefaultType
from knot_extensions import is_singleton, static_assert
static_assert(is_singleton(_NoDefaultType))
```

View File

@@ -1,453 +0,0 @@
# Subtype relation
The `is_subtype_of(S, T)` relation below checks if type `S` is a subtype of type `T`.
A fully static type `S` is a subtype of another fully static type `T` iff the set of values
represented by `S` is a subset of the set of values represented by `T`.
See the [typing documentation] for more information.
## Basic builtin types
- `bool` is a subtype of `int`. This is modeled after Python's runtime behavior, where `int` is a
supertype of `bool` (present in `bool`s bases and MRO).
- `int` is not a subtype of `float`/`complex`, even though `float`/`complex` can be used in place of
`int` in some contexts (see [special case for float and complex]).
```py
from knot_extensions import is_subtype_of, static_assert
static_assert(is_subtype_of(bool, bool))
static_assert(is_subtype_of(bool, int))
static_assert(is_subtype_of(bool, object))
static_assert(is_subtype_of(int, int))
static_assert(is_subtype_of(int, object))
static_assert(is_subtype_of(object, object))
static_assert(not is_subtype_of(int, bool))
static_assert(not is_subtype_of(int, str))
static_assert(not is_subtype_of(object, int))
static_assert(not is_subtype_of(int, float))
static_assert(not is_subtype_of(int, complex))
static_assert(is_subtype_of(TypeError, Exception))
static_assert(is_subtype_of(FloatingPointError, Exception))
```
## Class hierarchies
```py
from knot_extensions import is_subtype_of, static_assert
from typing_extensions import Never
class A: ...
class B1(A): ...
class B2(A): ...
class C(B1, B2): ...
static_assert(is_subtype_of(B1, A))
static_assert(not is_subtype_of(A, B1))
static_assert(is_subtype_of(B2, A))
static_assert(not is_subtype_of(A, B2))
static_assert(not is_subtype_of(B1, B2))
static_assert(not is_subtype_of(B2, B1))
static_assert(is_subtype_of(C, B1))
static_assert(is_subtype_of(C, B2))
static_assert(not is_subtype_of(B1, C))
static_assert(not is_subtype_of(B2, C))
static_assert(is_subtype_of(C, A))
static_assert(not is_subtype_of(A, C))
static_assert(is_subtype_of(Never, A))
static_assert(is_subtype_of(Never, B1))
static_assert(is_subtype_of(Never, B2))
static_assert(is_subtype_of(Never, C))
static_assert(is_subtype_of(A, object))
static_assert(is_subtype_of(B1, object))
static_assert(is_subtype_of(B2, object))
static_assert(is_subtype_of(C, object))
```
## Literal types
```py
from typing_extensions import Literal, LiteralString
from knot_extensions import is_subtype_of, static_assert
# Boolean literals
static_assert(is_subtype_of(Literal[True], bool))
static_assert(is_subtype_of(Literal[True], int))
static_assert(is_subtype_of(Literal[True], object))
# Integer literals
static_assert(is_subtype_of(Literal[1], int))
static_assert(is_subtype_of(Literal[1], object))
static_assert(not is_subtype_of(Literal[1], bool))
# See the note above (or link below) concerning int and float/complex
static_assert(not is_subtype_of(Literal[1], float))
# String literals
static_assert(is_subtype_of(Literal["foo"], LiteralString))
static_assert(is_subtype_of(Literal["foo"], str))
static_assert(is_subtype_of(Literal["foo"], object))
static_assert(is_subtype_of(LiteralString, str))
static_assert(is_subtype_of(LiteralString, object))
# Bytes literals
static_assert(is_subtype_of(Literal[b"foo"], bytes))
static_assert(is_subtype_of(Literal[b"foo"], object))
```
## Tuple types
```py
from knot_extensions import is_subtype_of, static_assert
class A1: ...
class B1(A1): ...
class A2: ...
class B2(A2): ...
class Unrelated: ...
static_assert(is_subtype_of(B1, A1))
static_assert(is_subtype_of(B2, A2))
# Zero-element tuples
static_assert(is_subtype_of(tuple[()], tuple[()]))
static_assert(not is_subtype_of(tuple[()], tuple[Unrelated]))
# One-element tuples
static_assert(is_subtype_of(tuple[B1], tuple[A1]))
static_assert(not is_subtype_of(tuple[B1], tuple[Unrelated]))
static_assert(not is_subtype_of(tuple[B1], tuple[()]))
static_assert(not is_subtype_of(tuple[B1], tuple[A1, Unrelated]))
# Two-element tuples
static_assert(is_subtype_of(tuple[B1, B2], tuple[A1, A2]))
static_assert(not is_subtype_of(tuple[B1, B2], tuple[Unrelated, A2]))
static_assert(not is_subtype_of(tuple[B1, B2], tuple[A1, Unrelated]))
static_assert(not is_subtype_of(tuple[B1, B2], tuple[Unrelated, Unrelated]))
static_assert(not is_subtype_of(tuple[B1, B2], tuple[()]))
static_assert(not is_subtype_of(tuple[B1, B2], tuple[A1]))
static_assert(not is_subtype_of(tuple[B1, B2], tuple[A1, A2, Unrelated]))
static_assert(is_subtype_of(tuple[int], tuple))
```
## Union types
```py
from knot_extensions import is_subtype_of, static_assert
class A: ...
class B1(A): ...
class B2(A): ...
class Unrelated1: ...
class Unrelated2: ...
static_assert(is_subtype_of(B1, A))
static_assert(is_subtype_of(B2, A))
# Union on the right hand side
static_assert(is_subtype_of(B1, A | Unrelated1))
static_assert(is_subtype_of(B1, Unrelated1 | A))
static_assert(not is_subtype_of(B1, Unrelated1 | Unrelated2))
# Union on the left hand side
static_assert(is_subtype_of(B1 | B2, A))
static_assert(is_subtype_of(B1 | B2 | A, object))
static_assert(not is_subtype_of(B1 | Unrelated1, A))
static_assert(not is_subtype_of(Unrelated1 | B1, A))
# Union on both sides
static_assert(is_subtype_of(B1 | bool, A | int))
static_assert(is_subtype_of(B1 | bool, int | A))
static_assert(not is_subtype_of(B1 | bool, Unrelated1 | int))
static_assert(not is_subtype_of(B1 | bool, int | Unrelated1))
# Example: Unions of literals
static_assert(is_subtype_of(Literal[1, 2, 3], int))
static_assert(not is_subtype_of(Literal[1, "two", 3], int))
```
## Intersection types
```py
from typing_extensions import Literal, LiteralString
from knot_extensions import Intersection, Not, is_subtype_of, static_assert
class A: ...
class B1(A): ...
class B2(A): ...
class C(B1, B2): ...
class Unrelated: ...
static_assert(is_subtype_of(B1, A))
static_assert(is_subtype_of(B2, A))
static_assert(is_subtype_of(C, A))
static_assert(is_subtype_of(C, B1))
static_assert(is_subtype_of(C, B2))
# For complements, the subtyping relation is reversed:
static_assert(is_subtype_of(Not[A], Not[B1]))
static_assert(is_subtype_of(Not[A], Not[B2]))
static_assert(is_subtype_of(Not[A], Not[C]))
static_assert(is_subtype_of(Not[B1], Not[C]))
static_assert(is_subtype_of(Not[B2], Not[C]))
# The intersection of two types is a subtype of both:
static_assert(is_subtype_of(Intersection[B1, B2], B1))
static_assert(is_subtype_of(Intersection[B1, B2], B2))
# … and of their common supertype:
static_assert(is_subtype_of(Intersection[B1, B2], A))
# A common subtype of two types is a subtype of their intersection:
static_assert(is_subtype_of(C, Intersection[B1, B2]))
# … but not the other way around:
static_assert(not is_subtype_of(Intersection[B1, B2], C))
# "Removing" B1 from A leaves a subtype of A.
static_assert(is_subtype_of(Intersection[A, Not[B1]], A))
static_assert(is_subtype_of(Intersection[A, Not[B1]], Not[B1]))
# B1 and B2 are not disjoint, so this is not true:
static_assert(not is_subtype_of(B2, Intersection[A, Not[B1]]))
# … but for two disjoint subtypes, it is:
static_assert(is_subtype_of(Literal[2], Intersection[int, Not[Literal[1]]]))
# A and Unrelated are not related, so this is not true:
static_assert(not is_subtype_of(Intersection[A, Not[B1]], Not[Unrelated]))
# … but for a disjoint type like `None`, it is:
static_assert(is_subtype_of(Intersection[A, Not[B1]], Not[None]))
# Complements of types are still subtypes of `object`:
static_assert(is_subtype_of(Not[A], object))
# More examples:
static_assert(is_subtype_of(type[str], Not[None]))
static_assert(is_subtype_of(Not[LiteralString], object))
static_assert(not is_subtype_of(Intersection[int, Not[Literal[2]]], Intersection[int, Not[Literal[3]]]))
static_assert(not is_subtype_of(Not[Literal[2]], Not[Literal[3]]))
static_assert(not is_subtype_of(Not[Literal[2]], Not[int]))
static_assert(not is_subtype_of(int, Not[Literal[3]]))
static_assert(not is_subtype_of(Literal[1], Intersection[int, Not[Literal[1]]]))
```
## Special types
### `Never`
`Never` is a subtype of all types.
```py
from typing_extensions import Literal, Never
from knot_extensions import AlwaysTruthy, AlwaysFalsy, is_subtype_of, static_assert
static_assert(is_subtype_of(Never, Never))
static_assert(is_subtype_of(Never, Literal[True]))
static_assert(is_subtype_of(Never, bool))
static_assert(is_subtype_of(Never, int))
static_assert(is_subtype_of(Never, object))
static_assert(is_subtype_of(Never, AlwaysTruthy))
static_assert(is_subtype_of(Never, AlwaysFalsy))
```
### `AlwaysTruthy` and `AlwaysFalsy`
```py
from knot_extensions import AlwaysTruthy, AlwaysFalsy, is_subtype_of, static_assert
static_assert(is_subtype_of(Literal[1], AlwaysTruthy))
static_assert(is_subtype_of(Literal[0], AlwaysFalsy))
static_assert(is_subtype_of(AlwaysTruthy, object))
static_assert(is_subtype_of(AlwaysFalsy, object))
static_assert(not is_subtype_of(Literal[1], AlwaysFalsy))
static_assert(not is_subtype_of(Literal[0], AlwaysTruthy))
static_assert(not is_subtype_of(str, AlwaysTruthy))
static_assert(not is_subtype_of(str, AlwaysFalsy))
```
### Module literals
```py
from types import ModuleType
from knot_extensions import TypeOf, is_subtype_of, static_assert
from typing_extensions import assert_type
import typing
assert_type(typing, TypeOf[typing])
static_assert(is_subtype_of(TypeOf[typing], ModuleType))
```
### Slice literals
```py
from knot_extensions import TypeOf, is_subtype_of, static_assert
static_assert(is_subtype_of(TypeOf[1:2:3], slice))
```
### Special forms
```py
from typing import _SpecialForm
from knot_extensions import TypeOf, is_subtype_of, static_assert
static_assert(is_subtype_of(TypeOf[Literal], _SpecialForm))
static_assert(is_subtype_of(TypeOf[Literal], object))
static_assert(not is_subtype_of(_SpecialForm, TypeOf[Literal]))
```
## Class literal types and `type[…]`
### Basic
```py
from typing import _SpecialForm
from typing_extensions import Literal, assert_type
from knot_extensions import TypeOf, is_subtype_of, static_assert
class Meta(type): ...
class HasCustomMetaclass(metaclass=Meta): ...
type LiteralBool = TypeOf[bool]
type LiteralInt = TypeOf[int]
type LiteralStr = TypeOf[str]
type LiteralObject = TypeOf[object]
assert_type(bool, LiteralBool)
assert_type(int, LiteralInt)
assert_type(str, LiteralStr)
assert_type(object, LiteralObject)
# bool
static_assert(is_subtype_of(LiteralBool, LiteralBool))
static_assert(is_subtype_of(LiteralBool, type[bool]))
static_assert(is_subtype_of(LiteralBool, type[int]))
static_assert(is_subtype_of(LiteralBool, type[object]))
static_assert(is_subtype_of(LiteralBool, type))
static_assert(is_subtype_of(LiteralBool, object))
static_assert(not is_subtype_of(LiteralBool, LiteralInt))
static_assert(not is_subtype_of(LiteralBool, LiteralObject))
static_assert(not is_subtype_of(LiteralBool, bool))
static_assert(not is_subtype_of(type, type[bool]))
# int
static_assert(is_subtype_of(LiteralInt, LiteralInt))
static_assert(is_subtype_of(LiteralInt, type[int]))
static_assert(is_subtype_of(LiteralInt, type[object]))
static_assert(is_subtype_of(LiteralInt, type))
static_assert(is_subtype_of(LiteralInt, object))
static_assert(not is_subtype_of(LiteralInt, LiteralObject))
static_assert(not is_subtype_of(LiteralInt, int))
static_assert(not is_subtype_of(type, type[int]))
# LiteralString
static_assert(is_subtype_of(LiteralStr, type[str]))
static_assert(is_subtype_of(LiteralStr, type))
static_assert(is_subtype_of(LiteralStr, type[object]))
static_assert(not is_subtype_of(type[str], LiteralStr))
# custom meta classes
type LiteralHasCustomMetaclass = TypeOf[HasCustomMetaclass]
static_assert(is_subtype_of(LiteralHasCustomMetaclass, Meta))
static_assert(is_subtype_of(Meta, type[object]))
static_assert(is_subtype_of(Meta, type))
static_assert(not is_subtype_of(Meta, type[type]))
```
### Unions of class literals
```py
from typing_extensions import assert_type
from knot_extensions import TypeOf, is_subtype_of, static_assert
class Base: ...
class Derived(Base): ...
class Unrelated: ...
type LiteralBase = TypeOf[Base]
type LiteralDerived = TypeOf[Derived]
type LiteralUnrelated = TypeOf[Unrelated]
assert_type(Base, LiteralBase)
assert_type(Derived, LiteralDerived)
assert_type(Unrelated, LiteralUnrelated)
static_assert(is_subtype_of(LiteralBase, type))
static_assert(is_subtype_of(LiteralBase, object))
static_assert(is_subtype_of(LiteralBase, type[Base]))
static_assert(is_subtype_of(LiteralDerived, type[Base]))
static_assert(is_subtype_of(LiteralDerived, type[Derived]))
static_assert(not is_subtype_of(LiteralBase, type[Derived]))
static_assert(is_subtype_of(type[Derived], type[Base]))
static_assert(is_subtype_of(LiteralBase | LiteralUnrelated, type))
static_assert(is_subtype_of(LiteralBase | LiteralUnrelated, object))
```
## Non-fully-static types
`Any`, `Unknown`, `Todo` and derivatives thereof do not participate in subtyping.
```py
from knot_extensions import Unknown, is_subtype_of, static_assert, Intersection
from typing_extensions import Any
static_assert(not is_subtype_of(Any, Any))
static_assert(not is_subtype_of(Any, int))
static_assert(not is_subtype_of(int, Any))
static_assert(not is_subtype_of(Any, object))
static_assert(not is_subtype_of(object, Any))
static_assert(not is_subtype_of(int, Any | int))
static_assert(not is_subtype_of(Intersection[Any, int], int))
static_assert(not is_subtype_of(tuple[int, int], tuple[int, Any]))
# The same for `Unknown`:
static_assert(not is_subtype_of(Unknown, Unknown))
static_assert(not is_subtype_of(Unknown, int))
static_assert(not is_subtype_of(int, Unknown))
static_assert(not is_subtype_of(Unknown, object))
static_assert(not is_subtype_of(object, Unknown))
static_assert(not is_subtype_of(int, Unknown | int))
static_assert(not is_subtype_of(Intersection[Unknown, int], int))
static_assert(not is_subtype_of(tuple[int, int], tuple[int, Unknown]))
```
[special case for float and complex]: https://typing.readthedocs.io/en/latest/spec/special-types.html#special-cases-for-float-and-complex
[typing documentation]: https://typing.readthedocs.io/en/latest/spec/concepts.html#subtype-supertype-and-type-equivalence

View File

@@ -1,47 +0,0 @@
# Truthiness
```py
from typing_extensions import Literal, LiteralString
from knot_extensions import AlwaysFalsy, AlwaysTruthy
def _(
a: Literal[1],
b: Literal[-1],
c: Literal["foo"],
d: tuple[Literal[0]],
e: Literal[1, 2],
f: AlwaysTruthy,
):
reveal_type(bool(a)) # revealed: Literal[True]
reveal_type(bool(b)) # revealed: Literal[True]
reveal_type(bool(c)) # revealed: Literal[True]
reveal_type(bool(d)) # revealed: Literal[True]
reveal_type(bool(e)) # revealed: Literal[True]
reveal_type(bool(f)) # revealed: Literal[True]
def _(
a: tuple[()],
b: Literal[0],
c: Literal[""],
d: Literal[b""],
e: Literal[0, 0],
f: AlwaysFalsy,
):
reveal_type(bool(a)) # revealed: Literal[False]
reveal_type(bool(b)) # revealed: Literal[False]
reveal_type(bool(c)) # revealed: Literal[False]
reveal_type(bool(d)) # revealed: Literal[False]
reveal_type(bool(e)) # revealed: Literal[False]
reveal_type(bool(f)) # revealed: Literal[False]
def _(
a: str,
b: Literal[1, 0],
c: str | Literal[0],
d: str | Literal[1],
):
reveal_type(bool(a)) # revealed: bool
reveal_type(bool(b)) # revealed: bool
reveal_type(bool(c)) # revealed: bool
reveal_type(bool(d)) # revealed: bool
```

View File

@@ -1,168 +0,0 @@
use std::fmt::Formatter;
use std::sync::Arc;
use ruff_db::files::File;
use super::path::SearchPath;
use crate::module_name::ModuleName;
/// Representation of a Python module.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Module {
inner: Arc<ModuleInner>,
}
impl Module {
pub(crate) fn new(
name: ModuleName,
kind: ModuleKind,
search_path: SearchPath,
file: File,
) -> Self {
let known = KnownModule::try_from_search_path_and_name(&search_path, &name);
Self {
inner: Arc::new(ModuleInner {
name,
kind,
search_path,
file,
known,
}),
}
}
/// The absolute name of the module (e.g. `foo.bar`)
pub fn name(&self) -> &ModuleName {
&self.inner.name
}
/// The file to the source code that defines this module
pub fn file(&self) -> File {
self.inner.file
}
/// Is this a module that we special-case somehow? If so, which one?
pub fn known(&self) -> Option<KnownModule> {
self.inner.known
}
/// Does this module represent the given known module?
pub fn is_known(&self, known_module: KnownModule) -> bool {
self.known() == Some(known_module)
}
/// The search path from which the module was resolved.
pub(crate) fn search_path(&self) -> &SearchPath {
&self.inner.search_path
}
/// Determine whether this module is a single-file module or a package
pub fn kind(&self) -> ModuleKind {
self.inner.kind
}
}
impl std::fmt::Debug for Module {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Module")
.field("name", &self.name())
.field("kind", &self.kind())
.field("file", &self.file())
.field("search_path", &self.search_path())
.finish()
}
}
#[derive(PartialEq, Eq, Hash)]
struct ModuleInner {
name: ModuleName,
kind: ModuleKind,
search_path: SearchPath,
file: File,
known: Option<KnownModule>,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ModuleKind {
/// A single-file module (e.g. `foo.py` or `foo.pyi`)
Module,
/// A python package (`foo/__init__.py` or `foo/__init__.pyi`)
Package,
}
impl ModuleKind {
pub const fn is_package(self) -> bool {
matches!(self, ModuleKind::Package)
}
}
/// Enumeration of various core stdlib modules in which important types are located
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum KnownModule {
Builtins,
Types,
Typeshed,
TypingExtensions,
Typing,
Sys,
#[allow(dead_code)]
Abc, // currently only used in tests
Collections,
KnotExtensions,
}
impl KnownModule {
pub const fn as_str(self) -> &'static str {
match self {
Self::Builtins => "builtins",
Self::Types => "types",
Self::Typing => "typing",
Self::Typeshed => "_typeshed",
Self::TypingExtensions => "typing_extensions",
Self::Sys => "sys",
Self::Abc => "abc",
Self::Collections => "collections",
Self::KnotExtensions => "knot_extensions",
}
}
pub fn name(self) -> ModuleName {
let self_as_str = self.as_str();
ModuleName::new_static(self_as_str)
.unwrap_or_else(|| panic!("{self_as_str} should be a valid module name!"))
}
pub(crate) fn try_from_search_path_and_name(
search_path: &SearchPath,
name: &ModuleName,
) -> Option<Self> {
if !search_path.is_standard_library() {
return None;
}
match name.as_str() {
"builtins" => Some(Self::Builtins),
"types" => Some(Self::Types),
"typing" => Some(Self::Typing),
"_typeshed" => Some(Self::Typeshed),
"typing_extensions" => Some(Self::TypingExtensions),
"sys" => Some(Self::Sys),
"abc" => Some(Self::Abc),
"collections" => Some(Self::Collections),
"knot_extensions" => Some(Self::KnotExtensions),
_ => None,
}
}
pub const fn is_builtins(self) -> bool {
matches!(self, Self::Builtins)
}
pub const fn is_typing(self) -> bool {
matches!(self, Self::Typing)
}
pub const fn is_knot_extensions(self) -> bool {
matches!(self, Self::KnotExtensions)
}
}

View File

@@ -1,136 +0,0 @@
use crate::module_resolver::SearchPaths;
use crate::python_platform::PythonPlatform;
use crate::python_version::PythonVersion;
use crate::Db;
use anyhow::Context;
use ruff_db::system::{SystemPath, SystemPathBuf};
use salsa::Durability;
use salsa::Setter;
#[salsa::input(singleton)]
pub struct Program {
pub python_version: PythonVersion,
#[return_ref]
pub python_platform: PythonPlatform,
#[return_ref]
pub(crate) search_paths: SearchPaths,
}
impl Program {
pub fn from_settings(db: &dyn Db, settings: ProgramSettings) -> anyhow::Result<Self> {
let ProgramSettings {
python_version,
python_platform,
search_paths,
} = settings;
tracing::info!("Python version: Python {python_version}, platform: {python_platform}");
let search_paths = SearchPaths::from_settings(db, &search_paths)
.with_context(|| "Invalid search path settings")?;
Ok(
Program::builder(python_version, python_platform, search_paths)
.durability(Durability::HIGH)
.new(db),
)
}
pub fn update_from_settings(
self,
db: &mut dyn Db,
settings: ProgramSettings,
) -> anyhow::Result<()> {
let ProgramSettings {
python_version,
python_platform,
search_paths,
} = settings;
if &python_platform != self.python_platform(db) {
tracing::debug!("Updating python platform: `{python_platform:?}`");
self.set_python_platform(db).to(python_platform);
}
if python_version != self.python_version(db) {
tracing::debug!("Updating python version: Python {python_version}");
self.set_python_version(db).to(python_version);
}
self.update_search_paths(db, &search_paths)?;
Ok(())
}
pub fn update_search_paths(
self,
db: &mut dyn Db,
search_path_settings: &SearchPathSettings,
) -> anyhow::Result<()> {
let search_paths = SearchPaths::from_settings(db, search_path_settings)?;
if self.search_paths(db) != &search_paths {
tracing::debug!("Update search paths");
self.set_search_paths(db).to(search_paths);
}
Ok(())
}
pub fn custom_stdlib_search_path(self, db: &dyn Db) -> Option<&SystemPath> {
self.search_paths(db).custom_stdlib()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ProgramSettings {
pub python_version: PythonVersion,
pub python_platform: PythonPlatform,
pub search_paths: SearchPathSettings,
}
/// Configures the search paths for module resolution.
#[derive(Eq, PartialEq, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct SearchPathSettings {
/// List of user-provided paths that should take first priority in the module resolution.
/// Examples in other type checkers are mypy's MYPYPATH environment variable,
/// or pyright's stubPath configuration setting.
pub extra_paths: Vec<SystemPathBuf>,
/// The root of the project, used for finding first-party modules.
pub src_roots: Vec<SystemPathBuf>,
/// Optional path to a "custom typeshed" directory on disk for us to use for standard-library types.
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
/// bundled as a zip file in the binary
pub typeshed: Option<SystemPathBuf>,
/// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.
pub site_packages: SitePackages,
}
impl SearchPathSettings {
pub fn new(src_roots: Vec<SystemPathBuf>) -> Self {
Self {
src_roots,
extra_paths: vec![],
typeshed: None,
site_packages: SitePackages::Known(vec![]),
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SitePackages {
Derived {
venv_path: SystemPathBuf,
},
/// Resolved site packages paths
Known(Vec<SystemPathBuf>),
}

View File

@@ -1,30 +0,0 @@
use std::fmt::{Display, Formatter};
/// The target platform to assume when resolving types.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "kebab-case")
)]
pub enum PythonPlatform {
/// Do not make any assumptions about the target platform.
#[default]
All,
/// Assume a specific target platform like `linux`, `darwin` or `win32`.
///
/// We use a string (instead of individual enum variants), as the set of possible platforms
/// may change over time. See <https://docs.python.org/3/library/sys.html#sys.platform> for
/// some known platform identifiers.
#[cfg_attr(feature = "serde", serde(untagged))]
Identifier(String),
}
impl Display for PythonPlatform {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
PythonPlatform::All => f.write_str("all"),
PythonPlatform::Identifier(name) => f.write_str(name),
}
}
}

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